From 04e72c27de31ac6fe52296c73c742bec0b357321 Mon Sep 17 00:00:00 2001 From: mfeemster Date: Mon, 26 Oct 2015 21:31:35 -0700 Subject: [PATCH] --User changes -Add a new dialog for editing QSS stylesheets. Allow for saving, reloading and setting styles as default. --Include a dark style with the installation called dark.qss. --Also add support for themes such as Fusion. --Resize some controls to better fit with the new style. -Add an option to specify the number of random embers generated on startup. 1 is the minimum and the default. --Bug fixes -Properly enable/disable thread priority label in final render dialog in response to enable/disable of the OpenCL checkbox. -Remove all inline stylesheets. -Show xaos spinners with 6 decimal places. --Code changes -Remove redundant comparisons to nullptr, use ! instead; -Give some controls valid names instead of the auto generated ones. -DoubleSpinBoxTableItemDelegate.h: Add virtual keyword to overridden functions. --- .../Installer/FractoriumInstaller.wixproj | 2 +- Builds/MSVC/Installer/Product.wxs | 7 +- Builds/MSVC/VS2013/Ember.rc | Bin 4692 -> 4692 bytes Builds/MSVC/VS2013/EmberCL.rc | Bin 4718 -> 4718 bytes Builds/MSVC/VS2013/Fractorium.vcxproj | 167 + Builds/MSVC/VS2013/Fractorium.vcxproj.filters | 68 +- Builds/QtCreator/Fractorium/Fractorium.pro | 18 +- Data/dark.qss | 611 ++++ Source/Ember/Ember.h | 12 +- Source/Ember/EmberDefines.h | 2 +- Source/Ember/EmberToXml.h | 4 +- Source/Ember/Interpolate.h | 2 +- Source/Ember/PaletteList.h | 2 +- Source/Ember/Renderer.cpp | 4 +- Source/Ember/Timing.h | 2 +- Source/Ember/Utils.h | 6 +- Source/Ember/Variation.h | 10 +- Source/Ember/VariationList.h | 8 +- Source/Ember/Xform.h | 8 +- Source/EmberAnimate/EmberAnimate.rc | 8 +- Source/EmberCL/RendererCL.cpp | 2 +- Source/EmberGenome/EmberGenome.rc | 8 +- Source/EmberRender/EmberRender.rc | 8 +- Source/Fractorium/AboutDialog.ui | 10 +- .../DoubleSpinBoxTableItemDelegate.h | 10 +- Source/Fractorium/FinalRenderDialog.cpp | 31 +- Source/Fractorium/FinalRenderDialog.ui | 36 +- .../Fractorium/FinalRenderEmberController.cpp | 2 +- Source/Fractorium/Fractorium.cpp | 74 +- Source/Fractorium/Fractorium.h | 14 +- Source/Fractorium/Fractorium.qrc | 2 + Source/Fractorium/Fractorium.rc | Bin 4578 -> 4578 bytes Source/Fractorium/Fractorium.ui | 537 +++- Source/Fractorium/FractoriumCommon.h | 41 + Source/Fractorium/FractoriumInfo.cpp | 26 +- Source/Fractorium/FractoriumMenus.cpp | 4 +- Source/Fractorium/FractoriumPch.h | 54 +- Source/Fractorium/FractoriumRender.cpp | 2 +- Source/Fractorium/FractoriumSettings.cpp | 15 +- Source/Fractorium/FractoriumSettings.h | 9 + Source/Fractorium/FractoriumToolbar.cpp | 19 +- Source/Fractorium/FractoriumXaos.cpp | 9 +- Source/Fractorium/FractoriumXforms.cpp | 26 - Source/Fractorium/FractoriumXformsAffine.cpp | 18 +- .../Fractorium/FractoriumXformsVariations.cpp | 2 - Source/Fractorium/GLWidget.cpp | 2 +- Source/Fractorium/Icons/checkbox_checked.png | Bin 0 -> 263 bytes .../Fractorium/Icons/checkbox_unchecked.png | Bin 0 -> 159 bytes Source/Fractorium/Main.cpp | 53 - Source/Fractorium/OptionsDialog.cpp | 4 + Source/Fractorium/OptionsDialog.h | 1 + Source/Fractorium/OptionsDialog.ui | 39 +- Source/Fractorium/QssDialog.cpp | 694 +++++ Source/Fractorium/QssDialog.h | 141 + Source/Fractorium/QssDialog.ui | 160 + Source/Fractorium/QssTextEdit.cpp | 10 + Source/Fractorium/QssTextEdit.h | 56 + Source/Fractorium/VariationsDialog.ui | 2 +- Source/Fractorium/csshighlighter.cpp | 178 ++ Source/Fractorium/csshighlighter.h | 67 + Source/Fractorium/qcssparser.cpp | 2697 +++++++++++++++++ Source/Fractorium/qcssparser.h | 832 +++++ Source/Fractorium/qcssscanner.cpp | 1171 +++++++ Source/Fractorium/qcssscanner.h | 62 + Source/Fractorium/qfunctions.h | 77 + 65 files changed, 7814 insertions(+), 332 deletions(-) create mode 100644 Data/dark.qss create mode 100644 Source/Fractorium/Icons/checkbox_checked.png create mode 100644 Source/Fractorium/Icons/checkbox_unchecked.png create mode 100644 Source/Fractorium/QssDialog.cpp create mode 100644 Source/Fractorium/QssDialog.h create mode 100644 Source/Fractorium/QssDialog.ui create mode 100644 Source/Fractorium/QssTextEdit.cpp create mode 100644 Source/Fractorium/QssTextEdit.h create mode 100644 Source/Fractorium/csshighlighter.cpp create mode 100644 Source/Fractorium/csshighlighter.h create mode 100644 Source/Fractorium/qcssparser.cpp create mode 100644 Source/Fractorium/qcssparser.h create mode 100644 Source/Fractorium/qcssscanner.cpp create mode 100644 Source/Fractorium/qcssscanner.h create mode 100644 Source/Fractorium/qfunctions.h diff --git a/Builds/MSVC/Installer/FractoriumInstaller.wixproj b/Builds/MSVC/Installer/FractoriumInstaller.wixproj index bceea02..67ea487 100644 --- a/Builds/MSVC/Installer/FractoriumInstaller.wixproj +++ b/Builds/MSVC/Installer/FractoriumInstaller.wixproj @@ -6,7 +6,7 @@ 3.7 {c8096c47-e358-438c-a520-146d46b0637d} 2.0 - Fractorium_Beta_0.9.9.1 + Fractorium_Beta_0.9.9.2 Package $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index 82c3de7..a5d6735 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -1,6 +1,6 @@ - + @@ -13,7 +13,7 @@ - + + + + diff --git a/Builds/MSVC/VS2013/Ember.rc b/Builds/MSVC/VS2013/Ember.rc index 26ccb12b776efe6ffd3a0aaf5207ef60c784d5cf..bd0ecb575112c11d3141e44d0dfe50768f16c109 100644 GIT binary patch delta 57 zcmcbjaz$ms5e`P9$wxU1futj+ev^a#1 F1pxN75C#AM delta 57 zcmcbjaz$ms5e`Pf$wxU1futj+ev^a#1 F1pxLc5CQ-I diff --git a/Builds/MSVC/VS2013/EmberCL.rc b/Builds/MSVC/VS2013/EmberCL.rc index a12a70f3df3c61439ea5e308df0ab8c7a00720d9..85e75670719a86a63c0f2a1afc6d863d133bdc74 100644 GIT binary patch delta 46 wcmaE-@=j&LAr3~P$%i=%fuudBpI3Kt0M8djFjIVU44)7S0A%M4r~m)} delta 46 wcmaE-@=j&LAr3~v$%i=%fuudBpI3Kt0M8djFjIVU44)7S0AzvUse Use + @@ -335,6 +336,11 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" + + + + + Create @@ -351,6 +357,12 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + true true @@ -399,6 +411,18 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + + + true + true + true + true + true true @@ -449,6 +473,12 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + true true @@ -497,6 +527,18 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + + + true + true + true + true + true true @@ -533,6 +575,12 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + true true @@ -581,6 +629,18 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + + + true + true + true + true + true true @@ -639,6 +699,87 @@ 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/VariationsDialog.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 QssDialog.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssDialog.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 QssDialog.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssDialog.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 QssDialog.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssDialog.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 QssDialog.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssDialog.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 QssDialog.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssDialog.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 QssDialog.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssDialog.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);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing csshighlighter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/csshighlighter.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);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing csshighlighter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/csshighlighter.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);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing csshighlighter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/csshighlighter.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);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing csshighlighter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/csshighlighter.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);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing csshighlighter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/csshighlighter.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);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing csshighlighter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/csshighlighter.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 QssTextEdit.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssTextEdit.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 QssTextEdit.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssTextEdit.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 QssTextEdit.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssTextEdit.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 QssTextEdit.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssTextEdit.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 QssTextEdit.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssTextEdit.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 QssTextEdit.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/QssTextEdit.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);%(AdditionalInputs) @@ -1280,6 +1421,32 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)".\GeneratedFiles\ui_%(Filename).h;%(Outputs) "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters index acef896..ab5eb74 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters @@ -54,7 +54,7 @@ False - {95078dd1-1c6e-476d-b565-cc844cef63d2} + {5ba9fccd-8922-4037-956f-d57177a43700} @@ -271,6 +271,51 @@ Generated Files\ReleaseNvidia + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\ReleaseNvidia + + + Dialogs\Qss + + + Dialogs\Qss + + + Dialogs\Qss + + + Dialogs\Qss + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\ReleaseNvidia + + + Dialogs\Qss + + + Dialogs\Qss + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\ReleaseNvidia + @@ -318,6 +363,15 @@ Generated Files + + Generated Files + + + Dialogs\Qss + + + Dialogs\Qss + @@ -386,6 +440,18 @@ Dialogs + + Form Files + + + Dialogs\Qss + + + Dialogs\Qss + + + Dialogs\Qss + diff --git a/Builds/QtCreator/Fractorium/Fractorium.pro b/Builds/QtCreator/Fractorium/Fractorium.pro index 54737fd..26c61d9 100644 --- a/Builds/QtCreator/Fractorium/Fractorium.pro +++ b/Builds/QtCreator/Fractorium/Fractorium.pro @@ -50,7 +50,12 @@ SOURCES += \ ../../../Source/Fractorium/Main.cpp \ ../../../Source/Fractorium/OptionsDialog.cpp \ ../../../Source/Fractorium/VariationsDialog.cpp \ - ../../../Source/Fractorium/SpinBox.cpp + ../../../Source/Fractorium/SpinBox.cpp \ + ../../../Source/Fractorium/csshighlighter.cpp \ + ../../../Source/Fractorium/qcssparser.cpp \ + ../../../Source/Fractorium/qcssscanner.cpp \ + ../../../Source/Fractorium/QssDialog.cpp \ + ../../../Source/Fractorium/QssTextEdit.cpp HEADERS += \ ../../../Source/Fractorium/AboutDialog.h \ @@ -79,14 +84,21 @@ HEADERS += \ ../../../Source/Fractorium/FractoriumCommon.h \ ../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h \ ../../../Source/Fractorium/PaletteTableWidgetItem.h \ - ../../../Source/Fractorium/VariationsDialog.h + ../../../Source/Fractorium/VariationsDialog.h \ + ../../../Source/Fractorium/csshighlighter.h \ + ../../../Source/Fractorium/qcssparser.h \ + ../../../Source/Fractorium/qcssscanner.h \ + ../../../Source/Fractorium/qfunctions.h \ + ../../../Source/Fractorium/QssDialog.h \ + ../../../Source/Fractorium/QssTextEdit.h FORMS += \ ../../../Source/Fractorium/AboutDialog.ui \ ../../../Source/Fractorium/FinalRenderDialog.ui \ ../../../Source/Fractorium/Fractorium.ui \ ../../../Source/Fractorium/VariationsDialog.ui \ - ../../../Source/Fractorium/OptionsDialog.ui + ../../../Source/Fractorium/OptionsDialog.ui \ + ../../../Source/Fractorium/QssDialog.ui OTHER_FILES += \ ../../../Source/Fractorium/Fractorium.aps \ diff --git a/Data/dark.qss b/Data/dark.qss new file mode 100644 index 0000000..22fc301 --- /dev/null +++ b/Data/dark.qss @@ -0,0 +1,611 @@ +/*---Base Style--- + This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows. + It's not needed for other themes. + You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/ +QTabBar::tab { height: 5ex; }/*Do this for windows*/ +/*QTabBar::tab { height: 3ex; }*//*Do this for linux*/ + +/*This is needed to give the labels on the status bar some padding.*/ +QStatusBar QLabel { padding-left: 2px; padding-right: 2px; } + +/*Specific styles below this line*/ + +QObject +{ + background-color : rgb(53, 53, 53); + color: darkgray; + alternate-background-color: rgb(53, 53, 53); + selection-color: black; + selection-background-color: rgb(42, 130, 218); +} + +QObject:disabled +{ + color: rgb(35, 35, 35); + background-color: rgb(53, 53, 53); + border-color: rgb(35, 35, 35); +} + +QDockWidget::float-button +{ + background-color: gray; +} + +QDockWidget::title +{ + margin: 1px; + padding: 2px; + background-color: gray; +} + +QTabWidget::pane +{ + border: 1px solid gray; +} + +QPushButton +{ + margin: 1px; + padding: 4px; + border: 1px solid gray; +} + +QPushButton:pressed +{ + background-color: gray; +} + +QPushButton:focus +{ + outline: none; +} + +QTableView QPushButton +{ + border: 1px solid gray; + margin: 1px; + padding: 0px; +} + +QLineEdit, QTextEdit +{ + border: 1px solid gray; + color: darkgray; + background-color: rgb(40, 40, 50); + selection-background-color: darkgray; +} + +QToolTip +{ + background-color: darkgray; + border: 1px solid darkgray; +} + +QSpinBox, +QDoubleSpinBox +{ + padding-right: 0px; + color: darkgray; + selection-background-color: darkgray; + font: 9pt "Segoe UI";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/ +} + +QCheckBox +{ + spacing: 5px; +} + +QCheckBox::indicator, +QTableView::indicator +{ + border: none; + border-radius: 2px; + background-color: lightgray; +} + +QCheckBox::indicator:enabled:unchecked, +QTableView::indicator:enabled:unchecked +{ + background-color: lightgray; + image: url(:/Fractorium/Icons/checkbox_unchecked.png); +} + +QCheckBox::indicator:enabled:checked, +QTableView::indicator:enabled:checked +{ + background-color: lightgray; + image: url(:/Fractorium/Icons/checkbox_checked.png); +} + +QCheckBox::indicator:disabled:unchecked, +QTableView::indicator:disabled:unchecked +{ + background-color: gray; + image: none; +} + +QCheckBox::indicator:disabled:checked, +QTableView::indicator:disabled:checked +{ + background-color: gray; + image: none; +} + +QRadioButton::indicator:checked +{ + background-color: black; + border: 2px solid gray; + border-radius: 7px; + width: 8px; + height: 8px; + margin: 3px; + padding: 1px; +} + +QRadioButton::indicator:checked:disabled +{ + background-color: rgb(35, 35, 35); +} + +QRadioButton::indicator:unchecked +{ + border: 2px solid gray; + border-radius: 7px; + width: 8px; + height: 8px; + margin: 3px; + padding: 1px; +} + +QComboBox +{ + margin: 0px; + padding-left: 4px; + border: 1px solid gray; +} + +QComboBox::down-arrow:enabled +{ + border: 1px solid gray; + margin-right: 2px; + margin-top: 0px; + margin-bottom: 1px; +} + + +QComboBox::down-arrow:disabled +{ + border: 1px solid rgb(35, 35, 35); + margin-right: 2px; + margin-top: 0px; + margin-bottom: 1px; +} + +QComboBox::drop-down +{ + border: none; +} + +/*For some reason this is needed with Fusion, but not with Windows*/ +QComboBox::item:selected +{ + selection-background-color: darkgray; +} + +QComboBox QAbstractItemView +{ + border: 1px solid gray; + outline: none; + selection-background-color: darkgray; +} + +QTableView QComboBox +{ + margin: 1px; + padding: 0px; + padding-left: 3px; +} + +QGroupBox QComboBox +{ + margin: 1px; + margin-bottom: 0px; +} + +QTableView QComboBox::down-arrow +{ + margin-top: 0px; + margin-right: 1px; + margin-bottom: 0px; +} + +QProgressBar +{ + color: black; + background-color: gray; + border: 0px none gray; + border-radius: 3px; + text-align: center; +} + +QProgressBar::chunk +{ + border-radius: 3px; + background-color: lightgray; +} + +QStatusBar QProgressBar +{ + min-width: 300px; + max-width: 300px; + margin-right: 4px; +} + +QMenuBar +{ + border-bottom: 1px solid gray; +} + +QMenuBar::item +{ + background-color: rgb(53, 53, 53); +} + +QMenu::item:disabled +{ + color: rgb(35, 35, 35); + +} + +QMenu::item:enabled:selected +{ + background-color: gray; +} + +QMenu::item:disabled:selected +{ + background-color: rgb(53, 53, 53); +} + +QToolBar +{ + border: 0px none gray; +} + +QGroupBox +{ + padding-top: 3px; + border: 2px solid gray; + border-radius: 4px; + margin-top: 3ex; +} + +QGroupBox::title +{ + subcontrol-origin: border; + subcontrol-position: top left; + margin-top: -1ex; + margin-left: 0px; + padding-right: 1px; + padding-left: 2px; + top: -2ex; + left: 8px; +} + +QListView +{ + selection-color: black; + selection-background-color: darkgray; +} + +QListView::item:selected +{ + background-color: darkgray; +} + +QTreeView +{ + border: 1px solid gray; + background-color: rgb(53, 53, 53); +} + +/*Setting this gives a more consistent look, but removes the ability to gray variations that are included in the xform*/ +QTreeView::item +{ + background-color: rgb(53, 53, 53); + color: darkgray; + outline: none; +} + +QTreeView::item:selected +{ + border: 0px none black; + background-color: gray; + outline: none; +} + +QTreeView::branch:!has-children +{ + background: rgb(53, 53, 53); +} + +QTreeView::branch:has-children:closed +{ + border: 1px solid darkgray; + background: gray; + margin: 2px; +} + +QTreeView::branch:has-children:!closed +{ + border: 1px solid lightgray; + background: gray; + margin-left: 1px; + margin-right: 0px; + margin-top: 3px; + margin-bottom: 3px; +} + +QTableView +{ + border-left: 0px none gray; + border-top: 0px none gray; + border-right: 0px none gray; + border-bottom: 0px none gray; + gridline-color: gray; + color: darkgray; + selection-color: darkgray; + selection-background-color: rgb(53, 53, 53); +} + +QTableView QTableCornerButton::section:enabled +{ + background-color: darkgray; +} + +QTableView QTableCornerButton::section:disabled +{ + background-color: rgb(53, 53, 53); +} + +QTableView::indicator:disabled +{ + background-color: rgb(35, 35, 35); +} + +QTableView:disabled +{ + color: rgb(35, 35, 35); + border: none; + gridline-color: rgb(35, 35, 35); +} + +QHeaderView::section::vertical:enabled +{ + color: black; + background-color: gray; + border: none; + border-bottom: 1px solid gray; + padding: 4px; +} + +QHeaderView::section::horizontal:enabled +{ + color: black; + background-color: darkgray; + border: 0px solid darkgray; + border-right: 1px solid gray; + padding: 4px; +} + +QHeaderView::section::vertical:disabled +{ + color: rgb(35, 35, 35); + background-color: rgb(53, 53, 53); + border: 0px none darkgray; + border-bottom: 1px solid rgb(53, 53, 53); + padding: 4px; +} + +QHeaderView::section::horizontal:disabled +{ + color:rgb(35, 35, 35); + background-color: rgb(53, 53, 53); + border: 0px none darkgray; + border-right: 1px solid rgb(53, 53, 53); + padding: 4px; +} + +QScrollBar::vertical +{ + background-color: darkgray; + border: 0px solid darkgray; + width: 15px; + margin: 22px 0 22px 0; +} + +QScrollBar::handle::vertical +{ + background-color: gray; + border-top: 1px solid darkgray; + border-bottom: 1px solid darkgray; + min-height: 20px; +} + +QScrollBar::add-line::vertical +{ + border: 0px solid darkgray; + background-color: gray; + height: 22px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line::vertical +{ + border: 0px solid darkgray; + background-color: gray; + height: 22px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow::vertical, QScrollBar::down-arrow::vertical +{ + border: 2px solid darkgray; + width: 5px; + height: 12px; + background-color: gray; +} + +QScrollBar::add-page::vertical, QScrollBar::sub-page::vertical, QScrollBar::add-page::horizontal, QScrollBar::sub-page::horizontal +{ + background-color: darkgray; +} + +QScrollBar::horizontal +{ + background-color: darkgray; + border: 0px solid darkgray; + height: 15px; + margin: 0px 20px 0 20px; +} + +QScrollBar::handle::horizontal +{ + background-color: gray; + border-left: 1px solid darkgray; + border-right: 1px solid darkgray; + min-width: 20px; +} + +QScrollBar::add-line::horizontal +{ + border: 0px solid darkgray; + background-color: gray; + width: 20px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::sub-line::horizontal +{ + border: 0px solid darkgray; + background-color: gray; + width: 20px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::left-arrow::horizontal, QScrollBar::right-arrow::horizontal +{ + border: 2px solid darkgray; + width: 12px; + height: 5px; + background-color: gray; +} + +QMenu::separator +{ + height: 1px; + background-color: gray; +} + +QToolBar::separator +{ + width: 1px; + margin-top: 3px; + margin-bottom: 2px; + background-color: gray; +} + +QStatusBar::item +{ + border: none; +} + +/*Specific controls*/ +QTableWidget#ColorTableHeader QHeaderView::section::horizontal, +QTableWidget#GeometryTableHeader QHeaderView::section::horizontal, +QTableWidget#FilterTableHeader QHeaderView::section::horizontal, +QTableWidget#IterationTableHeader QHeaderView::section::horizontal, +QTreeWidget#LibraryTree QHeaderView::section::horizontal +{ + border-right: none; +} + +QTableWidget#ColorTable, +QTableWidget#GeometryTable, +QTableWidget#FilterTable, +QTableWidget#IterationTable, +QTableWidget#XformWeightNameTable +{ + border-left: 1px solid gray; +} + +QTableWidget#SummaryTable, +QTableWidget#PaletteListTable +{ + border-left: 1px solid gray; +} + +QTableWidget#SummaryTable QHeaderView::section::vertical +{ + background-color: darkgray; +} + +QTableWidget#PaletteAdjustTable, +QTableWidget#PalettePreviewTable, +QTableWidget#XformColorIndexTable, +QTableWidget#XformColorValuesTable, +QTableWidget#InfoBoundsTable, +QTableWidget#OptionsXmlSavingTable, +QTableWidget#OptionsIdentityTable, +QTableWidget#FinalRenderSizeTable, +QTableWidget#FinalRenderParamsTable +{ + border-left: 1px solid gray; + border-top: 1px solid gray; +} + +QLineEdit#PaletteFilterLineEdit, +QLineEdit#VariationsFilterLineEdit +{ + height: 20px; + min-height: 20px; + max-height: 20px; +} + +QSpinBox#ThreadCountSpin, +QSpinBox#RandomCountSpin, +QSpinBox#CpuSubBatchSpin, +QSpinBox#OpenCLSubBatchSpin, +QSpinBox#FinalRenderCurrentSpin, +QSpinBox#FinalRenderThreadCountSpin +{ + padding: 2px; + border: 1px solid gray; +} + +QSpinBox#ThreadCountSpin:disabled, +QSpinBox#CpuSubBatchSpin:disabled, +QSpinBox#OpenCLSubBatchSpin:disabled, +QSpinBox#FinalRenderCurrentSpin:disabled, +QSpinBox#FinalRenderThreadCountSpin:disabled +{ + padding: 2px; + border: 1px solid rgb(35, 35, 35); +} + +QTableView#FinalRenderParamsTable QComboBox +{ + margin-top: 0px; + margin-bottom: 0px; +} + +QTableView#FinalRenderParamsTable QPushButton +{ + margin-top: 1px; + margin-bottom: 2px; + padding: 0px; +} diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index 6374ca5..e01f97e 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -180,7 +180,7 @@ public: SetProjFunc(); ClearEdit(); - if (ember.m_Edits != nullptr) + if (ember.m_Edits) m_Edits = xmlCopyDoc(ember.m_Edits, 1); CopyVec(m_EmberMotionElements, ember.m_EmberMotionElements); @@ -858,7 +858,7 @@ public: var->m_Weight = 0; - if (parVar != nullptr) + if (parVar) parVar->Clear(); for (size_t k = 0; k < size; k++)//For each ember in the list. @@ -869,17 +869,17 @@ public: { Variation* tempVar = tempXform->GetVariationById(var->VariationId());//See if the variation at this xform index exists in that ember at this xform index. - if (tempVar != nullptr) + if (tempVar) { //Interp weight. var->m_Weight += tempVar->m_Weight * coefs[k]; //If it was a parametric variation, interp params. - if (parVar != nullptr) + if (parVar) { ParametricVariation* tempParVar = dynamic_cast*>(tempVar); - if (tempParVar != nullptr && (parVar->ParamCount() == tempParVar->ParamCount()))//This check will should always be true, but just check to be absolutely sure to avoid clobbering memory. + if (tempParVar && (parVar->ParamCount() == tempParVar->ParamCount()))//This check will should always be true, but just check to be absolutely sure to avoid clobbering memory. { auto params = parVar->Params(); auto tempParams = tempParVar->Params(); @@ -1461,7 +1461,7 @@ public: /// void ClearEdit() { - if (m_Edits != nullptr) + if (m_Edits) xmlFreeDoc(m_Edits); m_Edits = nullptr; diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 8b16751..e937571 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -42,7 +42,7 @@ namespace EmberNs { -#define EMBER_VERSION "0.9.9.1" +#define EMBER_VERSION "0.9.9.2" #define EPS6 T(1e-6) #define EPS std::numeric_limits::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way. #define ISAAC_SIZE 4 diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index b288126..97c7611 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -296,7 +296,7 @@ public: } } - if (doEdits && ember.m_Edits != nullptr) + if (doEdits && ember.m_Edits) os << ToString(xmlDocGetRootElement(ember.m_Edits), 1, true, printEditDepth); os << "\n"; @@ -448,7 +448,7 @@ public: os.str(""); //Check for errors. - if (commentDoc != nullptr) + if (commentDoc) { //Loop through the children of the new document and copy them into the rootNode. diff --git a/Source/Ember/Interpolate.h b/Source/Ember/Interpolate.h index 950ca86..98b0df3 100644 --- a/Source/Ember/Interpolate.h +++ b/Source/Ember/Interpolate.h @@ -544,7 +544,7 @@ public: static void InterpParametricVar(vector*>& first, ParametricVariation* second, vector& c) { //First, make sure the variation vector is the same size as the coefficient vector. - if (second != nullptr && first.size() == c.size()) + if (second && first.size() == c.size()) { second->Clear(); auto secondParams = second->Params(); diff --git a/Source/Ember/PaletteList.h b/Source/Ember/PaletteList.h index 8a8d7a5..95ea736 100644 --- a/Source/Ember/PaletteList.h +++ b/Source/Ember/PaletteList.h @@ -49,7 +49,7 @@ public: { xmlDocPtr doc = xmlReadMemory(static_cast(buf.data()), int(buf.size()), filename.c_str(), nullptr, XML_PARSE_NONET); - if (doc != nullptr) + if (doc) { auto rootNode = xmlDocGetRootElement(doc); auto pfilename = shared_ptr(new string(filename)); diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index 50ba671..47e6fd9 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -1410,8 +1410,8 @@ template size_t Renderer::FuseCount() /// Non-virtual iterator wrappers. /// -template const byte* Renderer::XformDistributions() const { return m_Iterator != nullptr ? m_Iterator->XformDistributions() : nullptr; } -template size_t Renderer::XformDistributionsSize() const { return m_Iterator != nullptr ? m_Iterator->XformDistributionsSize() : 0; } +template const byte* Renderer::XformDistributions() const { return m_Iterator ? m_Iterator->XformDistributions() : nullptr; } +template size_t Renderer::XformDistributionsSize() const { return m_Iterator ? m_Iterator->XformDistributionsSize() : 0; } template Point* Renderer::Samples(size_t threadIndex) const { return threadIndex < m_Samples.size() ? const_cast*>(m_Samples[threadIndex].data()) : nullptr; } /// diff --git a/Source/Ember/Timing.h b/Source/Ember/Timing.h index bdd5fdf..f5c1c07 100644 --- a/Source/Ember/Timing.h +++ b/Source/Ember/Timing.h @@ -50,7 +50,7 @@ public: m_EndTime = Clock::now(); double ms = ElapsedTime(); - if (str != nullptr) + if (str) { cout << string(str) << (fullString ? "" : " processing time: ") << Format(ms) << endl; } diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index 2e021b8..8634d8f 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -182,7 +182,7 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru { fopen_s(&f, filename, "rb");//Open in binary mode. - if (f != nullptr) + if (f) { struct _stat statBuf; @@ -225,7 +225,7 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru b = false; } - if (f != nullptr) + if (f) fclose(f); return b; @@ -279,7 +279,7 @@ static void ClearVec(vector& vec, bool arrayDelete = false) { for (size_t i = 0; i < vec.size(); i++) { - if (vec[i] != nullptr) + if (vec[i]) { if (arrayDelete) delete [] vec[i]; diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h index 4bc6aed..8886324 100644 --- a/Source/Ember/Variation.h +++ b/Source/Ember/Variation.h @@ -1874,7 +1874,7 @@ protected: #define VARCOPYDOUBLE(name) \ virtual void Copy(Variation*& var) const override \ { \ - if (var != nullptr) \ + if (var) \ delete var; \ \ var = new name(*this); \ @@ -1905,7 +1905,7 @@ protected: \ virtual void Copy(Variation*& var) const override \ { \ - if (var != nullptr) \ + if (var) \ delete var; \ \ var = new name(*this); \ @@ -1932,7 +1932,7 @@ protected: \ virtual void Copy(Variation*& var) const override \ { \ - if (var != nullptr) \ + if (var) \ delete var; \ \ var = new name(*this); \ @@ -2018,7 +2018,7 @@ protected: \ virtual void Copy(Variation*& var) const override \ { \ - if (var != nullptr) \ + if (var) \ delete var; \ \ var = new name(*this); \ @@ -2049,7 +2049,7 @@ protected: \ virtual void Copy(Variation*& var) const override \ { \ - if (var != nullptr) \ + if (var) \ delete var; \ \ var = new name(*this); \ diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h index 24c8727..6abd57c 100644 --- a/Source/Ember/VariationList.h +++ b/Source/Ember/VariationList.h @@ -412,7 +412,7 @@ public: /// A pointer to the variation if found, else nullptr. const Variation* GetVariation(eVariationId id) const { - for (size_t i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++) + for (size_t i = 0; i < m_Variations.size() && m_Variations[i]; i++) if (id == m_Variations[i]->VariationId()) return m_Variations[i]; @@ -435,7 +435,7 @@ public: /// A pointer to the variation if found, else nullptr. const Variation* GetVariation(const string& name) const { - for (size_t i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++) + for (size_t i = 0; i < m_Variations.size() && m_Variations[i]; i++) if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str())) return m_Variations[i]; @@ -466,7 +466,7 @@ public: /// The parametric variation with a matching name, else nullptr. const ParametricVariation* GetParametricVariation(const string& name) const { - for (size_t i = 0; i < m_ParametricVariations.size() && m_ParametricVariations[i] != nullptr; i++) + for (size_t i = 0; i < m_ParametricVariations.size() && m_ParametricVariations[i]; i++) if (!_stricmp(name.c_str(), m_ParametricVariations[i]->Name().c_str())) return m_ParametricVariations[i]; @@ -480,7 +480,7 @@ public: /// The index of the variation with the matching name, else -1 int GetVariationIndex(const string& name) { - for (size_t i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++) + for (size_t i = 0; i < m_Variations.size() && m_Variations[i]; i++) if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str())) return int(i); diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index f36edec..fca3203 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -370,7 +370,7 @@ public: { for (auto v : variations) { - if (v != nullptr && v->VariationId() == id) + if (v && v->VariationId() == id) { var = v; keepGoing = false; @@ -395,7 +395,7 @@ public: { for (auto v : variations) { - if (v != nullptr && v->Name() == name) + if (v && v->Name() == name) { var = v; keepGoing = false; @@ -447,7 +447,7 @@ public: { for (size_t i = 0; i < variations.size(); i++) { - if (variations[i] != nullptr && variations[i]->VariationId() == id) + if (variations[i] && variations[i]->VariationId() == id) { delete variations[i]; variations.erase(variations.begin() + i); @@ -768,7 +768,7 @@ public: //At this point, we've added if needed, or just applied the motion func to the weight. //Now apply the motion func to the params if needed. - if (motParVar != nullptr) + if (motParVar) { auto parVar = dynamic_cast*>(var); auto params = parVar->Params(); diff --git a/Source/EmberAnimate/EmberAnimate.rc b/Source/EmberAnimate/EmberAnimate.rc index 2b37b96..ff4f154 100644 --- a/Source/EmberAnimate/EmberAnimate.rc +++ b/Source/EmberAnimate/EmberAnimate.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,9,1 - PRODUCTVERSION 0,9,9,1 + FILEVERSION 0,9,9,2 + PRODUCTVERSION 0,9,9,2 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as animations with motion blur" - VALUE "FileVersion", "0.9.9.1" + VALUE "FileVersion", "0.9.9.2" VALUE "InternalName", "EmberAnimate.exe" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2015, GPL v3" VALUE "OriginalFilename", "EmberAnimate.exe" VALUE "ProductName", "Ember Animate" - VALUE "ProductVersion", "0.9.9.1" + VALUE "ProductVersion", "0.9.9.2" END END BLOCK "VarFileInfo" diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index b9d0df5..6005364 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -759,7 +759,7 @@ eRenderStatus RendererCL::AccumulatorToFinalImage(byte* pixels, size { eRenderStatus status = RunFinalAccum(); - if (status == RENDER_OK && pixels != nullptr && !m_Devices.empty() && !m_Devices[0]->m_Wrapper.Shared()) + if (status == RENDER_OK && pixels && !m_Devices.empty() && !m_Devices[0]->m_Wrapper.Shared()) { pixels += finalOffset; diff --git a/Source/EmberGenome/EmberGenome.rc b/Source/EmberGenome/EmberGenome.rc index b067a10..0cb0868 100644 --- a/Source/EmberGenome/EmberGenome.rc +++ b/Source/EmberGenome/EmberGenome.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,9,1 - PRODUCTVERSION 0,9,9,1 + FILEVERSION 0,9,9,2 + PRODUCTVERSION 0,9,9,2 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Manipulates fractal flames parameter files" - VALUE "FileVersion", "0.9.9.1" + VALUE "FileVersion", "0.9.9.2" VALUE "InternalName", "EmberGenome.exe" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2015, GPL v3" VALUE "OriginalFilename", "EmberGenome.exe" VALUE "ProductName", "Ember Genome" - VALUE "ProductVersion", "0.9.9.1" + VALUE "ProductVersion", "0.9.9.2" END END BLOCK "VarFileInfo" diff --git a/Source/EmberRender/EmberRender.rc b/Source/EmberRender/EmberRender.rc index b5087c3..8196e23 100644 --- a/Source/EmberRender/EmberRender.rc +++ b/Source/EmberRender/EmberRender.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,9,1 - PRODUCTVERSION 0,9,9,1 + FILEVERSION 0,9,9,2 + PRODUCTVERSION 0,9,9,2 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as single images" - VALUE "FileVersion", "0.9.9.1" + VALUE "FileVersion", "0.9.9.2" VALUE "InternalName", "EmberRender.exe" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2015, GPL v3" VALUE "OriginalFilename", "EmberRender.exe" VALUE "ProductName", "Ember Render" - VALUE "ProductVersion", "0.9.9.1" + VALUE "ProductVersion", "0.9.9.2" END END BLOCK "VarFileInfo" diff --git a/Source/Fractorium/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui index 3782146..cc16621 100644 --- a/Source/Fractorium/AboutDialog.ui +++ b/Source/Fractorium/AboutDialog.ui @@ -58,7 +58,7 @@ QFrame::NoFrame - <html><head/><body><p align="center"><br/>Fractorium 0.9.9.1 Beta</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Lead: Matt Feemster<br/>Contributors: Simon Detheridge</span></p></body></html> + <html><head/><body><p align="center"><br/>Fractorium 0.9.9.2 Beta</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Lead: Matt Feemster<br/>Contributors: Simon Detheridge</span></p></body></html> Qt::RichText @@ -85,7 +85,7 @@ 483 - + @@ -246,12 +246,12 @@ - + 6 - + 100 @@ -277,7 +277,7 @@ - okButton + OkButton clicked() AboutDialog accept() diff --git a/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h b/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h index 5830b6c..9fd382c 100644 --- a/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h +++ b/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h @@ -34,7 +34,7 @@ public: /// Unused /// unused /// The DoubleSpinBox member - QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override { m_SpinBox->setParent(parent); @@ -46,7 +46,7 @@ public: /// /// Unused /// Unused - void destroyEditor(QWidget* editor, const QModelIndex& index) const override + virtual void destroyEditor(QWidget* editor, const QModelIndex& index) const override { } @@ -55,7 +55,7 @@ public: /// /// Unused /// Unused - void setEditorData(QWidget* editor, const QModelIndex& index) const override + virtual void setEditorData(QWidget* editor, const QModelIndex& index) const override { QPoint p(index.row(), index.column()); auto value = index.model()->data(index, Qt::EditRole).toDouble(); @@ -70,7 +70,7 @@ public: /// 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 + virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override { model->setData(index, m_SpinBox->value(), Qt::EditRole); } @@ -81,7 +81,7 @@ public: /// 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 + virtual void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override { editor->setGeometry(option.rect); } diff --git a/Source/Fractorium/FinalRenderDialog.cpp b/Source/Fractorium/FinalRenderDialog.cpp index 7b6bd16..1181424 100644 --- a/Source/Fractorium/FinalRenderDialog.cpp +++ b/Source/Fractorium/FinalRenderDialog.cpp @@ -38,7 +38,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set connect(ui.FinalRenderScaleNoneRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection); connect(ui.FinalRenderScaleWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection); connect(ui.FinalRenderScaleHeightRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection); - connect(ui.DeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection); + connect(ui.FinalRenderDeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection); SetupSpinner(ui.FinalRenderSizeTable, this, row, 1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnWidthScaleChanged(double)), true, 1.0, 1.0, 1.0); SetupSpinner(ui.FinalRenderSizeTable, this, row, 1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHeightScaleChanged(double)), true, 1.0, 1.0, 1.0); @@ -79,11 +79,11 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set connect(m_PrefixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnPrefixChanged(const QString&)), Qt::QueuedConnection); connect(m_SuffixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnSuffixChanged(const QString&)), Qt::QueuedConnection); - ui.StartRenderButton->disconnect(SIGNAL(clicked(bool))); - connect(ui.StartRenderButton, SIGNAL(clicked(bool)), this, SLOT(OnRenderClicked(bool)), Qt::QueuedConnection); - connect(ui.StopRenderButton, SIGNAL(clicked(bool)), this, SLOT(OnCancelRenderClicked(bool)), Qt::QueuedConnection); + ui.FinalRenderStartButton->disconnect(SIGNAL(clicked(bool))); + connect(ui.FinalRenderStartButton, SIGNAL(clicked(bool)), this, SLOT(OnRenderClicked(bool)), Qt::QueuedConnection); + connect(ui.FinalRenderStopButton, SIGNAL(clicked(bool)), this, SLOT(OnCancelRenderClicked(bool)), Qt::QueuedConnection); - table = ui.DeviceTable; + table = ui.FinalRenderDeviceTable; table->clearContents(); table->setRowCount(0); @@ -162,7 +162,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox); w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox); w = SetTabOrder(this, w, ui.FinalRenderCurrentSpin); - w = SetTabOrder(this, w, ui.DeviceTable); + w = SetTabOrder(this, w, ui.FinalRenderDeviceTable); w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin); w = SetTabOrder(this, w, ui.FinalRenderThreadPriorityComboBox); w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox); @@ -183,9 +183,9 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set w = SetTabOrder(this, w, m_PrefixEdit); w = SetTabOrder(this, w, m_SuffixEdit); w = SetTabOrder(this, w, ui.FinalRenderTextOutput); - w = SetTabOrder(this, w, ui.StartRenderButton); - w = SetTabOrder(this, w, ui.StopRenderButton); - w = SetTabOrder(this, w, ui.CloseButton); + w = SetTabOrder(this, w, ui.FinalRenderStartButton); + w = SetTabOrder(this, w, ui.FinalRenderStopButton); + w = SetTabOrder(this, w, ui.FinalRenderCloseButton); } /// @@ -228,7 +228,7 @@ double FractoriumFinalRenderDialog::Quality() { return m_QualitySpin->value(); } uint FractoriumFinalRenderDialog::TemporalSamples() { return m_TemporalSamplesSpin->value(); } uint FractoriumFinalRenderDialog::Supersample() { return m_SupersampleSpin->value(); } uint FractoriumFinalRenderDialog::Strips() { return m_StripsSpin->value(); } -QList FractoriumFinalRenderDialog::Devices() { return DeviceTableToSettings(ui.DeviceTable); } +QList FractoriumFinalRenderDialog::Devices() { return DeviceTableToSettings(ui.FinalRenderDeviceTable); } /// /// Capture the current state of the Gui. @@ -347,8 +347,9 @@ void FractoriumFinalRenderDialog::OnOpenCLCheckBoxStateChanged(int state) { bool checked = state == Qt::Checked; - ui.DeviceTable->setEnabled(checked); + ui.FinalRenderDeviceTable->setEnabled(checked); ui.FinalRenderThreadCountSpin->setEnabled(!checked); + ui.FinalRenderThreadPriorityLabel->setEnabled(!checked); ui.FinalRenderThreadPriorityComboBox->setEnabled(!checked); SetMemory(); } @@ -480,9 +481,9 @@ void FractoriumFinalRenderDialog::OnScaleRadioButtonChanged(bool checked) /// The column of the cell void FractoriumFinalRenderDialog::OnDeviceTableCellChanged(int row, int col) { - if (auto item = ui.DeviceTable->item(row, col)) + if (auto item = ui.FinalRenderDeviceTable->item(row, col)) { - HandleDeviceTableCheckChanged(ui.DeviceTable, row, col); + HandleDeviceTableCheckChanged(ui.FinalRenderDeviceTable, row, col); SetMemory(); } } @@ -497,7 +498,7 @@ void FractoriumFinalRenderDialog::OnDeviceTableRadioToggled(bool checked) { int row; auto s = sender(); - auto table = ui.DeviceTable; + auto table = ui.FinalRenderDeviceTable; QRadioButton* radio = nullptr; if (s) @@ -506,7 +507,7 @@ void FractoriumFinalRenderDialog::OnDeviceTableRadioToggled(bool checked) if (radio = qobject_cast(table->cellWidget(row, 1))) if (s == radio) { - HandleDeviceTableCheckChanged(ui.DeviceTable, row, 1); + HandleDeviceTableCheckChanged(ui.FinalRenderDeviceTable, row, 1); break; } } diff --git a/Source/Fractorium/FinalRenderDialog.ui b/Source/Fractorium/FinalRenderDialog.ui index 3ca4ccc..79e463b 100644 --- a/Source/Fractorium/FinalRenderDialog.ui +++ b/Source/Fractorium/FinalRenderDialog.ui @@ -45,7 +45,7 @@ 6 - + Qt::NoFocus @@ -58,7 +58,7 @@ true - + 0 @@ -84,7 +84,7 @@ 0 - + @@ -168,7 +168,7 @@ - + QLayout::SetNoConstraint @@ -240,7 +240,7 @@ - + 0 @@ -461,13 +461,13 @@ 0 - 46 + 45 16777215 - 46 + 45 @@ -670,13 +670,13 @@ 0 - 200 + 199 16777215 - 200 + 199 @@ -939,7 +939,7 @@ - + QLayout::SetDefaultConstraint @@ -1105,7 +1105,7 @@ - + Qt::TabFocus @@ -1118,7 +1118,7 @@ - + Qt::TabFocus @@ -1128,7 +1128,7 @@ - + Qt::TabFocus @@ -1165,14 +1165,14 @@ FinalRenderOpenCLCheckBox FinalRenderParamsTable FinalRenderTextOutput - StartRenderButton - StopRenderButton - CloseButton + FinalRenderStartButton + FinalRenderStopButton + FinalRenderCloseButton - StartRenderButton + FinalRenderStartButton clicked() FinalRenderDialog accept() @@ -1188,7 +1188,7 @@ - CloseButton + FinalRenderCloseButton clicked() FinalRenderDialog reject() diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp index 83a2ff0..c6a9de0 100644 --- a/Source/Fractorium/FinalRenderEmberController.cpp +++ b/Source/Fractorium/FinalRenderEmberController.cpp @@ -881,7 +881,7 @@ void FinalRenderEmberController::RenderComplete(Ember& ember, const EmberS ember.m_Edits = m_XmlWriter.CreateNewEditdoc(&ember, nullptr, "edit", m_Settings->Nick().toStdString(), m_Settings->Url().toStdString(), m_Settings->Id().toStdString(), "", 0, 0); m_XmlWriter.Save(newPath.toStdString().c_str(), ember, 0, true, false, true);//Note that the ember passed is used, rather than m_Ember because it's what was actually rendered. - if (tempEdit != nullptr) + if (tempEdit) xmlFreeDoc(tempEdit); } diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index 8cad6df..59015db 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -1,5 +1,6 @@ #include "FractoriumPch.h" #include "Fractorium.h" +#include "QssDialog.h" // X11 headers on Linux define this, causing build errors. #ifdef KeyRelease @@ -13,14 +14,16 @@ /// is present here, it's safe to assume it can't be done in the designer. /// /// The parent widget of this item -Fractorium::Fractorium(QWidget* p) +Fractorium::Fractorium(QWidget* p) : QMainWindow(p), m_Info(OpenCLInfo::Instance()) { int spinHeight = 20, iconSize_ = 9; size_t i = 0; + string s; Timing t; ui.setupUi(this); + qRegisterMetaType>("QVector");//For previews. qRegisterMetaType>("vector"); qRegisterMetaType("EmberTreeWidgetItemBase*"); @@ -33,7 +36,7 @@ Fractorium::Fractorium(QWidget* p) tabifyDockWidget(ui.XformsDockWidget, ui.XaosDockWidget); tabifyDockWidget(ui.XaosDockWidget, ui.PaletteDockWidget); tabifyDockWidget(ui.PaletteDockWidget, ui.InfoDockWidget); - + m_Docks.reserve(8); m_Docks.push_back(ui.LibraryDockWidget); m_Docks.push_back(ui.FlameDockWidget); @@ -47,6 +50,7 @@ Fractorium::Fractorium(QWidget* p) m_PaletteSortMode = 0;//Sort by palette ascending by default. m_ColorDialog = new QColorDialog(this); m_Settings = new FractoriumSettings(this); + m_QssDialog = new QssDialog(this); m_FileDialog = nullptr;//Use lazy instantiation upon first use. m_FolderDialog = nullptr; @@ -121,19 +125,19 @@ Fractorium::Fractorium(QWidget* p) m_QualitySpin->setValue(30 * m_Settings->Devices().size()); int statusBarHeight = 20 * devicePixelRatio(); - ui.statusBar->setMinimumHeight(statusBarHeight); - ui.statusBar->setMaximumHeight(statusBarHeight); + ui.StatusBar->setMinimumHeight(statusBarHeight); + ui.StatusBar->setMaximumHeight(statusBarHeight); m_RenderStatusLabel = new QLabel(this); m_RenderStatusLabel->setMinimumWidth(200); m_RenderStatusLabel->setAlignment(Qt::AlignRight); - ui.statusBar->addPermanentWidget(m_RenderStatusLabel); + ui.StatusBar->addPermanentWidget(m_RenderStatusLabel); m_CoordinateStatusLabel = new QLabel(this); m_CoordinateStatusLabel->setMinimumWidth(300); m_CoordinateStatusLabel->setMaximumWidth(300); m_CoordinateStatusLabel->setAlignment(Qt::AlignLeft); - ui.statusBar->addWidget(m_CoordinateStatusLabel); + ui.StatusBar->addWidget(m_CoordinateStatusLabel); int progressBarHeight = 15; int progressBarWidth = 300; @@ -144,7 +148,7 @@ Fractorium::Fractorium(QWidget* p) m_ProgressBar->setMaximumHeight(progressBarHeight); m_ProgressBar->setMinimumWidth(progressBarWidth); m_ProgressBar->setMaximumWidth(progressBarWidth); - ui.statusBar->addPermanentWidget(m_ProgressBar); + ui.StatusBar->addPermanentWidget(m_ProgressBar); //Setup pointer in the GL window to point back to here. ui.GLDisplay->SetMainWindow(this); @@ -162,29 +166,43 @@ Fractorium::Fractorium(QWidget* p) ui.XformsTabWidget->setCurrentIndex(2);//Make variations tab the currently selected one under the Xforms tab. } - //Setting certain values will completely throw off the GUI, doing everything - //from setting strange margins, to arbitrarily changing the fonts used. - //For these cases, the only way to fix the problem is to use style sheets. - ui.ColorTable->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.GeometryTable->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.FilterTable->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.IterationTable->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.XformAffineTab->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.XformWeightNameTable->setStyleSheet("QTableWidget::item { padding: 0px; }"); - ui.XformColorIndexTable->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.XformColorValuesTable->setStyleSheet("QTableWidget::item { padding: 1px; }"); - ui.XformPaletteRefTable->setStyleSheet("QTableWidget::item { padding: 0px; border: none; margin: 0px; }"); - ui.PaletteAdjustTable->setStyleSheet("QTableWidget::item { padding: 1px; }");//Need this to avoid covering the top border pixel with the spinners. - ui.statusBar->setStyleSheet("QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }"); - ui.XaosTableView->setStyleSheet("QTableView { margin: 1px}"); - - //setStyleSheet("QGroupBox { border: 2px solid gray; border-radius: 3px; } "); - m_PreviousPaletteRow = -1;//Force click handler the first time through. SetCoordinateStatus(0, 0, 0, 0); - SetTabOrders(); - + m_SettingsPath = QFileInfo(m_Settings->fileName()).absoluteDir().absolutePath(); + ifstream ifs((m_SettingsPath + "/default.qss").toStdString().c_str(), ifstream::in); + + if (ifs.is_open()) + { + string total, qs; + + while (std::getline(ifs, qs)) + total += qs + "\n"; + + m_Style = QString::fromStdString(total); + } + else + m_Style = BaseStyle(); + + setStyleSheet(m_Style); + + if (!m_Settings->Theme().isEmpty()) + { + if (auto theme = QStyleFactory::create(m_Settings->Theme())) + { + m_Theme = theme; + setStyle(m_Theme); + } + } + else + { + if (!QStyleFactory::keys().empty()) + { + m_Theme = QStyleFactory::create(qApp->style()->objectName()); + setStyle(m_Theme); + } + } + //At this point, everything has been setup except the renderer. Shortly after //this constructor exits, GLWidget::InitGL() will create the initial flock and start the rendering timer //which executes whenever the program is idle. Upon starting the timer, the renderer @@ -764,7 +782,7 @@ void Fractorium::SetTabOrders() w = SetTabOrder(this, w, ui.PaletteListTable); - w = SetTabOrder(this, ui.SummaryTableWidget, ui.SummaryTreeWidget);//Info summary. + w = SetTabOrder(this, ui.SummaryTable, ui.SummaryTree);//Info summary. w = SetTabOrder(this, ui.InfoBoundsGroupBox, ui.InfoBoundsFrame);//Info bounds. diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index d94d379..0657f6c 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -19,6 +19,7 @@ /// class GLWidget; +class QssDialog; class FractoriumOptionsDialog; class FractoriumVariationsDialog; class FractoriumFinalRenderDialog; @@ -42,9 +43,9 @@ template class FinalRenderEmberController; /// certain parameters don't require a full render, the minimum necessary processing will be ran. /// When the user changes something on the GUI, the required processing action is added to a vector. /// Upon the next execution of the idle timer function, the most significant action will be extracted -/// and applied to the renderer. The vector is then cleared. +/// and applied to the renderer. The state change vector is then cleared. /// On the left side of the window is a dock widget which contains all controls needed for -/// manipulating embers. +/// manipulating embers. It's tabs can be floated, dragged, docked and nested elsewhere. /// Qt takes very long to create file dialog windows, so they are kept as members and initialized /// upon first use with lazy instantiation and then kept around for the remainder of the program. /// Additional dialogs are for the about box, options, and final rendering out to a file. @@ -53,9 +54,6 @@ template class FinalRenderEmberController; /// Fractorium.cpp and the other functional areas are each broken out into their own files. /// The order of the functions in each .cpp file should roughly match the order they appear in the .h file. /// Future todo list: -/// Add all of the plugins/variations that work with Apophysis and are open source. -/// Allow specifying variations to include/exclude from random generation. -/// Allow the option to specify a different palette file rather than the default flam3-palettes.xml. /// Implement more rendering types. /// Add support for animation previewing. /// Add support for full animation editing and rendering. @@ -66,6 +64,7 @@ class Fractorium : public QMainWindow Q_OBJECT friend GLWidget; + friend QssDialog; friend FractoriumOptionsDialog; friend FractoriumFinalRenderDialog; friend FractoriumAboutDialog; @@ -149,6 +148,7 @@ public slots: void OnActionCL(bool checked); void OnActionSP(bool checked); void OnActionDP(bool checked); + void OnActionStyle(bool checked); //Library. void OnEmberTreeItemChanged(QTreeWidgetItem* item, int col); @@ -472,8 +472,12 @@ private: //Files. QFileDialog* m_FileDialog; QFileDialog* m_FolderDialog; + QssDialog* m_QssDialog; QString m_LastSaveAll; QString m_LastSaveCurrent; + QString m_Style; + QStyle* m_Theme; + QString m_SettingsPath; //QMenu* m_FileTreeMenu; QProgressBar* m_ProgressBar; diff --git a/Source/Fractorium/Fractorium.qrc b/Source/Fractorium/Fractorium.qrc index d73965c..b8604ce 100644 --- a/Source/Fractorium/Fractorium.qrc +++ b/Source/Fractorium/Fractorium.qrc @@ -44,5 +44,7 @@ Icons/square.png Icons/cube.png Icons/table_gear.png + Icons/checkbox_checked.png + Icons/checkbox_unchecked.png diff --git a/Source/Fractorium/Fractorium.rc b/Source/Fractorium/Fractorium.rc index 0c3971ef8f70e712126066bbbf4cc42c2aa7d106..92599dfead4ffca715fbac2f72eeaf102537f852 100644 GIT binary patch delta 50 zcmaE){789&7YC!!WN!{bMx)KO9PG?Mjv|-%TT@F+qejU*HvD0RU*k B4H5tV delta 50 zcmaE){789&7YC!^WN!{bM#Igu9PG?Mjv|-%TT@F+qejU*HvD0RU)E B4GsVR diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index 4665e4c..b29f075 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -6,8 +6,8 @@ 0 0 - 1442 - 926 + 1451 + 953 @@ -74,8 +74,8 @@ 0 0 - 1175 - 859 + 1184 + 886 @@ -99,7 +99,7 @@ - 40 + 0 0 240 881 @@ -123,7 +123,7 @@ Flame - + 0 @@ -355,13 +355,13 @@ 0 - 156 + 154 16777215 - 156 + 154 @@ -579,13 +579,13 @@ 0 - 156 + 154 16777215 - 156 + 154 @@ -956,13 +956,13 @@ 0 - 156 + 154 16777215 - 156 + 154 @@ -1203,13 +1203,13 @@ 0 - 266 + 264 16777215 - 266 + 264 @@ -1524,7 +1524,7 @@ - 550 + 530 0 240 881 @@ -1545,7 +1545,7 @@ Xaos - + 4 @@ -1727,7 +1727,7 @@ - 790 + 770 0 240 881 @@ -1748,7 +1748,7 @@ Palette - + 5 @@ -1773,13 +1773,13 @@ 0 - 22 + 21 16777215 - 22 + 21 @@ -1865,7 +1865,11 @@ 0 - + + + true + + @@ -1966,7 +1970,14 @@ - + + + + 0 + 0 + + + @@ -2167,15 +2178,15 @@ - 280 + 240 0 - 267 + 291 881 - 267 + 291 613 @@ -2188,7 +2199,7 @@ Xforms - + 5 @@ -2210,6 +2221,9 @@ 2 + + 0 + @@ -2227,7 +2241,7 @@ 60 - 16777215 + 22 @@ -2464,13 +2478,13 @@ 0 - 45 + 44 16777215 - 45 + 44 @@ -2926,7 +2940,7 @@ 16777215 - 68 + 67 @@ -3286,8 +3300,8 @@ 0 0 - 239 - 742 + 263 + 743 @@ -3493,11 +3507,26 @@ 0 + + 0 + - 4 + 3 + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform 90 degrees counter clockwise @@ -3512,6 +3541,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform 90 degrees clockwise @@ -3526,6 +3567,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units right @@ -3549,7 +3602,13 @@ 75 - 22 + 23 + + + + + 16777215 + 23 @@ -3587,6 +3646,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units up @@ -3601,6 +3672,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units down @@ -3624,7 +3707,13 @@ 75 - 22 + 23 + + + + + 16777215 + 23 @@ -3642,6 +3731,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units left @@ -3665,7 +3766,13 @@ 75 - 22 + 23 + + + + + 16777215 + 23 @@ -3724,6 +3831,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform x degrees counter clockwise @@ -3738,6 +3857,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform x degrees clockwise @@ -3758,6 +3889,18 @@ 0 + + + 0 + 24 + + + + + 16777215 + 24 + + Flip xform vertically @@ -3781,7 +3924,13 @@ 75 - 0 + 24 + + + + + 16777215 + 24 @@ -3800,6 +3949,18 @@ 0 + + + 0 + 24 + + + + + 16777215 + 24 + + Flip xform horizontally @@ -3814,6 +3975,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Scale xform x percent down @@ -3828,6 +4001,18 @@ + + + 0 + 24 + + + + + 16777215 + 24 + + Scale xform x percent up @@ -4089,13 +4274,25 @@ 0 - 4 + 3 true + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform 90 degrees counter clockwise @@ -4113,6 +4310,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform 90 degrees clockwise @@ -4130,6 +4339,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units right @@ -4156,7 +4377,13 @@ 75 - 22 + 23 + + + + + 16777215 + 23 @@ -4197,6 +4424,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units up @@ -4214,6 +4453,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units down @@ -4240,7 +4491,13 @@ 75 - 22 + 23 + + + + + 16777215 + 23 @@ -4261,6 +4518,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Move xform x units left @@ -4287,7 +4556,13 @@ 75 - 22 + 23 + + + + + 16777215 + 23 @@ -4349,6 +4624,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform x degrees counter clockwise @@ -4366,6 +4653,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Rotate xform x degrees clockwise @@ -4383,6 +4682,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Flip xform horizontally @@ -4400,6 +4711,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Flip xform vertically @@ -4426,7 +4749,13 @@ 75 - 0 + 24 + + + + + 16777215 + 24 @@ -4442,6 +4771,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Scale xform x percent up @@ -4459,6 +4800,18 @@ true + + + 0 + 24 + + + + + 16777215 + 24 + + Scale xform x percent down @@ -4646,20 +4999,33 @@ 0 - + + + + 0 + 22 + + + + + 16777215 + 22 + + + 30 - 0 + 23 30 - 16777215 + 23 @@ -4860,7 +5226,7 @@ 5 - 4 + 5 5 @@ -4946,7 +5312,7 @@ 0 0 - 235 + 259 673 @@ -5003,7 +5369,7 @@ - 1000 + 1010 0 301 881 @@ -5113,7 +5479,7 @@ QTabWidget::Triangular - 0 + 1 @@ -5130,7 +5496,7 @@ 5 - 4 + 5 5 @@ -5139,7 +5505,7 @@ 4 - + 0 @@ -5149,13 +5515,13 @@ 0 - 128 + 126 16777215 - 128 + 126 @@ -5207,7 +5573,7 @@ true - true + false false @@ -5289,7 +5655,7 @@ - + 0 @@ -5324,7 +5690,7 @@ 2 - true + false false @@ -5461,16 +5827,16 @@ 0 - 0 + 5 0 - 0 + 5 - 0 + 5 @@ -5933,12 +6299,12 @@ - + 0 0 - 1442 + 1451 21 @@ -6021,7 +6387,7 @@ - + true @@ -6103,7 +6469,7 @@ 0 0 256 - 828 + 855 @@ -6145,6 +6511,9 @@ false + + 27 + Current Flame File @@ -6159,7 +6528,7 @@ - + toolBar @@ -6198,6 +6567,8 @@ + + @@ -6330,6 +6701,9 @@ Add R&eflective Symmetry + + Add reflective symmetry + @@ -6339,11 +6713,17 @@ Add R&otational Symmetry + + Add rotational symmetry + Add Reflective &and Rotational Symmetry + + Add reflective and rotational symmetry + @@ -6401,7 +6781,7 @@ Paste Xml &Over - Paste Xml as a new flame in the current file + Paste Xml over the current flame in the current file Ctrl+Shift+V @@ -6426,6 +6806,9 @@ &Stop Rendering Previews + + Stop rendering previews + @@ -6435,6 +6818,9 @@ Render &Previews + + Render previews + @@ -6468,6 +6854,9 @@ Paste Xml A&ppend + + Paste Xml as a new flame in the current file + Ctrl+V @@ -6481,7 +6870,7 @@ &Flatten - Add the Flatten variation to each xform + Add the flatten variation to each xform @@ -6493,7 +6882,7 @@ &Unflatten - Remove the Flatten variation from each xform + Remove the flatten variation from each xform @@ -6527,6 +6916,9 @@ &Reset Workspace + + Reset workspace + @@ -6584,6 +6976,17 @@ Use double precision to render + + + true + + + Style + + + Show QSS style editor + + diff --git a/Source/Fractorium/FractoriumCommon.h b/Source/Fractorium/FractoriumCommon.h index fbe7516..29081d5 100644 --- a/Source/Fractorium/FractoriumCommon.h +++ b/Source/Fractorium/FractoriumCommon.h @@ -357,3 +357,44 @@ static void HandleDeviceTableCheckChanged(QTableWidget* table, int row, int col) if (primaryItem->checkState() == Qt::Unchecked) primaryItem->setCheckState(Qt::Checked); } + +/// +/// The basic style that is needed for things to look right, this varies by OS. +/// +/// The base style +static QString BaseStyle() +{ + return "/*---Base Style---\n" + "This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows.\n" + "It's not needed for other themes." + "You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/\n" +#ifndef WIN32 + "QTabBar::tab { height: 3ex; }\n\n" +#else + "QTabBar::tab { height: 5ex; }\n\n" +#endif + "/*This is needed to give the labels on the status bar some padding.*/\n" + "QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }\n\n" + ; +} + +/// +/// Get all parent objects of the passed in widget. +/// +/// The widget whose parents will be retrieved +/// The entire parent object chain in a QList +template +static QList GetAllParents(QWidget* widget) +{ + QList parents; + + while (auto parent = qobject_cast(widget->parent())) + { + if (auto parentT = qobject_cast(parent)) + parents.push_back(parentT); + + widget = parent; + } + + return parents; +} \ No newline at end of file diff --git a/Source/Fractorium/FractoriumInfo.cpp b/Source/Fractorium/FractoriumInfo.cpp index ca99b6d..58c4b6c 100644 --- a/Source/Fractorium/FractoriumInfo.cpp +++ b/Source/Fractorium/FractoriumInfo.cpp @@ -6,22 +6,22 @@ /// void Fractorium::InitInfoUI() { - auto treeHeader = ui.SummaryTreeWidget->header(); - auto tableHeader = ui.SummaryTableWidget->horizontalHeader(); + auto treeHeader = ui.SummaryTree->header(); + auto tableHeader = ui.SummaryTable->horizontalHeader(); treeHeader->setVisible(true); treeHeader->setSectionsClickable(true); treeHeader->setSectionResizeMode(QHeaderView::ResizeToContents); connect(treeHeader, SIGNAL(sectionClicked(int)), this, SLOT(OnSummaryTreeHeaderSectionClicked(int)), Qt::QueuedConnection); connect(tableHeader, SIGNAL(sectionResized(int, int, int)), this, SLOT(OnSummaryTableHeaderResized(int, int, int)), Qt::QueuedConnection); - SetFixedTableHeader(ui.SummaryTableWidget->verticalHeader()); + SetFixedTableHeader(ui.SummaryTable->verticalHeader()); - ui.SummaryTableWidget->setItem(0, 0, m_InfoNameItem = new QTableWidgetItem("")); - ui.SummaryTableWidget->setItem(1, 0, m_InfoPaletteItem = new QTableWidgetItem("")); - ui.SummaryTableWidget->setItem(2, 0, m_Info3dItem = new QTableWidgetItem("")); - ui.SummaryTableWidget->setItem(3, 0, m_InfoXaosItem = new QTableWidgetItem("")); - ui.SummaryTableWidget->setItem(4, 0, m_InfoXformCountItem = new QTableWidgetItem("")); - ui.SummaryTableWidget->setItem(5, 0, m_InfoFinalXformItem = new QTableWidgetItem("")); + ui.SummaryTable->setItem(0, 0, m_InfoNameItem = new QTableWidgetItem("")); + ui.SummaryTable->setItem(1, 0, m_InfoPaletteItem = new QTableWidgetItem("")); + ui.SummaryTable->setItem(2, 0, m_Info3dItem = new QTableWidgetItem("")); + ui.SummaryTable->setItem(3, 0, m_InfoXaosItem = new QTableWidgetItem("")); + ui.SummaryTable->setItem(4, 0, m_InfoXformCountItem = new QTableWidgetItem("")); + ui.SummaryTable->setItem(5, 0, m_InfoFinalXformItem = new QTableWidgetItem("")); } /// @@ -34,7 +34,7 @@ void Fractorium::InitInfoUI() void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize) { QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());//Create a QPixmap out of the QImage, will be empty on startup. - SetPaletteTableItem(&pixmap, ui.SummaryTableWidget, m_InfoPaletteItem, 1, 0); + SetPaletteTableItem(&pixmap, ui.SummaryTable, m_InfoPaletteItem, 1, 0); } /// @@ -44,7 +44,7 @@ void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int /// The column which was clicked void Fractorium::OnSummaryTreeHeaderSectionClicked(int logicalIndex) { - auto tree = ui.SummaryTreeWidget; + auto tree = ui.SummaryTree; if (logicalIndex) tree->expandAll(); @@ -73,8 +73,8 @@ void FractoriumEmberController::FillSummary() size_t x = 0, total = m_Ember.TotalXformCount(); Xform* xform = nullptr; QColor color; - auto table = m_Fractorium->ui.SummaryTableWidget; - auto tree = m_Fractorium->ui.SummaryTreeWidget; + auto table = m_Fractorium->ui.SummaryTable; + auto tree = m_Fractorium->ui.SummaryTree; QVariantList states; QTreeWidgetItemIterator it(tree); diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index d44dc8d..eb659c9 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -82,7 +82,7 @@ void FractoriumEmberController::NewFlock(size_t count) /// Ignored void Fractorium::OnActionNewFlock(bool checked) { - m_Controller->NewFlock(10); + m_Controller->NewFlock(m_Settings->RandomCount()); m_Controller->SetEmber(0); } @@ -285,7 +285,7 @@ void FractoriumEmberController::SaveCurrentAsXml() ApplyXmlSavingTemplate(ember); ember.m_Edits = writer.CreateNewEditdoc(&ember, nullptr, "edit", s->Nick().toStdString(), s->Url().toStdString(), s->Id().toStdString(), "", 0, 0); - if (tempEdit != nullptr) + if (tempEdit) xmlFreeDoc(tempEdit); if (writer.Save(filename.toStdString().c_str(), ember, 0, true, false, true)) diff --git a/Source/Fractorium/FractoriumPch.h b/Source/Fractorium/FractoriumPch.h index c9fba54..b8af03b 100644 --- a/Source/Fractorium/FractoriumPch.h +++ b/Source/Fractorium/FractoriumPch.h @@ -23,26 +23,52 @@ #endif #include -#include -#include +#include "qfunctions.h" +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "glm/glm.hpp" #include "glm/gtc/matrix_transform.hpp" diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index 371eb25..1178f1e 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -712,7 +712,7 @@ bool Fractorium::CreateControllerFromOptions() } } - return m_Controller.get() != nullptr; + return m_Controller.get(); } /// diff --git a/Source/Fractorium/FractoriumSettings.cpp b/Source/Fractorium/FractoriumSettings.cpp index efe1182..8056d07 100644 --- a/Source/Fractorium/FractoriumSettings.cpp +++ b/Source/Fractorium/FractoriumSettings.cpp @@ -46,11 +46,9 @@ void FractoriumSettings::EnsureDefaults() FinalThreadPriority(Clamp(FinalThreadPriority(), (int)eThreadPriority::LOWEST, (int)eThreadPriority::HIGHEST)); - if (CpuSubBatch() < 1) - CpuSubBatch(1); - - if (OpenCLSubBatch() < 1) - OpenCLSubBatch(1); + CpuSubBatch(std::max(1u, CpuSubBatch())); + OpenCLSubBatch(std::max(1u, OpenCLSubBatch())); + RandomCount(std::max(1u, RandomCount())); if (FinalScale() > SCALE_HEIGHT) FinalScale(0); @@ -124,6 +122,9 @@ void FractoriumSettings::CpuSubBatch(uint i) { setValue(CPUSUBBATCH, i); uint FractoriumSettings::OpenCLSubBatch() { return value(OPENCLSUBBATCH).toUInt(); } void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH, i); } + +uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); } +void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); } /// /// Final render settings. @@ -232,3 +233,7 @@ void FractoriumSettings::SaveAutoUnique(bool b) { setValue(AUTOUNIQUE, b) QMap FractoriumSettings::Variations() { return value(UIVARIATIONS).toMap(); } void FractoriumSettings::Variations(const QMap& m) { setValue(UIVARIATIONS, m); } + +QString FractoriumSettings::Theme() { return value(STYLETHEME).toString(); } +void FractoriumSettings::Theme(const QString& s) { setValue(STYLETHEME, s); } + diff --git a/Source/Fractorium/FractoriumSettings.h b/Source/Fractorium/FractoriumSettings.h index 71c2754..36612ac 100644 --- a/Source/Fractorium/FractoriumSettings.h +++ b/Source/Fractorium/FractoriumSettings.h @@ -19,6 +19,7 @@ #define OPENCLDEFILTER "render/opencldefilter" #define CPUSUBBATCH "render/cpusubbatch" #define OPENCLSUBBATCH "render/openclsubbatch" +#define RANDOMCOUNT "render/randomcount" #define FINALEARLYCLIP "finalrender/earlyclip" #define FINALYAXISUP "finalrender/finalyaxisup" @@ -60,6 +61,8 @@ #define UIVARIATIONS "ui/variations" +#define STYLETHEME "style/theme" + /// /// Class for preserving various program options between /// runs of Fractorium. Each of these generally corresponds @@ -111,6 +114,9 @@ public: uint OpenCLSubBatch(); void OpenCLSubBatch(uint i); + uint RandomCount(); + void RandomCount(uint i); + bool FinalEarlyClip(); void FinalEarlyClip(bool b); @@ -206,4 +212,7 @@ public: QMap Variations(); void Variations(const QMap& m); + + QString Theme(); + void Theme(const QString& s); }; diff --git a/Source/Fractorium/FractoriumToolbar.cpp b/Source/Fractorium/FractoriumToolbar.cpp index 2d3f630..181c2fe 100644 --- a/Source/Fractorium/FractoriumToolbar.cpp +++ b/Source/Fractorium/FractoriumToolbar.cpp @@ -1,5 +1,6 @@ #include "FractoriumPch.h" #include "Fractorium.h" +#include "QssDialog.h" /// /// Initialize the toolbar UI. @@ -15,10 +16,11 @@ void Fractorium::InitToolbarUI() spGroup->addAction(ui.ActionDP); SyncOptionsToToolbar(); - connect(ui.ActionCpu, SIGNAL(triggered(bool)), this, SLOT(OnActionCpu(bool)), Qt::QueuedConnection); - connect(ui.ActionCL, SIGNAL(triggered(bool)), this, SLOT(OnActionCL(bool)), Qt::QueuedConnection); - connect(ui.ActionSP, SIGNAL(triggered(bool)), this, SLOT(OnActionSP(bool)), Qt::QueuedConnection); - connect(ui.ActionDP, SIGNAL(triggered(bool)), this, SLOT(OnActionDP(bool)), Qt::QueuedConnection); + connect(ui.ActionCpu, SIGNAL(triggered(bool)), this, SLOT(OnActionCpu(bool)), Qt::QueuedConnection); + connect(ui.ActionCL, SIGNAL(triggered(bool)), this, SLOT(OnActionCL(bool)), Qt::QueuedConnection); + connect(ui.ActionSP, SIGNAL(triggered(bool)), this, SLOT(OnActionSP(bool)), Qt::QueuedConnection); + connect(ui.ActionDP, SIGNAL(triggered(bool)), this, SLOT(OnActionDP(bool)), Qt::QueuedConnection); + connect(ui.ActionStyle, SIGNAL(triggered(bool)), this, SLOT(OnActionStyle(bool)), Qt::QueuedConnection); } /// @@ -73,6 +75,15 @@ void Fractorium::OnActionDP(bool checked) } } +/// +/// Called when the show style button is clicked. +/// +/// Ignored +void Fractorium::OnActionStyle(bool checked) +{ + m_QssDialog->show(); +} + /// /// Sync options data to the check state of the toolbar buttons. /// This does not trigger a clicked() event. diff --git a/Source/Fractorium/FractoriumXaos.cpp b/Source/Fractorium/FractoriumXaos.cpp index 9ed25d1..d930fae 100644 --- a/Source/Fractorium/FractoriumXaos.cpp +++ b/Source/Fractorium/FractoriumXaos.cpp @@ -12,10 +12,11 @@ void Fractorium::InitXaosUI() 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_XaosSpinBox->setDecimals(6); + m_XaosSpinBox->setObjectName("XaosSpinBox"); m_XaosTableModel = nullptr; m_XaosTableItemDelegate = new DoubleSpinBoxTableItemDelegate(m_XaosSpinBox, this); @@ -146,6 +147,12 @@ void Fractorium::FillXaosTable() if (oldModel) delete oldModel; + + //Needed to get the dark stylesheet to correctly color the top left corner button. + auto widgetList = ui.XaosTableView->findChildren(); + + for (auto& it : widgetList) + it->setEnabled(true); } /// diff --git a/Source/Fractorium/FractoriumXforms.cpp b/Source/Fractorium/FractoriumXforms.cpp index d63b2b1..3aec572 100644 --- a/Source/Fractorium/FractoriumXforms.cpp +++ b/Source/Fractorium/FractoriumXforms.cpp @@ -31,32 +31,6 @@ void Fractorium::InitXformsUI() connect(ui.XformWeightNameTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnXformNameChanged(int, int)), Qt::QueuedConnection); ui.CurrentXformCombo->setProperty("soloxform", -1); -/* - ui.XformsTabWidget->setStyleSheet( - - "QTabWidget::pane \n" - "{\n" - " border: 5px solid #898C95;\n" - " font: 9pt "Segoe UI";\n" - "}\n" - "\n" - "QTabWidget::tab-bar \n" - "{\n" - " bottom: -8px;\n" - "}\n" - "\n" - "DoubleSpinBox \n" - "{\n" - " font: 9pt "Segoe UI";\n" - "}\n" - "\n" - "SpinBox \n" - "{\n" - " font: 9pt "Segoe UI";\n" - "}" - ); - */ - #ifndef WIN32 //For some reason linux makes these 24x24, even though the designer explicitly says 16x16. ui.AddXformButton->setIconSize(QSize(16, 16)); diff --git a/Source/Fractorium/FractoriumXformsAffine.cpp b/Source/Fractorium/FractoriumXformsAffine.cpp index 4ffe748..42c042b 100644 --- a/Source/Fractorium/FractoriumXformsAffine.cpp +++ b/Source/Fractorium/FractoriumXformsAffine.cpp @@ -16,8 +16,7 @@ void Fractorium::InitXformsAffineUI() table->horizontalHeader()->setSectionsClickable(true); table->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - - connect(table->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPreAffineRowDoubleClicked(int)), Qt::QueuedConnection); + connect(table->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPreAffineRowDoubleClicked(int)), Qt::QueuedConnection); connect(table->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPreAffineColDoubleClicked(int)), Qt::QueuedConnection); //Pre affine spinners. @@ -169,8 +168,10 @@ void Fractorium::InitXformsAffineUI() m_PostSpins[4] = m_PostY2Spin; m_PostSpins[5] = m_PostO2Spin; - ui.PostAffineGroupBox->setChecked(true);//Flip it once to force the disabling of the group box. - ui.PostAffineGroupBox->setChecked(false); + ui.PreAffineGroupBox->setChecked(false);//Flip both once to force enabling/disabling the disabling of the group boxes and the corner buttons. + ui.PreAffineGroupBox->setChecked(true);//Pre affine enabled. + ui.PostAffineGroupBox->setChecked(true); + ui.PostAffineGroupBox->setChecked(false);//Post affine disabled. } /// @@ -604,11 +605,20 @@ void FractoriumEmberController::FillAffineWithXform(Xform* xform, bool pre /// /// Trigger a redraw which will show or hide the circle affine transforms /// based on whether each group box is checked or not. +/// Note that all sub buttons must manually be disabled/enabled in order to +/// get the top left corner button in the proper state. This is needed so +/// any style sheets can properly draw it based on its state. +/// Without explicitly setting it, that button is never actually disabled. /// Called when the group box check box for pre or post affine is checked. /// /// Ignored void Fractorium::OnAffineGroupBoxToggled(bool on) { + auto widgetList = sender()->findChildren(); + + for (auto& it : widgetList) + it->setEnabled(on); + ui.GLDisplay->update(); } diff --git a/Source/Fractorium/FractoriumXformsVariations.cpp b/Source/Fractorium/FractoriumXformsVariations.cpp index 66160fa..9079a01 100644 --- a/Source/Fractorium/FractoriumXformsVariations.cpp +++ b/Source/Fractorium/FractoriumXformsVariations.cpp @@ -239,7 +239,6 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)//Would if (xformVar) xform->DeleteVariationById(var->VariationId()); - //widgetItem->setBackgroundColor(0, Qt::darkGray);//Ensure background is always white if weight goes to zero. widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero. } else @@ -256,7 +255,6 @@ void FractoriumEmberController::VariationSpinBoxValueChanged(double d)//Would newVar->m_Weight = d; xform->AddVariation(newVar); - //widgetItem->setBackgroundColor(0, Qt::darkGray);//Set background to gray when a variation has non-zero weight in this xform. widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform. //If they've added a new parametric variation, then grab the values currently in the spinners diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp index 0768969..0d0051e 100644 --- a/Source/Fractorium/GLWidget.cpp +++ b/Source/Fractorium/GLWidget.cpp @@ -1084,7 +1084,7 @@ int GLEmberController::UpdateHover(v3T& glCoords) m_HoverType = HoverNone; //If there's a selected/current xform, check it first so it gets precedence over the others. - if (m_SelectedXform != nullptr) + if (m_SelectedXform) { //These checks prevent highlighting the pre/post selected xform circle, when one is set to show all, and the other //is set to show current, and the user hovers over another xform, but doesn't select it, then moves the mouse diff --git a/Source/Fractorium/Icons/checkbox_checked.png b/Source/Fractorium/Icons/checkbox_checked.png new file mode 100644 index 0000000000000000000000000000000000000000..cbf06f6513d6b11721290c3f0f3be5bd2d157e84 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4u6ByT*@`3|I*ik&<|I5lYhrq4+ec# z+yBO~?Yr9HrFJEM@*55oe_nRScB?@5mA5a~+Dre>ztgEwn#&fj==0TE^WOLVUw)_h zGVAoH{kuQ@@2ZaH^Z#|}$Nuj}kALHrEm--ud-gxGfA5)Jz4-BC&-Z%fNmttYe61Zy zUiZ(w>|nOY<8OXM#j3ZbU$P1uSMYTF^L3AS_x^%bwsQt73{&s@xR6kvY6)~EgQu&X J%Q~loCIBeyblU&` literal 0 HcmV?d00001 diff --git a/Source/Fractorium/Icons/checkbox_unchecked.png b/Source/Fractorium/Icons/checkbox_unchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5465582a9a2e6a85adbe07a4a2da5e80b8b017 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4u6ByT*@`3|I*ik&<|I5Q2ZO$= z?SJFg_Fe7pQoE8r`3`OJR&5hR("GPU_MAX_ALLOC_PERCENT=100")); #endif -#ifndef WIN32 - a.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px; margin-top: 1.1em; background-color: transparent; } \n" - "QTabBar::tab { height: 2.8ex; } \n" - "QGroupBox::title " - "{" - " background-color: transparent;" - " subcontrol-origin: margin; " - //" left: 3px; " - " subcontrol-position: top left;" - " padding: 0 3px 0 3px;" - //" padding: 2px;" - "} \n" - "QComboBox { margin-top: 0px; padding-bottom: 0px; }" - ); -#endif - int rv = -1; try { - //a.setStyle(QStyleFactory::create("Fusion")); - //QPalette darkPalette; - /*darkPalette.setColor(QPalette::Window, QColor(53, 53, 53)); - darkPalette.setColor(QPalette::WindowText, Qt::white); - darkPalette.setColor(QPalette::Base, QColor(25, 25, 25)); - darkPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); - darkPalette.setColor(QPalette::ToolTipBase, Qt::white); - darkPalette.setColor(QPalette::ToolTipText, Qt::white); - darkPalette.setColor(QPalette::Text, Qt::white); - darkPalette.setColor(QPalette::Button, QColor(53, 53, 53)); - darkPalette.setColor(QPalette::ButtonText, Qt::white); - darkPalette.setColor(QPalette::BrightText, Qt::red); - darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); - - darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::HighlightedText, Qt::black);;*/ - - //darkPalette.setColor(QPalette::, Qt::lightGray); - //darkPalette.setColor(QPalette::Window, Qt::darkGray); - //darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, Qt::red); - //darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::blue);//Works for disabled buttons, but not for disabled menus. - - //a.setPalette(darkPalette); - //a.setStyleSheet("QToolTip { color: #ffffff; background-color: darkgray; border: 1px solid white; }"); - //a.setStyleSheet("QTableWidget { border-color: darkgray; }") - //QString s; - - //s = "QTableView, QSpinBox, QDoubleSpinBox, QGroupBox, QTreeWidget { background-color: darkGray; } "; - //s += "QComboBox, QTextEdit, QLineEdit { background - color: lightGray; } "; - //s += "QTabWidget { window-color: darkGray; } "; - //a.setStyleSheet("{ color: rgb(85, 170, 0); }"); - //a.setStyleSheet("GLWidget { background-color: darkgray; }"); - //a.setStyleSheet("QTableView, QDoubleSpinBox { background-color: darkgray; }");//Works! - //a.setStyleSheet(s);//Works! - //a.setStyleSheet("QTableView, QSpinBox, QDoubleSpinBox, QTreeWidget, QTreeWidgetItem { background-color: darkgray; }");//QTreeWidgetItem not needed. - //a.setStyleSheet("QTableView, DoubleSpinBox { background-color: darkgray; }");//Works! - Fractorium w; w.show(); a.installEventFilter(&w); diff --git a/Source/Fractorium/OptionsDialog.cpp b/Source/Fractorium/OptionsDialog.cpp index 99cd953..dc7e10e 100644 --- a/Source/Fractorium/OptionsDialog.cpp +++ b/Source/Fractorium/OptionsDialog.cpp @@ -74,6 +74,7 @@ bool FractoriumOptionsDialog::Double() { return ui.DoublePrecisionCheckBox->isCh bool FractoriumOptionsDialog::ShowAllXforms() { return ui.ShowAllXformsCheckBox->isChecked(); } bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); } uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); } +uint FractoriumOptionsDialog::RandomCount() { return ui.RandomCountSpin->value(); } /// /// The check state of one of the OpenCL devices was changed. @@ -130,6 +131,7 @@ void FractoriumOptionsDialog::OnOpenCLCheckBoxStateChanged(int state) ui.CpuFilteringLogRadioButton->setEnabled(!checked); ui.OpenCLFilteringDERadioButton->setEnabled(checked); ui.OpenCLFilteringLogRadioButton->setEnabled(checked); + ui.InteraciveCpuFilteringGroupBox->setEnabled(!checked); ui.InteraciveGpuFilteringGroupBox->setEnabled(checked); } @@ -178,6 +180,7 @@ void FractoriumOptionsDialog::GuiToData() m_Settings->Double(Double()); m_Settings->ShowAllXforms(ShowAllXforms()); m_Settings->ThreadCount(ThreadCount()); + m_Settings->RandomCount(RandomCount()); m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value()); m_Settings->OpenCLSubBatch(ui.OpenCLSubBatchSpin->value()); m_Settings->CpuDEFilter(ui.CpuFilteringDERadioButton->isChecked()); @@ -212,6 +215,7 @@ void FractoriumOptionsDialog::DataToGui() ui.DoublePrecisionCheckBox->setChecked(m_Settings->Double()); ui.ShowAllXformsCheckBox->setChecked(m_Settings->ShowAllXforms()); ui.ThreadCountSpin->setValue(m_Settings->ThreadCount()); + ui.RandomCountSpin->setValue(m_Settings->RandomCount()); ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch()); ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch()); SettingsToDeviceTable(ui.DeviceTable, devices); diff --git a/Source/Fractorium/OptionsDialog.h b/Source/Fractorium/OptionsDialog.h index 4fc02ca..790e96f 100644 --- a/Source/Fractorium/OptionsDialog.h +++ b/Source/Fractorium/OptionsDialog.h @@ -47,6 +47,7 @@ private: bool ShowAllXforms(); bool AutoUnique(); uint ThreadCount(); + uint RandomCount(); void DataToGui(); void GuiToData(); diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui index 525b5e5..bce1238 100644 --- a/Source/Fractorium/OptionsDialog.ui +++ b/Source/Fractorium/OptionsDialog.ui @@ -32,7 +32,7 @@ Options - true + false @@ -112,7 +112,7 @@ - <html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will give fluid, real-time interactive editing.</p></body></html> + <html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will provide fluid, real-time interactive editing.</p></body></html> Use OpenCL @@ -257,7 +257,7 @@ - + <html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html> @@ -273,7 +273,7 @@ - + The number of 10,000 iteration chunks ran per thread on the CPU @@ -290,7 +290,7 @@ in interactive mode for each mouse movement - + The number of ~8M iteration chunks ran using OpenCL @@ -307,7 +307,7 @@ in interactive mode for each mouse movement - + CPU Filtering @@ -354,7 +354,7 @@ in interactive mode for each mouse movement - + OpenCL Filtering @@ -398,6 +398,22 @@ in interactive mode for each mouse movement + + + + <html><head/><body><p>The number of random flames to generate on startup.</p><p>These are usually of low quality, so leave the count as 1 unless you are searching for good randoms.</p></body></html> + + + Randoms + + + 1 + + + 99999 + + + @@ -431,13 +447,13 @@ in interactive mode for each mouse movement 0 - 68 + 67 16777215 - 68 + 67 @@ -624,13 +640,13 @@ in interactive mode for each mouse movement 120 - 68 + 67 16777215 - 68 + 67 @@ -820,6 +836,7 @@ in interactive mode for each mouse movement TransparencyCheckBox ShowAllXformsCheckBox ContinuousUpdateCheckBox + RandomCountSpin ThreadCountSpin CpuSubBatchSpin OpenCLSubBatchSpin diff --git a/Source/Fractorium/QssDialog.cpp b/Source/Fractorium/QssDialog.cpp new file mode 100644 index 0000000..330043a --- /dev/null +++ b/Source/Fractorium/QssDialog.cpp @@ -0,0 +1,694 @@ +#include "FractoriumPch.h" +#include "QssDialog.h" +#include "ui_QssDialog.h" +#include "qcssscanner.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +/// +/// Comparison for sorting object names. +/// Strings not starting with the letter 'Q' take precedence. +/// This has the effect of putting custom derived classes first before +/// all Q* classes. +/// +/// The first string to compare +/// The second string to compare +/// True if s1 < s2 with special rules for 'Q' taken into account. +bool CaseInsensitiveLessThanQ(const QString& s1, const QString& s2) +{ + if (s1.length() && s2.length()) + { + if (s1[0] == 'Q' && s2[0] == 'Q') + return s1.toLower() < s2.toLower(); + else if (s1[0] == 'Q') + return false; + else if (s2[0] == 'Q') + return true; + else + return s1.toLower() < s2.toLower(); + } + + return false; +} + +/// +/// Construct a QssDialog. +/// This manually constructs much of the menu GUI via code rather +/// than in the designer. +/// +/// The main Fractorium window. +QssDialog::QssDialog(Fractorium* parent) : + QDialog(parent), + ui(new Ui::QssDialog), + m_FileDialog(nullptr), + m_AddColorAction(new QAction(tr("Add Color"), this)), + m_AddGeomAction(new QAction(tr("Add Geometry"), this)), + m_AddBorderAction(new QAction(tr("Add Border"), this)), + m_AddFontAction(new QAction(tr("Add Font..."), this)), + m_AddStyleAction(new QAction(tr("Set Theme"), this)) +{ + ui->setupUi(this); + m_Parent = parent; + m_LastStyle = m_Parent->styleSheet(); + setWindowTitle("QSS Editor - default.qss"); + connect(ui->QssEdit, SIGNAL(textChanged()), this, SLOT(SlotTextChanged())); + + QToolBar* toolBar = new QToolBar(this); + QMenu* colorActionMenu = new QMenu(this); + QMenu* geomActionMenu = new QMenu(this); + QMenu* borderActionMenu = new QMenu(this); + QMenu* styleActionMenu = new QMenu(this); + + (m_ColorActionMapper = new QSignalMapper(this))->setMapping(m_AddColorAction, QString()); + (m_GeomActionMapper = new QSignalMapper(this))->setMapping(m_AddGeomAction, QString()); + (m_BorderActionMapper = new QSignalMapper(this))->setMapping(m_AddBorderAction, QString()); + (m_StyleActionMapper = new QSignalMapper(this))->setMapping(m_AddStyleAction, QString()); + + connect(ui->QssLoadButton, SIGNAL(clicked()), this, SLOT(LoadButton_clicked()), Qt::QueuedConnection); + connect(ui->QssSaveButton, SIGNAL(clicked()), this, SLOT(SaveButton_clicked()), Qt::QueuedConnection); + connect(ui->QssSaveDefaultButton, SIGNAL(clicked()), this, SLOT(SaveDefaultButton_clicked()), Qt::QueuedConnection); + connect(ui->QssBasicButton, SIGNAL(clicked()), this, SLOT(BasicButton_clicked()), Qt::QueuedConnection); + connect(ui->QssMediumButton, SIGNAL(clicked()), this, SLOT(MediumButton_clicked()), Qt::QueuedConnection); + connect(ui->QssAdvancedButton, SIGNAL(clicked()), this, SLOT(AdvancedButton_clicked()), Qt::QueuedConnection); + connect(m_AddFontAction, SIGNAL(triggered()), this, SLOT(SlotAddFont())); + + QVector> colorVec; + + colorVec.reserve(12); + colorVec.push_back(QPair("color", "")); + colorVec.push_back(QPair("background-color", "")); + colorVec.push_back(QPair("alternate-background-color", "")); + colorVec.push_back(QPair("border-color", "")); + colorVec.push_back(QPair("border-top-color", "")); + colorVec.push_back(QPair("border-right-color", "")); + colorVec.push_back(QPair("border-bottom-color", "")); + colorVec.push_back(QPair("border-left-color", "")); + colorVec.push_back(QPair("gridline-color", "")); + colorVec.push_back(QPair("selection-color", "")); + colorVec.push_back(QPair("selection-background-color", "")); + + for (auto& c : colorVec) + { + auto colorAction = colorActionMenu->addAction(c.first); + + m_ColorMap[c.first] = c.second; + connect(colorAction, SIGNAL(triggered()), m_ColorActionMapper, SLOT(map())); + m_ColorActionMapper->setMapping(colorAction, c.first); + } + + QVector> geomVec; + + geomVec.reserve(12); + geomVec.push_back(QPair("width", "100px")); + geomVec.push_back(QPair("height", "50px")); + geomVec.push_back(QPair("spacing", "10")); + geomVec.push_back(QPair("padding", "3px")); + geomVec.push_back(QPair("padding-top", "3px")); + geomVec.push_back(QPair("padding-right", "3px")); + geomVec.push_back(QPair("padding-bottom", "3px")); + geomVec.push_back(QPair("padding-left", "3px")); + geomVec.push_back(QPair("margin", "3px")); + geomVec.push_back(QPair("margin-top", "3px")); + geomVec.push_back(QPair("margin-right", "3px")); + geomVec.push_back(QPair("margin-bottom", "3px")); + geomVec.push_back(QPair("margin-left", "3px")); + + for (auto& g : geomVec) + { + auto geomAction = geomActionMenu->addAction(g.first); + + m_GeomMap[g.first] = g.second; + connect(geomAction, SIGNAL(triggered()), m_GeomActionMapper, SLOT(map())); + m_GeomActionMapper->setMapping(geomAction, g.first); + } + + QVector> borderVec; + + borderVec.reserve(8); + borderVec.push_back(QPair("border", "1px solid black")); + borderVec.push_back(QPair("border-top", "1px inset black")); + borderVec.push_back(QPair("border-right", "1px outset black")); + borderVec.push_back(QPair("border-bottom", "1px ridge black")); + borderVec.push_back(QPair("border-left", "1px groove black")); + borderVec.push_back(QPair("border-style", "double")); + borderVec.push_back(QPair("border-width", "1px")); + borderVec.push_back(QPair("border-radius", "10px")); + + for (auto& b : borderVec) + { + auto borderAction = borderActionMenu->addAction(b.first); + + m_BorderMap[b.first] = b.second; + connect(borderAction, SIGNAL(triggered()), m_BorderActionMapper, SLOT(map())); + m_BorderActionMapper->setMapping(borderAction, b.first); + } + + auto styles = QStyleFactory::keys(); + + for (auto& s : styles) + { + auto styleAction = styleActionMenu->addAction(s); + + m_StyleMap[s] = s; + connect(styleAction, SIGNAL(triggered()), m_StyleActionMapper, SLOT(map())); + m_StyleActionMapper->setMapping(styleAction, s); + } + + connect(m_ColorActionMapper, SIGNAL(mapped(QString)), this, SLOT(SlotAddColor(QString))); + connect(m_GeomActionMapper, SIGNAL(mapped(QString)), this, SLOT(SlotAddGeom(QString))); + connect(m_BorderActionMapper, SIGNAL(mapped(QString)), this, SLOT(SlotAddBorder(QString))); + connect(m_StyleActionMapper, SIGNAL(mapped(QString)), this, SLOT(SlotSetTheme(QString))); + + m_AddColorAction->setMenu(colorActionMenu); + m_AddGeomAction->setMenu(geomActionMenu); + m_AddBorderAction->setMenu(borderActionMenu); + m_AddStyleAction->setMenu(styleActionMenu); + + toolBar->addAction(m_AddColorAction); + toolBar->addAction(m_AddGeomAction); + toolBar->addAction(m_AddBorderAction); + toolBar->addAction(m_AddFontAction); + toolBar->addAction(m_AddStyleAction); + ui->verticalLayout->insertWidget(0, toolBar); + ui->QssEdit->setFocus(); + m_ApplyTimer = new QTimer(this); + m_ApplyTimer->setSingleShot(true); + m_ApplyTimer->setInterval(1000); + connect(m_ApplyTimer, SIGNAL(timeout()), this, SLOT(SlotApplyCss())); +} + +/// +/// Destructor that stops the apply timer and deletes the ui. +/// +QssDialog::~QssDialog() +{ + m_ApplyTimer->stop(); + delete ui; +} + +/// +/// Thin wrapper around getting the text from the main text box as plain text. +/// +/// The plain text of the main text box +QString QssDialog::Text() const +{ + return ui->QssEdit->toPlainText(); +} + +/// +/// Thin wrapper around setting the text of the main text box. +/// +/// The text to set +void QssDialog::SetText(const QString& t) +{ + ui->QssEdit->setText(t); +} + +/// +/// Get the class names of all objects in the application. +/// This only makes one entry for each class type. +/// It will also optionally return the object names as well for advanced QSS editing. +/// +/// Whether to get the individual object names as well +/// A list of all class names with optional entries for each individual object +QList QssDialog::GetClassNames(bool includeObjectNames) +{ + QSet classNames; + QList> dialogClassNames; + auto widgetList = m_Parent->findChildren(); + + for (int i = 0; i < widgetList.size(); i++) + { + auto classAndName = QString(widgetList[i]->metaObject()->className()); + + if (!includeObjectNames) + { + classNames.insert(classAndName); + } + else + { + auto dlg = qobject_cast(widgetList[i]); + + if (dlg)//Dialogs only nest one level deep, so no need for generalized recursion. + { + QSet dlgSet; + auto dlgWidgetList = dlg->findChildren();//Find all children of the dialog. + + dlgSet.insert(classAndName);//Add the basic dialog class name, opening curly brace will be added later. + classAndName += " "; + + for (int i = 0; i < dlgWidgetList.size(); i++) + { + auto dlgClassAndName = classAndName + QString(dlgWidgetList[i]->metaObject()->className()); + dlgSet.insert(dlgClassAndName); + + if (!dlgWidgetList[i]->objectName().isEmpty())//Add the class with object name for individual control customization. + { + dlgClassAndName += "#" + dlgWidgetList[i]->objectName(); + dlgSet.insert(dlgClassAndName); + } + } + + auto dlgList = dlgSet.toList();//Convert set to list and sort. + qSort(dlgList.begin(), dlgList.end(), CaseInsensitiveLessThanQ); + dialogClassNames.push_back(dlgList);//Add this to the full list after sorting at the end. + } + else if (GetAllParents(widgetList[i]).empty())//Skip widgets on dialogs, they are added above. + { + classNames.insert(classAndName);//Add the basic class name. + + if (!widgetList[i]->objectName().isEmpty())//Add the class with object name for individual control customization. + { + classAndName += "#" + widgetList[i]->objectName(); + classNames.insert(classAndName); + } + } + } + } + + auto l = classNames.toList(); + qSort(l.begin(), l.end(), CaseInsensitiveLessThanQ); + + for (auto& d : dialogClassNames) + l.append(d); + + return l; +} + +/// +/// Determines whether the passed in stylesheet text is valid. +/// If the initial parse fails, a second attempt is made by wrapping the entire +/// text in curly braces. +/// +/// The stylesheet text to analyze. +/// True if valid, else false. +bool QssDialog::IsStyleSheetValid(const QString& styleSheet) +{ + QCss::Parser parser(styleSheet); + QCss::StyleSheet sheet; + if (parser.parse(&sheet)) + return true; + QString fullSheet = QStringLiteral("* { "); + fullSheet += styleSheet; + fullSheet += QLatin1Char('}'); + QCss::Parser parser2(fullSheet); + return parser2.parse(&sheet); +} + +/// +/// Save the current stylesheet text to default.qss. +/// Also save the selected theme to the settings. +/// Called when the user clicks ok. +/// Not called if cancelled or closed with the X. +/// +void QssDialog::accept() +{ + if (m_Theme) + m_Parent->m_Settings->Theme(m_Theme->objectName()); + + SaveDefaultButton_clicked(); + QDialog::accept(); +} + +/// +/// Restore the stylesheet and theme to what it was when the dialog was opened. +/// Called when the user clicks cancel or closes with the X. +/// +void QssDialog::reject() +{ + if (!m_LastStyle.isEmpty()) + m_Parent->setStyleSheet(m_LastStyle); + + if (m_LastTheme) + { + m_Parent->setStyle(m_LastTheme); + m_Parent->m_Settings->Theme(m_LastTheme->objectName()); + } + + QDialog::reject(); +} + +/// +/// Shows the event. +/// +/// The e. +void QssDialog::showEvent(QShowEvent* e) +{ + if (m_Parent) + { + m_LastStyle = m_Parent->styleSheet(); + m_LastTheme = m_Parent->m_Theme;//The style() member cannot be relied upon, it is *not* the same object passed to setStyle(); + SetText(m_LastStyle); + } + + QDialog::showEvent(e); +} + +/// +/// Start the timer which will analyze and apply the current stylesheet text. +/// Each successive keystroke will reset the timer if it has not timed out yet. +/// This is only called when the dialog is visible because it seems to be spurriously +/// called on startup. +/// Called when the user changes the text in main text box. +/// +void QssDialog::SlotTextChanged() +{ + if (isVisible())//Sometimes this fires even though the window is not shown yet. + m_ApplyTimer->start(); +} + +/// +/// Add a color string to the stylesheet text. +/// Called when the user clicks the add color menu. +/// +/// The color string selector to add +void QssDialog::SlotAddColor(const QString& s) +{ + const QColor color = QColorDialog::getColor(0xffffffff, this, QString(), QColorDialog::ShowAlphaChannel); + + if (!color.isValid()) + return; + + QString colorStr; + + if (color.alpha() == 255) + { + colorStr = QString(QStringLiteral("rgb(%1, %2, %3)")).arg( + color.red()).arg(color.green()).arg(color.blue()); + } + else + { + colorStr = QString(QStringLiteral("rgba(%1, %2, %3, %4)")).arg( + color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()); + } + + InsertCssProperty(s, colorStr); +} + +/// +/// Adds a geometry string to the stylesheet text. +/// +/// The geometry string to add +void QssDialog::SlotAddGeom(const QString& s) +{ + auto val = m_GeomMap[s]; + + InsertCssProperty(s, val); +} + +/// +/// Adds a border string to the stylesheet text. +/// +/// The border string to add +void QssDialog::SlotAddBorder(const QString& s) +{ + auto val = m_BorderMap[s]; + + InsertCssProperty(s, val); +} + +/// +/// Set the theme to the user selection. +/// Called when the user selects an item on the theme combo box. +/// +/// The s. +void QssDialog::SlotSetTheme(const QString& s) +{ + if (auto theme = QStyleFactory::create(s)) + { + m_Theme = theme; + m_Parent->setStyle(m_Theme); + } +} + +/// +/// Add a font string. +/// Called when the user clicks the add font menu button. +/// +void QssDialog::SlotAddFont() +{ + bool ok; + auto font = QFontDialog::getFont(&ok, this); + + if (ok) + { + QString fontStr; + + if (font.weight() != QFont::Normal) + { + fontStr += QString::number(font.weight()); + fontStr += QLatin1Char(' '); + } + + switch (font.style()) + { + case QFont::StyleItalic: + fontStr += QStringLiteral("italic "); + break; + case QFont::StyleOblique: + fontStr += QStringLiteral("oblique "); + break; + default: + break; + } + + fontStr += QString::number(font.pointSize()); + fontStr += QStringLiteral("pt \""); + fontStr += font.family(); + fontStr += QLatin1Char('"'); + InsertCssProperty(QStringLiteral("font"), fontStr); + } +} + +/// +/// Check if the current stylesheet is valid and apply it if so. +/// Also indicate via label whether it was valid. +/// +void QssDialog::SlotApplyCss() +{ + auto label = ui->QssValidityLabel; + auto style = Text(); + const bool valid = IsStyleSheetValid(style); + ui->QssButtonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); + + if (valid) + { + label->setText(tr("Valid Style Sheet")); + label->setStyleSheet(QStringLiteral("color: green")); + m_Parent->setStyleSheet(style); + } + else + { + label->setText(tr("Invalid Style Sheet")); + label->setStyleSheet(QStringLiteral("color: red")); + } +} + +/// +/// Load a stylesheet from disk. +/// Called when the user clicks the load button. +/// +void QssDialog::LoadButton_clicked() +{ + string s; + auto f = OpenFile(); + + if (!f.isEmpty() && ReadFile(f.toStdString().c_str(), s) && !s.empty()) + SetText(QString::fromStdString(s)); + + setWindowTitle("QSS Editor - " + f); +} + +/// +/// Save the stylesheet to disk. +/// Called when the user clicks the save button. +/// +void QssDialog::SaveButton_clicked() +{ + auto path = SaveFile(); + + if (!path.isEmpty()) + { + ofstream of(path.toStdString()); + string s = Text().toStdString(); + + if (of.is_open()) + { + of << s; + of.close(); + } + else + QMessageBox::critical(this, "File open error", "Failed to open " + path + ", style will not be set as default"); + } +} + +/// +/// Save the stylesheet to the default.qss on disk. +/// This will be loaded the next time Fractorium runs. +/// Called when the user clicks the save as default button. +/// +void QssDialog::SaveDefaultButton_clicked() +{ + auto path = m_Parent->m_SettingsPath + "/default.qss"; + ofstream of(path.toStdString()); + auto s = Text().toStdString(); + + if (of.is_open()) + { + of << s; + of.close(); + } + else + QMessageBox::critical(this, "File open error", "Failed to open " + path + ", style will not be set as default"); +} + +/// +/// Fill the main text box with the most basic style. +/// Called when the Basic button is clicked. +/// +void QssDialog::BasicButton_clicked() +{ + SetText(BaseStyle()); + setWindowTitle("QSS Editor"); +} + +/// +/// Fill the main text box with a medium specificity style. +/// This will expose all control types in the application. +/// Called when the Medium button is clicked. +/// +void QssDialog::MediumButton_clicked() +{ + QString str = BaseStyle(); + auto names = GetClassNames(false); + + for (auto& it : names) + str += it + QString("\n{\n\t\n}\n\n"); + + SetText(str); + setWindowTitle("QSS Editor"); +} + +/// +/// Fill the main text box with the most advanced style. +/// This will expose all control types in the application as well as their named instances. +/// Called when the Advanced button is clicked. +/// +void QssDialog::AdvancedButton_clicked() +{ + QString str = BaseStyle(); + auto names = GetClassNames(true); + + for (auto& it : names) + str += it + QString("\n{\n\t\n}\n\n"); + + SetText(str); + setWindowTitle("QSS Editor"); +} + +/// +/// Insert a CSS property. +/// This is called whenever the user inserts a value via the menus. +/// +/// The name of the property to insert +/// The value of the property to insert +void QssDialog::InsertCssProperty(const QString& name, const QString& value) +{ + auto editor = ui->QssEdit; + auto cursor = editor->textCursor(); + + if (!name.isEmpty()) + { + cursor.beginEditBlock(); + cursor.removeSelectedText(); + cursor.movePosition(QTextCursor::EndOfLine); + + //Simple check to see if we're in a selector scope. + const QTextDocument* doc = editor->document(); + const QTextCursor closing = doc->find(QStringLiteral("}"), cursor, QTextDocument::FindBackward); + const QTextCursor opening = doc->find(QStringLiteral("{"), cursor, QTextDocument::FindBackward); + const bool inSelector = !opening.isNull() && (closing.isNull() || + closing.position() < opening.position()); + QString insertion; + + //Reasonable attempt at positioning things correctly. This can and often is wrong, but is sufficient for our purposes. + if (editor->textCursor().block().length() != 1 && !editor->textCursor().block().text().isEmpty()) + insertion += QLatin1Char('\n'); + + if (inSelector && editor->textCursor().block().text() != "\t") + insertion += QLatin1Char('\t'); + + insertion += name; + insertion += QStringLiteral(": "); + insertion += value; + insertion += QLatin1Char(';'); + cursor.insertText(insertion); + cursor.endEditBlock(); + } + else + { + cursor.insertText(value); + } +} + +/// +/// Initial file dialog creation. +/// This will perform lazy instantiation since it takes a long time. +/// +void QssDialog::SetupFileDialog() +{ + if (!m_FileDialog) + { + auto path = m_Parent->m_SettingsPath; + m_FileDialog = new QFileDialog(this); + m_FileDialog->setDirectory(path); + m_FileDialog->setViewMode(QFileDialog::List); + } +} + +/// +/// Present a file open dialog and retun the file selected. +/// +/// The file selected if any, else empty string. +QString QssDialog::OpenFile() +{ + QStringList filenames; + + SetupFileDialog(); + + m_FileDialog->setFileMode(QFileDialog::ExistingFile); + m_FileDialog->setAcceptMode(QFileDialog::AcceptOpen); + m_FileDialog->setNameFilter("Qss (*.qss)"); + m_FileDialog->setWindowTitle("Open Stylesheet"); + m_FileDialog->selectNameFilter("*.qss"); + + if (m_FileDialog->exec() == QDialog::Accepted) + filenames = m_FileDialog->selectedFiles(); + + return !filenames.empty() ? filenames[0] : ""; +} + +/// +/// Present a file save dialog and retun the file selected. +/// +/// The file selected for saving if any, else empty string. +QString QssDialog::SaveFile() +{ + QStringList filenames; + + SetupFileDialog(); + m_FileDialog->setFileMode(QFileDialog::AnyFile); + m_FileDialog->setAcceptMode(QFileDialog::AcceptSave); + m_FileDialog->setNameFilter("Qss (*.qss)"); + m_FileDialog->setWindowTitle("Save Stylesheet"); + m_FileDialog->selectNameFilter("*.qss"); + + if (m_FileDialog->exec() == QDialog::Accepted) + filenames = m_FileDialog->selectedFiles(); + + return !filenames.empty() ? filenames[0] : ""; +} diff --git a/Source/Fractorium/QssDialog.h b/Source/Fractorium/QssDialog.h new file mode 100644 index 0000000..958d556 --- /dev/null +++ b/Source/Fractorium/QssDialog.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#pragma once + +#include "Fractorium.h" +#include "FractoriumCommon.h" +#include "QssTextEdit.h" +#include "qcssparser.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +namespace Ui +{ + class QssDialog; +} + +/// +/// A dialog for editing the stylesheet used in the application. +/// This is meant to be used in the following way: +/// On first run, no stylesheet is present/selected, so a basic style +/// is used on startup. This style differs slightly between Windows and Linux. See BaseStyle() for details. +/// If the user clicks Save as default or ok to exit the dialog, the text of this stylesheet will +/// be saved to the application settings folder in the file default.qss. +/// On all subsequent runs, the main window will detect the presence of default.qss and load it. +/// The user can load a different stylesheet from disk, such as dark.qss which comes with the installation. +/// They can save this back to disk (under a different name because dark.qss is made read only by the installer), +/// however it will not become the default until they explicitly click the Save as default button or click ok. +/// The other buttons Basic, Medium and Advanced produce an empty style sheet that gives access to various controls. +/// Basic: Just the base style. +/// Medium: Basic + every type of control in the application. +/// Advanced: Medium + the name of every individual control in the application. It is not intended that the user fill +/// out a custom style for every single control. Rather, it's to make them aware of the names of the controls in the +/// event they want to set some custom styling for a specific control. +/// For all practical purposes, the user will probably start with dark.qss, edit what they need and save to a new stylesheet, +// then set that one as the default. +/// +class QssDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QssDialog(Fractorium* parent); + ~QssDialog(); + + QString Text() const; + void SetText(const QString& t); + QList GetClassNames(bool includeObjectNames); + static bool IsStyleSheetValid(const QString& styleSheet); + +public slots: + virtual void accept() override; + virtual void reject() override; + +protected: + virtual void showEvent(QShowEvent* e) override; + +private slots: + void SlotTextChanged(); + void SlotAddColor(const QString& p); + void SlotAddGeom(const QString& p); + void SlotAddBorder(const QString& p); + void SlotSetTheme(const QString& s); + void SlotAddFont(); + void SlotApplyCss(); + + void LoadButton_clicked(); + void SaveButton_clicked(); + void SaveDefaultButton_clicked(); + void BasicButton_clicked(); + void MediumButton_clicked(); + void AdvancedButton_clicked(); + +private: + void InsertCssProperty(const QString &name, const QString &value); + void SetupFileDialog(); + QString OpenFile(); + QString SaveFile(); + + QStyle* m_Theme; + QStyle* m_LastTheme; + QString m_LastStyle; + QAction* m_AddColorAction; + QAction* m_AddGeomAction; + QAction* m_AddBorderAction; + QAction* m_AddFontAction; + QAction* m_AddStyleAction; + QSignalMapper* m_ColorActionMapper; + QSignalMapper* m_GeomActionMapper; + QSignalMapper* m_BorderActionMapper; + QSignalMapper* m_StyleActionMapper; + QHash m_ColorMap; + QHash m_GeomMap; + QHash m_BorderMap; + QHash m_StyleMap; + QTimer* m_ApplyTimer; + Fractorium* m_Parent; + QFileDialog* m_FileDialog; + Ui::QssDialog *ui; +}; diff --git a/Source/Fractorium/QssDialog.ui b/Source/Fractorium/QssDialog.ui new file mode 100644 index 0000000..5120819 --- /dev/null +++ b/Source/Fractorium/QssDialog.ui @@ -0,0 +1,160 @@ + + + QssDialog + + + + 0 + 0 + 1041 + 644 + + + + QSS Editor + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + + + + + Load... + + + + + + + Save... + + + + + + + Save as default + + + + + + + Basic + + + + + + + Medium + + + + + + + Advanced + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Valid Qss + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + QssTextEdit + QTextEdit +
QssTextEdit.h
+
+
+ + + + QssButtonBox + accepted() + QssDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + QssButtonBox + rejected() + QssDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/Source/Fractorium/QssTextEdit.cpp b/Source/Fractorium/QssTextEdit.cpp new file mode 100644 index 0000000..e42428c --- /dev/null +++ b/Source/Fractorium/QssTextEdit.cpp @@ -0,0 +1,10 @@ +#include "FractoriumPch.h" +#include "QssTextEdit.h" + +QssTextEdit::QssTextEdit(QWidget* parent) : + QTextEdit(parent) +{ + setTabStopWidth(fontMetrics().width(QLatin1Char(' '))*4); + setAcceptRichText(false); + new CssHighlighter(document()); +} diff --git a/Source/Fractorium/QssTextEdit.h b/Source/Fractorium/QssTextEdit.h new file mode 100644 index 0000000..dceabed --- /dev/null +++ b/Source/Fractorium/QssTextEdit.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#pragma once + +#include "FractoriumPch.h" +#include "csshighlighter.h" + +class QssTextEdit : public QTextEdit +{ + Q_OBJECT +public: + QssTextEdit(QWidget* parent = nullptr); + +signals: + +public slots: + +}; diff --git a/Source/Fractorium/VariationsDialog.ui b/Source/Fractorium/VariationsDialog.ui index 2da42a0..3631f1b 100644 --- a/Source/Fractorium/VariationsDialog.ui +++ b/Source/Fractorium/VariationsDialog.ui @@ -98,7 +98,7 @@
- + diff --git a/Source/Fractorium/csshighlighter.cpp b/Source/Fractorium/csshighlighter.cpp new file mode 100644 index 0000000..73a7ed2 --- /dev/null +++ b/Source/Fractorium/csshighlighter.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "FractoriumPch.h" +#include "csshighlighter.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +CssHighlighter::CssHighlighter(QTextDocument *document) +: QSyntaxHighlighter(document) +{ +} + +void CssHighlighter::highlightBlock(const QString& text) +{ + enum Token { ALNUM, LBRACE, RBRACE, COLON, SEMICOLON, COMMA, QUOTE, SLASH, STAR }; + static const int transitions[10][9] = { + { Selector, Property, Selector, Pseudo, Property, Selector, Quote, MaybeComment, Selector }, // Selector + { Property, Property, Selector, Value, Property, Property, Quote, MaybeComment, Property }, // Property + { Value, Property, Selector, Value, Property, Value, Quote, MaybeComment, Value }, // Value + { Pseudo1, Property, Selector, Pseudo2, Selector, Selector, Quote, MaybeComment, Pseudo }, // Pseudo + { Pseudo1, Property, Selector, Pseudo, Selector, Selector, Quote, MaybeComment, Pseudo1 }, // Pseudo1 + { Pseudo2, Property, Selector, Pseudo, Selector, Selector, Quote, MaybeComment, Pseudo2 }, // Pseudo2 + { Quote, Quote, Quote, Quote, Quote, Quote, -1, Quote, Quote }, // Quote + { -1, -1, -1, -1, -1, -1, -1, -1, Comment }, // MaybeComment + { Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, MaybeCommentEnd }, // Comment + { Comment, Comment, Comment, Comment, Comment, Comment, Comment, -1, MaybeCommentEnd } // MaybeCommentEnd + }; + + int lastIndex = 0; + bool lastWasSlash = false; + int state = previousBlockState(), save_state; + if (state == -1) { + // As long as the text is empty, leave the state undetermined + if (text.isEmpty()) { + setCurrentBlockState(-1); + return; + } + // The initial state is based on the precense of a : and the absense of a {. + // This is because Qt style sheets support both a full stylesheet as well as + // an inline form with just properties. + state = save_state = (text.indexOf(QLatin1Char(':')) > -1 && + text.indexOf(QLatin1Char('{')) == -1) ? Property : Selector; + } else { + save_state = state>>16; + state &= 0x00ff; + } + + if (state == MaybeCommentEnd) { + state = Comment; + } else if (state == MaybeComment) { + state = save_state; + } + + for (int i = 0; i < text.length(); i++) { + int token = ALNUM; + const QChar c = text.at(i); + const char a = c.toLatin1(); + + if (state == Quote) { + if (a == '\\') { + lastWasSlash = true; + } else { + if (a == '\"' && !lastWasSlash) { + token = QUOTE; + } + lastWasSlash = false; + } + } else { + switch (a) { + case '{': token = LBRACE; break; + case '}': token = RBRACE; break; + case ':': token = COLON; break; + case ';': token = SEMICOLON; break; + case ',': token = COMMA; break; + case '\"': token = QUOTE; break; + case '/': token = SLASH; break; + case '*': token = STAR; break; + default: break; + } + } + + int new_state = transitions[state][token]; + + if (new_state != state) { + bool include_token = new_state == MaybeCommentEnd || (state == MaybeCommentEnd && new_state!= Comment) + || state == Quote; + highlight(text, lastIndex, i-lastIndex+include_token, state); + + if (new_state == Comment) { + lastIndex = i-1; // include the slash and star + } else { + lastIndex = i + ((token == ALNUM || new_state == Quote) ? 0 : 1); + } + } + + if (new_state == -1) { + state = save_state; + } else if (state <= Pseudo2) { + save_state = state; + state = new_state; + } else { + state = new_state; + } + } + + highlight(text, lastIndex, text.length() - lastIndex, state); + setCurrentBlockState(state + (save_state<<16)); +} + +void CssHighlighter::highlight(const QString &text, int start, int length, int state) +{ + if (start >= text.length() || length <= 0) + return; + + QTextCharFormat format; + + switch (state) { + case Selector: + setFormat(start, length, QColor::fromRgb(43, 145, 175));//Teal, like the Visual Studio default for classes in C++ and C#. + break; + case Property: + setFormat(start, length, Qt::darkBlue); + break; + case Value: + setFormat(start, length, Qt::black); + break; + case Pseudo1: + setFormat(start, length, Qt::darkRed); + break; + case Pseudo2: + setFormat(start, length, Qt::black); + break; + case Quote: + setFormat(start, length, Qt::darkMagenta); + break; + case Comment: + case MaybeCommentEnd: + format.setForeground(Qt::darkGreen); + setFormat(start, length, format); + break; + default: + break; + } +} diff --git a/Source/Fractorium/csshighlighter.h b/Source/Fractorium/csshighlighter.h new file mode 100644 index 0000000..2ff91c0 --- /dev/null +++ b/Source/Fractorium/csshighlighter.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt Designer. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// +#pragma once + +#include "FractoriumPch.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +class CssHighlighter : public QSyntaxHighlighter +{ + Q_OBJECT +public: + explicit CssHighlighter(QTextDocument *document); + +protected: + void highlightBlock(const QString&); + void highlight(const QString&, int, int, int/*State*/); + +private: + enum State { Selector, Property, Value, Pseudo, Pseudo1, Pseudo2, Quote, + MaybeComment, Comment, MaybeCommentEnd }; +}; diff --git a/Source/Fractorium/qcssparser.cpp b/Source/Fractorium/qcssparser.cpp new file mode 100644 index 0000000..9f444b7 --- /dev/null +++ b/Source/Fractorium/qcssparser.cpp @@ -0,0 +1,2697 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "FractoriumPch.h" +#include "qcssparser.h" +#include "qcssscanner.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +using namespace QCss; + +struct QCssKnownValue +{ + const char *name; + quint64 id; +}; + +static const QCssKnownValue properties[NumProperties - 1] = { + { "-qt-background-role", QtBackgroundRole }, + { "-qt-block-indent", QtBlockIndent }, + { "-qt-list-indent", QtListIndent }, + { "-qt-list-number-prefix", QtListNumberPrefix }, + { "-qt-list-number-suffix", QtListNumberSuffix }, + { "-qt-paragraph-type", QtParagraphType }, + { "-qt-style-features", QtStyleFeatures }, + { "-qt-table-type", QtTableType }, + { "-qt-user-state", QtUserState }, + { "alternate-background-color", QtAlternateBackground }, + { "background", Background }, + { "background-attachment", BackgroundAttachment }, + { "background-clip", BackgroundClip }, + { "background-color", BackgroundColor }, + { "background-image", BackgroundImage }, + { "background-origin", BackgroundOrigin }, + { "background-position", BackgroundPosition }, + { "background-repeat", BackgroundRepeat }, + { "border", Border }, + { "border-bottom", BorderBottom }, + { "border-bottom-color", BorderBottomColor }, + { "border-bottom-left-radius", BorderBottomLeftRadius }, + { "border-bottom-right-radius", BorderBottomRightRadius }, + { "border-bottom-style", BorderBottomStyle }, + { "border-bottom-width", BorderBottomWidth }, + { "border-color", BorderColor }, + { "border-image", BorderImage }, + { "border-left", BorderLeft }, + { "border-left-color", BorderLeftColor }, + { "border-left-style", BorderLeftStyle }, + { "border-left-width", BorderLeftWidth }, + { "border-radius", BorderRadius }, + { "border-right", BorderRight }, + { "border-right-color", BorderRightColor }, + { "border-right-style", BorderRightStyle }, + { "border-right-width", BorderRightWidth }, + { "border-style", BorderStyles }, + { "border-top", BorderTop }, + { "border-top-color", BorderTopColor }, + { "border-top-left-radius", BorderTopLeftRadius }, + { "border-top-right-radius", BorderTopRightRadius }, + { "border-top-style", BorderTopStyle }, + { "border-top-width", BorderTopWidth }, + { "border-width", BorderWidth }, + { "bottom", Bottom }, + { "color", Property::Color }, + { "float", Float }, + { "font", QCss::Font }, + { "font-family", FontFamily }, + { "font-size", FontSize }, + { "font-style", FontStyle }, + { "font-variant", FontVariant }, + { "font-weight", FontWeight }, + { "height", Height }, + { "image", QtImage }, + { "image-position", QtImageAlignment }, + { "left", Left }, + { "line-height", LineHeight }, + { "list-style", ListStyle }, + { "list-style-type", ListStyleType }, + { "margin" , Margin }, + { "margin-bottom", MarginBottom }, + { "margin-left", MarginLeft }, + { "margin-right", MarginRight }, + { "margin-top", MarginTop }, + { "max-height", MaximumHeight }, + { "max-width", MaximumWidth }, + { "min-height", MinimumHeight }, + { "min-width", MinimumWidth }, + { "outline", Outline }, + { "outline-bottom-left-radius", OutlineBottomLeftRadius }, + { "outline-bottom-right-radius", OutlineBottomRightRadius }, + { "outline-color", OutlineColor }, + { "outline-offset", OutlineOffset }, + { "outline-radius", OutlineRadius }, + { "outline-style", OutlineStyle }, + { "outline-top-left-radius", OutlineTopLeftRadius }, + { "outline-top-right-radius", OutlineTopRightRadius }, + { "outline-width", OutlineWidth }, + { "padding", Padding }, + { "padding-bottom", PaddingBottom }, + { "padding-left", PaddingLeft }, + { "padding-right", PaddingRight }, + { "padding-top", PaddingTop }, + { "page-break-after", PageBreakAfter }, + { "page-break-before", PageBreakBefore }, + { "position", Position }, + { "right", Right }, + { "selection-background-color", QtSelectionBackground }, + { "selection-color", QtSelectionForeground }, + { "spacing", QtSpacing }, + { "subcontrol-origin", QtOrigin }, + { "subcontrol-position", QtPosition }, + { "text-align", TextAlignment }, + { "text-decoration", TextDecoration }, + { "text-indent", TextIndent }, + { "text-transform", TextTransform }, + { "text-underline-style", TextUnderlineStyle }, + { "top", Top }, + { "vertical-align", VerticalAlignment }, + { "white-space", Whitespace }, + { "width", Width } +}; + +static const QCssKnownValue values[NumKnownValues - 1] = { + { "active", Value_Active }, + { "alternate-base", Value_AlternateBase }, + { "always", Value_Always }, + { "auto", Value_Auto }, + { "base", Value_Base }, + { "bold", Value_Bold }, + { "bottom", Value_Bottom }, + { "bright-text", Value_BrightText }, + { "button", Value_Button }, + { "button-text", Value_ButtonText }, + { "center", Value_Center }, + { "circle", Value_Circle }, + { "dark", Value_Dark }, + { "dashed", Value_Dashed }, + { "decimal", Value_Decimal }, + { "disabled", Value_Disabled }, + { "disc", Value_Disc }, + { "dot-dash", Value_DotDash }, + { "dot-dot-dash", Value_DotDotDash }, + { "dotted", Value_Dotted }, + { "double", Value_Double }, + { "groove", Value_Groove }, + { "highlight", Value_Highlight }, + { "highlighted-text", Value_HighlightedText }, + { "inset", Value_Inset }, + { "italic", Value_Italic }, + { "large", Value_Large }, + { "left", Value_Left }, + { "light", Value_Light }, + { "line-through", Value_LineThrough }, + { "link", Value_Link }, + { "link-visited", Value_LinkVisited }, + { "lower-alpha", Value_LowerAlpha }, + { "lower-roman", Value_LowerRoman }, + { "lowercase", Value_Lowercase }, + { "medium", Value_Medium }, + { "mid", Value_Mid }, + { "middle", Value_Middle }, + { "midlight", Value_Midlight }, + { "native", Value_Native }, + { "none", Value_None }, + { "normal", Value_Normal }, + { "nowrap", Value_NoWrap }, + { "oblique", Value_Oblique }, + { "off", Value_Off }, + { "on", Value_On }, + { "outset", Value_Outset }, + { "overline", Value_Overline }, + { "pre", Value_Pre }, + { "pre-wrap", Value_PreWrap }, + { "ridge", Value_Ridge }, + { "right", Value_Right }, + { "selected", Value_Selected }, + { "shadow", Value_Shadow }, + { "small" , Value_Small }, + { "small-caps", Value_SmallCaps }, + { "solid", Value_Solid }, + { "square", Value_Square }, + { "sub", Value_Sub }, + { "super", Value_Super }, + { "text", Value_Text }, + { "top", Value_Top }, + { "transparent", Value_Transparent }, + { "underline", Value_Underline }, + { "upper-alpha", Value_UpperAlpha }, + { "upper-roman", Value_UpperRoman }, + { "uppercase", Value_Uppercase }, + { "wave", Value_Wave }, + { "window", Value_Window }, + { "window-text", Value_WindowText }, + { "x-large", Value_XLarge }, + { "xx-large", Value_XXLarge } +}; + +//Map id to strings as they appears in the 'values' array above +static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 54, 35, 26, 70, 71, 25, 43, 5, 63, 47, + 29, 58, 59, 27, 51, 61, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 50, 24, 46, 67, 37, 3, 2, 40, 62, 16, + 11, 57, 14, 32, 64, 33, 65, 55, 66, 34, 69, 8, 28, 38, 12, 36, 60, 7, 9, 4, 68, 53, 22, 23, 30, 31, + 1, 15, 0, 52, 45, 44 }; + +QString Value::toString() const +{ + if (type == KnownIdentifier) { + return QLatin1String(values[indexOfId[variant.toInt()]].name); + } else { + return variant.toString(); + } +} + +static const QCssKnownValue pseudos[NumPseudos - 1] = { + { "active", PseudoClass_Active }, + { "adjoins-item", PseudoClass_Item }, + { "alternate", PseudoClass_Alternate }, + { "bottom", PseudoClass_Bottom }, + { "checked", PseudoClass_Checked }, + { "closable", PseudoClass_Closable }, + { "closed", PseudoClass_Closed }, + { "default", PseudoClass_Default }, + { "disabled", PseudoClass_Disabled }, + { "edit-focus", PseudoClass_EditFocus }, + { "editable", PseudoClass_Editable }, + { "enabled", PseudoClass_Enabled }, + { "exclusive", PseudoClass_Exclusive }, + { "first", PseudoClass_First }, + { "flat", PseudoClass_Flat }, + { "floatable", PseudoClass_Floatable }, + { "focus", PseudoClass_Focus }, + { "has-children", PseudoClass_Children }, + { "has-siblings", PseudoClass_Sibling }, + { "horizontal", PseudoClass_Horizontal }, + { "hover", PseudoClass_Hover }, + { "indeterminate" , PseudoClass_Indeterminate }, + { "last", PseudoClass_Last }, + { "left", PseudoClass_Left }, + { "maximized", PseudoClass_Maximized }, + { "middle", PseudoClass_Middle }, + { "minimized", PseudoClass_Minimized }, + { "movable", PseudoClass_Movable }, + { "next-selected", PseudoClass_NextSelected }, + { "no-frame", PseudoClass_Frameless }, + { "non-exclusive", PseudoClass_NonExclusive }, + { "off", PseudoClass_Unchecked }, + { "on", PseudoClass_Checked }, + { "only-one", PseudoClass_OnlyOne }, + { "open", PseudoClass_Open }, + { "pressed", PseudoClass_Pressed }, + { "previous-selected", PseudoClass_PreviousSelected }, + { "read-only", PseudoClass_ReadOnly }, + { "right", PseudoClass_Right }, + { "selected", PseudoClass_Selected }, + { "top", PseudoClass_Top }, + { "unchecked" , PseudoClass_Unchecked }, + { "vertical", PseudoClass_Vertical }, + { "window", PseudoClass_Window } +}; + +static const QCssKnownValue origins[NumKnownOrigins - 1] = { + { "border", Origin_Border }, + { "content", Origin_Content }, + { "margin", Origin_Margin }, // not in css + { "padding", Origin_Padding } +}; + +static const QCssKnownValue repeats[NumKnownRepeats - 1] = { + { "no-repeat", Repeat_None }, + { "repeat-x", Repeat_X }, + { "repeat-xy", Repeat_XY }, + { "repeat-y", Repeat_Y } +}; + +static const QCssKnownValue tileModes[NumKnownTileModes - 1] = { + { "repeat", TileMode_Repeat }, + { "round", TileMode_Round }, + { "stretch", TileMode_Stretch }, +}; + +static const QCssKnownValue positions[NumKnownPositionModes - 1] = { + { "absolute", PositionMode_Absolute }, + { "fixed", PositionMode_Fixed }, + { "relative", PositionMode_Relative }, + { "static", PositionMode_Static } +}; + +static const QCssKnownValue attachments[NumKnownAttachments - 1] = { + { "fixed", Attachment_Fixed }, + { "scroll", Attachment_Scroll } +}; + +static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = { + { "background-color", StyleFeature_BackgroundColor }, + { "background-gradient", StyleFeature_BackgroundGradient }, + { "none", StyleFeature_None } +}; + +#if defined(Q_CC_MSVC) && _MSC_VER < 1600 +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QCssKnownValue &prop1, const QCssKnownValue &prop2) +{ + return QString::compare(QString::fromLatin1(prop1.name), QLatin1String(prop2.name), Qt::CaseInsensitive) < 0; +} +#endif + +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &name, const QCssKnownValue &prop) +{ + return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0; +} + +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QCssKnownValue &prop, const QString &name) +{ + return QString::compare(QLatin1String(prop.name), name, Qt::CaseInsensitive) < 0; +} + +static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues) +{ + const QCssKnownValue *end = &start[numValues - 1]; + const QCssKnownValue *prop = std::lower_bound(start, end, name); + if ((prop == end) || (name < *prop)) + return 0; + return prop->id; +} + +/////////////////////////////////////////////////////////////////////////////// +// Value Extractor +ValueExtractor::ValueExtractor(const QVector &decls, const QPalette &pal) +: declarations(decls), adjustment(0), fontExtracted(false), pal(pal) +{ +} + +LengthData ValueExtractor::lengthValue(const Value& v) +{ + QString s = v.variant.toString(); + s.reserve(s.length()); + LengthData data; + data.unit = LengthData::NONE; + if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) + data.unit = LengthData::Px; + else if (s.endsWith(QLatin1String("ex"), Qt::CaseInsensitive)) + data.unit = LengthData::Ex; + else if (s.endsWith(QLatin1String("em"), Qt::CaseInsensitive)) + data.unit = LengthData::Em; + + if (data.unit != LengthData::NONE) + s.chop(2); + + data.number = s.toDouble(); + return data; +} + +static int lengthValueFromData(const LengthData& data, const QFont& f) +{ + if (data.unit == LengthData::Ex) + return qRound(QFontMetrics(f).xHeight() * data.number); + else if (data.unit == LengthData::Em) + return qRound(QFontMetrics(f).height() * data.number); + return qRound(data.number); +} + +int ValueExtractor::lengthValue(const Declaration &decl) +{ + if (decl.d->parsed.isValid()) + return lengthValueFromData(qvariant_cast(decl.d->parsed), f); + if (decl.d->values.count() < 1) + return 0; + LengthData data = lengthValue(decl.d->values.at(0)); + decl.d->parsed = QVariant::fromValue(data); + return lengthValueFromData(data,f); +} + +void ValueExtractor::lengthValues(const Declaration &decl, int *m) +{ + if (decl.d->parsed.isValid()) { + QList v = decl.d->parsed.toList(); + for (int i = 0; i < 4; i++) + m[i] = lengthValueFromData(qvariant_cast(v.at(i)), f); + return; + } + + LengthData datas[4]; + int i; + for (i = 0; i < qMin(decl.d->values.count(), 4); i++) + datas[i] = lengthValue(decl.d->values[i]); + + if (i == 0) { + LengthData zero = {0.0, LengthData::NONE}; + datas[0] = datas[1] = datas[2] = datas[3] = zero; + } else if (i == 1) { + datas[3] = datas[2] = datas[1] = datas[0]; + } else if (i == 2) { + datas[2] = datas[0]; + datas[3] = datas[1]; + } else if (i == 3) { + datas[3] = datas[1]; + } + + QList v; + for (i = 0; i < 4; i++) { + v += QVariant::fromValue(datas[i]); + m[i] = lengthValueFromData(datas[i], f); + } + decl.d->parsed = v; +} + +bool ValueExtractor::extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh) +{ + extractFont(); + bool hit = false; + for (int i = 0; i < declarations.count(); i++) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case Width: *w = lengthValue(decl); break; + case Height: *h = lengthValue(decl); break; + case MinimumWidth: *minw = lengthValue(decl); break; + case MinimumHeight: *minh = lengthValue(decl); break; + case MaximumWidth: *maxw = lengthValue(decl); break; + case MaximumHeight: *maxh = lengthValue(decl); break; + default: continue; + } + hit = true; + } + + return hit; +} + +bool ValueExtractor::extractPosition(int *left, int *top, int *right, int *bottom, QCss::Origin *origin, + Qt::Alignment *position, QCss::PositionMode *mode, Qt::Alignment *textAlignment) +{ + extractFont(); + bool hit = false; + for (int i = 0; i < declarations.count(); i++) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case Left: *left = lengthValue(decl); break; + case Top: *top = lengthValue(decl); break; + case Right: *right = lengthValue(decl); break; + case Bottom: *bottom = lengthValue(decl); break; + case QtOrigin: *origin = decl.originValue(); break; + case QtPosition: *position = decl.alignmentValue(); break; + case TextAlignment: *textAlignment = decl.alignmentValue(); break; + case Position: *mode = decl.positionValue(); break; + default: continue; + } + hit = true; + } + + return hit; +} + +bool ValueExtractor::extractBox(int *margins, int *paddings, int *spacing) +{ + extractFont(); + bool hit = false; + for (int i = 0; i < declarations.count(); i++) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case PaddingLeft: paddings[LeftEdge] = lengthValue(decl); break; + case PaddingRight: paddings[RightEdge] = lengthValue(decl); break; + case PaddingTop: paddings[TopEdge] = lengthValue(decl); break; + case PaddingBottom: paddings[BottomEdge] = lengthValue(decl); break; + case Padding: lengthValues(decl, paddings); break; + + case MarginLeft: margins[LeftEdge] = lengthValue(decl); break; + case MarginRight: margins[RightEdge] = lengthValue(decl); break; + case MarginTop: margins[TopEdge] = lengthValue(decl); break; + case MarginBottom: margins[BottomEdge] = lengthValue(decl); break; + case Margin: lengthValues(decl, margins); break; + case QtSpacing: if (spacing) *spacing = lengthValue(decl); break; + + default: continue; + } + hit = true; + } + + return hit; +} + +int ValueExtractor::extractStyleFeatures() +{ + int features = StyleFeature_None; + for (int i = 0; i < declarations.count(); i++) { + const Declaration &decl = declarations.at(i); + if (decl.d->propertyId == QtStyleFeatures) + features = decl.styleFeaturesValue(); + } + return features; +} + +QSize ValueExtractor::sizeValue(const Declaration &decl) +{ + if (decl.d->parsed.isValid()) { + QList v = decl.d->parsed.toList(); + return QSize(lengthValueFromData(qvariant_cast(v.at(0)), f), + lengthValueFromData(qvariant_cast(v.at(1)), f)); + } + + LengthData x[2] = { {0, LengthData::NONE }, {0, LengthData::NONE} }; + if (decl.d->values.count() > 0) + x[0] = lengthValue(decl.d->values.at(0)); + if (decl.d->values.count() > 1) + x[1] = lengthValue(decl.d->values.at(1)); + else + x[1] = x[0]; + QList v; + v << QVariant::fromValue(x[0]) << QVariant::fromValue(x[1]); + decl.d->parsed = v; + return QSize(lengthValueFromData(x[0], f), lengthValueFromData(x[1], f)); +} + +void ValueExtractor::sizeValues(const Declaration &decl, QSize *radii) +{ + radii[0] = sizeValue(decl); + for (int i = 1; i < 4; i++) + radii[i] = radii[0]; +} + +bool ValueExtractor::extractBorder(int *borders, QBrush *colors, BorderStyle *styles, + QSize *radii) +{ + extractFont(); + bool hit = false; + for (int i = 0; i < declarations.count(); i++) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case BorderLeftWidth: borders[LeftEdge] = lengthValue(decl); break; + case BorderRightWidth: borders[RightEdge] = lengthValue(decl); break; + case BorderTopWidth: borders[TopEdge] = lengthValue(decl); break; + case BorderBottomWidth: borders[BottomEdge] = lengthValue(decl); break; + case BorderWidth: lengthValues(decl, borders); break; + + case BorderLeftColor: colors[LeftEdge] = decl.brushValue(pal); break; + case BorderRightColor: colors[RightEdge] = decl.brushValue(pal); break; + case BorderTopColor: colors[TopEdge] = decl.brushValue(pal); break; + case BorderBottomColor: colors[BottomEdge] = decl.brushValue(pal); break; + case BorderColor: decl.brushValues(colors, pal); break; + + case BorderTopStyle: styles[TopEdge] = decl.styleValue(); break; + case BorderBottomStyle: styles[BottomEdge] = decl.styleValue(); break; + case BorderLeftStyle: styles[LeftEdge] = decl.styleValue(); break; + case BorderRightStyle: styles[RightEdge] = decl.styleValue(); break; + case BorderStyles: decl.styleValues(styles); break; + +#ifndef QT_OS_ANDROID_GCC_48_WORKAROUND + case BorderTopLeftRadius: radii[0] = sizeValue(decl); break; +#else + case BorderTopLeftRadius: new(radii)QSize(sizeValue(decl)); break; +#endif + case BorderTopRightRadius: radii[1] = sizeValue(decl); break; + case BorderBottomLeftRadius: radii[2] = sizeValue(decl); break; + case BorderBottomRightRadius: radii[3] = sizeValue(decl); break; + case BorderRadius: sizeValues(decl, radii); break; + + case BorderLeft: + borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]); + break; + case BorderTop: + borderValue(decl, &borders[TopEdge], &styles[TopEdge], &colors[TopEdge]); + break; + case BorderRight: + borderValue(decl, &borders[RightEdge], &styles[RightEdge], &colors[RightEdge]); + break; + case BorderBottom: + borderValue(decl, &borders[BottomEdge], &styles[BottomEdge], &colors[BottomEdge]); + break; + case Border: + borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]); + borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge]; + styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge]; + colors[TopEdge] = colors[RightEdge] = colors[BottomEdge] = colors[LeftEdge]; + break; + + default: continue; + } + hit = true; + } + + return hit; +} + +bool ValueExtractor::extractOutline(int *borders, QBrush *colors, BorderStyle *styles, + QSize *radii, int *offsets) +{ + extractFont(); + bool hit = false; + for (int i = 0; i < declarations.count(); i++) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case OutlineWidth: lengthValues(decl, borders); break; + case OutlineColor: decl.brushValues(colors, pal); break; + case OutlineStyle: decl.styleValues(styles); break; + + case OutlineTopLeftRadius: radii[0] = sizeValue(decl); break; + case OutlineTopRightRadius: radii[1] = sizeValue(decl); break; + case OutlineBottomLeftRadius: radii[2] = sizeValue(decl); break; + case OutlineBottomRightRadius: radii[3] = sizeValue(decl); break; + case OutlineRadius: sizeValues(decl, radii); break; + case OutlineOffset: lengthValues(decl, offsets); break; + + case Outline: + borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]); + borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge]; + styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge]; + colors[TopEdge] = colors[RightEdge] = colors[BottomEdge] = colors[LeftEdge]; + break; + + default: continue; + } + hit = true; + } + + return hit; +} + +static Qt::Alignment parseAlignment(const QCss::Value *values, int count) +{ + Qt::Alignment a[2] = { 0, 0 }; + for (int i = 0; i < qMin(2, count); i++) { + if (values[i].type != Value::KnownIdentifier) + break; + switch (values[i].variant.toInt()) { + case Value_Left: a[i] = Qt::AlignLeft; break; + case Value_Right: a[i] = Qt::AlignRight; break; + case Value_Top: a[i] = Qt::AlignTop; break; + case Value_Bottom: a[i] = Qt::AlignBottom; break; + case Value_Center: a[i] = Qt::AlignCenter; break; + default: break; + } + } + + if (a[0] == Qt::AlignCenter && a[1] != 0 && a[1] != Qt::AlignCenter) + a[0] = (a[1] == Qt::AlignLeft || a[1] == Qt::AlignRight) ? Qt::AlignVCenter : Qt::AlignHCenter; + if ((a[1] == 0 || a[1] == Qt::AlignCenter) && a[0] != Qt::AlignCenter) + a[1] = (a[0] == Qt::AlignLeft || a[0] == Qt::AlignRight) ? Qt::AlignVCenter : Qt::AlignHCenter; + return a[0] | a[1]; +} + +static ColorData parseColorValue(QCss::Value v) +{ + if (v.type == Value::Identifier || v.type == Value::String) { + v.variant.convert(QVariant::Color); + v.type = Value::Color; + } + + if (v.type == Value::Color) + return qvariant_cast(v.variant); + + if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent) + return QColor(Qt::transparent); + + if (v.type != Value::Function) + return ColorData(); + + QStringList lst = v.variant.toStringList(); + if (lst.count() != 2) + return ColorData(); + + if ((lst.at(0).compare(QLatin1String("palette"), Qt::CaseInsensitive)) == 0) { + int role = findKnownValue(lst.at(1).trimmed(), values, NumKnownValues); + if (role >= Value_FirstColorRole && role <= Value_LastColorRole) + return (QPalette::ColorRole)(role-Value_FirstColorRole); + + return ColorData(); + } + + bool rgb = lst.at(0).startsWith(QLatin1String("rgb")); + bool rgba = lst.at(0).startsWith(QLatin1String("rgba")); + + Parser p(lst.at(1)); + if (!p.testExpr()) + return ColorData(); + + QVector colorDigits; + if (!p.parseExpr(&colorDigits)) + return ColorData(); + + for (int i = 0; i < qMin(colorDigits.count(), 7); i += 2) { + if (colorDigits.at(i).type == Value::Percentage) { + colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (255. / 100.); + colorDigits[i].type = Value::Number; + } else if (colorDigits.at(i).type != Value::Number) { + return ColorData(); + } + } + + int v1 = colorDigits.at(0).variant.toInt(); + int v2 = colorDigits.at(2).variant.toInt(); + int v3 = colorDigits.at(4).variant.toInt(); + int alpha = 255; + if (colorDigits.count() >= 7) { + int alphaValue = colorDigits.at(6).variant.toInt(); + if (rgba && alphaValue <= 1) + alpha = colorDigits.at(6).variant.toReal() * 255.; + else + alpha = alphaValue; + } + + return rgb ? QColor::fromRgb(v1, v2, v3, alpha) + : QColor::fromHsv(v1, v2, v3, alpha); +} + +static QColor colorFromData(const ColorData& c, const QPalette &pal) +{ + if (c.type == ColorData::Color) { + return c.color; + } else if (c.type == ColorData::Role) { + return pal.color(c.role); + } + return QColor(); +} + +static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal) +{ + ColorData c = parseColorValue(v); + if (c.type == ColorData::Color) { + return QBrush(c.color); + } else if (c.type == ColorData::Role) { + return c.role; + } + + if (v.type != Value::Function) + return BrushData(); + + QStringList lst = v.variant.toStringList(); + if (lst.count() != 2) + return BrushData(); + + QStringList gradFuncs; + gradFuncs << QLatin1String("qlineargradient") << QLatin1String("qradialgradient") << QLatin1String("qconicalgradient") << QLatin1String("qgradient"); + int gradType = -1; + + if ((gradType = gradFuncs.indexOf(lst.at(0).toLower())) == -1) + return BrushData(); + + QHash vars; + QVector stops; + + int spread = -1; + QStringList spreads; + spreads << QLatin1String("pad") << QLatin1String("reflect") << QLatin1String("repeat"); + + bool dependsOnThePalette = false; + Parser parser(lst.at(1)); + while (parser.hasNext()) { + parser.skipSpace(); + if (!parser.test(IDENT)) + return BrushData(); + QString attr = parser.lexem(); + parser.skipSpace(); + if (!parser.test(COLON)) + return BrushData(); + parser.skipSpace(); + if (attr.compare(QLatin1String("stop"), Qt::CaseInsensitive) == 0) { + QCss::Value stop, color; + parser.next(); + if (!parser.parseTerm(&stop)) return BrushData(); + parser.skipSpace(); + parser.next(); + if (!parser.parseTerm(&color)) return BrushData(); + ColorData cd = parseColorValue(color); + if(cd.type == ColorData::Role) + dependsOnThePalette = true; + stops.append(QGradientStop(stop.variant.toReal(), colorFromData(cd, pal))); + } else { + parser.next(); + QCss::Value value; + (void)parser.parseTerm(&value); + if (attr.compare(QLatin1String("spread"), Qt::CaseInsensitive) == 0) { + spread = spreads.indexOf(value.variant.toString()); + } else { + vars[attr] = value.variant.toReal(); + } + } + parser.skipSpace(); + (void)parser.test(COMMA); + } + + if (gradType == 0) { + QLinearGradient lg(vars.value(QLatin1String("x1")), vars.value(QLatin1String("y1")), + vars.value(QLatin1String("x2")), vars.value(QLatin1String("y2"))); + lg.setCoordinateMode(QGradient::ObjectBoundingMode); + lg.setStops(stops); + if (spread != -1) + lg.setSpread(QGradient::Spread(spread)); + BrushData bd = QBrush(lg); + if (dependsOnThePalette) + bd.type = BrushData::DependsOnThePalette; + return bd; + } + + if (gradType == 1) { + QRadialGradient rg(vars.value(QLatin1String("cx")), vars.value(QLatin1String("cy")), + vars.value(QLatin1String("radius")), vars.value(QLatin1String("fx")), + vars.value(QLatin1String("fy"))); + rg.setCoordinateMode(QGradient::ObjectBoundingMode); + rg.setStops(stops); + if (spread != -1) + rg.setSpread(QGradient::Spread(spread)); + BrushData bd = QBrush(rg); + if (dependsOnThePalette) + bd.type = BrushData::DependsOnThePalette; + return bd; + } + + if (gradType == 2) { + QConicalGradient cg(vars.value(QLatin1String("cx")), vars.value(QLatin1String("cy")), + vars.value(QLatin1String("angle"))); + cg.setCoordinateMode(QGradient::ObjectBoundingMode); + cg.setStops(stops); + if (spread != -1) + cg.setSpread(QGradient::Spread(spread)); + BrushData bd = QBrush(cg); + if (dependsOnThePalette) + bd.type = BrushData::DependsOnThePalette; + return bd; + } + + return BrushData(); +} + +static QBrush brushFromData(const BrushData& c, const QPalette &pal) +{ + if (c.type == BrushData::Role) { + return pal.color(c.role); + } else { + return c.brush; + } +} + +static BorderStyle parseStyleValue(QCss::Value v) +{ + if (v.type == Value::KnownIdentifier) { + switch (v.variant.toInt()) { + case Value_None: + return BorderStyle_None; + case Value_Dotted: + return BorderStyle_Dotted; + case Value_Dashed: + return BorderStyle_Dashed; + case Value_Solid: + return BorderStyle_Solid; + case Value_Double: + return BorderStyle_Double; + case Value_DotDash: + return BorderStyle_DotDash; + case Value_DotDotDash: + return BorderStyle_DotDotDash; + case Value_Groove: + return BorderStyle_Groove; + case Value_Ridge: + return BorderStyle_Ridge; + case Value_Inset: + return BorderStyle_Inset; + case Value_Outset: + return BorderStyle_Outset; + case Value_Native: + return BorderStyle_Native; + default: + break; + } + } + + return BorderStyle_Unknown; +} + +void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color) +{ + if (decl.d->parsed.isValid()) { + BorderData data = qvariant_cast(decl.d->parsed); + *width = lengthValueFromData(data.width, f); + *style = data.style; + *color = data.color.type != BrushData::Invalid ? brushFromData(data.color, pal) : QBrush(QColor()); + return; + } + + *width = 0; + *style = BorderStyle_None; + *color = QColor(); + + if (decl.d->values.isEmpty()) + return; + + BorderData data; + data.width.number = 0; + data.width.unit = LengthData::NONE; + data.style = BorderStyle_None; + + int i = 0; + if (decl.d->values.at(i).type == Value::Length || decl.d->values.at(i).type == Value::Number) { + data.width = lengthValue(decl.d->values.at(i)); + *width = lengthValueFromData(data.width, f); + if (++i >= decl.d->values.count()) { + decl.d->parsed = QVariant::fromValue(data); + return; + } + } + + data.style = parseStyleValue(decl.d->values.at(i)); + if (data.style != BorderStyle_Unknown) { + *style = data.style; + if (++i >= decl.d->values.count()) { + decl.d->parsed = QVariant::fromValue(data); + return; + } + } else { + data.style = BorderStyle_None; + } + + data.color = parseBrushValue(decl.d->values.at(i), pal); + *color = brushFromData(data.color, pal); + if (data.color.type != BrushData::DependsOnThePalette) + decl.d->parsed = QVariant::fromValue(data); +} + +static void parseShorthandBackgroundProperty(const QVector &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal) +{ + *brush = BrushData(); + *image = QString(); + *repeat = Repeat_XY; + *alignment = Qt::AlignTop | Qt::AlignLeft; + + for (int i = 0; i < values.count(); ++i) { + const QCss::Value &v = values.at(i); + if (v.type == Value::Uri) { + *image = v.variant.toString(); + continue; + } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_None) { + *image = QString(); + continue; + } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent) { + *brush = QBrush(Qt::transparent); + } + + Repeat repeatAttempt = static_cast(findKnownValue(v.variant.toString(), + repeats, NumKnownRepeats)); + if (repeatAttempt != Repeat_Unknown) { + *repeat = repeatAttempt; + continue; + } + + if (v.type == Value::KnownIdentifier) { + const int start = i; + int count = 1; + if (i < values.count() - 1 + && values.at(i + 1).type == Value::KnownIdentifier) { + ++i; + ++count; + } + Qt::Alignment a = parseAlignment(values.constData() + start, count); + if (int(a) != 0) { + *alignment = a; + continue; + } + i -= count - 1; + } + + *brush = parseBrushValue(v, pal); + } +} + +bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *repeat, + Qt::Alignment *alignment, Origin *origin, Attachment *attachment, + Origin *clip) +{ + bool hit = false; + for (int i = 0; i < declarations.count(); ++i) { + const Declaration &decl = declarations.at(i); + if (decl.d->values.isEmpty()) + continue; + const QCss::Value &val = decl.d->values.at(0); + switch (decl.d->propertyId) { + case BackgroundColor: + *brush = decl.brushValue(); + break; + case BackgroundImage: + if (val.type == Value::Uri) + *image = val.variant.toString(); + break; + case BackgroundRepeat: + if (decl.d->parsed.isValid()) { + *repeat = static_cast(decl.d->parsed.toInt()); + } else { + *repeat = static_cast(findKnownValue(val.variant.toString(), + repeats, NumKnownRepeats)); + decl.d->parsed = *repeat; + } + break; + case BackgroundPosition: + *alignment = decl.alignmentValue(); + break; + case BackgroundOrigin: + *origin = decl.originValue(); + break; + case BackgroundClip: + *clip = decl.originValue(); + break; + case Background: + if (decl.d->parsed.isValid()) { + BackgroundData data = qvariant_cast(decl.d->parsed); + *brush = brushFromData(data.brush, pal); + *image = data.image; + *repeat = data.repeat; + *alignment = data.alignment; + } else { + BrushData brushData; + parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal); + *brush = brushFromData(brushData, pal); + if (brushData.type != BrushData::DependsOnThePalette) { + BackgroundData data = { brushData, *image, *repeat, *alignment }; + decl.d->parsed = QVariant::fromValue(data); + } + } + break; + case BackgroundAttachment: + *attachment = decl.attachmentValue(); + break; + default: continue; + } + hit = true; + } + return hit; +} + +static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment) +{ + if (value.type == Value::KnownIdentifier) { + bool valid = true; + switch (value.variant.toInt()) { + case Value_Small: *fontSizeAdjustment = -1; break; + case Value_Medium: *fontSizeAdjustment = 0; break; + case Value_Large: *fontSizeAdjustment = 1; break; + case Value_XLarge: *fontSizeAdjustment = 2; break; + case Value_XXLarge: *fontSizeAdjustment = 3; break; + default: valid = false; break; + } + return valid; + } + if (value.type != Value::Length) + return false; + + bool valid = false; + QString s = value.variant.toString(); + if (s.endsWith(QLatin1String("pt"), Qt::CaseInsensitive)) { + s.chop(2); + value.variant = s; + if (value.variant.convert((QVariant::Type)qMetaTypeId())) { + font->setPointSizeF(value.variant.toReal()); + valid = true; + } + } else if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) { + s.chop(2); + value.variant = s; + if (value.variant.convert(QVariant::Int)) { + font->setPixelSize(value.variant.toInt()); + valid = true; + } + } + return valid; +} + +static bool setFontStyleFromValue(const QCss::Value &value, QFont *font) +{ + if (value.type != Value::KnownIdentifier) + return false ; + switch (value.variant.toInt()) { + case Value_Normal: font->setStyle(QFont::StyleNormal); return true; + case Value_Italic: font->setStyle(QFont::StyleItalic); return true; + case Value_Oblique: font->setStyle(QFont::StyleOblique); return true; + default: break; + } + return false; +} + +static bool setFontWeightFromValue(const QCss::Value &value, QFont *font) +{ + if (value.type == Value::KnownIdentifier) { + switch (value.variant.toInt()) { + case Value_Normal: font->setWeight(QFont::Normal); return true; + case Value_Bold: font->setWeight(QFont::Bold); return true; + default: break; + } + return false; + } + if (value.type != Value::Number) + return false; + font->setWeight(qMin(value.variant.toInt() / 8, 99)); + return true; +} + +/** \internal + * parse the font family from the values (starting from index \a start) + * and set it the \a font + * The function returns \c true if a family was extracted. + */ +static bool setFontFamilyFromValues(const QVector &values, QFont *font, int start = 0) +{ + QString family; + bool shouldAddSpace = false; + for (int i = start; i < values.count(); ++i) { + const QCss::Value &v = values.at(i); + if (v.type == Value::TermOperatorComma) { + family += QLatin1Char(','); + shouldAddSpace = false; + continue; + } + const QString str = v.variant.toString(); + if (str.isEmpty()) + break; + if (shouldAddSpace) + family += QLatin1Char(' '); + family += str; + shouldAddSpace = true; + } + if (family.isEmpty()) + return false; + font->setFamily(family); + return true; +} + +static void setTextDecorationFromValues(const QVector &values, QFont *font) +{ + for (int i = 0; i < values.count(); ++i) { + if (values.at(i).type != Value::KnownIdentifier) + continue; + switch (values.at(i).variant.toInt()) { + case Value_Underline: font->setUnderline(true); break; + case Value_Overline: font->setOverline(true); break; + case Value_LineThrough: font->setStrikeOut(true); break; + case Value_None: + font->setUnderline(false); + font->setOverline(false); + font->setStrikeOut(false); + break; + default: break; + } + } +} + +static void parseShorthandFontProperty(const QVector &values, QFont *font, int *fontSizeAdjustment) +{ + font->setStyle(QFont::StyleNormal); + font->setWeight(QFont::Normal); + *fontSizeAdjustment = -255; + + int i = 0; + while (i < values.count()) { + if (setFontStyleFromValue(values.at(i), font) + || setFontWeightFromValue(values.at(i), font)) + ++i; + else + break; + } + + if (i < values.count()) { + setFontSizeFromValue(values.at(i), font, fontSizeAdjustment); + ++i; + } + + if (i < values.count()) { + setFontFamilyFromValues(values, font, i); + } +} + +static void setFontVariantFromValue(const QCss::Value &value, QFont *font) +{ + if (value.type == Value::KnownIdentifier) { + switch (value.variant.toInt()) { + case Value_Normal: font->setCapitalization(QFont::MixedCase); break; + case Value_SmallCaps: font->setCapitalization(QFont::SmallCaps); break; + default: break; + } + } +} + +static void setTextTransformFromValue(const QCss::Value &value, QFont *font) +{ + if (value.type == Value::KnownIdentifier) { + switch (value.variant.toInt()) { + case Value_None: font->setCapitalization(QFont::MixedCase); break; + case Value_Uppercase: font->setCapitalization(QFont::AllUppercase); break; + case Value_Lowercase: font->setCapitalization(QFont::AllLowercase); break; + default: break; + } + } +} + +bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment) +{ + if (fontExtracted) { + *font = f; + *fontSizeAdjustment = adjustment; + return fontExtracted == 1; + } + + bool hit = false; + for (int i = 0; i < declarations.count(); ++i) { + const Declaration &decl = declarations.at(i); + if (decl.d->values.isEmpty()) + continue; + const QCss::Value &val = decl.d->values.at(0); + switch (decl.d->propertyId) { + case FontSize: setFontSizeFromValue(val, font, fontSizeAdjustment); break; + case FontStyle: setFontStyleFromValue(val, font); break; + case FontWeight: setFontWeightFromValue(val, font); break; + case FontFamily: setFontFamilyFromValues(decl.d->values, font); break; + case TextDecoration: setTextDecorationFromValues(decl.d->values, font); break; + case Font: parseShorthandFontProperty(decl.d->values, font, fontSizeAdjustment); break; + case FontVariant: setFontVariantFromValue(val, font); break; + case TextTransform: setTextTransformFromValue(val, font); break; + default: continue; + } + hit = true; + } + + f = *font; + adjustment = *fontSizeAdjustment; + fontExtracted = hit ? 1 : 2; + return hit; +} + +bool ValueExtractor::extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg) +{ + bool hit = false; + for (int i = 0; i < declarations.count(); ++i) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case Color: *fg = decl.brushValue(pal); break; + case QtSelectionForeground: *sfg = decl.brushValue(pal); break; + case QtSelectionBackground: *sbg = decl.brushValue(pal); break; + case QtAlternateBackground: *abg = decl.brushValue(pal); break; + default: continue; + } + hit = true; + } + return hit; +} + +void ValueExtractor::extractFont() +{ + if (fontExtracted) + return; + int dummy = -255; + extractFont(&f, &dummy); +} + +bool ValueExtractor::extractImage(QIcon *icon, Qt::Alignment *a, QSize *size) +{ + bool hit = false; + for (int i = 0; i < declarations.count(); ++i) { + const Declaration &decl = declarations.at(i); + switch (decl.d->propertyId) { + case QtImage: + *icon = decl.iconValue(); + if (decl.d->values.count() > 0 && decl.d->values.at(0).type == Value::Uri) { + // try to pull just the size from the image... + QImageReader imageReader(decl.d->values.at(0).variant.toString()); + if ((*size = imageReader.size()).isNull()) { + // but we'll have to load the whole image if the + // format doesn't support just reading the size + *size = imageReader.read().size(); + } + } + break; + case QtImageAlignment: *a = decl.alignmentValue(); break; + default: continue; + } + hit = true; + } + return hit; +} + +/////////////////////////////////////////////////////////////////////////////// +// Declaration +QColor Declaration::colorValue(const QPalette &pal) const +{ + if (d->values.count() != 1) + return QColor(); + + if (d->parsed.isValid()) { + if (d->parsed.type() == QVariant::Color) + return qvariant_cast(d->parsed); + if (d->parsed.type() == QVariant::Int) + return pal.color((QPalette::ColorRole)(d->parsed.toInt())); + } + + ColorData color = parseColorValue(d->values.at(0)); + if(color.type == ColorData::Role) { + d->parsed = QVariant::fromValue(color.role); + return pal.color((QPalette::ColorRole)(color.role)); + } else { + d->parsed = QVariant::fromValue(color.color); + return color.color; + } +} + +QBrush Declaration::brushValue(const QPalette &pal) const +{ + if (d->values.count() != 1) + return QBrush(); + + if (d->parsed.isValid()) { + if (d->parsed.type() == QVariant::Brush) + return qvariant_cast(d->parsed); + if (d->parsed.type() == QVariant::Int) + return pal.color((QPalette::ColorRole)(d->parsed.toInt())); + } + + BrushData data = parseBrushValue(d->values.at(0), pal); + + if(data.type == BrushData::Role) { + d->parsed = QVariant::fromValue(data.role); + return pal.color((QPalette::ColorRole)(data.role)); + } else { + if (data.type != BrushData::DependsOnThePalette) + d->parsed = QVariant::fromValue(data.brush); + return data.brush; + } +} + +void Declaration::brushValues(QBrush *c, const QPalette &pal) const +{ + int needParse = 0x1f; // bits 0..3 say if we should parse the corresponding value. + // the bit 4 say we need to update d->parsed + int i = 0; + if (d->parsed.isValid()) { + needParse = 0; + QList v = d->parsed.toList(); + for (i = 0; i < qMin(v.count(), 4); i++) { + if (v.at(i).type() == QVariant::Brush) { + c[i] = qvariant_cast(v.at(i)); + } else if (v.at(i).type() == QVariant::Int) { + c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt())); + } else { + needParse |= (1< v; + for (i = 0; i < qMin(d->values.count(), 4); i++) { + if (!(needParse & (1<values.at(i), pal); + if(data.type == BrushData::Role) { + v += QVariant::fromValue(data.role); + c[i] = pal.color((QPalette::ColorRole)(data.role)); + } else { + if (data.type != BrushData::DependsOnThePalette) { + v += QVariant::fromValue(data.brush); + } else { + v += QVariant(); + } + c[i] = data.brush; + } + } + if (needParse & 0x10) + d->parsed = v; + } + if (i == 0) c[0] = c[1] = c[2] = c[3] = QBrush(); + else if (i == 1) c[3] = c[2] = c[1] = c[0]; + else if (i == 2) c[2] = c[0], c[3] = c[1]; + else if (i == 3) c[3] = c[1]; +} + +bool Declaration::realValue(qreal *real, const char *unit) const +{ + if (d->values.count() != 1) + return false; + const Value &v = d->values.at(0); + if (unit && v.type != Value::Length) + return false; + QString s = v.variant.toString(); + if (unit) { + if (!s.endsWith(QLatin1String(unit), Qt::CaseInsensitive)) + return false; + s.chop(qstrlen(unit)); + } + bool ok = false; + qreal val = s.toDouble(&ok); + if (ok) + *real = val; + return ok; +} + +static bool intValueHelper(const QCss::Value &v, int *i, const char *unit) +{ + if (unit && v.type != Value::Length) + return false; + QString s = v.variant.toString(); + if (unit) { + if (!s.endsWith(QLatin1String(unit), Qt::CaseInsensitive)) + return false; + s.chop(qstrlen(unit)); + } + bool ok = false; + int val = s.toInt(&ok); + if (ok) + *i = val; + return ok; +} + +bool Declaration::intValue(int *i, const char *unit) const +{ + if (d->values.count() != 1) + return false; + return intValueHelper(d->values.at(0), i, unit); +} + +QSize Declaration::sizeValue() const +{ + if (d->parsed.isValid()) + return qvariant_cast(d->parsed); + + int x[2] = { 0, 0 }; + if (d->values.count() > 0) + intValueHelper(d->values.at(0), &x[0], "px"); + if (d->values.count() > 1) + intValueHelper(d->values.at(1), &x[1], "px"); + else + x[1] = x[0]; + QSize size(x[0], x[1]); + d->parsed = QVariant::fromValue(size); + return size; +} + +QRect Declaration::rectValue() const +{ + if (d->values.count() != 1) + return QRect(); + + if (d->parsed.isValid()) + return qvariant_cast(d->parsed); + + const QCss::Value &v = d->values.at(0); + if (v.type != Value::Function) + return QRect(); + QStringList func = v.variant.toStringList(); + if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0) + return QRect(); + QStringList args = func[1].split(QLatin1Char(' '), QString::SkipEmptyParts); + if (args.count() != 4) + return QRect(); + QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()); + d->parsed = QVariant::fromValue(rect); + return rect; +} + +void Declaration::colorValues(QColor *c, const QPalette &pal) const +{ + int i; + if (d->parsed.isValid()) { + QList v = d->parsed.toList(); + for (i = 0; i < qMin(d->values.count(), 4); i++) { + if (v.at(i).type() == QVariant::Color) { + c[i] = qvariant_cast(v.at(i)); + } else { + c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt())); + } + } + } else { + QList v; + for (i = 0; i < qMin(d->values.count(), 4); i++) { + ColorData color = parseColorValue(d->values.at(i)); + if(color.type == ColorData::Role) { + v += QVariant::fromValue(color.role); + c[i] = pal.color((QPalette::ColorRole)(color.role)); + } else { + v += QVariant::fromValue(color.color); + c[i] = color.color; + } + } + d->parsed = v; + } + + if (i == 0) c[0] = c[1] = c[2] = c[3] = QColor(); + else if (i == 1) c[3] = c[2] = c[1] = c[0]; + else if (i == 2) c[2] = c[0], c[3] = c[1]; + else if (i == 3) c[3] = c[1]; +} + +BorderStyle Declaration::styleValue() const +{ + if (d->values.count() != 1) + return BorderStyle_None; + return parseStyleValue(d->values.at(0)); +} + +void Declaration::styleValues(BorderStyle *s) const +{ + int i; + for (i = 0; i < qMin(d->values.count(), 4); i++) + s[i] = parseStyleValue(d->values.at(i)); + if (i == 0) s[0] = s[1] = s[2] = s[3] = BorderStyle_None; + else if (i == 1) s[3] = s[2] = s[1] = s[0]; + else if (i == 2) s[2] = s[0], s[3] = s[1]; + else if (i == 3) s[3] = s[1]; +} + +Repeat Declaration::repeatValue() const +{ + if (d->parsed.isValid()) + return static_cast(d->parsed.toInt()); + if (d->values.count() != 1) + return Repeat_Unknown; + int v = findKnownValue(d->values.at(0).variant.toString(), + repeats, NumKnownRepeats); + d->parsed = v; + return static_cast(v); +} + +Origin Declaration::originValue() const +{ + if (d->parsed.isValid()) + return static_cast(d->parsed.toInt()); + if (d->values.count() != 1) + return Origin_Unknown; + int v = findKnownValue(d->values.at(0).variant.toString(), + origins, NumKnownOrigins); + d->parsed = v; + return static_cast(v); +} + +PositionMode Declaration::positionValue() const +{ + if (d->parsed.isValid()) + return static_cast(d->parsed.toInt()); + if (d->values.count() != 1) + return PositionMode_Unknown; + int v = findKnownValue(d->values.at(0).variant.toString(), + positions, NumKnownPositionModes); + d->parsed = v; + return static_cast(v); +} + +Attachment Declaration::attachmentValue() const +{ + if (d->parsed.isValid()) + return static_cast(d->parsed.toInt()); + if (d->values.count() != 1) + return Attachment_Unknown; + int v = findKnownValue(d->values.at(0).variant.toString(), + attachments, NumKnownAttachments); + d->parsed = v; + return static_cast(v); +} + +int Declaration::styleFeaturesValue() const +{ + Q_ASSERT(d->propertyId == QtStyleFeatures); + if (d->parsed.isValid()) + return d->parsed.toInt(); + int features = StyleFeature_None; + for (int i = 0; i < d->values.count(); i++) { + features |= static_cast(findKnownValue(d->values.value(i).variant.toString(), + styleFeatures, NumKnownStyleFeatures)); + } + d->parsed = features; + return features; +} + +QString Declaration::uriValue() const +{ + if (d->values.isEmpty() || d->values.at(0).type != Value::Uri) + return QString(); + return d->values.at(0).variant.toString(); +} + +Qt::Alignment Declaration::alignmentValue() const +{ + if (d->parsed.isValid()) + return Qt::Alignment(d->parsed.toInt()); + if (d->values.isEmpty() || d->values.count() > 2) + return Qt::AlignLeft | Qt::AlignTop; + + Qt::Alignment v = parseAlignment(d->values.constData(), d->values.count()); + d->parsed = int(v); + return v; +} + +void Declaration::borderImageValue(QString *image, int *cuts, + TileMode *h, TileMode *v) const +{ + *image = uriValue(); + for (int i = 0; i < 4; i++) + cuts[i] = -1; + *h = *v = TileMode_Stretch; + + if (d->values.count() < 2) + return; + + if (d->values.at(1).type == Value::Number) { // cuts! + int i; + for (i = 0; i < qMin(d->values.count()-1, 4); i++) { + const Value& v = d->values.at(i+1); + if (v.type != Value::Number) + break; + cuts[i] = v.variant.toString().toInt(); + } + if (i == 0) cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0; + else if (i == 1) cuts[3] = cuts[2] = cuts[1] = cuts[0]; + else if (i == 2) cuts[2] = cuts[0], cuts[3] = cuts[1]; + else if (i == 3) cuts[3] = cuts[1]; + } + + if (d->values.last().type == Value::Identifier) { + *v = static_cast(findKnownValue(d->values.last().variant.toString(), + tileModes, NumKnownTileModes)); + } + if (d->values[d->values.count() - 2].type == Value::Identifier) { + *h = static_cast + (findKnownValue(d->values[d->values.count()-2].variant.toString(), + tileModes, NumKnownTileModes)); + } else + *h = *v; +} + +QIcon Declaration::iconValue() const +{ + if (d->parsed.isValid()) + return qvariant_cast(d->parsed); + + QIcon icon; + for (int i = 0; i < d->values.count();) { + const Value &value = d->values.at(i++); + if (value.type != Value::Uri) + break; + QString uri = value.variant.toString(); + QIcon::Mode mode = QIcon::Normal; + QIcon::State state = QIcon::Off; + for (int j = 0; j < 2; j++) { + if (i != d->values.count() && d->values.at(i).type == Value::KnownIdentifier) { + switch (d->values.at(i).variant.toInt()) { + case Value_Disabled: mode = QIcon::Disabled; break; + case Value_Active: mode = QIcon::Active; break; + case Value_Selected: mode = QIcon::Selected; break; + case Value_Normal: mode = QIcon::Normal; break; + case Value_On: state = QIcon::On; break; + case Value_Off: state = QIcon::Off; break; + default: break; + } + ++i; + } else { + break; + } + } + + // QIcon is soo broken + if (icon.isNull()) + icon = QIcon(uri); + else + icon.addPixmap(uri, mode, state); + + if (i == d->values.count()) + break; + + if (d->values.at(i).type == Value::TermOperatorComma) + i++; + } + + d->parsed = QVariant::fromValue(icon); + return icon; +} + +/////////////////////////////////////////////////////////////////////////////// +// Selector +int Selector::specificity() const +{ + int val = 0; + for (int i = 0; i < basicSelectors.count(); ++i) { + const BasicSelector &sel = basicSelectors.at(i); + if (!sel.elementName.isEmpty()) + val += 1; + + val += (sel.pseudos.count() + sel.attributeSelectors.count()) * 0x10; + val += sel.ids.count() * 0x100; + } + return val; +} + +QString Selector::pseudoElement() const +{ + const BasicSelector& bs = basicSelectors.last(); + if (!bs.pseudos.isEmpty() && bs.pseudos.at(0).type == PseudoClass_Unknown) + return bs.pseudos.at(0).name; + return QString(); +} + +quint64 Selector::pseudoClass(quint64 *negated) const +{ + const BasicSelector& bs = basicSelectors.last(); + if (bs.pseudos.isEmpty()) + return PseudoClass_Unspecified; + quint64 pc = PseudoClass_Unknown; + for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.count(); i++) { + const Pseudo &pseudo = bs.pseudos.at(i); + if (pseudo.type == PseudoClass_Unknown) + return PseudoClass_Unknown; + if (!pseudo.negated) + pc |= pseudo.type; + else if (negated) + *negated |= pseudo.type; + } + return pc; +} + +/////////////////////////////////////////////////////////////////////////////// +// StyleSheet +void StyleSheet::buildIndexes(Qt::CaseSensitivity nameCaseSensitivity) +{ + QVector universals; + for (int i = 0; i < styleRules.count(); ++i) { + const StyleRule &rule = styleRules.at(i); + QVector universalsSelectors; + for (int j = 0; j < rule.selectors.count(); ++j) { + const Selector& selector = rule.selectors.at(j); + + if (selector.basicSelectors.isEmpty()) + continue; + + if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) { + if (selector.basicSelectors.count() != 1) + continue; + } else if (selector.basicSelectors.count() <= 1) { + continue; + } + + const BasicSelector &sel = selector.basicSelectors.at(selector.basicSelectors.count() - 1); + + if (!sel.ids.isEmpty()) { + StyleRule nr; + nr.selectors += selector; + nr.declarations = rule.declarations; + nr.order = i; + idIndex.insert(sel.ids.at(0), nr); + } else if (!sel.elementName.isEmpty()) { + StyleRule nr; + nr.selectors += selector; + nr.declarations = rule.declarations; + nr.order = i; + QString name = sel.elementName; + if (nameCaseSensitivity == Qt::CaseInsensitive) + name=name.toLower(); + nameIndex.insert(name, nr); + } else { + universalsSelectors += selector; + } + } + if (!universalsSelectors.isEmpty()) { + StyleRule nr; + nr.selectors = universalsSelectors; + nr.declarations = rule.declarations; + nr.order = i; + universals << nr; + } + } + styleRules = universals; +} + +/////////////////////////////////////////////////////////////////////////////// +// StyleSelector +StyleSelector::~StyleSelector() +{ +} + +bool StyleSelector::nodeNameEquals(NodePtr node, const QString& nodeName) const +{ + return nodeNames(node).contains(nodeName, nameCaseSensitivity); +} + +QStringList StyleSelector::nodeIds(NodePtr node) const +{ + return QStringList(attribute(node, QLatin1String("id"))); +} + +bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node) +{ + if (selector.basicSelectors.isEmpty()) + return false; + + if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) { + if (selector.basicSelectors.count() != 1) + return false; + return basicSelectorMatches(selector.basicSelectors.at(0), node); + } + if (selector.basicSelectors.count() <= 1) + return false; + + int i = selector.basicSelectors.count() - 1; + node = duplicateNode(node); + bool match = true; + + BasicSelector sel = selector.basicSelectors.at(i); + do { + match = basicSelectorMatches(sel, node); + if (!match) { + if (sel.relationToNext == BasicSelector::MatchNextSelectorIfParent + || i == selector.basicSelectors.count() - 1) // first element must always match! + break; + } + + if (match || sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor) + --i; + + if (i < 0) + break; + + sel = selector.basicSelectors.at(i); + if (sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor + || sel.relationToNext == BasicSelector::MatchNextSelectorIfParent) { + + NodePtr nextParent = parentNode(node); + freeNode(node); + node = nextParent; + } else if (sel.relationToNext == BasicSelector::MatchNextSelectorIfPreceeds) { + NodePtr previousSibling = previousSiblingNode(node); + freeNode(node); + node = previousSibling; + } + if (isNullNode(node)) { + match = false; + break; + } + } while (i >= 0 && (match || sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor)); + + freeNode(node); + + return match; +} + +bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node) +{ + if (!sel.attributeSelectors.isEmpty()) { + if (!hasAttributes(node)) + return false; + + for (int i = 0; i < sel.attributeSelectors.count(); ++i) { + const QCss::AttributeSelector &a = sel.attributeSelectors.at(i); + + const QString attrValue = attribute(node, a.name); + if (attrValue.isNull()) + return false; + + if (a.valueMatchCriterium == QCss::AttributeSelector::MatchContains) { + + QStringList lst = attrValue.split(QLatin1Char(' ')); + if (!lst.contains(a.value)) + return false; + } else if ( + (a.valueMatchCriterium == QCss::AttributeSelector::MatchEqual + && attrValue != a.value) + || + (a.valueMatchCriterium == QCss::AttributeSelector::MatchBeginsWith + && !attrValue.startsWith(a.value)) + ) + return false; + } + } + + if (!sel.elementName.isEmpty() + && !nodeNameEquals(node, sel.elementName)) + return false; + + if (!sel.ids.isEmpty() + && sel.ids != nodeIds(node)) + return false; + + return true; +} + +void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOrigin origin, + int depth, QMap *weightedRules) +{ + for (int j = 0; j < rule.selectors.count(); ++j) { + const Selector& selector = rule.selectors.at(j); + if (selectorMatches(selector, node)) { + uint weight = rule.order + + selector.specificity() *0x100 + + (uint(origin) + depth)*0x100000; + StyleRule newRule = rule; + if(rule.selectors.count() > 1) { + newRule.selectors.resize(1); + newRule.selectors[0] = selector; + } + //We might have rules with the same weight if they came from a rule with several selectors + weightedRules->insertMulti(weight, newRule); + } + } +} + +// Returns style rules that are in ascending order of specificity +// Each of the StyleRule returned will contain exactly one Selector +QVector StyleSelector::styleRulesForNode(NodePtr node) +{ + QVector rules; + if (styleSheets.isEmpty()) + return rules; + + QMap weightedRules; // (spec, rule) that will be sorted below + + //prune using indexed stylesheet + for (int sheetIdx = 0; sheetIdx < styleSheets.count(); ++sheetIdx) { + const StyleSheet &styleSheet = styleSheets.at(sheetIdx); + for (int i = 0; i < styleSheet.styleRules.count(); ++i) { + matchRule(node, styleSheet.styleRules.at(i), styleSheet.origin, styleSheet.depth, &weightedRules); + } + + if (!styleSheet.idIndex.isEmpty()) { + QStringList ids = nodeIds(node); + for (int i = 0; i < ids.count(); i++) { + const QString &key = ids.at(i); + QMultiHash::const_iterator it = styleSheet.idIndex.constFind(key); + while (it != styleSheet.idIndex.constEnd() && it.key() == key) { + matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules); + ++it; + } + } + } + if (!styleSheet.nameIndex.isEmpty()) { + QStringList names = nodeNames(node); + for (int i = 0; i < names.count(); i++) { + QString name = names.at(i); + if (nameCaseSensitivity == Qt::CaseInsensitive) + name = name.toLower(); + QMultiHash::const_iterator it = styleSheet.nameIndex.constFind(name); + while (it != styleSheet.nameIndex.constEnd() && it.key() == name) { + matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules); + ++it; + } + } + } + if (!medium.isEmpty()) { + for (int i = 0; i < styleSheet.mediaRules.count(); ++i) { + if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) { + for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.count(); ++j) { + matchRule(node, styleSheet.mediaRules.at(i).styleRules.at(j), styleSheet.origin, + styleSheet.depth, &weightedRules); + } + } + } + } + } + + rules.reserve(weightedRules.count()); + QMap::const_iterator it = weightedRules.constBegin(); + for ( ; it != weightedRules.constEnd() ; ++it) + rules += *it; + + return rules; +} + +// for qtexthtmlparser which requires just the declarations with Enabled state +// and without pseudo elements +QVector StyleSelector::declarationsForNode(NodePtr node, const char *extraPseudo) +{ + QVector decls; + QVector rules = styleRulesForNode(node); + for (int i = 0; i < rules.count(); i++) { + const Selector& selector = rules.at(i).selectors.at(0); + const QString pseudoElement = selector.pseudoElement(); + + if (extraPseudo && pseudoElement == QLatin1String(extraPseudo)) { + decls += rules.at(i).declarations; + continue; + } + + if (!pseudoElement.isEmpty()) // skip rules with pseudo elements + continue; + quint64 pseudoClass = selector.pseudoClass(); + if (pseudoClass == PseudoClass_Enabled || pseudoClass == PseudoClass_Unspecified) + decls += rules.at(i).declarations; + } + return decls; +} + +QString Symbol::lexem() const +{ + QString result; + if (len > 0) + result.reserve(len); + for (int i = 0; i < len; ++i) { + if (text.at(start + i) == QLatin1Char('\\') && i < len - 1) + ++i; + result += text.at(start + i); + } + return result; +} + +Parser::Parser(const QString &css, bool isFile) +{ + init(css, isFile); +} + +Parser::Parser() +{ + index = 0; + errorIndex = -1; + hasEscapeSequences = false; +} + +void Parser::init(const QString &css, bool isFile) +{ + QString styleSheet = css; + if (isFile) { + QFile file(css); + if (file.open(QFile::ReadOnly)) { + sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1Char('/'); + QTextStream stream(&file); + styleSheet = stream.readAll(); + } else { + qWarning() << "QCss::Parser - Failed to load file " << css; + styleSheet.clear(); + } + } else { + sourcePath.clear(); + } + + hasEscapeSequences = false; + symbols.resize(0); + symbols.reserve(8); + Scanner::scan(Scanner::preprocess(styleSheet, &hasEscapeSequences), &symbols); + index = 0; + errorIndex = -1; +} + +bool Parser::parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity) +{ + if (testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("charset"))) { + if (!next(STRING)) return false; + if (!next(SEMICOLON)) return false; + } + + while (test(S) || test(CDO) || test(CDC)) {} + + while (testImport()) { + ImportRule rule; + if (!parseImport(&rule)) return false; + styleSheet->importRules.append(rule); + while (test(S) || test(CDO) || test(CDC)) {} + } + + do { + if (testMedia()) { + MediaRule rule; + if (!parseMedia(&rule)) return false; + styleSheet->mediaRules.append(rule); + } else if (testPage()) { + PageRule rule; + if (!parsePage(&rule)) return false; + styleSheet->pageRules.append(rule); + } else if (testRuleset()) { + StyleRule rule; + if (!parseRuleset(&rule)) return false; + styleSheet->styleRules.append(rule); + } else if (test(ATKEYWORD_SYM)) { + if (!until(RBRACE)) return false; + } else if (hasNext()) { + return false; + } + while (test(S) || test(CDO) || test(CDC)) {} + } while (hasNext()); + styleSheet->buildIndexes(nameCaseSensitivity); + return true; +} + +Symbol Parser::errorSymbol() +{ + if (errorIndex == -1) return Symbol(); + return symbols.at(errorIndex); +} + +static inline void removeOptionalQuotes(QString *str) +{ + if (!str->startsWith(QLatin1Char('\'')) + && !str->startsWith(QLatin1Char('\"'))) + return; + str->remove(0, 1); + str->chop(1); +} + +bool Parser::parseImport(ImportRule *importRule) +{ + skipSpace(); + + if (test(STRING)) { + importRule->href = lexem(); + } else { + if (!testAndParseUri(&importRule->href)) return false; + } + removeOptionalQuotes(&importRule->href); + + skipSpace(); + + if (testMedium()) { + if (!parseMedium(&importRule->media)) return false; + + while (test(COMMA)) { + skipSpace(); + if (!parseNextMedium(&importRule->media)) return false; + } + } + + if (!next(SEMICOLON)) return false; + + skipSpace(); + return true; +} + +bool Parser::parseMedia(MediaRule *mediaRule) +{ + do { + skipSpace(); + if (!parseNextMedium(&mediaRule->media)) return false; + } while (test(COMMA)); + + if (!next(LBRACE)) return false; + skipSpace(); + + while (testRuleset()) { + StyleRule rule; + if (!parseRuleset(&rule)) return false; + mediaRule->styleRules.append(rule); + } + + if (!next(RBRACE)) return false; + skipSpace(); + return true; +} + +bool Parser::parseMedium(QStringList *media) +{ + media->append(lexem()); + skipSpace(); + return true; +} + +bool Parser::parsePage(PageRule *pageRule) +{ + skipSpace(); + + if (testPseudoPage()) + if (!parsePseudoPage(&pageRule->selector)) return false; + + skipSpace(); + if (!next(LBRACE)) return false; + + do { + skipSpace(); + Declaration decl; + if (!parseNextDeclaration(&decl)) return false; + if (!decl.isEmpty()) + pageRule->declarations.append(decl); + } while (test(SEMICOLON)); + + if (!next(RBRACE)) return false; + skipSpace(); + return true; +} + +bool Parser::parsePseudoPage(QString *selector) +{ + if (!next(IDENT)) return false; + *selector = lexem(); + return true; +} + +bool Parser::parseNextOperator(Value *value) +{ + if (!hasNext()) return true; + switch (next()) { + case SLASH: value->type = Value::TermOperatorSlash; skipSpace(); break; + case COMMA: value->type = Value::TermOperatorComma; skipSpace(); break; + default: prev(); break; + } + return true; +} + +bool Parser::parseCombinator(BasicSelector::Relation *relation) +{ + *relation = BasicSelector::NoRelation; + if (lookup() == S) { + *relation = BasicSelector::MatchNextSelectorIfAncestor; + skipSpace(); + } else { + prev(); + } + if (test(PLUS)) { + *relation = BasicSelector::MatchNextSelectorIfPreceeds; + } else if (test(GREATER)) { + *relation = BasicSelector::MatchNextSelectorIfParent; + } + skipSpace(); + return true; +} + +bool Parser::parseProperty(Declaration *decl) +{ + decl->d->property = lexem(); + decl->d->propertyId = static_cast(findKnownValue(decl->d->property, properties, NumProperties)); + skipSpace(); + return true; +} + +bool Parser::parseRuleset(StyleRule *styleRule) +{ + Selector sel; + if (!parseSelector(&sel)) return false; + styleRule->selectors.append(sel); + + while (test(COMMA)) { + skipSpace(); + Selector sel; + if (!parseNextSelector(&sel)) return false; + styleRule->selectors.append(sel); + } + + skipSpace(); + if (!next(LBRACE)) return false; + const int declarationStart = index; + + do { + skipSpace(); + Declaration decl; + const int rewind = index; + if (!parseNextDeclaration(&decl)) { + index = rewind; + const bool foundSemicolon = until(SEMICOLON); + const int semicolonIndex = index; + + index = declarationStart; + const bool foundRBrace = until(RBRACE); + + if (foundSemicolon && semicolonIndex < index) { + decl = Declaration(); + index = semicolonIndex - 1; + } else { + skipSpace(); + return foundRBrace; + } + } + if (!decl.isEmpty()) + styleRule->declarations.append(decl); + } while (test(SEMICOLON)); + + if (!next(RBRACE)) return false; + skipSpace(); + return true; +} + +bool Parser::parseSelector(Selector *sel) +{ + BasicSelector basicSel; + if (!parseSimpleSelector(&basicSel)) return false; + while (testCombinator()) { + if (!parseCombinator(&basicSel.relationToNext)) return false; + + if (!testSimpleSelector()) break; + sel->basicSelectors.append(basicSel); + + basicSel = BasicSelector(); + if (!parseSimpleSelector(&basicSel)) return false; + } + sel->basicSelectors.append(basicSel); + return true; +} + +bool Parser::parseSimpleSelector(BasicSelector *basicSel) +{ + int minCount = 0; + if (lookupElementName()) { + if (!parseElementName(&basicSel->elementName)) return false; + } else { + prev(); + minCount = 1; + } + bool onceMore; + int count = 0; + do { + onceMore = false; + if (test(HASH)) { + QString theid = lexem(); + // chop off leading # + theid.remove(0, 1); + basicSel->ids.append(theid); + onceMore = true; + } else if (testClass()) { + onceMore = true; + AttributeSelector a; + a.name = QLatin1String("class"); + a.valueMatchCriterium = AttributeSelector::MatchContains; + if (!parseClass(&a.value)) return false; + basicSel->attributeSelectors.append(a); + } else if (testAttrib()) { + onceMore = true; + AttributeSelector a; + if (!parseAttrib(&a)) return false; + basicSel->attributeSelectors.append(a); + } else if (testPseudo()) { + onceMore = true; + Pseudo ps; + if (!parsePseudo(&ps)) return false; + basicSel->pseudos.append(ps); + } + if (onceMore) ++count; + } while (onceMore); + return count >= minCount; +} + +bool Parser::parseClass(QString *name) +{ + if (!next(IDENT)) return false; + *name = lexem(); + return true; +} + +bool Parser::parseElementName(QString *name) +{ + switch (lookup()) { + case STAR: name->clear(); break; + case IDENT: *name = lexem(); break; + default: return false; + } + return true; +} + +bool Parser::parseAttrib(AttributeSelector *attr) +{ + skipSpace(); + if (!next(IDENT)) return false; + attr->name = lexem(); + skipSpace(); + + if (test(EQUAL)) { + attr->valueMatchCriterium = AttributeSelector::MatchEqual; + } else if (test(INCLUDES)) { + attr->valueMatchCriterium = AttributeSelector::MatchContains; + } else if (test(DASHMATCH)) { + attr->valueMatchCriterium = AttributeSelector::MatchBeginsWith; + } else { + return next(RBRACKET); + } + + skipSpace(); + + if (!test(IDENT) && !test(STRING)) return false; + attr->value = unquotedLexem(); + + skipSpace(); + return next(RBRACKET); +} + +bool Parser::parsePseudo(Pseudo *pseudo) +{ + (void)test(COLON); + pseudo->negated = test(EXCLAMATION_SYM); + if (test(IDENT)) { + pseudo->name = lexem(); + pseudo->type = static_cast(findKnownValue(pseudo->name, pseudos, NumPseudos)); + return true; + } + if (!next(FUNCTION)) return false; + pseudo->function = lexem(); + // chop off trailing parenthesis + pseudo->function.chop(1); + skipSpace(); + if (!test(IDENT)) return false; + pseudo->name = lexem(); + skipSpace(); + return next(RPAREN); +} + +bool Parser::parseNextDeclaration(Declaration *decl) +{ + if (!testProperty()) + return true; // not an error! + if (!parseProperty(decl)) return false; + if (!next(COLON)) return false; + skipSpace(); + if (!parseNextExpr(&decl->d->values)) return false; + if (testPrio()) + if (!parsePrio(decl)) return false; + return true; +} + +bool Parser::testPrio() +{ + const int rewind = index; + if (!test(EXCLAMATION_SYM)) return false; + skipSpace(); + if (!test(IDENT)) { + index = rewind; + return false; + } + if (lexem().compare(QLatin1String("important"), Qt::CaseInsensitive) != 0) { + index = rewind; + return false; + } + return true; +} + +bool Parser::parsePrio(Declaration *declaration) +{ + declaration->d->important = true; + skipSpace(); + return true; +} + +bool Parser::parseExpr(QVector *values) +{ + Value val; + if (!parseTerm(&val)) return false; + values->append(val); + bool onceMore; + do { + onceMore = false; + val = Value(); + if (!parseNextOperator(&val)) return false; + if (val.type != QCss::Value::Unknown) + values->append(val); + if (testTerm()) { + onceMore = true; + val = Value(); + if (!parseTerm(&val)) return false; + values->append(val); + } + } while (onceMore); + return true; +} + +bool Parser::testTerm() +{ + return test(PLUS) || test(MINUS) + || test(NUMBER) + || test(PERCENTAGE) + || test(LENGTH) + || test(STRING) + || test(IDENT) + || testHexColor() + || testFunction(); +} + +bool Parser::parseTerm(Value *value) +{ + QString str = lexem(); + bool haveUnary = false; + if (lookup() == PLUS || lookup() == MINUS) { + haveUnary = true; + if (!hasNext()) return false; + next(); + str += lexem(); + } + + value->variant = str; + value->type = QCss::Value::String; + switch (lookup()) { + case NUMBER: + value->type = Value::Number; + value->variant.convert(QVariant::Double); + break; + case PERCENTAGE: + value->type = Value::Percentage; + str.chop(1); // strip off % + value->variant = str; + break; + case LENGTH: + value->type = Value::Length; + break; + + case STRING: + if (haveUnary) return false; + value->type = Value::String; + str.chop(1); + str.remove(0, 1); + value->variant = str; + break; + case IDENT: { + if (haveUnary) return false; + value->type = Value::Identifier; + const int theid = findKnownValue(str, values, NumKnownValues); + if (theid != 0) { + value->type = Value::KnownIdentifier; + value->variant = theid; + } + break; + } + default: { + if (haveUnary) return false; + prev(); + if (testHexColor()) { + QColor col; + if (!parseHexColor(&col)) return false; + value->type = Value::Color; + value->variant = col; + } else if (testFunction()) { + QString name, args; + if (!parseFunction(&name, &args)) return false; + if (name == QLatin1String("url")) { + value->type = Value::Uri; + removeOptionalQuotes(&args); + if (QFileInfo(args).isRelative() && !sourcePath.isEmpty()) { + args.prepend(sourcePath); + } + value->variant = args; + } else { + value->type = Value::Function; + value->variant = QStringList() << name << args; + } + } else { + return recordError(); + } + return true; + } + } + skipSpace(); + return true; +} + +bool Parser::parseFunction(QString *name, QString *args) +{ + *name = lexem(); + name->chop(1); + skipSpace(); + const int start = index; + if (!until(RPAREN)) return false; + for (int i = start; i < index - 1; ++i) + args->append(symbols.at(i).lexem()); + /* + if (!nextExpr(&arguments)) return false; + if (!next(RPAREN)) return false; + */ + skipSpace(); + return true; +} + +bool Parser::parseHexColor(QColor *col) +{ + col->setNamedColor(lexem()); + if (!col->isValid()) { + qWarning("QCssParser::parseHexColor: Unknown color name '%s'",lexem().toLatin1().constData()); + return false; + } + skipSpace(); + return true; +} + +bool Parser::testAndParseUri(QString *uri) +{ + const int rewind = index; + if (!testFunction()) return false; + + QString name, args; + if (!parseFunction(&name, &args)) { + index = rewind; + return false; + } + if (name.toLower() != QLatin1String("url")) { + index = rewind; + return false; + } + *uri = args; + removeOptionalQuotes(uri); + return true; +} + +bool Parser::testSimpleSelector() +{ + return testElementName() + || (test(HASH)) + || testClass() + || testAttrib() + || testPseudo(); +} + +bool Parser::next(QCss::TokenType t) +{ + if (hasNext() && next() == t) + return true; + return recordError(); +} + +bool Parser::test(QCss::TokenType t) +{ + if (index >= symbols.count()) + return false; + if (symbols.at(index).token == t) { + ++index; + return true; + } + return false; +} + +QString Parser::unquotedLexem() const +{ + QString s = lexem(); + if (lookup() == STRING) { + s.chop(1); + s.remove(0, 1); + } + return s; +} + +QString Parser::lexemUntil(QCss::TokenType t) +{ + QString lexem; + while (hasNext() && next() != t) + lexem += symbol().lexem(); + return lexem; +} + +bool Parser::until(QCss::TokenType target, QCss::TokenType target2) +{ + int braceCount = 0; + int brackCount = 0; + int parenCount = 0; + if (index) { + switch(symbols.at(index-1).token) { + case LBRACE: ++braceCount; break; + case LBRACKET: ++brackCount; break; + case FUNCTION: + case LPAREN: ++parenCount; break; + default: ; + } + } + while (index < symbols.size()) { + QCss::TokenType t = symbols.at(index++).token; + switch (t) { + case LBRACE: ++braceCount; break; + case RBRACE: --braceCount; break; + case LBRACKET: ++brackCount; break; + case RBRACKET: --brackCount; break; + case FUNCTION: + case LPAREN: ++parenCount; break; + case RPAREN: --parenCount; break; + default: break; + } + if ((t == target || (target2 != NONE && t == target2)) + && braceCount <= 0 + && brackCount <= 0 + && parenCount <= 0) + return true; + + if (braceCount < 0 || brackCount < 0 || parenCount < 0) { + --index; + break; + } + } + return false; +} + +bool Parser::testTokenAndEndsWith(QCss::TokenType t, QLatin1String str) +{ + if (!test(t)) return false; + if (!lexem().endsWith(str, Qt::CaseInsensitive)) { + prev(); + return false; + } + return true; +} diff --git a/Source/Fractorium/qcssparser.h b/Source/Fractorium/qcssparser.h new file mode 100644 index 0000000..c78dfe5 --- /dev/null +++ b/Source/Fractorium/qcssparser.h @@ -0,0 +1,832 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#pragma once + +#include "FractoriumPch.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +class QIcon; + +namespace QCss +{ + +enum Property { + UnknownProperty, + BackgroundColor, + Color, + Float, + Font, + FontFamily, + FontSize, + FontStyle, + FontWeight, + Margin, + MarginBottom, + MarginLeft, + MarginRight, + MarginTop, + QtBlockIndent, + QtListIndent, + QtParagraphType, + QtTableType, + QtUserState, + TextDecoration, + TextIndent, + TextUnderlineStyle, + VerticalAlignment, + Whitespace, + QtSelectionForeground, + QtSelectionBackground, + Border, + BorderLeft, + BorderRight, + BorderTop, + BorderBottom, + Padding, + PaddingLeft, + PaddingRight, + PaddingTop, + PaddingBottom, + PageBreakBefore, + PageBreakAfter, + QtAlternateBackground, + BorderLeftStyle, + BorderRightStyle, + BorderTopStyle, + BorderBottomStyle, + BorderStyles, + BorderLeftColor, + BorderRightColor, + BorderTopColor, + BorderBottomColor, + BorderColor, + BorderLeftWidth, + BorderRightWidth, + BorderTopWidth, + BorderBottomWidth, + BorderWidth, + BorderTopLeftRadius, + BorderTopRightRadius, + BorderBottomLeftRadius, + BorderBottomRightRadius, + BorderRadius, + Background, + BackgroundOrigin, + BackgroundClip, + BackgroundRepeat, + BackgroundPosition, + BackgroundAttachment, + BackgroundImage, + BorderImage, + QtSpacing, + Width, + Height, + MinimumWidth, + MinimumHeight, + MaximumWidth, + MaximumHeight, + QtImage, + Left, + Right, + Top, + Bottom, + QtOrigin, + QtPosition, + Position, + QtStyleFeatures, + QtBackgroundRole, + ListStyleType, + ListStyle, + QtImageAlignment, + TextAlignment, + Outline, + OutlineOffset, + OutlineWidth, + OutlineColor, + OutlineStyle, + OutlineRadius, + OutlineTopLeftRadius, + OutlineTopRightRadius, + OutlineBottomLeftRadius, + OutlineBottomRightRadius, + FontVariant, + TextTransform, + QtListNumberPrefix, + QtListNumberSuffix, + LineHeight, + NumProperties +}; + +enum KnownValue { + UnknownValue, + Value_Normal, + Value_Pre, + Value_NoWrap, + Value_PreWrap, + Value_Small, + Value_Medium, + Value_Large, + Value_XLarge, + Value_XXLarge, + Value_Italic, + Value_Oblique, + Value_Bold, + Value_Underline, + Value_Overline, + Value_LineThrough, + Value_Sub, + Value_Super, + Value_Left, + Value_Right, + Value_Top, + Value_Bottom, + Value_Center, + Value_Native, + Value_Solid, + Value_Dotted, + Value_Dashed, + Value_DotDash, + Value_DotDotDash, + Value_Double, + Value_Groove, + Value_Ridge, + Value_Inset, + Value_Outset, + Value_Wave, + Value_Middle, + Value_Auto, + Value_Always, + Value_None, + Value_Transparent, + Value_Disc, + Value_Circle, + Value_Square, + Value_Decimal, + Value_LowerAlpha, + Value_UpperAlpha, + Value_LowerRoman, + Value_UpperRoman, + Value_SmallCaps, + Value_Uppercase, + Value_Lowercase, + + /* keep these in same order as QPalette::ColorRole */ + Value_FirstColorRole, + Value_WindowText = Value_FirstColorRole, + Value_Button, + Value_Light, + Value_Midlight, + Value_Dark, + Value_Mid, + Value_Text, + Value_BrightText, + Value_ButtonText, + Value_Base, + Value_Window, + Value_Shadow, + Value_Highlight, + Value_HighlightedText, + Value_Link, + Value_LinkVisited, + Value_AlternateBase, + Value_LastColorRole = Value_AlternateBase, + + Value_Disabled, + Value_Active, + Value_Selected, + Value_On, + Value_Off, + + NumKnownValues +}; + +enum BorderStyle { + BorderStyle_Unknown, + BorderStyle_None, + BorderStyle_Dotted, + BorderStyle_Dashed, + BorderStyle_Solid, + BorderStyle_Double, + BorderStyle_DotDash, + BorderStyle_DotDotDash, + BorderStyle_Groove, + BorderStyle_Ridge, + BorderStyle_Inset, + BorderStyle_Outset, + BorderStyle_Native, + NumKnownBorderStyles +}; + +enum Edge { + TopEdge, + RightEdge, + BottomEdge, + LeftEdge, + NumEdges +}; + +enum Corner { + TopLeftCorner, + TopRightCorner, + BottomLeftCorner, + BottomRightCorner +}; + +enum TileMode { + TileMode_Unknown, + TileMode_Round, + TileMode_Stretch, + TileMode_Repeat, + NumKnownTileModes +}; + +enum Repeat { + Repeat_Unknown, + Repeat_None, + Repeat_X, + Repeat_Y, + Repeat_XY, + NumKnownRepeats +}; + +enum Origin { + Origin_Unknown, + Origin_Padding, + Origin_Border, + Origin_Content, + Origin_Margin, + NumKnownOrigins +}; + +enum PositionMode { + PositionMode_Unknown, + PositionMode_Static, + PositionMode_Relative, + PositionMode_Absolute, + PositionMode_Fixed, + NumKnownPositionModes +}; + +enum Attachment { + Attachment_Unknown, + Attachment_Fixed, + Attachment_Scroll, + NumKnownAttachments +}; + +enum StyleFeature { + StyleFeature_None = 0, + StyleFeature_BackgroundColor = 1, + StyleFeature_BackgroundGradient = 2, + NumKnownStyleFeatures = 4 +}; + +static inline bool isHexDigit(const char c) +{ + return (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F') + ; +} + +struct Value +{ + enum Type { + Unknown, + Number, + Percentage, + Length, + String, + Identifier, + KnownIdentifier, + Uri, + Color, + Function, + TermOperatorSlash, + TermOperatorComma + }; + inline Value() : type(Unknown) { } + Type type; + QVariant variant; + QString toString() const; +}; + +struct ColorData { + ColorData() : role(QPalette::NoRole), type(Invalid) {} + ColorData(const QColor &col) : color(col), role(QPalette::NoRole), type(Color) {} + ColorData(QPalette::ColorRole r) : role(r), type(Role) {} + QColor color; + QPalette::ColorRole role; + enum { Invalid, Color, Role} type; +}; + +struct BrushData { + BrushData() : role(QPalette::NoRole), type(Invalid) {} + BrushData(const QBrush &br) : brush(br), role(QPalette::NoRole), type(Brush) {} + BrushData(QPalette::ColorRole r) : role(r), type(Role) {} + QBrush brush; + QPalette::ColorRole role; + enum { Invalid, Brush, Role, DependsOnThePalette } type; +}; + +struct BackgroundData { + BrushData brush; + QString image; + Repeat repeat; + Qt::Alignment alignment; +}; + +struct LengthData { + qreal number; + enum { NONE, Px, Ex, Em } unit; +}; + +struct BorderData { + LengthData width; + BorderStyle style; + BrushData color; +}; + + +// 1. StyleRule - x:hover, y:clicked > z:checked { prop1: value1; prop2: value2; } +// 2. QVector - x:hover, y:clicked z:checked +// 3. QVector - y:clicked z:checked +// 4. QVector - { prop1: value1; prop2: value2; } +// 5. Declaration - prop1: value1; + +struct Declaration +{ + struct DeclarationData : public QSharedData + { + inline DeclarationData() : propertyId(UnknownProperty), important(false) {} + QString property; + Property propertyId; + QVector values; + QVariant parsed; + bool important; + }; + QExplicitlySharedDataPointer d; + inline Declaration() : d(new DeclarationData()) {} + inline bool isEmpty() const { return d->property.isEmpty() && d->propertyId == UnknownProperty; } + + // helper functions + QColor colorValue(const QPalette & = QPalette()) const; + void colorValues(QColor *c, const QPalette & = QPalette()) const; + QBrush brushValue(const QPalette & = QPalette()) const; + void brushValues(QBrush *c, const QPalette & = QPalette()) const; + + BorderStyle styleValue() const; + void styleValues(BorderStyle *s) const; + + Origin originValue() const; + Repeat repeatValue() const; + Qt::Alignment alignmentValue() const; + PositionMode positionValue() const; + Attachment attachmentValue() const; + int styleFeaturesValue() const; + + bool intValue(int *i, const char *unit = 0) const; + bool realValue(qreal *r, const char *unit = 0) const; + + QSize sizeValue() const; + QRect rectValue() const; + QString uriValue() const; + QIcon iconValue() const; + + void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const; +}; + +const quint64 PseudoClass_Unknown = Q_UINT64_C(0x0000000000000000); +const quint64 PseudoClass_Enabled = Q_UINT64_C(0x0000000000000001); +const quint64 PseudoClass_Disabled = Q_UINT64_C(0x0000000000000002); +const quint64 PseudoClass_Pressed = Q_UINT64_C(0x0000000000000004); +const quint64 PseudoClass_Focus = Q_UINT64_C(0x0000000000000008); +const quint64 PseudoClass_Hover = Q_UINT64_C(0x0000000000000010); +const quint64 PseudoClass_Checked = Q_UINT64_C(0x0000000000000020); +const quint64 PseudoClass_Unchecked = Q_UINT64_C(0x0000000000000040); +const quint64 PseudoClass_Indeterminate = Q_UINT64_C(0x0000000000000080); +const quint64 PseudoClass_Unspecified = Q_UINT64_C(0x0000000000000100); +const quint64 PseudoClass_Selected = Q_UINT64_C(0x0000000000000200); +const quint64 PseudoClass_Horizontal = Q_UINT64_C(0x0000000000000400); +const quint64 PseudoClass_Vertical = Q_UINT64_C(0x0000000000000800); +const quint64 PseudoClass_Window = Q_UINT64_C(0x0000000000001000); +const quint64 PseudoClass_Children = Q_UINT64_C(0x0000000000002000); +const quint64 PseudoClass_Sibling = Q_UINT64_C(0x0000000000004000); +const quint64 PseudoClass_Default = Q_UINT64_C(0x0000000000008000); +const quint64 PseudoClass_First = Q_UINT64_C(0x0000000000010000); +const quint64 PseudoClass_Last = Q_UINT64_C(0x0000000000020000); +const quint64 PseudoClass_Middle = Q_UINT64_C(0x0000000000040000); +const quint64 PseudoClass_OnlyOne = Q_UINT64_C(0x0000000000080000); +const quint64 PseudoClass_PreviousSelected = Q_UINT64_C(0x0000000000100000); +const quint64 PseudoClass_NextSelected = Q_UINT64_C(0x0000000000200000); +const quint64 PseudoClass_Flat = Q_UINT64_C(0x0000000000400000); +const quint64 PseudoClass_Left = Q_UINT64_C(0x0000000000800000); +const quint64 PseudoClass_Right = Q_UINT64_C(0x0000000001000000); +const quint64 PseudoClass_Top = Q_UINT64_C(0x0000000002000000); +const quint64 PseudoClass_Bottom = Q_UINT64_C(0x0000000004000000); +const quint64 PseudoClass_Exclusive = Q_UINT64_C(0x0000000008000000); +const quint64 PseudoClass_NonExclusive = Q_UINT64_C(0x0000000010000000); +const quint64 PseudoClass_Frameless = Q_UINT64_C(0x0000000020000000); +const quint64 PseudoClass_ReadOnly = Q_UINT64_C(0x0000000040000000); +const quint64 PseudoClass_Active = Q_UINT64_C(0x0000000080000000); +const quint64 PseudoClass_Closable = Q_UINT64_C(0x0000000100000000); +const quint64 PseudoClass_Movable = Q_UINT64_C(0x0000000200000000); +const quint64 PseudoClass_Floatable = Q_UINT64_C(0x0000000400000000); +const quint64 PseudoClass_Minimized = Q_UINT64_C(0x0000000800000000); +const quint64 PseudoClass_Maximized = Q_UINT64_C(0x0000001000000000); +const quint64 PseudoClass_On = Q_UINT64_C(0x0000002000000000); +const quint64 PseudoClass_Off = Q_UINT64_C(0x0000004000000000); +const quint64 PseudoClass_Editable = Q_UINT64_C(0x0000008000000000); +const quint64 PseudoClass_Item = Q_UINT64_C(0x0000010000000000); +const quint64 PseudoClass_Closed = Q_UINT64_C(0x0000020000000000); +const quint64 PseudoClass_Open = Q_UINT64_C(0x0000040000000000); +const quint64 PseudoClass_EditFocus = Q_UINT64_C(0x0000080000000000); +const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000); +// The Any specifier is never generated, but can be used as a wildcard in searches. +const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff); +const int NumPseudos = 45; + +struct Pseudo +{ + Pseudo() : type(0), negated(false) { } + quint64 type; + QString name; + QString function; + bool negated; +}; + +struct AttributeSelector +{ + enum ValueMatchType { + NoMatch, + MatchEqual, + MatchContains, + MatchBeginsWith + }; + inline AttributeSelector() : valueMatchCriterium(NoMatch) {} + + QString name; + QString value; + ValueMatchType valueMatchCriterium; +}; + +struct BasicSelector +{ + inline BasicSelector() : relationToNext(NoRelation) {} + + enum Relation { + NoRelation, + MatchNextSelectorIfAncestor, + MatchNextSelectorIfParent, + MatchNextSelectorIfPreceeds + }; + + QString elementName; + + QStringList ids; + QVector pseudos; + QVector attributeSelectors; + + Relation relationToNext; +}; + +struct Selector +{ + QVector basicSelectors; + int specificity() const; + quint64 pseudoClass(quint64 *negated = 0) const; + QString pseudoElement() const; +}; + +struct StyleRule; +struct MediaRule; +struct PageRule; +struct ImportRule; + +struct ValueExtractor +{ + ValueExtractor(const QVector &declarations, const QPalette & = QPalette()); + + bool extractFont(QFont *font, int *fontSizeAdjustment); + bool extractBackground(QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *, + QCss::Origin *); + bool extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh); + bool extractPosition(int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *, + QCss::PositionMode *, Qt::Alignment *); + bool extractBox(int *margins, int *paddings, int *spacing = 0); + bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii); + bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets); + bool extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg); + int extractStyleFeatures(); + bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size); + + int lengthValue(const Declaration &decl); + +private: + void extractFont(); + void borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color); + LengthData lengthValue(const Value& v); + void lengthValues(const Declaration &decl, int *m); + QSize sizeValue(const Declaration &decl); + void sizeValues(const Declaration &decl, QSize *radii); + + QVector declarations; + QFont f; + int adjustment; + int fontExtracted; + QPalette pal; +}; + +struct StyleRule +{ + StyleRule() : order(0) { } + QVector selectors; + QVector declarations; + int order; +}; + +struct MediaRule +{ + QStringList media; + QVector styleRules; +}; + +struct PageRule +{ + QString selector; + QVector declarations; +}; + +struct ImportRule +{ + QString href; + QStringList media; +}; + +enum StyleSheetOrigin { + StyleSheetOrigin_Unspecified, + StyleSheetOrigin_UserAgent, + StyleSheetOrigin_User, + StyleSheetOrigin_Author, + StyleSheetOrigin_Inline +}; + +struct StyleSheet +{ + StyleSheet() : origin(StyleSheetOrigin_Unspecified), depth(0) { } + QVector styleRules; //only contains rules that are not indexed + QVector mediaRules; + QVector pageRules; + QVector importRules; + StyleSheetOrigin origin; + int depth; // applicable only for inline style sheets + QMultiHash nameIndex; + QMultiHash idIndex; + void buildIndexes(Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive); +}; + +class StyleSelector +{ +public: + StyleSelector() : nameCaseSensitivity(Qt::CaseSensitive) {} + virtual ~StyleSelector(); + + union NodePtr { + void *ptr; + int id; + }; + + QVector styleRulesForNode(NodePtr node); + QVector declarationsForNode(NodePtr node, const char *extraPseudo = 0); + + virtual bool nodeNameEquals(NodePtr node, const QString& nodeName) const; + virtual QString attribute(NodePtr node, const QString &name) const = 0; + virtual bool hasAttributes(NodePtr node) const = 0; + virtual QStringList nodeIds(NodePtr node) const; + virtual QStringList nodeNames(NodePtr node) const = 0; + virtual bool isNullNode(NodePtr node) const = 0; + virtual NodePtr parentNode(NodePtr node) const = 0; + virtual NodePtr previousSiblingNode(NodePtr node) const = 0; + virtual NodePtr duplicateNode(NodePtr node) const = 0; + virtual void freeNode(NodePtr node) const = 0; + + QVector styleSheets; + QString medium; + Qt::CaseSensitivity nameCaseSensitivity; +private: + void matchRule(NodePtr node, const StyleRule &rules, StyleSheetOrigin origin, + int depth, QMap *weightedRules); + bool selectorMatches(const Selector &rule, NodePtr node); + bool basicSelectorMatches(const BasicSelector &rule, NodePtr node); +}; + +enum TokenType { + NONE, + + S, + + CDO, + CDC, + INCLUDES, + DASHMATCH, + + LBRACE, + PLUS, + GREATER, + COMMA, + + STRING, + INVALID, + + IDENT, + + HASH, + + ATKEYWORD_SYM, + + EXCLAMATION_SYM, + + LENGTH, + + PERCENTAGE, + NUMBER, + + FUNCTION, + + COLON, + SEMICOLON, + RBRACE, + SLASH, + MINUS, + DOT, + STAR, + LBRACKET, + RBRACKET, + EQUAL, + LPAREN, + RPAREN, + OR +}; + +struct Symbol +{ + inline Symbol() : token(NONE), start(0), len(-1) {} + TokenType token; + QString text; + int start, len; + QString lexem() const; +}; + +class Scanner +{ +public: + static QString preprocess(const QString &input, bool *hasEscapeSequences = 0); + static void scan(const QString &preprocessedInput, QVector *symbols); +}; + +class Parser +{ +public: + Parser(); + explicit Parser(const QString &css, bool file = false); + + void init(const QString &css, bool file = false); + bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive); + Symbol errorSymbol(); + + bool parseImport(ImportRule *importRule); + bool parseMedia(MediaRule *mediaRule); + bool parseMedium(QStringList *media); + bool parsePage(PageRule *pageRule); + bool parsePseudoPage(QString *selector); + bool parseNextOperator(Value *value); + bool parseCombinator(BasicSelector::Relation *relation); + bool parseProperty(Declaration *decl); + bool parseRuleset(StyleRule *styleRule); + bool parseSelector(Selector *sel); + bool parseSimpleSelector(BasicSelector *basicSel); + bool parseClass(QString *name); + bool parseElementName(QString *name); + bool parseAttrib(AttributeSelector *attr); + bool parsePseudo(Pseudo *pseudo); + bool parseNextDeclaration(Declaration *declaration); + bool parsePrio(Declaration *declaration); + bool parseExpr(QVector *values); + bool parseTerm(Value *value); + bool parseFunction(QString *name, QString *args); + bool parseHexColor(QColor *col); + bool testAndParseUri(QString *uri); + + inline bool testRuleset() { return testSelector(); } + inline bool testSelector() { return testSimpleSelector(); } + inline bool parseNextSelector(Selector *sel) { if (!testSelector()) return recordError(); return parseSelector(sel); } + bool testSimpleSelector(); + inline bool parseNextSimpleSelector(BasicSelector *basicSel) { if (!testSimpleSelector()) return recordError(); return parseSimpleSelector(basicSel); } + inline bool testElementName() { return test(IDENT) || test(STAR); } + inline bool testClass() { return test(DOT); } + inline bool testAttrib() { return test(LBRACKET); } + inline bool testPseudo() { return test(COLON); } + inline bool testMedium() { return test(IDENT); } + inline bool parseNextMedium(QStringList *media) { if (!testMedium()) return recordError(); return parseMedium(media); } + inline bool testPseudoPage() { return test(COLON); } + inline bool testImport() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("import")); } + inline bool testMedia() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("media")); } + inline bool testPage() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("page")); } + inline bool testCombinator() { return test(PLUS) || test(GREATER) || test(S); } + inline bool testProperty() { return test(IDENT); } + bool testTerm(); + inline bool testExpr() { return testTerm(); } + inline bool parseNextExpr(QVector *values) { if (!testExpr()) return recordError(); return parseExpr(values); } + bool testPrio(); + inline bool testHexColor() { return test(HASH); } + inline bool testFunction() { return test(FUNCTION); } + inline bool parseNextFunction(QString *name, QString *args) { if (!testFunction()) return recordError(); return parseFunction(name, args); } + + inline bool lookupElementName() const { return lookup() == IDENT || lookup() == STAR; } + + inline void skipSpace() { while (test(S)) {}; } + + inline bool hasNext() const { return index < symbols.count(); } + inline TokenType next() { return symbols.at(index++).token; } + bool next(TokenType t); + bool test(TokenType t); + inline void prev() { index--; } + inline const Symbol &symbol() const { return symbols.at(index - 1); } + inline QString lexem() const { return symbol().lexem(); } + QString unquotedLexem() const; + QString lexemUntil(TokenType t); + bool until(TokenType target, TokenType target2 = NONE); + inline TokenType lookup() const { + return (index - 1) < symbols.count() ? symbols.at(index - 1).token : NONE; + } + + bool testTokenAndEndsWith(TokenType t, QLatin1String str); + + inline bool recordError() { errorIndex = index; return false; } + + QVector symbols; + int index; + int errorIndex; + bool hasEscapeSequences; + QString sourcePath; +}; + +} // namespace QCss + +Q_DECLARE_METATYPE( QCss::BackgroundData ) +Q_DECLARE_METATYPE( QCss::LengthData ) +Q_DECLARE_METATYPE( QCss::BorderData ) diff --git a/Source/Fractorium/qcssscanner.cpp b/Source/Fractorium/qcssscanner.cpp new file mode 100644 index 0000000..f4c3c57 --- /dev/null +++ b/Source/Fractorium/qcssscanner.cpp @@ -0,0 +1,1171 @@ +#include "FractoriumPch.h" +#include "qcssscanner.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +namespace QCss +{ +QCssScanner::QCssScanner(const QString &inp) +{ + input = inp; + pos = 0; + lexemStart = 0; + lexemLength = 0; +} + +int QCssScanner::handleCommentStart() +{ + while (pos < input.size() - 1) { + if (input.at(pos) == QLatin1Char('*') + && input.at(pos + 1) == QLatin1Char('/')) { + pos += 2; + break; + } + ++pos; + } + return QCss::TokenType::S; +} + +int QCssScanner::lex() +{ + lexemStart = pos; + lexemLength = 0; + int lastAcceptingPos = -1; + int token = -1; + QChar ch; + + // initial state + ch = next(); + if (ch.unicode() >= 9 && ch.unicode() <= 10) + goto state_1; + if (ch.unicode() >= 12 && ch.unicode() <= 13) + goto state_1; + if (ch.unicode() == 32) + goto state_1; + if (ch.unicode() == 33) { + token = QCss::EXCLAMATION_SYM; + goto found; + } + if (ch.unicode() == 34) + goto state_3; + if (ch.unicode() == 35) + goto state_4; + if (ch.unicode() == 39) + goto state_5; + if (ch.unicode() == 40) { + token = QCss::LPAREN; + goto found; + } + if (ch.unicode() == 41) { + token = QCss::RPAREN; + goto found; + } + if (ch.unicode() == 42) { + token = QCss::STAR; + goto found; + } + if (ch.unicode() == 43) + goto state_9; + if (ch.unicode() == 44) + goto state_10; + if (ch.unicode() == 45) + goto state_11; + if (ch.unicode() == 46) + goto state_12; + if (ch.unicode() == 47) + goto state_13; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_14; + if (ch.unicode() == 58) { + token = QCss::COLON; + goto found; + } + if (ch.unicode() == 59) { + token = QCss::SEMICOLON; + goto found; + } + if (ch.unicode() == 60) + goto state_17; + if (ch.unicode() == 61) { + token = QCss::EQUAL; + goto found; + } + if (ch.unicode() == 62) + goto state_19; + if (ch.unicode() == 64) + goto state_20; + if (ch.unicode() == 91) { + token = QCss::LBRACKET; + goto found; + } + if (ch.unicode() == 92) + goto state_22; + if (ch.unicode() == 93) { + token = QCss::RBRACKET; + goto found; + } + if (ch.unicode() == 95) + goto state_24; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_24; + if (ch.unicode() == 123) + goto state_25; + if (ch.unicode() == 124) + goto state_26; + if (ch.unicode() == 125) { + token = QCss::RBRACE; + goto found; + } + if (ch.unicode() == 126) + goto state_28; + goto out; +state_1: + lastAcceptingPos = pos; + token = QCss::S; + ch = next(); + if (ch.unicode() >= 9 && ch.unicode() <= 10) + goto state_29; + if (ch.unicode() >= 12 && ch.unicode() <= 13) + goto state_29; + if (ch.unicode() == 32) + goto state_29; + if (ch.unicode() == 43) + goto state_9; + if (ch.unicode() == 44) + goto state_10; + if (ch.unicode() == 62) + goto state_19; + if (ch.unicode() == 123) + goto state_25; + goto out; +state_3: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_4: + ch = next(); + if (ch.unicode() == 45) + goto state_33; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_33; + if (ch.unicode() == 92) + goto state_34; + if (ch.unicode() == 95) + goto state_33; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_33; + goto out; +state_5: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_9: + lastAcceptingPos = pos; + token = QCss::PLUS; + goto out; +state_10: + lastAcceptingPos = pos; + token = QCss::COMMA; + goto out; +state_11: + lastAcceptingPos = pos; + token = QCss::MINUS; + ch = next(); + if (ch.unicode() == 45) + goto state_38; + if (ch.unicode() == 92) + goto state_22; + if (ch.unicode() == 95) + goto state_24; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_24; + goto out; +state_12: + lastAcceptingPos = pos; + token = QCss::DOT; + ch = next(); + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_39; + goto out; +state_13: + lastAcceptingPos = pos; + token = QCss::SLASH; + ch = next(); + if (ch.unicode() == 42) { + token = handleCommentStart(); + goto found; + } + goto out; +state_14: + lastAcceptingPos = pos; + token = QCss::NUMBER; + ch = next(); + if (ch.unicode() == 37) + goto state_41; + if (ch.unicode() == 45) + goto state_42; + if (ch.unicode() == 46) + goto state_43; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_44; + if (ch.unicode() == 92) + goto state_45; + if (ch.unicode() == 95) + goto state_46; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_46; + goto out; +state_17: + ch = next(); + if (ch.unicode() == 33) + goto state_47; + goto out; +state_19: + lastAcceptingPos = pos; + token = QCss::GREATER; + goto out; +state_20: + ch = next(); + if (ch.unicode() == 45) + goto state_48; + if (ch.unicode() == 92) + goto state_49; + if (ch.unicode() == 95) + goto state_50; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_50; + goto out; +state_22: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_51; + if (ch.unicode() == 11) + goto state_51; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_51; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_51; + if (ch.unicode() >= 103) + goto state_51; + goto out; +state_24: + lastAcceptingPos = pos; + token = QCss::IDENT; + ch = next(); + if (ch.unicode() == 40) + goto state_52; + if (ch.unicode() == 45) + goto state_53; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_53; + if (ch.unicode() == 92) + goto state_54; + if (ch.unicode() == 95) + goto state_53; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_53; + goto out; +state_25: + lastAcceptingPos = pos; + token = QCss::LBRACE; + goto out; +state_26: + lastAcceptingPos = pos; + token = QCss::OR; + ch = next(); + if (ch.unicode() == 61) { + token = QCss::DASHMATCH; + goto found; + } + goto out; +state_28: + ch = next(); + if (ch.unicode() == 61) { + token = QCss::INCLUDES; + goto found; + } + goto out; +state_29: + lastAcceptingPos = pos; + token = QCss::S; + ch = next(); + if (ch.unicode() >= 9 && ch.unicode() <= 10) + goto state_29; + if (ch.unicode() >= 12 && ch.unicode() <= 13) + goto state_29; + if (ch.unicode() == 32) + goto state_29; + if (ch.unicode() == 43) + goto state_9; + if (ch.unicode() == 44) + goto state_10; + if (ch.unicode() == 62) + goto state_19; + if (ch.unicode() == 123) + goto state_25; + goto out; +state_30: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_31: + lastAcceptingPos = pos; + token = QCss::STRING; + goto out; +state_32: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_57; + if (ch.unicode() == 10) + goto state_58; + if (ch.unicode() == 11) + goto state_57; + if (ch.unicode() == 12) + goto state_59; + if (ch.unicode() == 13) + goto state_60; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_57; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_57; + if (ch.unicode() >= 103) + goto state_57; + goto out; +state_33: + lastAcceptingPos = pos; + token = QCss::HASH; + ch = next(); + if (ch.unicode() == 45) + goto state_61; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_61; + if (ch.unicode() == 92) + goto state_62; + if (ch.unicode() == 95) + goto state_61; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_61; + goto out; +state_34: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_63; + if (ch.unicode() == 11) + goto state_63; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_63; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_63; + if (ch.unicode() >= 103) + goto state_63; + goto out; +state_35: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_36: + lastAcceptingPos = pos; + token = QCss::STRING; + goto out; +state_37: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_64; + if (ch.unicode() == 10) + goto state_65; + if (ch.unicode() == 11) + goto state_64; + if (ch.unicode() == 12) + goto state_66; + if (ch.unicode() == 13) + goto state_67; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_64; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_64; + if (ch.unicode() >= 103) + goto state_64; + goto out; +state_38: + ch = next(); + if (ch.unicode() == 62) { + token = QCss::CDC; + goto found; + } + goto out; +state_39: + lastAcceptingPos = pos; + token = QCss::NUMBER; + ch = next(); + if (ch.unicode() == 37) + goto state_41; + if (ch.unicode() == 45) + goto state_42; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_69; + if (ch.unicode() == 92) + goto state_45; + if (ch.unicode() == 95) + goto state_46; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_46; + goto out; +state_41: + lastAcceptingPos = pos; + token = QCss::PERCENTAGE; + goto out; +state_42: + ch = next(); + if (ch.unicode() == 92) + goto state_45; + if (ch.unicode() == 95) + goto state_46; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_46; + goto out; +state_43: + ch = next(); + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_39; + goto out; +state_44: + lastAcceptingPos = pos; + token = QCss::NUMBER; + ch = next(); + if (ch.unicode() == 37) + goto state_41; + if (ch.unicode() == 45) + goto state_42; + if (ch.unicode() == 46) + goto state_43; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_44; + if (ch.unicode() == 92) + goto state_45; + if (ch.unicode() == 95) + goto state_46; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_46; + goto out; +state_45: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_70; + if (ch.unicode() == 11) + goto state_70; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_70; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_70; + if (ch.unicode() >= 103) + goto state_70; + goto out; +state_46: + lastAcceptingPos = pos; + token = QCss::LENGTH; + ch = next(); + if (ch.unicode() == 45) + goto state_71; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_71; + if (ch.unicode() == 92) + goto state_72; + if (ch.unicode() == 95) + goto state_71; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_71; + goto out; +state_47: + ch = next(); + if (ch.unicode() == 45) + goto state_73; + goto out; +state_48: + ch = next(); + if (ch.unicode() == 92) + goto state_49; + if (ch.unicode() == 95) + goto state_50; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_50; + goto out; +state_49: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_74; + if (ch.unicode() == 11) + goto state_74; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_74; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_74; + if (ch.unicode() >= 103) + goto state_74; + goto out; +state_50: + lastAcceptingPos = pos; + token = QCss::ATKEYWORD_SYM; + ch = next(); + if (ch.unicode() == 45) + goto state_75; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_75; + if (ch.unicode() == 92) + goto state_76; + if (ch.unicode() == 95) + goto state_75; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_75; + goto out; +state_51: + lastAcceptingPos = pos; + token = QCss::IDENT; + ch = next(); + if (ch.unicode() == 40) + goto state_52; + if (ch.unicode() == 45) + goto state_53; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_53; + if (ch.unicode() == 92) + goto state_54; + if (ch.unicode() == 95) + goto state_53; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_53; + goto out; +state_52: + lastAcceptingPos = pos; + token = QCss::FUNCTION; + goto out; +state_53: + lastAcceptingPos = pos; + token = QCss::IDENT; + ch = next(); + if (ch.unicode() == 40) + goto state_52; + if (ch.unicode() == 45) + goto state_53; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_53; + if (ch.unicode() == 92) + goto state_54; + if (ch.unicode() == 95) + goto state_53; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_53; + goto out; +state_54: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_77; + if (ch.unicode() == 11) + goto state_77; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_77; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_77; + if (ch.unicode() >= 103) + goto state_77; + goto out; +state_57: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_58: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_59: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_60: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 10) + goto state_78; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_61: + lastAcceptingPos = pos; + token = QCss::HASH; + ch = next(); + if (ch.unicode() == 45) + goto state_61; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_61; + if (ch.unicode() == 92) + goto state_62; + if (ch.unicode() == 95) + goto state_61; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_61; + goto out; +state_62: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_79; + if (ch.unicode() == 11) + goto state_79; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_79; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_79; + if (ch.unicode() >= 103) + goto state_79; + goto out; +state_63: + lastAcceptingPos = pos; + token = QCss::HASH; + ch = next(); + if (ch.unicode() == 45) + goto state_61; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_61; + if (ch.unicode() == 92) + goto state_62; + if (ch.unicode() == 95) + goto state_61; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_61; + goto out; +state_64: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_65: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_66: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_67: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 10) + goto state_80; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_69: + lastAcceptingPos = pos; + token = QCss::NUMBER; + ch = next(); + if (ch.unicode() == 37) + goto state_41; + if (ch.unicode() == 45) + goto state_42; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_69; + if (ch.unicode() == 92) + goto state_45; + if (ch.unicode() == 95) + goto state_46; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_46; + goto out; +state_70: + lastAcceptingPos = pos; + token = QCss::LENGTH; + ch = next(); + if (ch.unicode() == 45) + goto state_71; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_71; + if (ch.unicode() == 92) + goto state_72; + if (ch.unicode() == 95) + goto state_71; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_71; + goto out; +state_71: + lastAcceptingPos = pos; + token = QCss::LENGTH; + ch = next(); + if (ch.unicode() == 45) + goto state_71; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_71; + if (ch.unicode() == 92) + goto state_72; + if (ch.unicode() == 95) + goto state_71; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_71; + goto out; +state_72: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_81; + if (ch.unicode() == 11) + goto state_81; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_81; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_81; + if (ch.unicode() >= 103) + goto state_81; + goto out; +state_73: + ch = next(); + if (ch.unicode() == 45) { + token = QCss::CDO; + goto found; + } + goto out; +state_74: + lastAcceptingPos = pos; + token = QCss::ATKEYWORD_SYM; + ch = next(); + if (ch.unicode() == 45) + goto state_75; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_75; + if (ch.unicode() == 92) + goto state_76; + if (ch.unicode() == 95) + goto state_75; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_75; + goto out; +state_75: + lastAcceptingPos = pos; + token = QCss::ATKEYWORD_SYM; + ch = next(); + if (ch.unicode() == 45) + goto state_75; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_75; + if (ch.unicode() == 92) + goto state_76; + if (ch.unicode() == 95) + goto state_75; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_75; + goto out; +state_76: + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_83; + if (ch.unicode() == 11) + goto state_83; + if (ch.unicode() >= 14 && ch.unicode() <= 47) + goto state_83; + if (ch.unicode() >= 58 && ch.unicode() <= 96) + goto state_83; + if (ch.unicode() >= 103) + goto state_83; + goto out; +state_77: + lastAcceptingPos = pos; + token = QCss::IDENT; + ch = next(); + if (ch.unicode() == 40) + goto state_52; + if (ch.unicode() == 45) + goto state_53; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_53; + if (ch.unicode() == 92) + goto state_54; + if (ch.unicode() == 95) + goto state_53; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_53; + goto out; +state_78: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_30; + if (ch.unicode() == 11) + goto state_30; + if (ch.unicode() >= 14 && ch.unicode() <= 33) + goto state_30; + if (ch.unicode() == 34) + goto state_31; + if (ch.unicode() >= 35 && ch.unicode() <= 91) + goto state_30; + if (ch.unicode() == 92) + goto state_32; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_30; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_30; + if (ch.unicode() >= 123) + goto state_30; + goto out; +state_79: + lastAcceptingPos = pos; + token = QCss::HASH; + ch = next(); + if (ch.unicode() == 45) + goto state_61; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_61; + if (ch.unicode() == 92) + goto state_62; + if (ch.unicode() == 95) + goto state_61; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_61; + goto out; +state_80: + lastAcceptingPos = pos; + token = QCss::INVALID; + ch = next(); + if (ch.unicode() >= 1 && ch.unicode() <= 9) + goto state_35; + if (ch.unicode() == 11) + goto state_35; + if (ch.unicode() >= 14 && ch.unicode() <= 38) + goto state_35; + if (ch.unicode() == 39) + goto state_36; + if (ch.unicode() >= 40 && ch.unicode() <= 91) + goto state_35; + if (ch.unicode() == 92) + goto state_37; + if (ch.unicode() >= 93 && ch.unicode() <= 96) + goto state_35; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_35; + if (ch.unicode() >= 123) + goto state_35; + goto out; +state_81: + lastAcceptingPos = pos; + token = QCss::LENGTH; + ch = next(); + if (ch.unicode() == 45) + goto state_71; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_71; + if (ch.unicode() == 92) + goto state_72; + if (ch.unicode() == 95) + goto state_71; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_71; + goto out; +state_83: + lastAcceptingPos = pos; + token = QCss::ATKEYWORD_SYM; + ch = next(); + if (ch.unicode() == 45) + goto state_75; + if (ch.unicode() >= 48 && ch.unicode() <= 57) + goto state_75; + if (ch.unicode() == 92) + goto state_76; + if (ch.unicode() == 95) + goto state_75; + if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256) + goto state_75; + goto out; +found: + lastAcceptingPos = pos; + +out: + if (lastAcceptingPos != -1) { + lexemLength = lastAcceptingPos - lexemStart; + pos = lastAcceptingPos; + } + return token; +} + + +QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences) +{ + QString output = input; + + if (hasEscapeSequences) + *hasEscapeSequences = false; + + int i = 0; + while (i < output.size()) { + if (output.at(i) == QLatin1Char('\\')) { + + ++i; + // test for unicode hex escape + int hexCount = 0; + const int hexStart = i; + while (i < output.size() + && isHexDigit(output.at(i).toLatin1()) + && hexCount < 7) { + ++hexCount; + ++i; + } + if (hexCount == 0) { + if (hasEscapeSequences) + *hasEscapeSequences = true; + continue; + } + + hexCount = qMin(hexCount, 6); + bool ok = false; + ushort code = output.mid(hexStart, hexCount).toUShort(&ok, 16); + if (ok) { + output.replace(hexStart - 1, hexCount + 1, QChar(code)); + i = hexStart; + } + else { + i = hexStart; + } + } + else { + ++i; + } + } + return output; +} + +void Scanner::scan(const QString &preprocessedInput, QVector *symbols) +{ + QCssScanner scanner(preprocessedInput); + Symbol sym; + int tok = scanner.lex(); + while (tok != -1) { + sym.token = static_cast(tok); + sym.text = scanner.input; + sym.start = scanner.lexemStart; + sym.len = scanner.lexemLength; + symbols->append(sym); + tok = scanner.lex(); + } +} +} \ No newline at end of file diff --git a/Source/Fractorium/qcssscanner.h b/Source/Fractorium/qcssscanner.h new file mode 100644 index 0000000..5e2ac61 --- /dev/null +++ b/Source/Fractorium/qcssscanner.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#pragma once +#include "FractoriumPch.h" +#include "qcssparser.h" + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +namespace QCss +{ +// auto generated. DO NOT EDIT. +class QCssScanner +{ +public: + QCssScanner(const QString &inp); + + inline QChar next() { + return (pos < input.length()) ? input.at(pos++) : QChar(); + } + int handleCommentStart(); + int lex(); + + QString input; + int pos; + int lexemStart; + int lexemLength; +}; +} \ No newline at end of file diff --git a/Source/Fractorium/qfunctions.h b/Source/Fractorium/qfunctions.h new file mode 100644 index 0000000..9099dc9 --- /dev/null +++ b/Source/Fractorium/qfunctions.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qfunctions_*. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +#pragma once + +/// +/// The code in this file did not originate in Fractorium. +/// It was taken either in whole or in part from the source code +/// of Qt Creator. Their license applies. +/// + +#if defined(Q_OS_WINCE) +# include "QtCore/qfunctions_wince.h" +#elif defined(Q_OS_VXWORKS) +# include "QtCore/qfunctions_vxworks.h" +#elif defined(Q_OS_NACL) +# include "QtCore/qfunctions_nacl.h" +#elif defined(Q_OS_WINRT) +# include "QtCore/qfunctions_winrt.h" +#endif + +#ifdef Q_CC_RVCT +// rvct doesn't see static operators when using our qalgorithms +# define Q_STATIC_GLOBAL_OPERATOR inline +# define Q_STATIC_GLOBAL_INLINE_OPERATOR inline +#else +# define Q_STATIC_GLOBAL_OPERATOR static +# define Q_STATIC_GLOBAL_INLINE_OPERATOR static inline +#endif