diff --git a/.gitignore b/.gitignore index ab08eea..fc4073b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,9 @@ _ReSharper*/ *.sdf bin64/ Borderless/GeneratedFiles/ +*.opendb +*.ipch +*.generated.* +LLVM/ +Installer/custom/lib/ +Installer/custom/redist/* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7530c18 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,8 @@ +[submodule "serialization"] + path = serialization + url = https://github.com/Helios-vmg/cppserialization.git + branch = master +[submodule "luajit-2.0"] + path = luajit-2.0 + url = http://luajit.org/git/luajit-2.0.git + branch = master diff --git a/Borderless.pro b/Borderless.pro new file mode 100644 index 0000000..846a023 --- /dev/null +++ b/Borderless.pro @@ -0,0 +1,96 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2016-05-27T04:24:14 +# +#------------------------------------------------- + +# Find Boost library. + +# Try to use qmake variable's value. +_BOOST_ROOT = $$BOOST_ROOT +isEmpty(_BOOST_ROOT) { + message(\"Boost Library\" qmake value not detected...) + + # Try to use the system environment value. + _BOOST_ROOT = $$(BOOST_ROOT) +} + +isEmpty(_BOOST_ROOT) { + message(\"Boost Library\" environment variable not detected...) +} else { + message(\"Boost Library\" detected in BOOST_ROOT = \"$$_BOOST_ROOT\") + INCLUDEPATH += $$_BOOST_ROOT +} + +QT += core gui network widgets + +TARGET = Borderless +QMAKE_EXTRA_TARGETS += SerializationCode +TEMPLATE = app +QMAKE_CXXFLAGS += -std=c++11 +INCLUDEPATH += $$PWD/serialization/postsrc $$PWD/src + +SOURCES += src/ClangErrorMessage.cpp \ + src/DirectoryListing.cpp \ + src/ImageViewerApplication.cpp \ + src/ImageViewport.cpp \ + src/LoadedImage.cpp \ + src/main.cpp \ + src/MainWindow.cpp \ + src/MainWindowMovement.cpp \ + src/MainWindowSettings.cpp \ + src/MainWindowShortcuts.cpp \ + src/OptionsDialog.cpp \ + src/RotateDialog.cpp \ + src/Shortcuts.cpp \ + src/SingleInstanceApplication.cpp \ + src/ZoomModeDropDown.cpp \ + src/plugin-core/capi.cpp \ + src/plugin-core/ImageStore.cpp \ + src/plugin-core/PluginCoreState.cpp \ + src/serialization/Implementations.cpp \ + src/serialization/Inlining.cpp \ + src/serialization/MainSettings.cpp \ + src/serialization/ShortcutsSettings.cpp \ + src/serialization/WindowState.cpp + +HEADERS += src/ClangErrorMessage.hpp \ + src/DirectoryListing.h \ + src/Enums.h \ + src/GenericException.h \ + src/ImageViewerApplication.h \ + src/ImageViewport.h \ + src/LoadedImage.h \ + src/MainWindow.h \ + src/Misc.h \ + src/OptionsDialog.h \ + src/Quadrangular.h \ + src/resource.h \ + src/RotateDialog.h \ + src/ShortcutInfo.h \ + src/Shortcuts.h \ + src/SingleInstanceApplication.h \ + src/stdafx.h \ + src/StreamRedirector.h \ + src/ZoomModeDropDown.h \ + src/plugin-core/capi.h \ + src/plugin-core/ImageStore.h \ + src/plugin-core/PluginCoreState.h \ + src/plugin-core/Cpp/main.h \ + src/plugin-core/Lua/main.h + +FORMS += src/ClangErrorMessage.ui \ + src/InfoDialog.ui \ + src/MainWindow.ui \ + src/OptionsDialog.ui \ + src/RotateDialog.ui + +RESOURCES += src/resources.qrc + +LASC.target = $$PWD/LAS +#LASC.depends = FORCE +LASC.commands = chmod +x build_las.sh; ./build_las.sh + +SerializationCode.target = $$PWD/src/serialization/settings.generated.cpp +SerializationCode.depends = LASC $$PWD/src/serialization/settings.txt +SerializationCode.commands = chmod +x build_serialization.sh; ./build_serialization.sh diff --git a/Borderless.sln b/Borderless.sln index 7ba890a..17d940f 100644 --- a/Borderless.sln +++ b/Borderless.sln @@ -1,9 +1,33 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Borderless", "Borderless\Borderless.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" + ProjectSection(ProjectDependencies) = postProject + {27EE8D4B-AD52-4888-A793-21C589739AB7} = {27EE8D4B-AD52-4888-A793-21C589739AB7} + {886936B8-F314-4A7A-915A-C1138AF46B83} = {886936B8-F314-4A7A-915A-C1138AF46B83} + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF} = {80D643C5-A28D-441E-9404-8ADF6FAF7FBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LAS", "serialization\LAS\LAS.vcxproj", "{886936B8-F314-4A7A-915A-C1138AF46B83}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luajit", "luajit\luajit.vcxproj", "{068B1B0F-54A0-4818-926F-B35A72F71BDE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lua", "Lua", "{D79D789A-1522-4F52-B3BF-6EAFE1599CEC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LuaInterpreter", "LuaInterpreter\LuaInterpreter.vcxproj", "{27EE8D4B-AD52-4888-A793-21C589739AB7}" + ProjectSection(ProjectDependencies) = postProject + {068B1B0F-54A0-4818-926F-B35A72F71BDE} = {068B1B0F-54A0-4818-926F-B35A72F71BDE} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interpreters", "Interpreters", "{7AE2B9D8-5D7F-48C6-9A30-1A68BB46C581}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cpp", "Cpp", "{AD2FEDF6-80CE-4BFA-8FDB-89DCE507826A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppInterpreter", "CppInterpreter\CppInterpreter.vcxproj", "{80D643C5-A28D-441E-9404-8ADF6FAF7FBF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StdOutputRedirect", "StdOutputRedirect\StdOutputRedirect.vcxproj", "{FBC0C925-BDA0-496C-B897-DC7947573F8F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -27,8 +51,75 @@ Global {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Debug|Win32.ActiveCfg = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Debug|Win32.Build.0 = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Debug|x64.ActiveCfg = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Debug|x64.Build.0 = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.DebugRelease|Win32.ActiveCfg = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.DebugRelease|Win32.Build.0 = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.DebugRelease|x64.ActiveCfg = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.DebugRelease|x64.Build.0 = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Release|Win32.ActiveCfg = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Release|Win32.Build.0 = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Release|x64.ActiveCfg = Release|Win32 + {886936B8-F314-4A7A-915A-C1138AF46B83}.Release|x64.Build.0 = Release|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Debug|Win32.ActiveCfg = Debug|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Debug|Win32.Build.0 = Debug|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Debug|x64.ActiveCfg = Debug|x64 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Debug|x64.Build.0 = Debug|x64 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.DebugRelease|Win32.ActiveCfg = Release|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.DebugRelease|Win32.Build.0 = Release|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.DebugRelease|x64.ActiveCfg = Release|x64 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.DebugRelease|x64.Build.0 = Release|x64 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Release|Win32.ActiveCfg = Release|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Release|Win32.Build.0 = Release|Win32 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Release|x64.ActiveCfg = Release|x64 + {068B1B0F-54A0-4818-926F-B35A72F71BDE}.Release|x64.Build.0 = Release|x64 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Debug|Win32.ActiveCfg = Debug|Win32 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Debug|Win32.Build.0 = Debug|Win32 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Debug|x64.ActiveCfg = Debug|x64 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Debug|x64.Build.0 = Debug|x64 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.DebugRelease|Win32.ActiveCfg = Release|Win32 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.DebugRelease|Win32.Build.0 = Release|Win32 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.DebugRelease|x64.ActiveCfg = Release|x64 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.DebugRelease|x64.Build.0 = Release|x64 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Release|Win32.ActiveCfg = Release|Win32 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Release|Win32.Build.0 = Release|Win32 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Release|x64.ActiveCfg = Release|x64 + {27EE8D4B-AD52-4888-A793-21C589739AB7}.Release|x64.Build.0 = Release|x64 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Debug|Win32.ActiveCfg = Debug|Win32 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Debug|Win32.Build.0 = Debug|Win32 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Debug|x64.ActiveCfg = Debug|x64 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Debug|x64.Build.0 = Debug|x64 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.DebugRelease|Win32.ActiveCfg = Release|Win32 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.DebugRelease|Win32.Build.0 = Release|Win32 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.DebugRelease|x64.ActiveCfg = Release|x64 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.DebugRelease|x64.Build.0 = Release|x64 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Release|Win32.ActiveCfg = Release|Win32 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Release|Win32.Build.0 = Release|Win32 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Release|x64.ActiveCfg = Release|x64 + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF}.Release|x64.Build.0 = Release|x64 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Debug|Win32.ActiveCfg = Debug|Win32 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Debug|Win32.Build.0 = Debug|Win32 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Debug|x64.ActiveCfg = Debug|x64 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Debug|x64.Build.0 = Debug|x64 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.DebugRelease|Win32.ActiveCfg = Release|Win32 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.DebugRelease|Win32.Build.0 = Release|Win32 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.DebugRelease|x64.ActiveCfg = Release|x64 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.DebugRelease|x64.Build.0 = Release|x64 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Release|Win32.ActiveCfg = Release|Win32 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Release|Win32.Build.0 = Release|Win32 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Release|x64.ActiveCfg = Release|x64 + {FBC0C925-BDA0-496C-B897-DC7947573F8F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {068B1B0F-54A0-4818-926F-B35A72F71BDE} = {D79D789A-1522-4F52-B3BF-6EAFE1599CEC} + {D79D789A-1522-4F52-B3BF-6EAFE1599CEC} = {7AE2B9D8-5D7F-48C6-9A30-1A68BB46C581} + {27EE8D4B-AD52-4888-A793-21C589739AB7} = {D79D789A-1522-4F52-B3BF-6EAFE1599CEC} + {AD2FEDF6-80CE-4BFA-8FDB-89DCE507826A} = {7AE2B9D8-5D7F-48C6-9A30-1A68BB46C581} + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF} = {AD2FEDF6-80CE-4BFA-8FDB-89DCE507826A} + EndGlobalSection EndGlobal diff --git a/Borderless/Borderless.vcxproj b/Borderless/Borderless.vcxproj index adfc65f..63cc3bb 100644 --- a/Borderless/Borderless.vcxproj +++ b/Borderless/Borderless.vcxproj @@ -1,5 +1,5 @@  - + DebugRelease @@ -33,27 +33,27 @@ Application - v120 + v140 Application - v120 + v140 Application - v120 + v140 Application - v120 + v140 Application - v120 + v140 Application - v120 + v140 @@ -100,13 +100,14 @@ - UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + BUILDING_BORDERLESS;UNICODE;WIN32;WIN64;QT_DLL;BUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;$(SolutionDir)\serialization\postsrc;$(SolutionDir)\src;%(AdditionalIncludeDirectories) Disabled ProgramDatabase MultiThreadedDebugDLL true true + Async Windows @@ -118,30 +119,36 @@ - UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + BUILDING_BORDERLESS;UNICODE;WIN32;WIN64;QT_DLL;BUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;$(SolutionDir)\serialization\postsrc;$(SolutionDir)\src;%(AdditionalIncludeDirectories) Disabled ProgramDatabase MultiThreadedDebugDLL true true + Async + false Windows $(OutDir)\$(ProjectName).exe - $(QTDIR)\lib;%(AdditionalLibraryDirectories) + $(QTDIR)\lib;$(SolutionDir)lib64;%(AdditionalLibraryDirectories) true qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Networkd.lib;Qt5Widgetsd.lib;%(AdditionalDependencies) + + - UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + BUILDING_BORDERLESS;UNICODE;WIN32;WIN64;QT_DLL;BUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;$(SolutionDir)\serialization\postsrc;$(SolutionDir)\src;%(AdditionalIncludeDirectories) MultiThreadedDLL true true + true + Async Windows @@ -153,13 +160,14 @@ - UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + BUILDING_BORDERLESS;UNICODE;WIN32;WIN64;QT_DLL;BUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;$(SolutionDir)\serialization\postsrc;$(SolutionDir)\src;%(AdditionalIncludeDirectories) MultiThreadedDLL true true + Async Windows @@ -171,35 +179,38 @@ - UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + BUILDING_BORDERLESS;UNICODE;WIN32;WIN64;QT_DLL;BUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;$(SolutionDir)\serialization\postsrc;$(SolutionDir)\src;%(AdditionalIncludeDirectories) MultiThreadedDLL true true + true + Async Windows $(OutDir)\$(ProjectName).exe - $(QTDIR)\lib;%(AdditionalLibraryDirectories) + $(QTDIR)\lib;$(SolutionDir)lib64;%(AdditionalLibraryDirectories) false qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Network.lib;Qt5Widgets.lib;%(AdditionalDependencies) - UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + BUILDING_BORDERLESS;UNICODE;WIN32;WIN64;QT_DLL;BUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;$(SolutionDir)\serialization\postsrc;$(SolutionDir)\src;%(AdditionalIncludeDirectories) ProgramDatabase MultiThreadedDLL true true Disabled + Async Windows $(OutDir)\$(ProjectName).exe - $(QTDIR)\lib;%(AdditionalLibraryDirectories) + $(QTDIR)\lib;$(SolutionDir)lib64;%(AdditionalLibraryDirectories) true qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Network.lib;Qt5Widgets.lib;%(AdditionalDependencies) @@ -217,9 +228,40 @@ - + + + + + + + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + + + + true + true + true + true + true true @@ -256,6 +298,12 @@ true true + + true + true + true + true + true true @@ -306,6 +354,12 @@ + + true + true + true + true + true true @@ -348,25 +402,59 @@ + + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing ClangErrorMessage.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing ClangErrorMessage.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing ClangErrorMessage.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing ClangErrorMessage.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing ClangErrorMessage.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing ClangErrorMessage.hpp... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + + + + + + + + + Moc%27ing OptionsDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing OptionsDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing OptionsDialog.h... Moc%27ing OptionsDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing OptionsDialog.h... Moc%27ing OptionsDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) @@ -375,26 +463,25 @@ $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing RotateDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing RotateDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing RotateDialog.h... Moc%27ing RotateDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing RotateDialog.h... Moc%27ing RotateDialog.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) @@ -402,7 +489,6 @@ $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) - @@ -410,22 +496,22 @@ Moc%27ing SingleInstanceApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing SingleInstanceApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing SingleInstanceApplication.h... Moc%27ing SingleInstanceApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing SingleInstanceApplication.h... Moc%27ing SingleInstanceApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) @@ -436,22 +522,22 @@ Moc%27ing MainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing MainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing MainWindow.h... Moc%27ing MainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing MainWindow.h... Moc%27ing MainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) @@ -462,22 +548,22 @@ Moc%27ing ImageViewport.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing ImageViewport.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing ImageViewport.h... Moc%27ing ImageViewport.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing ImageViewport.h... Moc%27ing ImageViewport.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) @@ -488,22 +574,22 @@ Moc%27ing ImageViewerApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing ImageViewerApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing ImageViewerApplication.h... Moc%27ing ImageViewerApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" Moc%27ing ImageViewerApplication.h... Moc%27ing ImageViewerApplication.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DBUILDING_BORDERLESS -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DBUILDING_BORDERLESSBUILDING_BORDERLESSQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I$(SolutionDir)\serialization\postsrc" "-I.\..\src" $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) @@ -637,12 +723,134 @@ "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + + + false + false + false + false + false + false + cd "$(SolutionDir)src\serialization" +set file1=settings.txt +set file2=settings.generated.h +for /f %%i in ('dir /b /o:d %file1% %file2%') do set newest=%%i +if "%newest%"=="%file2%" goto end + +echo Processing %(Filename)%(Extension)... +"$(SolutionDir)bin\LAS.exe" "%(FullPath)" > nul + +:end + $(SolutionDir)src\serialization\settings.aux.generated.cpp;$(SolutionDir)src\serialization\settings.generated.cpp;$(SolutionDir)src\serialization\settings.generated.h + cd "$(SolutionDir)src\serialization" +set file1=settings.txt +set file2=settings.generated.h +for /f %%i in ('dir /b /o:d %file1% %file2%') do set newest=%%i +if "%newest%"=="%file2%" goto end + +echo Processing %(Filename)%(Extension)... +"$(SolutionDir)bin\LAS.exe" "%(FullPath)" > nul + +:end + $(SolutionDir)src\serialization\settings.aux.generated.cpp;$(SolutionDir)src\serialization\settings.generated.cpp;$(SolutionDir)src\serialization\settings.generated.h + cd "$(SolutionDir)src\serialization" +set file1=settings.txt +set file2=settings.generated.h +for /f %%i in ('dir /b /o:d %file1% %file2%') do set newest=%%i +if "%newest%"=="%file2%" goto end + +echo Processing %(Filename)%(Extension)... +"$(SolutionDir)bin\LAS.exe" "%(FullPath)" > nul + +:end + $(SolutionDir)src\serialization\settings.aux.generated.cpp;$(SolutionDir)src\serialization\settings.generated.cpp;$(SolutionDir)src\serialization\settings.generated.h + cd "$(SolutionDir)src\serialization" +set file1=settings.txt +set file2=settings.generated.h +for /f %%i in ('dir /b /o:d %file1% %file2%') do set newest=%%i +if "%newest%"=="%file2%" goto end + +echo Processing %(Filename)%(Extension)... +"$(SolutionDir)bin\LAS.exe" "%(FullPath)" > nul + +:end + $(SolutionDir)src\serialization\settings.aux.generated.cpp;$(SolutionDir)src\serialization\settings.generated.cpp;$(SolutionDir)src\serialization\settings.generated.h + cd "$(SolutionDir)src\serialization" +set file1=settings.txt +set file2=settings.generated.h +for /f %%i in ('dir /b /o:d %file1% %file2%') do set newest=%%i +if "%newest%"=="%file2%" goto end + +echo Processing %(Filename)%(Extension)... +"$(SolutionDir)bin\LAS.exe" "%(FullPath)" > nul + +:end + $(SolutionDir)src\serialization\settings.aux.generated.cpp;$(SolutionDir)src\serialization\settings.generated.cpp;$(SolutionDir)src\serialization\settings.generated.h + cd "$(SolutionDir)src\serialization" +set file1=settings.txt +set file2=settings.generated.h +for /f %%i in ('dir /b /o:d %file1% %file2%') do set newest=%%i +if "%newest%"=="%file2%" goto end + +echo Processing %(Filename)%(Extension)... +"$(SolutionDir)bin\LAS.exe" "%(FullPath)" > nul + +:end + $(SolutionDir)src\serialization\settings.aux.generated.cpp;$(SolutionDir)src\serialization\settings.generated.cpp;$(SolutionDir)src\serialization\settings.generated.h + false + false + false + false + false + false + false + false + false + false + false + false + Processing %(Filename)%(Extension) serializer definition... + Processing %(Filename)%(Extension) serializer definition... + Processing %(Filename)%(Extension) serializer definition... + Processing %(Filename)%(Extension) serializer definition... + Processing %(Filename)%(Extension) serializer definition... + Processing %(Filename)%(Extension) serializer definition... + + + + + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o "$(ProjectDir)\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o "$(ProjectDir)\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o "$(ProjectDir)\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o "$(ProjectDir)\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o "$(ProjectDir)\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + $(QTDIR)\bin\uic.exe;%(AdditionalInputs) + Uic%27ing %(Identity)... + .\GeneratedFiles\ui_%(Filename).h;%(Outputs) + "$(QTDIR)\bin\uic.exe" -o "$(ProjectDir)\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" + + - + \ No newline at end of file diff --git a/Borderless/Borderless.vcxproj.filters b/Borderless/Borderless.vcxproj.filters index 3c06248..6dca966 100644 --- a/Borderless/Borderless.vcxproj.filters +++ b/Borderless/Borderless.vcxproj.filters @@ -38,6 +38,9 @@ cpp;moc False + + {fff07627-1e93-4938-8955-0c7dff0697fd} + @@ -79,9 +82,6 @@ Source Files - - Source Files - Source Files @@ -142,6 +142,51 @@ Generated Files\Release + + Generated Files\DebugRelease + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -174,6 +219,11 @@ Form Files + + + + Form Files + @@ -200,13 +250,31 @@ Header Files - + + Header Files + + + Generated Files + + + Header Files + + Header Files - + Header Files - + + Header Files + + + Header Files + + + Header Files + + Header Files diff --git a/COPYING.txt b/COPYING.txt index f48bccd..3324486 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -1,4 +1,4 @@ -Copyright (c) 2015, Helios +Copyright (c) 2015-2016, Helios All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/CppInterpreter/CppInterpreter.vcxproj b/CppInterpreter/CppInterpreter.vcxproj new file mode 100644 index 0000000..cea1e93 --- /dev/null +++ b/CppInterpreter/CppInterpreter.vcxproj @@ -0,0 +1,182 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + Create + Create + Create + Create + + + stdafx.h + stdafx.h + stdafx.h + stdafx.h + + + + + + + + + + {80D643C5-A28D-441E-9404-8ADF6FAF7FBF} + Win32Proj + CppInterpreter + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + $(SolutionDir)bin64\ + + + false + + + false + $(SolutionDir)bin64\ + + + + Use + Level3 + Disabled + WIN32;BUILDING_CPPINTERPRETER;WIN32;_DEBUG;_WINDOWS;_USRDLL;CPPINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)\LLVM\include\;%(AdditionalIncludeDirectories) + Async + + + Windows + true + clangAnalysis.lib;clangAST.lib;clangBasic.lib;clangCodeGen.lib;clangDriver.lib;clangEdit.lib;clangFrontend.lib;clangLex.lib;clangParse.lib;clangSema.lib;clangSerialization.lib;LLVMAnalysis.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMExecutionEngine.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCJIT.lib;LLVMMCParser.lib;LLVMObjCARCOpts.lib;LLVMObject.lib;LLVMOption.lib;LLVMProfileData.lib;LLVMRuntimeDyld.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSupport.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + WIN32;BUILDING_CPPINTERPRETER;_DEBUG;_WINDOWS;_USRDLL;CPPINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)\LLVM\include\;%(AdditionalIncludeDirectories) + Async + + + Windows + true + $(SolutionDir)\LLVM\lib64\Debug\ + clangAnalysis.lib;clangAST.lib;clangBasic.lib;clangCodeGen.lib;clangDriver.lib;clangEdit.lib;clangFrontend.lib;clangLex.lib;clangParse.lib;clangSema.lib;clangSerialization.lib;LLVMAnalysis.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMExecutionEngine.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCJIT.lib;LLVMMCParser.lib;LLVMObjCARCOpts.lib;LLVMObject.lib;LLVMOption.lib;LLVMProfileData.lib;LLVMRuntimeDyld.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSupport.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;BUILDING_CPPINTERPRETER;WIN32;NDEBUG;_WINDOWS;_USRDLL;CPPINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)\LLVM\include\;%(AdditionalIncludeDirectories) + Async + + + Windows + true + true + true + clangAnalysis.lib;clangAST.lib;clangBasic.lib;clangCodeGen.lib;clangDriver.lib;clangEdit.lib;clangFrontend.lib;clangLex.lib;clangParse.lib;clangSema.lib;clangSerialization.lib;LLVMAnalysis.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMExecutionEngine.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCJIT.lib;LLVMMCParser.lib;LLVMObjCARCOpts.lib;LLVMObject.lib;LLVMOption.lib;LLVMProfileData.lib;LLVMRuntimeDyld.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSupport.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;BUILDING_CPPINTERPRETER;NDEBUG;_WINDOWS;_USRDLL;CPPINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)\LLVM\include\;%(AdditionalIncludeDirectories) + Async + MultiThreadedDLL + + + Windows + true + true + true + $(SolutionDir)\LLVM\lib64\Release\ + clangAnalysis.lib;clangAST.lib;clangBasic.lib;clangCodeGen.lib;clangDriver.lib;clangEdit.lib;clangFrontend.lib;clangLex.lib;clangParse.lib;clangSema.lib;clangSerialization.lib;LLVMAnalysis.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMExecutionEngine.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCJIT.lib;LLVMMCParser.lib;LLVMObjCARCOpts.lib;LLVMObject.lib;LLVMOption.lib;LLVMProfileData.lib;LLVMRuntimeDyld.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSupport.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/CppInterpreter/CppInterpreter.vcxproj.filters b/CppInterpreter/CppInterpreter.vcxproj.filters new file mode 100644 index 0000000..cc47b22 --- /dev/null +++ b/CppInterpreter/CppInterpreter.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/Installer/custom/README.txt b/Installer/custom/README.txt new file mode 100644 index 0000000..96a4824 --- /dev/null +++ b/Installer/custom/README.txt @@ -0,0 +1,15 @@ +Place in .\lib\clang\[clang_version]\include the MSVC headers. +Note: At the time of writing, clang_version = 3.8.0 + +Place in .\bin the Qt DLLs. Currently, these are used: +icudt54.dll +icuin54.dll +icuuc54.dll +Qt5Core.dll +Qt5Gui.dll +Qt5Network.dll +Qt5Svg.dll +Qt5Widgets.dll +Also, place the plugins directory. Note that, for release builds, files matching +the following patterns do not need to be distributed: *d.dll *d.pdb +The cleaned plugins directory is slightly under 10 MiB. diff --git a/Installer/custom/icons/icon.ico b/Installer/custom/icons/icon.ico new file mode 100644 index 0000000..a682482 Binary files /dev/null and b/Installer/custom/icons/icon.ico differ diff --git a/Installer/custom/icons/icon16.png b/Installer/custom/icons/icon16.png new file mode 100644 index 0000000..c025dca Binary files /dev/null and b/Installer/custom/icons/icon16.png differ diff --git a/Installer/custom/icons/icon256.png b/Installer/custom/icons/icon256.png new file mode 100644 index 0000000..aae37dd Binary files /dev/null and b/Installer/custom/icons/icon256.png differ diff --git a/Installer/custom/icons/icon32.png b/Installer/custom/icons/icon32.png new file mode 100644 index 0000000..cadc797 Binary files /dev/null and b/Installer/custom/icons/icon32.png differ diff --git a/Installer/custom/icons/icon48.png b/Installer/custom/icons/icon48.png new file mode 100644 index 0000000..88717e9 Binary files /dev/null and b/Installer/custom/icons/icon48.png differ diff --git a/Installer/custom/qt.conf b/Installer/custom/qt.conf new file mode 100644 index 0000000..4c9994f --- /dev/null +++ b/Installer/custom/qt.conf @@ -0,0 +1,2 @@ +[Paths] +Prefix=. diff --git a/Installer/generate_registry.py b/Installer/generate_registry.py new file mode 100644 index 0000000..07dd501 --- /dev/null +++ b/Installer/generate_registry.py @@ -0,0 +1,28 @@ +s = 'Root: HKCR; Subkey: "{#MyAppExeName}.[EXTENSION]"; Flags: uninsdeletekey\n' + \ + 'Root: HKCR; Subkey: "{#MyAppExeName}.[EXTENSION]"; ValueType: string; ValueName: ""; ValueData: "[NAME] file"\n' + \ + 'Root: HKCR; Subkey: "{#MyAppExeName}.[EXTENSION]\\DefaultIcon"; Flags: uninsdeletekey\n' + \ + 'Root: HKCR; Subkey: "{#MyAppExeName}.[EXTENSION]\\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\\bin\\{#MyAppExeName}"\n' + \ + 'Root: HKCR; Subkey: "{#MyAppExeName}.[EXTENSION]\\shell\\open\\command"; Flags: uninsdeletekey\n' + \ + 'Root: HKCR; Subkey: "{#MyAppExeName}.[EXTENSION]\\shell\\open\\command"; ValueType: string; ValueName: ""; ValueData: """{app}\\bin\\{#MyAppExeName}"" ""%1"""\n' + \ + 'Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".[EXTENSION]" ; ValueData: ""\n' + \ + 'Root: HKCR; Subkey: ".[EXTENSION]\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.[EXTENSION]" ; ValueData: ""\n' + +array = [ + 'bmp', + 'jpg', + 'jpeg', + 'png', + 'gif', + 'svg', + 'webp', + 'ico', + 'tga', + 'tif', + 'tiff', + 'jp2' +] + +for i in array: + ext = i + name = i.upper() + print(s.replace('[EXTENSION]', ext).replace('[NAME]', name)) diff --git a/Installer/registry.iss b/Installer/registry.iss new file mode 100644 index 0000000..38d0eda --- /dev/null +++ b/Installer/registry.iss @@ -0,0 +1,108 @@ +Root: HKCR; Subkey: "{#MyAppExeName}.bmp"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.bmp"; ValueType: string; ValueName: ""; ValueData: "BMP file" +Root: HKCR; Subkey: "{#MyAppExeName}.bmp\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.bmp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.bmp\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.bmp\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".bmp" ; ValueData: "" +Root: HKCR; Subkey: ".bmp\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.bmp" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.jpg"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jpg"; ValueType: string; ValueName: ""; ValueData: "JPG file" +Root: HKCR; Subkey: "{#MyAppExeName}.jpg\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jpg\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.jpg\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jpg\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".jpg" ; ValueData: "" +Root: HKCR; Subkey: ".jpg\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.jpg" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.jpeg"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jpeg"; ValueType: string; ValueName: ""; ValueData: "JPEG file" +Root: HKCR; Subkey: "{#MyAppExeName}.jpeg\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jpeg\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.jpeg\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jpeg\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".jpeg" ; ValueData: "" +Root: HKCR; Subkey: ".jpeg\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.jpeg" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.png"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.png"; ValueType: string; ValueName: ""; ValueData: "PNG file" +Root: HKCR; Subkey: "{#MyAppExeName}.png\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.png\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.png\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.png\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".png" ; ValueData: "" +Root: HKCR; Subkey: ".png\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.png" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.gif"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.gif"; ValueType: string; ValueName: ""; ValueData: "GIF file" +Root: HKCR; Subkey: "{#MyAppExeName}.gif\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.gif\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.gif\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.gif\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".gif" ; ValueData: "" +Root: HKCR; Subkey: ".gif\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.gif" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.svg"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.svg"; ValueType: string; ValueName: ""; ValueData: "SVG file" +Root: HKCR; Subkey: "{#MyAppExeName}.svg\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.svg\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.svg\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.svg\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".svg" ; ValueData: "" +Root: HKCR; Subkey: ".svg\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.svg" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.webp"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.webp"; ValueType: string; ValueName: ""; ValueData: "WEBP file" +Root: HKCR; Subkey: "{#MyAppExeName}.webp\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.webp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.webp\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.webp\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".webp" ; ValueData: "" +Root: HKCR; Subkey: ".webp\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.webp" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.ico"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.ico"; ValueType: string; ValueName: ""; ValueData: "ICO file" +Root: HKCR; Subkey: "{#MyAppExeName}.ico\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.ico\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.ico\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.ico\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".ico" ; ValueData: "" +Root: HKCR; Subkey: ".ico\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.ico" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.tga"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tga"; ValueType: string; ValueName: ""; ValueData: "TGA file" +Root: HKCR; Subkey: "{#MyAppExeName}.tga\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tga\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.tga\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tga\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".tga" ; ValueData: "" +Root: HKCR; Subkey: ".tga\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.tga" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.tif"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tif"; ValueType: string; ValueName: ""; ValueData: "TIF file" +Root: HKCR; Subkey: "{#MyAppExeName}.tif\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tif\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.tif\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tif\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".tif" ; ValueData: "" +Root: HKCR; Subkey: ".tif\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.tif" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.tiff"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tiff"; ValueType: string; ValueName: ""; ValueData: "TIFF file" +Root: HKCR; Subkey: "{#MyAppExeName}.tiff\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tiff\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.tiff\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.tiff\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".tiff" ; ValueData: "" +Root: HKCR; Subkey: ".tiff\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.tiff" ; ValueData: "" + +Root: HKCR; Subkey: "{#MyAppExeName}.jp2"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jp2"; ValueType: string; ValueName: ""; ValueData: "JP2 file" +Root: HKCR; Subkey: "{#MyAppExeName}.jp2\DefaultIcon"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jp2\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\{#MyAppExeName}" +Root: HKCR; Subkey: "{#MyAppExeName}.jp2\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "{#MyAppExeName}.jp2\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".jp2" ; ValueData: "" +Root: HKCR; Subkey: ".jp2\OpenWithProgIds"; ValueType: string; ValueName: "{#MyAppExeName}.jp2" ; ValueData: "" + diff --git a/Installer/setup.iss b/Installer/setup.iss new file mode 100644 index 0000000..6c03c51 --- /dev/null +++ b/Installer/setup.iss @@ -0,0 +1,76 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "BorderlessImageViewer" +#define MyAppVersion "0.2" +#define MyAppURL "https://github.com/Helios-vmg/Borderless" +#define MyAppExeName "Borderless.exe" +#define SourceBasePath ".." + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{F86CCAD1-7B42-4869-8A0B-3B32A0717A0B} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DisableProgramGroupPage=yes +LicenseFile={#SourceBasePath}\COPYING.txt +OutputDir={#SourceBasePath}\bin64\ +OutputBaseFilename=Borderless_setup +SetupIconFile=custom\icons\icon.ico +Compression=lzma +SolidCompression=yes +ArchitecturesInstallIn64BitMode=x64 + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "{#SourceBasePath}\bin64\{#MyAppExeName}"; DestDir: "{app}\bin"; Flags: ignoreversion; Components: main +Source: "{#SourceBasePath}\COPYING.txt"; DestDir: "{app}"; Flags: ignoreversion; Components: main +Source: "custom\qt.conf"; DestDir: "{app}\bin"; Flags: ignoreversion; Components: main +Source: "custom\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion recursesubdirs; Components: main +Source: "custom\redist\*"; DestDir: "{app}\bin"; Flags: ignoreversion; Components: main +Source: "{#SourceBasePath}\doc\*"; DestDir: "{app}\doc"; Flags: ignoreversion; Components: main +Source: "{#SourceBasePath}\samples\*"; DestDir: "{app}\samples"; Flags: ignoreversion; Components: cppi luai +Source: "{#SourceBasePath}\bin64\LuaInterpreter.dll"; DestDir: "{app}\bin"; Flags: ignoreversion; Components: luai +Source: "{#SourceBasePath}\bin64\CppInterpreter.dll"; DestDir: "{app}\bin"; Flags: ignoreversion; Components: cppi +Source: "custom\lib\*"; DestDir: "{app}\lib"; Flags: ignoreversion recursesubdirs; Components: cppi +Source: "{#SourceBasePath}\src\plugin-core\Cpp\RuntimeLibrary\*"; DestDir: "{app}\lib\clang\3.8.0\include"; Flags: ignoreversion; Components: cppi + +[Components] +Name: "main"; Description: "Main Executable"; Types: full minimum custom; Flags: fixed +Name: "luai"; Description: "Lua Interpreter Plugin"; Types: full custom; ExtraDiskSpaceRequired: 774656 +Name: "cppi"; Description: "C++ Interpreter Plugin"; Types: full custom; ExtraDiskSpaceRequired: 48755650 + +[Types] +Name: "full"; Description: "Full installation" +Name: "minimum"; Description: "Minimal installation" +Name: "custom"; Description: "Custom installation"; Flags: iscustom + +[Registry] +; Set up Applications subkey +Root: HKCR; Subkey: "Applications\{#MyAppExeName}"; Flags: uninsdeletekey +Root: HKCR; Subkey: "Applications\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppName}" +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\SupportedTypes"; Flags: uninsdeletekey +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\shell\open\command"; Flags: uninsdeletekey +Root: HKCR; Subkey: "Applications\{#MyAppExeName}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\{#MyAppExeName}"" ""%1""" + +#include "registry.iss" + +[Icons] +Name: "{commonprograms}\{#MyAppName}"; Filename: "{app}\bin\{#MyAppExeName}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\bin\{#MyAppExeName}"; Tasks: desktopicon + +[Run] +Filename: "{app}\bin\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + diff --git a/LuaInterpreter/LuaInterpreter.vcxproj b/LuaInterpreter/LuaInterpreter.vcxproj new file mode 100644 index 0000000..63c18ab --- /dev/null +++ b/LuaInterpreter/LuaInterpreter.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + {27EE8D4B-AD52-4888-A793-21C589739AB7} + Win32Proj + LuaInterpreter + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + $(SolutionDir)bin64\ + + + false + + + false + $(SolutionDir)bin64\ + + + + + + Level3 + Disabled + WIN32;BUILDING_LUAINTERPRETER;WIN32;_DEBUG;_WINDOWS;_USRDLL;LUAINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)luajit-2.0\src + MultiThreadedDebug + + + Windows + true + $(SolutionDir)lib + lua51.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;BUILDING_LUAINTERPRETER;_DEBUG;_WINDOWS;_USRDLL;LUAINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)luajit-2.0\src + MultiThreadedDebug + + + Windows + true + $(SolutionDir)lib64 + lua51.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;BUILDING_LUAINTERPRETER;WIN32;NDEBUG;_WINDOWS;_USRDLL;LUAINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)luajit-2.0\src + MultiThreaded + + + Windows + true + true + true + $(SolutionDir)lib + lua51.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;BUILDING_LUAINTERPRETER;NDEBUG;_WINDOWS;_USRDLL;LUAINTERPRETER_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)luajit-2.0\src + MultiThreaded + + + Windows + true + true + true + $(SolutionDir)lib64 + lua51.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/LuaInterpreter/LuaInterpreter.vcxproj.filters b/LuaInterpreter/LuaInterpreter.vcxproj.filters new file mode 100644 index 0000000..6107f05 --- /dev/null +++ b/LuaInterpreter/LuaInterpreter.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/README.md b/README.md index 89c9fb5..f800647 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,18 @@ This is an image viewer with a minimalist GUI. It's intended to be a viewer and Current features: * Minimally intrusive UI. Image display windows are completely frameless. No titlebar, no status bar, no nothing. The program is mainly controlled with the keyboard, and more complex functions are accessed through a context menu. -* Supported formats: BMP, JPEG, PNG, GIF. Other formats may already be supported by Qt (which handles the decoding), but they haven't been tested. +* Supported operating systems: Windows 7 and newer for the x86-64 architecture, FreeBSD, Linux. +* Supported formats: BMP, JPEG, PNG, GIF, basic SVG support. Other formats may already be supported by Qt (which handles the decoding), but they haven't been tested. * Proper transparency display. - -Planned features: -* SVG support. +* User-programmable filters in Lua (provided by LuaJIT) or C++ (provided by LLVM+Clang). Possible future features: * Support for traversing images in common archive formats. -* Plugin interface of some kind. -Requirements: -* Qt 5.4.1 or newer. +Requirements (compilation): +* Qt 5.4.1 or newer +* Boost.Iostreams +* LuaJIT (optional) +* LLVM and libclang (optional) + +NOTICE: This repository uses submodules! To correctly get all dependencies, clone with git clone --recursive diff --git a/StdOutputRedirect/StdOutputRedirect.cpp b/StdOutputRedirect/StdOutputRedirect.cpp new file mode 100644 index 0000000..0384098 --- /dev/null +++ b/StdOutputRedirect/StdOutputRedirect.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include + +const size_t buffer_size = 4096; + +template +typename std::enable_if::value, void>::type +zero_struct(T &s){ + memset(&s, 0, sizeof(s)); +} + +HANDLE CreateChildProcess(std::wstring program, HANDLE write_pipe_end){ + PROCESS_INFORMATION pi; + STARTUPINFO si; + zero_struct(pi); + zero_struct(si); + + si.cb = sizeof(STARTUPINFO); + si.hStdError = write_pipe_end; + si.hStdOutput = write_pipe_end; + si.dwFlags |= STARTF_USESTDHANDLES; + + auto success = CreateProcessW(0, &program[0], 0, 0, true, 0, 0, 0, &si, &pi); + + if (!success) + throw std::exception("CreateProcess failed."); + + CloseHandle(pi.hThread); + return pi.hProcess; +} + +void ReadFromPipe(HANDLE process, HANDLE read_pipe_end){ + DWORD read, written; + CHAR buffer[buffer_size]; + HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + while (true){ + DWORD exit_code; + auto success = GetExitCodeProcess(process, &exit_code); + if (!success || exit_code != STILL_ACTIVE) + break; + success = ReadFile(read_pipe_end, buffer, buffer_size, &read, nullptr); + if (!success || !read) + break; + + success = WriteFile(hParentStdOut, buffer, read, &written, 0); + if (!success) + break; + } +} + +int main(int argc, char **argv){ + try{ + FreeConsole(); + + SECURITY_ATTRIBUTES saAttr; + + HANDLE read_pipe_end = nullptr; + HANDLE write_pipe_end = nullptr; + + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = true; + saAttr.lpSecurityDescriptor = nullptr; + + if (!CreatePipe(&read_pipe_end, &write_pipe_end, &saAttr, 0)) + throw std::exception("StdoutRd CreatePipe failed."); + + if (!SetHandleInformation(read_pipe_end, HANDLE_FLAG_INHERIT, 0)) + throw std::exception("Stdout SetHandleInformation failed."); + + auto child = CreateChildProcess(L"Borderless.exe", write_pipe_end); + + ReadFromPipe(child, read_pipe_end); + + CloseHandle(child); + }catch (std::exception &e){ + std::cerr << "ERROR: " << e.what() << std::endl; + } + return 0; +} diff --git a/StdOutputRedirect/StdOutputRedirect.vcxproj b/StdOutputRedirect/StdOutputRedirect.vcxproj new file mode 100644 index 0000000..280177c --- /dev/null +++ b/StdOutputRedirect/StdOutputRedirect.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {FBC0C925-BDA0-496C-B897-DC7947573F8F} + Win32Proj + StdOutputRedirect + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/StdOutputRedirect/StdOutputRedirect.vcxproj.filters b/StdOutputRedirect/StdOutputRedirect.vcxproj.filters new file mode 100644 index 0000000..f665d50 --- /dev/null +++ b/StdOutputRedirect/StdOutputRedirect.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/build_serialization.sh b/build_serialization.sh new file mode 100644 index 0000000..24fbdf8 --- /dev/null +++ b/build_serialization.sh @@ -0,0 +1,7 @@ +#!/bin/sh +cd serialization +chmod +x build.sh +./build.sh +mv LAS.out ../LAS +cd ../src/serialization +../../LAS settings.txt diff --git a/doc/Building.txt b/doc/Building.txt new file mode 100644 index 0000000..15cc6c4 --- /dev/null +++ b/doc/Building.txt @@ -0,0 +1,50 @@ +Requirements: +* A C++ compiler with good C++11 support. The following compilers have been + tested: MSVC 2013 and 2015, Clang 3.4.1, GCC 5.3.1. +* Qt 5.4.1 or newer +* Boost.Iostreams +* LuaJIT (optional) +* LLVM and libclang (optional) + + +Building on Windows + +A solution file for Visual Studio 2015 is provided. It can also be used with +2013, but the toolchain version of each project must be changed to use v12, +instead of the 2015 default v14. +Before building, Visual Studio must be configured to use the correct Qt version, +as well as Boost.Iostreams and whatever other Boost libraries it depends on. +Building the entire solution builds everything required by the application, +including the serializer generator which is ran during the build process. + +To build the Lua plugin, LuaJIT >= 2.0 is required. Version 2.0.4 is included as +a submodule and a project is included in the solution to build and link to it. + +To build the C++ plugin, LLVM and Clang are required. Since building these +projects is time-consuming and non-trivial, a build of version 3.8 can be +downloaded from here: +https://drive.google.com/open?id=0B0RA3x3xMSnKV19IdDZYNU9BVEU +If you wish to build LLVM and Clang yourself, note that the project expects to +find the corresponding files in the following directories: +$(SolutionDir)\LLVM\include\clang Clang C++ headers +$(SolutionDir)\LLVM\include\clang-c Clang C headers +$(SolutionDir)\LLVM\include\llvm LLVM C++ headers +$(SolutionDir)\LLVM\include\llvm-c LLVM C headers +$(SolutionDir)\LLVM\lib64\Debug x86-64 libraries with debugging symbols +$(SolutionDir)\LLVM\lib64\Release x86-64 libraries with optimizations +The libraries should link statically, without any DLLs. + + +Building on Linux/BSD + +Before building the application proper, be sure to run build_serialization.sh to +build the serializer generator and generate the serialization code. This script +assumes that c++ refers to the default C++ compiler for the system. + +A .pro file for use with Qt Creator is provided. Before building, it should be +configured to use the correct Qt version, and the Boost libraries should be +visible to the compiler. +Building the project should generate the final executable. + +The plugins have yet to be tested on these platforms, but they may still work in +their current state. diff --git a/doc/Plugins.txt b/doc/Plugins.txt new file mode 100644 index 0000000..4fa3bba --- /dev/null +++ b/doc/Plugins.txt @@ -0,0 +1,177 @@ +The following describes the plugin interface, as well as general considerations +to write filters. + + +Basic introduction + +To run a filter, the user right-clicks on an image (called the "caller image") +in the application, and selects one from the context menu. The selected filter +is said to operate on the caller image, although this isn't necessarily the +case. The menu is populated by traversing a "filters" subdirectory in the user's +configuration directory (its location depends on the platform. On Windows, it's +in %APPDATA%\BorderlessImageViewer\filters). + + +General concepts + +A filter operates on an array of pixels -- a bitmap. Bitmaps passed and returned +by filters are always 32-bit in depth. That is, they contain four channels (red, +green, blue, and transparency [or alpha]), each of which may have any of 256 +values of intensity. +A bitmap has the following properties that determine its memory layout: width, +height, stride, and pitch. Width and height are the sizes of the corresponding +dimensions of the bitmap in pixels. The stride is the size of a pixel in bytes. +Currently, the stride is always 4; if performance of the filter is an concern, +it's okay to assume that this value will always be 4 (the compiler may generate +faster code when this value is hard-coded). The pitch is the size of a row in +bytes. Note that if stride * width may be different from pitch, although this is +very improbable. +Pixels are stored in row-major order, from left to right and from top to bottom. +In other words, a bitmap that is displayed as +ABC +DEF +GHI +will appear in memory as ABCDEFGHI. Channels are always stored in RGBA order +regardless of the endianness of the platform. In other words, red is always the +first byte of a pixel, then green, then blue, then alpha. + + +Lua modes of operations + +Lua filters may execute in one of two modes: normal, or pure filter. A "normal" +filter runs from beginning to end and needs not use the image that was used to +call it at all. For example, this is useful to write, for example, a generator +that just writes an image to disk. +A pure filter must define a global boolean named 'is_pure_filter' set to true +and a global function named 'main' that accepts an integer and returns an +integer. The passed integer is a handle to the image on which the filter was +called, and the return value must be an integer to an image serving as output of +the filter. This mode is useful to define filters that behave as pure +mathematical functions. For example, a filter that rotates the displayed image +by 30° and displays the result. Additionally, in the future it may be possible +to chain pure filters together. + + +Lua API + +load_image(path: string): integer +Loads an image from the file system. The returned integer serves as a handle to +pass to other functions. If this handle is lost, the image can no longer be +unloaded or operated on. This is equivalent to a pointer leak. +The interpreter may or may not implement some system to clean up leaked images +that can no longer be referenced by any filters. + +allocate_image(width: integer, height: integer): integer +Creates an image of the given dimensions and returns a handle to it. All pixels +of the new image are initialized to black transparent. + +unload_image(handle: integer) +Unloads the image associated to the given handle, releasing the memory used by +it. + +traverse_image(handle: integer, callback: function) +callback(r: integer, g: integer, b: integer, a: integer, x: integer, y: integer) +Calls the provided callback for every pixel of the image associated with the +provided handle, passing to it the RGBA values and the coordinates of the pixel. +The RGBA values are given in the range 0-255 inclusive. The coordinates are +0-indexed (e.g. the rightmost column is width - 1). + +set_current_pixel(r: integer, g: integer, b: integer, a: integer) +Must be called from the callback passed to a traverse_image() call. Sets the +pixel currently being traversed to the given RGBA quadruplet. +The RGBA values should be given in the range 0-255 inclusive. + +save_image(handle: image, path: string) +Saves the image associated with the given handle to the given path on the file +system. Optionally, an object may be passed as a third parameter to specify +options. +{format: string, compression: integer} +format: E.g. "jpeg", "png", etc. +compression: An integer between 0 and 100. + +rgb_to_hsv(r: integer, g: integer, b: integer): real, integer, integer +Converts an RGB triplet to the HSV (hue-saturation-value) color space. +The RGBA values should be given in the range 0-255 inclusive. +The hue is given in the range 0-360. The saturation and value are given in the +range 0-255. +Example: h, s, v = rgb_to_hsv(r, g, b) + +hsv_to_rgb(h: real, s: integer, v: integer): integer, integer, integer +Performs the reverse operation to rgb_to_hsv(). + +bitwise_and(a: integer, b: integer): integer +bitwise_or(a: integer, b: integer): integer +bitwise_xor(a: integer, b: integer): integer +bitwise_not(a: integer): integer +Performs the given bitwise operation on the operands and returns the result. + +get_pixel(handle: integer, x: integer, y: integer): integer, integer, integer, integer +Returns the RGBA values of a single pixel of the image. x should be in the range +[0; width - 1], and y should be in the range [0; height - 1]. + +get_image_dimensions(handle: integer): integer, integer +Returns the width and height of the image. + +display_in_current_window(handle: image) +Displays the image in the window from which the filter was called. The call +may take effect only after the filter has finished. + +get_displayed_image(): integer +Returns the image currently being displayed on the window that called the +filter. + +debug_print(string) +Windows-only: Sends the given string to debug output. The debug output can be +read using programs such as DbgView. + +show_message_box(string) +Show a message box with the given string. + + +Special considerations for C++ filters + +The C++ implementation is provided by Clang, acting as a JIT compiler. The +performance of the generated code is identical to that of code generated by the +command line compiler. + +At the time of writing, the latest release of Clang is 3.8. At this point, there +is no standard library implementation for Clang on Windows. The interpreter +configures libclang to be able to use MSVC's implementation, but this support is +not perfect. Specifically, library features that require linking with static +MSVC runtime libraries cannot be used, because there's no way to tell libclang +to link these in. The following features are known to work: +* STL containers. +* std::string. +The following features are known NOT to work: +* All IO streams, including std::stringstream. C streams can still be used. A + stringstream replacement is provided (see borderless_runtime.h for details). +* Random functions, including both and . [TODO]A replacement + is provided.[/TODO] +* Time functions, including both and . A clock() replacement is provided. +* std::shared_ptr. std::unique_ptr and std::auto_ptr haven't been tested, but + they might work. +Other features may be unavailable. If you happen to use a feature that not +available, the program will abort, with libclang sending the linker error +message to stderr. I don't seem to be able to override this behavior. To see the +error message, redirect stderr to a file. Unfortunately, this only reveals the +specific missing symbol, not the header that caused the problem. It's therefore +recommended to add new headers to the source one at a time. + +libclang sends all its error messages to stderr. On Windows, for Windows +applications (as opposed to console applications), redirecting standard streams +is very tricky. This is why the error message box that pops up when compiler +errors are detected is not very helpful. If you want this message box to display +the compiler errors, you'll need to build Borderless as a console application. +This should enable the redirection to a string. + + +C++ modes of operation + +C++ filters only operate as pure filters. A C++ filter should always include +. This file defines the low level entry point into the filter and +initializes the environment. You can implement this yourself if you prefer, but +this is not recommended. +The main function for the filter has the following signature: +B::Image entry_point(B::Application &app, B::Image img); + +TODO: Describe the C++ run-time library. diff --git a/lib/placeholder b/lib/placeholder new file mode 100644 index 0000000..e69de29 diff --git a/lib64/placeholder b/lib64/placeholder new file mode 100644 index 0000000..e69de29 diff --git a/luajit-2.0 b/luajit-2.0 new file mode 160000 index 0000000..69e5342 --- /dev/null +++ b/luajit-2.0 @@ -0,0 +1 @@ +Subproject commit 69e5342eb893815b18a1ec84ba74b0e0d1cc9beb diff --git a/luajit/luajit.vcxproj b/luajit/luajit.vcxproj new file mode 100644 index 0000000..442bcb2 --- /dev/null +++ b/luajit/luajit.vcxproj @@ -0,0 +1,183 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {068B1B0F-54A0-4818-926F-B35A72F71BDE} + Win32Proj + luajit + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + lib + $(SolutionDir)bin\ + lua51 + + + true + $(SolutionDir)bin64\ + lua51 + lib + + + false + lib + $(SolutionDir)bin\ + lua51 + + + false + $(SolutionDir)bin64\ + lua51 + lib + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LUAJIT_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + + + cd $(SolutionDir)luajit-2.0\src +call msvcbuild.bat debug +move /y "$(SolutionDir)luajit-2.0\src\lua51.lib" "$(SolutionDir)lib" +move /y "$(SolutionDir)luajit-2.0\src\lua51.dll" "$(SolutionDir)bin" + + + + + + + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;LUAJIT_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + + + cd $(SolutionDir)luajit-2.0\src +call msvcbuild.bat debug static +move /y "$(SolutionDir)luajit-2.0\src\lua51.lib" "$(SolutionDir)lib64" +rem move /y "$(SolutionDir)luajit-2.0\src\lua51.dll" "$(SolutionDir)bin64" + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LUAJIT_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + cd $(SolutionDir)luajit-2.0\src +call msvcbuild.bat +move /y "$(SolutionDir)luajit-2.0\src\lua51.lib" "$(SolutionDir)lib" +move /y "$(SolutionDir)luajit-2.0\src\lua51.dll" "$(SolutionDir)bin" + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;LUAJIT_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + cd $(SolutionDir)luajit-2.0\src +call msvcbuild.bat static +move /y "$(SolutionDir)luajit-2.0\src\lua51.lib" "$(SolutionDir)lib64" +rem move /y "$(SolutionDir)luajit-2.0\src\lua51.dll" "$(SolutionDir)bin64" + + + + + + \ No newline at end of file diff --git a/luajit/luajit.vcxproj.filters b/luajit/luajit.vcxproj.filters new file mode 100644 index 0000000..f81daba --- /dev/null +++ b/luajit/luajit.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/samples/AlignedDither.lua b/samples/AlignedDither.lua new file mode 100644 index 0000000..8eade22 --- /dev/null +++ b/samples/AlignedDither.lua @@ -0,0 +1,70 @@ +function gcd(a, b) + while b ~= 0 do + --debug_print(a .. ", " .. b) + local t = b + b = a % b + a = t + end + --debug_print(a) + return a +end + +function reduce_fraction(a, b) + local c = gcd(a, b) + return a / c, b / c +end + +local img = get_displayed_image() +w, h = get_image_dimensions(img) + +function generate_bayer_matrix(power) + local ret = {} + if power == 0 then + ret[0] = 0; + return ret + end + local side = 2^power + local last = generate_bayer_matrix(power - 1) + local last_side = 2^(power-1) + local offsets = { + {0, 0}, + {1, 1}, + {0, 1}, + {1, 0}, + } + for quadrant = 0, 3 do + local offx = offsets[quadrant + 1][1] * last_side + local offy = offsets[quadrant + 1][2] * last_side + for y = 0, last_side - 1 do + for x = 0, last_side - 1 do + local dst = x + offx + (y + offy) * side + local src = x + y * last_side + ret[dst] = last[src] * 4 + quadrant; + end + end + end + return ret +end + +local pattern = generate_bayer_matrix(4) + +function dither_pixel(r, g, b, a, x, y) + local luma = r * 0.2126 + g * 0.7152 + b * 0.0722 + luma = math.floor(luma + 0.5) + local c = 0 + local i = x % 16 + y % 16 * 16 + if luma >= pattern[i] then + c = 255 + end + return c, c, c, a +end + +traverse_image( + img, + function (r, g, b, a, x, y) + set_current_pixel(dither_pixel(r, g, b, a, x, y)) + end +) + +display_in_current_window(img) +unload_image(img) diff --git a/samples/FSD.cpp b/samples/FSD.cpp new file mode 100644 index 0000000..1de249f --- /dev/null +++ b/samples/FSD.cpp @@ -0,0 +1,145 @@ +// This example applies a Floyd-Steinberg dither with 2 colors on the selected +// image. It runs over 5 times faster than the Lua implementation, excluding +// compilation time. + +#include "borderless.h" +#include + +typedef float pixel_t; + +pixel_t f(int x, const std::vector &colors){ + float pos = x / 255.f * (colors.size() - 1); + int which = floor(pos + 0.5f); + return (pixel_t)colors[which]; +} + +std::vector construct_colors(int count){ + std::vector ret(count); + for (int i = 0; i < count; i++) + ret[i] = 255 * i / (count - 1); + return ret; +} + +pixel_t luma(int r, int g, int b){ + return (r * 2126 + g * 7152 + b * 722) / (pixel_t)10000; +} + +std::vector construct_pixels(B::Image &img){ + int w, h; + img.get_dimensions(w, h); + + std::vector pixels(w * h); + + B::ImageIterator it(img); + u8 *pixel; + int i = 0; + while (it.next(pixel)) + pixels[i++] = luma(pixel[0], pixel[1], pixel[2]); + + return pixels; +} + +void compute_dither(B::Image &img, std::vector &pixels, const std::vector &colors){ + int w, h; + img.get_dimensions(w, h); + + static const int offsets[][2] = { + { 1, 0 }, + { -1, 1 }, + { 0, 1 }, + { 1, 1 }, + }; + static const float weights[][4] = { + { 0, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 7.f/16.f, 0, 0, 0 }, + { 8.f/16.f, 0, 6.f/16.f, 2.f/16.f }, + { 0, 0, 0, 0 }, + { 0, 7.f/16.f, 9.f/16.f, 0 }, + { 7.f/16.f, 0, 0, 0 }, + { 7.f/16.f, 3.f/16.f, 5.f/16.f, 1.f/16.f } + }; + + bool errored = false; + + for (int y = 0; y < h; y++){ + int start = 0; + int finish = w - 1; + bool invert = y % 2 != 0; + int step = invert ? -1 : 1; + if (invert){ + start = w - 1; + finish = -1; + } + for (int x = start; x != finish; x += step){ + pixel_t oldpixel = pixels[x + y * w]; + if (oldpixel > 255) + oldpixel = 255; + else if (oldpixel < 0) + oldpixel = 0; + pixel_t newpixel = f(oldpixel, colors); + pixels[x + y * w] = newpixel; + pixel_t qe = oldpixel - newpixel; + int weight_chosen; + if (!invert) + weight_chosen = (!!x) * 4 + (x != w - 1) * 2 + (y != h - 1); + else + weight_chosen = (!!x) * 2 + (x != w - 1) * 4 + (y != h - 1); + + for (int i = 0; i < 4; i++){ + float weight = weights[weight_chosen][i]; + if (weight <= 0) + continue; + int x2 = x + offsets[i][0] * (!invert * 2 - 1); + int y2 = y + offsets[i][1]; + int j = x2 + y2 * w; + if (((!invert && y2 == y && x2 < x) || (invert && y2 == y && x2 > x)) && !errored){ + B::Stream() << "Internal error detected!" << B::msgbox; + errored = true; + } + pixels[j] += qe * weight; + } + } + } +} + +void copy_back(B::Image &img, const std::vector &pixels){ + B::ImageIterator it(img); + u8 *pixel; + int i = 0; + while (it.next(pixel)){ + auto c = (int)floor(pixels[i++]); + pixel[0] = c; + pixel[1] = c; + pixel[2] = c; + } +} + +void copy_back(B::Image &img, const std::vector &pixels){ + B::ImageIterator it(img); + u8 *pixel; + int i = 0; + while (it.next(pixel)){ + auto c = pixels[i++]; + pixel[0] = c; + pixel[1] = c; + pixel[2] = c; + } +} + +void apply_floyd_steinberg(B::Image &img, int color_count){ + auto colors = construct_colors(color_count); + auto pixels = construct_pixels(img); + compute_dither(img, pixels, colors); + copy_back(img, pixels); +} + +B::Image entry_point(B::Application &app, B::Image img){ + auto t0 = borderless_clock(); + + apply_floyd_steinberg(img, 2); + + auto t1 = borderless_clock(); + B::Stream() << "Filter took " << t1 - t0 << " s." << B::msgbox; + return img; +} diff --git a/samples/FSD.lua b/samples/FSD.lua new file mode 100644 index 0000000..ba8eaf8 --- /dev/null +++ b/samples/FSD.lua @@ -0,0 +1,105 @@ +-- This example applies a Floyd-Steinberg dither with 2 colors on the select +-- image. + +is_pure_filter = true + +local use_old_traversal = false + +function make_f(colors, radius, nosteps) + return function(x) + local pos = x / 255 * (#colors - 1) + 1 + local low = math.floor(pos) + local high = math.ceil(pos) + local which = math.random() < ((pos - low) - radius) / (1 - radius) and high or low + if nosteps then + which = math.floor(pos + 0.5) + end + return colors[which] + end +end + +function main(img) + local t0 = os.clock() + local w, h + w, h = get_image_dimensions(img) + local colors = {} + local steps = 2 + for i = 1, steps do + colors[i] = 255 / (steps - 1) * (i - 1) + end + local f = make_f(colors, 0, false) + + local pixels = {} + traverse_image( + img, + function (r, g, b, a, x, y) + local luma = r * 0.2126 + g * 0.7152 + b * 0.0722 + pixels[x + y * w] = luma + end + ) + local offsets = { + { 1, 0 }, + { -1, 1 }, + { 0, 1 }, + { 1, 1 } + } + local weights = { + { 0, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 7/16, 0, 0, 0 }, + { 8/16, 0, 6/16, 2/16 }, + { 0, 0, 0, 0 }, + { 0, 7/16, 9/16, 0 }, + { 7/16, 0, 0, 0 }, + { 7/16, 3/16, 5/16, 1/16 } + } + for y = 0, h - 1 do + local start = 0 + local finish = w - 1 + local invert = y % 2 ~= 0 + local step = invert and -1 or 1 + if invert then + start, finish = finish, start + end + for x = start, finish, step do + local oldpixel = pixels[x + y * w] + if oldpixel > 255 then + oldpixel = 255 + else + if oldpixel < 0 then + oldpixel = 0 + end + end + local newpixel = f(oldpixel) + pixels[x + y * w] = newpixel + local qe = oldpixel - newpixel + local weight_chosen + if not invert then + weight_chosen = (x == 0 and 0 or 4) + (x == w - 1 and 0 or 2) + (y == h - 1 and 0 or 1) + 1 + else + weight_chosen = (x == 0 and 0 or 2) + (x == w - 1 and 0 or 4) + (y == h - 1 and 0 or 1) + 1 + end + for i = 1, 4 do + local weight = weights[weight_chosen][i] + if weight > 0 then + local x2 = x + offsets[i][1] * (invert and -1 or 1) + local y2 = y + offsets[i][2] + local j = x2 + y2 * w + if (not invert and y2 == y and x2 < x) or (invert and y2 == y and x2 > x) then + print("ERROR ", x, y, x2, y2, invert) + end + pixels[j] = pixels[j] + qe * weight + end + end + end + end + traverse_image( + img, + function (r, g, b, a, x, y) + local c = pixels[x + y * w] + set_current_pixel(c, c, c, a) + end + ) + local t1 = os.clock() + show_message_box("Elapsed time: " .. (t1 - t0) .. " s") +end diff --git a/samples/FSD2.lua b/samples/FSD2.lua new file mode 100644 index 0000000..57d3cf4 --- /dev/null +++ b/samples/FSD2.lua @@ -0,0 +1,135 @@ +local t0 = os.clock() +local img = get_displayed_image() +local w, h +w, h = get_image_dimensions(img) +local colors = {} +local steps = 2 +for i = 1, steps do + colors[i] = 255 / (steps - 1) * (i - 1) +end +local radius = 0 + +function f(x, nosteps) + local pos = x / 255 * (#colors - 1) + 1 + local low = math.floor(pos) + local high = math.ceil(pos) + local which = math.random() < ((pos - low) - radius) / (1 - radius) and high or low + if nosteps then + which = math.floor(pos + 0.5) + end + return colors[which] +end + +print("Loading image data.") +local pixels = {} +traverse_image( + img, + function (r, g, b, a, x, y) + local off = (x + y * w) * 4 + pixels[off + 0] = r + pixels[off + 1] = g + pixels[off + 2] = b + pixels[off + 3] = a + end +) +print("Computing new data.") +local offsets = { + { 1, 0 }, + { -1, 1 }, + { 0, 1 }, + { 1, 1 } +} +local weights = { + { 0, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 7/16, 0, 0, 0 }, + { 8/16, 0, 6/16, 2/16 }, + { 0, 0, 0, 0 }, + { 0, 7/16, 9/16, 0 }, + { 7/16, 0, 0, 0 }, + { 7/16, 3/16, 5/16, 1/16 } +} +--[[ +local weights = { + { 0, 0, 0, 0 }, + { 0, 3/16, 0, 0 }, + { 7/16, 0, 0, 0 }, + { 7/16, 0, 5/16, 1/16 }, + { 0, 0, 0, 0 }, + { 0, 3/16, 5/16, 0 }, + { 7/16, 0, 0, 0 }, + { 7/16, 3/16, 5/16, 1/16 } +} +]]-- +for y = 0, h - 1 do + local start = 0 + local finish = w - 1 + local invert = y % 2 ~= 0 + local step = invert and -1 or 1 + if invert then + start, finish = finish, start + end + for x = start, finish, step do + for c = 0, 3, 1 do + local channel = (x + y * w) * 4 + c + local oldpixel = pixels[channel] + if oldpixel > 255 then + oldpixel = 255 + else + if oldpixel < 0 then + oldpixel = 0 + end + end + local newpixel = f(oldpixel, true) + pixels[channel] = newpixel + local qe = oldpixel - newpixel + local weight_chosen + if not invert then + weight_chosen = (x == 0 and 0 or 4) + (x == w - 1 and 0 or 2) + (y == h - 1 and 0 or 1) + 1 + else + weight_chosen = (x == 0 and 0 or 2) + (x == w - 1 and 0 or 4) + (y == h - 1 and 0 or 1) + 1 + end + for i = 1, 4 do + local weight = weights[weight_chosen][i] + if weight > 0 then + local x2 = x + offsets[i][1] * (invert and -1 or 1) + local y2 = y + offsets[i][2] + local j = (x2 + y2 * w) * 4 + c + if (not invert and y2 == y and x2 < x) or (invert and y2 == y and x2 > x) then + print("ERROR ", x, y, x2, y2, invert) + end + pixels[j] = pixels[j] + qe * weight + end + end + end + end +end +print("Applying new data.") +traverse_image( + img, + function (r, g, b, a, x, y) + local off = (x + y * w) * 4; + set_current_pixel( + pixels[off + 0], + pixels[off + 1], + pixels[off + 2], + pixels[off + 3] + ) + end +) +print("Saving image data.") +display_in_current_window(img) +save_image(img, "z:/output.png") +unload_image(img) +local t1 = os.clock() +print("Elapsed time: ", t1 - t0, " s") +--img = load_image("sample.jpg") +--traverse_image( +-- img, +-- function (r, g, b, a, x, y) +-- local luma = r * 0.2126 + g * 0.7152 + b * 0.0722 +-- set_current_pixel(luma, luma, luma, a) +-- end +--) +--save_image(img, "output2.png") +--unload_image(img) diff --git a/samples/ZZFSD.lua b/samples/ZZFSD.lua new file mode 100644 index 0000000..8179c4b --- /dev/null +++ b/samples/ZZFSD.lua @@ -0,0 +1,113 @@ +local t0 = os.clock() +local img = get_displayed_image() +local w, h +w, h = get_image_dimensions(img) +local colors = {} +local steps = 2 +for i = 1, steps do + colors[i] = 255 / (steps - 1) * (i - 1) +end +local radius = 0 + +function f(x, nosteps) + local pos = x / 255 * (#colors - 1) + 1 + local low = math.floor(pos) + local high = math.ceil(pos) + local which = math.random() < ((pos - low) - radius) / (1 - radius) and high or low + if nosteps then + which = math.floor(pos + 0.5) + end + return colors[which] +end + +print("Loading image data.") +local pixels = {} +traverse_image( + img, + function (r, g, b, a, x, y) + local luma = r * 0.2126 + g * 0.7152 + b * 0.0722 + --luma = y / (h - 1) * 255 + pixels[x + y * w] = luma + end +) +print("Computing new data.") + +function create_weights() + return { + { + offset = { 1, 0 }, + weight = 7/16 + }, + { + offset = { 1, 1 }, + weight = 2/16 + }, + { + offset = { 0, 1 }, + weight = 7/16 + } + } +end + +do + local x, y, state + x = 0 + y = 0 + state = 0 + while true do + x, y, state = zig_zag_order(x, y, w, h, state) + if state < 0 then + break + end + + local oldpixel = pixels[x + y * w] + if oldpixel > 255 then + oldpixel = 255 + else + if oldpixel < 0 then + oldpixel = 0 + end + end + local newpixel = f(oldpixel, true) + pixels[x + y * w] = newpixel + local qe = oldpixel - newpixel + local weights = create_weights() + local unusable = 0 + local sum = 0 + for i = 1, #weights do + local x2 = x + weights[i].offset[1] + local y2 = y + weights[i].offset[2] + if x2 >= w or x2 < 0 or y2 >= h or y2 < 0 then + unusable = unusable + weights[i].weight + weights[i].weight = 0 + else + sum = sum + weights[i].weight + end + end + for i = 1, #weights do + weights[i].weight = weights[i].weight + weights[i].weight / sum * unusable + end + for i = 1, #weights do + local weight = weights[i].weight + if weight > 0 then + local x2 = x + weights[i].offset[1] + local y2 = y + weights[i].offset[2] + local j = x2 + y2 * w + pixels[j] = pixels[j] + qe * weight + end + end + end +end +print("Applying new data.") +traverse_image( + img, + function (r, g, b, a, x, y) + local c = pixels[x + y * w] + set_current_pixel(c, c, c, 255) + end +) +print("Saving image data.") +display_in_current_window(img) +unload_image(img) +local t1 = os.clock() +print("Elapsed time: ", t1 - t0, " s") diff --git a/samples/negative.cpp b/samples/negative.cpp new file mode 100644 index 0000000..39a5663 --- /dev/null +++ b/samples/negative.cpp @@ -0,0 +1,32 @@ +#include "borderless.h" + +#define USE_ITERATOR + +B::Image entry_point(B::Application &app, B::Image img){ + auto t0 = borderless_clock(); + +#ifdef USE_ITERATOR + B::ImageIterator it(img); + u8 *pixel; + while (it.next(pixel)){ + pixel[0] ^= 255; + pixel[1] ^= 255; + pixel[2] ^= 255; + } +#else + int w, h, stride, pitch; + unsigned char *pixels; + img.get_pixel_data(w, h, stride, pitch, pixels); + int n = w * h; + for (int i = 0; i < n; i++){ + pixels[0] ^= 255; + pixels[1] ^= 255; + pixels[2] ^= 255; + pixels += 4; + } +#endif + + auto t1 = borderless_clock(); + B::Stream() << "Filter took " << t1 - t0 << " s." << B::msgbox; + return img; +} diff --git a/serialization b/serialization new file mode 160000 index 0000000..346a0f9 --- /dev/null +++ b/serialization @@ -0,0 +1 @@ +Subproject commit 346a0f92cc8feddfbfc46560b4609ab4a32854fb diff --git a/src/ClangErrorMessage.cpp b/src/ClangErrorMessage.cpp new file mode 100644 index 0000000..167b98e --- /dev/null +++ b/src/ClangErrorMessage.cpp @@ -0,0 +1,13 @@ +#include "ClangErrorMessage.hpp" + +ClangErrorMessage::ClangErrorMessage(QWidget * parent) : QDialog(parent) { + ui.setupUi(this); +} + +ClangErrorMessage::~ClangErrorMessage() { + +} + +void ClangErrorMessage::set_error_message(const QString &msg){ + this->ui.plainTextEdit->setPlainText(msg); +} diff --git a/src/ClangErrorMessage.hpp b/src/ClangErrorMessage.hpp new file mode 100644 index 0000000..29951b4 --- /dev/null +++ b/src/ClangErrorMessage.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include "ui_ClangErrorMessage.h" + +class ClangErrorMessage : public QDialog { + Q_OBJECT + +public: + ClangErrorMessage(QWidget * parent = Q_NULLPTR); + ~ClangErrorMessage(); + + void set_error_message(const QString &); + +private: + Ui::ClangErrorMessage ui; +}; diff --git a/src/ClangErrorMessage.ui b/src/ClangErrorMessage.ui new file mode 100644 index 0000000..7796f6d --- /dev/null +++ b/src/ClangErrorMessage.ui @@ -0,0 +1,74 @@ + + + ClangErrorMessage + + + + 0 + 0 + 1156 + 460 + + + + Dialog + + + + + + + Courier New + + + + QPlainTextEdit::NoWrap + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + + + + + pushButton + clicked() + ClangErrorMessage + accept() + + + 521 + 396 + + + 284 + 208 + + + + + diff --git a/src/DirectoryListing.cpp b/src/DirectoryListing.cpp index e372dfb..c3f5860 100644 --- a/src/DirectoryListing.cpp +++ b/src/DirectoryListing.cpp @@ -1,32 +1,11 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ -#include "directorylisting.h" +#include "DirectoryListing.h" #include #include #include @@ -43,6 +22,7 @@ static const char *supported_extensions[] = { "*.webp", "*.ico", "*.tga", + "*.tif", "*.tiff", "*.jp2", }; diff --git a/src/DirectoryListing.h b/src/DirectoryListing.h index e932834..549cd75 100644 --- a/src/DirectoryListing.h +++ b/src/DirectoryListing.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef DIRECTORYLISTING_H diff --git a/src/Enums.h b/src/Enums.h new file mode 100644 index 0000000..0d0db0e --- /dev/null +++ b/src/Enums.h @@ -0,0 +1,19 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef ENUM_H +#define ENUM_H + +enum class ZoomMode { + Normal = 0, + Locked = 1, + Automatic = 2, + AutoFit = Automatic | 0, + AutoFill = Automatic | 1, +}; + +#endif diff --git a/src/GenericException.h b/src/GenericException.h new file mode 100644 index 0000000..3c3326e --- /dev/null +++ b/src/GenericException.h @@ -0,0 +1,27 @@ +#ifndef GENERIC_EXCEPTION +#define GENERIC_EXCEPTION + +#include + +#if defined _MSC_VER +#if _MSC_VER >= 1900 +#define NOEXCEPT noexcept +#else +#define NOEXCEPT +#endif +#else +#define NOEXCEPT noexcept +#endif + +class GenericException : public std::exception{ + const char *cmessage; +public: + GenericException(const char *message): cmessage(message){} + virtual ~GenericException(){} + virtual const char *what() const NOEXCEPT{ + return this->cmessage; + } +}; + + +#endif diff --git a/src/ImageViewerApplication.cpp b/src/ImageViewerApplication.cpp index 807aaa7..665eff2 100644 --- a/src/ImageViewerApplication.cpp +++ b/src/ImageViewerApplication.cpp @@ -1,56 +1,38 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "ImageViewerApplication.h" +#include "plugin-core/PluginCoreState.h" #include "MainWindow.h" #include "RotateDialog.h" #include "Misc.h" #include "OptionsDialog.h" +#include "GenericException.h" #include #include #include #include +#include +#include -const ZoomMode ImageViewerApplication::default_zoom_mode_for_new_windows = ZoomMode::Normal; -const ZoomMode ImageViewerApplication::default_fullscreen_zoom_mode_for_new_windows = ZoomMode::AutoFit; - -ImageViewerApplication::ImageViewerApplication(int argc, char **argv, const QString &unique_name): +ImageViewerApplication::ImageViewerApplication(int &argc, char **argv, const QString &unique_name): SingleInstanceApplication(argc, argv, unique_name), - do_not_save(false){ - this->reset_settings(); - this->restore_settings(); - this->setQuitOnLastWindowClosed(!this->keep_application_in_background); - this->new_instance(this->args); - if (!this->windows.size() && !this->keep_application_in_background) + do_not_save(false), + tray_icon(QIcon(":/icon16.png"), this){ + if (!this->restore_settings()) + this->settings = std::make_shared(); + this->reset_tray_menu(); + this->conditional_tray_show(); + this->setQuitOnLastWindowClosed(!this->settings->get_keep_application_in_background()); + ImageViewerApplication::new_instance(this->args); + if (!this->windows.size() && !this->settings->get_keep_application_in_background()) throw NoWindowsException(); - - connect(this->desktop(), SIGNAL(resized(int)), this, SLOT(resolution_change(int))); - connect(this->desktop(), SIGNAL(workAreaResized(int)), this, SLOT(work_area_change(int))); + + this->setup_slots(); } ImageViewerApplication::~ImageViewerApplication(){ @@ -123,147 +105,160 @@ void ImageViewerApplication::release_directory(std::shared_ptrshortcuts.reset_settings(); -} - -DEFINE_SETTING_STRING(clamp_strength); -DEFINE_SETTING_STRING(clamp_to_edges); -DEFINE_SETTING_STRING(use_checkerboard_pattern); -DEFINE_SETTING_STRING(last_state); -DEFINE_SETTING_STRING(windows); -DEFINE_SETTING_STRING(window); -DEFINE_SETTING_STRING(center_when_displayed); -DEFINE_SETTING_STRING(zoom_mode_for_new_windows); -DEFINE_SETTING_STRING(fullscreen_zoom_mode_for_new_windows); -DEFINE_SETTING_STRING(shortcuts); -DEFINE_SETTING_STRING(keep_application_in_background); - -#define SAVE_SETTING(x) tree.set_value(#x, this->x) - -void ImageViewerApplication::save_current_state(SettingsTree &tree){ - auto last_state = tree.create_tree(); - this->save_current_windows(*last_state); - tree.add_tree(last_state_setting, last_state); -} - -void ImageViewerApplication::save_current_windows(SettingsTree &tree){ - auto windows = tree.create_array(); - int i = 0; +void ImageViewerApplication::save_current_state(std::shared_ptr &state){ + state = std::make_shared(); + this->save_current_windows(state->get_windows()); +} + +void ImageViewerApplication::save_current_windows(std::vector> &windows){ for (auto &w : this->windows) - windows->push_back(w.second->save_state()); - tree.add_tree(windows_setting, windows); + windows.push_back(w.second->save_state()); } +class SettingsException : public GenericException{ +public: + SettingsException(const char *what) : GenericException(what){} +}; + +class DeserializationException : public std::exception { +protected: + const char *message; +public: + DeserializationException(DeserializerStream::ErrorType type){ + switch (type){ + case DeserializerStream::ErrorType::UnexpectedEndOfFile: + this->message = "Unexpected end of file."; + break; + case DeserializerStream::ErrorType::InconsistentSmartPointers: + this->message = "Serialized stream uses smart pointers inconsistently."; + break; + case DeserializerStream::ErrorType::UnknownObjectId: + this->message = "Serialized stream contains a reference to an unknown object."; + break; + case DeserializerStream::ErrorType::InvalidProgramState: + this->message = "The program is in an unknown state."; + break; + case DeserializerStream::ErrorType::MainObjectNotSerializable: + this->message = "The root object is not an instance of a Serializable subclass."; + break; + case DeserializerStream::ErrorType::AllocateAbstractObject: + this->message = "The stream contains a concrete object with an abstract class type ID."; + break; + default: + this->message = "Unknown."; + break; + } + } + virtual const char *what() const NOEXCEPT override { + return this->message; + } +}; + +class ImplementedDeserializerStream : public DeserializerStream { +protected: + void report_error(ErrorType type, const char *) override { + throw DeserializationException(type); + } +public: + ImplementedDeserializerStream(std::istream &stream) : DeserializerStream(stream){} +}; + void ImageViewerApplication::save_settings(bool with_state){ if (this->do_not_save) return; - SettingsTree tree; - SAVE_SETTING(clamp_strength); - SAVE_SETTING(clamp_to_edges); - SAVE_SETTING(use_checkerboard_pattern); - SAVE_SETTING(center_when_displayed); - SAVE_SETTING(zoom_mode_for_new_windows); - SAVE_SETTING(fullscreen_zoom_mode_for_new_windows); - SAVE_SETTING(keep_application_in_background); + QString path = this->get_config_filename(); + if (path.isNull()) + return; + Settings settings; + settings.main = this->settings; if (with_state) - this->save_current_state(tree); - tree.add_tree(shortcuts_setting, this->shortcuts.save_settings()); - this->settings.write(tree); - this->do_not_save = true; + this->save_current_state(settings.state); + settings.shortcuts = this->shortcuts.save_settings(); + + QFile file(path); + file.open(QFile::WriteOnly | QFile::Truncate); + if (!file.isOpen()) + return; + boost::iostreams::stream stream(&file); + SerializerStream ss(stream); + ss.serialize(settings, true); } -void ImageViewerApplication::restore_current_state(const SettingsTree &tree){ - auto subtree = tree.get_array(windows_setting); - if (subtree) - this->restore_current_windows(*subtree); +void ImageViewerApplication::restore_current_state(const ApplicationState &windows_state){ + this->restore_current_windows(windows_state.get_windows()); } -void ImageViewerApplication::restore_current_windows(const SettingsArray &tree){ +void ImageViewerApplication::restore_current_windows(const std::vector> &window_states){ this->windows.clear(); - tree.iterate([this](int, const SettingsItem &item){ - if (!item.is_value() && !item.is_array()) - this->add_window(sharedp_t(new MainWindow(*this, static_cast(item)))); - }); + for (auto &state : window_states) + this->add_window(std::make_shared(*this, state)); } std::shared_ptr ImageViewerApplication::build_context_menu(MainWindow *caller){ this->context_menu_last_requester = caller; std::shared_ptr ret(new QMenu); auto initial = ret->actions().size(); - caller->build_context_menu(*ret); - if (ret->actions().size() != initial) - ret->addSeparator(); + if (caller){ + caller->build_context_menu(*ret, this->get_lua_submenu(caller)); + if (ret->actions().size() != initial) + ret->addSeparator(); + } + auto receiver = caller ? (QObject *)caller : (QObject *)this; ret->addAction("Options...", this, SLOT(show_options()), this->shortcuts.get_current_sequence(show_options_command)); - ret->addAction("Quit", this, SLOT(quit_slot()), this->shortcuts.get_current_sequence(quit_command)); + ret->addAction("Quit", receiver, SLOT(quit_slot()), this->shortcuts.get_current_sequence(quit_command)); return ret; } -OptionsPack ImageViewerApplication::get_option_values() const{ - OptionsPack ret; - ret.center_images = this->center_when_displayed; - ret.use_checkerboard = this->use_checkerboard_pattern; - ret.clamp_to_edges = this->clamp_to_edges; - ret.keep_in_background = this->keep_application_in_background; - ret.clamp_strength = this->clamp_strength; - ret.windowed_zoom_mode = this->zoom_mode_for_new_windows; - ret.fullscreen_zoom_mode = this->fullscreen_zoom_mode_for_new_windows; - return ret; -} - -void ImageViewerApplication::set_option_values(const OptionsPack &options){ - this->center_when_displayed = options.center_images; - this->use_checkerboard_pattern = options.use_checkerboard; - this->clamp_to_edges = options.clamp_to_edges; - this->keep_application_in_background = options.keep_in_background; - this->clamp_strength = options.clamp_strength; - this->zoom_mode_for_new_windows = options.windowed_zoom_mode; - this->fullscreen_zoom_mode_for_new_windows = options.fullscreen_zoom_mode; - - this->setQuitOnLastWindowClosed(!this->keep_application_in_background); +void ImageViewerApplication::set_option_values(MainSettings &settings){ + *this->settings = settings; + this->setQuitOnLastWindowClosed(!this->settings->get_keep_application_in_background()); } void ImageViewerApplication::show_options(){ OptionsDialog dialog(*this); dialog.exec(); + this->reset_tray_menu(); + this->conditional_tray_show(); } void ImageViewerApplication::quit_and_discard_state(){ this->save_settings(false); + this->do_not_save = true; this->quit(); } -#define RESTORE_SETTING(key) tree->get_value(this->key, key##_setting) - -void ImageViewerApplication::restore_settings(){ - auto tree = this->settings.read(); - if (!tree) - return; - RESTORE_SETTING(clamp_strength); - RESTORE_SETTING(clamp_to_edges); - RESTORE_SETTING(use_checkerboard_pattern); - RESTORE_SETTING(keep_application_in_background); - RESTORE_SETTING(center_when_displayed); - RESTORE_SETTING(zoom_mode_for_new_windows); - RESTORE_SETTING(fullscreen_zoom_mode_for_new_windows); - - std::shared_ptr subtree; +bool ImageViewerApplication::restore_settings(){ + QString path = this->get_config_filename(); + if (path.isNull()) + return false; + QFile file(path); + file.open(QFile::ReadOnly); + if (!file.isOpen()) + return false; + boost::iostreams::stream stream(&file); + ImplementedDeserializerStream ds(stream); + std::shared_ptr settings; + try{ + settings.reset(ds.deserialize(true)); + }catch (std::bad_cast &){ + return false; + }catch (DeserializationException &ex){ + QMessageBox msgbox; + msgbox.setWindowTitle("Error reading configuration"); + msgbox.setText(ex.what()); + msgbox.setIcon(QMessageBox::Critical); + msgbox.exec(); + return false; + } + this->settings = settings->main; - subtree = tree->get_tree(shortcuts_setting); - if (subtree) - this->shortcuts.restore_settings(*subtree); + if (settings->shortcuts) + this->shortcuts.restore_settings(*settings->shortcuts); - subtree = tree->get_tree(last_state_setting); - if (subtree) - this->restore_current_state(*subtree); + if (settings->state) + this->restore_current_state(*settings->state); + return true; } void ImageViewerApplication::resolution_change(int screen){ @@ -289,4 +284,126 @@ void ImageViewerApplication::options_changed(const std::vector & void ImageViewerApplication::propagate_shortcuts(){ for (auto &w : this->windows) w.second->setup_shortcuts(); -} \ No newline at end of file +} + +QString ImageViewerApplication::get_config_location(){ + auto &ret = this->config_location; + if (ret.isNull()){ + auto list = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + if (!list.size()) + return QString::null; + ret = list[0]; + int index = ret.lastIndexOf('/'); + if (index < 0) + index = ret.lastIndexOf('\\'); + ret = ret.mid(0, index); + auto c = QDir::separator(); + ret += c; + ret += "BorderlessImageViewer"; + ret += c; + QDir dir(ret); + if (!dir.mkpath(ret)) + return ret = QString::null; + } + return ret; +} + +QString ImageViewerApplication::get_config_filename(){ + auto &ret = this->config_filename; + if (ret.isNull()){ + ret = this->get_config_location(); + if (ret.isNull()) + return ret; + ret += "settings.dat"; + } + return ret; +} + +QString ImageViewerApplication::get_user_filters_location(){ + auto &ret = this->user_filters_location; + if (ret.isNull()){ + ret = this->get_config_location(); + if (ret.isNull()) + return ret; + ret += "filters"; + ret += QDir::separator(); + QDir dir(ret); + if (!dir.mkpath(ret)) + return ret = QString::null; + } + return ret; +} + +QStringList ImageViewerApplication::get_user_filter_list(){ + QStringList ret; + + auto user_filters_location = this->get_user_filters_location(); + if (user_filters_location.isNull()) + return ret; + + QDir directory(user_filters_location); + directory.setFilter(QDir::Files | QDir::Hidden); + directory.setSorting(QDir::Name); + QStringList filters; + filters << "*.lua"; + for (auto i = accepted_cpp_extensions_size; i--;) + filters << QString("*.") + accepted_cpp_extensions[i]; + directory.setNameFilters(filters); + return directory.entryList(); +} + +QMenu &ImageViewerApplication::get_lua_submenu(MainWindow *){ + this->lua_submenu.clear(); + this->lua_submenu.setTitle("User filters"); + auto list = this->get_user_filter_list(); + if (list.isEmpty()){ + this->lua_submenu.addAction("(None)"); + this->lua_submenu.actions()[0]->setEnabled(false); + }else + for (auto &i : list){ + //this->lua_submenu.addAction("Quit", caller, SLOT(user_script_slot())); + this->lua_submenu.addAction(i); + } + return this->lua_submenu; +} + +void ImageViewerApplication::lua_script_activated(QAction *action){ + try{ + this->context_menu_last_requester->process_user_script(this->get_user_filters_location() + action->text()); + }catch (std::exception &e){ + QMessageBox msgbox; + msgbox.setWindowTitle("Error"); + QString text = "Error executing user script \""; + text += action->text(); + text += "\": "; + text += e.what(); + msgbox.setText(text); + msgbox.setIcon(QMessageBox::Critical); + msgbox.exec(); + } +} + +PluginCoreState &ImageViewerApplication::get_plugin_core_state(){ + if (!this->plugin_core_state) + this->plugin_core_state.reset(new PluginCoreState); + return *this->plugin_core_state; +} + +void ImageViewerApplication::setup_slots(){ + connect(this->desktop(), SIGNAL(resized(int)), this, SLOT(resolution_change(int))); + connect(this->desktop(), SIGNAL(workAreaResized(int)), this, SLOT(work_area_change(int))); + connect(&this->lua_submenu, SIGNAL(triggered(QAction *)), this, SLOT(lua_script_activated(QAction *))); +} + +void ImageViewerApplication::reset_tray_menu(){ + this->last_tray_context_menu = this->build_context_menu(); + this->tray_icon.setContextMenu(this->last_tray_context_menu.get()); + this->tray_context_menu.swap(this->last_tray_context_menu); +} + +void ImageViewerApplication::conditional_tray_show(){ + if (this->settings->get_keep_application_in_background()) + this->tray_icon.show(); + else + this->tray_icon.hide(); +} diff --git a/src/ImageViewerApplication.h b/src/ImageViewerApplication.h index 6a27360..607ba10 100644 --- a/src/ImageViewerApplication.h +++ b/src/ImageViewerApplication.h @@ -1,83 +1,29 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef IMAGEVIEWERAPPLICATION_H #define IMAGEVIEWERAPPLICATION_H #include "SingleInstanceApplication.h" -#include "Settings.h" +#include "serialization/settings.generated.h" +#include "plugin-core/PluginCoreState.h" #include "Shortcuts.h" +#include "Streams.h" +#include "Enums.h" #include #include #include +#include class QAction; +struct lua_State; class NoWindowsException : public std::exception{}; -enum class ZoomMode{ - Normal = 0, - Locked = 1, - Automatic = 2, - AutoFit = Automatic | 0, - AutoFill = Automatic | 1, -}; - -struct OptionsPack{ - bool center_images, - use_checkerboard, - clamp_to_edges, - keep_in_background; - int clamp_strength; - ZoomMode windowed_zoom_mode, - fullscreen_zoom_mode; - bool operator==(const OptionsPack &b) const{ - if (this->center_images != b.center_images) - return false; - if (this->use_checkerboard != b.use_checkerboard) - return false; - if (this->clamp_to_edges != b.clamp_to_edges) - return false; - if (this->clamp_strength != b.clamp_strength) - return false; - if (this->windowed_zoom_mode != b.windowed_zoom_mode) - return false; - if (this->fullscreen_zoom_mode != b.fullscreen_zoom_mode) - return false; - if (this->keep_in_background != b.keep_in_background) - return false; - return true; - } - bool operator!=(const OptionsPack &b) const{ - return !(*this == b); - } -}; - class ImageViewerApplication : public SingleInstanceApplication { Q_OBJECT @@ -89,71 +35,87 @@ class ImageViewerApplication : public SingleInstanceApplication std::vector > actions; ApplicationShortcuts shortcuts; MainWindow *context_menu_last_requester; - - Settings settings; - DEFINE_SETTING(int, clamp_strength, 25); - DEFINE_SETTING(bool, clamp_to_edges, true); - DEFINE_SETTING(bool, use_checkerboard_pattern, true); - DEFINE_SETTING(bool, center_when_displayed, true); - DEFINE_SETTING(bool, keep_application_in_background, true); - DEFINE_SETTING2(ZoomMode, zoom_mode_for_new_windows); - DEFINE_SETTING2(ZoomMode, fullscreen_zoom_mode_for_new_windows); - - void save_current_state(SettingsTree &tree); - void save_current_windows(SettingsTree &tree); - void restore_current_state(const SettingsTree &tree); - void restore_current_windows(const SettingsArray &tree); + QString config_location, + config_filename, + user_filters_location; + + std::shared_ptr settings; + + QMenu lua_submenu; + std::unique_ptr plugin_core_state; + QSystemTrayIcon tray_icon; + std::shared_ptr tray_context_menu, + last_tray_context_menu; + + void save_current_state(std::shared_ptr &); + void save_current_windows(std::vector> &); + void restore_current_state(const ApplicationState &); + void restore_current_windows(const std::vector> &); void propagate_shortcuts(); + QMenu &get_lua_submenu(MainWindow *caller); + QString get_config_location(); + QString get_config_filename(); + QString get_user_filters_location(); + QStringList get_user_filter_list(); + void setup_slots(); + void reset_tray_menu(); + void conditional_tray_show(); protected: void new_instance(const QStringList &args) override; void add_window(sharedp_t window); public: - ImageViewerApplication(int argc, char **argv, const QString &unique_name); + ImageViewerApplication(int &argc, char **argv, const QString &unique_name); ~ImageViewerApplication(); std::shared_ptr request_directory(const QString &path); void release_directory(std::shared_ptr); bool get_clamp_to_edges() const{ - return this->clamp_to_edges; + return this->settings->get_clamp_to_edges(); } int get_clamp_strength() const{ - return this->clamp_strength; + return this->settings->get_clamp_strength(); } bool get_use_checkerboard_pattern() const{ - return this->use_checkerboard_pattern; + return this->settings->get_use_checkerboard_pattern(); } - void reset_settings(); void save_settings(bool with_state = true); - void restore_settings(); + bool restore_settings(); void quit_and_discard_state(); bool toggle_center_when_displayed(){ - this->center_when_displayed = !this->center_when_displayed; - return this->center_when_displayed; + this->settings->set_center_when_displayed(!this->settings->get_center_when_displayed()); + return this->settings->get_center_when_displayed(); } bool get_center_when_displayed() const{ - return this->center_when_displayed; + return this->settings->get_center_when_displayed(); } ZoomMode get_zoom_mode_for_new_windows() const{ - return this->zoom_mode_for_new_windows; + return this->settings->get_zoom_mode_for_new_windows(); } ZoomMode get_fullscreen_zoom_mode_for_new_windows() const{ - return this->fullscreen_zoom_mode_for_new_windows; + return this->settings->get_fullscreen_zoom_mode_for_new_windows(); } void minimize_all(); const ApplicationShortcuts &get_shortcuts() const{ return this->shortcuts; } void options_changed(const std::vector &new_shortcuts); - std::shared_ptr build_context_menu(MainWindow *caller); - OptionsPack get_option_values() const; - void set_option_values(const OptionsPack &); + std::shared_ptr build_context_menu(MainWindow *caller = nullptr); + std::shared_ptr get_option_values() const{ + return this->settings; + } + void set_option_values(MainSettings &settings); + PluginCoreState &get_plugin_core_state(); public slots: void window_closing(MainWindow *); void show_options(); void resolution_change(int screen); void work_area_change(int screen); + void lua_script_activated(QAction *action); + void quit_slot(){ + this->quit(); + } }; #endif // IMAGEVIEWERAPPLICATION_H diff --git a/src/ImageViewport.cpp b/src/ImageViewport.cpp index de46267..0a31218 100644 --- a/src/ImageViewport.cpp +++ b/src/ImageViewport.cpp @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "ImageViewport.h" @@ -31,8 +10,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -DEFINE_SETTING_STRING(transform); - ImageViewport::ImageViewport(QWidget *parent) : QLabel(parent), zoom(1){ @@ -61,7 +38,7 @@ QMatrix translate(const QMatrix &m, const QPointF &offset){ return QMatrix(m.m11(), m.m12(), m.m21(), m.m22(), m.dx() + offset.x(), m.dy() + offset.y()); } -void ImageViewport::paintEvent(QPaintEvent *ev){ +void ImageViewport::paintEvent(QPaintEvent *){ QPainter painter(this); painter.setRenderHint(or_flags(QPainter::SmoothPixmapTransform, QPainter::Antialiasing)); painter.setClipping(false); @@ -71,19 +48,18 @@ void ImageViewport::paintEvent(QPaintEvent *ev){ auto offset = src_quad.move_to_origin(); transform = translate(transform, offset); painter.setMatrix(transform); - auto temp = painter.clipRegion().boundingRect(); if (this->pixmap()) painter.drawPixmap(QRect(QPoint(0, 0), this->image_size), *this->pixmap()); else if (this->movie()) painter.drawPixmap(QRect(QPoint(0, 0), this->image_size), this->movie()->currentPixmap()); } -void ImageViewport::save_state(SettingsTree &tree){ - tree.set_value(transform_setting, this->transform); +void ImageViewport::save_state(WindowState &state) const{ + state.set_transform(this->transform); } -void ImageViewport::load_state(const SettingsTree &tree){ - tree.get_value(this->transform, transform_setting); +void ImageViewport::load_state(const WindowState &state){ + this->transform = state.get_transform().to_QMatrix(); this->transform_changed(); } diff --git a/src/ImageViewport.h b/src/ImageViewport.h index 16861a6..df0f372 100644 --- a/src/ImageViewport.h +++ b/src/ImageViewport.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef IMAGEVIEWPORT_H @@ -33,7 +12,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "Quadrangular.h" -#include "Settings.h" +#include "serialization/settings.generated.h" class LoadedGraphics; @@ -93,8 +72,8 @@ class ImageViewport : public QLabel void set_transform(const QMatrix &); void flip(bool hor); - void save_state(SettingsTree &tree); - void load_state(const SettingsTree &tree); + void save_state(WindowState &) const; + void load_state(const WindowState &); void paintEvent(QPaintEvent *) override; void set_image(LoadedGraphics &li); diff --git a/src/LoadedImage.cpp b/src/LoadedImage.cpp index 53e896d..4d7bae6 100644 --- a/src/LoadedImage.cpp +++ b/src/LoadedImage.cpp @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "LoadedImage.h" @@ -33,7 +12,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. LoadedImage::LoadedImage(const QString &path){ QImage img(path); - if (this->null = img.isNull()) + if ((this->null = img.isNull())) return; this->compute_average_color(img); this->image = QtConcurrent::run([](QImage img){ return QPixmap::fromImage(img); }, img); @@ -41,6 +20,13 @@ LoadedImage::LoadedImage(const QString &path){ this->alpha = img.hasAlphaChannel(); } +LoadedImage::LoadedImage(const QImage &image){ + this->compute_average_color(image); + this->image = QtConcurrent::run([](QImage img){ return QPixmap::fromImage(img); }, image); + this->size = image.size(); + this->alpha = image.hasAlphaChannel(); +} + LoadedImage::~LoadedImage(){ this->background_color.cancel(); } @@ -87,10 +73,14 @@ void LoadedImage::assign_to_QLabel(QLabel &label){ label.setPixmap(this->image); } +QImage LoadedImage::get_QImage() const{ + return ((QPixmap)this->image).toImage(); +} + LoadedAnimation::LoadedAnimation(const QString &path): animation(path){ this->null = !this->animation.isValid(); if (!this->null){ - bool ok = this->animation.jumpToNextFrame(); + (void)this->animation.jumpToNextFrame(); this->size = this->animation.currentPixmap().size(); this->alpha = true; } @@ -101,6 +91,10 @@ void LoadedAnimation::assign_to_QLabel(QLabel &label){ this->animation.start(); } +QImage LoadedAnimation::get_QImage() const{ + return this->animation.currentImage(); +} + std::shared_ptr LoadedGraphics::create(const QString &path){ if (path.endsWith(".gif", Qt::CaseInsensitive)) return std::shared_ptr(new LoadedAnimation(path)); diff --git a/src/LoadedImage.h b/src/LoadedImage.h index d51fa14..ef3c751 100644 --- a/src/LoadedImage.h +++ b/src/LoadedImage.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef LOADEDIMAGE_H @@ -56,6 +35,7 @@ class LoadedGraphics{ return this->alpha; } virtual void assign_to_QLabel(QLabel &) = 0; + virtual QImage get_QImage() const = 0; static std::shared_ptr create(const QString &path); }; @@ -66,6 +46,7 @@ class LoadedImage : public LoadedGraphics{ void compute_average_color(QImage); public: LoadedImage(const QString &path); + LoadedImage(const QImage &image); ~LoadedImage(); QColor get_background_color() override{ return this->background_color.result(); @@ -74,6 +55,7 @@ class LoadedImage : public LoadedGraphics{ return false; } void assign_to_QLabel(QLabel &) override; + QImage get_QImage() const override; }; class LoadedAnimation : public LoadedGraphics{ @@ -88,6 +70,7 @@ class LoadedAnimation : public LoadedGraphics{ return true; } void assign_to_QLabel(QLabel &) override; + QImage get_QImage() const override; }; #endif // LOADEDIMAGE_H diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 71950a1..b1619d5 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -1,33 +1,12 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "MainWindow.h" -#include "ui_mainwindow.h" +#include "ui_MainWindow.h" #include "Misc.h" #include "RotateDialog.h" #include @@ -37,9 +16,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - -const ZoomMode MainWindow::default_zoom_mode = ZoomMode::Normal; -const ZoomMode MainWindow::default_fullscreen_zoom_mode = ZoomMode::AutoFit; +#include "plugin-core/PluginCoreState.h" +#include "GenericException.h" MainWindow::MainWindow(ImageViewerApplication &app, const QStringList &arguments, QWidget *parent): QMainWindow(parent), @@ -47,15 +25,15 @@ MainWindow::MainWindow(ImageViewerApplication &app, const QStringList &arguments app(&app){ this->init(); if (arguments.size() >= 2) - this->display_image(arguments[1]); + this->open_path_and_display_image(arguments[1]); } -MainWindow::MainWindow(ImageViewerApplication &app, const SettingsTree &tree, QWidget *parent): +MainWindow::MainWindow(ImageViewerApplication &app, const std::shared_ptr &state, QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), app(&app){ this->init(); - this->restore_state(tree); + this->restore_state(state); this->set_background(); } @@ -64,11 +42,14 @@ MainWindow::~MainWindow(){ } void MainWindow::init(){ + if (!this->window_state) + this->window_state = std::make_shared(); this->moving_forward = true; this->not_moved = false; - this->fullscreen_zoom = this->zoom = 1; + this->window_state->set_zoom(1); + this->window_state->set_fullscreen_zoom(1); this->color_calculated = false; - this->fullscreen = false; + this->window_state->set_fullscreen(false); this->ui->setupUi(this); this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); this->reset_settings(); @@ -84,28 +65,43 @@ void MainWindow::init(){ void MainWindow::set_desktop_size(int screen){ this->desktop_size = this->app->desktop()->availableGeometry(screen); + this->desktop_size.setHeight(this->desktop_size.height()); this->screen_size = this->app->desktop()->screenGeometry(screen); } -QPoint MainWindow::get_image_pos() const{ - return this->ui->label->pos(); +void MainWindow::save_image_pos(bool force){ + if (this->window_state->get_fullscreen() && !force) + return; + auto p = this->ui->label->pos(); + qDebug() << "Saving image position at " << p; + this->image_pos = p; +} + +void MainWindow::restore_image_pos(){ + QPoint p; + if (this->image_pos){ + p = *this->image_pos; + qDebug() << "Restoring image position: " << p; + }else{ + qDebug() << "Saved image position in unset state. Restoring to " << p; + } + this->ui->label->move(p); } -void MainWindow::set_image_pos(const QPoint &p){ - this->ui->label->move(p); - if (!this->fullscreen) - this->image_pos = p; +void MainWindow::clear_image_pos(){ + qDebug() << "Clearing image position."; + this->image_pos.clear(); } void MainWindow::set_zoom(){ auto ds = this->desktop_size.size(); - if (this->fullscreen) + if (this->window_state->get_fullscreen()) ds = this->screen_size.size(); auto ps = this->displayed_image->get_size(); this->ui->label->compute_size_no_zoom(ps); double dr = (double)ds.width() / (double)ds.height(); double pr = (double)ps.width() / (double)ps.height(); - auto &zoom = this->get_current_zoom(); + auto zoom = this->get_current_zoom(); switch (this->get_current_zoom_mode()){ case ZoomMode::Normal: zoom = 1; @@ -125,33 +121,40 @@ void MainWindow::set_zoom(){ zoom = (double)ds.height() / (double)ps.height(); break; } + this->set_current_zoom(zoom); } void MainWindow::apply_zoom(bool first_display, double old_zoom){ auto label_pos = this->ui->label->pos(); + qDebug() << "MainWindow::apply_zoom(): label_pos = " << label_pos; auto center = to_QPoint(this->size()) / 2; + qDebug() << "MainWindow::apply_zoom(): center = " << center; auto center_at = center - label_pos; + qDebug() << "MainWindow::apply_zoom(): center_at = " << center_at; auto zoom = this->get_current_zoom(); + qDebug() << "MainWindow::apply_zoom(): zoom = " << zoom; - this->display_image(this->displayed_image); + this->display_image_in_label(this->displayed_image, first_display); - auto new_location = center - center_at * (zoom / old_zoom); + if (zoom != 1){ + auto new_location = center - center_at * (zoom / old_zoom); + qDebug() << "MainWindow::apply_zoom(): center - center_at * (zoom / old_zoom) = " + << center << " - " << center_at << " * (" << zoom << " / " << old_zoom << ") = " << new_location; - if (first_display){ - if (!this->app->get_center_when_displayed()){ + if (first_display && !this->app->get_center_when_displayed()){ if (new_location.x() < 0) new_location.setX(0); if (new_location.y() < 0) new_location.setY(0); } - } - this->move_image(new_location); + this->move_image(new_location); + } } void MainWindow::change_zoom(bool in){ - auto &zoom = this->get_current_zoom(); + auto zoom = this->get_current_zoom(); auto old_zoom = zoom; #if 0 if (in) @@ -163,9 +166,10 @@ void MainWindow::change_zoom(bool in){ #else zoom *= in ? 1.25 : (1.0 / 1.25); #endif + this->set_current_zoom(zoom); this->apply_zoom(false, old_zoom); if (this->current_zoom_mode_is_auto()) - this->get_current_zoom_mode() = ZoomMode::Normal; + this->set_current_zoom_mode(ZoomMode::Normal); } void MainWindow::setup_backgrounds(){ @@ -174,7 +178,7 @@ void MainWindow::setup_backgrounds(){ QPalette palette = widget->palette(); QImage alpha(":/alpha.png"); if (alpha.isNull()) - throw std::exception("Resource not found: \"alpha.png\""); + throw GenericException("Resource not found: \"alpha.png\""); palette.setBrush(QPalette::Window, QBrush(alpha)); widget->setPalette(palette); } @@ -192,19 +196,18 @@ void MainWindow::set_solid(const QColor &col){ } void MainWindow::set_background(bool force){ - bool b = this->use_checkerboard_pattern; - if (this->using_checkerboard_pattern == b && !force) + if (!this->window_state->get_using_checkerboard_pattern_updated() && !force) return; - if (!b) - this->set_solid(this->displayed_image->get_background_color()); QWidget *p1 = this->ui->checkerboard; QWidget *p2 = this->ui->solid; - if (!b) + if (!this->window_state->get_using_checkerboard_pattern()){ + this->set_solid(this->displayed_image->get_background_color()); std::swap(p1, p2); + } p1->show(); p2->hide(); - this->using_checkerboard_pattern = b; + this->window_state->set_using_checkerboard_pattern_updated(false); } void MainWindow::set_background_sizes(){ @@ -224,7 +227,7 @@ void MainWindow::show_nothing(){ this->set_solid(Qt::black); this->resize(800, 600); this->ui->label->resize(this->size()); - this->border_size = this->default_border_size; + this->window_state->reset_border_size(); } void MainWindow::resize_to_max(){ @@ -253,19 +256,29 @@ void MainWindow::advance(){ } void MainWindow::set_iterator(){ - this->directory_iterator->advance_to(this->current_filename); + this->directory_iterator->advance_to(QString::fromStdWString(this->window_state->get_current_filename())); +} + +double MainWindow::get_current_zoom() const{ + return !this->window_state->get_fullscreen() ? this->window_state->get_zoom() : this->window_state->get_fullscreen_zoom(); } -double &MainWindow::get_current_zoom(){ - return !this->fullscreen ? this->zoom : this->fullscreen_zoom; +void MainWindow::set_current_zoom(double value){ + if (this->window_state->get_fullscreen()) + this->window_state->set_fullscreen_zoom(value); + else + this->window_state->set_zoom(value); } -ZoomMode &MainWindow::get_current_zoom_mode(){ - return const_cast(const_cast(this)->get_current_zoom_mode()); +void MainWindow::set_current_zoom_mode(const ZoomMode &mode){ + if (!this->window_state->get_fullscreen()) + this->window_state->set_zoom_mode(mode); + else + this->window_state->set_fullscreen_zoom_mode(mode); } -const ZoomMode &MainWindow::get_current_zoom_mode() const{ - return !this->fullscreen ? this->zoom_mode : this->fullscreen_zoom_mode; +ZoomMode MainWindow::get_current_zoom_mode() const{ + return !this->window_state->get_fullscreen() ? this->window_state->get_zoom_mode() : this->window_state->get_fullscreen_zoom_mode(); } void MainWindow::move_in_direction(bool forward){ @@ -273,14 +286,15 @@ void MainWindow::move_in_direction(bool forward){ return; this->set_iterator(); this->moving_forward = forward; - size_t i = this->directory_iterator->pos(); + auto old_pos = this->directory_iterator->pos(); this->advance(); - if (this->directory_iterator->pos() == i) + if (this->directory_iterator->pos() == old_pos) return; - this->display_image(**this->directory_iterator); + this->clear_image_pos(); + this->open_path_and_display_image(**this->directory_iterator); } -void MainWindow::display_image(QString path){ +void MainWindow::open_path_and_display_image(QString path){ std::shared_ptr li; size_t i = 0; auto &label = this->ui->label; @@ -305,33 +319,39 @@ void MainWindow::display_image(QString path){ } this->color_calculated = false; label->move(0, 0); - split_path(this->current_directory, this->current_filename, path); - this->setWindowTitle(this->current_filename); + QString current_directory, + current_filename; + split_path(current_directory, current_filename, path); + this->window_state->set_current_directory(current_directory.toStdWString()); + this->window_state->set_current_filename(current_filename.toStdWString()); + this->setWindowTitle(current_filename); if (!this->directory_iterator) - this->directory_iterator = this->app->request_directory(this->current_directory); + this->directory_iterator = this->app->request_directory(current_directory); this->displayed_image = li; label->reset_transform(); this->set_zoom(); - if (this->get_current_zoom() != 1) - this->apply_zoom(true, 1); - else - this->display_image(li); + this->apply_zoom(true, 1); +} + +void MainWindow::display_filtered_image(const std::shared_ptr &graphics){ + this->displayed_image = graphics; + this->display_image_in_label(graphics, false); } -void MainWindow::display_image(std::shared_ptr graphics){ +void MainWindow::display_image_in_label(const std::shared_ptr &graphics, bool first_display){ auto zoom = this->get_current_zoom(); auto &label = this->ui->label; label->set_image(*graphics); - //label->setPixmap(pixmap); label->set_zoom(zoom); auto size = label->get_size(); int mindim = std::min(size.width(), size.height()); - if (mindim < this->default_border_size * 3) - this->border_size = mindim / 3; - else - this->border_size = this->default_border_size; + this->window_state->set_border_size( + (std::uint32_t)mindim < this->window_state->default_border_size * 3 ? + mindim / 3 : + this->window_state->default_border_size + ); label->resize(size); if (!this->color_calculated && this->displayed_image->has_alpha()){ @@ -341,6 +361,13 @@ void MainWindow::display_image(std::shared_ptr graphics){ this->reposition_window(); this->set_background_sizes(); + + if (first_display && this->app->get_center_when_displayed()){ + auto label_size = label->size(); + auto window_size = this->size(); + auto new_label_position = (window_size - label_size) / 2; + this->move_image(to_QPoint(new_label_position)); + } } void MainWindow::show_rotate_dialog(){ @@ -352,9 +379,10 @@ void MainWindow::show_context_menu(QMouseEvent *ev){ this->app->postEvent(this, new QContextMenuEvent(QContextMenuEvent::Other, ev->screenPos().toPoint())); } -void MainWindow::build_context_menu(QMenu &menu){ - menu.addAction("Transform...", this, SLOT(show_rotate_dialog())); - menu.addAction("Close", this, SLOT(close_slot()), this->app->get_shortcuts().get_current_sequence(close_command)); +void MainWindow::build_context_menu(QMenu &main_menu, QMenu &lua_submenu){ + main_menu.addAction("Transform...", this, SLOT(show_rotate_dialog())); + main_menu.addMenu(&lua_submenu); + main_menu.addAction("Close", this, SLOT(close_slot()), this->app->get_shortcuts().get_current_sequence(close_command)); } //void MainWindow::keyReleaseEvent(QKeyEvent *ev){ @@ -434,20 +462,20 @@ void MainWindow::work_area_change(int screen){ void MainWindow::resize_window_rect(const QSize &s){ this->window_rect.setSize(s); - if (!this->fullscreen) + if (!this->window_state->get_fullscreen()) this->resize(s); } void MainWindow::move_window_rect(const QPoint &p){ this->window_rect.setX(p.x()); this->window_rect.setY(p.y()); - if (!this->fullscreen) + if (!this->window_state->get_fullscreen()) this->move(p); } void MainWindow::set_window_rect(const QRect &r){ this->window_rect = r; - if (!this->fullscreen) + if (!this->window_state->get_fullscreen()) this->setGeometry(r); } @@ -462,18 +490,29 @@ QMatrix MainWindow::get_image_transform() const{ double MainWindow::set_image_transform(const QMatrix &m){ this->ui->label->set_transform(m); this->fix_positions_and_zoom(); - return this->zoom; + return this->window_state->get_zoom(); } double MainWindow::get_image_zoom() const{ - return this->zoom; + return this->window_state->get_zoom(); } void MainWindow::set_image_zoom(double x){ - double &zoom = this->get_current_zoom(); - double last = zoom; - zoom = x; + //double &zoom = this->get_current_zoom(); + double last = this->get_current_zoom(); + this->set_current_zoom(x); this->apply_zoom(false, last); - this->ui->label->set_zoom(this->zoom = x); - this->get_current_zoom_mode() = ZoomMode::Normal; + this->window_state->set_zoom(x); + this->ui->label->set_zoom(x); + this->set_current_zoom_mode(ZoomMode::Normal); +} + +void MainWindow::process_user_script(const QString &path){ + auto &plugin_core_state = this->app->get_plugin_core_state(); + plugin_core_state.set_current_caller(this); + plugin_core_state.execute(path); +} + +QImage MainWindow::get_image() const{ + return this->displayed_image->get_QImage(); } diff --git a/src/MainWindow.h b/src/MainWindow.h index f2b6be0..c1bce0d 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef MAINWINDOW_H @@ -35,12 +14,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LoadedImage.h" #include "DirectoryListing.h" #include "ImageViewerApplication.h" -#include "Settings.h" -#include "Rational.h" #include #include #include #include +#include "Misc.h" namespace Ui { class MainWindow; @@ -56,22 +34,19 @@ class MainWindow : public QMainWindow{ window_rect; QPoint first_mouse_pos, first_window_pos, - first_label_pos, - image_pos; + first_label_pos; + Optional image_pos; QSize first_window_size; std::shared_ptr displayed_image; std::vector horizontal_clampers, vertical_clampers; - QString current_directory, - current_filename; + //QString current_directory, + // current_filename; std::shared_ptr directory_iterator; bool moving_forward; std::vector > shortcuts; bool not_moved; - double zoom, - fullscreen_zoom; bool color_calculated; - bool fullscreen; std::vector connections; enum class ResizeMode{ @@ -87,12 +62,7 @@ class MainWindow : public QMainWindow{ }; ResizeMode resize_mode; - DEFINE_SETTING(int, border_size, 50); - DEFINE_SETTING(int, movement_size, 100); - DEFINE_SETTING2(ZoomMode, zoom_mode); - DEFINE_SETTING2(ZoomMode, fullscreen_zoom_mode); - bool using_checkerboard_pattern; - bool use_checkerboard_pattern; + std::shared_ptr window_state; bool move_image(const QPoint &new_position); QPoint compute_movement(const QPoint &new_position); @@ -121,14 +91,16 @@ class MainWindow : public QMainWindow{ void offset_image(const QPoint &); void set_desktop_size(int screen = -1); void set_iterator(); - double &get_current_zoom(); - ZoomMode &get_current_zoom_mode(); - const ZoomMode &get_current_zoom_mode() const; + double get_current_zoom() const; + void set_current_zoom(double); + void set_current_zoom_mode(const ZoomMode &); + ZoomMode get_current_zoom_mode() const; void resolution_to_window_size(); void reposition_window(); void reposition_image(); - QPoint get_image_pos() const; - void set_image_pos(const QPoint &); + void save_image_pos(bool force = false); + void restore_image_pos(); + void clear_image_pos(); void rotate(bool right, bool fine = false); void fix_positions_and_zoom(); @@ -143,15 +115,16 @@ class MainWindow : public QMainWindow{ void closeEvent(QCloseEvent *event) override; void contextMenuEvent(QContextMenuEvent *) override; //bool event(QEvent *) override; - void display_image(std::shared_ptr); public: explicit MainWindow(ImageViewerApplication &app, const QStringList &arguments, QWidget *parent = 0); - explicit MainWindow(ImageViewerApplication &app, const SettingsTree &tree, QWidget *parent = 0); + explicit MainWindow(ImageViewerApplication &app, const std::shared_ptr &state, QWidget *parent = 0); ~MainWindow(); - void display_image(QString path); - std::shared_ptr save_state() const; - void restore_state(const SettingsTree &tree); + void open_path_and_display_image(QString path); + void display_image_in_label(const std::shared_ptr &graphics, bool first_display); + void display_filtered_image(const std::shared_ptr &); + std::shared_ptr save_state() const; + void restore_state(const std::shared_ptr &); bool is_null() const{ return !this->displayed_image || this->displayed_image->is_null(); } @@ -165,10 +138,12 @@ class MainWindow : public QMainWindow{ void set_image_zoom(double); double set_image_transform(const QMatrix &); void setup_shortcuts(); - void build_context_menu(QMenu &); + void build_context_menu(QMenu &main_menu, QMenu &lua_submenu); bool current_zoom_mode_is_auto() const{ return check_flag(this->get_current_zoom_mode(), ZoomMode::Automatic); } + void process_user_script(const QString &path); + QImage get_image() const; public slots: void label_transform_updated(); diff --git a/src/MainWindowMovement.cpp b/src/MainWindowMovement.cpp index 3d10de1..5b98e6c 100644 --- a/src/MainWindowMovement.cpp +++ b/src/MainWindowMovement.cpp @@ -1,33 +1,12 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "MainWindow.h" -#include "ui_mainwindow.h" +#include "ui_MainWindow.h" void set_flags(bool &left, bool &right, bool &middle, QMouseEvent *ev){ left = check_flag(ev->buttons(), Qt::LeftButton); @@ -104,7 +83,7 @@ void MainWindow::mouseMoveEvent(QMouseEvent *ev){ return; if (left){ - if (this->fullscreen) + if (this->window_state->get_fullscreen()) return; if (this->resize_mode == ResizeMode::None) this->move_window(this->first_window_pos + ev->globalPos() - this->first_mouse_pos); @@ -181,17 +160,18 @@ void MainWindow::compute_resize(QPoint &out_label_pos, QRect &out_window_rect, Q auto label_rect = this->ui->label->rect(); - if (rect.width() < this->border_size){ + auto border_size = this->window_state->get_border_size(); + if ((std::uint32_t)rect.width() < border_size){ if (right) - rect.setWidth(this->border_size); + rect.setWidth(border_size); else - rect.setLeft(rect.right() - this->border_size + 1); + rect.setLeft(rect.right() - border_size + 1); } - if (rect.height() < this->border_size){ + if ((std::uint32_t)rect.height() < border_size){ if (bottom) - rect.setHeight(this->border_size); + rect.setHeight(border_size); else - rect.setTop(rect.bottom() - this->border_size + 1); + rect.setTop(rect.bottom() - border_size + 1); } if (rect.width() > label_rect.width()){ @@ -312,7 +292,7 @@ QPoint MainWindow::compute_movement(const QPoint &_new_position){ void MainWindow::reposition_window(){ this->resize_to_max(); - if (this->fullscreen) + if (this->window_state->get_fullscreen()) this->resolution_to_window_size(); this->reposition_image(); } @@ -322,10 +302,10 @@ void MainWindow::reposition_image(){ } MainWindow::ResizeMode MainWindow::get_resize_mode(const QPoint &pos){ - if (this->fullscreen || this->current_zoom_mode_is_auto()) + if (this->window_state->get_fullscreen() || this->current_zoom_mode_is_auto()) return ResizeMode::None; - for (int border = this->border_size; border >= 0; border -= 5){ + for (int border = this->window_state->get_border_size(); border >= 0; border -= 5){ bool left = false, top = false, right = false, diff --git a/src/MainWindowSettings.cpp b/src/MainWindowSettings.cpp index 1c5d7c1..c69c87d 100644 --- a/src/MainWindowSettings.cpp +++ b/src/MainWindowSettings.cpp @@ -1,115 +1,47 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "MainWindow.h" -#include "ui_mainwindow.h" +#include "ui_MainWindow.h" #include -DEFINE_SETTING_STRING(using_checkerboard_pattern); -DEFINE_SETTING_STRING(current_directory); -DEFINE_SETTING_STRING(current_filename); -DEFINE_SETTING_STRING(movement_size); -DEFINE_SETTING_STRING(zoom_mode); -DEFINE_SETTING_STRING(pos); -DEFINE_SETTING_STRING(label_pos); -DEFINE_SETTING_STRING(size); -DEFINE_SETTING_STRING(zoom); -DEFINE_SETTING_STRING(fullscreen_zoom_mode); -DEFINE_SETTING_STRING(fullscreen); - -void MainWindow::restore_state(const SettingsTree &tree){ - QString current_directory, - current_filename; - QPoint pos, label_pos; - QSize size; - auto zoom = this->zoom; - auto zoom_mode = this->zoom_mode; - auto fullscreen_zoom_mode = this->fullscreen_zoom_mode; - int movement_size = this->movement_size; - bool using_checkerboard_pattern = this->using_checkerboard_pattern; - bool fullscreen = false; -#define RESTORE_SETTING(key) tree.get_value(key, key##_setting) - RESTORE_SETTING(using_checkerboard_pattern); - RESTORE_SETTING(current_directory); - RESTORE_SETTING(current_filename); - RESTORE_SETTING(movement_size); - RESTORE_SETTING(pos); - RESTORE_SETTING(label_pos); - RESTORE_SETTING(size); - RESTORE_SETTING(zoom); - RESTORE_SETTING(zoom_mode); - RESTORE_SETTING(fullscreen_zoom_mode); - RESTORE_SETTING(fullscreen); - - auto path = current_directory; +void MainWindow::restore_state(const std::shared_ptr &state){ + this->window_state = state; + this->window_state->set_using_checkerboard_pattern_updated(true); + auto path = QString::fromStdWString(this->window_state->get_current_directory()); path += QDir::separator(); - path += current_filename; - this->use_checkerboard_pattern = using_checkerboard_pattern; - this->using_checkerboard_pattern = !using_checkerboard_pattern; - - this->zoom = zoom; - this->zoom_mode = ZoomMode::Locked; - this->fullscreen = fullscreen; - this->display_image(path); - this->ui->label->load_state(tree); - this->zoom_mode = zoom_mode; - this->fullscreen_zoom_mode = fullscreen_zoom_mode; - - this->ui->label->move(label_pos); - this->move(pos); - this->resize(size); - this->movement_size = movement_size; + path += QString::fromStdWString(this->window_state->get_current_filename()); + auto temp_zoom_mode = this->window_state->get_zoom_mode(); + this->window_state->set_zoom_mode(ZoomMode::Locked); + this->open_path_and_display_image(path); + this->ui->label->load_state(*state); + this->window_state->set_zoom_mode(temp_zoom_mode); + + this->ui->label->move(this->window_state->get_label_pos().to_QPoint()); + this->move(this->window_state->get_pos().to_QPoint()); + this->resize(this->window_state->get_size().to_QSize()); this->fix_positions_and_zoom(); } -#define SAVE_SETTING(x) ret->set_value(#x, this->x) - -std::shared_ptr MainWindow::save_state() const{ - auto ret = SettingsTree::create_tree(); - ret->set_value(pos_setting, this->pos()); - ret->set_value(size_setting, this->size()); - ret->set_value(label_pos_setting, this->ui->label->pos()); - SAVE_SETTING(using_checkerboard_pattern); - SAVE_SETTING(current_directory); - SAVE_SETTING(current_filename); - SAVE_SETTING(zoom); - SAVE_SETTING(fullscreen); - ret->set_value(zoom_mode_setting, (int)this->zoom_mode); - ret->set_value(fullscreen_zoom_mode_setting, (int)this->fullscreen_zoom_mode); - SAVE_SETTING(movement_size); - this->ui->label->save_state(*ret); - return ret; +std::shared_ptr MainWindow::save_state() const{ + this->window_state->set_pos(this->pos()); + this->window_state->set_size(this->size()); + this->window_state->set_label_pos(this->ui->label->pos()); + this->ui->label->save_state(*this->window_state); + return this->window_state; } void MainWindow::reset_settings(){ - this->use_checkerboard_pattern = this->app->get_use_checkerboard_pattern(); - this->using_checkerboard_pattern = !this->use_checkerboard_pattern; - this->movement_size = this->default_movement_size; - this->zoom_mode = this->app->get_zoom_mode_for_new_windows(); - this->fullscreen_zoom_mode = this->app->get_fullscreen_zoom_mode_for_new_windows(); + auto &state = this->window_state; + if (!state) + state = std::make_shared(); + WindowState defaults; + state->set_using_checkerboard_pattern(this->app->get_use_checkerboard_pattern()); + state->set_movement_size(defaults.get_movement_size()); + state->set_zoom_mode(this->app->get_zoom_mode_for_new_windows()); + state->set_fullscreen_zoom_mode(this->app->get_fullscreen_zoom_mode_for_new_windows()); } diff --git a/src/MainWindowShortcuts.cpp b/src/MainWindowShortcuts.cpp index e9b4940..41e3f2d 100644 --- a/src/MainWindowShortcuts.cpp +++ b/src/MainWindowShortcuts.cpp @@ -1,33 +1,12 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "MainWindow.h" -#include "ui_mainwindow.h" +#include "ui_MainWindow.h" void MainWindow::setup_shortcuts(){ static struct Pair{ @@ -108,7 +87,7 @@ void MainWindow::back_slot(){ } void MainWindow::background_swap_slot(){ - this->use_checkerboard_pattern = !this->use_checkerboard_pattern; + this->window_state->flip_using_checkerboard_pattern(); this->set_background(); } @@ -125,19 +104,19 @@ void MainWindow::zoom_out_slot(){ } void MainWindow::up_slot(){ - this->offset_image(QPoint(0, this->movement_size)); + this->offset_image(QPoint(0, this->window_state->get_movement_size())); } void MainWindow::down_slot(){ - this->offset_image(QPoint(0, -this->movement_size)); + this->offset_image(QPoint(0, -this->window_state->get_movement_size())); } void MainWindow::left_slot(){ - this->offset_image(QPoint(this->movement_size, 0)); + this->offset_image(QPoint(this->window_state->get_movement_size(), 0)); } void MainWindow::right_slot(){ - this->offset_image(QPoint(-this->movement_size, 0)); + this->offset_image(QPoint(-this->window_state->get_movement_size(), 0)); } void MainWindow::up_big_slot(){ @@ -166,7 +145,7 @@ void MainWindow::offset_image(const QPoint &offset){ void MainWindow::reset_zoom_slot(){ int zoom = this->get_current_zoom(); - this->get_current_zoom_mode() = ZoomMode::Normal; + this->set_current_zoom_mode(ZoomMode::Normal); this->ui->label->reset_transform(); this->set_zoom(); this->apply_zoom(false, zoom); @@ -188,7 +167,9 @@ void cycle_zoom_mode(ZoomMode &mode){ } void MainWindow::cycle_zoom_mode_slot(){ - cycle_zoom_mode(this->get_current_zoom_mode()); + auto mode = this->get_current_zoom_mode(); + cycle_zoom_mode(mode); + this->set_current_zoom_mode(mode); auto zoom = this->get_current_zoom(); this->set_zoom(); this->apply_zoom(false, zoom); @@ -200,7 +181,9 @@ void toggle_lock_zoom(ZoomMode &mode){ } void MainWindow::toggle_lock_zoom_slot(){ - toggle_lock_zoom(this->zoom_mode); + auto mode = this->window_state->get_zoom_mode(); + toggle_lock_zoom(mode); + this->window_state->set_zoom_mode(mode); } void MainWindow::go_to_start(){ @@ -212,7 +195,7 @@ void MainWindow::go_to_start(){ if (this->directory_iterator->pos() == i) return; this->moving_forward = true; - this->display_image(**this->directory_iterator); + this->open_path_and_display_image(**this->directory_iterator); } void MainWindow::go_to_end(){ @@ -224,18 +207,18 @@ void MainWindow::go_to_end(){ if (this->directory_iterator->pos() == i) return; this->moving_forward = false; - this->display_image(**this->directory_iterator); + this->open_path_and_display_image(**this->directory_iterator); } void MainWindow::toggle_fullscreen(){ auto zoom = this->get_current_zoom(); - this->fullscreen = !this->fullscreen; - if (!this->fullscreen){ + this->window_state->set_fullscreen(!this->window_state->get_fullscreen()); + if (!this->window_state->get_fullscreen()){ this->apply_zoom(false, zoom); this->setGeometry(this->window_rect); - this->set_image_pos(this->image_pos); + this->restore_image_pos(); }else{ - this->image_pos = this->get_image_pos(); + this->save_image_pos(true); this->set_zoom(); this->apply_zoom(false, zoom); this->resolution_to_window_size(); diff --git a/src/Misc.h b/src/Misc.h index 39cfe6e..6d42df9 100644 --- a/src/Misc.h +++ b/src/Misc.h @@ -1,34 +1,14 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef MISC_H #define MISC_H +#include "GenericException.h" #include #include #include @@ -160,4 +140,65 @@ void set_max(T &a, const T &b){ a = std::max(a, b); } +class OptionalNotSetException : public GenericException{ +public: + OptionalNotSetException(): GenericException("Attempting to access the object of an uninitialized Optional."){} +}; + +template +class Optional{ + bool set; + T data; +public: + Optional(): set(false){} + Optional(const T &data): set(true), data(data){} + Optional(const Optional &existing): set(existing.set), data(existing.data){} + Optional(Optional &&existing): set(existing.set), data(existing.data){ + existing.clear(); + } + const Optional &operator=(const Optional &existing){ + this->set = existing.set; + this->data = existing.data; + return *this; + } + const Optional &operator=(Optional &&existing){ + this->set = existing.set; + this->data = existing.data; + existing.clear(); + return *this; + } + const Optional &operator=(const T &data){ + this->set = true; + this->data = data; + return *this; + } + const Optional &operator=(T &&data){ + this->set = true; + this->data = data; + return *this; + } + void clear(){ + this->set = false; + } + operator bool() const{ + return this->set; + } + T &operator*(){ + if (!*this) + throw OptionalNotSetException(); + return this->data; + } + const T &operator*() const{ + if (!*this) + throw OptionalNotSetException(); + return this->data; + } + T *operator->(){ + return &this->data; + } + const T *operator->() const{ + return &this->data; + } +}; + #endif // MISC_H diff --git a/src/OptionsDialog.cpp b/src/OptionsDialog.cpp index 5a4d7e5..382c8e2 100644 --- a/src/OptionsDialog.cpp +++ b/src/OptionsDialog.cpp @@ -1,34 +1,12 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "OptionsDialog.h" #include "ImageViewerApplication.h" -#include #include #include @@ -48,7 +26,7 @@ void ShortcutListModel::sort(){ // first <= x < y !f(x) and for all y <= z < last f(z), find_all() returns y, // or last if it does not exist. template -It find_all(It first, It last, F &f){ +It find_all(It first, It last, const F &f){ auto n = last - first; while (n > 0){ auto n2 = n / 2; @@ -121,11 +99,11 @@ void ShortcutListModel::replace_all(const std::vector &new_short } } -QModelIndex ShortcutListModel::index(int row, int column, const QModelIndex &parent) const{ +QModelIndex ShortcutListModel::index(int row, int column, const QModelIndex &) const{ return this->createIndex(row, column); } -QModelIndex ShortcutListModel::parent(const QModelIndex &idx) const{ +QModelIndex ShortcutListModel::parent(const QModelIndex &) const{ return QModelIndex(); } @@ -142,7 +120,7 @@ int ShortcutListModel::columnCount(const QModelIndex &parent) const{ } QVariant ShortcutListModel::data(const QModelIndex &index, int role) const{ - if (index.row() < 0 || index.row() >= this->items.size() || index.column() < 0 || index.column() > 1 || role != Qt::DisplayRole) + if (index.row() < 0 || (size_t)index.row() >= this->items.size() || index.column() < 0 || index.column() > 1 || role != Qt::DisplayRole) return QVariant(); switch (index.column()){ case 0: @@ -156,13 +134,13 @@ QVariant ShortcutListModel::data(const QModelIndex &index, int role) const{ class ShortcutListHeaderModel : public QAbstractItemModel{ public: - QModelIndex index(int row, int column, const QModelIndex &parent) const{ + QModelIndex index(int row, int column, const QModelIndex &) const{ return this->createIndex(row, column); } - QModelIndex parent(const QModelIndex &idx) const{ + QModelIndex parent(const QModelIndex &) const{ return QModelIndex(); } - int rowCount(const QModelIndex &parent) const{ + int rowCount(const QModelIndex &) const{ return 0; } int columnCount(const QModelIndex &parent) const{ @@ -170,10 +148,10 @@ class ShortcutListHeaderModel : public QAbstractItemModel{ return 0; return 2; } - QVariant data(const QModelIndex &index, int role) const{ + QVariant data(const QModelIndex &, int) const{ return QVariant(); } - QVariant headerData(int section, Qt::Orientation orientation, int role) const{ + QVariant headerData(int section, Qt::Orientation, int role) const{ if (section < 0 || section > 1 || role != Qt::DisplayRole) return QVariant(); switch (section){ @@ -192,7 +170,7 @@ static ShortcutListHeaderModel slhm; OptionsDialog::OptionsDialog(ImageViewerApplication &app): ui(new Ui_OptionsDialog), app(&app), - no_changes(true){ + no_shortcut_changes(true){ this->setModal(true); this->ui->setupUi(this); @@ -228,13 +206,13 @@ void OptionsDialog::setup_shortcuts_list_view(){ } void OptionsDialog::setup_general_options(){ - this->ui->center_when_displayed_cb->setChecked(this->options.center_images); - this->ui->use_checkerboard_pattern_cb->setChecked(this->options.use_checkerboard); - this->ui->clamp_to_edges_cb->setChecked(this->options.clamp_to_edges); - this->ui->keep_application_running_cb->setChecked(this->options.keep_in_background); - this->ui->clamp_strength_spinbox->setValue(this->options.clamp_strength); - this->ui->zoom_mode_for_new_windows_cb->set_selected_item(this->options.windowed_zoom_mode); - this->ui->fullscreen_zoom_mode_for_new_windows_cb->set_selected_item(this->options.fullscreen_zoom_mode); + this->ui->center_when_displayed_cb->setChecked(this->options->get_center_when_displayed()); + this->ui->use_checkerboard_pattern_cb->setChecked(this->options->get_use_checkerboard_pattern()); + this->ui->clamp_to_edges_cb->setChecked(this->options->get_clamp_to_edges()); + this->ui->keep_application_running_cb->setChecked(this->options->get_keep_application_in_background()); + this->ui->clamp_strength_spinbox->setValue(this->options->get_clamp_strength()); + this->ui->zoom_mode_for_new_windows_cb->set_selected_item(this->options->get_zoom_mode_for_new_windows()); + this->ui->fullscreen_zoom_mode_for_new_windows_cb->set_selected_item(this->options->get_fullscreen_zoom_mode_for_new_windows()); } void OptionsDialog::setup_signals(){ @@ -260,7 +238,7 @@ void OptionsDialog::sequence_entered(){ this->ui->add_button->setEnabled(!this->sequence_exists_in_model(seq)); } -void OptionsDialog::selected_shortcut_changed(const QItemSelection &selected, const QItemSelection &deselected){ +void OptionsDialog::selected_shortcut_changed(const QItemSelection &selected, const QItemSelection &){ this->ui->remove_button->setEnabled(!!selected.indexes().size()); } @@ -271,7 +249,7 @@ void OptionsDialog::add_button_clicked(bool){ auto command = this->ui->command_input->currentData(); auto str_command = command.toString(); this->sl_model->add_new_item(this->app->get_shortcuts(), str_command, seq); - this->no_changes = false; + this->no_shortcut_changes = false; } void OptionsDialog::remove_button_clicked(bool){ @@ -291,7 +269,7 @@ void OptionsDialog::remove_button_clicked(bool){ combo->setCurrentIndex(found); this->ui->key_sequence_input->setKeySequence(item.sequence); this->sequence_entered(); - this->no_changes = false; + this->no_shortcut_changes = false; this->ui->shortcuts_list_view->setCurrentIndex(index); } @@ -301,23 +279,23 @@ void OptionsDialog::item_inserted_into_shortcut_model(size_t index){ this->ui->add_button->setEnabled(false); } -OptionsPack OptionsDialog::build_options(){ - OptionsPack ret; - ret.center_images = this->ui->center_when_displayed_cb->isChecked(); - ret.use_checkerboard = this->ui->use_checkerboard_pattern_cb->isChecked(); - ret.clamp_to_edges = this->ui->clamp_to_edges_cb->isChecked(); - ret.keep_in_background = this->ui->keep_application_running_cb->isChecked(); - ret.clamp_strength = this->ui->clamp_strength_spinbox->value(); - ret.windowed_zoom_mode = this->ui->zoom_mode_for_new_windows_cb->get_selected_item(); - ret.fullscreen_zoom_mode = this->ui->fullscreen_zoom_mode_for_new_windows_cb->get_selected_item(); +std::shared_ptr OptionsDialog::build_options(){ + auto ret = std::make_shared(); + ret->set_center_when_displayed(this->ui->center_when_displayed_cb->isChecked()); + ret->set_use_checkerboard_pattern(this->ui->use_checkerboard_pattern_cb->isChecked()); + ret->set_clamp_to_edges(this->ui->clamp_to_edges_cb->isChecked()); + ret->set_keep_application_in_background(this->ui->keep_application_running_cb->isChecked()); + ret->set_clamp_strength(this->ui->clamp_strength_spinbox->value()); + ret->set_zoom_mode_for_new_windows(this->ui->zoom_mode_for_new_windows_cb->get_selected_item()); + ret->set_fullscreen_zoom_mode_for_new_windows(this->ui->fullscreen_zoom_mode_for_new_windows_cb->get_selected_item()); return ret; } void OptionsDialog::accept(){ auto options = this->build_options(); - if (options != this->options) - this->app->set_option_values(options); - if (!this->no_changes) + if (*options != *this->options) + this->app->set_option_values(*options); + if (!this->no_shortcut_changes) this->app->options_changed(this->sl_model->get_items()); this->hide(); } @@ -330,5 +308,5 @@ void OptionsDialog::reset_button_clicked(bool){ auto defaults = this->app->get_shortcuts().get_default_shortcuts(); this->sl_model->replace_all(defaults); this->ui->shortcuts_list_view->resizeColumnToContents(0); - this->no_changes = false; + this->no_shortcut_changes = false; } diff --git a/src/OptionsDialog.h b/src/OptionsDialog.h index 0413ccf..630c439 100644 --- a/src/OptionsDialog.h +++ b/src/OptionsDialog.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef OPTIONS_DIALOG_H @@ -70,15 +49,15 @@ class OptionsDialog : public QDialog{ std::shared_ptr sl_model; std::shared_ptr sl_selmodel; ImageViewerApplication *app; - bool no_changes; - OptionsPack options; + bool no_shortcut_changes; + std::shared_ptr options; void setup_command_input(); void setup_shortcuts_list_view(); void setup_signals(); bool sequence_exists_in_model(const QKeySequence &); void setup_general_options(); - OptionsPack build_options(); + std::shared_ptr build_options(); public: OptionsDialog(ImageViewerApplication &app); diff --git a/src/Quadrangular.h b/src/Quadrangular.h index b8b57c1..232c74f 100644 --- a/src/Quadrangular.h +++ b/src/Quadrangular.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef QUADRANGULAR_H diff --git a/src/Rational.h b/src/Rational.h deleted file mode 100644 index 3351add..0000000 --- a/src/Rational.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - -Copyright (c) 2015, Helios -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef RATIONAL_H -#define RATIONAL_H -#include -#include -#include - -template -class basic_rational{ - T numerator; - T denominator; - - void normalize(){ - auto a = this->numerator; - auto b = this->denominator; - if (a < 0) - a = -a; - if (b < 0) - b = -b; - while (b){ - auto t = b; - b = a % b; - a = t; - } - if (!a) - return; - this->numerator /= a; - this->denominator /= a; - if (this->denominator < 0){ - this->numerator = -this->numerator; - this->denominator = -this->denominator; - } - } -public: - basic_rational(T n = 0){ - *this = n; - } - basic_rational(T a, T b): numerator(a), denominator(b){ - this->normalize(); - } - template - basic_rational(const std::pair &p){ - *this = basic_rational((T)p.first, (T)p.second); - } - basic_rational(const basic_rational &q){ - *this = q; - } - std::pair to_pair() const{ - return std::make_pair(this->numerator, this->denominator); - } - T get_numerator() const{ - return this->numerator; - } - T get_denominator() const{ - return this->denominator; - } - const basic_rational &operator=(const basic_rational &q){ - this->numerator = q.numerator; - this->denominator = q.denominator; - return *this; - } - const basic_rational &operator=(T n){ - this->numerator = n; - this->denominator = 1; - return *this; - } - - const basic_rational &operator+=(T n){ - this->numerator += n * this->denominator; - return *this; - } - const basic_rational &operator+=(const basic_rational &q){ - this->numerator = this->numerator * q.denominator + q.numerator * this->denominator; - this->denominator *= q.denominator; - this->normalize(); - return *this; - } - - const basic_rational &operator-=(T n){ - this->numerator -= n * this->denominator; - return *this; - } - const basic_rational &operator-=(const basic_rational &q){ - this->numerator = this->numerator * q.denominator - q.numerator * this->denominator; - this->denominator *= q.denominator; - this->normalize(); - return *this; - } - - const basic_rational &operator*=(T n){ - this->numerator *= n; - this->normalize(); - return *this; - } - const basic_rational &operator*=(const basic_rational &q){ - this->numerator *= q.numerator; - this->denominator *= q.denominator; - this->normalize(); - return *this; - } - - const basic_rational &operator/=(T n){ - this->denominator *= n; - this->normalize(); - return *this; - } - const basic_rational &operator/=(const basic_rational &q){ - this->numerator *= q.denominator; - this->denominator *= q.numerator; - this->normalize(); - return *this; - } - - bool undefined() const{ - return !this->denominator; - } - bool null() const{ - return !this->numerator && !this->denominator; - } - basic_rational reciprocal() const{ - return basic_rational(this->denominator, this->numerator); - } - -#define DEFINE_RATIONAL_OVERLOAD(op) \ - basic_rational operator##op(T n){ \ - auto ret = *this; \ - ret op##= n; \ - return ret; \ - } \ - basic_rational operator##op(const basic_rational &q){ \ - auto ret = *this; \ - ret op##= q; \ - return ret; \ - } - DEFINE_RATIONAL_OVERLOAD(+) - DEFINE_RATIONAL_OVERLOAD(-) - DEFINE_RATIONAL_OVERLOAD(*) - DEFINE_RATIONAL_OVERLOAD(/) -#undef DEFINE_RATIONAL_OVERLOAD - - operator T() const{ - return this->numerator / this->denominator; - } -#define DEFINE_RATIONAL_RELATIONAL_OVERLOAD(op) \ - bool operator##op(const basic_rational &q) const{ \ - return this->numerator * q.denominator op q.numerator * this->denominator; \ - } - DEFINE_RATIONAL_RELATIONAL_OVERLOAD(<) - DEFINE_RATIONAL_RELATIONAL_OVERLOAD(>) - DEFINE_RATIONAL_RELATIONAL_OVERLOAD(<=) - DEFINE_RATIONAL_RELATIONAL_OVERLOAD(>=) - DEFINE_RATIONAL_RELATIONAL_OVERLOAD(==) - DEFINE_RATIONAL_RELATIONAL_OVERLOAD(!=) -}; - -template -inline T operator*(T n, const basic_rational &q){ - return (T)(q * n); -} - -template -inline QSize operator*(const QSize &s, const basic_rational &q){ - return s * q.get_numerator() / q.get_denominator(); -} - -template -inline QPoint operator*(const QPoint &p, const basic_rational &q){ - T x = p.x(); - T y = p.y(); - x = x * q.get_numerator() / q.get_denominator(); - y = y * q.get_numerator() / q.get_denominator(); - return QPoint(x, y); -} - -template -inline QSizeF operator*(const QSizeF &s, const basic_rational &q){ - T w = s.width(); - T h = s.height(); - w = w * q.get_numerator() / q.get_denominator(); - h = h * q.get_numerator() / q.get_denominator(); - return QSize(w, h); -} - -template -inline QPointF operator*(const QPointF &p, const basic_rational &q){ - return p * q.get_numerator() / q.get_denominator(); -} - -typedef basic_rational Rational; -typedef basic_rational RationalLL; - -#endif // RATIONAL_H diff --git a/src/RotateDialog.cpp b/src/RotateDialog.cpp index 1164ff9..24874cd 100644 --- a/src/RotateDialog.cpp +++ b/src/RotateDialog.cpp @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "RotateDialog.h" @@ -34,8 +13,8 @@ const double log_125 = log(1.25); RotateDialog::RotateDialog(MainWindow &parent) : QDialog(parent.centralWidget()), - main_window(parent), ui(new Ui_RotateDialog), + main_window(parent), result(false), in_do_transform(false){ this->setModal(true); diff --git a/src/RotateDialog.h b/src/RotateDialog.h index c34d1e1..1df1740 100644 --- a/src/RotateDialog.h +++ b/src/RotateDialog.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef ROTATE_DIALOG_H diff --git a/src/Settings.cpp b/src/Settings.cpp deleted file mode 100644 index ed5586a..0000000 --- a/src/Settings.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - -Copyright (c) 2015, Helios -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "Settings.h" -#include -#include -#include -#include -#include - -//#define USE_XML -#define USE_JSON -#ifdef USE_XML -#include -#endif -#ifdef USE_JSON -#include -#include -#include -#endif - -bool get_config_location(QString &dst); - -void SettingsValue::operator=(bool val){ - this->value = QVariant((int)val); -} - -Settings::Settings() -{ - if (!get_config_location(this->path)) - throw SettingsException("Can't determine settings path."); - QDir dir(this->path); - if (!dir.mkpath(this->path)) - throw SettingsException("Can't create settings path."); - this->path += "settings."; -#if defined USE_XML - this->path += "xml"; -#elif defined USE_JSON - this->path += "json"; -#endif -} - -#ifdef USE_XML -void write(QDomDocument &doc, QDomElement &element, SettingsTree &tree){ - auto f1 = [&element, &doc](const QString &name, SettingsValue &value){ - auto el = doc.createElement(name); - el.appendChild(doc.createTextNode(value.to_string())); - element.appendChild(el); - }; - auto f2 = [&element, &doc, this](const QString &name, SettingsTree &tree){ - auto el = doc.createElement(name); - write(doc, el, tree); - element.appendChild(el); - }; - tree.iterate_over_values(f1); - tree.iterate_over_trees(f2); -} -#endif - -#ifdef USE_JSON -void write_tree(QJsonObject &obj, SettingsTree &tree); -void write_array(QJsonObject &obj, SettingsTree &tree); - -void write_array(QJsonArray &array, SettingsArray &tree){ - tree.iterate([&](int i, SettingsItem &item){ - if (item.is_value()) - array.push_back(QJsonValue(static_cast(item).to_string())); - else if (item.is_array()){ - QJsonArray new_array; - write_array(new_array, static_cast(item)); - array.push_back(new_array); - }else{ - QJsonObject object; - write_tree(object, static_cast(item)); - array.push_back(object); - } - }); -} - -void write_tree(QJsonObject &obj, SettingsTree &tree){ - tree.iterate([&](const QString &key, SettingsItem &item){ - if (item.is_value()) - obj[key] = QJsonValue(static_cast(item).to_string()); - else if (item.is_array()){ - QJsonArray new_array; - write_array(new_array, static_cast(item)); - obj[key] = new_array; - }else{ - QJsonObject object; - write_tree(object, static_cast(item)); - obj[key] = object; - } - }); -} -#endif - -void Settings::write(SettingsTree &tree){ -#ifdef USE_XML - QDomDocument doc; - auto el = doc.createElement("settings"); - ::write(doc, el, tree); - doc.appendChild(el); - QFile file(this->path); - file.open(QFile::WriteOnly); - if (!file.isOpen()) - return; - QTextStream stream(&file); - doc.save(stream, 4); -#endif -#ifdef USE_JSON - QJsonDocument doc; - QJsonObject root; - ::write_tree(root, tree); - doc.setObject(root); - QFile file(this->path); - file.open(QFile::WriteOnly); - if (!file.isOpen()) - return; - file.write(doc.toJson(QJsonDocument::Indented)); -#endif -} - -#ifdef USE_JSON -std::shared_ptr read_obj(QJsonObject &obj); -std::shared_ptr read_array(QJsonArray &arr); - -template -std::shared_ptr add_sub(const T &key, QJsonValueRef &item){ - if (item.isObject()) - return key, read_obj(item.toObject()); - if (item.isArray()) - return key, read_array(item.toArray()); - if (item.isString()) - return std::shared_ptr(new SettingsValue(item.toString())); - return std::shared_ptr(); -} - -std::shared_ptr read_array(QJsonArray &arr){ - std::shared_ptr ret(new SettingsArray); - auto size = arr.size(); - for (int i = 0; i < size; i++){ - auto item = add_sub(i, arr[i]); - if (!item) - continue; - ret->push_back(item); - } - return ret; -} - -std::shared_ptr read_obj(QJsonObject &obj){ - std::shared_ptr ret(new SettingsTree); - auto keys = obj.keys(); - for (auto &key : keys){ - auto item = add_sub(key, obj[key]); - if (!item) - continue; - ret->add_tree(key, item); - } - return ret; -} -#endif - -std::shared_ptr Settings::read(){ -#ifdef USE_JSON - std::shared_ptr ret; - QFile file(this->path); - file.open(QFile::ReadOnly); - if (!file.isOpen()) - return ret; - auto doc = QJsonDocument::fromJson(file.readAll()); - if (doc.isNull()) - return ret; - return ::read_obj(doc.object()); -#endif -} - -bool get_config_location(QString &dst){ - auto list = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); - if (!list.size()) - return false; - dst = list[0]; - int index = dst.lastIndexOf('/'); - if (index < 0) - index = dst.lastIndexOf('\\'); - dst = dst.mid(0, index); - auto c = QDir::separator(); - dst += c; - dst += "BorderlessImageViewer"; - dst += c; - return true; -} diff --git a/src/Settings.h b/src/Settings.h deleted file mode 100644 index 4147627..0000000 --- a/src/Settings.h +++ /dev/null @@ -1,365 +0,0 @@ -/* - -Copyright (c) 2015, Helios -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef SETTINGS_H -#define SETTINGS_H -#include "Rational.h" -#include "Misc.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class SettingsException : public std::exception{ -public: - SettingsException(const char *what): std::exception(what){} -}; - -class SettingsItem{ - bool m_value; - bool m_array; -public: - SettingsItem(bool val, bool arr = false): m_value(val), m_array(arr){} - virtual ~SettingsItem(){} - bool is_value() const{ - return this->m_value; - } - bool is_array() const{ - return this->m_array; - } -}; - -class SettingsValue : public SettingsItem{ - QVariant value; - bool unset; - - template - static typename std::enable_if::value>::type conditional_cast_to_int(SettingsValue &dst, const T &src){ - dst = (int)src; - } - - template - static typename std::enable_if::value>::type conditional_cast_to_int(SettingsValue &dst, const T &src){ - dst = src; - } - -public: - SettingsValue(): SettingsItem(true), unset(true){} - template - SettingsValue(const T &val): SettingsItem(true), unset(false){ - conditional_cast_to_int(*this, val); - } - template - void operator=(const T &val){ - this->value = QVariant(val); - } - void operator=(bool val); - void operator=(const QPoint &val){ - *this = ::to_pair(val); - } - void operator=(const QSize &val){ - *this = ::to_pair(val); - } - template - void operator=(const basic_rational &val){ - *this = val.to_pair(); - } - template - void operator=(const std::pair &val){ - std::stringstream stream; - stream << val.first << ' ' << val.second; - *this = stream.str().c_str(); - } - void operator=(const QMatrix &val){ - std::stringstream stream; - stream - << val.m11() << ' ' - << val.m21() << ' ' - << val.m12() << ' ' - << val.m22(); - *this = stream.str().c_str(); - } - void operator=(const QKeySequence &seq){ - *this = seq.toString(); - } - bool is_unset() const{ - return this->unset; - } - QString to_string() const{ - return this->value.toString(); - } - int to_int() const{ - return this->value.toInt(); - } - bool to_bool() const{ - return this->value.toBool(); - } - double to_double() const{ - return this->value.toDouble(); - } - QPoint to_QPoint() const{ - return ::to_QPoint(this->to_pair()); - } - QSize to_QSize() const{ - return ::to_QSize(this->to_pair()); - } - QMatrix to_QMatrix() const{ - std::stringstream stream(this->to_string().toStdString()); - double m[4]; - stream - >> m[0] - >> m[1] - >> m[2] - >> m[3]; - return QMatrix(m[0], m[2], m[1], m[3], 0, 0); - } - template - basic_rational to_basic_rational() const{ - return basic_rational(this->to_pair()); - } - template - std::pair to_pair() const{ - std::stringstream stream(this->to_string().toStdString()); - std::pair ret; - stream >> ret.first >> ret.second; - return ret; - } - template - void to(T &dst) const{ - if (std::is_enum::value) - dst = (T)this->to_int(); - } - void to(QKeySequence &dst) const{ - dst = this->to_string(); - } - void to(QString &dst) const{ - dst = this->to_string(); - } - void to(int &dst) const{ - dst = this->to_int(); - } - void to(bool &dst) const{ - dst = this->to_bool(); - } - void to(double &dst) const{ - dst = this->to_double(); - } - void to(QPoint &dst) const{ - dst = this->to_QPoint(); - } - void to(QSize &dst) const{ - dst = this->to_QSize(); - } - template - void to(basic_rational &dst) const{ - dst = this->to_basic_rational(); - } - template - void to(std::pair &dst) const{ - dst = this->to_pair(); - } - void to(QMatrix &dst) const{ - dst = this->to_QMatrix(); - } -}; - -class SettingsTree; -class SettingsArray; - -template -class AssociativeTree : public SettingsItem{ -protected: - MapT tree; - int get_int(const KeyT &s) const{ - auto it = this->find(s); - if (!it) - return 0; - if (it->is_value()){ - auto val = *static_cast(it->second.get()); - return val.to_int(); - } - return 0; - } - virtual std::shared_ptr find(const KeyT &k) const = 0; - -public: - AssociativeTree(bool is_array): SettingsItem(false, is_array){} - template - void set_value(const KeyT &key, const T &val){ - this->tree[key] = std::shared_ptr(new SettingsValue(val)); - } - template - void add_tree(const KeyT &key, const T &subtree){ - this->tree[key] = std::static_pointer_cast(subtree); - } - /* - template - void iterate_over_values(T &f) const{ - for (auto &i : this->tree){ - std::shared_ptr item = i.second; - if (item->is_value()) - f(i.first, *static_cast(item.get())); - } - } - template - void iterate_over_trees(T &f) const; - template - void iterate_over_arrays(T &f) const; - */ - template - void get_value(T &dst, const KeyT &key) const{ - auto it = this->find(key); - if (!it) - return; - std::shared_ptr p = it; - if (!p->is_value()) - return; - SettingsValue &val = static_cast(*p.get()); - val.to(dst); - } - std::shared_ptr operator[](const KeyT &key){ - auto it = this->find(key); - if (!it) - return std::shared_ptrsecond; - } - std::shared_ptr get_tree(const KeyT &key) const; - std::shared_ptr get_array(const KeyT &key) const; - static std::shared_ptr create_tree(); - static std::shared_ptr create_array(); -}; - -class SettingsTree : public AssociativeTree > > { -protected: - std::shared_ptr find(const QString &k) const override{ - auto it = this->tree.find(k); - if (it == this->tree.end()) - return nullptr; - return it->second; - } - -public: - SettingsTree() : AssociativeTree > >(false){} - template - void iterate(T &f) const{ - for (auto &i : this->tree) - f(i.first, *i.second); - } -}; - -class SettingsArray: public AssociativeTree > > { -protected: - std::shared_ptr find(const int &k) const override{ - if (k < 0 || k >= this->tree.size()) - return nullptr; - return this->tree[k]; - } - -public: - SettingsArray() : AssociativeTree > >(true){} - size_t size() const{ - return this->tree.size(); - } - template - void iterate(T &f) const{ - int p = 0; - for (auto &i : this->tree) - f(p++, *i); - } - void push_back(const std::shared_ptr &item){ - this->tree.push_back(item); - } -}; - -template -std::shared_ptr AssociativeTree::create_tree(){ - return std::shared_ptr(new SettingsTree); -} - -template -std::shared_ptr AssociativeTree::create_array(){ - return std::shared_ptr(new SettingsArray); -} - -template -std::shared_ptr AssociativeTree::get_tree(const KeyT &key) const{ - auto it = this->tree.find(key); - return it == this->tree.end() || it->second->is_value() || it->second->is_array() ? nullptr : std::static_pointer_cast(it->second); -} - -template -std::shared_ptr AssociativeTree::get_array(const KeyT &key) const{ - auto it = this->tree.find(key); - return it == this->tree.end() || it->second->is_value() || !it->second->is_array() ? nullptr : std::static_pointer_cast(it->second); -} -/* -template -template -void AssociativeTree::iterate_over_trees(T &f) const{ - for (auto &i : this->tree){ - std::shared_ptr item = i.second; - if (!item->is_value() && !item->is_array()) - f(i.first, *static_cast(item.get())); - } -} - -template -template -void AssociativeTree::iterate_over_arrays(T &f) const{ - for (auto &i : this->tree){ - std::shared_ptr item = i.second; - if (!item->is_value() && item->is_array()) - f(i.first, *static_cast(item.get())); - } -} -*/ -class Settings -{ - QString path; -public: - Settings(); - void write(SettingsTree &tree); - std::shared_ptr read(); -}; - -#define DEFINE_SETTING_STRING(x) static const char *x##_setting = #x -#define DEFINE_SETTING(type, name, default_value) static const type default_##name = default_value; \ - type name -#define DEFINE_SETTING2(type, name) static const type default_##name; \ - type name -#define RESET_SETTING(x) this->x = this->default_##x - -#endif // SETTINGS_H diff --git a/src/ShortcutInfo.h b/src/ShortcutInfo.h new file mode 100644 index 0000000..e5b69d3 --- /dev/null +++ b/src/ShortcutInfo.h @@ -0,0 +1,36 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef SHORTCUTINFO_H +#define SHORTCUTINFO_H + +#include + +struct ShortcutInfo { + const char *display_name; + const char *internal_name; + const char *default_sequences_str[4]; + QKeySequence default_sequences_seq[4]; + size_t sequences_count; + ShortcutInfo() {} + ShortcutInfo(const char *display_name, const char *internal_name) : display_name(display_name), internal_name(internal_name), sequences_count(0) {} + ShortcutInfo(const char *display_name, const char *internal_name, const char *s1) : display_name(display_name), internal_name(internal_name), sequences_count(0) { + *this << s1; + } + ShortcutInfo(const char *display_name, const char *internal_name, const char *s1, const char *s2) : display_name(display_name), internal_name(internal_name), sequences_count(0) { + *this << s1 << s2; + } + ShortcutInfo &operator<<(const char *s) { + this->sequences_count %= 4; + this->default_sequences_str[this->sequences_count] = s; + this->default_sequences_seq[this->sequences_count] = QKeySequence((QString)s); + this->sequences_count++; + return *this; + } +}; + +#endif diff --git a/src/Shortcuts.cpp b/src/Shortcuts.cpp index bb55fed..6ee4189 100644 --- a/src/Shortcuts.cpp +++ b/src/Shortcuts.cpp @@ -1,148 +1,53 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "Shortcuts.h" -#define DEFINE_COMMAND_INTERNAL_NAME(x) const char *x##_command = #x - -DEFINE_COMMAND_INTERNAL_NAME(back); -DEFINE_COMMAND_INTERNAL_NAME(background_swap); -DEFINE_COMMAND_INTERNAL_NAME(close); -DEFINE_COMMAND_INTERNAL_NAME(cycle_zoom_mode); -DEFINE_COMMAND_INTERNAL_NAME(down); -DEFINE_COMMAND_INTERNAL_NAME(down_big); -DEFINE_COMMAND_INTERNAL_NAME(flip_h); -DEFINE_COMMAND_INTERNAL_NAME(flip_v); -DEFINE_COMMAND_INTERNAL_NAME(go_to_end); -DEFINE_COMMAND_INTERNAL_NAME(go_to_start); -DEFINE_COMMAND_INTERNAL_NAME(left); -DEFINE_COMMAND_INTERNAL_NAME(left_big); -DEFINE_COMMAND_INTERNAL_NAME(minimize); -DEFINE_COMMAND_INTERNAL_NAME(minimize_all); -DEFINE_COMMAND_INTERNAL_NAME(next); -DEFINE_COMMAND_INTERNAL_NAME(quit); -DEFINE_COMMAND_INTERNAL_NAME(quit2); -DEFINE_COMMAND_INTERNAL_NAME(reset_zoom); -DEFINE_COMMAND_INTERNAL_NAME(right); -DEFINE_COMMAND_INTERNAL_NAME(right_big); -DEFINE_COMMAND_INTERNAL_NAME(rotate_left); -DEFINE_COMMAND_INTERNAL_NAME(rotate_left_fine); -DEFINE_COMMAND_INTERNAL_NAME(rotate_right); -DEFINE_COMMAND_INTERNAL_NAME(rotate_right_fine); -DEFINE_COMMAND_INTERNAL_NAME(show_options); -DEFINE_COMMAND_INTERNAL_NAME(toggle_fullscreen); -DEFINE_COMMAND_INTERNAL_NAME(toggle_lock_zoom); -DEFINE_COMMAND_INTERNAL_NAME(up); -DEFINE_COMMAND_INTERNAL_NAME(up_big); -DEFINE_COMMAND_INTERNAL_NAME(zoom_in); -DEFINE_COMMAND_INTERNAL_NAME(zoom_out); - -#define SETUP_DEFAULT_SHORTCUT1(x, y, z) this->default_shortcuts[y] = ShortcutInfo(x, y, z) -#define SETUP_DEFAULT_SHORTCUT2(x, y, z, z2) this->default_shortcuts[y] = ShortcutInfo(x, y, z, z2) +std::map get_default_shortcuts(); ApplicationShortcuts::ApplicationShortcuts(){ - SETUP_DEFAULT_SHORTCUT1("Quit", quit_command, "Q"); - SETUP_DEFAULT_SHORTCUT1("Quit without saving windows", quit2_command, "Ctrl+Q" ); - SETUP_DEFAULT_SHORTCUT2("Next image", next_command, "Space", "Right" ); - SETUP_DEFAULT_SHORTCUT2("Previous image", back_command, "Backspace", "Left" ); - SETUP_DEFAULT_SHORTCUT1("Change background mode", background_swap_command, "B" ); - SETUP_DEFAULT_SHORTCUT1("Close current", close_command, "Escape" ); - SETUP_DEFAULT_SHORTCUT1("Zoom in", zoom_in_command, "+" ); - SETUP_DEFAULT_SHORTCUT1("Zoom out", zoom_out_command, "-" ); - SETUP_DEFAULT_SHORTCUT1("Reset image transform", reset_zoom_command, "Shift+R" ); - SETUP_DEFAULT_SHORTCUT1("Move up", up_command, "Ctrl+Up" ); - SETUP_DEFAULT_SHORTCUT1("Move down", down_command, "Ctrl+Down" ); - SETUP_DEFAULT_SHORTCUT1("Move left", left_command, "Ctrl+Left" ); - SETUP_DEFAULT_SHORTCUT1("Move right", right_command, "Ctrl+Right" ); - SETUP_DEFAULT_SHORTCUT1("Move up (big step)", up_big_command, "Page Up" ); - SETUP_DEFAULT_SHORTCUT1("Move down (big step)", down_big_command, "Page Down" ); - SETUP_DEFAULT_SHORTCUT1("Move left (big step)", left_big_command, "Ctrl+Page Up" ); - SETUP_DEFAULT_SHORTCUT1("Move right (big step)", right_big_command, "Ctrl+Page Down" ); - SETUP_DEFAULT_SHORTCUT1("Change fit mode", cycle_zoom_mode_command, "F" ); - SETUP_DEFAULT_SHORTCUT1("Toggle zoom lock", toggle_lock_zoom_command, "Shift+L" ); - SETUP_DEFAULT_SHORTCUT1("Go to first image", go_to_start_command, "Home" ); - SETUP_DEFAULT_SHORTCUT1("Go to last image", go_to_end_command, "End" ); - SETUP_DEFAULT_SHORTCUT1("Show options dialog", show_options_command, "O"); - SETUP_DEFAULT_SHORTCUT2("Toggle fullscreen", toggle_fullscreen_command, "Return", "Enter"); - SETUP_DEFAULT_SHORTCUT1("Mirror horizontally", flip_h_command, "H" ); - SETUP_DEFAULT_SHORTCUT1("Mirror vertically", flip_v_command, "V" ); - SETUP_DEFAULT_SHORTCUT1("Minimize current window", minimize_command, "M" ); - SETUP_DEFAULT_SHORTCUT1("Minimize all windows", minimize_all_command, "Shift+M"); - SETUP_DEFAULT_SHORTCUT1("Rotate left", rotate_left_command, "L"); - SETUP_DEFAULT_SHORTCUT1("Rotate right", rotate_right_command, "R"); + this->default_shortcuts = ::get_default_shortcuts(); this->reset_settings(); } -void ApplicationShortcuts::restore_settings(const SettingsTree &tree){ - auto &shortcuts = this->current_shortcuts; - shortcuts.clear(); - tree.iterate([&shortcuts](const QString &key, const SettingsItem &subtree){ - if (subtree.is_value() || !subtree.is_array()) - return; - auto array = static_cast(subtree); - std::shared_ptr ss(new ShortcutSetting); - ss->command = key; - shortcuts[key] = ss; - auto f = [&](int key, const SettingsItem &item){ - if (!item.is_value()) - return; - auto value = static_cast(item); - QKeySequence sequence; - value.to(sequence); - ss->sequences.push_back(sequence); - }; +void ApplicationShortcuts::restore_settings(const Shortcuts &shortcuts){ + this->current_shortcuts.clear(); + for (auto &s : shortcuts.shortcuts){ + auto ss = std::make_shared(); + auto key = QString::fromStdString(s.first); + ss->command = key; + this->current_shortcuts[key] = ss; - array.iterate(f); - }); - + for (auto &s2 : s.second) + ss->sequences.emplace_back(QKeySequence(QString::fromStdWString(s2))); + } } void ApplicationShortcuts::reset_settings(){ - for (auto &p : this->default_shortcuts){ + auto &map = this->current_shortcuts; + map.clear(); + for (auto &p : this->default_shortcuts) { auto key = p.second.internal_name; - auto &map = this->current_shortcuts; std::shared_ptr ss(new ShortcutSetting); ss->command = key; map[key] = ss; for (size_t i = 0; i < p.second.sequences_count; i++) - ss->sequences.push_back(p.second.default_sequences[i]); + ss->sequences.push_back(p.second.default_sequences_seq[i]); } } -std::shared_ptr ApplicationShortcuts::save_settings(){ - std::shared_ptr ret(new SettingsTree); +std::shared_ptr ApplicationShortcuts::save_settings() const{ + auto ret = std::make_shared(); for (auto &s : this->current_shortcuts){ - std::shared_ptr array(new SettingsArray); - int i = 0; + auto key = s.first.toStdString(); + auto &shortcuts = ret->shortcuts[key]; for (auto &seq : s.second->sequences) - array->push_back(std::shared_ptr(new SettingsValue(seq))); - ret->add_tree(s.first, array); + shortcuts.push_back(seq.toString().toStdWString()); } return ret; } @@ -177,7 +82,7 @@ std::vector ApplicationShortcuts::get_default_shortcuts() const{ pushee.command = p.second.internal_name; pushee.display_name = p.second.display_name; for (size_t i = 0; i < p.second.sequences_count; i++){ - pushee.sequence = p.second.default_sequences[i]; + pushee.sequence = p.second.default_sequences_seq[i]; ret.push_back(pushee); } } diff --git a/src/Shortcuts.h b/src/Shortcuts.h index d75bcdf..3bb4abb 100644 --- a/src/Shortcuts.h +++ b/src/Shortcuts.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef SHORTCUTS_H @@ -34,7 +13,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include "Settings.h" +#include "serialization/settings.generated.h" +#include "ShortcutInfo.h" #define DECLARE_COMMAND_INTERNAL_NAME(x) extern const char *x##_command @@ -75,27 +55,6 @@ struct ShortcutSetting{ std::vector sequences; }; -struct ShortcutInfo{ - const char *display_name; - const char *internal_name; - QKeySequence default_sequences[4]; - size_t sequences_count; - ShortcutInfo(){} - ShortcutInfo(const char *display_name, const char *internal_name) : display_name(display_name), internal_name(internal_name), sequences_count(0){} - ShortcutInfo(const char *display_name, const char *internal_name, const char *s1) : display_name(display_name), internal_name(internal_name), sequences_count(0){ - *this << s1; - } - ShortcutInfo(const char *display_name, const char *internal_name, const char *s1, const char *s2) : display_name(display_name), internal_name(internal_name), sequences_count(0){ - *this << s1 << s2; - } - ShortcutInfo &operator<<(const char *s){ - this->sequences_count %= 4; - this->default_sequences[this->sequences_count] = QKeySequence((QString)s); - this->sequences_count++; - return *this; - } -}; - struct ShortcutTriple{ QString command; QString display_name; @@ -107,9 +66,9 @@ class ApplicationShortcuts{ std::map > current_shortcuts; public: ApplicationShortcuts(); - void restore_settings(const SettingsTree &tree); + void restore_settings(const Shortcuts &); void reset_settings(); - std::shared_ptr save_settings(); + std::shared_ptr save_settings() const; const ShortcutInfo *get_shortcut_info(const QString &command) const; QString get_display_name(const QString &command) const; const ShortcutSetting *get_shortcut_setting(const QString &command) const; diff --git a/src/SingleInstanceApplication.cpp b/src/SingleInstanceApplication.cpp index 258aef5..6be3733 100644 --- a/src/SingleInstanceApplication.cpp +++ b/src/SingleInstanceApplication.cpp @@ -1,32 +1,12 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "SingleInstanceApplication.h" +#include "GenericException.h" #include #include #include @@ -35,6 +15,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +//#define DISABLE_SINGLE_INSTANCE + #ifdef WIN32 #include @@ -43,37 +25,54 @@ void allow_set_foreground_window(qint64 pid){ ret = ret; } #else -void allow_set_foreground_window(qulonglong pid){ +void allow_set_foreground_window(qulonglong){ } #endif -SingleInstanceApplication::SingleInstanceApplication(int argc, char *argv[], const QString &unique_name): +SingleInstanceApplication::SingleInstanceApplication(int &argc, char **argv, const QString &unique_name): QApplication(argc, argv), - unique_name(unique_name), - running(false){ + running(false), + unique_name(unique_name){ +#ifndef DISABLE_SINGLE_INSTANCE this->args = this->arguments(); - this->shared_memory.setKey(unique_name); - bool success; - for (int tries = 0; tries < 5; tries++){ - if (this->shared_memory.attach()){ - QLocalSocket socket(this); - this->running = true; - qint64 server_pid; - if (this->communicate_with_server(socket, server_pid, this->arguments())) - allow_set_foreground_window(server_pid); - throw ApplicationAlreadyRunningException(); + bool success = false; + for (int tries = 0; tries < 5 && !success; tries++){ + this->shared_memory.reset(new QSharedMemory); + this->shared_memory->setKey(unique_name); + for (; tries < 5 && !success; tries++){ + if (this->shared_memory->attach()){ + QLocalSocket socket(this); + this->running = true; + qint64 server_pid; + if (this->communicate_with_server(socket, server_pid, this->arguments())) + allow_set_foreground_window(server_pid); + else{ + this->clear_shared_memory(); + break; + } + throw ApplicationAlreadyRunningException(); + } + success = this->shared_memory->create(1); } - success = this->shared_memory.create(1); - if (success) - break; } if (!success) - throw std::exception("Unable to allocate shared memory."); + throw GenericException("Unable to allocate shared memory."); this->local_server.reset(new QLocalServer(this)); connect(this->local_server.get(), SIGNAL(newConnection()), this, SLOT(receive_message())); - this->local_server->listen(unique_name); + for (int i = 0; i < 2 && !this->local_server->listen(unique_name); i++) + this->clear_shared_memory(); +#endif +} + +void SingleInstanceApplication::clear_shared_memory(){ +#ifndef WIN32 + QFile file("/tmp/" + unique_name); + if (file.exists()) + std::cerr << "Shared memory exists!\n"; + file.remove(); +#endif } void SingleInstanceApplication::receive_message(){ @@ -96,10 +95,13 @@ bool SingleInstanceApplication::communicate_with_server(QLocalSocket &socket, qi if (!this->communicate_with_server(socket, response, to_QByteArray(list))) return false; server_pid = 0; - unsigned char buf[sizeof(server_pid)]; + union{ + unsigned char buf[sizeof(qint64)]; + qint64 pid; + } u; for (int i = 0; i < response.size(); i++) - buf[i] = response[i]; - server_pid = *(quint64 *)buf; + u.buf[i] = response[i]; + server_pid = u.pid; return true; } @@ -108,16 +110,16 @@ bool SingleInstanceApplication::communicate_with_server(QLocalSocket &socket, QB return false; socket.connectToServer(this->unique_name, QIODevice::ReadWrite); if (!socket.waitForConnected(this->timeout)){ - qDebug(socket.errorString().toLatin1()); + qDebug() << socket.errorString().toLatin1(); return false; } socket.write(msg); if (!socket.waitForBytesWritten(this->timeout)){ - qDebug(socket.errorString().toLatin1()); + qDebug() << socket.errorString().toLatin1(); return false; } if (!socket.waitForReadyRead(this->timeout)){ - qDebug(socket.errorString().toLatin1()); + qDebug() << socket.errorString().toLatin1(); return false; } response = socket.readAll(); diff --git a/src/SingleInstanceApplication.h b/src/SingleInstanceApplication.h index 9407842..c701a58 100644 --- a/src/SingleInstanceApplication.h +++ b/src/SingleInstanceApplication.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef SINGLEINSTANCEAPPLICATION_H @@ -50,7 +29,7 @@ class SingleInstanceApplication : public QApplication{ bool running; QString unique_name; - QSharedMemory shared_memory; + std::unique_ptr shared_memory; std::shared_ptr local_server; static const int timeout = 1000; @@ -60,6 +39,7 @@ class SingleInstanceApplication : public QApplication{ } bool communicate_with_server(QLocalSocket &socket, qint64 &server_pid, const QStringList &list); bool communicate_with_server(QLocalSocket &socket, QByteArray &response, const QByteArray &msg); + void clear_shared_memory(); protected: QStringList args; @@ -67,7 +47,7 @@ class SingleInstanceApplication : public QApplication{ public: //May throw ApplicationAlreadyRunningException. - explicit SingleInstanceApplication(int argc, char **argv, const QString &unique_name); + explicit SingleInstanceApplication(int &argc, char **argv, const QString &unique_name); bool is_running() const{ return this->running; } diff --git a/src/StreamRedirector.cpp b/src/StreamRedirector.cpp new file mode 100644 index 0000000..9a1fd2f --- /dev/null +++ b/src/StreamRedirector.cpp @@ -0,0 +1,90 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "stdafx.h" +#include "StreamRedirector.h" +#ifndef USING_PRECOMPILED_HEADERS +#ifdef WIN32 +#include +#else +#include +#endif +#include +#include +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4996) +#endif + +StdStreamRedirector::StdStreamRedirector(){ + this->pipes[READ] = 0; + this->pipes[WRITE] = 0; + if (_pipe(this->pipes.data(), 65536, O_BINARY) == -1) + return; + this->old_stdout = dup(fileno(stdout)); + this->old_stderr = dup(fileno(stderr)); + + this->initialized = true; +} + +StdStreamRedirector::~StdStreamRedirector(){ + this->end_capture(); + if (this->old_stdout > 0) + close(this->old_stdout); + if (this->old_stderr > 0) + close(this->old_stderr); + if (this->pipes[READ] > 0) + close(this->pipes[READ]); + if (this->pipes[WRITE] > 0) + close(this->pipes[WRITE]); +} + +void StdStreamRedirector::begin_capture(){ + if (!this->initialized) + return; + this->end_capture(); + fflush(stdout); + fflush(stderr); + auto temp = fileno(stdout); + dup2(this->pipes[WRITE], fileno(stdout)); + dup2(this->pipes[WRITE], fileno(stderr)); + this->capturing = true; +} + +bool StdStreamRedirector::end_capture(){ + if (!this->initialized || !this->capturing) + return false; + this->capturing = false; + fflush(stdout); + fflush(stderr); + if (this->old_stdout >= 0) + dup2(this->old_stdout, fileno(stdout)); + if (this->old_stderr >= 0) + dup2(this->old_stderr, fileno(stderr)); + this->capture.clear(); + + std::string buf; + const int bufSize = 1024; + buf.resize(bufSize); + int bytesRead = 0; + if (!eof(this->pipes[READ])) + bytesRead = read(this->pipes[READ], &(*buf.begin()), bufSize); + + while (bytesRead == bufSize){ + this->capture += buf; + bytesRead = 0; + if (!eof(this->pipes[READ])) + bytesRead = read(this->pipes[READ], &(*buf.begin()), bufSize); + } + + if (bytesRead > 0){ + buf.resize(bytesRead); + this->capture += buf; + } + return true; +} diff --git a/src/StreamRedirector.h b/src/StreamRedirector.h new file mode 100644 index 0000000..1c9c690 --- /dev/null +++ b/src/StreamRedirector.h @@ -0,0 +1,45 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef STREAMREDIRECTOR_H +#define STREAMREDIRECTOR_H + +#include +#include + +class StdStreamRedirector{ + enum PIPES { READ, WRITE }; + std::array pipes = {{0, 0}}; + int old_stdout = 0; + int old_stderr = 0; + bool capturing = false; + bool initialized = false; + std::string capture; +public: + StdStreamRedirector(); + ~StdStreamRedirector(); + void begin_capture(); + bool end_capture(); + const std::string &get_capture() const{ + return this->capture; + } +}; + +class StdStreamRedirectionGuard{ + StdStreamRedirector redir; + std::string &dst; +public: + StdStreamRedirectionGuard(std::string &dst): dst(dst){ + this->redir.begin_capture(); + } + ~StdStreamRedirectionGuard(){ + this->redir.end_capture(); + this->dst = this->redir.get_capture(); + } +}; + +#endif diff --git a/src/Streams.cpp b/src/Streams.cpp new file mode 100644 index 0000000..4f71014 --- /dev/null +++ b/src/Streams.cpp @@ -0,0 +1,29 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "Streams.h" +#include + +std::streamsize QFileInputStream::read(char *s, std::streamsize n){ + std::streamsize ret = 0; + bool bad = false; + while (n){ + auto count = this->file->read(s, n); + ret += count; + s += count; + n -= count; + if (this->file->error() != QFileDevice::NoError || this->file->atEnd()){ + bad = true; + break; + } + } + return !ret && bad ? -1 : ret; +} + +std::streamsize QFileOutputStream::write(const char *s, std::streamsize n){ + return this->file->write(s, n); +} diff --git a/src/Streams.h b/src/Streams.h new file mode 100644 index 0000000..4d0dd74 --- /dev/null +++ b/src/Streams.h @@ -0,0 +1,34 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef STREAMS_H +#define STREAMS_H + +#include + +class QFile; + +class QFileInputStream{ + QFile *file; +public: + typedef char char_type; + typedef boost::iostreams::source_tag category; + QFileInputStream(QFile *file): file(file){} + std::streamsize read(char *s, std::streamsize n); +}; + +class QFileOutputStream{ + QFile *file; +public: + typedef char char_type; + typedef boost::iostreams::sink_tag category; + QFileOutputStream(QFile *file): file(file){} + std::streamsize write(const char *s, std::streamsize n); +}; + + +#endif diff --git a/src/ZoomModeDropDown.cpp b/src/ZoomModeDropDown.cpp index d251d26..c3ce2fd 100644 --- a/src/ZoomModeDropDown.cpp +++ b/src/ZoomModeDropDown.cpp @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "ZoomModeDropDown.h" diff --git a/src/ZoomModeDropDown.h b/src/ZoomModeDropDown.h index a3cacee..21e20f1 100644 --- a/src/ZoomModeDropDown.h +++ b/src/ZoomModeDropDown.h @@ -1,29 +1,8 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #ifndef ZOOMMODEDROPDOWN_H diff --git a/src/main.cpp b/src/main.cpp index 1d39d96..dfa801e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,34 +1,13 @@ /* - -Copyright (c) 2015, Helios +Copyright (c), Helios All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +Distributed under a permissive license. See COPYING.txt for details. */ #include "ImageViewerApplication.h" -int main(int argc, char *argv[]){ +int main(int argc, char **argv){ try{ ImageViewerApplication app(argc, argv, "BorderlessViewer"); return app.exec(); diff --git a/src/plugin-core/CallResult.h b/src/plugin-core/CallResult.h new file mode 100644 index 0000000..0d4426f --- /dev/null +++ b/src/plugin-core/CallResult.h @@ -0,0 +1,19 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef CALLRESULT_H +#define CALLRESULT_H + +class CallResultImpl; + +struct CallResult{ + CallResultImpl *impl = nullptr; + bool success = true; + const char *error_message = nullptr; +}; + +#endif diff --git a/src/plugin-core/CallResultImpl.h b/src/plugin-core/CallResultImpl.h new file mode 100644 index 0000000..3cf145b --- /dev/null +++ b/src/plugin-core/CallResultImpl.h @@ -0,0 +1,24 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef CALLRESULTIMPL_H +#define CALLRESULTIMPL_H + +#include +#include "CallResult.h" + +class CallResultImpl{ +public: + bool success; + std::string message; + + CallResultImpl(): success(true){} + CallResultImpl(const char *message): message(message){} + CallResultImpl(const std::string &message): message(message){} +}; + +#endif diff --git a/src/plugin-core/Cpp/CppInterpreter.cpp b/src/plugin-core/Cpp/CppInterpreter.cpp new file mode 100644 index 0000000..ff1e877 --- /dev/null +++ b/src/plugin-core/Cpp/CppInterpreter.cpp @@ -0,0 +1,273 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "stdafx.h" +#include "CppInterpreter.h" +#include "../CallResultImpl.h" +#include "../../StreamRedirector.h" +#ifndef USING_PRECOMPILED_HEADERS +#include "llvm_headers.h" +#include +#endif + +CppInterpreterParameters::retrieve_tls_f global_retrieve_tls = nullptr; +CppInterpreterParameters::store_tls_f global_store_tls_f = nullptr; + +struct FailedToHash : public std::exception{ + std::string msg; +public: + FailedToHash(const std::string &path){ + this->msg = "Unable to compute hash for \'" + path + "\'."; + } + const char *what() const noexcept override{ + return this->msg.c_str(); + } +}; + +CppInterpreter::CppInterpreter(const CppInterpreterParameters ¶meters): parameters(parameters){ + global_retrieve_tls = this->parameters.retrieve_tls; + global_store_tls_f = this->parameters.store_tls; + auto params = this->parameters; + this->hf = [params](const std::string &path) -> Sha1Sum{ + Sha1Sum ret; + if (!params.get_file_sha1(params.state, path.c_str(), ret.data, sizeof(ret.data))) + throw FailedToHash(path); + return ret; + }; +} + +CppInterpreter::~CppInterpreter(){ + +} + +using namespace clang; +using namespace clang::driver; + +static llvm::ExecutionEngine *create_execution_engine(std::unique_ptr M, std::string *ErrorStr){ + return llvm::EngineBuilder(std::move(M)) + .setEngineKind(llvm::EngineKind::Either) + .setErrorStr(ErrorStr) + .create(); +} + +extern "C" __declspec(dllexport) void borderless_CppInterpreter_get_state(void **state, void **image){ + auto This = (CppInterpreter *)global_retrieve_tls(nullptr); + This->pass_main_arguments(*state, *image); +} + +extern "C" __declspec(dllexport) void borderless_CppInterpreter_return_result(void *return_value){ + auto This = (CppInterpreter *)global_retrieve_tls(nullptr); + This->set_return_value(return_value); +} + +bool execute(llvm::Module &mod, llvm::ExecutionEngine &execution_engine, CppInterpreter &cpp, std::string &error_message){ + llvm::Function *EntryFn = mod.getFunction("__borderless_main"); + if (!EntryFn){ + error_message = "'__borderless_main' function not found in module."; + return false; + } + + ArrayRef args; + execution_engine.finalizeObject(); + + global_store_tls_f(nullptr, &cpp); + execution_engine.runFunction(EntryFn, args); + + cpp.display_return_value_in_current_window(); + + return true; +} + +void CppInterpreter::display_return_value_in_current_window(){ + this->parameters.display_in_current_window(this->parameters.state, this->return_value); + +} + +CallResult CppInterpreter::execute_path(const char *filename){ + { + CallResult ret; + if (this->attempt_cache_reuse(ret, filename)) + return ret; + } + + std::string error_message; + std::string redirection; + while (true){ +#if defined(WIN32) && defined(_CONSOLE) || !defined(WIN32) + StdStreamRedirectionGuard guard(redirection); +#endif + + IntrusiveRefCntPtr diagnostic_options = new DiagnosticOptions(); + TextDiagnosticPrinter *text_diagnostic_printer = new TextDiagnosticPrinter(llvm::errs(), &*diagnostic_options); + + IntrusiveRefCntPtr diagnostic_ids(new DiagnosticIDs()); + DiagnosticsEngine diagnostics_engine(diagnostic_ids, &*diagnostic_options, text_diagnostic_printer); + + // Use ELF on windows for now. + std::string TripleStr = llvm::sys::getProcessTriple(); + llvm::Triple triple(TripleStr); + if (triple.isOSBinFormatCOFF()) + triple.setObjectFormat(llvm::Triple::COFF); + + Driver driver("driver", triple.str(), diagnostics_engine); + driver.setTitle("clang interpreter"); + driver.setCheckInputsExist(false); + + // FIXME: This is a hack to try to force the driver to do something we can + // recognize. We need to extend the driver library to support this use model + // (basically, exactly one input, and the operation mode is hard wired). + SmallVector args; + args.push_back("clang"); + args.push_back(filename); + args.push_back("-fsyntax-only"); + args.push_back("-fms-compatibility-version=19"); + args.push_back("-O3"); + std::unique_ptr C(driver.BuildCompilation(args)); + if (!C){ + error_message = "Error initializing compiler."; + break; + } + + // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate. + + // We expect to get back exactly one command job, if we didn't something + // failed. Extract that job from the compilation. + const driver::JobList &jobs = C->getJobs(); + auto jobs_size = jobs.size(); + if (jobs_size != 1 || !isa(*jobs.begin())) { + SmallString<256> Msg; + llvm::raw_svector_ostream OS(Msg); + jobs.Print(OS, "; ", true); + //Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); + error_message = OS.str(); + break; + } + + const driver::Command &command = cast(*jobs.begin()); + if (llvm::StringRef(command.getCreator().getName()) != "clang") { + //Diags.Report(diag::err_fe_expected_clang_command); + error_message = "Expected clang command."; + break; + } + + // Initialize a compiler invocation object from the clang (-cc1) arguments. + const driver::ArgStringList &ccargs = command.getArguments(); + std::unique_ptr invocation(new CompilerInvocation); + CompilerInvocation::CreateFromArgs( + *invocation, + const_cast(ccargs.data()), + const_cast(ccargs.data()) + ccargs.size(), + diagnostics_engine + ); + + // FIXME: This is copied from cc1_main.cpp; simplify and eliminate. + + // Create a compiler instance to handle the actual work. + CompilerInstance clang; + clang.setInvocation(invocation.release()); + + // Create the compilers actual diagnostics engine. + clang.createDiagnostics(); + if (!clang.hasDiagnostics()){ + error_message = "No diagnostics."; + break; + } + + // Create and execute the frontend to generate an LLVM bitcode module. + std::shared_ptr context(new llvm::LLVMContext); + std::unique_ptr action(new EmitLLVMOnlyAction(context.get())); + if (!clang.ExecuteAction(*action)){ + error_message = "Code generation failed."; + break; + } + + std::unique_ptr module = action->takeModule(); + if (!module){ + error_message = "No module generated."; + break; + } + + auto mod = module.get(); + + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + + std::shared_ptr execution_engine(create_execution_engine(std::move(module), &error_message)); + + if (!execution_engine){ + error_message = "Unable to make execution engine: " + error_message; + break; + } + + if (!execute(*mod, *execution_engine, *this, error_message)) + break; + + this->save_in_cache(filename, context, execution_engine, mod); + + return CallResult(); + } + + CallResult ret; + ret.impl = new CallResultImpl(redirection + "\n\n" + error_message); + ret.success = false; + ret.error_message = ret.impl->message.c_str(); + return ret; +} + +void CppInterpreter::pass_main_arguments(void *&state, void *&image) const{ + state = this->parameters.state; + image = this->parameters.caller_image; +} + +bool CppInterpreter::attempt_cache_reuse(CallResult &result, const char *path){ + std::string spath = path; + auto it = this->cached_programs.find(spath); + if (it == this->cached_programs.end()) + return false; + auto &program = *it->second; + if (!program.equals(path)){ + this->cached_programs.erase(it); + return false; + } + result = program.execute(); + return true; +} + +void CppInterpreter::save_in_cache(const char *path, const std::shared_ptr &context, const std::shared_ptr &execution_engine, llvm::Module *module){ + std::string spath = path; + this->cached_programs[spath].reset(new CachedProgram(this, spath, context, execution_engine, module)); +} + +CachedProgram::CachedProgram( + CppInterpreter *interpreter, + const std::string &path, + const std::shared_ptr &context, + const std::shared_ptr &execution_engine, + llvm::Module *module +){ + this->interpreter = interpreter; + this->path = path; + this->context = context; + this->execution_engine = execution_engine; + this->module = module; + this->hash = (*this->interpreter->get_hash_function())(this->path); +} + +CallResult CachedProgram::execute(){ + std::string error_message; + CallResult ret; + if (::execute(*this->module, *this->execution_engine, *this->interpreter, error_message)) + return ret; + ret.impl = new CallResultImpl(error_message); + ret.success = false; + ret.error_message = ret.impl->message.c_str(); + return ret; +} + +bool CachedProgram::equals(const std::string &path){ + return (*this->interpreter->get_hash_function())(path) == this->hash; +} diff --git a/src/plugin-core/Cpp/CppInterpreter.h b/src/plugin-core/Cpp/CppInterpreter.h new file mode 100644 index 0000000..bdd8d51 --- /dev/null +++ b/src/plugin-core/Cpp/CppInterpreter.h @@ -0,0 +1,67 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef CPPINTERPRETER_H +#define CPPINTERPRETER_H + +#include "main.h" +#include +#include + +struct Sha1Sum{ + unsigned char data[20]; + bool operator==(const Sha1Sum &b){ + return !memcmp(this->data, b.data, sizeof(this->data)); + } +}; + +typedef std::function hash_function; + +class CachedProgram{ + CppInterpreter *interpreter; + std::string path; + Sha1Sum hash; + std::shared_ptr context; + std::shared_ptr execution_engine; + llvm::Module *module; +public: + CachedProgram( + CppInterpreter *interpreter, + const std::string &path, + const std::shared_ptr &context, + const std::shared_ptr &execution_engine, + llvm::Module *module + ); + bool equals(const std::string &path); + CallResult execute(); +}; + +class CppInterpreter{ + CppInterpreterParameters parameters; + hash_function hf; + void *return_value; + std::map> cached_programs; + bool attempt_cache_reuse(CallResult &, const char *); + void save_in_cache(const char *, const std::shared_ptr &, const std::shared_ptr &, llvm::Module *); +public: + CppInterpreter(const CppInterpreterParameters &); + ~CppInterpreter(); + CallResult execute_path(const char *filename); + void pass_main_arguments(void *&, void *&) const; + void set_return_value(void *rv){ + this->return_value = rv; + } + hash_function *get_hash_function(){ + return &this->hf; + } + void reset_image(external_state image){ + this->parameters.caller_image = image; + } + void display_return_value_in_current_window(); +}; + +#endif diff --git a/src/plugin-core/Cpp/RuntimeLibrary/borderless.h b/src/plugin-core/Cpp/RuntimeLibrary/borderless.h new file mode 100644 index 0000000..0e9191a --- /dev/null +++ b/src/plugin-core/Cpp/RuntimeLibrary/borderless.h @@ -0,0 +1,21 @@ +#ifndef BORDERLESS_H +#define BORDERLESS_H + +#include "borderless_runtime.h" + +extern "C" void borderless_CppInterpreter_get_state(B::state_t *, B::handle_t *); +extern "C" void borderless_CppInterpreter_return_result(void *); + +B::Image entry_point(B::Application &app, B::Image img); + +extern "C" void __borderless_main(){ + B::state_t state; + B::handle_t img; + borderless_CppInterpreter_get_state(&state, &img); + B::g_application = new B::Application(state); + auto ret = entry_point(*B::g_application, B::Image(img)); + ret.ref(); + delete B::g_application; + borderless_CppInterpreter_return_result(ret.get_handle()); +} +#endif diff --git a/src/plugin-core/Cpp/RuntimeLibrary/borderless_runtime.cpp b/src/plugin-core/Cpp/RuntimeLibrary/borderless_runtime.cpp new file mode 100644 index 0000000..a32e749 --- /dev/null +++ b/src/plugin-core/Cpp/RuntimeLibrary/borderless_runtime.cpp @@ -0,0 +1,94 @@ +B::Image Application::get_displayed_image(){ + auto handle = ::get_displayed_image(this->state); + auto it = this->handles.find((uintptr_t)handle); + if (it != this->handles.end()) + return Image(it->second); + shared_ptr ret(handle); + this->handles[(uintptr_t)handle] = ret; + return Image(ret); +} + +void Application::display_in_current_window(const Image &img){ + if (img) + ::display_in_current_window(this->state, img.get_handle()); +} + +void Application::debug_print(const std::string &s){ + ::debug_print(s.c_str()); +} + +void Application::show_message_box(const std::string &s){ + ::show_message_box(s.c_str()); +} + +Image::Image(const char *path){ + auto p = load_image(g_application->get_state(), path); + if (p) + this->handle.reset(p); +} + +Image::Image(int w, int h){ + auto p = allocate_image(g_application->get_state(), w, h); + if (p) + this->handle.reset(p); +} + +Image::~Image(){ + if (this->handle.unique()) + ::unload_image(this->get_handle()); +} + +Image Image::clone() const{ + return Image(clone_image(this->get_handle())); +} + +Image Image::clone_without_data() const{ + return Image(clone_image_without_data(this->get_handle())); +} + +void Image::get_dimensions(int &w, int &h){ + if (!this->dims_initialized){ + get_image_dimensions(this->get_handle(), &this->w, &this->h); + this->dims_initialized = true; + } + w = this->w; + h = this->h; +} + +void Image::get_pixel_data(int &w, int &h, int &stride, int &pitch, unsigned char *&pixels){ + this->get_dimensions(w, h); + if (!this->props_initialized){ + this->pixels = get_image_pixel_data(this->get_handle(), &this->stride, &this->pitch); + this->props_initialized = true; + } + stride = this->stride; + pitch = this->pitch; + pixels = this->pixels; +} + +bool Image::save(const char *path){ + return !!save_image(this->get_handle(), path); +} + +ImageIterator::ImageIterator(Image &image): image(image){ + this->image.get_pixel_data(this->w, this->h, this->stride, this->pitch, this->pixels); + this->reset(); +} + +bool ImageIterator::next(u8 *&pi){ + if (this->i >= this->n) + return false; + pi = this->pixels + this->i++ * 4; + return true; +} + +void ImageIterator::position(int &x, int &y) const{ + auto i = this->i - 1; + x = i % this->w; + y = i / this->w; +} + +void ImageIterator::reset(){ + this->i = 0; + this->n = this->w * this->h; +} diff --git a/src/plugin-core/Cpp/RuntimeLibrary/borderless_runtime.h b/src/plugin-core/Cpp/RuntimeLibrary/borderless_runtime.h new file mode 100644 index 0000000..f653077 --- /dev/null +++ b/src/plugin-core/Cpp/RuntimeLibrary/borderless_runtime.h @@ -0,0 +1,293 @@ +#ifndef BORDERLESS_RUNTIME_H +#define BORDERLESS_RUNTIME_H + +#include "capi.h" +//#include +#include +#include +#include + +namespace B{ + typedef ::Image *handle_t; + typedef ::PluginCoreState *state_t; + class Image; + + class shared_ptr{ + handle_t p; + unsigned *refcount; + void clear(){ + if (!*this) + return; + if (this->unique()) + delete this->refcount; + else + --*this->refcount; + this->refcount = nullptr; + this->p = nullptr; + } + public: + shared_ptr(): p(nullptr), refcount(nullptr){} + explicit shared_ptr(handle_t p): p(p), refcount(new unsigned(1)){} + shared_ptr(const shared_ptr &o): p(o.p), refcount(o.refcount){ + ++*this->refcount; + } + ~shared_ptr(){ + this->clear(); + } + operator bool() const{ + return !!this->p; + } + bool unique() const{ + return !!this->refcount && *this->refcount == 1; + } + handle_t get() const{ + return this->p; + } + void reset(handle_t p = nullptr){ + this->clear(); + if (!p) + return; + this->p = p; + this->refcount = new unsigned(1); + } + void ref(){ + if (*this) + ++*this->refcount; + } + }; + + class Application{ + friend class B::Image; + state_t state; + std::unordered_map handles; + + state_t get_state() const{ + return this->state; + } + public: + Application(state_t state): state(state){} + B::Image get_displayed_image(); + void display_in_current_window(const Image &); + void debug_print(const std::string &); + void show_message_box(const std::string &); + }; + + Application *g_application; + + class Image{ + friend class Application; + shared_ptr handle; + bool dims_initialized = false; + int w = -1, + h = -1; + bool props_initialized = false; + int stride = -1, + pitch = -1; + unsigned char *pixels = nullptr; + + Image(const decltype(Image::handle) &handle): handle(handle){} + public: + Image(){} + Image(handle_t handle): handle(handle){} + Image(const char *path); + Image(const std::string &path): Image(path.c_str()){} + Image(int w, int h); + ~Image(); + Image clone() const; + Image clone_without_data() const; + void ref(){ + this->handle.ref(); + } + operator bool() const{ + return !!this->handle; + } + void get_dimensions(int &w, int &h); + void get_pixel_data(int &w, int &h, int &stride, int &pitch, unsigned char *&pixels); + bool save(const char *path); + bool save(const std::string &path){ + return this->save(path.c_str()); + } + handle_t get_handle() const{ + return this->handle ? this->handle.get() : nullptr; + } + }; + + class ImageIterator{ + Image ℑ + u8 *pixels; + int w, h, stride, pitch, i, n; + unsigned state; + public: + ImageIterator(Image &); + // Behaves like iterator++ != end for while and for predicate. + bool next(u8 *&pi); + void position(int &x, int &y) const; + void reset(); + }; + + + enum class StreamCommand{ + Endl, + Hex, + DebugPrint, + MsgBox, + }; + + class Stream{ + std::string buffer; + bool hex = false; + template + void write_unsigned(T x){ + if (!this->hex){ + if (!x) + this->buffer += '0'; + else{ + const auto n = sizeof(T) * 8 / 3; + this->buffer.reserve(this->buffer.size() + n); + char temp[n]; + unsigned i = 0; + while (x && i < 100){ + temp[i++] = '0' + x % 10; + x /= 10; + } + while (i--) + this->buffer += temp[i]; + } + }else{ + const auto n = sizeof(T) * 8 / 4; + this->buffer.reserve(this->buffer.size() + n); + char temp[n]; + unsigned i = 0; + for (; i < n; i++){ + auto digit = x % 16; + temp[i] = x < 10 ? '0' + digit : 'a' - 10 + digit; + x /= 16; + } + while (i--) + this->buffer += temp[i]; + this->hex = false; + } + } + template + void write_signed(T x){ + if (x < 0){ + this->buffer += '-'; + x = -x; + } + this->write_unsigned(x); + } + public: + Stream(){} + Stream(const std::string &s): buffer(s){} + const std::string &str() const{ + return this->buffer; + } + Stream &operator<<(char c){ + this->buffer += c; + return *this; + } + + Stream &operator<<(unsigned char x){ + this->write_unsigned(x); + return *this; + } + Stream &operator<<(unsigned short x){ + this->write_unsigned(x); + return *this; + } + Stream &operator<<(unsigned int x){ + this->write_unsigned(x); + return *this; + } + Stream &operator<<(unsigned long x){ + this->write_unsigned(x); + return *this; + } + Stream &operator<<(unsigned long long x){ + this->write_unsigned(x); + return *this; + } + + Stream &operator<<(signed char x){ + this->write_signed(x); + return *this; + } + Stream &operator<<(signed short x){ + this->write_signed(x); + return *this; + } + Stream &operator<<(signed int x){ + this->write_signed(x); + return *this; + } + Stream &operator<<(signed long x){ + this->write_signed(x); + return *this; + } + Stream &operator<<(signed long long x){ + this->write_signed(x); + return *this; + } + + Stream &operator<<(float x){ + auto temp = double_to_string(x); + this->buffer += temp; + release_double_to_string(temp); + return *this; + } + Stream &operator<<(double x){ + auto temp = double_to_string(x); + this->buffer += temp; + release_double_to_string(temp); + return *this; + } + + Stream &operator<<(const char *s){ + this->buffer += s; + return *this; + } + Stream &operator<<(const std::string &s){ + this->buffer += s; + return *this; + } + Stream &operator<<(const u8_quad &q){ + this->buffer.reserve(this->buffer.size() + 17); + this->buffer += '#'; + for (int i = 0; i < 4; i++){ + this->hex = true; + *this << (unsigned char)q.data[i]; + } + return *this; + } + Stream &operator<<(const StreamCommand &c){ + switch (c){ + case StreamCommand::Endl: + *this << '\n'; + break; + case StreamCommand::Hex: + this->hex = true; + break; + case StreamCommand::DebugPrint: + g_application->debug_print(this->buffer); + this->buffer.clear(); + break; + case StreamCommand::MsgBox: + g_application->show_message_box(this->buffer); + this->buffer.clear(); + break; + default: + break; + } + return *this; + } + }; + + StreamCommand hex = StreamCommand::Hex; + StreamCommand endl = StreamCommand::Endl; + StreamCommand debugprint = StreamCommand::DebugPrint; + StreamCommand msgbox = StreamCommand::MsgBox; + + #include "borderless_runtime.cpp" +} + +#endif diff --git a/src/plugin-core/Cpp/llvm_headers.h b/src/plugin-core/Cpp/llvm_headers.h new file mode 100644 index 0000000..17f0dc1 --- /dev/null +++ b/src/plugin-core/Cpp/llvm_headers.h @@ -0,0 +1,35 @@ +#ifdef _MSC_VER +#pragma once +#pragma warning(push) +#pragma warning(disable: 4141) +#pragma warning(disable: 4244) +#pragma warning(disable: 4267) +#pragma warning(disable: 4624) +#pragma warning(disable: 4800) +#pragma warning(disable: 4996) +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/src/plugin-core/Cpp/main.cpp b/src/plugin-core/Cpp/main.cpp new file mode 100644 index 0000000..b548f86 --- /dev/null +++ b/src/plugin-core/Cpp/main.cpp @@ -0,0 +1,54 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "stdafx.h" +#include "main.h" +#include "CppInterpreter.h" +#include "../CallResultImpl.h" + +#ifdef WIN32 +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ + switch (ul_reason_for_call){ + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + llvm::llvm_shutdown(); + break; + } + return TRUE; +} +#endif + +CPP_PLUGIN_EXPORT_C CppInterpreter *new_CppInterpreter(CppInterpreterParameters *parameters){ + return new CppInterpreter(*parameters); +} + +CPP_PLUGIN_EXPORT_C void delete_CppInterpreter(CppInterpreter *interpreter){ + delete interpreter; +} + +CPP_PLUGIN_EXPORT_C void CppInterpreter_execute(CallResult *result, CppInterpreter *interpreter, const char *filename){ + try{ + auto r = interpreter->execute_path(filename); + if (result) + *result = r; + }catch (std::exception &e){ + result->impl = new CallResultImpl((std::string)"Exception thrown: " + e.what()); + result->error_message = result->impl->message.c_str(); + result->success = false; + } +} + +CPP_PLUGIN_EXPORT_C void CppInterpreter_reset_imag(CppInterpreter *interpreter, external_state image){ + interpreter->reset_image(image); +} + +CPP_PLUGIN_EXPORT_C void delete_CppCallResult(CallResult *result){ + delete result->impl; +} diff --git a/src/plugin-core/Cpp/main.h b/src/plugin-core/Cpp/main.h new file mode 100644 index 0000000..0ab51c9 --- /dev/null +++ b/src/plugin-core/Cpp/main.h @@ -0,0 +1,55 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef CPPINTERPRETERMAIN_H +#define CPPINTERPRETERMAIN_H + +#ifndef __cplusplus +#error Only use this file from C++! +#endif + +#include "../CallResult.h" + +#define CPP_PLUGIN_EXTERN_C extern "C" + +#if defined WIN32 && defined BUILDING_CPPINTERPRETER +#define CPP_PLUGIN_EXPORT_C CPP_PLUGIN_EXTERN_C __declspec(dllexport) +#else +#define CPP_PLUGIN_EXPORT_C CPP_PLUGIN_EXTERN_C +#endif + +class CppInterpreter; +typedef void *external_state; + +struct CppInterpreterParameters{ + external_state state; + external_state caller_image; + +#define CppInterpreterParameters_DECLARE_FUNCTION(rt, x, ...) \ + typedef rt (*x##_f)(external_state, __VA_ARGS__); \ + x##_f x +#define CppInterpreterParameters_DECLARE_FUNCTION0(rt, x) \ + typedef rt (*x##_f)(external_state); \ + x##_f x + CppInterpreterParameters_DECLARE_FUNCTION(void, release_returned_string, char *); + CppInterpreterParameters_DECLARE_FUNCTION(void, store_tls, void *); + CppInterpreterParameters_DECLARE_FUNCTION0(void *, retrieve_tls); + CppInterpreterParameters_DECLARE_FUNCTION(void, display_in_current_window, void *handle); + CppInterpreterParameters_DECLARE_FUNCTION(bool, get_file_sha1, const char *path, unsigned char *buffer, size_t buffer_size); +}; + +#define Cpp_DECLARE_EXPORTED_FUNCTION(rt, x, ...) \ + typedef rt (*x##_f)(__VA_ARGS__); \ + CPP_PLUGIN_EXPORT_C rt x(__VA_ARGS__) + +Cpp_DECLARE_EXPORTED_FUNCTION(CppInterpreter *, new_CppInterpreter, CppInterpreterParameters *parameters); +Cpp_DECLARE_EXPORTED_FUNCTION(void, delete_CppInterpreter, CppInterpreter *); +Cpp_DECLARE_EXPORTED_FUNCTION(void, CppInterpreter_execute, CallResult *result, CppInterpreter *, const char *filename); +Cpp_DECLARE_EXPORTED_FUNCTION(void, CppInterpreter_reset_imag, CppInterpreter *, external_state); +Cpp_DECLARE_EXPORTED_FUNCTION(void, delete_CppCallResult, CallResult *); + +#endif diff --git a/src/plugin-core/Cpp/stdafx.cpp b/src/plugin-core/Cpp/stdafx.cpp new file mode 100644 index 0000000..a27b824 --- /dev/null +++ b/src/plugin-core/Cpp/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/src/plugin-core/Cpp/stdafx.h b/src/plugin-core/Cpp/stdafx.h new file mode 100644 index 0000000..e9a8def --- /dev/null +++ b/src/plugin-core/Cpp/stdafx.h @@ -0,0 +1,20 @@ +#ifdef _MSC_VER +#pragma once + +#define USING_PRECOMPILED_HEADERS +#include "llvm_headers.h" +#include + +#ifdef WIN32 +#include +#else +#include +#endif +#include +#include + +#ifdef WIN32 +#include +#endif + +#endif diff --git a/src/plugin-core/ImageStore.cpp b/src/plugin-core/ImageStore.cpp new file mode 100644 index 0000000..7e7c27e --- /dev/null +++ b/src/plugin-core/ImageStore.cpp @@ -0,0 +1,232 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "ImageStore.h" +#include +#include + +Image::Image(const QString &path, ImageStore &owner, int handle): + owner(&owner), + own_handle(handle), + alphaed(false){ + if (!QFile::exists(path)) + throw ImageOperationResult("File not found."); + this->bitmap = QImage(path); + if (this->bitmap.isNull()) + throw ImageOperationResult("Unknown error."); + this->w = this->bitmap.width(); + this->h = this->bitmap.height(); +} + +Image::Image(int w, int h, ImageStore &owner, int handle): + owner(&owner), + own_handle(handle), + alphaed(false){ + this->bitmap = QImage(w, h, QImage::Format_RGBA8888); + if (this->bitmap.isNull()) + throw ImageOperationResult("Unknown error."); + this->w = this->bitmap.width(); + this->h = this->bitmap.height(); +} + +Image::Image(const QImage &image, ImageStore &owner, int handle): + owner(&owner), + own_handle(handle), + alphaed(false){ + this->bitmap = image; + if (this->bitmap.isNull()) + throw ImageOperationResult("Unknown error."); + this->w = this->bitmap.width(); + this->h = this->bitmap.height(); +} + +void Image::traverse(traversal_callback cb){ + this->to_alpha(); + + auto pixels = this->bitmap.bits(); + for (int y = 0; y < this->h; y++){ + //auto scanline = pixels + this->pitch * (this->h - 1 - y); + auto scanline = pixels + this->pitch * y; + for (int x = 0; x < this->w; x++){ + auto pixel = scanline + x * this->stride; + int r = pixel[0]; + int g = pixel[1]; + int b = pixel[2]; + int a = pixel[3]; + auto prev = this->owner->get_current_traversal_image(); + auto prev_pixel = this->current_pixel; + this->owner->set_current_traversal_image(this); + this->current_pixel = pixel; + cb(r, g, b, a, x, y); + this->owner->set_current_traversal_image(prev); + this->current_pixel = prev_pixel; + } + } +} + +void Image::to_alpha(){ + if (this->alphaed) + return; + if (this->bitmap.format() != QImage::Format_RGBA8888) + this->bitmap = this->bitmap.convertToFormat(QImage::Format_RGBA8888); + this->pitch = this->bitmap.bytesPerLine(); + this->alphaed = true; +} + +void Image::set_current_pixel(const pixel_t &rgba){ + for (int i = 0; i < 4; i++) + this->current_pixel[i] = rgba[i]; +} + +ImageOperationResult Image::save(const QString &path, SaveOptions opt){ + ImageOperationResult ret; + ret.success = this->bitmap.save(path, opt.format.size() ? opt.format.c_str() : nullptr, opt.compression); + if (!ret.success) + ret.message = "Unknown error."; + return ret; +} + +ImageOperationResult Image::get_pixel(unsigned x, unsigned y){ + if (x >= (unsigned)this->w || y >= (unsigned)this->h) + return "Invalid coordinates."; + this->to_alpha(); + auto pixels = this->bitmap.bits(); + auto pixel = pixels + this->pitch * y + this->stride * x; + ImageOperationResult ret; + ret.success = 1; + for (int i = 0; i < 4; i++) + ret.results[i] = pixel[i]; + return ret; +} + +ImageOperationResult Image::get_dimensions(){ + ImageOperationResult ret; + ret.success = true; + ret.results[0] = this->w; + ret.results[1] = this->h; + return ret; +} + +ImageOperationResult ImageStore::load(const char *path){ + return this->load(QString::fromUtf8(path)); +} + +Image *ImageStore::load_image(const char *path){ + auto qpath = QString::fromUtf8(path); + decltype(this->images)::mapped_type ret; + try{ + ret.reset(new Image(path, *this, this->next_index)); + }catch (ImageOperationResult &ior){ + return nullptr; + } + this->images[this->next_index++] = ret; + return ret.get(); +} + +ImageOperationResult ImageStore::load(const QString &path){ + decltype(this->images)::mapped_type img; + try{ + img.reset(new Image(path, *this, this->next_index)); + }catch (ImageOperationResult &ior){ + return ior; + } + ImageOperationResult ret; + ret.results[0] = this->next_index++; + this->images[ret.results[0]] = img; + return ret; +} + +ImageOperationResult ImageStore::unload(int handle){ + auto it = this->images.find(handle); + if (it == this->images.end()) + return HANDLE_NOT_FOUND_MSG; + this->images.erase(it); + return ImageOperationResult(); +} + +ImageOperationResult ImageStore::save(int handle, const QString &path, SaveOptions opt){ + auto it = this->images.find(handle); + if (it == this->images.end()) + return HANDLE_NOT_FOUND_MSG; + return it->second->save(path, opt); +} + +ImageOperationResult ImageStore::traverse(int handle, traversal_callback cb){ + auto it = this->images.find(handle); + if (it == this->images.end()) + return HANDLE_NOT_FOUND_MSG; + auto img = it->second; + img->traverse(cb); + return ImageOperationResult(); +} + +Image *ImageStore::allocate_image(int w, int h){ + if (w < 1 || h < 1) + return nullptr; + decltype(this->images)::mapped_type ret; + try{ + ret.reset(new Image(w, h, *this, this->next_index)); + }catch (ImageOperationResult &ior){ + return nullptr; + } + this->images[this->next_index++] = ret; + return ret.get(); +} + +ImageOperationResult ImageStore::allocate(int w, int h){ + if (w < 1 || h < 1 ) + return "both width and height must be at least 1."; + decltype(this->images)::mapped_type img; + try{ + img.reset(new Image(w, h, *this, this->next_index)); + }catch (ImageOperationResult &ior){ + return ior; + } + ImageOperationResult ior; + ior.results[0] = this->next_index++; + this->images[ior.results[0]] = img; + return ior; +} + +ImageOperationResult ImageStore::get_pixel(int handle, unsigned x, unsigned y){ + auto it = this->images.find(handle); + if (it == this->images.end()) + return HANDLE_NOT_FOUND_MSG; + return it->second->get_pixel(x, y); +} + +void ImageStore::set_current_pixel(const pixel_t &rgba){ + if (!this->current_traversal_image) + return; + this->current_traversal_image->set_current_pixel(rgba); +} + +ImageOperationResult ImageStore::get_dimensions(int handle){ + auto it = this->images.find(handle); + if (it == this->images.end()) + return HANDLE_NOT_FOUND_MSG; + return it->second->get_dimensions(); +} + +int ImageStore::store(const QImage &image){ + int ret = this->next_index; + try{ + this->images[ret] = std::make_shared(image, *this, ret); + }catch (std::exception &){ + return -1; + } + this->next_index++; + return ret; +} + +void *Image::get_pixels_pointer(unsigned &stride, unsigned &pitch){ + this->to_alpha(); + + stride = this->stride; + pitch = this->pitch; + return this->bitmap.bits(); +} diff --git a/src/plugin-core/ImageStore.h b/src/plugin-core/ImageStore.h new file mode 100644 index 0000000..d7ad333 --- /dev/null +++ b/src/plugin-core/ImageStore.h @@ -0,0 +1,124 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef IMAGESTORE_H +#define IMAGESTORE_H + +#include +#include +#include +#include +#include +#include +#include "capi.h" + +class Image; +class QString; + +struct ImageOperationResult{ + bool success; + int results[4]; + std::string message; + ImageOperationResult(const char *msg = nullptr): success(!msg), message(msg ? msg : ""){} +}; + +enum class Trinary{ + Undefined, + False, + True, +}; + +struct SaveOptions{ + int compression; + std::string format; + SaveOptions(): compression(-1){} +}; + +typedef std::function traversal_callback; +typedef std::array pixel_t; + +class ImageStore; + +class Image{ + ImageStore *owner; + int own_handle; + QImage bitmap; + bool alphaed; + int w, h; + static const unsigned stride = 4; + unsigned pitch; + std::uint8_t *current_pixel; + + void to_alpha(); +public: + Image(const QString &path, ImageStore &owner, int handle); + Image(int w, int h, ImageStore &owner, int handle); + Image(const QImage &, ImageStore &owner, int handle); + void traverse(traversal_callback cb); + void set_current_pixel(const pixel_t &rgba); + ImageOperationResult save(const QString &path, SaveOptions opt); + ImageOperationResult get_pixel(unsigned x, unsigned y); + ImageOperationResult get_dimensions(); + void get_dimensions(int &w, int &h){ + w = this->w; + h = this->h; + } + QImage get_bitmap() const{ + return this->bitmap; + } + ImageStore *get_owner() const{ + return this->owner; + } + int get_handle() const{ + return this->own_handle; + } + void *get_pixels_pointer(unsigned &stride, unsigned &pitch); +}; + +class ImageStore{ + std::unordered_map> images; + Image *current_traversal_image; + int next_index; +public: + ImageStore(): current_traversal_image(nullptr){} + ImageOperationResult load(const char *path); + ImageOperationResult load(const QString &path); + Image *load_image(const char *path); + int store(const QImage &); + ImageOperationResult unload(int handle); + void unload(Image *img){ + this->unload(img->get_handle()); + } + ImageOperationResult save(int handle, const QString &path, SaveOptions opt); + ImageOperationResult traverse(int handle, traversal_callback cb); + ImageOperationResult allocate(int w, int h); + Image *allocate_image(int w, int h); + ImageOperationResult get_pixel(int handle, unsigned x, unsigned y); + void set_current_pixel(const pixel_t &rgba); + ImageOperationResult get_dimensions(int handle); + + Image *get_current_traversal_image(){ + return this->current_traversal_image; + } + void set_current_traversal_image(Image *image){ + this->current_traversal_image = image; + } + std::shared_ptr get_image(int img) const{ + auto i = this->images.find(img); + if (i == this->images.end()) + return std::shared_ptr(); + return i->second; + } + void clear(){ + this->images.clear(); + this->next_index = 0; + } +}; + +#define HANDLE_NOT_FOUND_MSG "Image handle doesn't exist." + +#endif diff --git a/src/plugin-core/Lua/LuaInterpreter.cpp b/src/plugin-core/Lua/LuaInterpreter.cpp new file mode 100644 index 0000000..3c9639c --- /dev/null +++ b/src/plugin-core/Lua/LuaInterpreter.cpp @@ -0,0 +1,178 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "LuaInterpreter.h" +#include "lua.h" +#include "../CallResultImpl.h" +#include +#include + +LuaInterpreter::LuaInterpreter(const LuaInterpreterParameters ¶ms): parameters(params){ + auto state = this->parameters.state; + auto f = this->parameters.release_returned_string; + this->release_function = [=](char *s){ f(state, s); }; + this->lua_state = init_lua_state(this); +} + +LuaInterpreter::~LuaInterpreter(){} + +CallResult LuaInterpreter::execute_buffer(const char *filename, const void *buffer, size_t size){ + CallResult ret; + auto state = this->lua_state.get(); + try{ + luaL_loadbuffer(state, (const char *)buffer, size, filename); + lua_call(state, 0, 0); + lua_getglobal(state, "is_pure_filter"); + bool pure_filter = false; + if (lua_isboolean(state, -1)) + pure_filter = !!lua_toboolean(state, -1); + lua_pop(state, 1); + if (pure_filter){ + lua_getglobal(state, "main"); + if (!lua_isfunction(state, -1)) + throw std::exception("Pure filter doesn't contain a main function."); + + auto imgno = this->get_caller_image(); + lua_pushinteger(state, imgno); + lua_call(state, 1, 1); + if (lua_isnumber(state, -1)) + imgno = (int)lua_tointeger(state, -1); + auto image = this->display_in_current_window(imgno); + } + }catch (LuaStackUnwind &){ + }catch (std::exception &e){ + ret.impl = new CallResultImpl(e.what()); + ret.success = false; + ret.error_message = ret.impl->message.c_str(); + return ret; + }catch (...){ + std::stringstream stream; + stream << "Lua threw an error: " << lua_tostring(state, -1); + ret.impl = new CallResultImpl(stream.str()); + ret.success = false; + ret.error_message = ret.impl->message.c_str(); + return ret; + } + return ret; +} + +void LuaInterpreter::message_box(const char *title, const char *message, bool is_error){ + this->parameters.show_message_box(this->parameters.state, title, message, is_error); +} + +ImageOperationResult to_ImageOperationResult(const ImageOperationResultExternal &src, std::function &release){ + ImageOperationResult ret; + ret.success = src.success; + if (src.message) + ret.message = src.message; + static_assert(sizeof(ret.results) == sizeof(src.results), "Inconsistent struct definitions!"); + memcpy(ret.results, src.results, sizeof(ret.results)); + release(src.message); + return ret; +} + +ImageOperationResult LuaInterpreter::load_image(const char *path){ + return to_ImageOperationResult(this->parameters.load_image(this->parameters.state, path), this->release_function); +} + +ImageOperationResult LuaInterpreter::unload_image(int handle){ + return to_ImageOperationResult(this->parameters.unload_image(this->parameters.state, handle), this->release_function); +} + +ImageOperationResult LuaInterpreter::allocate_image(int w, int h){ + return to_ImageOperationResult(this->parameters.allocate_image(this->parameters.state, w, h), this->release_function); +} + +ImageOperationResult LuaInterpreter::save_image(int handle, const char *path, const SaveOptions &options){ + auto ret = this->parameters.save_image(this->parameters.state, handle, path, options.compression, options.format.c_str()); + return to_ImageOperationResult(ret, this->release_function); +} + +ImageOperationResult LuaInterpreter::traverse(int handle, traverse_callback_t cb, void *ud){ + image_info info; + auto ret = this->parameters.get_image_info(this->parameters.state, handle, &info); + if (!ret.results) + return to_ImageOperationResult(ret, this->release_function); + this->release_function(ret.message); + + auto pixels = (unsigned char *)info.pixels; + traversal_stack_frame current_frame = { + this->frame, + info, + nullptr, + }; + for (int y = 0; y < info.h; y++){ + //auto scanline = pixels + this->pitch * (this->h - 1 - y); + auto scanline = pixels + info.pitch * y; + for (int x = 0; x < info.w; x++){ + auto pixel = scanline + x * info.stride; + int r = pixel[0]; + int g = pixel[1]; + int b = pixel[2]; + int a = pixel[3]; + + current_frame.current_pixel = pixel; + + this->frame = ¤t_frame; + cb(ud, r, g, b, a, x, y); + this->frame = this->frame->prev; + } + } + + return ImageOperationResult(); +} + +void LuaInterpreter::set_current_pixel(const pixel_t &rgba){ + if (!this->frame) + return; + auto pixel = this->frame->current_pixel; + for (int i = 0; i < 4; i++) + pixel[i] = rgba[i]; +} + +ImageOperationResult LuaInterpreter::get_pixel(int handle, int x, int y){ + image_info info; + auto result = this->parameters.get_image_info(this->parameters.state, handle, &info); + if (!result.results) + return to_ImageOperationResult(result, this->release_function); + this->release_function(result.message); + + if (x >= info.w || y >= info.h) + return "Invalid coordinates."; + auto pixels = (unsigned char *)info.pixels; + auto pixel = pixels + info.pitch * y + info.stride * x; + ImageOperationResult ret; + for (int i = 0; i < 4; i++) + ret.results[i] = pixel[i]; + return ret; +} + +ImageOperationResult LuaInterpreter::get_image_dimensions(int handle){ + image_info info; + auto result = this->parameters.get_image_info(this->parameters.state, handle, &info); + if (!result.results) + return to_ImageOperationResult(result, this->release_function); + this->release_function(result.message); + + ImageOperationResult ret; + ret.results[0] = info.w; + ret.results[1] = info.h; + return ret; +} + +int LuaInterpreter::get_caller_image(){ + return this->parameters.get_caller_image(this->parameters.state); +} + +ImageOperationResult LuaInterpreter::display_in_current_window(int handle){ + this->parameters.display_in_current_window(this->parameters.state, handle); + return ImageOperationResult(); +} + +void LuaInterpreter::debug_print(const char *string){ + this->parameters.debug_print(this->parameters.state, string); +} diff --git a/src/plugin-core/Lua/LuaInterpreter.h b/src/plugin-core/Lua/LuaInterpreter.h new file mode 100644 index 0000000..a0263e5 --- /dev/null +++ b/src/plugin-core/Lua/LuaInterpreter.h @@ -0,0 +1,63 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef LUAINTERPRETER_H +#define LUAINTERPRETER_H + +#include "main.h" +#include +#include +#include +#include +#include + +struct ImageOperationResult{ + bool success; + int results[4]; + std::string message; + ImageOperationResult(const char *msg = nullptr): success(!msg), message(msg ? msg : ""){} +}; + +typedef std::array pixel_t; + +struct SaveOptions{ + int compression; + std::string format; + SaveOptions(): compression(-1){} +}; + +struct traversal_stack_frame{ + traversal_stack_frame *prev; + image_info info; + unsigned char *current_pixel; +}; + +class LuaInterpreter{ + LuaInterpreterParameters parameters; + std::function release_function; + std::shared_ptr lua_state; + traversal_stack_frame *frame = nullptr; +public: + LuaInterpreter(const LuaInterpreterParameters ¶ms); + ~LuaInterpreter(); + CallResult execute_buffer(const char *filename, const void *buffer, size_t size); + void message_box(const char *title, const char *message, bool is_error); + ImageOperationResult load_image(const char *path); + ImageOperationResult unload_image(int handle); + ImageOperationResult allocate_image(int w, int h); + ImageOperationResult save_image(int handle, const char *path, const SaveOptions &); + typedef void (*traverse_callback_t)(void *, int r, int g, int b, int a, int x, int y); + ImageOperationResult traverse(int handle, traverse_callback_t cb, void *ud); + void set_current_pixel(const pixel_t &); + ImageOperationResult get_pixel(int handle, int x, int y); + ImageOperationResult get_image_dimensions(int handle); + int get_caller_image(); + ImageOperationResult display_in_current_window(int handle); + void debug_print(const char *string); +}; + +#endif diff --git a/src/plugin-core/Lua/lua.cpp b/src/plugin-core/Lua/lua.cpp new file mode 100644 index 0000000..735202e --- /dev/null +++ b/src/plugin-core/Lua/lua.cpp @@ -0,0 +1,677 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "lua.h" +#include "LuaInterpreter.h" +#include "../CallResultImpl.h" +#include +#include +#include +#include + +#ifdef WIN32 +#include +#undef max +#undef min +#endif + +#define MINIMIZE_CHECKING + +const char * const plugin_core_state_global_name = "__plugincorestate"; +const char * const current_image_global_name = "__current_image"; + +static LuaInterpreter *get_interpreter(lua_State *state){ + lua_getglobal(state, plugin_core_state_global_name); + auto ret = (LuaInterpreter *)lua_touserdata(state, -1); + lua_pop(state, 1); + return ret; +} + +double euclidean_modulo(double x, double y){ + if (x < 0) + x = y - fmod(-x, y); + if (x >= y) + x = fmod(x, y); + return x; +} + +bool get_lua_global_function(lua_State *state, const char *name){ + lua_getglobal(state, name); + if (!lua_isfunction(state, -1)){ + lua_pop(state, 1); + return 0; + } + return 1; +} + +void handle_call_to_c_error(lua_State *state, const char *function, const char *msg){ + lua_Debug debug; + lua_getstack(state, 1, &debug); + lua_getinfo(state, "nSl", &debug); + int line = debug.currentline; + std::stringstream stream; + stream << "ERROR at line " << line << " calling function " << function << "(): " << msg; + auto interpreter = get_interpreter(state); + interpreter->message_box("Error executing Lua script.", stream.str().c_str(), true); +} + +#define DECLARE_LUA_FUNCTION(x) static int x(lua_State *state) + +DECLARE_LUA_FUNCTION(load_image){ + std::string msg; +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 1) + msg = "Not enough parameters."; + else if (!lua_isstring(state, 1)) + msg = "The parameter should be a string."; +#endif + if (!msg.size()){ + auto interpreter = get_interpreter(state); + auto res = interpreter->load_image(lua_tostring(state, 1)); + if (res.success){ + lua_pushinteger(state, res.results[0]); + return 1; + } + msg = res.message; + } + + handle_call_to_c_error(state, __FUNCTION__, msg.c_str()); + lua_pushnil(state); + lua_pushstring(state, msg.c_str()); + return 2; +} + +DECLARE_LUA_FUNCTION(allocate_image){ + std::string msg; +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 2){ + msg = "Not enough parameters."; + }else if (!lua_isnumber(state, 1) || !lua_isnumber(state, 2)){ + msg = "Both parameters must be integers."; + } +#endif + if (!msg.size()){ + int w = (int)lua_tointeger(state, 1); + int h = (int)lua_tointeger(state, 2); + if (w <= 0 || h <= 0) + msg = "Both parameters must be greater than zero."; + else{ + auto interpreter = get_interpreter(state); + auto res = interpreter->allocate_image(w, h); + if (res.success){ + lua_pushinteger(state, res.results[0]); + return 1; + } + msg = res.message; + } + } + handle_call_to_c_error(state, __FUNCTION__, msg.c_str()); + lua_pushnil(state); + lua_pushstring(state, msg.c_str()); + return 2; +} + +DECLARE_LUA_FUNCTION(traverse_image){ +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 2){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } + if (!lua_isnumber(state, 1) || !lua_isfunction(state, 2)){ + handle_call_to_c_error(state, __FUNCTION__, "Parameters are of incorrect types."); + return 0; + } +#endif + int imgno = (int)lua_tointeger(state, 1); + auto interpreter = get_interpreter(state); + + interpreter->traverse( + imgno, + [](void *State, int r, int g, int b, int a, int x, int y){ + auto state = (lua_State *)State; + lua_pushvalue(state, 2); + lua_pushinteger(state, r); + lua_pushinteger(state, g); + lua_pushinteger(state, b); + lua_pushinteger(state, a); + lua_pushinteger(state, x); + lua_pushinteger(state, y); + lua_call(state, 6, 0); + }, + state + ); + + return 0; +} + +DECLARE_LUA_FUNCTION(rgb_to_hsv){ +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 3){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } +#endif + double rgb[3]; + for (int i = 0; i < 3; i++){ +#ifndef MINIMIZE_CHECKING + if (!lua_isnumber(state, i + 1)){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be integers."); + return 0; + } +#endif + rgb[i] = (double)lua_tonumber(state, i + 1); + if (rgb[i] < 0 || rgb[i] > 255){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be in the range [0; 255]."); + return 0; + } + rgb[i] /= 255.0; + } + double &r = rgb[0]; + double &g = rgb[1]; + double &b = rgb[2]; + double hue, sat, val, max, min, delta; + max = std::max(r, std::max(g, b)); + min = std::min(r, std::min(g, b)); + delta = max - min; + + val = max; + sat = !max ? 0 : delta / max; + + if (!delta || !sat) + hue = 0; + else{ + if (val == r){ + hue = euclidean_modulo((g - b) / delta, 6); + }else if (val == g) + hue = (b - r) / delta + 2; + else + hue = (r - g) / delta + 4; + hue *= 60; + } + + lua_pushnumber(state, hue); + lua_pushnumber(state, sat); + lua_pushnumber(state, val); + return 3; +} + +DECLARE_LUA_FUNCTION(hsv_to_rgb){ +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 3){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } +#endif + double hsv[3]; + for (int i = 0; i < 3; i++){ +#ifndef MINIMIZE_CHECKING + if (!lua_isnumber(state, i + 1)){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be numbers."); + return 0; + } +#endif + hsv[i] = lua_tonumber(state, i + 1); + } + + double &hue = hsv[0], + &sat = hsv[1], + &val = hsv[2]; + + hue = euclidean_modulo(hue, 360); + + if (sat < 0 || sat > 1){ + handle_call_to_c_error(state, __FUNCTION__, "Saturation should be in the range [0;1]."); + return 0; + } + if (val < 0 || val > 1){ + handle_call_to_c_error(state, __FUNCTION__, "Value should be in the range [0;1]."); + return 0; + } + + double chroma = val * sat, + c = chroma; + double x = chroma * (1 - abs(euclidean_modulo(hue / 60, 2) - 1)); + double m = val - chroma; + double values[][3] = { + { c, x, 0 }, + { x, c, 0 }, + { 0, c, x }, + { 0, x, c }, + { x, 0, c }, + { c, 0, x }, + }; + int j = (int)(hue / 60); + assert(j >= 0 && j < 6); + for (int i = 0; i < 3; i++){ + auto x = (int)((values[j][i] + m) * 255); + lua_pushnumber(state, x); + } + + return 3; +} + +DECLARE_LUA_FUNCTION(set_current_pixel){ +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 4){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } +#endif + pixel_t rgba; + memset(rgba.data(), 0, rgba.size() * sizeof(rgba[0])); + for (int i = 0; i < 4; i++){ +#ifndef MINIMIZE_CHECKING + if (!lua_isnumber(state, i + 1)){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be integers."); + return 0; + } +#endif + int c = (int)lua_tointeger(state, i + 1); + if (c < 0 || c > 255){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be in the range [0; 255]."); + return 0; + } + rgba[i] = (std::uint8_t)c; + } + auto interpreter = get_interpreter(state); + interpreter->set_current_pixel(rgba); + return 0; +} + +void to_lower(std::string &s){ + std::transform(s.begin(), s.end(), s.begin(), tolower); +} + +DECLARE_LUA_FUNCTION(save_image){ + std::string msg; +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 2) + msg = "Not enough parameters."; + else if (!lua_isnumber(state, 1)) + msg = "The first parameter should be a number."; + else if (!lua_isstring(state, 2)) + msg = "The second parameter should be a string."; +#endif + if (!msg.size()){ + int handle = (int)lua_tointeger(state, 1); + SaveOptions opt; + if (lua_gettop(state) >= 3 && lua_istable(state, 3)){ + { + lua_pushstring(state, "format"); + lua_gettable(state, 3); + if (lua_isstring(state, -1)){ + std::string s = lua_tostring(state, -1); + to_lower(s); + opt.format = s; + } + lua_pop(state, 1); + } + { + lua_pushstring(state, "compression"); + lua_gettable(state, 3); + if (lua_isnumber(state, -1)) + opt.compression = (int)lua_tointeger(state, -1); + lua_pop(state, 1); + } + } + auto path = lua_tostring(state, 2); + auto interpreter = get_interpreter(state); + auto res = interpreter->save_image(handle, path, opt); + if (res.success){ + lua_pushboolean(state, true); + return 1; + } + msg = res.message; + } + handle_call_to_c_error(state, __FUNCTION__, msg.c_str()); + lua_pushboolean(state, false); + return 1; +} + +DECLARE_LUA_FUNCTION(bitwise_and){ + auto x = lua_tointeger(state, 1); + auto y = lua_tointeger(state, 2); + x &= y; + lua_pushinteger(state, x); + return 1; +} + +DECLARE_LUA_FUNCTION(bitwise_or){ + auto x = lua_tointeger(state, 1); + auto y = lua_tointeger(state, 2); + x |= y; + lua_pushinteger(state, x); + return 1; +} + +DECLARE_LUA_FUNCTION(bitwise_xor){ + auto x = lua_tointeger(state, 1); + auto y = lua_tointeger(state, 2); + x ^= y; + lua_pushinteger(state, x); + return 1; +} + +DECLARE_LUA_FUNCTION(bitwise_not){ + auto x = lua_tointeger(state, 1); + x = ~x; + lua_pushinteger(state, x); + return 1; +} + +DECLARE_LUA_FUNCTION(unload_image){ +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 1){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } + if (!lua_isnumber(state, 1)){ + handle_call_to_c_error(state, __FUNCTION__, "Parameter should be an integer."); + return 0; + } +#endif + auto core_state = get_interpreter(state); + auto res = core_state->unload_image((int)lua_tointeger(state, 1)); + if (!res.success) + handle_call_to_c_error(state, __FUNCTION__, res.message.c_str()); + return 0; +} + +DECLARE_LUA_FUNCTION(get_pixel){ +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 3){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } +#endif + int params[3]; + for (int i = 0; i < 3; i++){ +#ifndef MINIMIZE_CHECKING + if (!lua_isnumber(state, i + 1)){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be integers."); + return 0; + } +#endif + params[i] = (int)lua_tointeger(state, i + 1); + if (i && params[i] < 0){ + handle_call_to_c_error(state, __FUNCTION__, "Coordinates may not be negative."); + return 0; + } + } + + auto interpreter = get_interpreter(state); + auto res = interpreter->get_pixel(params[0], params[1], params[2]); + if (!res.success){ + handle_call_to_c_error(state, __FUNCTION__, res.message.c_str()); + return 0; + } + for (int i = 0; i < 4; i++) + lua_pushinteger(state, res.results[i]); + return 4; +} + +DECLARE_LUA_FUNCTION(get_image_dimensions){ + if (lua_gettop(state) < 1){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } + if (!lua_isnumber(state, 1)){ + handle_call_to_c_error(state, __FUNCTION__, "The parameter should be an integer."); + return 0; + } + int img = (int)lua_tointeger(state, 1); + auto interpreter = get_interpreter(state); + auto res = interpreter->get_image_dimensions(img); + + if (!res.success){ + handle_call_to_c_error(state, __FUNCTION__, res.message.c_str()); + return 0; + } + for (int i = 0; i < 2; i++) + lua_pushinteger(state, res.results[i]); + return 2; +} + +enum class ZigZagState{ + Initial = 0, + RightwardsOnTop, + DownLeft, + DownwardsOnLeft, + UpRight, + DownwardsOnRight, + RightwardsOnBottom, + End = -1, +}; + +DECLARE_LUA_FUNCTION(zig_zag_order){ + if (lua_gettop(state) < 5){ + handle_call_to_c_error(state, __FUNCTION__, "Not enough parameters."); + return 0; + } + int params[5]; + for (int i = 0; i < 5; i++){ + if (!lua_isnumber(state, i + 1)){ + handle_call_to_c_error(state, __FUNCTION__, "All parameters should be integers."); + return 0; + } + params[i] = (int)lua_tointeger(state, i + 1); + } + int x = params[0], + y = params[1], + w = params[2], + h = params[3]; + ZigZagState s = (ZigZagState)params[4]; + +#define allleft (!x) +#define allright (x == w - 1) +#define attop (!y) +#define atbottom (y == h - 1) + if (atbottom && allright) + s = ZigZagState::End; + for (int repeat = 1; repeat--; ){ + switch (s){ + case ZigZagState::Initial: + x = 0; + y = 0; + s = ZigZagState::RightwardsOnTop; + break; + case ZigZagState::RightwardsOnTop: + if (allright){ + s = ZigZagState::DownwardsOnRight; + repeat++; + break; + } + x++; + s = ZigZagState::DownLeft; + break; + case ZigZagState::DownLeft: + if (atbottom){ + s = ZigZagState::RightwardsOnBottom; + repeat++; + break; + } + if (allleft){ + s = ZigZagState::DownwardsOnLeft; + repeat++; + break; + } + x--; + y++; + //maintain state + break; + case ZigZagState::DownwardsOnLeft: + if (atbottom){ + s = ZigZagState::RightwardsOnBottom; + repeat++; + break; + } + y++; + s = ZigZagState::UpRight; + break; + case ZigZagState::UpRight: + if (allright){ + s = ZigZagState::DownwardsOnRight; + repeat++; + break; + } + if (attop){ + s = ZigZagState::RightwardsOnTop; + repeat++; + break; + } + x++; + y--; + //maintain state + break; + + + + case ZigZagState::DownwardsOnRight: + if (atbottom){ + s = ZigZagState::End; + repeat++; + break; + } + y++; + s = ZigZagState::DownLeft; + break; + case ZigZagState::RightwardsOnBottom: + if (allright){ + s = ZigZagState::End; + repeat++; + break; + } + x++; + s = ZigZagState::UpRight; + break; + case ZigZagState::End: + repeat = 0; + break; + } + } + lua_pushinteger(state, x); + lua_pushinteger(state, y); + lua_pushinteger(state, (int)s); + return 3; +} + +DECLARE_LUA_FUNCTION(get_displayed_image){ + lua_getglobal(state, current_image_global_name); + if (!lua_isnil(state, -1)) + return 1; + lua_pop(state, 1); + + auto interpreter = get_interpreter(state); + auto image = interpreter->get_caller_image(); + lua_pushinteger(state, image); + lua_setglobal(state, current_image_global_name); + lua_pushinteger(state, image); + return 1; +} + +DECLARE_LUA_FUNCTION(display_in_current_window){ + std::string msg; +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 1) + msg = "Not enough parameters."; + else if (!lua_isnumber(state, 1)) + msg = "The first parameter should be a number."; +#endif + if (!msg.size()){ + int handle = (int)lua_tointeger(state, 1); + auto interpreter = get_interpreter(state); + auto result = interpreter->display_in_current_window(handle); + if (result.success){ + lua_pushboolean(state, true); + return 1; + } + msg = result.message; + } + handle_call_to_c_error(state, __FUNCTION__, msg.c_str()); + lua_pushboolean(state, false); + return 1; +} + +DECLARE_LUA_FUNCTION(debug_print){ +#ifdef WIN32 + auto interpreter = get_interpreter(state); + std::string temp = lua_tostring(state, 1); + temp += "\r\n"; + interpreter->debug_print(temp.c_str()); +#endif + return 0; +} + +DECLARE_LUA_FUNCTION(show_message_box){ + std::string msg; +#ifndef MINIMIZE_CHECKING + if (lua_gettop(state) < 1) + msg = "Not enough parameters."; + else if (!lua_isstring(state, 1)) + msg = "The first parameter should be a string."; +#endif + if (!msg.size()){ + auto interpreter = get_interpreter(state); + interpreter->message_box(nullptr, lua_tostring(state, 1), false); + lua_pushboolean(state, true); + return 1; + } + handle_call_to_c_error(state, __FUNCTION__, msg.c_str()); + lua_pushboolean(state, false); + return 1; +} + +int lua_panic_function(lua_State *state){ + std::stringstream stream; + stream << "Lua threw an error: " << lua_tostring(state, -1); + auto interpreter = get_interpreter(state); + interpreter->message_box(nullptr, stream.str().c_str(), true); + throw LuaStackUnwind(); + return 0; +} + +#define EXPOSE_LUA_FUNCTION(x) { #x, x } + +std::shared_ptr init_lua_state(LuaInterpreter *interpreter){ + std::shared_ptr ret(luaL_newstate(), [](lua_State *state){ lua_close(state); }); + lua_State *state = ret.get(); + luaL_openlibs(state); + + luaL_Reg c_functions[] = { + EXPOSE_LUA_FUNCTION(load_image), + EXPOSE_LUA_FUNCTION(allocate_image), + EXPOSE_LUA_FUNCTION(unload_image), + EXPOSE_LUA_FUNCTION(traverse_image), + EXPOSE_LUA_FUNCTION(rgb_to_hsv), + EXPOSE_LUA_FUNCTION(hsv_to_rgb), + EXPOSE_LUA_FUNCTION(set_current_pixel), + EXPOSE_LUA_FUNCTION(save_image), + EXPOSE_LUA_FUNCTION(bitwise_and), + EXPOSE_LUA_FUNCTION(bitwise_or), + EXPOSE_LUA_FUNCTION(bitwise_xor), + EXPOSE_LUA_FUNCTION(bitwise_not), + EXPOSE_LUA_FUNCTION(get_pixel), + EXPOSE_LUA_FUNCTION(get_image_dimensions), + EXPOSE_LUA_FUNCTION(zig_zag_order), + EXPOSE_LUA_FUNCTION(display_in_current_window), + EXPOSE_LUA_FUNCTION(get_displayed_image), + EXPOSE_LUA_FUNCTION(debug_print), + EXPOSE_LUA_FUNCTION(show_message_box), + }; + for (auto &r : c_functions){ + lua_pushcfunction(state, r.func); + lua_setglobal(state, r.name); + } + + lua_pushlightuserdata(state, interpreter); + lua_setglobal(state, plugin_core_state_global_name); + + lua_atpanic(state, lua_panic_function); + + return ret; +} + diff --git a/src/plugin-core/Lua/lua.h b/src/plugin-core/Lua/lua.h new file mode 100644 index 0000000..74d85cb --- /dev/null +++ b/src/plugin-core/Lua/lua.h @@ -0,0 +1,28 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef BORDERLESSLUA_H +#define BORDERLESSLUA_H + +#include +#include + +class LuaInterpreter; + +bool get_lua_global_function(lua_State *state, const char *name); +void handle_call_to_c_error(lua_State *state, const char *function, const char *msg); +std::shared_ptr init_lua_state(LuaInterpreter *core_state); +int lua_panic_function(lua_State *state); + +class LuaStackUnwind : public std::exception{ +public: + const char *what() const noexcept override{ + return "Control flow exception."; + } +}; + +#endif diff --git a/src/plugin-core/Lua/main.cpp b/src/plugin-core/Lua/main.cpp new file mode 100644 index 0000000..d94e796 --- /dev/null +++ b/src/plugin-core/Lua/main.cpp @@ -0,0 +1,43 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "main.h" +#include "LuaInterpreter.h" +#include "../CallResultImpl.h" + +#ifdef WIN32 +#include + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ + switch (ul_reason_for_call){ + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +#endif + +LUA_PLUGIN_EXPORT_C LuaInterpreter *new_LuaInterpreter(LuaInterpreterParameters *parameters){ + return new LuaInterpreter(*parameters); +} + +LUA_PLUGIN_EXPORT_C void delete_LuaInterpreter(LuaInterpreter *interpreter){ + delete interpreter; +} + +LUA_PLUGIN_EXPORT_C void LuaInterpreter_execute(CallResult *result, LuaInterpreter *interpreter, const char *filename, const void *buffer, size_t size){ + auto r = interpreter->execute_buffer(filename, buffer, size); + if (result) + *result = r; +} + +LUA_PLUGIN_EXPORT_C void delete_LuaCallResult(CallResult *result){ + delete result->impl; +} diff --git a/src/plugin-core/Lua/main.h b/src/plugin-core/Lua/main.h new file mode 100644 index 0000000..48e63ea --- /dev/null +++ b/src/plugin-core/Lua/main.h @@ -0,0 +1,70 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef LUAINTERPRETERMAIN_H +#define LUAINTERPRETERMAIN_H + +#ifndef __cplusplus +#error Only use this file from C++! +#endif + +#include "../CallResult.h" + +#define LUA_PLUGIN_EXTERN_C extern "C" + +#if defined WIN32 && defined BUILDING_LUAINTERPRETER +#define LUA_PLUGIN_EXPORT_C LUA_PLUGIN_EXTERN_C __declspec(dllexport) +#else +#define LUA_PLUGIN_EXPORT_C LUA_PLUGIN_EXTERN_C +#endif + +class LuaInterpreter; +typedef void *external_state; + +struct ImageOperationResultExternal{ + bool success = true; + int results[4]; + char *message = nullptr; +}; + +struct image_info{ + int handle; + int w, h, stride, pitch; + void *pixels; +}; + +struct LuaInterpreterParameters{ + external_state state; + +#define LuaInterpreterParameters_DECLARE_FUNCTION(rt, x, ...) \ + typedef rt (*x##_f)(external_state, __VA_ARGS__); \ + x##_f x +#define LuaInterpreterParameters_DECLARE_FUNCTION0(rt, x) \ + typedef rt (*x##_f)(external_state); \ + x##_f x + LuaInterpreterParameters_DECLARE_FUNCTION(void, release_returned_string, char *); + LuaInterpreterParameters_DECLARE_FUNCTION(void, show_message_box, const char *title, const char *message, bool is_error); + LuaInterpreterParameters_DECLARE_FUNCTION(ImageOperationResultExternal, get_image_info, int handle, image_info *); + LuaInterpreterParameters_DECLARE_FUNCTION(ImageOperationResultExternal, load_image, const char *path); + LuaInterpreterParameters_DECLARE_FUNCTION(ImageOperationResultExternal, unload_image, int handle); + LuaInterpreterParameters_DECLARE_FUNCTION(ImageOperationResultExternal, allocate_image, int w, int h); + LuaInterpreterParameters_DECLARE_FUNCTION(ImageOperationResultExternal, save_image, int handle, const char *path, int compression, const char *format); + LuaInterpreterParameters_DECLARE_FUNCTION0(int, get_caller_image); + LuaInterpreterParameters_DECLARE_FUNCTION(void, display_in_current_window, int handle); + LuaInterpreterParameters_DECLARE_FUNCTION(void, debug_print, const char *string); +}; + +#define Lua_DECLARE_EXPORTED_FUNCTION(rt, x, ...) \ + typedef rt (*x##_f)(__VA_ARGS__); \ + LUA_PLUGIN_EXPORT_C rt x(__VA_ARGS__) + +Lua_DECLARE_EXPORTED_FUNCTION(LuaInterpreter *, new_LuaInterpreter, LuaInterpreterParameters *parameters); +Lua_DECLARE_EXPORTED_FUNCTION(void, delete_LuaInterpreter, LuaInterpreter *); +Lua_DECLARE_EXPORTED_FUNCTION(void, LuaInterpreter_execute, CallResult *result, LuaInterpreter *, const char *filename, const void *buffer, size_t size); +Lua_DECLARE_EXPORTED_FUNCTION(void, delete_LuaCallResult, CallResult *); + +#endif diff --git a/src/plugin-core/PluginCoreState.cpp b/src/plugin-core/PluginCoreState.cpp new file mode 100644 index 0000000..6fd55f0 --- /dev/null +++ b/src/plugin-core/PluginCoreState.cpp @@ -0,0 +1,358 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "PluginCoreState.h" +#include "../LoadedImage.h" +#include "../MainWindow.h" +#include "../ClangErrorMessage.hpp" +#include "../GenericException.h" +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#undef min +#endif + +const char * const accepted_cpp_extensions[] = { + "cpp", + "c", + "cc", + "cxx", + "c++", +}; +const size_t accepted_cpp_extensions_size = sizeof(accepted_cpp_extensions) / sizeof(*accepted_cpp_extensions); + +bool is_cpp_path(const QString &path){ + auto file_extension = QFileInfo(path).suffix(); + for (auto &ext : accepted_cpp_extensions) + if (!file_extension.compare(QString(ext), Qt::CaseInsensitive)) + return true; + return false; +} + +bool is_lua_path(const QString &path){ + auto file_extension = QFileInfo(path).suffix().toLower(); + return file_extension == "lua"; +} + +PluginCoreState::PluginCoreState(){ +} + +void PluginCoreState::execute(const QString &path){ + if (!QFile::exists(path)) + throw GenericException("File not found."); + if (is_cpp_path(path)) + this->execute_cpp(path); + if (is_lua_path(path)) + this->execute_lua(path); +} + +#define RESOLVE_FUNCTION(lib, x) auto x = (x##_f)lib.resolve(#x) +#define RESOLVE_FUNCTION2(lib, x) this->x = (x##_f)lib.resolve(#x) + +void PluginCoreState::execute_lua(const QString &path){ + if (!this->lua_library.isLoaded()){ + this->lua_library.setFileName("LuaInterpreter"); + this->lua_library.load(); + } + if (!this->lua_library.isLoaded()) + return; + this->caller_image_handle = -1; + QFile file(path); + file.open(QFile::ReadOnly); + if (!file.isOpen()) + throw GenericException("Unknown error while reading file."); + auto data = file.readAll(); + + auto filename = QFileInfo(path).fileName(); + + RESOLVE_FUNCTION(this->lua_library, new_LuaInterpreter); + RESOLVE_FUNCTION(this->lua_library, delete_LuaInterpreter); + RESOLVE_FUNCTION(this->lua_library, LuaInterpreter_execute); + RESOLVE_FUNCTION(this->lua_library, delete_LuaCallResult); + + auto params = this->construct_LuaInterpreterParameters(); + std::shared_ptr interpreter(new_LuaInterpreter(¶ms), [=](LuaInterpreter *i){ delete_LuaInterpreter(i); }); + + CallResult result; + LuaInterpreter_execute(&result, interpreter.get(), filename.toUtf8().toStdString().c_str(), data.data(), data.size()); + delete_LuaCallResult(&result); +} + +int PluginCoreState::get_caller_image_handle(){ + if (this->caller_image_handle >= 0) + return this->caller_image_handle; + return this->caller_image_handle = this->image_store.store(this->latest_caller->get_image()); +} + +void PluginCoreState::display_in_caller(int handle){ + this->display_in_caller(this->get_store().get_image(handle).get()); +} + +void PluginCoreState::display_in_caller(Image *image){ + if (image) + this->latest_caller->display_filtered_image(std::make_shared(image->get_bitmap())); +} + +char *clone_string(const char *s){ + if (!s) + return nullptr; + auto n = strlen(s); + auto ret = new char[n + 1]; + memcpy(ret, s, n); + ret[n] = 0; + return ret; +} + +char *clone_string(const std::string &s){ + auto n = s.size(); + if (!n) + return nullptr; + auto ret = new char[n + 1]; + memcpy(ret, &s[0], n); + ret[n] = 0; + return ret; +} + +ImageOperationResultExternal to_ImageOperationResultExternal(const ImageOperationResult &src){ + ImageOperationResultExternal ret; + ret.success = src.success; + static_assert(sizeof(ret.results) == sizeof(src.results), "Inconsistent struct definitions!"); + memcpy(ret.results, src.results, sizeof(ret.results)); + ret.message = clone_string(src.message); + return ret; +} + +namespace lua_implementations{ +#define LUA_FUNCTION_SIGNATURE(rt, x, ...) rt x(external_state state, __VA_ARGS__) +#define LUA_FUNCTION_SIGNATURE0(rt, x) rt x(external_state state) + +LUA_FUNCTION_SIGNATURE(void, release_returned_string, char *s){ + delete[] s; +} + +LUA_FUNCTION_SIGNATURE(void, show_message_box, const char *title, const char *message, bool is_error){ + QMessageBox msgbox; + if (title) + msgbox.setWindowTitle(QString::fromUtf8(title)); + msgbox.setText(QString::fromUtf8(message)); + if (is_error) + msgbox.setIcon(QMessageBox::Critical); + msgbox.exec(); +} + +LUA_FUNCTION_SIGNATURE(ImageOperationResultExternal, get_image_info, int handle, image_info *info){ + ImageOperationResultExternal ret; + auto This = (PluginCoreState *)state; + auto image = This->get_store().get_image(handle); + if (!image){ + ret.success = false; + ret.message = clone_string(HANDLE_NOT_FOUND_MSG); + return ret; + } + info->handle = handle; + unsigned stride, pitch; + info->pixels = image->get_pixels_pointer(stride, pitch); + info->stride = stride; + info->pitch = pitch; + auto temp = image->get_dimensions(); + info->w = temp.results[0]; + info->h = temp.results[1]; + ret.success = true; + return ret; +} + +LUA_FUNCTION_SIGNATURE(ImageOperationResultExternal, load_image, const char *path){ + auto This = (PluginCoreState *)state; + return to_ImageOperationResultExternal(This->get_store().load(path)); +} + +LUA_FUNCTION_SIGNATURE(ImageOperationResultExternal, unload_image, int handle){ + auto This = (PluginCoreState *)state; + return to_ImageOperationResultExternal(This->get_store().unload(handle)); +} + +LUA_FUNCTION_SIGNATURE(ImageOperationResultExternal, allocate_image, int w, int h){ + auto This = (PluginCoreState *)state; + return to_ImageOperationResultExternal(This->get_store().allocate(w, h)); +} + +LUA_FUNCTION_SIGNATURE(ImageOperationResultExternal, save_image, int handle, const char *path, int compression, const char *format){ + auto This = (PluginCoreState *)state; + SaveOptions opt; + opt.compression = compression; + if (format) + opt.format = format; + return to_ImageOperationResultExternal(This->get_store().save(handle, QString::fromUtf8(path), opt)); +} + +LUA_FUNCTION_SIGNATURE0(int, get_caller_image){ + auto This = (PluginCoreState *)state; + return This->get_caller_image_handle(); +} + +LUA_FUNCTION_SIGNATURE(void, display_in_current_window, int handle){ + auto This = (PluginCoreState *)state; + This->display_in_caller(handle); +} + +LUA_FUNCTION_SIGNATURE(void, debug_print, const char *string){ +#ifdef WIN32 + auto temp = QString::fromUtf8(string); + OutputDebugStringW(temp.toStdWString().c_str()); +#endif +} + +} + +LuaInterpreterParameters PluginCoreState::construct_LuaInterpreterParameters(){ + LuaInterpreterParameters ret; + ret.state = this; +#define PASS_FUNCTION_TO_LUA(x) ret.x = lua_implementations::x + PASS_FUNCTION_TO_LUA(release_returned_string); + PASS_FUNCTION_TO_LUA(show_message_box); + PASS_FUNCTION_TO_LUA(get_image_info); + PASS_FUNCTION_TO_LUA(load_image); + PASS_FUNCTION_TO_LUA(unload_image); + PASS_FUNCTION_TO_LUA(allocate_image); + PASS_FUNCTION_TO_LUA(save_image); + PASS_FUNCTION_TO_LUA(get_caller_image); + PASS_FUNCTION_TO_LUA(display_in_current_window); + PASS_FUNCTION_TO_LUA(debug_print); + + return ret; +} + +namespace cpp_implementations{ + +QThreadStorage tls; + +#define CPP_FUNCTION_SIGNATURE(rt, x, ...) rt x(external_state state, __VA_ARGS__) +#define CPP_FUNCTION_SIGNATURE0(rt, x) rt x(external_state state) + +CPP_FUNCTION_SIGNATURE(void, release_returned_string, char *s){ + delete[] s; +} + +CPP_FUNCTION_SIGNATURE(void, store_tls, void *s){ + auto This = (PluginCoreState *)tls.localData(); + This->store_tls(s); +} + +CPP_FUNCTION_SIGNATURE0(void *, retrieve_tls){ + auto This = (PluginCoreState *)tls.localData(); + return This->retrieve_tls(); +} + +CPP_FUNCTION_SIGNATURE(void, display_in_current_window, void *image){ + if (!image) + return; + auto This = (PluginCoreState *)tls.localData(); + This->display_in_caller((Image *)image); +} + +CPP_FUNCTION_SIGNATURE(bool, get_file_sha1, const char *path, unsigned char *buffer, size_t buffer_size){ + auto qpath = QString::fromUtf8(path); + QCryptographicHash hash(QCryptographicHash::Sha1); + QFile file(qpath); + file.open(QFile::ReadOnly); + if (!file.isOpen()) + return false; + hash.addData(&file); + auto result = hash.result(); + memcpy(buffer, result.constData(), std::min(result.size(), buffer_size)); + return true; +} + +} + +void *PluginCoreState::get_image_pointer(){ + return this->image_store.get_image(this->get_caller_image_handle()).get(); +} + +CppInterpreterParameters PluginCoreState::construct_CppInterpreterParameters(){ + CppInterpreterParameters ret; + ret.state = this; + ret.caller_image = this->get_image_pointer(); +#define PASS_FUNCTION_TO_CPP(x) ret.x = cpp_implementations::x + PASS_FUNCTION_TO_CPP(release_returned_string); + PASS_FUNCTION_TO_CPP(store_tls); + PASS_FUNCTION_TO_CPP(retrieve_tls); + PASS_FUNCTION_TO_CPP(display_in_current_window); + PASS_FUNCTION_TO_CPP(get_file_sha1); + + return ret; +} + +void PluginCoreState::execute_cpp(const QString &path){ + this->caller_image_handle = -1; + { + QFile file(path); + file.open(QFile::ReadOnly); + if (!file.isOpen()) + throw GenericException("Unknown error while reading file."); + } + if (this->cpp_interpreter){ + this->execute_cpp_ready(path); + return; + } + if (!this->cpp_library.isLoaded()){ + this->cpp_library.setFileName("CppInterpreter"); + this->cpp_library.load(); + } + if (!this->cpp_library.isLoaded()) + return; + + RESOLVE_FUNCTION(this->cpp_library, new_CppInterpreter); + RESOLVE_FUNCTION(this->cpp_library, delete_CppInterpreter); + RESOLVE_FUNCTION2(this->cpp_library, CppInterpreter_execute); + RESOLVE_FUNCTION2(this->cpp_library, delete_CppCallResult); + RESOLVE_FUNCTION2(this->cpp_library, CppInterpreter_reset_imag); + + auto params = this->construct_CppInterpreterParameters(); + this->cpp_interpreter.reset(new_CppInterpreter(¶ms), [=](CppInterpreter *i){ delete_CppInterpreter(i); }); + + this->execute_cpp_ready(path); +} + +void PluginCoreState::execute_cpp_ready(const QString &path){ + CppInterpreter_reset_imag(this->cpp_interpreter.get(), this->get_image_pointer()); + auto old_tls = cpp_implementations::tls.localData(); + cpp_implementations::tls.setLocalData((uintptr_t)this); + auto old_size = this->cpp_tls_size; + this->cpp_tls_size = this->cpp_tls.size(); + + CallResult result; + auto parameter = QDir::toNativeSeparators(path).toUtf8().toStdString(); + this->CppInterpreter_execute(&result, this->cpp_interpreter.get(), parameter.c_str()); + if (!result.success){ + ClangErrorMessage msgbox; + msgbox.set_error_message(QString::fromUtf8(result.error_message)); + msgbox.exec(); + } + this->delete_CppCallResult(&result); + + this->cpp_tls.resize(this->cpp_tls_size); + this->cpp_tls_size = old_size; + cpp_implementations::tls.setLocalData(old_tls); +} + +void PluginCoreState::store_tls(void *p){ + if (this->cpp_tls_size == this->cpp_tls.size()) + this->cpp_tls.push_back(p); + else + this->cpp_tls.back() = p; +} + +void *PluginCoreState::retrieve_tls(){ + if (this->cpp_tls_size == this->cpp_tls.size()) + return nullptr; + return this->cpp_tls.back(); +} diff --git a/src/plugin-core/PluginCoreState.h b/src/plugin-core/PluginCoreState.h new file mode 100644 index 0000000..4eed944 --- /dev/null +++ b/src/plugin-core/PluginCoreState.h @@ -0,0 +1,65 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef PLUGINCORESTATE_H +#define PLUGINCORESTATE_H + +#include "ImageStore.h" +#include +#include +#include +#include +#include "Lua/main.h" +#include "Cpp/main.h" + +class QString; +class MainWindow; + +class PluginCoreState{ + MainWindow *latest_caller = nullptr; + ImageStore image_store; + QLibrary lua_library; + QLibrary cpp_library; + std::vector cpp_tls; + size_t cpp_tls_size; + int caller_image_handle = -1; + std::shared_ptr cpp_interpreter; + void (*CppInterpreter_execute)(CallResult *, CppInterpreter *, const char *); + void (*delete_CppCallResult)(CallResult *); + void (*CppInterpreter_reset_imag)(CppInterpreter *, external_state); + + void execute_lua(const QString &); + void execute_cpp(const QString &); + void execute_cpp_ready(const QString &); + void *get_image_pointer(); +public: + PluginCoreState(); + void set_current_caller(MainWindow *mw){ + this->latest_caller = mw; + } + void execute(const QString &path); + MainWindow *get_caller() const{ + assert(!!this->latest_caller); + return this->latest_caller; + } + ImageStore &get_store(){ + return this->image_store; + } + LuaInterpreterParameters construct_LuaInterpreterParameters(); + CppInterpreterParameters construct_CppInterpreterParameters(); + int get_caller_image_handle(); + void display_in_caller(int handle); + void display_in_caller(Image *img); + void store_tls(void *); + void *retrieve_tls(); +}; + +bool is_cpp_path(const QString &); +extern const char * const accepted_cpp_extensions[]; +extern const size_t accepted_cpp_extensions_size; + +#endif diff --git a/src/plugin-core/capi.cpp b/src/plugin-core/capi.cpp new file mode 100644 index 0000000..fe00b1c --- /dev/null +++ b/src/plugin-core/capi.cpp @@ -0,0 +1,104 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "capi.h" +#include "ImageStore.h" +#include "PluginCoreState.h" +#include +#include +#include +#ifdef WIN32 +#include +#endif + +EXPORT_C Image *load_image(PluginCoreState *state, const char *path){ + return state->get_store().load_image(path); +} + +EXPORT_C Image *allocate_image(PluginCoreState *state, int w, int h){ + return state->get_store().allocate_image(w, h); +} + +EXPORT_C Image *clone_image(Image *){ + return nullptr; +} + +EXPORT_C Image *clone_image_without_data(Image *){ + return nullptr; +} + +EXPORT_C void unload_image(Image *image){ + auto store = image->get_owner(); + store->unload(image); +} + +EXPORT_C void get_image_dimensions(Image *image, int *w, int *h){ + image->get_dimensions(*w, *h); +} + +EXPORT_C u8 *get_image_pixel_data(Image *image, int *stride, int *pitch){ + unsigned temp1, temp2; + auto ret = (u8 *)image->get_pixels_pointer(temp1, temp2); + *stride = temp1; + *pitch = temp2; + return ret; +} + + +EXPORT_C Image *get_displayed_image(PluginCoreState *state){ + auto handle = state->get_caller_image_handle(); + return state->get_store().get_image(handle).get(); +} + +EXPORT_C void display_in_current_window(PluginCoreState *state, Image *image){ + state->display_in_caller(image); +} + +EXPORT_C void rgb_to_hsv(u8_quad *, u8_quad){ +} + +EXPORT_C void hsv_to_rgb(u8_quad *, u8_quad){ + +} + +#ifdef WIN32 +EXPORT_C void debug_print(const char *string){ + auto w = QString::fromUtf8(string).toStdWString(); + OutputDebugStringW(w.c_str()); +#else +EXPORT_C void debug_print(const char *){ +#endif +} + +EXPORT_C void show_message_box(const char *string){ + QMessageBox msgbox; + msgbox.setText(QString::fromUtf8(string)); + msgbox.exec(); +} + +EXPORT_C int save_image(Image *image, const char *path){ + image->save(QString::fromUtf8(path), SaveOptions()); + return false; +} + +EXPORT_C double borderless_clock(){ + return clock() / (double)CLOCKS_PER_SEC; +} + +EXPORT_C char *double_to_string(double x){ + std::stringstream stream; + stream << x; + auto s = stream.str(); + auto ret = new char[s.size() + 1]; + ret[s.size()] = 0; + memcpy(ret, &s[0], s.size()); + return ret; +} + +EXPORT_C void release_double_to_string(char *s){ + delete[] s; +} diff --git a/src/plugin-core/capi.h b/src/plugin-core/capi.h new file mode 100644 index 0000000..5ea5b69 --- /dev/null +++ b/src/plugin-core/capi.h @@ -0,0 +1,75 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#ifndef CAPI_H +#define CAPI_H + +#ifndef __cplusplus +#define EXTERN_C +#else +#define EXTERN_C extern "C" +#endif + +#if defined WIN32 && defined BUILDING_BORDERLESS +#define EXPORT_C EXTERN_C __declspec(dllexport) +#else +#define EXPORT_C EXTERN_C +#endif + +#if defined BUILDING_BORDERLESS || defined __cplusplus +class PluginCoreState; +class Image; +#else +typedef void PluginCoreState; +typedef void Image; +#endif + +typedef unsigned char u8; + +struct u8_quad{ + u8 data[4]; +}; + +typedef struct u8_quad u8_quad; + +/* Note: Paths must be UTF-8 strings.*/ + +/* Image constructors. */ + +EXPORT_C Image *load_image(PluginCoreState *state, const char *path); +EXPORT_C Image *allocate_image(PluginCoreState *state, int w, int h); +EXPORT_C Image *clone_image(Image *image); +EXPORT_C Image *clone_image_without_data(Image *image); +EXPORT_C void unload_image(Image *image); + + +/* Image property accessors. */ + +EXPORT_C void get_image_dimensions(Image *image, int *w, int *h); +EXPORT_C u8 *get_image_pixel_data(Image *image, int *stride, int *pitch); + + +/* Image display functions. */ +EXPORT_C Image *get_displayed_image(PluginCoreState *state); +EXPORT_C void display_in_current_window(PluginCoreState *state, Image *image); + +/* Utility functions. */ + +EXPORT_C void rgb_to_hsv(u8_quad *hsv, u8_quad rgb); +EXPORT_C void hsv_to_rgb(u8_quad *rgb, u8_quad hsv); +EXPORT_C void debug_print(const char *string); +EXPORT_C void show_message_box(const char *string); + + +/* Miscellaneous functions. */ + +EXPORT_C int save_image(Image *image, const char *path); +EXPORT_C double borderless_clock(); +EXPORT_C char *double_to_string(double); +EXPORT_C void release_double_to_string(char *); + +#endif diff --git a/src/resources.qrc b/src/resources.qrc index 5592247..68a48af 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -1,5 +1,6 @@ - - - resources/alpha.png - - + + + resources/alpha.png + resources/icons/icon16.png + + diff --git a/src/serialization/ApplicationState.h b/src/serialization/ApplicationState.h new file mode 100644 index 0000000..13b784a --- /dev/null +++ b/src/serialization/ApplicationState.h @@ -0,0 +1,4 @@ +public: + ApplicationState(){} + DEFINE_INLINE_GETTER(windows) + DEFINE_INLINE_NONCONST_GETTER(windows) diff --git a/src/serialization/DoubleQuadTuple.h b/src/serialization/DoubleQuadTuple.h new file mode 100644 index 0000000..97d1d12 --- /dev/null +++ b/src/serialization/DoubleQuadTuple.h @@ -0,0 +1,6 @@ +public: + DoubleQuadTuple(double x0 = 1, double x1 = 0, double x2 = 0, double x3 = 1) : x0(x0), x1(x1), x2(x2), x3(x3) {} + DoubleQuadTuple(const QMatrix &mat): DoubleQuadTuple(mat.m11(), mat.m21(), mat.m12(), mat.m22()){} + QMatrix to_QMatrix() const{ + return QMatrix(this->x0, this->x2, this->x1, this->x3, 0, 0); + } diff --git a/src/serialization/Implementations.cpp b/src/serialization/Implementations.cpp new file mode 100644 index 0000000..f55473e --- /dev/null +++ b/src/serialization/Implementations.cpp @@ -0,0 +1,24 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "settings.generated.h" + +#define DEFINE_TRIVIAL_IMPLEMENTATIONS(x) x::~x(){} void x::rollback_deserialization(){} + +DEFINE_TRIVIAL_IMPLEMENTATIONS(IntPair) +DEFINE_TRIVIAL_IMPLEMENTATIONS(UintPair) +DEFINE_TRIVIAL_IMPLEMENTATIONS(DoubleQuadTuple) +DEFINE_TRIVIAL_IMPLEMENTATIONS(WindowState) +DEFINE_TRIVIAL_IMPLEMENTATIONS(ApplicationState) +DEFINE_TRIVIAL_IMPLEMENTATIONS(Settings) +DEFINE_TRIVIAL_IMPLEMENTATIONS(MainSettings) +DEFINE_TRIVIAL_IMPLEMENTATIONS(Shortcuts) + +void WindowState::set_using_checkerboard_pattern(bool b){ + this->using_checkerboard_pattern = b; + this->using_checkerboard_pattern_updated = true; +} diff --git a/src/serialization/Inlining.cpp b/src/serialization/Inlining.cpp new file mode 100644 index 0000000..3849bdb --- /dev/null +++ b/src/serialization/Inlining.cpp @@ -0,0 +1,12 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "settings.generated.cpp" +#include "settings.aux.generated.cpp" +#include "../../serialization/postsrc/DeserializerStream.cpp" +#include "../../serialization/postsrc/Serializable.cpp" +#include "../../serialization/postsrc/SerializerStream.cpp" diff --git a/src/serialization/IntPair.h b/src/serialization/IntPair.h new file mode 100644 index 0000000..84429d4 --- /dev/null +++ b/src/serialization/IntPair.h @@ -0,0 +1,6 @@ +public: + IntPair(int x = 0, int y = 0): x(x), y(y){} + IntPair(const QPoint &point): IntPair(point.x(), point.y()){} + QPoint to_QPoint() const{ + return QPoint(this->x, this->y); + } \ No newline at end of file diff --git a/src/serialization/MainSettings.cpp b/src/serialization/MainSettings.cpp new file mode 100644 index 0000000..4e710fe --- /dev/null +++ b/src/serialization/MainSettings.cpp @@ -0,0 +1,31 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "settings.generated.h" +#include "../Enums.h" + +MainSettings::MainSettings(){ + this->clamp_strength = 25; + this->clamp_to_edges = true; + this->use_checkerboard_pattern = true; + this->center_when_displayed = true; + this->keep_application_in_background = true; + this->set_zoom_mode_for_new_windows(ZoomMode::Normal); + this->set_fullscreen_zoom_mode_for_new_windows(ZoomMode::AutoFit); +} + +bool MainSettings::operator==(const MainSettings &other) const{ +#define CHECK_EQUALITY(x) if (this->x != other.x) return false + CHECK_EQUALITY(clamp_strength); + CHECK_EQUALITY(clamp_to_edges); + CHECK_EQUALITY(use_checkerboard_pattern); + CHECK_EQUALITY(center_when_displayed); + CHECK_EQUALITY(zoom_mode_for_new_windows); + CHECK_EQUALITY(fullscreen_zoom_mode_for_new_windows); + CHECK_EQUALITY(keep_application_in_background); + return true; +} diff --git a/src/serialization/MainSettings.h b/src/serialization/MainSettings.h new file mode 100644 index 0000000..d0a9ad4 --- /dev/null +++ b/src/serialization/MainSettings.h @@ -0,0 +1,13 @@ +public: +MainSettings(); +DEFINE_INLINE_SETTER_GETTER(clamp_strength) +DEFINE_INLINE_SETTER_GETTER(clamp_to_edges) +DEFINE_INLINE_SETTER_GETTER(use_checkerboard_pattern) +DEFINE_INLINE_SETTER_GETTER(center_when_displayed) +DEFINE_ENUM_INLINE_SETTER_GETTER(ZoomMode, zoom_mode_for_new_windows) +DEFINE_ENUM_INLINE_SETTER_GETTER(ZoomMode, fullscreen_zoom_mode_for_new_windows) +DEFINE_INLINE_SETTER_GETTER(keep_application_in_background) +bool operator==(const MainSettings &other) const; +bool operator!=(const MainSettings &other) const{ + return !(*this == other); +} diff --git a/src/serialization/Settings.h b/src/serialization/Settings.h new file mode 100644 index 0000000..78f8ca8 --- /dev/null +++ b/src/serialization/Settings.h @@ -0,0 +1,2 @@ +public: + Settings(){} diff --git a/src/serialization/Shortcuts.h b/src/serialization/Shortcuts.h new file mode 100644 index 0000000..6fc3f02 --- /dev/null +++ b/src/serialization/Shortcuts.h @@ -0,0 +1,3 @@ +public: + Shortcuts(){} + void initialize_to_defaults(); diff --git a/src/serialization/ShortcutsSettings.cpp b/src/serialization/ShortcutsSettings.cpp new file mode 100644 index 0000000..b856c4c --- /dev/null +++ b/src/serialization/ShortcutsSettings.cpp @@ -0,0 +1,93 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "settings.generated.h" +#include "../ShortcutInfo.h" +#include + +#define DEFINE_COMMAND_INTERNAL_NAME(x) const char *x##_command = #x + +DEFINE_COMMAND_INTERNAL_NAME(back); +DEFINE_COMMAND_INTERNAL_NAME(background_swap); +DEFINE_COMMAND_INTERNAL_NAME(close); +DEFINE_COMMAND_INTERNAL_NAME(cycle_zoom_mode); +DEFINE_COMMAND_INTERNAL_NAME(down); +DEFINE_COMMAND_INTERNAL_NAME(down_big); +DEFINE_COMMAND_INTERNAL_NAME(flip_h); +DEFINE_COMMAND_INTERNAL_NAME(flip_v); +DEFINE_COMMAND_INTERNAL_NAME(go_to_end); +DEFINE_COMMAND_INTERNAL_NAME(go_to_start); +DEFINE_COMMAND_INTERNAL_NAME(left); +DEFINE_COMMAND_INTERNAL_NAME(left_big); +DEFINE_COMMAND_INTERNAL_NAME(minimize); +DEFINE_COMMAND_INTERNAL_NAME(minimize_all); +DEFINE_COMMAND_INTERNAL_NAME(next); +DEFINE_COMMAND_INTERNAL_NAME(quit); +DEFINE_COMMAND_INTERNAL_NAME(quit2); +DEFINE_COMMAND_INTERNAL_NAME(reset_zoom); +DEFINE_COMMAND_INTERNAL_NAME(right); +DEFINE_COMMAND_INTERNAL_NAME(right_big); +DEFINE_COMMAND_INTERNAL_NAME(rotate_left); +DEFINE_COMMAND_INTERNAL_NAME(rotate_left_fine); +DEFINE_COMMAND_INTERNAL_NAME(rotate_right); +DEFINE_COMMAND_INTERNAL_NAME(rotate_right_fine); +DEFINE_COMMAND_INTERNAL_NAME(show_options); +DEFINE_COMMAND_INTERNAL_NAME(toggle_fullscreen); +DEFINE_COMMAND_INTERNAL_NAME(toggle_lock_zoom); +DEFINE_COMMAND_INTERNAL_NAME(up); +DEFINE_COMMAND_INTERNAL_NAME(up_big); +DEFINE_COMMAND_INTERNAL_NAME(zoom_in); +DEFINE_COMMAND_INTERNAL_NAME(zoom_out); + +#define SETUP_DEFAULT_SHORTCUT1(x, y, z) ret[y] = ShortcutInfo(x, y, z) +#define SETUP_DEFAULT_SHORTCUT2(x, y, z, z2) ret[y] = ShortcutInfo(x, y, z, z2) + +std::map get_default_shortcuts() { + std::map ret; + SETUP_DEFAULT_SHORTCUT1("Quit", quit_command, "Q"); + SETUP_DEFAULT_SHORTCUT1("Quit without saving windows", quit2_command, "Ctrl+Q"); + SETUP_DEFAULT_SHORTCUT2("Next image", next_command, "Space", "Right"); + SETUP_DEFAULT_SHORTCUT2("Previous image", back_command, "Backspace", "Left"); + SETUP_DEFAULT_SHORTCUT1("Change background mode", background_swap_command, "B"); + SETUP_DEFAULT_SHORTCUT1("Close current", close_command, "Escape"); + SETUP_DEFAULT_SHORTCUT1("Zoom in", zoom_in_command, "+"); + SETUP_DEFAULT_SHORTCUT1("Zoom out", zoom_out_command, "-"); + SETUP_DEFAULT_SHORTCUT1("Reset image transform", reset_zoom_command, "Shift+R"); + SETUP_DEFAULT_SHORTCUT1("Move up", up_command, "Ctrl+Up"); + SETUP_DEFAULT_SHORTCUT1("Move down", down_command, "Ctrl+Down"); + SETUP_DEFAULT_SHORTCUT1("Move left", left_command, "Ctrl+Left"); + SETUP_DEFAULT_SHORTCUT1("Move right", right_command, "Ctrl+Right"); + SETUP_DEFAULT_SHORTCUT1("Move up (big step)", up_big_command, "Page Up"); + SETUP_DEFAULT_SHORTCUT1("Move down (big step)", down_big_command, "Page Down"); + SETUP_DEFAULT_SHORTCUT1("Move left (big step)", left_big_command, "Ctrl+Page Up"); + SETUP_DEFAULT_SHORTCUT1("Move right (big step)", right_big_command, "Ctrl+Page Down"); + SETUP_DEFAULT_SHORTCUT1("Change fit mode", cycle_zoom_mode_command, "F"); + SETUP_DEFAULT_SHORTCUT1("Toggle zoom lock", toggle_lock_zoom_command, "Shift+L"); + SETUP_DEFAULT_SHORTCUT1("Go to first image", go_to_start_command, "Home"); + SETUP_DEFAULT_SHORTCUT1("Go to last image", go_to_end_command, "End"); + SETUP_DEFAULT_SHORTCUT1("Show options dialog", show_options_command, "O"); + SETUP_DEFAULT_SHORTCUT2("Toggle fullscreen", toggle_fullscreen_command, "Return", "Enter"); + SETUP_DEFAULT_SHORTCUT1("Mirror horizontally", flip_h_command, "H"); + SETUP_DEFAULT_SHORTCUT1("Mirror vertically", flip_v_command, "V"); + SETUP_DEFAULT_SHORTCUT1("Minimize current window", minimize_command, "M"); + SETUP_DEFAULT_SHORTCUT1("Minimize all windows", minimize_all_command, "Shift+M"); + SETUP_DEFAULT_SHORTCUT1("Rotate left", rotate_left_command, "L"); + SETUP_DEFAULT_SHORTCUT1("Rotate right", rotate_right_command, "R"); + return ret; +} + +void Shortcuts::initialize_to_defaults(){ + auto shortcuts = get_default_shortcuts(); + for (auto &s : shortcuts) { + auto key = s.second.internal_name; + auto &v = this->shortcuts[key]; + for (size_t i = 0; i < s.second.sequences_count; i++) { + auto str = s.second.default_sequences_str[i]; + v.push_back(std::wstring(str, str + strlen(str))); + } + } +} diff --git a/src/serialization/UintPair.h b/src/serialization/UintPair.h new file mode 100644 index 0000000..61755c0 --- /dev/null +++ b/src/serialization/UintPair.h @@ -0,0 +1,6 @@ +public: + UintPair(unsigned x = 0, unsigned y = 0) : x(x), y(y) {} + UintPair(const QSize &size) : UintPair(size.width(), size.height()) {} + QSize to_QSize() const{ + return QSize(this->x, this->y); + } diff --git a/src/serialization/WindowState.cpp b/src/serialization/WindowState.cpp new file mode 100644 index 0000000..beb3f96 --- /dev/null +++ b/src/serialization/WindowState.cpp @@ -0,0 +1,19 @@ +/* +Copyright (c), Helios +All rights reserved. + +Distributed under a permissive license. See COPYING.txt for details. +*/ + +#include "settings.generated.h" +#include "../Enums.h" + +WindowState::WindowState(){ + this->using_checkerboard_pattern = true; + this->zoom = 1; + this->fullscreen = false; + this->zoom_mode = (std::uint32_t)ZoomMode::Normal; + this->fullscreen_zoom_mode = (std::uint32_t)ZoomMode::AutoFit; + this->border_size = this->default_border_size; + this->movement_size = 100; +} diff --git a/src/serialization/WindowState.h b/src/serialization/WindowState.h new file mode 100644 index 0000000..7e3b62d --- /dev/null +++ b/src/serialization/WindowState.h @@ -0,0 +1,27 @@ +private: + bool using_checkerboard_pattern_updated; +public: + WindowState(); + DEFINE_INLINE_SETTER_GETTER(pos) + DEFINE_INLINE_SETTER_GETTER(size) + DEFINE_INLINE_SETTER_GETTER(label_pos) + DEFINE_INLINE_GETTER(using_checkerboard_pattern) + void set_using_checkerboard_pattern(bool); + void flip_using_checkerboard_pattern(){ + this->set_using_checkerboard_pattern(!this->using_checkerboard_pattern); + } + DEFINE_INLINE_SETTER_GETTER(using_checkerboard_pattern_updated) + DEFINE_INLINE_SETTER_GETTER(current_directory) + DEFINE_INLINE_SETTER_GETTER(current_filename) + DEFINE_INLINE_SETTER_GETTER(zoom) + DEFINE_INLINE_SETTER_GETTER(fullscreen_zoom) + DEFINE_INLINE_SETTER_GETTER(fullscreen) + DEFINE_ENUM_INLINE_SETTER_GETTER(ZoomMode, zoom_mode) + DEFINE_ENUM_INLINE_SETTER_GETTER(ZoomMode, fullscreen_zoom_mode) + DEFINE_INLINE_SETTER_GETTER(movement_size) + DEFINE_INLINE_SETTER_GETTER(transform) + DEFINE_INLINE_SETTER_GETTER(border_size) + static const decltype(border_size) default_border_size = 50; + void reset_border_size(){ + this->border_size = default_border_size; + } diff --git a/src/serialization/settings.aux.h b/src/serialization/settings.aux.h new file mode 100644 index 0000000..72265c8 --- /dev/null +++ b/src/serialization/settings.aux.h @@ -0,0 +1,12 @@ +#include "../Enums.h" +#include +#include +#include + +#define DEFINE_INLINE_GETTER(x) const decltype(x) &get_##x() const{ return this->x; } +#define DEFINE_INLINE_NONCONST_GETTER(x) decltype(x) &get_##x(){ return this->x; } +#define DEFINE_INLINE_SETTER(x) void set_##x(const decltype(x) &v){ this->x = v; } +#define DEFINE_ENUM_INLINE_GETTER(t, x) t get_##x() const{ return (t)this->x; } +#define DEFINE_ENUM_INLINE_SETTER(t, x) void set_##x(const t &v){ this->x = (decltype(this->x))v; } +#define DEFINE_INLINE_SETTER_GETTER(x) DEFINE_INLINE_GETTER(x) DEFINE_INLINE_SETTER(x) +#define DEFINE_ENUM_INLINE_SETTER_GETTER(t, x) DEFINE_ENUM_INLINE_GETTER(t, x) DEFINE_ENUM_INLINE_SETTER(t, x) diff --git a/src/serialization/settings.txt b/src/serialization/settings.txt new file mode 100644 index 0000000..e9a8036 --- /dev/null +++ b/src/serialization/settings.txt @@ -0,0 +1,61 @@ +cpp settings{ + struct IntPair{ + int32_t x; + int32_t y; + #include "IntPair.h" + } + struct UintPair{ + uint32_t x; + uint32_t y; + #include "UintPair.h" + } + struct DoubleQuadTuple{ + double x0; + double x1; + double x2; + double x3; + #include "DoubleQuadTuple.h" + } + class WindowState{ + IntPair pos; + UintPair size; + IntPair label_pos; + bool using_checkerboard_pattern; + wstring current_directory; + wstring current_filename; + double zoom; + double fullscreen_zoom; + bool fullscreen; + uint32_t zoom_mode; + uint32_t fullscreen_zoom_mode; + uint32_t border_size; + int32_t movement_size; + DoubleQuadTuple transform; + #include "WindowState.h" + } + class MainSettings{ + uint32_t clamp_strength; + bool clamp_to_edges; + bool use_checkerboard_pattern; + bool center_when_displayed; + uint32_t zoom_mode_for_new_windows; + uint32_t fullscreen_zoom_mode_for_new_windows; + bool keep_application_in_background; + #include "MainSettings.h" + } + class ApplicationState{ + vector> windows; + #include "ApplicationState.h" + } + class Shortcuts{ + public: + map> shortcuts; + #include "Shortcuts.h" + } + struct Settings{ + shared_ptr main; + shared_ptr state; + shared_ptr shortcuts; + #include "Settings.h" + } +} diff --git a/src/stdafx.h b/src/stdafx.h new file mode 100644 index 0000000..e69de29