diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:29:28 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:29:28 +0200 |
commit | 75c07011b7c4d06acd7b45dabdcd60ab9d80f385 (patch) | |
tree | 8853c3978dd152ef377e652239448b1352320206 /ui | |
parent | 5.22 (diff) | |
download | FreeFileSync-75c07011b7c4d06acd7b45dabdcd60ab9d80f385.tar.gz FreeFileSync-75c07011b7c4d06acd7b45dabdcd60ab9d80f385.tar.bz2 FreeFileSync-75c07011b7c4d06acd7b45dabdcd60ab9d80f385.zip |
5.23
Diffstat (limited to 'ui')
53 files changed, 0 insertions, 22333 deletions
diff --git a/ui/IFileDialog_Vista/IFileDialog_Vista.vcxproj b/ui/IFileDialog_Vista/IFileDialog_Vista.vcxproj deleted file mode 100644 index 7f84b4fb..00000000 --- a/ui/IFileDialog_Vista/IFileDialog_Vista.vcxproj +++ /dev/null @@ -1,244 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" /> - <ClCompile Include="ifile_dialog.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="ifile_dialog.h" /> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{70394AEF-5897-4911-AFA1-82EAF0581EFA}</ProjectGuid> - <RootNamespace>ShadowDll</RootNamespace> - <Keyword>Win32Proj</Keyword> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup> - <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">IFileDialog_Vista_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">IFileDialog_Vista_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">IFileDialog_Vista_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">IFileDialog_Vista_$(Platform)</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;IFILE_DIALOG_VISTA_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>false</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>EditAndContinue</DebugInformationFormat> - <DisableSpecificWarnings>4100</DisableSpecificWarnings> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>true</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> - <SubSystem>Windows</SubSystem> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX86</TargetMachine> - <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <Midl> - <TargetEnvironment>X64</TargetEnvironment> - </Midl> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;IFILE_DIALOG_VISTA_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>false</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100</DisableSpecificWarnings> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>true</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> - <SubSystem>Windows</SubSystem> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX64</TargetMachine> - <AdditionalLibraryDirectories> - </AdditionalLibraryDirectories> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;IFILE_DIALOG_VISTA_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100</DisableSpecificWarnings> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>false</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <SubSystem>Windows</SubSystem> - <OptimizeReferences>true</OptimizeReferences> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX86</TargetMachine> - <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <Midl> - <TargetEnvironment>X64</TargetEnvironment> - </Midl> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;IFILE_DIALOG_VISTA_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100</DisableSpecificWarnings> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>false</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <SubSystem>Windows</SubSystem> - <OptimizeReferences>true</OptimizeReferences> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX64</TargetMachine> - <AdditionalLibraryDirectories> - </AdditionalLibraryDirectories> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project>
\ No newline at end of file diff --git a/ui/IFileDialog_Vista/ifile_dialog.cpp b/ui/IFileDialog_Vista/ifile_dialog.cpp deleted file mode 100644 index f56df9e7..00000000 --- a/ui/IFileDialog_Vista/ifile_dialog.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "ifile_dialog.h" -#define WIN32_LEAN_AND_MEAN -#include <zen/com_error.h> -#include <zen/com_ptr.h> -#include <Shobjidl.h> -#include <zen/scope_guard.h> -#include <string> - -using namespace zen; - - -namespace -{ -bool showFolderPickerImpl(HWND ownerWindow, //throw SysError; return "false" if cancelled by user - const wchar_t* defaultFolder, //optional! - const GUID* persistenceGuid, // - std::wstring& selectedFolder) -{ - ComPtr<IFileDialog> fileDlg; - ZEN_COM_CHECK(::CoCreateInstance(CLSID_FileOpenDialog, //throw SysError - nullptr, - CLSCTX_ALL, - IID_PPV_ARGS(fileDlg.init()))); - - if (persistenceGuid) - ZEN_COM_CHECK(fileDlg->SetClientGuid(*persistenceGuid)); - - FILEOPENDIALOGOPTIONS dlgOptions = 0; - ZEN_COM_CHECK(fileDlg->GetOptions(&dlgOptions)); //throw SysError - ZEN_COM_CHECK(fileDlg->SetOptions(dlgOptions | FOS_PICKFOLDERS | FOS_NOVALIDATE | FOS_FORCEFILESYSTEM)); - - if (defaultFolder) //show last selection instead of top level if no default available - { - ComPtr<IShellItem> folderItem; - ZEN_COM_CHECK(::SHCreateItemFromParsingName(defaultFolder, - nullptr, - IID_PPV_ARGS(folderItem.init()))); - ZEN_COM_CHECK(fileDlg->SetFolder(folderItem.get())); - } - - try - { - ZEN_COM_CHECK(fileDlg->Show(ownerWindow)); //may fail with: HRESULT_FROM_WIN32(ERROR_CANCELLED) - } - catch (const SysError&) { return false; } - - ComPtr<IShellItem> folderItem; - ZEN_COM_CHECK(fileDlg->GetResult(folderItem.init())); - - LPWSTR folderPath = nullptr; - ZEN_COM_CHECK(folderItem->GetDisplayName(SIGDN_FILESYSPATH, &folderPath)); - ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(folderPath)); - - selectedFolder = folderPath; - return true; -} - -wchar_t* allocString(const std::wstring& msg) //ownership passed -{ - auto tmp = new wchar_t [msg.size() + 1]; //std::bad_alloc ? - ::wmemcpy(tmp, msg.c_str(), msg.size() + 1); //include 0-termination - return tmp; -} -} - -//################################################################################################## - -void ifile::showFolderPicker(void* ownerWindow, - const wchar_t* defaultFolder, - const GuidProxy* guid, - wchar_t*& selectedFolder, - bool& cancelled, - wchar_t*& errorMsg) -{ - selectedFolder = nullptr; - cancelled = false; - errorMsg = nullptr; - - try - { - static_assert(sizeof(GuidProxy) == sizeof(GUID), ""); - GUID winGuid = {}; - if (guid) - ::memcpy(&winGuid, guid, sizeof(GUID)); - - std::wstring folderPath; - if (showFolderPickerImpl(static_cast<HWND>(ownerWindow), defaultFolder, guid ? &winGuid : nullptr, folderPath)) //throw SysError - selectedFolder = allocString(folderPath); - else - cancelled = true; - } - catch (const SysError& e) - { - errorMsg = allocString(e.toString()); //std::bad_alloc ? - } -} - - -void ifile::freeString(const wchar_t* str) -{ - delete [] str; -} diff --git a/ui/IFileDialog_Vista/ifile_dialog.h b/ui/IFileDialog_Vista/ifile_dialog.h deleted file mode 100644 index 5b4dc532..00000000 --- a/ui/IFileDialog_Vista/ifile_dialog.h +++ /dev/null @@ -1,67 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef IFILE_DIALOG_HEADER_916743921746324 -#define IFILE_DIALOG_HEADER_916743921746324 - -#ifdef IFILE_DIALOG_VISTA_DLL_EXPORTS -#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport) -#else -#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport) -#endif - -#include <zen/build_info.h> - - -namespace ifile -{ -/*-------------- - |declarations| - --------------*/ - -//COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize -//Requires Windows Vista and later - -typedef char GuidProxy[16]; //= Windows 128-bit GUID; we don't want to include "Guiddef.h" here! - -DLL_FUNCTION_DECLARATION -void showFolderPicker(void* ownerWindow, //in; ==HWND - const wchar_t* defaultFolder, //in, optional! - const GuidProxy* guid, //set nullptr by default: Windows stores dialog state (position, x, y coordinates, ect.) associated with the process executable name => use other GUID when needed - wchar_t*& selectedFolder, //out: call freeString() after use! - bool& cancelled, //out - wchar_t*& errorMsg); //out, optional: call freeString() after use! - -DLL_FUNCTION_DECLARATION -void freeString(const wchar_t* str); - -/*---------- - |typedefs| - ----------*/ -typedef bool (*FunType_showFolderPicker)(void* ownerWindow, - const wchar_t* defaultFolder, - const GuidProxy* guid, - wchar_t*& selectedFolder, - bool& cancelled, - wchar_t*& errorMsg); -typedef void (*FunType_freeString)(const wchar_t* str); - -/*-------------- - |symbol names| - --------------*/ -//(use const pointers to ensure internal linkage) -const char funName_showFolderPicker[] = "showFolderPicker"; -const char funName_freeString [] = "freeString"; - -/*--------------- - |library names| - ---------------*/ -inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"IFileDialog_Vista_x64.dll" : L"IFileDialog_Vista_Win32.dll"; } -} - -#undef DLL_FUNCTION_DECLARATION - -#endif //IFILE_DIALOG_HEADER_916743921746324 diff --git a/ui/Taskbar_Seven/Taskbar_Seven.vcxproj b/ui/Taskbar_Seven/Taskbar_Seven.vcxproj deleted file mode 100644 index 2617569a..00000000 --- a/ui/Taskbar_Seven/Taskbar_Seven.vcxproj +++ /dev/null @@ -1,236 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{70394AEF-5897-4911-AFA1-82EAF0581EFA}</ProjectGuid> - <RootNamespace>ShadowDll</RootNamespace> - <Keyword>Win32Proj</Keyword> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup> - <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Taskbar7_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Taskbar7_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Taskbar7_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Taskbar7_$(Platform)</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>false</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>EditAndContinue</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>true</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> - <SubSystem>Windows</SubSystem> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX86</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <Midl> - <TargetEnvironment>X64</TargetEnvironment> - </Midl> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>false</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>true</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> - <SubSystem>Windows</SubSystem> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX64</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <SubSystem>Windows</SubSystem> - <OptimizeReferences>true</OptimizeReferences> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX86</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <Midl> - <TargetEnvironment>X64</TargetEnvironment> - </Midl> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <SubSystem>Windows</SubSystem> - <OptimizeReferences>true</OptimizeReferences> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX64</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" /> - <ClCompile Include="taskbar.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="taskbar.h" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project>
\ No newline at end of file diff --git a/ui/Taskbar_Seven/taskbar.cpp b/ui/Taskbar_Seven/taskbar.cpp deleted file mode 100644 index 72be7016..00000000 --- a/ui/Taskbar_Seven/taskbar.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "taskbar.h" -#include <map> -#include <string> - -#define WIN32_LEAN_AND_MEAN -#include <zen/com_error.h> -#include <zen/com_ptr.h> - -#include <ShObjIdl.h> - -using namespace zen; - - -namespace -{ -std::wstring lastErrorMessage; - - -ComPtr<ITaskbarList3> getInstance() -{ - ComPtr<ITaskbarList3> taskbarlist; - - HRESULT hr = ::CoCreateInstance(CLSID_TaskbarList, - nullptr, - CLSCTX_ALL, - IID_PPV_ARGS(taskbarlist.init())); - if (FAILED(hr)) - { - lastErrorMessage = formatComError(L"Error calling \"CoCreateInstance\".", hr); - return ComPtr<ITaskbarList3>(); - } - - return taskbarlist; -} -} -//################################################################################################## - - -bool tbseven::setStatus(void* hwnd, //HWND: window assciated to the taskbar icon - TaskBarStatus status) -{ - TBPFLAG flag = TBPF_NORMAL; - switch (status) - { - case STATUS_NOPROGRESS: - flag = TBPF_NOPROGRESS; - break; - case STATUS_INDETERMINATE: - flag = TBPF_INDETERMINATE; - break; - case STATUS_NORMAL: - flag = TBPF_NORMAL; - break; - case STATUS_ERROR: - flag = TBPF_ERROR; - break; - case STATUS_PAUSED: - flag = TBPF_PAUSED; - break; - } - - ComPtr<ITaskbarList3> taskbarlist = getInstance(); - if (!taskbarlist) //error msg already set - return false; - - HRESULT hr = taskbarlist->SetProgressState(static_cast<HWND>(hwnd), //[in] HWND hwnd, - flag); //[in] TBPFLAG tbpFlags - if (FAILED(hr)) - { - lastErrorMessage = formatComError(L"Error calling \"SetProgressState\".", hr); - return false; - } - - return true; -} - - -bool tbseven::setProgress(void* hwnd, //HWND: window assciated to the taskbar icon - size_t current, - size_t total) -{ - ComPtr<ITaskbarList3> taskbarlist = getInstance(); - if (!taskbarlist) //error msg already set - return false; - - HRESULT hr = taskbarlist->SetProgressValue( - static_cast<HWND>(hwnd), //[in] HWND hwnd, - current, //[in] ULONGLONG ullCompleted, - total); //[in] ULONGLONG ullTotal - if (FAILED(hr)) - { - lastErrorMessage = formatComError(L"Error calling \"SetProgressValue\".", hr); - return false; - } - - return true; -} - - -void tbseven::getLastError(wchar_t* buffer, size_t bufferSize) -{ - if (bufferSize > 0) - { - size_t endPos = lastErrorMessage.copy(buffer, bufferSize - 1); - buffer[endPos] = 0; - } -} diff --git a/ui/Taskbar_Seven/taskbar.h b/ui/Taskbar_Seven/taskbar.h deleted file mode 100644 index 4a158d1f..00000000 --- a/ui/Taskbar_Seven/taskbar.h +++ /dev/null @@ -1,74 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef TASKBAR_SEVEN_DLL_H -#define TASKBAR_SEVEN_DLL_H - -#ifdef TASKBAR_SEVEN_DLL_EXPORTS -#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport) -#else -#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport) -#endif - -#include <zen/build_info.h> - - -namespace tbseven -{ -/*-------------- - |declarations| - --------------*/ - -enum TaskBarStatus -{ - STATUS_NOPROGRESS, - STATUS_INDETERMINATE, - STATUS_NORMAL, - STATUS_ERROR, - STATUS_PAUSED -}; - - -//COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize - -DLL_FUNCTION_DECLARATION -bool setStatus(void* hwnd, //HWND: window assciated to the taskbar icon - TaskBarStatus status); - - -DLL_FUNCTION_DECLARATION -bool setProgress(void* hwnd, //HWND: window assciated to the taskbar icon - size_t current, - size_t total); - -//if any of the functions above returns 'false', this message returns last error -DLL_FUNCTION_DECLARATION -void getLastError(wchar_t* buffer, size_t bufferSize); - -/*---------- - |typedefs| - ----------*/ -typedef bool (*FunType_setStatus )(void* hwnd, TaskBarStatus status); -typedef bool (*FunType_setProgress )(void* hwnd, size_t current, size_t total); -typedef void (*FunType_getLastError)(wchar_t* buffer, size_t bufferSize); - -/*-------------- - |symbol names| - --------------*/ -//(use const pointers to ensure internal linkage) -const char funName_setStatus [] = "setStatus"; -const char funName_setProgress [] = "setProgress"; -const char funName_getLastError[] = "getLastError"; - -/*--------------- - |library names| - ---------------*/ -inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"Taskbar7_x64.dll" : L"Taskbar7_Win32.dll"; } -} - -#undef DLL_FUNCTION_DECLARATION - -#endif //TASKBAR_SEVEN_DLL_H diff --git a/ui/app_icon.h b/ui/app_icon.h deleted file mode 100644 index a1240fee..00000000 --- a/ui/app_icon.h +++ /dev/null @@ -1,40 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef APP_ICON_H6748179634932174683214 -#define APP_ICON_H6748179634932174683214 - -#include <wx/icon.h> -#include <wx+/image_resources.h> - -namespace zen -{ -inline -wxIcon getFfsIcon() -{ - //wxWidgets' bitmap to icon conversion on OS X can only deal with very specific sizes => check on all platforms! - assert(getResourceImage(L"FreeFileSync").GetWidth () == getResourceImage(L"FreeFileSync").GetHeight() && - getResourceImage(L"FreeFileSync").GetWidth() % 128 == 0); -#ifdef ZEN_WIN - //for compatibility it seems we need to stick with a "real" icon - return wxIcon(L"A_FFS_ICON"); - -#elif defined ZEN_LINUX - //attention: make sure to not implicitly call "instance()" again => deadlock on Linux - wxIcon icon; - icon.CopyFromBitmap(getResourceImage(L"FreeFileSync")); //use big logo bitmap for better quality - return icon; - -#elif defined ZEN_MAC - wxIcon icon; - icon.CopyFromBitmap(getResourceImage(L"FreeFileSync").ConvertToImage().Scale(128, 128, wxIMAGE_QUALITY_HIGH)); //"von hinten durch die Brust ins Auge" - return icon; -#endif -} -} - - -#endif //APP_ICON_H6748179634932174683214 diff --git a/ui/batch_config.cpp b/ui/batch_config.cpp deleted file mode 100644 index 4807e4a1..00000000 --- a/ui/batch_config.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "batch_config.h" -#include <wx/wupdlock.h> -#include <wx+/mouse_move_dlg.h> -#include <wx+/std_button_order.h> -#include <wx+/font_size.h> -#include <wx+/image_resources.h> -#include "gui_generated.h" -#include "dir_name.h" -#include "../ui/exec_finished_box.h" -#include "../lib/help_provider.h" - -using namespace zen; -using namespace xmlAccess; - - -namespace -{ -enum ButtonPressed -{ - BUTTON_CANCEL, - BUTTON_SAVE_AS -}; - - -class BatchDialog : public BatchDlgGenerated -{ -public: - BatchDialog(wxWindow* parent, - XmlBatchConfig& batchCfg, //in/out - std::vector<std::wstring>& onCompletionHistory, - size_t onCompletionHistoryMax); - -private: - virtual void OnClose (wxCloseEvent& event) { EndModal(BUTTON_CANCEL); } - virtual void OnCancel (wxCommandEvent& event) { EndModal(BUTTON_CANCEL); } - virtual void OnSaveBatchJob(wxCommandEvent& event); - virtual void OnErrorPopup (wxCommandEvent& event) { localBatchCfg.handleError = ON_ERROR_POPUP; updateGui(); } - virtual void OnErrorIgnore(wxCommandEvent& event) { localBatchCfg.handleError = ON_ERROR_IGNORE; updateGui(); } - virtual void OnErrorStop (wxCommandEvent& event) { localBatchCfg.handleError = ON_ERROR_STOP; updateGui(); } - virtual void OnHelpScheduleBatch(wxHyperlinkEvent& event) { displayHelpEntry(L"html/Schedule a Batch Job.html", this); } - - virtual void OnToggleGenerateLogfile(wxCommandEvent& event) { updateGui(); } - virtual void OnToggleLogfilesLimit (wxCommandEvent& event) { updateGui(); } - - void updateGui(); //re-evaluate gui after config changes - - void setConfig(const XmlBatchConfig& batchCfg); - XmlBatchConfig getConfig() const; - - XmlBatchConfig& batchCfgOutRef; //output only! - XmlBatchConfig localBatchCfg; //a mixture of settings some of which have OWNERSHIP WITHIN GUI CONTROLS! use getConfig() to resolve - - std::unique_ptr<DirectoryName<FolderHistoryBox>> logfileDir; //always bound, solve circular compile-time dependency -}; - -//################################################################################################################################### - -BatchDialog::BatchDialog(wxWindow* parent, - XmlBatchConfig& batchCfg, - std::vector<std::wstring>& onCompletionHistory, - size_t onCompletionHistoryMax) : - BatchDlgGenerated(parent), - batchCfgOutRef(batchCfg) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonSaveAs).setCancel(m_buttonCancel)); - - m_staticTextDescr->SetLabel(replaceCpy(m_staticTextDescr->GetLabel(), L"%x", L"FreeFileSync.exe <" + _("job name") + L">.ffs_batch")); - - m_comboBoxExecFinished->initHistory(onCompletionHistory, onCompletionHistoryMax); - - m_bitmapBatchJob->SetBitmap(getResourceImage(L"batch")); - - logfileDir = make_unique<DirectoryName<FolderHistoryBox>>(*m_panelLogfile, *m_buttonSelectLogfileDir, *m_logfileDir); - - setConfig(batchCfg); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - // Layout(); - - m_buttonSaveAs->SetFocus(); -} - - -void BatchDialog::updateGui() //re-evaluate gui after config changes -{ - XmlBatchConfig cfg = getConfig(); //resolve parameter ownership: some on GUI controls, others member variables - - m_panelLogfile ->Enable(m_checkBoxGenerateLogfile->GetValue()); //enabled status is *not* directly dependent from resolved config! (but transitively) - m_spinCtrlLogfileLimit->Enable(m_checkBoxGenerateLogfile->GetValue() && m_checkBoxLogfilesLimit->GetValue()); - - m_toggleBtnErrorIgnore->SetValue(false); - m_toggleBtnErrorPopup ->SetValue(false); - m_toggleBtnErrorStop ->SetValue(false); - switch (cfg.handleError) //*not* owned by GUI controls - { - case ON_ERROR_IGNORE: - m_toggleBtnErrorIgnore->SetValue(true); - break; - case ON_ERROR_POPUP: - m_toggleBtnErrorPopup->SetValue(true); - break; - case ON_ERROR_STOP: - m_toggleBtnErrorStop->SetValue(true); - break; - } -} - - -void BatchDialog::setConfig(const XmlBatchConfig& batchCfg) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - localBatchCfg = batchCfg; //contains some parameters not owned by GUI controls - - //transfer parameter ownership to GUI - m_checkBoxShowProgress->SetValue(batchCfg.showProgress); - logfileDir->setName(utfCvrtTo<wxString>(batchCfg.logFileDirectory)); - m_comboBoxExecFinished->setValue(batchCfg.mainCfg.onCompletion); - - //map single parameter "logfiles limit" to all three checkboxs and spin ctrl: - m_checkBoxGenerateLogfile->SetValue(batchCfg.logfilesCountLimit != 0); - m_checkBoxLogfilesLimit ->SetValue(batchCfg.logfilesCountLimit >= 0); - m_spinCtrlLogfileLimit ->SetValue(batchCfg.logfilesCountLimit >= 0 ? batchCfg.logfilesCountLimit : 100 /*XmlBatchConfig().logfilesCountLimit*/); - //attention: emits a "change value" event!! => updateGui() called implicitly! - - updateGui(); //re-evaluate gui after config changes -} - - -XmlBatchConfig BatchDialog::getConfig() const -{ - XmlBatchConfig batchCfg = localBatchCfg; - - //load parameters with ownership within GIU controls... - - //load structure with batch settings "batchCfg" - batchCfg.showProgress = m_checkBoxShowProgress->GetValue(); - batchCfg.logFileDirectory = utfCvrtTo<Zstring>(logfileDir->getName()); - batchCfg.mainCfg.onCompletion = m_comboBoxExecFinished->getValue(); - //get single parameter "logfiles limit" from all three checkboxes and spin ctrl: - batchCfg.logfilesCountLimit = m_checkBoxGenerateLogfile->GetValue() ? (m_checkBoxLogfilesLimit->GetValue() ? m_spinCtrlLogfileLimit->GetValue() : -1) : 0; - - return batchCfg; -} - - -void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) -{ - batchCfgOutRef = getConfig(); - m_comboBoxExecFinished->addItemHistory(); //a good place to commit current "on completion" history item - EndModal(BUTTON_SAVE_AS); -} -} - - -bool zen::customizeBatchConfig(wxWindow* parent, - xmlAccess::XmlBatchConfig& batchCfg, //in/out - std::vector<std::wstring>& execFinishedhistory, - size_t execFinishedhistoryMax) -{ - BatchDialog batchDlg(parent, batchCfg, execFinishedhistory, execFinishedhistoryMax); - return static_cast<ButtonPressed>(batchDlg.ShowModal()) == BUTTON_SAVE_AS; -} diff --git a/ui/batch_config.h b/ui/batch_config.h deleted file mode 100644 index 5bff09e1..00000000 --- a/ui/batch_config.h +++ /dev/null @@ -1,22 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef BATCHCONFIG_H_INCLUDED -#define BATCHCONFIG_H_INCLUDED - -#include <wx/window.h> -#include "../lib/process_xml.h" - -namespace zen -{ -//show and let user customize batch settings (without saving) -bool customizeBatchConfig(wxWindow* parent, //return "false" if aborted, "true" on "do save" - xmlAccess::XmlBatchConfig& batchCfg, //in/out - std::vector<std::wstring>& execFinishedhistory, - size_t execFinishedhistoryMax); -} - -#endif // BATCHCONFIG_H_INCLUDED diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp deleted file mode 100644 index bca6b484..00000000 --- a/ui/batch_status_handler.cpp +++ /dev/null @@ -1,477 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "batch_status_handler.h" -#include <zen/file_handling.h> -#include <zen/file_traverser.h> -//#include <zen/format_unit.h> -#include <zen/shell_execute.h> -#include <wx+/popup_dlg.h> -#include <wx/app.h> -#include "exec_finished_box.h" -#include "../lib/ffs_paths.h" -#include "../lib/resolve_path.h" -#include "../lib/status_handler_impl.h" -#include "../lib/generate_logfile.h" - -using namespace zen; - - -namespace -{ -class FindLogfiles : public TraverseCallback -{ -public: - FindLogfiles(const Zstring& prefix, std::vector<Zstring>& logfiles) : prefix_(prefix), logfiles_(logfiles) {} - -private: - virtual void onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details) - { - const Zstring fileName(shortName); - if (startsWith(fileName, prefix_) && endsWith(fileName, Zstr(".log"))) - logfiles_.push_back(fullName); - } - - virtual TraverseCallback* onDir (const Zchar* shortName, const Zstring& fullName) { return nullptr; } //DON'T traverse into subdirs - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) { return LINK_SKIP; } - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) { assert(false); return ON_ERROR_IGNORE; } //errors are not really critical in this context - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) { assert(false); return ON_ERROR_IGNORE; } // - - const Zstring prefix_; - std::vector<Zstring>& logfiles_; -}; - - -void limitLogfileCount(const Zstring& logdir, const std::wstring& jobname, size_t maxCount) //throw() -{ - std::vector<Zstring> logFiles; - FindLogfiles traverseCallback(utfCvrtTo<Zstring>(jobname), logFiles); //throw()! - - traverseFolder(logdir, - traverseCallback); - - if (logFiles.size() <= maxCount) - return; - - //delete oldest logfiles: take advantage of logfile naming convention to find them - std::nth_element(logFiles.begin(), logFiles.end() - maxCount, logFiles.end(), LessFilename()); - - std::for_each(logFiles.begin(), logFiles.end() - maxCount, - [](const Zstring& filename) { try { removeFile(filename); } catch (FileError&) {} }); -} - - -std::unique_ptr<FileOutput> prepareNewLogfile(const Zstring& logfileDirectory, //throw FileError - const std::wstring& jobName, - const TimeComp& timeStamp) //return value always bound! -{ - //create logfile directory if required - Zstring logfileDir = logfileDirectory.empty() ? - getConfigDir() + Zstr("Logs") : - getFormattedDirectoryName(logfileDirectory); - - makeDirectory(logfileDir); //throw FileError - - //assemble logfile name - const Zstring body = appendSeparator(logfileDir) + utfCvrtTo<Zstring>(jobName) + Zstr(" ") + formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"), timeStamp); - - //ensure uniqueness - for (int i = 0;; ++i) - try - { - const Zstring& filename = i == 0 ? - body + Zstr(".log") : - body + Zstr('_') + numberTo<Zstring>(i) + Zstr(".log"); - - return make_unique<FileOutput>(filename, FileOutput::ACC_CREATE_NEW); //throw FileError, ErrorTargetExisting - //*no* file system race-condition! - } - catch (const ErrorTargetExisting&) {} -} -} - -//############################################################################################################################## - -BatchStatusHandler::BatchStatusHandler(bool showProgress, - const std::wstring& jobName, - const TimeComp& timeStamp, - const Zstring& logfileDirectory, //may be empty - int logfilesCountLimit, - size_t lastSyncsLogFileSizeMax, - const xmlAccess::OnError handleError, - size_t automaticRetryCount, - size_t automaticRetryDelay, - const SwitchToGui& switchBatchToGui, //functionality to change from batch mode to GUI mode - FfsReturnCode& returnCode, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory) : - switchBatchToGui_(switchBatchToGui), - showFinalResults(showProgress), //=> exit immediately or wait when finished - switchToGuiRequested(false), - logfilesCountLimit_(logfilesCountLimit), - lastSyncsLogFileSizeMax_(lastSyncsLogFileSizeMax), - handleError_(handleError), - returnCode_(returnCode), - automaticRetryCount_(automaticRetryCount), - automaticRetryDelay_(automaticRetryDelay), - progressDlg(createProgressDialog(*this, [this] { this->onProgressDialogTerminate(); }, *this, nullptr, showProgress, jobName, execWhenFinished, execFinishedHistory)), - jobName_(jobName) -{ - if (logfilesCountLimit != 0) - { - zen::Opt<std::wstring> errMsg = tryReportingError([&] { logFile = prepareNewLogfile(logfileDirectory, jobName, timeStamp); }, //throw FileError; return value always bound! - *this); - if (errMsg) - { - raiseReturnCode(returnCode_, FFS_RC_ABORTED); - throw BatchAbortProcess(); - } - } - - totalTime.Start(); //measure total time - - //if (logFile) - // ::wxSetEnv(L"logfile", utfCvrtTo<wxString>(logFile->getFilename())); -} - - -BatchStatusHandler::~BatchStatusHandler() -{ - //------------ "on completion" command conceptually is part of the sync, not cleanup -------------------------------------- - - //decide whether to stay on status screen or exit immediately... - if (switchToGuiRequested) //-> avoid recursive yield() calls, thous switch not before ending batch mode - { - try - { - switchBatchToGui_.execute(); //open FreeFileSync GUI - } - catch (...) {} - showFinalResults = false; - } - else if (progressDlg) - { - if (progressDlg->getWindowIfVisible()) - showFinalResults = true; - - //execute "on completion" command (even in case of ignored errors) - if (!abortIsRequested()) //if aborted (manually), we don't execute the command - { - const std::wstring finalCommand = progressDlg->getExecWhenFinishedCommand(); //final value (after possible user modification) - if (!finalCommand.empty()) - { - if (isCloseProgressDlgCommand(finalCommand)) - showFinalResults = false; //take precedence over current visibility status - else - try - { - tryReportingError([&] { shellExecute2(expandMacros(utfCvrtTo<Zstring>(finalCommand)), EXEC_TYPE_SYNC); }, //throw FileError, throw X? - *this); - } - catch (...) {} - } - } - } - //------------ end of sync: begin of cleanup -------------------------------------- - - const int totalErrors = errorLog.getItemCount(TYPE_ERROR | TYPE_FATAL_ERROR); //evaluate before finalizing log - const int totalWarnings = errorLog.getItemCount(TYPE_WARNING); - - //finalize error log - std::wstring finalStatus; - if (abortIsRequested()) - { - raiseReturnCode(returnCode_, FFS_RC_ABORTED); - finalStatus = _("Synchronization stopped"); - errorLog.logMsg(finalStatus, TYPE_ERROR); - } - else if (totalErrors > 0) - { - raiseReturnCode(returnCode_, FFS_RC_FINISHED_WITH_ERRORS); - finalStatus = _("Synchronization completed with errors"); - errorLog.logMsg(finalStatus, TYPE_ERROR); - } - else if (totalWarnings > 0) - { - raiseReturnCode(returnCode_, FFS_RC_FINISHED_WITH_WARNINGS); - finalStatus = _("Synchronization completed with warnings"); - errorLog.logMsg(finalStatus, TYPE_WARNING); - } - else - { - if (getObjectsTotal(PHASE_SYNCHRONIZING) == 0 && //we're past "initNewPhase(PHASE_SYNCHRONIZING)" at this point! - getDataTotal (PHASE_SYNCHRONIZING) == 0) - finalStatus = _("Nothing to synchronize"); //even if "ignored conflicts" occurred! - else - finalStatus = _("Synchronization completed successfully"); - errorLog.logMsg(finalStatus, TYPE_INFO); - } - - const SummaryInfo summary = - { - jobName_, - finalStatus, - getObjectsCurrent(PHASE_SYNCHRONIZING), getDataCurrent(PHASE_SYNCHRONIZING), - getObjectsTotal (PHASE_SYNCHRONIZING), getDataTotal (PHASE_SYNCHRONIZING), - totalTime.Time() / 1000 - }; - - //print the results list: logfile - if (logFile.get()) - { - try - { - //saving log file below may take a *long* time, so report (without logging) - reportStatus(replaceCpy(_("Saving log file %x..."), L"%x", fmtFileName(logFile->getFilename()))); //throw? - forceUiRefresh(); // - } - catch (...) {} - - if (logfilesCountLimit_ > 0) - limitLogfileCount(beforeLast(logFile->getFilename(), FILE_NAME_SEPARATOR), jobName_, logfilesCountLimit_); //throw() - - try - { - saveLogToFile(summary, errorLog, *logFile); //throw FileError - } - catch (FileError&) {} - } - try - { - saveToLastSyncsLog(summary, errorLog, lastSyncsLogFileSizeMax_); //throw FileError - } - catch (FileError&) {} - - if (progressDlg) - { - if (showFinalResults) //warning: wxWindow::Show() is called within processHasFinished()! - { - //notify about (logical) application main window => program won't quit, but stay on this dialog - //setMainWindow(progressDlg->getAsWindow()); -> not required anymore since we block waiting until dialog is closed below - - //notify to progressDlg that current process has ended - if (abortIsRequested()) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_ABORTED, errorLog); //enable okay and close events - else if (totalErrors > 0) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_ERROR, errorLog); - else if (totalWarnings > 0) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_WARNINGS, errorLog); - else - progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_SUCCESS, errorLog); - } - else - progressDlg->closeWindowDirectly(); //progressDlg is main window => program will quit directly - - //wait until progress dialog notified shutdown via onProgressDialogTerminate() - //-> required since it has our "this" pointer captured in lambda "notifyWindowTerminate"! - //-> nicely manages dialog lifetime - while (progressDlg) - { - wxTheApp->Yield(); //*first* refresh GUI (removing flicker) before sleeping! - boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL)); - } - } -} - - -void BatchStatusHandler::initNewPhase(int objectsTotal, Int64 dataTotal, ProcessCallback::Phase phaseID) -{ - StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID); - if (progressDlg) - progressDlg->initNewPhase(); //call after "StatusHandler::initNewPhase" -} - - -void BatchStatusHandler::updateProcessedData(int objectsDelta, Int64 dataDelta) -{ - StatusHandler::updateProcessedData(objectsDelta, dataDelta); - - if (progressDlg) - progressDlg->notifyProgressChange(); //noexcept - //note: this method should NOT throw in order to properly allow undoing setting of statistics! -} - - -void BatchStatusHandler::reportInfo(const std::wstring& text) -{ - StatusHandler::reportInfo(text); - errorLog.logMsg(text, TYPE_INFO); -} - - -void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) -{ - errorLog.logMsg(warningMessage, TYPE_WARNING); - - if (!warningActive) - return; - - switch (handleError_) - { - case xmlAccess::ON_ERROR_POPUP: - { - if (!progressDlg) abortThisProcess(); - PauseTimers dummy(*progressDlg); - forceUiRefresh(); - - bool dontWarnAgain = false; - switch (showConfirmationDialog3(progressDlg->getWindowIfVisible(), DialogInfoType::WARNING, PopupDialogCfg3(). - setDetailInstructions(warningMessage + L"\n\n" + _("You can switch to FreeFileSync's main window to resolve this issue.")). - setCheckBox(dontWarnAgain, _("&Don't show this warning again"), ConfirmationButton3::DONT_DO_IT), - _("&Ignore"), _("&Switch"))) - { - case ConfirmationButton3::DO_IT: //ignore - warningActive = !dontWarnAgain; - break; - - case ConfirmationButton3::DONT_DO_IT: //switch - errorLog.logMsg(_("Switching to FreeFileSync's main window"), TYPE_INFO); - switchToGuiRequested = true; - abortThisProcess(); - break; - - case ConfirmationButton3::CANCEL: - abortThisProcess(); - break; - } - } - break; //keep it! last switch might not find match - - case xmlAccess::ON_ERROR_STOP: - abortThisProcess(); - break; - - case xmlAccess::ON_ERROR_IGNORE: - break; - } -} - - -ProcessCallback::Response BatchStatusHandler::reportError(const std::wstring& errorMessage, size_t retryNumber) -{ - //auto-retry - if (retryNumber < automaticRetryCount_) - { - errorLog.logMsg(errorMessage + L"\n=> " + - _P("Automatic retry in 1 second...", "Automatic retry in %x seconds...", automaticRetryDelay_), TYPE_INFO); - //delay - const int iterations = static_cast<int>(1000 * automaticRetryDelay_ / UI_UPDATE_INTERVAL); //always round down: don't allow for negative remaining time below - for (int i = 0; i < iterations; ++i) - { - reportStatus(_("Error") + L": " + _P("Automatic retry in 1 second...", "Automatic retry in %x seconds...", - (1000 * automaticRetryDelay_ - i * UI_UPDATE_INTERVAL + 999) / 1000)); //integer round up - boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL)); - } - return ProcessCallback::RETRY; - } - - - //always, except for "retry": - zen::ScopeGuard guardWriteLog = zen::makeGuard([&] { errorLog.logMsg(errorMessage, TYPE_ERROR); }); - - switch (handleError_) - { - case xmlAccess::ON_ERROR_POPUP: - { - if (!progressDlg) abortThisProcess(); - PauseTimers dummy(*progressDlg); - forceUiRefresh(); - - bool ignoreNextErrors = false; - switch (showConfirmationDialog3(progressDlg->getWindowIfVisible(), DialogInfoType::ERROR2, PopupDialogCfg3(). - setDetailInstructions(errorMessage). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors"), ConfirmationButton3::DONT_DO_IT), - _("&Ignore"), _("&Retry"))) - { - case ConfirmationButton3::DO_IT: //ignore - if (ignoreNextErrors) //falsify only - handleError_ = xmlAccess::ON_ERROR_IGNORE; - return ProcessCallback::IGNORE_ERROR; - - case ConfirmationButton3::DONT_DO_IT: //retry - guardWriteLog.dismiss(); - errorLog.logMsg(errorMessage + L"\n=> " + _("Retrying operation..."), TYPE_INFO); - return ProcessCallback::RETRY; - - case ConfirmationButton3::CANCEL: - abortThisProcess(); - break; - } - } - break; //used if last switch didn't find a match - - case xmlAccess::ON_ERROR_STOP: - abortThisProcess(); - break; - - case xmlAccess::ON_ERROR_IGNORE: - return ProcessCallback::IGNORE_ERROR; - } - - assert(false); - return ProcessCallback::IGNORE_ERROR; //dummy value -} - - -void BatchStatusHandler::reportFatalError(const std::wstring& errorMessage) -{ - errorLog.logMsg(errorMessage, TYPE_FATAL_ERROR); - - switch (handleError_) - { - case xmlAccess::ON_ERROR_POPUP: - { - if (!progressDlg) abortThisProcess(); - PauseTimers dummy(*progressDlg); - forceUiRefresh(); - - bool ignoreNextErrors = false; - switch (showConfirmationDialog(progressDlg->getWindowIfVisible(), DialogInfoType::ERROR2, - PopupDialogCfg().setTitle(_("Serious Error")). - setDetailInstructions(errorMessage). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors")), - _("&Ignore"))) - { - case ConfirmationButton::DO_IT: - if (ignoreNextErrors) //falsify only - handleError_ = xmlAccess::ON_ERROR_IGNORE; - break; - case ConfirmationButton::CANCEL: - abortThisProcess(); - break; - } - } - break; - - case xmlAccess::ON_ERROR_STOP: - abortThisProcess(); - break; - - case xmlAccess::ON_ERROR_IGNORE: - break; - } -} - - -void BatchStatusHandler::forceUiRefresh() -{ - if (progressDlg) - progressDlg->updateGui(); -} - - -void BatchStatusHandler::abortThisProcess() -{ - requestAbortion(); //just make sure... - throw BatchAbortProcess(); //abort can be triggered by progressDlg -} - - -void BatchStatusHandler::onProgressDialogTerminate() -{ - //it's responsibility of "progressDlg" to call requestAbortion() when closing dialog - progressDlg = nullptr; -} diff --git a/ui/batch_status_handler.h b/ui/batch_status_handler.h deleted file mode 100644 index de6e71b3..00000000 --- a/ui/batch_status_handler.h +++ /dev/null @@ -1,76 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef BATCHSTATUSHANDLER_H_INCLUDED -#define BATCHSTATUSHANDLER_H_INCLUDED - -#include <zen/error_log.h> -#include <zen/file_io.h> -#include <zen/time.h> -#include "../lib/status_handler.h" -#include "../lib/process_xml.h" -#include "progress_indicator.h" -#include "switch_to_gui.h" -#include "lib/return_codes.h" - - -//Exception class used to abort the "compare" and "sync" process -class BatchAbortProcess {}; - - -//BatchStatusHandler(SyncProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! -class BatchStatusHandler : public zen::StatusHandler //throw BatchAbortProcess -{ -public: - BatchStatusHandler(bool showProgress, //defines: -start minimized and -quit immediately when finished - const std::wstring& jobName, //should not be empty for a batch job! - const zen::TimeComp& timeStamp, - const Zstring& logfileDirectory, - int logfilesCountLimit, //0: logging inactive; < 0: no limit - size_t lastSyncsLogFileSizeMax, - const xmlAccess::OnError handleError, - size_t automaticRetryCount, - size_t automaticRetryDelay, - const zen::SwitchToGui& switchBatchToGui, //functionality to change from batch mode to GUI mode - zen::FfsReturnCode& returnCode, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory); - ~BatchStatusHandler(); - - virtual void initNewPhase (int objectsTotal, zen::Int64 dataTotal, Phase phaseID); - virtual void updateProcessedData(int objectsDelta, zen::Int64 dataDelta); - virtual void reportInfo(const std::wstring& text); - virtual void forceUiRefresh(); - - virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); - virtual Response reportError(const std::wstring& errorMessage, size_t retryNumber); - virtual void reportFatalError(const std::wstring& errorMessage); - -private: - virtual void abortThisProcess(); //throw BatchAbortProcess - void onProgressDialogTerminate(); - - const zen::SwitchToGui& switchBatchToGui_; //functionality to change from batch mode to GUI mode - bool showFinalResults; - bool switchToGuiRequested; - const int logfilesCountLimit_; - const size_t lastSyncsLogFileSizeMax_; - xmlAccess::OnError handleError_; - zen::ErrorLog errorLog; //list of non-resolved errors and warnings - zen::FfsReturnCode& returnCode_; - - const size_t automaticRetryCount_; - const size_t automaticRetryDelay_; - - SyncProgressDialog* progressDlg; //managed to have shorter lifetime than this handler! - std::unique_ptr<zen::FileOutput> logFile; //optional! - - const std::wstring jobName_; - wxStopWatch totalTime; -}; - - -#endif // BATCHSTATUSHANDLER_H_INCLUDED diff --git a/ui/check_version.cpp b/ui/check_version.cpp deleted file mode 100644 index 79fd2507..00000000 --- a/ui/check_version.cpp +++ /dev/null @@ -1,318 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "check_version.h" -//#include <memory> -#include <zen/string_tools.h> -#include <zen/i18n.h> -#include <zen/utf.h> -#include <wx/timer.h> -#include <wx/utils.h> -#include <wx+/popup_dlg.h> -#include "../version/version.h" -////#include "../lib/ffs_paths.h" -#include <zen/scope_guard.h> - -#ifdef ZEN_WIN -#include <zen/win.h> //tame wininet include -#include <wininet.h> - -#elif defined ZEN_LINUX || defined ZEN_MAC -#include <wx/protocol/http.h> -#include <wx/sstream.h> -#endif - -using namespace zen; - - -namespace -{ -#ifdef ZEN_WIN -class InternetConnectionError {}; - -class WinInetAccess //using IE proxy settings! :) -{ -public: - WinInetAccess(const wchar_t* url) //throw InternetConnectionError (if url cannot be reached; no need to also call readBytes()) - { - //::InternetAttemptConnect(0) -> not working as expected: succeeds even when there is no internet connection! - - hInternet = ::InternetOpen(L"FreeFileSync", //_In_ LPCTSTR lpszAgent, - INTERNET_OPEN_TYPE_PRECONFIG, //_In_ DWORD dwAccessType, - nullptr, //_In_ LPCTSTR lpszProxyName, - nullptr, //_In_ LPCTSTR lpszProxyBypass, - 0); //_In_ DWORD dwFlags - if (!hInternet) - throw InternetConnectionError(); - zen::ScopeGuard guardInternet = zen::makeGuard([&] { ::InternetCloseHandle(hInternet); }); - - hRequest = ::InternetOpenUrl(hInternet, //_In_ HINTERNET hInternet, - url, //_In_ LPCTSTR lpszUrl, - nullptr, //_In_ LPCTSTR lpszHeaders, - 0, //_In_ DWORD dwHeadersLength, - INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_UI, //_In_ DWORD dwFlags, - 0); //_In_ DWORD_PTR dwContext - if (!hRequest) //won't fail due to unreachable url here! There is no substitute for HTTP_QUERY_STATUS_CODE!!! - throw InternetConnectionError(); - zen::ScopeGuard guardRequest = zen::makeGuard([&] { ::InternetCloseHandle(hRequest); }); - - DWORD statusCode = 0; - DWORD bufferLength = sizeof(statusCode); - if (!::HttpQueryInfo(hRequest, //_In_ HINTERNET hRequest, - HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, //_In_ DWORD dwInfoLevel, - &statusCode, //_Inout_ LPVOID lpvBuffer, - &bufferLength, //_Inout_ LPDWORD lpdwBufferLength, - nullptr)) //_Inout_ LPDWORD lpdwIndex - throw InternetConnectionError(); - - if (statusCode != HTTP_STATUS_OK) - throw InternetConnectionError(); //e.g. 404 - HTTP_STATUS_NOT_FOUND - - guardRequest .dismiss(); - guardInternet.dismiss(); - } - - ~WinInetAccess() - { - ::InternetCloseHandle(hRequest); - ::InternetCloseHandle(hInternet); - } - - template <class OutputIterator> - OutputIterator readBytes(OutputIterator result) //throw InternetConnectionError - { - //internet says "HttpQueryInfo() + HTTP_QUERY_CONTENT_LENGTH" not supported by all http servers... - const DWORD bufferSize = 64 * 1024; - std::vector<char> buffer(bufferSize); - for (;;) - { - DWORD bytesRead = 0; - if (!::InternetReadFile(hRequest, //_In_ HINTERNET hFile, - &buffer[0], //_Out_ LPVOID lpBuffer, - bufferSize, //_In_ DWORD dwNumberOfBytesToRead, - &bytesRead)) //_Out_ LPDWORD lpdwNumberOfBytesRead - throw InternetConnectionError(); - if (bytesRead == 0) - return result; - - result = std::copy(buffer.begin(), buffer.begin() + bytesRead, result); - } - } - -private: - HINTERNET hInternet; - HINTERNET hRequest; -}; - - -inline -bool canAccessUrl(const wchar_t* url) //throw () -{ - try - { - (void)WinInetAccess(url); //throw InternetConnectionError - return true; - } - catch (const InternetConnectionError&) { return false; } -} - - -template <class OutputIterator> inline -OutputIterator readBytesUrl(const wchar_t* url, OutputIterator result) //throw InternetConnectionError -{ - return WinInetAccess(url).readBytes(result); //throw InternetConnectionError -} -#endif - - -enum GetVerResult -{ - GET_VER_SUCCESS, - GET_VER_NO_CONNECTION, //no internet connection or just Sourceforge down? - GET_VER_PAGE_NOT_FOUND //version file seems to have moved! => trigger an update! -}; - -GetVerResult getOnlineVersion(wxString& version) //empty string on error; -{ -#ifdef ZEN_WIN - //internet access supporting proxy connections - std::vector<char> output; - try - { - readBytesUrl(L"http://freefilesync.sourceforge.net/latest_version.txt", std::back_inserter(output)); //throw InternetConnectionError - } - catch (const InternetConnectionError&) - { - return canAccessUrl(L"http://sourceforge.net/") ? GET_VER_PAGE_NOT_FOUND : GET_VER_NO_CONNECTION; - } - - output.push_back('\0'); - version = utfCvrtTo<wxString>(&output[0]); - return GET_VER_SUCCESS; - -#elif defined ZEN_LINUX || defined ZEN_MAC - wxWindowDisabler dummy; - - auto getStringFromUrl = [](const wxString& server, const wxString& page, int timeout, wxString* output) -> bool //true on successful connection - { - wxHTTP webAccess; - webAccess.SetHeader(L"content-type", L"text/html; charset=utf-8"); - webAccess.SetTimeout(timeout); //default: 10 minutes(WTF are these wxWidgets people thinking???)... - - if (webAccess.Connect(server)) //will *not* fail for non-reachable url here! - { - //wxApp::IsMainLoopRunning(); // should return true - - std::unique_ptr<wxInputStream> httpStream(webAccess.GetInputStream(page)); - //must be deleted BEFORE webAccess is closed - - if (httpStream && webAccess.GetError() == wxPROTO_NOERR) - { - if (output) - { - output->clear(); - wxStringOutputStream outStream(output); - httpStream->Read(outStream); - } - return true; - } - } - return false; - }; - - if (getStringFromUrl(L"freefilesync.sourceforge.net", L"/latest_version.txt", 5, &version)) - return GET_VER_SUCCESS; - - const bool canConnectToSf = getStringFromUrl(L"sourceforge.net", L"/", 1, nullptr); - return canConnectToSf ? GET_VER_PAGE_NOT_FOUND : GET_VER_NO_CONNECTION; -#endif -} - - -const wchar_t VERSION_SEP = L'.'; - -std::vector<size_t> parseVersion(const wxString& version) -{ - std::vector<wxString> digits = split(version, VERSION_SEP); - - std::vector<size_t> output; - std::transform(digits.begin(), digits.end(), std::back_inserter(output), [&](const wxString& d) { return stringTo<size_t>(d); }); - return output; -} - - -bool haveNewerVersion(const wxString& onlineVersion) -{ - std::vector<size_t> current = parseVersion(zen::currentVersion); - std::vector<size_t> online = parseVersion(onlineVersion); - - if (online.empty() || online[0] == 0) //online version may be "This website has been moved..." In this case better check for an update - return true; - - return std::lexicographical_compare(current.begin(), current.end(), - online .begin(), online .end()); -} -} - - -void zen::checkForUpdateNow(wxWindow* parent) -{ - wxString onlineVersion; - switch (getOnlineVersion(onlineVersion)) - { - case GET_VER_SUCCESS: - if (haveNewerVersion(onlineVersion)) - { - switch (showConfirmationDialog(parent, DialogInfoType::INFO, PopupDialogCfg(). - setTitle(_("Check for Program Updates")). - setMainInstructions(_("A new version of FreeFileSync is available:") + L" " + onlineVersion + L"\n\n" + _("Download now?")), - _("&Download"))) - { - case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/get_latest.php"); - break; - case ConfirmationButton::CANCEL: - break; - } - } - else - showNotificationDialog(parent, DialogInfoType::INFO, PopupDialogCfg(). - setTitle(_("Check for Program Updates")). - setMainInstructions(_("FreeFileSync is up to date."))); - break; - - case GET_VER_NO_CONNECTION: - showNotificationDialog(parent, DialogInfoType::ERROR2, PopupDialogCfg(). - setTitle(("Check for Program Updates")). - setMainInstructions(_("Unable to connect to sourceforge.net."))); - break; - - case GET_VER_PAGE_NOT_FOUND: - switch (showConfirmationDialog(parent, DialogInfoType::ERROR2, PopupDialogCfg(). - setTitle(_("Check for Program Updates")). - setMainInstructions(_("Cannot find current FreeFileSync version number online. Do you want to check manually?")), - _("&Check"))) - { - case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/"); - break; - case ConfirmationButton::CANCEL: - break; - } - break; - } -} - - -void zen::checkForUpdatePeriodically(wxWindow* parent, long& lastUpdateCheck, const std::function<void()>& onBeforeInternetAccess) -{ - if (lastUpdateCheck != -1) - { - if (wxGetLocalTime() >= lastUpdateCheck + 7 * 24 * 3600) //check weekly - { - onBeforeInternetAccess(); //notify client before (potentially) blocking some time - wxString onlineVersion; - switch (getOnlineVersion(onlineVersion)) - { - case GET_VER_SUCCESS: - lastUpdateCheck = wxGetLocalTime(); - - if (haveNewerVersion(onlineVersion)) - { - switch (showConfirmationDialog(parent, DialogInfoType::INFO, PopupDialogCfg(). - setTitle(_("Check for Program Updates")). - setMainInstructions(_("A new version of FreeFileSync is available:") + L" " + onlineVersion + L"\n\n" + _("Download now?")), - _("&Download"))) - { - case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/get_latest.php"); - break; - case ConfirmationButton::CANCEL: - break; - } - } - break; - - case GET_VER_NO_CONNECTION: - break; //ignore this error - - case GET_VER_PAGE_NOT_FOUND: - switch (showConfirmationDialog(parent, DialogInfoType::ERROR2, PopupDialogCfg(). - setTitle(_("Check for Program Updates")). - setMainInstructions(_("Cannot find current FreeFileSync version number online. Do you want to check manually?")), - _("&Check"))) - { - case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/"); - break; - case ConfirmationButton::CANCEL: - break; - } - break; - } - } - } -} diff --git a/ui/check_version.h b/ui/check_version.h deleted file mode 100644 index d2e7220f..00000000 --- a/ui/check_version.h +++ /dev/null @@ -1,20 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef UPDATEVERSION_H_INCLUDED -#define UPDATEVERSION_H_INCLUDED - -#include <functional> -#include <wx/window.h> - - -namespace zen -{ -void checkForUpdateNow(wxWindow* parent); -void checkForUpdatePeriodically(wxWindow* parent, long& lastUpdateCheck, const std::function<void()>& onBeforeInternetAccess); //-1: check never -} - -#endif // UPDATEVERSION_H_INCLUDED diff --git a/ui/column_attr.h b/ui/column_attr.h deleted file mode 100644 index 070e6dd8..00000000 --- a/ui/column_attr.h +++ /dev/null @@ -1,111 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef COL_ATTR_HEADER_189467891346732143214 -#define COL_ATTR_HEADER_189467891346732143214 - -#include <vector> - -namespace zen -{ -enum ColumnTypeRim -{ - COL_TYPE_DIRECTORY, - COL_TYPE_FULL_PATH, - COL_TYPE_REL_PATH, - COL_TYPE_FILENAME, - COL_TYPE_SIZE, - COL_TYPE_DATE, - COL_TYPE_EXTENSION -}; - -struct ColumnAttributeRim -{ - ColumnAttributeRim() : type_(COL_TYPE_DIRECTORY), offset_(0), stretch_(0), visible_(false) {} - ColumnAttributeRim(ColumnTypeRim type, int offset, int stretch, bool visible) : type_(type), offset_(offset), stretch_(stretch), visible_(visible) {} - - ColumnTypeRim type_; - int offset_; - int stretch_; - bool visible_; -}; - -warn_static("two stretched oclumsn: hide vergrößert range!") -inline -std::vector<ColumnAttributeRim> getDefaultColumnAttributesLeft() -{ - std::vector<ColumnAttributeRim> attr; - attr.push_back(ColumnAttributeRim(COL_TYPE_FULL_PATH, 250, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_DIRECTORY, 200, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_REL_PATH, 200, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_FILENAME, -280, 1, true)); //stretch to full width and substract sum of fixed size widths! - attr.push_back(ColumnAttributeRim(COL_TYPE_DATE, 112, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_SIZE, 80, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_EXTENSION, 60, 0, false)); - return attr; -} - -inline -std::vector<ColumnAttributeRim> getDefaultColumnAttributesRight() -{ - std::vector<ColumnAttributeRim> attr; - attr.push_back(ColumnAttributeRim(COL_TYPE_FULL_PATH, 250, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_DIRECTORY, 200, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_REL_PATH, 200, 0, false)); //already shown on left side - attr.push_back(ColumnAttributeRim(COL_TYPE_FILENAME, -80, 1, true)); //stretch to full width and substract sum of fixed size widths! - attr.push_back(ColumnAttributeRim(COL_TYPE_DATE, 112, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_SIZE, 80, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_EXTENSION, 60, 0, false)); - return attr; -} - -//------------------------------------------------------------------ - -enum ColumnTypeMiddle -{ - COL_TYPE_CHECKBOX, - COL_TYPE_CMP_CATEGORY, - COL_TYPE_SYNC_ACTION, -}; - -//------------------------------------------------------------------ - -enum ColumnTypeNavi -{ - COL_TYPE_NAVI_BYTES, - COL_TYPE_NAVI_DIRECTORY, - COL_TYPE_NAVI_ITEM_COUNT -}; - - -struct ColumnAttributeNavi -{ - ColumnAttributeNavi() : type_(COL_TYPE_NAVI_DIRECTORY), offset_(0), stretch_(0), visible_(false) {} - ColumnAttributeNavi(ColumnTypeNavi type, int offset, int stretch, bool visible) : type_(type), offset_(offset), stretch_(stretch), visible_(visible) {} - - ColumnTypeNavi type_; - int offset_; - int stretch_; - bool visible_; -}; - - -const bool defaultValueShowPercentage = true; -const ColumnTypeNavi defaultValueLastSortColumn = COL_TYPE_NAVI_BYTES; //remember sort on navigation panel -const bool defaultValueLastSortAscending = false; // - -inline -std::vector<ColumnAttributeNavi> getDefaultColumnAttributesNavi() -{ - std::vector<ColumnAttributeNavi> attr; - attr.push_back(ColumnAttributeNavi(COL_TYPE_NAVI_DIRECTORY, -120, 1, true)); //stretch to full width and substract sum of fixed size widths - attr.push_back(ColumnAttributeNavi(COL_TYPE_NAVI_ITEM_COUNT, 60, 0, true)); - attr.push_back(ColumnAttributeNavi(COL_TYPE_NAVI_BYTES, 60, 0, true)); //GTK needs a few pixels width more - return attr; -} -} - -#endif // COL_ATTR_HEADER_189467891346732143214 diff --git a/ui/custom_grid.cpp b/ui/custom_grid.cpp deleted file mode 100644 index 4f498a20..00000000 --- a/ui/custom_grid.cpp +++ /dev/null @@ -1,1800 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "custom_grid.h" -#include <wx/dc.h> -#include <wx/settings.h> -#include <zen/i18n.h> -#include <zen/file_error.h> -#include <zen/basic_math.h> -#include <zen/format_unit.h> -#include <zen/scope_guard.h> -#include <wx+/tooltip.h> -#include <wx+/string_conv.h> -#include <wx+/rtl.h> -#include <wx+/image_tools.h> -#include <wx+/image_resources.h> -#include "../file_hierarchy.h" - -using namespace zen; -using namespace gridview; - - -const wxEventType zen::EVENT_GRID_CHECK_ROWS = wxNewEventType(); -const wxEventType zen::EVENT_GRID_SYNC_DIRECTION = wxNewEventType(); - -namespace -{ -const wxColour COLOR_ORANGE (238, 201, 0); -const wxColour COLOR_GREY (212, 208, 200); -const wxColour COLOR_YELLOW (247, 252, 62); -const wxColour COLOR_YELLOW_LIGHT(253, 252, 169); -const wxColour COLOR_CMP_RED (255, 185, 187); -const wxColour COLOR_SYNC_BLUE (185, 188, 255); -const wxColour COLOR_SYNC_GREEN (196, 255, 185); -const wxColour COLOR_NOT_ACTIVE (228, 228, 228); //light grey - - -const Zstring ICON_FILE_FOLDER = Zstr("folder"); -const size_t ROW_COUNT_NO_DATA = 10; - -/* -class hierarchy: - GridDataBase - /|\ - ________________|________________ - | | - GridDataRim | - /|\ | - __________|__________ | - | | | - GridDataLeft GridDataRight GridDataMiddle -*/ - - - -void refreshCell(Grid& grid, size_t row, ColumnType colType) -{ - wxRect cellArea = grid.getCellArea(row, colType); //returns empty rect if column not found; absolute coordinates! - if (cellArea.height > 0) - { - cellArea.SetTopLeft(grid.CalcScrolledPosition(cellArea.GetTopLeft())); - grid.getMainWin().RefreshRect(cellArea, false); - } -} - - -std::pair<ptrdiff_t, ptrdiff_t> getVisibleRows(const Grid& grid) //returns range [from, to) -{ - const wxSize clientSize = grid.getMainWin().GetClientSize(); - if (clientSize.GetHeight() > 0) - { - wxPoint topLeft = grid.CalcUnscrolledPosition(wxPoint(0, 0)); - wxPoint bottom = grid.CalcUnscrolledPosition(wxPoint(0, clientSize.GetHeight() - 1)); - - const ptrdiff_t rowCount = grid.getRowCount(); - const ptrdiff_t rowFrom = grid.getRowAtPos(topLeft.y); //return -1 for invalid position, rowCount if out of range - if (rowFrom >= 0) - { - const ptrdiff_t rowTo = grid.getRowAtPos(bottom.y); - if (0 <= rowTo && rowTo < rowCount) - return std::make_pair(rowFrom, rowTo + 1); - else - return std::make_pair(rowFrom, rowCount); - } - } - return std::make_pair(0, 0); -} - - -void fillBackgroundDefaultColorAlternating(wxDC& dc, const wxRect& rect, bool evenRowNumber) -{ - //alternate background color to improve readability (while lacking cell borders) - if (!evenRowNumber) - { - //accessibility, support high-contrast schemes => work with user-defined background color! - const auto backCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - - auto incChannel = [](unsigned char c, int diff) { return static_cast<unsigned char>(std::max(0, std::min(255, c + diff))); }; - - auto getAdjustedColor = [&](int diff) - { - return wxColor(incChannel(backCol.Red (), diff), - incChannel(backCol.Green(), diff), - incChannel(backCol.Blue (), diff)); - }; - - auto colorDist = [](const wxColor& lhs, const wxColor& rhs) //just some metric - { - return numeric::power<2>(static_cast<int>(lhs.Red ()) - static_cast<int>(rhs.Red ())) + - numeric::power<2>(static_cast<int>(lhs.Green()) - static_cast<int>(rhs.Green())) + - numeric::power<2>(static_cast<int>(lhs.Blue ()) - static_cast<int>(rhs.Blue ())); - }; - - const int signLevel = colorDist(backCol, *wxBLACK) < colorDist(backCol, *wxWHITE) ? 1 : -1; //brighten or darken - - const wxColor colOutter = getAdjustedColor(signLevel * 14); //just some very faint gradient to avoid visual distraction - const wxColor colInner = getAdjustedColor(signLevel * 11); // - - //clearArea(dc, rect, backColAlt); - - //add some nice background gradient - wxRect rectUpper = rect; - rectUpper.height /= 2; - wxRect rectLower = rect; - rectLower.y += rectUpper.height; - rectLower.height -= rectUpper.height; - dc.GradientFillLinear(rectUpper, colOutter, colInner, wxSOUTH); - dc.GradientFillLinear(rectLower, colOutter, colInner, wxNORTH); - } - else - clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -} - - -Zstring getExtension(const Zstring& shortName) -{ - return contains(shortName, Zchar('.')) ? afterLast(shortName, Zchar('.')) : Zstring(); -}; - - -class IconUpdater; -class GridEventManager; -class GridDataLeft; -class GridDataRight; - -struct IconManager -{ - IconManager(GridDataLeft& provLeft, GridDataRight& provRight, IconBuffer::IconSize sz) : iconBuffer(sz), - iconUpdater(make_unique<IconUpdater>(provLeft, provRight, iconBuffer)) {} - - void startIconUpdater(); - IconBuffer& refIconBuffer() { return iconBuffer; } -private: - IconBuffer iconBuffer; - std::unique_ptr<IconUpdater> iconUpdater; //bind ownership to GridDataRim<>! -}; - -//######################################################################################################## - -class GridDataBase : public GridData -{ -public: - GridDataBase(Grid& grid, const std::shared_ptr<const zen::GridView>& gridDataView) : grid_(grid), gridDataView_(gridDataView) {} - - void holdOwnership(const std::shared_ptr<GridEventManager>& evtMgr) { evtMgr_ = evtMgr; } - GridEventManager* getEventManager() { return evtMgr_.get(); } - -protected: - Grid& refGrid() { return grid_; } - const Grid& refGrid() const { return grid_; } - - const GridView* getGridDataView() const { return gridDataView_.get(); } - - const FileSystemObject* getRawData(size_t row) const - { - if (auto view = getGridDataView()) - return view->getObject(row); - return nullptr; - } - -private: - virtual size_t getRowCount() const - { - if (gridDataView_) - { - if (gridDataView_->rowsTotal() == 0) - return ROW_COUNT_NO_DATA; - return gridDataView_->rowsOnView(); - } - else - return ROW_COUNT_NO_DATA; - - //return std::max(MIN_ROW_COUNT, gridDataView_ ? gridDataView_->rowsOnView() : 0); - } - - std::shared_ptr<GridEventManager> evtMgr_; - Grid& grid_; - std::shared_ptr<const GridView> gridDataView_; -}; - -//######################################################################################################## - -template <SelectedSide side> -class GridDataRim : public GridDataBase -{ -public: - GridDataRim(const std::shared_ptr<const zen::GridView>& gridDataView, Grid& grid) : GridDataBase(grid, gridDataView) {} - - void setIconManager(const std::shared_ptr<IconManager>& iconMgr) { iconMgr_ = iconMgr; } - - void updateNewAndGetMissingIcons(std::list<Zstring>& newLoad) //loads all (not yet) drawn icons - { - //don't check too often! give worker thread some time to fetch data - if (iconMgr_) - { - const auto& rowsOnScreen = getVisibleRows(refGrid()); - - //loop over all visible rows - const ptrdiff_t firstRow = rowsOnScreen.first; - const ptrdiff_t rowCount = rowsOnScreen.second - firstRow; - - for (ptrdiff_t i = 0; i < rowCount; ++i) - { - //alternate when adding rows: first, last, first + 1, last - 1 ... -> Icon buffer will then load reversely, i.e. from inside out - const ptrdiff_t currentRow = firstRow + (i % 2 == 0 ? - i / 2 : - rowCount - 1 - (i - 1) / 2); - - if (isFailedLoad(currentRow)) //find failed attempts to load icon - { - const Zstring filename = getIconFile(currentRow); - if (!filename.empty() && filename != ICON_FILE_FOLDER) - { - //test if they are already loaded in buffer: - if (iconMgr_->refIconBuffer().readyForRetrieval(filename)) - { - //do a *full* refresh for *every* failed load to update partial DC updates while scrolling - refreshCell(refGrid(), currentRow, static_cast<ColumnType>(COL_TYPE_FILENAME)); - setFailedLoad(currentRow, false); - } - else //not yet in buffer: mark for async. loading - newLoad.push_back(filename); - } - } - } - } - } - -private: - bool isFailedLoad(size_t row) const { return row < failedLoads.size() ? failedLoads[row] != 0 : false; } - - void setFailedLoad(size_t row, bool failed) - { - if (failed) //let's only pay for iconupdater when needed - if (iconMgr_) - iconMgr_->startIconUpdater(); - - if (failedLoads.size() != refGrid().getRowCount()) - failedLoads.resize(refGrid().getRowCount()); - - if (row < failedLoads.size()) - failedLoads[row] = failed; - } - -protected: - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override - { - if (enabled) - { - if (selected) - dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST); - //ignore focus - else - { - //alternate background color to improve readability (while lacking cell borders) - if (getRowDisplayType(row) == DISP_TYPE_NORMAL) - fillBackgroundDefaultColorAlternating(dc, rect, row % 2 == 0); - else - clearArea(dc, rect, getBackGroundColor(row)); - - //draw horizontal border if required - DisplayType dispTp = getRowDisplayType(row); - if (dispTp != DISP_TYPE_NORMAL && - dispTp == getRowDisplayType(row + 1)) - { - const wxColor colorGridLine = wxColour(192, 192, 192); //light grey - wxDCPenChanger dummy2(dc, wxPen(colorGridLine, 1, wxSOLID)); - dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight() + wxPoint(1, 0)); - } - } - } - else - clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - } - - wxColor getBackGroundColor(size_t row) const - { - //accessibility: always set both foreground AND background colors! - // => harmonize with renderCell()! - - switch (getRowDisplayType(row)) - { - case DISP_TYPE_NORMAL: - break; - case DISP_TYPE_FOLDER: - return COLOR_GREY; - case DISP_TYPE_SYMLINK: - return COLOR_ORANGE; - case DISP_TYPE_INACTIVE: - return COLOR_NOT_ACTIVE; - } - return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - } - -private: - enum DisplayType - { - DISP_TYPE_NORMAL, - DISP_TYPE_FOLDER, - DISP_TYPE_SYMLINK, - DISP_TYPE_INACTIVE, - }; - - DisplayType getRowDisplayType(size_t row) const - { - const FileSystemObject* fsObj = getRawData(row); - if (!fsObj ) - return DISP_TYPE_NORMAL; - - //mark filtered rows - if (!fsObj->isActive()) - return DISP_TYPE_INACTIVE; - - if (fsObj->isEmpty<side>()) //always show not existing files/dirs/symlinks as empty - return DISP_TYPE_NORMAL; - - DisplayType output = DISP_TYPE_NORMAL; - //mark directories and symlinks - struct GetRowType : public FSObjectVisitor - { - GetRowType(DisplayType& result) : result_(result) {} - - virtual void visit(const FilePair& fileObj) {} - virtual void visit(const SymlinkPair& linkObj) - { - result_ = DISP_TYPE_SYMLINK; - } - virtual void visit(const DirPair& dirObj) - { - result_ = DISP_TYPE_FOLDER; - } - private: - DisplayType& result_; - } getType(output); - fsObj->accept(getType); - return output; - } - - virtual wxString getValue(size_t row, ColumnType colType) const - { - if (const FileSystemObject* fsObj = getRawData(row)) - { - struct GetTextValue : public FSObjectVisitor - { - GetTextValue(ColumnTypeRim colType, const FileSystemObject& fso) : colType_(colType), fsObj_(fso) {} - - virtual void visit(const FilePair& fileObj) - { - switch (colType_) - { - case COL_TYPE_FULL_PATH: - value = toWx(appendSeparator(beforeLast(fileObj.getBaseDirPf<side>() + fileObj.getObjRelativeName(), FILE_NAME_SEPARATOR))); - break; - case COL_TYPE_FILENAME: //filename - value = toWx(fileObj.getShortName<side>()); - break; - case COL_TYPE_REL_PATH: //relative path - value = toWx(beforeLast(fileObj.getObjRelativeName(), FILE_NAME_SEPARATOR)); //returns empty string if ch not found - break; - case COL_TYPE_DIRECTORY: - value = toWx(fileObj.getBaseDirPf<side>()); - break; - case COL_TYPE_SIZE: //file size - if (!fsObj_.isEmpty<side>()) - value = zen::toGuiString(fileObj.getFileSize<side>()); - - // -> test file id - //if (!fsObj_.isEmpty<side>()) - // value = toGuiString(fileObj.getFileId<side>().second) + L" " + toGuiString(fileObj.getFileId<side>().first); - break; - case COL_TYPE_DATE: //date - if (!fsObj_.isEmpty<side>()) - value = zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()); - break; - case COL_TYPE_EXTENSION: //file extension - value = toWx(getExtension(fileObj.getShortName<side>())); - break; - } - } - - virtual void visit(const SymlinkPair& linkObj) - { - switch (colType_) - { - case COL_TYPE_FULL_PATH: - value = toWx(appendSeparator(beforeLast(linkObj.getBaseDirPf<side>() + linkObj.getObjRelativeName(), FILE_NAME_SEPARATOR))); - break; - case COL_TYPE_FILENAME: //filename - value = toWx(linkObj.getShortName<side>()); - break; - case COL_TYPE_REL_PATH: //relative path - value = toWx(beforeLast(linkObj.getObjRelativeName(), FILE_NAME_SEPARATOR)); //returns empty string if ch not found - break; - case COL_TYPE_DIRECTORY: - value = toWx(linkObj.getBaseDirPf<side>()); - break; - case COL_TYPE_SIZE: //file size - if (!fsObj_.isEmpty<side>()) - value = L"<" + _("Symlink") + L">"; - break; - case COL_TYPE_DATE: //date - if (!fsObj_.isEmpty<side>()) - value = zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()); - break; - case COL_TYPE_EXTENSION: //file extension - value = toWx(getExtension(linkObj.getShortName<side>())); - break; - } - } - - virtual void visit(const DirPair& dirObj) - { - switch (colType_) - { - case COL_TYPE_FULL_PATH: - value = toWx(appendSeparator(beforeLast(dirObj.getBaseDirPf<side>() + dirObj.getObjRelativeName(), FILE_NAME_SEPARATOR))); - break; - case COL_TYPE_FILENAME: - value = toWx(dirObj.getShortName<side>()); - break; - case COL_TYPE_REL_PATH: - value = toWx(beforeLast(dirObj.getObjRelativeName(), FILE_NAME_SEPARATOR)); //returns empty string if ch not found - break; - case COL_TYPE_DIRECTORY: - value = toWx(dirObj.getBaseDirPf<side>()); - break; - case COL_TYPE_SIZE: //file size - if (!fsObj_.isEmpty<side>()) - value = L"<" + _("Folder") + L">"; - break; - case COL_TYPE_DATE: //date - if (!fsObj_.isEmpty<side>()) - value = wxEmptyString; - break; - case COL_TYPE_EXTENSION: //file extension - value = wxEmptyString; - break; - } - } - ColumnTypeRim colType_; - wxString value; - - const FileSystemObject& fsObj_; - } getVal(static_cast<ColumnTypeRim>(colType), *fsObj); - fsObj->accept(getVal); - return getVal.value; - } - //if data is not found: - return wxEmptyString; - } - - static const int GAP_SIZE = 2; - - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool selected) override - { - wxRect rectTmp = rect; - - const bool isActive = [&]() -> bool - { - if (const FileSystemObject* fsObj = this->getRawData(row)) - return fsObj->isActive(); - return true; - }(); - - //draw file icon - if (static_cast<ColumnTypeRim>(colType) == COL_TYPE_FILENAME && - iconMgr_) - { - rectTmp.x += GAP_SIZE; - rectTmp.width -= GAP_SIZE; - - const int iconSize = iconMgr_->refIconBuffer().getSize(); - if (rectTmp.GetWidth() >= iconSize) - { - // Partitioning: - // __________________________ - // | gap | icon | gap | text | - // -------------------------- - - const Zstring filename = getIconFile(row); - if (!filename.empty()) - { - wxBitmap fileIcon; - - //first check if it is a directory icon: - if (filename == ICON_FILE_FOLDER) - fileIcon = iconMgr_->refIconBuffer().genericDirIcon(); - else //retrieve file icon - { - if (Opt<wxBitmap> tmpIco = iconMgr_->refIconBuffer().retrieveFileIcon(filename)) - fileIcon = *tmpIco; - else - { - fileIcon = iconMgr_->refIconBuffer().genericFileIcon(); //better than nothing - setFailedLoad(row, true); //save status of failed icon load -> used for async. icon loading - //falsify only! we want to avoid writing incorrect success values when only partially updating the DC, e.g. when scrolling, - //see repaint behavior of ::ScrollWindow() function! - } - } - - if (fileIcon.IsOk()) - { - wxRect rectIcon = rectTmp; - rectIcon.width = iconSize; //support small thumbnail centering - if (isActive) - drawBitmapRtlNoMirror(dc, fileIcon, rectIcon, wxALIGN_CENTER, buffer); - else - drawBitmapRtlNoMirror(dc, wxBitmap(fileIcon.ConvertToImage().ConvertToGreyscale(1.0 / 3, 1.0 / 3, 1.0 / 3)), //treat all channels equally! - rectIcon, wxALIGN_CENTER, buffer); - } - } - } - rectTmp.x += iconSize; - rectTmp.width -= iconSize; - } - - std::unique_ptr<wxDCTextColourChanger> dummy3; - if (getRowDisplayType(row) != DISP_TYPE_NORMAL) - dummy3 = make_unique<wxDCTextColourChanger>(dc, *wxBLACK); //accessibility: always set both foreground AND background colors! - - //draw text - if (static_cast<ColumnTypeRim>(colType) == COL_TYPE_SIZE && refGrid().GetLayoutDirection() != wxLayout_RightToLeft) - { - //have file size right-justified (but don't change for RTL languages) - rectTmp.width -= GAP_SIZE; - drawCellText(dc, rectTmp, getValue(row, colType), isActive, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - } - else - { - rectTmp.x += GAP_SIZE; - rectTmp.width -= GAP_SIZE; - drawCellText(dc, rectTmp, getValue(row, colType), isActive, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - } - } - - virtual int getBestSize(wxDC& dc, size_t row, ColumnType colType) override - { - // Partitioning: - // ________________________________ - // | gap | icon | gap | text | gap | - // -------------------------------- - - int bestSize = 0; - if (static_cast<ColumnTypeRim>(colType) == COL_TYPE_FILENAME && iconMgr_) - bestSize += GAP_SIZE + iconMgr_->refIconBuffer().getSize(); - - bestSize += GAP_SIZE + dc.GetTextExtent(getValue(row, colType)).GetWidth() + GAP_SIZE; - - return bestSize; // + 1 pix for cell border line -> not used anymore! - } - - virtual wxString getColumnLabel(ColumnType colType) const - { - switch (static_cast<ColumnTypeRim>(colType)) - { - case COL_TYPE_FULL_PATH: - return _("Full path"); - case COL_TYPE_FILENAME: - return _("Name"); //= short name - case COL_TYPE_REL_PATH: - return _("Relative path"); - case COL_TYPE_DIRECTORY: - return _("Base folder"); - case COL_TYPE_SIZE: - return _("Size"); - case COL_TYPE_DATE: - return _("Date"); - case COL_TYPE_EXTENSION: - return _("Extension"); - } - return wxEmptyString; - } - - virtual void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override - { - wxRect rectInside = drawColumnLabelBorder(dc, rect); - drawColumnLabelBackground(dc, rectInside, highlighted); - - rectInside.x += COLUMN_GAP_LEFT; - rectInside.width -= COLUMN_GAP_LEFT; - drawColumnLabelText(dc, rectInside, getColumnLabel(colType)); - - //draw sort marker - if (getGridDataView()) - { - auto sortInfo = getGridDataView()->getSortInfo(); - if (sortInfo) - { - if (colType == static_cast<ColumnType>(sortInfo->type_) && (side == LEFT_SIDE) == sortInfo->onLeft_) - { - const wxBitmap& marker = getResourceImage(sortInfo->ascending_ ? L"sortAscending" : L"sortDescending"); - wxPoint markerBegin = rectInside.GetTopLeft() + wxPoint((rectInside.width - marker.GetWidth()) / 2, 0); - dc.DrawBitmap(marker, markerBegin, true); //respect 2-pixel gap - } - } - } - } - - Zstring getIconFile(size_t row) const //return ICON_FILE_FOLDER if row points to a folder - { - const FileSystemObject* fsObj = getRawData(row); - if (fsObj && !fsObj->isEmpty<side>()) - { - struct GetIcon : public FSObjectVisitor - { - virtual void visit(const FilePair& fileObj) - { - iconName = fileObj.getFullName<side>(); - } - virtual void visit(const SymlinkPair& linkObj) - { - iconName = linkObj.getFullName<side>(); - } - virtual void visit(const DirPair& dirObj) - { - iconName = ICON_FILE_FOLDER; - } - - Zstring iconName; - } getIcon; - fsObj->accept(getIcon); - return getIcon.iconName; - } - return Zstring(); - } - - virtual wxString getToolTip(size_t row, ColumnType colType) const override - { - wxString toolTip; - - const FileSystemObject* fsObj = getRawData(row); - if (fsObj && !fsObj->isEmpty<side>()) - { - toolTip = toWx(getGridDataView() && getGridDataView()->getFolderPairCount() > 1 ? - fsObj->getFullName<side>() : - fsObj->getRelativeName<side>()); - - struct AssembleTooltip : public FSObjectVisitor - { - AssembleTooltip(wxString& tipMsg) : tipMsg_(tipMsg) {} - - virtual void visit(const FilePair& fileObj) - { - tipMsg_ += L"\n" + - _("Size:") + L" " + zen::filesizeToShortString(to<Int64>(fileObj.getFileSize<side>())) + L"\n" + - _("Date:") + L" " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()); - } - - virtual void visit(const SymlinkPair& linkObj) - { - tipMsg_ += L"\n" + - _("Date:") + L" " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()); - } - - virtual void visit(const DirPair& dirObj) {} - - wxString& tipMsg_; - } assembler(toolTip); - fsObj->accept(assembler); - } - return toolTip; - } - - std::shared_ptr<IconManager> iconMgr_; //optional - std::vector<char> failedLoads; //effectively a vector<bool> of size "number of rows" - std::unique_ptr<wxBitmap> buffer; //avoid costs of recreating this temporal variable -}; - - -class GridDataLeft : public GridDataRim<LEFT_SIDE> -{ -public: - GridDataLeft(const std::shared_ptr<const zen::GridView>& gridDataView, Grid& grid) : GridDataRim<LEFT_SIDE>(gridDataView, grid) {} - - void setNavigationMarker(hash_set<const FileSystemObject*>&& markedFilesAndLinks, - hash_set<const HierarchyObject*>&& markedContainer) - { - markedFilesAndLinks_.swap(markedFilesAndLinks); - markedContainer_ .swap(markedContainer); - } - -private: - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override - { - GridDataRim<LEFT_SIDE>::renderRowBackgound(dc, rect, row, enabled, selected); - - //mark rows selected on navigation grid: - if (enabled && !selected) - { - const bool markRow = [&]() -> bool - { - if (const FileSystemObject* fsObj = getRawData(row)) - { - if (markedFilesAndLinks_.find(fsObj) != markedFilesAndLinks_.end()) //mark files/links directly - return true; - - if (auto dirObj = dynamic_cast<const DirPair*>(fsObj)) - { - if (markedContainer_.find(dirObj) != markedContainer_.end()) //mark directories which *are* the given HierarchyObject* - return true; - } - - //mark all objects which have the HierarchyObject as *any* matching ancestor - const HierarchyObject* parent = &(fsObj->parent()); - for (;;) - { - if (markedContainer_.find(parent) != markedContainer_.end()) - return true; - - if (auto dirObj = dynamic_cast<const DirPair*>(parent)) - parent = &(dirObj->parent()); - else - break; - } - } - return false; - }(); - - if (markRow) - { - //const wxColor COLOR_TREE_SELECTION_GRADIENT = wxColor(101, 148, 255); //H:158 S:255 V:178 - const wxColor COLOR_TREE_SELECTION_GRADIENT = getColorSelectionGradientFrom(); - - wxRect rectTmp = rect; - rectTmp.width /= 20; - dc.GradientFillLinear(rectTmp, COLOR_TREE_SELECTION_GRADIENT, GridDataRim<LEFT_SIDE>::getBackGroundColor(row), wxEAST); - } - } - } - - hash_set<const FileSystemObject*> markedFilesAndLinks_; //mark files/symlinks directly within a container - hash_set<const HierarchyObject*> markedContainer_; //mark full container including all child-objects - //DO NOT DEREFERENCE!!!! NOT GUARANTEED TO BE VALID!!! -}; - - -class GridDataRight : public GridDataRim<RIGHT_SIDE> -{ -public: - GridDataRight(const std::shared_ptr<const zen::GridView>& gridDataView, Grid& grid) : GridDataRim<RIGHT_SIDE>(gridDataView, grid) {} -}; - -//######################################################################################################## - -class GridDataMiddle : public GridDataBase -{ -public: - GridDataMiddle(const std::shared_ptr<const zen::GridView>& gridDataView, Grid& grid) : - GridDataBase(grid, gridDataView), - highlightSyncAction_(false), - toolTip(grid), //tool tip must not live longer than grid! - notch(getResourceImage(L"notch").ConvertToImage()) {} - - void onSelectBegin(const wxPoint& clientPos, size_t row, ColumnType colType) - { - if (row < refGrid().getRowCount()) - { - refGrid().clearSelection(false); //don't emit event, prevent recursion! - dragSelection = make_unique<std::pair<size_t, BlockPosition>>(row, mousePosToBlock(clientPos, row, static_cast<ColumnTypeMiddle>(colType))); - toolTip.hide(); //handle custom tooltip - } - } - - void onSelectEnd(size_t rowFirst, size_t rowLast) //we cannot reuse row from "onSelectBegin": if user is holding shift, this may now be in the middle of the range! - { - refGrid().clearSelection(false); //don't emit event, prevent recursion! - - //issue custom event - if (dragSelection) - { - if (rowFirst < rowLast && //may be empty? probably not in this context - rowLast <= refGrid().getRowCount()) - { - if (wxEvtHandler* evtHandler = refGrid().GetEventHandler()) - switch (dragSelection->second) - { - case BLOCKPOS_CHECK_BOX: - { - const FileSystemObject* fsObj = getRawData(dragSelection->first); - const bool setIncluded = fsObj ? !fsObj->isActive() : true; - - CheckRowsEvent evt(rowFirst, rowLast, setIncluded); - evtHandler->ProcessEvent(evt); - } - break; - case BLOCKPOS_LEFT: - { - SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::LEFT); - evtHandler->ProcessEvent(evt); - } - break; - case BLOCKPOS_MIDDLE: - { - SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::NONE); - evtHandler->ProcessEvent(evt); - } - break; - case BLOCKPOS_RIGHT: - { - SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::RIGHT); - evtHandler->ProcessEvent(evt); - } - break; - } - } - dragSelection.reset(); - } - - //update highlight and tooltip: on OS X no mouse movement event is generated after a mouse button click (unlike on Windows) - wxPoint clientPos = refGrid().getMainWin().ScreenToClient(wxGetMousePosition()); - onMouseMovement(clientPos); - } - - void onMouseMovement(const wxPoint& clientPos) - { - //manage block highlighting and custom tooltip - if (!dragSelection) - { - auto refreshHighlight = [&](size_t row) - { - refreshCell(refGrid(), row, static_cast<ColumnType>(COL_TYPE_CHECKBOX)); - refreshCell(refGrid(), row, static_cast<ColumnType>(COL_TYPE_SYNC_ACTION)); - }; - - const wxPoint& topLeftAbs = refGrid().CalcUnscrolledPosition(clientPos); - const size_t row = refGrid().getRowAtPos(topLeftAbs.y); //return -1 for invalid position, rowCount if one past the end - auto colInfo = refGrid().getColumnAtPos(topLeftAbs.x); //(column type, component position) - - if (row < refGrid().getRowCount() && colInfo) - { - if (highlight) refreshHighlight(highlight->row_); //refresh old highlight - - highlight = make_unique<MouseHighlight>(row, mousePosToBlock(clientPos, row, static_cast<ColumnTypeMiddle>(colInfo->first))); - - refreshHighlight(highlight->row_); - - //show custom tooltip - if (refGrid().getMainWin().GetClientRect().Contains(clientPos)) //cursor might have moved outside visible client area - showToolTip(row, static_cast<ColumnTypeMiddle>(colInfo->first), refGrid().getMainWin().ClientToScreen(clientPos)); - } - else - onMouseLeave(); - } - } - - void onMouseLeave() //wxEVT_LEAVE_WINDOW does not respect mouse capture! - { - if (!dragSelection) - { - if (highlight) - { - refreshCell(refGrid(), highlight->row_, static_cast<ColumnType>(COL_TYPE_CHECKBOX)); - refreshCell(refGrid(), highlight->row_, static_cast<ColumnType>(COL_TYPE_SYNC_ACTION)); - highlight.reset(); - } - toolTip.hide(); //handle custom tooltip - } - } - - void highlightSyncAction(bool value) { highlightSyncAction_ = value; } - -private: - virtual wxString getValue(size_t row, ColumnType colType) const override - { - if (const FileSystemObject* fsObj = getRawData(row)) - switch (static_cast<ColumnTypeMiddle>(colType)) - { - case COL_TYPE_CHECKBOX: - break; - case COL_TYPE_CMP_CATEGORY: - return getSymbol(fsObj->getCategory()); - case COL_TYPE_SYNC_ACTION: - return getSymbol(fsObj->getSyncOperation()); - } - return wxString(); - } - - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override - { - const FileSystemObject* fsObj = getRawData(row); - GridData::drawCellBackground(dc, rect, enabled, selected, highlightSyncAction_ ? - getBackGroundColorSyncAction(fsObj) : - getBackGroundColorCmpCategory(fsObj)); - } - - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool selected) override - { - auto drawInactiveColumBackground = [&](const FileSystemObject& fsObj) - { - if (fsObj.isActive()) - fillBackgroundDefaultColorAlternating(dc, rect, row % 2 == 0); - else - clearArea(dc, rect, COLOR_NOT_ACTIVE); - }; - - switch (static_cast<ColumnTypeMiddle>(colType)) - { - case COL_TYPE_CHECKBOX: - if (const FileSystemObject* fsObj = getRawData(row)) - { - wxRect rectInside = rect; - - //if sync action is shown draw notch on left side, right side otherwise - if (notch.GetHeight() != rectInside.GetHeight()) - notch.Rescale(notch.GetWidth(), rectInside.GetHeight()); - if (highlightSyncAction_) - { - drawBitmapRtlMirror(dc, notch, rectInside, wxALIGN_LEFT, buffer); - rectInside.x += notch.GetWidth(); - rectInside.width -= notch.GetWidth(); - } - else - { - //wxWidgets screws up again and has wxALIGN_RIGHT off by one pixel! -> use wxALIGN_LEFT instead - wxRect rectNotch(rectInside.x + rectInside.width - notch.GetWidth(), rectInside.y, - notch.GetWidth(), rectInside.height); - drawBitmapRtlMirror(dc, notch, rectNotch, wxALIGN_LEFT, buffer); - rectInside.width -= notch.GetWidth(); - } - - const bool rowHighlighted = dragSelection ? row == dragSelection->first : highlight ? row == highlight->row_ : false; - const BlockPosition highlightBlock = dragSelection ? dragSelection->second : highlight ? highlight->blockPos_ : BLOCKPOS_CHECK_BOX; - - if (rowHighlighted && highlightBlock == BLOCKPOS_CHECK_BOX) - drawBitmapRtlMirror(dc, getResourceImage(fsObj->isActive() ? L"checkboxTrueFocus" : L"checkboxFalseFocus"), rectInside, wxALIGN_CENTER, buffer); - else //default - drawBitmapRtlMirror(dc, getResourceImage(fsObj->isActive() ? L"checkboxTrue" : L"checkboxFalse" ), rectInside, wxALIGN_CENTER, buffer); - } - break; - - case COL_TYPE_CMP_CATEGORY: - if (const FileSystemObject* fsObj = getRawData(row)) - { - if (highlightSyncAction_) - drawInactiveColumBackground(*fsObj); - - if (!highlightSyncAction_) - drawBitmapRtlMirror(dc, getCmpResultImage(fsObj->getCategory()), rect, wxALIGN_CENTER, buffer); - else if (fsObj->getCategory() != FILE_EQUAL) //don't show = in both middle columns - drawBitmapRtlMirror(dc, greyScale(getCmpResultImage(fsObj->getCategory())), rect, wxALIGN_CENTER, buffer); - } - break; - - case COL_TYPE_SYNC_ACTION: - if (const FileSystemObject* fsObj = getRawData(row)) - { - if (!highlightSyncAction_) - drawInactiveColumBackground(*fsObj); - - const bool rowHighlighted = dragSelection ? row == dragSelection->first : highlight ? row == highlight->row_ : false; - const BlockPosition highlightBlock = dragSelection ? dragSelection->second : highlight ? highlight->blockPos_ : BLOCKPOS_CHECK_BOX; - - //synchronization preview - if (rowHighlighted && highlightBlock != BLOCKPOS_CHECK_BOX) - switch (highlightBlock) - { - case BLOCKPOS_CHECK_BOX: - break; - case BLOCKPOS_LEFT: - drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SyncDirection::LEFT)), rect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, buffer); - break; - case BLOCKPOS_MIDDLE: - drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SyncDirection::NONE)), rect, wxALIGN_CENTER, buffer); - break; - case BLOCKPOS_RIGHT: - drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SyncDirection::RIGHT)), rect, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, buffer); - break; - } - else //default - { - if (highlightSyncAction_) - drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->getSyncOperation()), rect, wxALIGN_CENTER, buffer); - else if (fsObj->getSyncOperation() != SO_EQUAL) //don't show = in both middle columns - drawBitmapRtlMirror(dc, greyScale(getSyncOpImage(fsObj->getSyncOperation())), rect, wxALIGN_CENTER, buffer); - } - } - break; - } - } - - virtual wxString getColumnLabel(ColumnType colType) const override - { - switch (static_cast<ColumnTypeMiddle>(colType)) - { - case COL_TYPE_CHECKBOX: - break; - case COL_TYPE_CMP_CATEGORY: - return _("Category") + L" (F9)"; - case COL_TYPE_SYNC_ACTION: - return _("Action") + L" (F9)"; - } - return wxEmptyString; - } - - virtual wxString getToolTip(ColumnType colType) const override { return getColumnLabel(colType); } - - virtual void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override - { - switch (static_cast<ColumnTypeMiddle>(colType)) - { - case COL_TYPE_CHECKBOX: - drawColumnLabelBackground(dc, rect, false); - break; - - case COL_TYPE_CMP_CATEGORY: - { - wxRect rectInside = drawColumnLabelBorder(dc, rect); - drawColumnLabelBackground(dc, rectInside, highlighted); - - const wxBitmap& cmpIcon = getResourceImage(L"compare_small"); - drawBitmapRtlNoMirror(dc, highlightSyncAction_ ? greyScale(cmpIcon) : cmpIcon, rectInside, wxALIGN_CENTER, buffer); - } - break; - - case COL_TYPE_SYNC_ACTION: - { - wxRect rectInside = drawColumnLabelBorder(dc, rect); - drawColumnLabelBackground(dc, rectInside, highlighted); - - const wxBitmap& syncIcon = getResourceImage(L"sync_small"); - drawBitmapRtlNoMirror(dc, highlightSyncAction_ ? syncIcon : greyScale(syncIcon), rectInside, wxALIGN_CENTER, buffer); - } - break; - } - } - - static wxColor getBackGroundColorSyncAction(const FileSystemObject* fsObj) - { - if (fsObj) - { - if (!fsObj->isActive()) - return COLOR_NOT_ACTIVE; - - switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_DO_NOTHING: - return COLOR_NOT_ACTIVE; - case SO_EQUAL: - break; //usually white - - case SO_CREATE_NEW_LEFT: - case SO_OVERWRITE_LEFT: - case SO_DELETE_LEFT: - case SO_MOVE_LEFT_SOURCE: - case SO_MOVE_LEFT_TARGET: - case SO_COPY_METADATA_TO_LEFT: - return COLOR_SYNC_BLUE; - - case SO_CREATE_NEW_RIGHT: - case SO_OVERWRITE_RIGHT: - case SO_DELETE_RIGHT: - case SO_MOVE_RIGHT_SOURCE: - case SO_MOVE_RIGHT_TARGET: - case SO_COPY_METADATA_TO_RIGHT: - return COLOR_SYNC_GREEN; - - case SO_UNRESOLVED_CONFLICT: - return COLOR_YELLOW; - } - } - return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - } - - static wxColor getBackGroundColorCmpCategory(const FileSystemObject* fsObj) - { - if (fsObj) - { - if (!fsObj->isActive()) - return COLOR_NOT_ACTIVE; - - switch (fsObj->getCategory()) - { - case FILE_LEFT_SIDE_ONLY: - case FILE_LEFT_NEWER: - return COLOR_SYNC_BLUE; //COLOR_CMP_BLUE; - - case FILE_RIGHT_SIDE_ONLY: - case FILE_RIGHT_NEWER: - return COLOR_SYNC_GREEN; //COLOR_CMP_GREEN; - - case FILE_DIFFERENT: - return COLOR_CMP_RED; - case FILE_EQUAL: - break; //usually white - case FILE_CONFLICT: - case FILE_DIFFERENT_METADATA: //= sub-category of equal, but hint via background that sync direction follows conflict-setting - return COLOR_YELLOW; - //return COLOR_YELLOW_LIGHT; - } - } - return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - } - - enum BlockPosition //each cell can be divided into four blocks concerning mouse selections - { - BLOCKPOS_CHECK_BOX, - BLOCKPOS_LEFT, - BLOCKPOS_MIDDLE, - BLOCKPOS_RIGHT - }; - - //determine block position within cell - BlockPosition mousePosToBlock(const wxPoint& clientPos, size_t row, ColumnTypeMiddle colType) const - { - switch (static_cast<ColumnTypeMiddle>(colType)) - { - case COL_TYPE_CHECKBOX: - case COL_TYPE_CMP_CATEGORY: - break; - - case COL_TYPE_SYNC_ACTION: - { - const int absX = refGrid().CalcUnscrolledPosition(clientPos).x; - - const wxRect rect = refGrid().getCellArea(row, static_cast<ColumnType>(COL_TYPE_SYNC_ACTION)); //returns empty rect if column not found; absolute coordinates! - if (rect.width > 0 && rect.height > 0) - if (const FileSystemObject* const fsObj = getRawData(row)) - if (fsObj->getSyncOperation() != SO_EQUAL) //in sync-preview equal files shall be treated like a checkbox - // cell: - // ----------------------- - // | left | middle | right| - // ----------------------- - if (rect.GetX() <= absX) - { - if (absX < rect.GetX() + rect.GetWidth() / 3) - return BLOCKPOS_LEFT; - else if (absX < rect.GetX() + 2 * rect.GetWidth() / 3) - return BLOCKPOS_MIDDLE; - else if (absX < rect.GetX() + rect.GetWidth()) - return BLOCKPOS_RIGHT; - } - } - break; - } - return BLOCKPOS_CHECK_BOX; - } - - void showToolTip(size_t row, ColumnTypeMiddle colType, wxPoint posScreen) - { - if (const FileSystemObject* fsObj = getRawData(row)) - { - bool showTooltipSyncAction = true; - switch (colType) - { - case COL_TYPE_CHECKBOX: - showTooltipSyncAction = highlightSyncAction_; - break; - case COL_TYPE_CMP_CATEGORY: - showTooltipSyncAction = false; - break; - case COL_TYPE_SYNC_ACTION: - break; - } - - if (showTooltipSyncAction) //synchronization preview - { - const wchar_t* imageName = [&]() -> const wchar_t* - { - const SyncOperation syncOp = fsObj->getSyncOperation(); - switch (syncOp) - { - case SO_CREATE_NEW_LEFT: - return L"so_create_left"; - case SO_CREATE_NEW_RIGHT: - return L"so_create_right"; - case SO_DELETE_LEFT: - return L"so_delete_left"; - case SO_DELETE_RIGHT: - return L"so_delete_right"; - case SO_MOVE_LEFT_SOURCE: - return L"so_move_left_source"; - case SO_MOVE_LEFT_TARGET: - return L"so_move_left_target"; - case SO_MOVE_RIGHT_SOURCE: - return L"so_move_right_source"; - case SO_MOVE_RIGHT_TARGET: - return L"so_move_right_target"; - case SO_OVERWRITE_LEFT: - return L"so_update_left"; - case SO_OVERWRITE_RIGHT: - return L"so_update_right"; - case SO_COPY_METADATA_TO_LEFT: - return L"so_move_left"; - case SO_COPY_METADATA_TO_RIGHT: - return L"so_move_right"; - case SO_DO_NOTHING: - return L"so_none"; - case SO_EQUAL: - return L"cat_equal"; - case SO_UNRESOLVED_CONFLICT: - return L"cat_conflict"; - }; - assert(false); - return L""; - }(); - const auto& img = mirrorIfRtl(getResourceImage(imageName)); - toolTip.show(getSyncOpDescription(*fsObj), posScreen, &img); - } - else - { - const wchar_t* imageName = [&]() -> const wchar_t* - { - const CompareFilesResult cmpRes = fsObj->getCategory(); - switch (cmpRes) - { - case FILE_LEFT_SIDE_ONLY: - return L"cat_left_only"; - case FILE_RIGHT_SIDE_ONLY: - return L"cat_right_only"; - case FILE_LEFT_NEWER: - return L"cat_left_newer"; - case FILE_RIGHT_NEWER: - return L"cat_right_newer"; - case FILE_DIFFERENT: - return L"cat_different"; - case FILE_EQUAL: - case FILE_DIFFERENT_METADATA: //= sub-category of equal - return L"cat_equal"; - case FILE_CONFLICT: - return L"cat_conflict"; - } - assert(false); - return L""; - }(); - const auto& img = mirrorIfRtl(getResourceImage(imageName)); - toolTip.show(getCategoryDescription(*fsObj), posScreen, &img); - } - } - else - toolTip.hide(); //if invalid row... - } - - bool highlightSyncAction_; - - struct MouseHighlight - { - MouseHighlight(size_t row, BlockPosition blockPos) : row_(row), blockPos_(blockPos) {} - const size_t row_; - const BlockPosition blockPos_; - }; - std::unique_ptr<MouseHighlight> highlight; //current mouse highlight - std::unique_ptr<std::pair<size_t, BlockPosition>> dragSelection; //(row, block); area clicked when beginning selection - std::unique_ptr<wxBitmap> buffer; //avoid costs of recreating this temporal variable - Tooltip toolTip; - wxImage notch; -}; - -//######################################################################################################## - -const wxEventType EVENT_ALIGN_SCROLLBARS = wxNewEventType(); - -class GridEventManager : private wxEvtHandler -{ -public: - GridEventManager(Grid& gridL, - Grid& gridC, - Grid& gridR, - GridDataMiddle& provMiddle) : - gridL_(gridL), gridC_(gridC), gridR_(gridR), scrollMaster(nullptr), - provMiddle_(provMiddle), - scrollbarUpdatePending(false) - { - gridL_.Connect(EVENT_GRID_COL_RESIZE, GridColumnResizeEventHandler(GridEventManager::onResizeColumnL), nullptr, this); - gridR_.Connect(EVENT_GRID_COL_RESIZE, GridColumnResizeEventHandler(GridEventManager::onResizeColumnR), nullptr, this); - - gridL_.getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (GridEventManager::onKeyDownL), nullptr, this); - gridC_.getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (GridEventManager::onKeyDownC), nullptr, this); - gridR_.getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (GridEventManager::onKeyDownR), nullptr, this); - - gridC_.getMainWin().Connect(wxEVT_MOTION, wxMouseEventHandler(GridEventManager::onCenterMouseMovement), nullptr, this); - gridC_.getMainWin().Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(GridEventManager::onCenterMouseLeave ), nullptr, this); - - gridC_.Connect(EVENT_GRID_MOUSE_LEFT_DOWN, GridClickEventHandler (GridEventManager::onCenterSelectBegin), nullptr, this); - gridC_.Connect(EVENT_GRID_SELECT_RANGE, GridRangeSelectEventHandler(GridEventManager::onCenterSelectEnd ), nullptr, this); - - //clear selection of other grid when selecting on - gridL_.Connect(EVENT_GRID_SELECT_RANGE, GridRangeSelectEventHandler(GridEventManager::onGridSelectionL), nullptr, this); - gridR_.Connect(EVENT_GRID_SELECT_RANGE, GridRangeSelectEventHandler(GridEventManager::onGridSelectionR), nullptr, this); - - //parallel grid scrolling: do NOT use DoPrepareDC() to align grids! GDI resource leak! Use regular paint event instead: - gridL_.getMainWin().Connect(wxEVT_PAINT, wxEventHandler(GridEventManager::onPaintGridL), nullptr, this); - gridC_.getMainWin().Connect(wxEVT_PAINT, wxEventHandler(GridEventManager::onPaintGridC), nullptr, this); - gridR_.getMainWin().Connect(wxEVT_PAINT, wxEventHandler(GridEventManager::onPaintGridR), nullptr, this); - - auto connectGridAccess = [&](Grid& grid, wxObjectEventFunction func) - { - grid.Connect(wxEVT_SCROLLWIN_TOP, func, nullptr, this); - grid.Connect(wxEVT_SCROLLWIN_BOTTOM, func, nullptr, this); - grid.Connect(wxEVT_SCROLLWIN_LINEUP, func, nullptr, this); - grid.Connect(wxEVT_SCROLLWIN_LINEDOWN, func, nullptr, this); - grid.Connect(wxEVT_SCROLLWIN_PAGEUP, func, nullptr, this); - grid.Connect(wxEVT_SCROLLWIN_PAGEDOWN, func, nullptr, this); - grid.Connect(wxEVT_SCROLLWIN_THUMBTRACK, func, nullptr, this); - //wxEVT_KILL_FOCUS -> there's no need to reset "scrollMaster" - //wxEVT_SET_FOCUS -> not good enough: - //e.g.: left grid has input, right grid is "scrollMaster" due to dragging scroll thumb via mouse. - //=> Next keyboard input on left does *not* emit focus change event, but still "scrollMaster" needs to change - //=> hook keyboard input instead of focus event: - grid.getMainWin().Connect(wxEVT_CHAR, func, nullptr, this); - grid.getMainWin().Connect(wxEVT_KEY_UP, func, nullptr, this); - grid.getMainWin().Connect(wxEVT_KEY_DOWN, func, nullptr, this); - }; - connectGridAccess(gridL_, wxEventHandler(GridEventManager::onGridAccessL)); // - connectGridAccess(gridC_, wxEventHandler(GridEventManager::onGridAccessC)); //connect *after* onKeyDown() in order to receive callback *before*!!! - connectGridAccess(gridR_, wxEventHandler(GridEventManager::onGridAccessR)); // - - Connect(EVENT_ALIGN_SCROLLBARS, wxEventHandler(GridEventManager::onAlignScrollBars), NULL, this); - } - - ~GridEventManager() { assert(!scrollbarUpdatePending); } - - void setScrollMaster(const Grid& grid) { scrollMaster = &grid; } - -private: - void onCenterSelectBegin(GridClickEvent& event) - { - - provMiddle_.onSelectBegin(event.GetPosition(), event.row_, event.colType_); - event.Skip(); - } - - void onCenterSelectEnd(GridRangeSelectEvent& event) - { - provMiddle_.onSelectEnd(event.rowFirst_, event.rowLast_); - event.Skip(); - } - - void onCenterMouseMovement(wxMouseEvent& event) - { - provMiddle_.onMouseMovement(event.GetPosition()); - event.Skip(); - } - - void onCenterMouseLeave(wxMouseEvent& event) - { - provMiddle_.onMouseLeave(); - event.Skip(); - } - - void onGridSelectionL(GridRangeSelectEvent& event) { onGridSelection(gridL_, gridR_); event.Skip(); } - void onGridSelectionR(GridRangeSelectEvent& event) { onGridSelection(gridR_, gridL_); event.Skip(); } - - void onGridSelection(const Grid& grid, Grid& other) - { - if (!wxGetKeyState(WXK_CONTROL)) //clear other grid unless user is holding CTRL - other.clearSelection(false); //don't emit event, prevent recursion! - } - - void onKeyDownL(wxKeyEvent& event) { onKeyDown(event, gridL_); } - void onKeyDownC(wxKeyEvent& event) { onKeyDown(event, gridC_); } - void onKeyDownR(wxKeyEvent& event) { onKeyDown(event, gridR_); } - - void onKeyDown(wxKeyEvent& event, const Grid& grid) - { - int keyCode = event.GetKeyCode(); - if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) - { - if (keyCode == WXK_LEFT) - keyCode = WXK_RIGHT; - else if (keyCode == WXK_RIGHT) - keyCode = WXK_LEFT; - else if (keyCode == WXK_NUMPAD_LEFT) - keyCode = WXK_NUMPAD_RIGHT; - else if (keyCode == WXK_NUMPAD_RIGHT) - keyCode = WXK_NUMPAD_LEFT; - } - - //skip middle component when navigating via keyboard - - const auto row = grid.getGridCursor().first; - - if (event.ShiftDown()) - ; - else if (event.ControlDown()) - ; - else - switch (keyCode) - { - case WXK_LEFT: - case WXK_NUMPAD_LEFT: - gridL_.setGridCursor(row); - gridL_.SetFocus(); - //since key event is likely originating from right grid, we need to set scrollMaster manually! - scrollMaster = &gridL_; //onKeyDown is called *after* onGridAccessL()! - return; //swallow event - - case WXK_RIGHT: - case WXK_NUMPAD_RIGHT: - gridR_.setGridCursor(row); - gridR_.SetFocus(); - scrollMaster = &gridR_; - return; //swallow event - } - - event.Skip(); - } - - void onResizeColumnL(GridColumnResizeEvent& event) { resizeOtherSide(gridL_, gridR_, event.colType_, event.offset_); } - void onResizeColumnR(GridColumnResizeEvent& event) { resizeOtherSide(gridR_, gridL_, event.colType_, event.offset_); } - - void resizeOtherSide(const Grid& src, Grid& trg, ColumnType type, int offset) - { - //find stretch factor of resized column: type is unique due to makeConsistent()! - std::vector<Grid::ColumnAttribute> cfgSrc = src.getColumnConfig(); - auto it = std::find_if(cfgSrc.begin(), cfgSrc.end(), [&](Grid::ColumnAttribute& ca) { return ca.type_ == type; }); - if (it == cfgSrc.end()) - return; - const int stretchSrc = it->stretch_; - - //we do not propagate resizings on stretched columns to the other side: awkward user experience - if (stretchSrc > 0) - return; - - //apply resized offset to other side, but only if stretch factors match! - std::vector<Grid::ColumnAttribute> cfgTrg = trg.getColumnConfig(); - std::for_each(cfgTrg.begin(), cfgTrg.end(), [&](Grid::ColumnAttribute& ca) - { - if (ca.type_ == type && ca.stretch_ == stretchSrc) - ca.offset_ = offset; - }); - trg.setColumnConfig(cfgTrg); - } - - void onGridAccessL(wxEvent& event) { scrollMaster = &gridL_; event.Skip(); } - void onGridAccessC(wxEvent& event) { scrollMaster = &gridC_; event.Skip(); } - void onGridAccessR(wxEvent& event) { scrollMaster = &gridR_; event.Skip(); } - - void onPaintGridL(wxEvent& event) { onPaintGrid(gridL_); event.Skip(); } - void onPaintGridC(wxEvent& event) { onPaintGrid(gridC_); event.Skip(); } - void onPaintGridR(wxEvent& event) { onPaintGrid(gridR_); event.Skip(); } - - void onPaintGrid(const Grid& grid) - { - //align scroll positions of all three grids *synchronously* during paint event! (wxGTK has visible delay when this is done asynchronously, no delay on Windows) - - //determine lead grid - const Grid* lead = nullptr; - Grid* follow1 = nullptr; - Grid* follow2 = nullptr; - auto setGrids = [&](const Grid& l, Grid& f1, Grid& f2) { lead = &l; follow1 = &f1; follow2 = &f2; }; - - if (&gridC_ == scrollMaster) - setGrids(gridC_, gridL_, gridR_); - else if (&gridR_ == scrollMaster) - setGrids(gridR_, gridL_, gridC_); - else //default: left panel - setGrids(gridL_, gridC_, gridR_); - - //align other grids only while repainting the lead grid to avoid scrolling and updating a grid at the same time! - if (lead != &grid) return; - - auto scroll = [](Grid& target, int y) //support polling - { - //scroll vertically only - scrolling horizontally becomes annoying if left and right sides have different widths; - //e.g. h-scroll on left would be undone when scrolling vertically on right which doesn't have a h-scrollbar - int yOld = 0; - target.GetViewStart(nullptr, &yOld); - if (yOld != y) - target.Scroll(-1, y); //empirical test Windows/Ubuntu: this call does NOT trigger a wxEVT_SCROLLWIN event, which would incorrectly set "scrollMaster" to "&target"! - }; - int y = 0; - lead->GetViewStart(nullptr, &y); - scroll(*follow1, y); - scroll(*follow2, y); - - //harmonize placement of horizontal scrollbar to avoid grids getting out of sync! - //since this affects the grid that is currently repainted as well, we do work asynchronously! - //avoids at least this problem: remaining graphics artifact when changing from Grid::SB_SHOW_ALWAYS to Grid::SB_SHOW_NEVER at location of old scrollbar (Windows only) - - //perf note: send one async event at most, else they may accumulate and create perf issues, see grid.cpp - if (!scrollbarUpdatePending) - { - scrollbarUpdatePending = true; - wxCommandEvent alignEvent(EVENT_ALIGN_SCROLLBARS); - AddPendingEvent(alignEvent); //waits until next idle event - may take up to a second if the app is busy on wxGTK! - } - } - - void onAlignScrollBars(wxEvent& event) - { - ZEN_ON_SCOPE_EXIT(scrollbarUpdatePending = false); - assert(scrollbarUpdatePending); - - auto needsHorizontalScrollbars = [](const Grid& grid) -> bool - { - const wxWindow& mainWin = grid.getMainWin(); - return mainWin.GetVirtualSize().GetWidth() > mainWin.GetClientSize().GetWidth(); - //assuming Grid::updateWindowSizes() does its job well, this should suffice! - //CAVEAT: if horizontal and vertical scrollbar are circular dependent from each other - //(h-scrollbar is shown due to v-scrollbar consuming horizontal width, ect...) - //while in fact both are NOT needed, this special case results in a bogus need for scrollbars! - //see https://sourceforge.net/tracker/?func=detail&aid=3514183&group_id=234430&atid=1093083 - // => since we're outside the Grid abstraction, we should not duplicate code to handle this special case as it seems to be insignificant - }; - - Grid::ScrollBarStatus sbStatusX = needsHorizontalScrollbars(gridL_) || - needsHorizontalScrollbars(gridR_) ? - Grid::SB_SHOW_ALWAYS : Grid::SB_SHOW_NEVER; - gridL_.showScrollBars(sbStatusX, Grid::SB_SHOW_NEVER); - gridC_.showScrollBars(sbStatusX, Grid::SB_SHOW_NEVER); - gridR_.showScrollBars(sbStatusX, Grid::SB_SHOW_AUTOMATIC); - } - - Grid& gridL_; - Grid& gridC_; - Grid& gridR_; - - const Grid* scrollMaster; //for address check only; this needn't be the grid having focus! - //e.g. mouse wheel events should set window under cursor as scrollMaster, but *not* change focus - - GridDataMiddle& provMiddle_; - bool scrollbarUpdatePending; -}; -} - -//######################################################################################################## - -void gridview::init(Grid& gridLeft, Grid& gridCenter, Grid& gridRight, const std::shared_ptr<const zen::GridView>& gridDataView) -{ - auto provLeft_ = std::make_shared<GridDataLeft >(gridDataView, gridLeft); - auto provMiddle_ = std::make_shared<GridDataMiddle>(gridDataView, gridCenter); - auto provRight_ = std::make_shared<GridDataRight >(gridDataView, gridRight); - - gridLeft .setDataProvider(provLeft_); //data providers reference grid => - gridCenter.setDataProvider(provMiddle_); //ownership must belong *exclusively* to grid! - gridRight .setDataProvider(provRight_); - - auto evtMgr = std::make_shared<GridEventManager>(gridLeft, gridCenter, gridRight, *provMiddle_); - provLeft_ ->holdOwnership(evtMgr); - provMiddle_->holdOwnership(evtMgr); - provRight_ ->holdOwnership(evtMgr); - - gridCenter.enableColumnMove (false); - gridCenter.enableColumnResize(false); - - gridCenter.showRowLabel(false); - gridRight .showRowLabel(false); - - //gridLeft .showScrollBars(Grid::SB_SHOW_AUTOMATIC, Grid::SB_SHOW_NEVER); -> redundant: configuration happens in GridEventManager::onAlignScrollBars() - //gridCenter.showScrollBars(Grid::SB_SHOW_NEVER, Grid::SB_SHOW_NEVER); - - const int widthCategory = 30; - const int widthCheckbox = getResourceImage(L"checkboxTrue").GetWidth() + 4 + getResourceImage(L"notch").GetWidth(); - const int widthAction = 45; - gridCenter.SetSize(widthCategory + widthCheckbox + widthAction, -1); - - std::vector<Grid::ColumnAttribute> attribMiddle; - attribMiddle.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_CMP_CATEGORY), widthCategory, 0, true)); - attribMiddle.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_CHECKBOX ), widthCheckbox, 0, true)); - attribMiddle.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_SYNC_ACTION ), widthAction, 0, true)); - gridCenter.setColumnConfig(attribMiddle); -} - - -namespace -{ -std::vector<ColumnAttributeRim> makeConsistent(const std::vector<ColumnAttributeRim>& attribs) -{ - std::set<ColumnTypeRim> usedTypes; - - std::vector<ColumnAttributeRim> output; - //remove duplicates: required by GridEventManager::resizeOtherSide() to find corresponding column on other side - std::copy_if(attribs.begin(), attribs.end(), std::back_inserter(output), - [&](const ColumnAttributeRim& a) { return usedTypes.insert(a.type_).second; }); - - //make sure each type is existing! -> should *only* be a problem if user manually messes with globalsettings.xml - const auto& defAttr = getDefaultColumnAttributesLeft(); - std::copy_if(defAttr.begin(), defAttr.end(), std::back_inserter(output), - [&](const ColumnAttributeRim& a) { return usedTypes.insert(a.type_).second; }); - - return output; -} -} - -std::vector<Grid::ColumnAttribute> gridview::convertConfig(const std::vector<ColumnAttributeRim>& attribs) -{ - const auto& attribClean = makeConsistent(attribs); - - std::vector<Grid::ColumnAttribute> output; - std::transform(attribClean.begin(), attribClean.end(), std::back_inserter(output), - [&](const ColumnAttributeRim& ca) { return Grid::ColumnAttribute(static_cast<ColumnType>(ca.type_), ca.offset_, ca.stretch_, ca.visible_); }); - - return output; -} - - -std::vector<ColumnAttributeRim> gridview::convertConfig(const std::vector<Grid::ColumnAttribute>& attribs) -{ - std::vector<ColumnAttributeRim> output; - - std::transform(attribs.begin(), attribs.end(), std::back_inserter(output), - [&](const Grid::ColumnAttribute& ca) { return ColumnAttributeRim(static_cast<ColumnTypeRim>(ca.type_), ca.offset_, ca.stretch_, ca.visible_); }); - - return makeConsistent(output); -} - - -namespace -{ -class IconUpdater : private wxEvtHandler //update file icons periodically: use SINGLE instance to coordinate left and right grid in parallel -{ -public: - IconUpdater(GridDataLeft& provLeft, GridDataRight& provRight, IconBuffer& iconBuffer) : provLeft_(provLeft), provRight_(provRight), iconBuffer_(iconBuffer) - { - timer.Connect(wxEVT_TIMER, wxEventHandler(IconUpdater::loadIconsAsynchronously), nullptr, this); - } - - void start() { if (!timer.IsRunning()) timer.Start(50); } //timer interval in [ms] - -private: - void stop() { if ( timer.IsRunning()) timer.Stop(); } - - void loadIconsAsynchronously(wxEvent& event) //loads all (not yet) drawn icons - { - std::list<Zstring> newLoad; - provLeft_ .updateNewAndGetMissingIcons(newLoad); - provRight_.updateNewAndGetMissingIcons(newLoad); - iconBuffer_.setWorkload(newLoad); - - if (newLoad.empty()) //let's only pay for iconupdater when needed - stop(); - } - - GridDataLeft& provLeft_; - GridDataRight& provRight_; - IconBuffer& iconBuffer_; - wxTimer timer; -}; - - -//resolve circular linker dependencies -inline -void IconManager::startIconUpdater() { if (iconUpdater) iconUpdater->start(); } -} - - -void gridview::setupIcons(Grid& gridLeft, Grid& gridCenter, Grid& gridRight, bool show, IconBuffer::IconSize sz) -{ - auto* provLeft = dynamic_cast<GridDataLeft*>(gridLeft .getDataProvider()); - auto* provRight = dynamic_cast<GridDataRight*>(gridRight.getDataProvider()); - - if (provLeft && provRight) - { - int iconHeight = 0; - if (show) - { - auto iconMgr = std::make_shared<IconManager>(*provLeft, *provRight, sz); - provLeft ->setIconManager(iconMgr); - provRight->setIconManager(iconMgr); - iconHeight = iconMgr->refIconBuffer().getSize(); - } - else - { - provLeft ->setIconManager(nullptr); - provRight->setIconManager(nullptr); - iconHeight = IconBuffer::getSize(IconBuffer::SIZE_SMALL); - } - - const int newRowHeight = std::max(iconHeight, gridLeft.getMainWin().GetCharHeight()) + 1; //add some space - - gridLeft .setRowHeight(newRowHeight); - gridCenter.setRowHeight(newRowHeight); - gridRight .setRowHeight(newRowHeight); - } - else - assert(false); -} - - -void gridview::clearSelection(Grid& gridLeft, Grid& gridCenter, Grid& gridRight) -{ - gridLeft .clearSelection(); - gridCenter.clearSelection(); - gridRight .clearSelection(); -} - -void gridview::refresh(Grid& gridLeft, Grid& gridCenter, Grid& gridRight) -{ - gridLeft .Refresh(); - gridCenter.Refresh(); - gridRight .Refresh(); -} - - -void gridview::setScrollMaster(Grid& grid) -{ - if (auto prov = dynamic_cast<GridDataBase*>(grid.getDataProvider())) - if (auto evtMgr = prov->getEventManager()) - { - evtMgr->setScrollMaster(grid); - return; - } - assert(false); -} - - -void gridview::setNavigationMarker(Grid& gridLeft, - hash_set<const FileSystemObject*>&& markedFilesAndLinks, - hash_set<const HierarchyObject*>&& markedContainer) -{ - if (auto provLeft = dynamic_cast<GridDataLeft*>(gridLeft.getDataProvider())) - provLeft->setNavigationMarker(std::move(markedFilesAndLinks), std::move(markedContainer)); - else - assert(false); - gridLeft.Refresh(); -} - - -void gridview::highlightSyncAction(Grid& gridCenter, bool value) -{ - if (auto provMiddle = dynamic_cast<GridDataMiddle*>(gridCenter.getDataProvider())) - provMiddle->highlightSyncAction(value); - else - assert(false); -} - -wxBitmap zen::getSyncOpImage(SyncOperation syncOp) -{ - switch (syncOp) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - return getResourceImage(L"so_create_left_small"); - case SO_CREATE_NEW_RIGHT: - return getResourceImage(L"so_create_right_small"); - case SO_DELETE_LEFT: - return getResourceImage(L"so_delete_left_small"); - case SO_DELETE_RIGHT: - return getResourceImage(L"so_delete_right_small"); - case SO_MOVE_LEFT_SOURCE: - return getResourceImage(L"so_move_left_source_small"); - case SO_MOVE_LEFT_TARGET: - return getResourceImage(L"so_move_left_target_small"); - case SO_MOVE_RIGHT_SOURCE: - return getResourceImage(L"so_move_right_source_small"); - case SO_MOVE_RIGHT_TARGET: - return getResourceImage(L"so_move_right_target_small"); - case SO_OVERWRITE_LEFT: - return getResourceImage(L"so_update_left_small"); - case SO_OVERWRITE_RIGHT: - return getResourceImage(L"so_update_right_small"); - case SO_COPY_METADATA_TO_LEFT: - return getResourceImage(L"so_move_left_small"); - case SO_COPY_METADATA_TO_RIGHT: - return getResourceImage(L"so_move_right_small"); - case SO_DO_NOTHING: - return getResourceImage(L"so_none_small"); - case SO_EQUAL: - return getResourceImage(L"cat_equal_small"); - case SO_UNRESOLVED_CONFLICT: - return getResourceImage(L"cat_conflict_small"); - } - return wxNullBitmap; -} - - -wxBitmap zen::getCmpResultImage(CompareFilesResult cmpResult) -{ - switch (cmpResult) - { - case FILE_LEFT_SIDE_ONLY: - return getResourceImage(L"cat_left_only_small"); - case FILE_RIGHT_SIDE_ONLY: - return getResourceImage(L"cat_right_only_small"); - case FILE_LEFT_NEWER: - return getResourceImage(L"cat_left_newer_small"); - case FILE_RIGHT_NEWER: - return getResourceImage(L"cat_right_newer_small"); - case FILE_DIFFERENT: - return getResourceImage(L"cat_different_small"); - case FILE_EQUAL: - case FILE_DIFFERENT_METADATA: //= sub-category of equal - return getResourceImage(L"cat_equal_small"); - case FILE_CONFLICT: - return getResourceImage(L"cat_conflict_small"); - } - return wxNullBitmap; -} diff --git a/ui/custom_grid.h b/ui/custom_grid.h deleted file mode 100644 index 32beee01..00000000 --- a/ui/custom_grid.h +++ /dev/null @@ -1,82 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef CUSTOMGRID_H_INCLUDED -#define CUSTOMGRID_H_INCLUDED - -#include <wx+/grid.h> -#include "grid_view.h" -#include "column_attr.h" -#include "../lib/icon_buffer.h" - -namespace zen -{ -//setup grid to show grid view within three components: -namespace gridview -{ -void init(Grid& gridLeft, Grid& gridCenter, Grid& gridRight, const std::shared_ptr<const GridView>& gridDataView); - -std::vector<Grid::ColumnAttribute> convertConfig(const std::vector<ColumnAttributeRim>& attribs); //+ make consistent -std::vector<ColumnAttributeRim> convertConfig(const std::vector<Grid::ColumnAttribute>& attribs); // - -void highlightSyncAction(Grid& gridCenter, bool value); - -void setupIcons(Grid& gridLeft, Grid& gridCenter, Grid& gridRight, bool show, IconBuffer::IconSize sz); - -void clearSelection(Grid& gridLeft, Grid& gridCenter, Grid& gridRight); //clear all components -void refresh(Grid& gridLeft, Grid& gridCenter, Grid& gridRight); - -void setScrollMaster(Grid& grid); - -//mark rows selected in navigation/compressed tree and navigate to leading object -void setNavigationMarker(Grid& gridLeft, - hash_set<const FileSystemObject*>&& markedFilesAndLinks,//mark files/symlinks directly within a container - hash_set<const HierarchyObject*>&& markedContainer); //mark full container including child-objects -} - -wxBitmap getSyncOpImage(SyncOperation syncOp); -wxBitmap getCmpResultImage(CompareFilesResult cmpResult); - - -//---------- custom events for middle grid ---------- - -//(UN-)CHECKING ROWS FROM SYNCHRONIZATION -extern const wxEventType EVENT_GRID_CHECK_ROWS; -//SELECTING SYNC DIRECTION -extern const wxEventType EVENT_GRID_SYNC_DIRECTION; - -struct CheckRowsEvent : public wxCommandEvent -{ - CheckRowsEvent(size_t rowFirst, size_t rowLast, bool setIncluded) : wxCommandEvent(EVENT_GRID_CHECK_ROWS), rowFirst_(rowFirst), rowLast_(rowLast), setIncluded_(setIncluded) { assert(rowFirst <= rowLast); } - virtual wxEvent* Clone() const { return new CheckRowsEvent(*this); } - - const size_t rowFirst_; //selected range: [rowFirst_, rowLast_) - const size_t rowLast_; //range is empty when clearing selection - const bool setIncluded_; -}; - - -struct SyncDirectionEvent : public wxCommandEvent -{ - SyncDirectionEvent(size_t rowFirst, size_t rowLast, SyncDirection direction) : wxCommandEvent(EVENT_GRID_SYNC_DIRECTION), rowFirst_(rowFirst), rowLast_(rowLast), direction_(direction) { assert(rowFirst <= rowLast); } - virtual wxEvent* Clone() const { return new SyncDirectionEvent(*this); } - - const size_t rowFirst_; //see CheckRowsEvent - const size_t rowLast_; // - const SyncDirection direction_; -}; - -typedef void (wxEvtHandler::*CheckRowsEventFunction)(CheckRowsEvent&); -typedef void (wxEvtHandler::*SyncDirectionEventFunction)(SyncDirectionEvent&); - -#define CheckRowsEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(CheckRowsEventFunction, &func) - -#define SyncDirectionEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(SyncDirectionEventFunction, &func) -} - -#endif // CUSTOMGRID_H_INCLUDED diff --git a/ui/dir_name.cpp b/ui/dir_name.cpp deleted file mode 100644 index 022773e4..00000000 --- a/ui/dir_name.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "dir_name.h" -#include <zen/thread.h> -#include <zen/file_handling.h> -#include <wx/dnd.h> -#include <wx/window.h> -#include <wx/textctrl.h> -#include <wx/statbox.h> -#include <wx/dirdlg.h> -#include <wx/scrolwin.h> -#include <wx+/string_conv.h> -#include <wx+/popup_dlg.h> -#include "../lib/resolve_path.h" -#include "folder_history_box.h" - -#ifdef ZEN_WIN -#include <zen/dll.h> -#include <zen/win_ver.h> -#include "IFileDialog_Vista\ifile_dialog.h" -#endif - -using namespace zen; - - -const wxEventType zen::EVENT_ON_DIR_SELECTED = wxNewEventType(); -const wxEventType zen::EVENT_ON_DIR_MANUAL_CORRECTION = wxNewEventType(); - -namespace -{ -void setDirectoryNameImpl(const wxString& dirname, wxWindow& tooltipWnd, wxStaticText* staticText) -{ - const wxString dirFormatted = utfCvrtTo<wxString>(getFormattedDirectoryName(toZ(dirname))); //may block when resolving [<volume name>] - - tooltipWnd.SetToolTip(nullptr); //workaround wxComboBox bug http://trac.wxwidgets.org/ticket/10512 / http://trac.wxwidgets.org/ticket/12659 - tooltipWnd.SetToolTip(dirFormatted); //who knows when the real bugfix reaches mere mortals via an official release... - - if (staticText) - { - //change static box label only if there is a real difference to what is shown in wxTextCtrl anyway - wxString dirNormalized = dirname; - trim(dirNormalized); - if (!dirNormalized.empty()) - if (!endsWith(dirNormalized, FILE_NAME_SEPARATOR)) - dirNormalized += FILE_NAME_SEPARATOR; - - staticText->SetLabel(dirNormalized == dirFormatted ? wxString(_("Drag && drop")) : dirFormatted); - } -} - - -void setDirectoryName(const wxString& dirname, - wxTextCtrl* txtCtrl, - wxWindow& tooltipWnd, - wxStaticText* staticText) //pointers are optional -{ - if (txtCtrl) - txtCtrl->ChangeValue(dirname); - setDirectoryNameImpl(dirname, tooltipWnd, staticText); -} - - -void setDirectoryName(const wxString& dirname, - FolderHistoryBox* comboBox, - wxWindow& tooltipWnd, - wxStaticText* staticText) //pointers are optional -{ - if (comboBox) - comboBox->setValue(dirname); - setDirectoryNameImpl(dirname, tooltipWnd, staticText); -} -} -//############################################################################################################## - -template <class NameControl> -DirectoryName<NameControl>::DirectoryName(wxWindow& dropWindow, - wxButton& selectButton, - NameControl& dirName, - wxStaticText* staticText, - wxWindow* dropWindow2) : - dropWindow_(dropWindow), - dropWindow2_(dropWindow2), - selectButton_(selectButton), - dirName_(dirName), - staticText_(staticText) -{ - //prepare drag & drop - setupFileDrop(dropWindow_); - dropWindow_.Connect(EVENT_DROP_FILE, FileDropEventHandler(DirectoryName::onFilesDropped), nullptr, this); - - if (dropWindow2_) - { - setupFileDrop(*dropWindow2_); - dropWindow2_->Connect(EVENT_DROP_FILE, FileDropEventHandler(DirectoryName::onFilesDropped), nullptr, this); - } - - //keep dirPicker and dirName synchronous - dirName_ .Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (DirectoryName::onMouseWheel), nullptr, this); - dirName_ .Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(DirectoryName::onWriteDirManually), nullptr, this); - selectButton_.Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DirectoryName::onSelectDir ), nullptr, this); -} - - -template <class NameControl> -DirectoryName<NameControl>::~DirectoryName() -{ - dropWindow_.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(DirectoryName::onFilesDropped), nullptr, this); - if (dropWindow2_) - dropWindow2_->Disconnect(EVENT_DROP_FILE, FileDropEventHandler(DirectoryName::onFilesDropped), nullptr, this); - - dirName_ .Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (DirectoryName::onMouseWheel), nullptr, this); - dirName_ .Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(DirectoryName::onWriteDirManually), nullptr, this); - selectButton_.Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DirectoryName::onSelectDir ), nullptr, this); -} - - -template <class NameControl> -void DirectoryName<NameControl>::onMouseWheel(wxMouseEvent& event) -{ - //for combobox: although switching through available items is wxWidgets default, this is NOT windows default, e.g. explorer - //additionally this will delete manual entries, although all the users wanted is scroll the parent window! - - //redirect to parent scrolled window! - wxWindow* wnd = &dirName_; - while ((wnd = wnd->GetParent()) != nullptr) //silence MSVC warning - if (dynamic_cast<wxScrolledWindow*>(wnd) != nullptr) - if (wxEvtHandler* evtHandler = wnd->GetEventHandler()) - { - evtHandler->AddPendingEvent(event); - break; - } - - // event.Skip(); -} - - -template <class NameControl> -void DirectoryName<NameControl>::onFilesDropped(FileDropEvent& event) -{ - const auto& files = event.getFiles(); - if (files.empty()) - return; - - if (acceptDrop(files, event.getDropPosition(), event.getDropWindow())) - { - const wxString fileName = event.getFiles()[0]; - if (dirExists(toZ(fileName))) - setDirectoryName(fileName, &dirName_, dirName_, staticText_); - else - { - wxString parentName = beforeLast(fileName, utfCvrtTo<wxString>(FILE_NAME_SEPARATOR)); //returns empty string if ch not found -#ifdef ZEN_WIN - if (endsWith(parentName, L":")) //volume name - parentName += FILE_NAME_SEPARATOR; -#endif - if (dirExists(toZ(parentName))) - setDirectoryName(parentName, &dirName_, dirName_, staticText_); - else //set original name unconditionally: usecase: inactive mapped network shares - setDirectoryName(fileName, &dirName_, dirName_, staticText_); - } - - //notify action invoked by user - wxCommandEvent dummy(EVENT_ON_DIR_SELECTED); - ProcessEvent(dummy); - } - else - event.Skip(); //let other handlers try!!! -} - - -template <class NameControl> -void DirectoryName<NameControl>::onWriteDirManually(wxCommandEvent& event) -{ - setDirectoryName(event.GetString(), static_cast<NameControl*>(nullptr), dirName_, staticText_); - - wxCommandEvent dummy(EVENT_ON_DIR_MANUAL_CORRECTION); - ProcessEvent(dummy); - event.Skip(); -} - - -template <class NameControl> -void DirectoryName<NameControl>::onSelectDir(wxCommandEvent& event) -{ - wxString defaultDirname; //default selection for dir picker - { - const Zstring dirFmt = getFormattedDirectoryName(toZ(getName())); - if (!dirFmt.empty()) - { - //convert to Zstring first: we don't want to pass wxString by value and risk MT issues! - auto ft = async([=] { return zen::dirExists(dirFmt); }); - - if (ft.timed_wait(boost::posix_time::milliseconds(200)) && ft.get()) //potentially slow network access: wait 200ms at most - defaultDirname = utfCvrtTo<wxString>(dirFmt); - } - } - - //wxDirDialog internally uses lame-looking SHBrowseForFolder(); we better use IFileDialog() instead! (remembers size and position!) - std::unique_ptr<wxString> newFolder; -#ifdef ZEN_WIN - if (vistaOrLater()) - { - using namespace ifile; - const DllFun<FunType_showFolderPicker> showFolderPicker(getDllName(), funName_showFolderPicker); - const DllFun<FunType_freeString> freeString (getDllName(), funName_freeString); - if (showFolderPicker && freeString) - { - wchar_t* selectedFolder = nullptr; - wchar_t* errorMsg = nullptr; - bool cancelled = false; - ZEN_ON_SCOPE_EXIT(freeString(selectedFolder)); - ZEN_ON_SCOPE_EXIT(freeString(errorMsg)); - - const GuidProxy guid = { '\x0', '\x4a', '\xf9', '\x31', '\xb4', '\x92', '\x40', '\xa0', - '\x8d', '\xc2', '\xc', '\xa5', '\xef', '\x59', '\x6e', '\x3b' - }; //some random GUID => have Windows save IFileDialog state separately from other file/dir pickers! - - showFolderPicker(static_cast<HWND>(selectButton_.GetHWND()), //in; ==HWND - defaultDirname.empty() ? static_cast<const wchar_t*>(nullptr) : defaultDirname.c_str(), //in, optional! - &guid, - selectedFolder, //out: call freeString() after use! - cancelled, //out - errorMsg); //out, optional: call freeString() after use! - if (errorMsg) - { - showNotificationDialog(&dropWindow_, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(errorMsg)); - return; - } - if (cancelled || !selectedFolder) - return; - newFolder = make_unique<wxString>(selectedFolder); - } - } -#endif - if (!newFolder.get()) - { - wxDirDialog dirPicker(&selectButton_, _("Select a folder"), defaultDirname); //put modal wxWidgets dialogs on stack: creating on freestore leads to memleak! - if (dirPicker.ShowModal() != wxID_OK) - return; - newFolder = make_unique<wxString>(dirPicker.GetPath()); - } - - setDirectoryName(*newFolder, &dirName_, dirName_, staticText_); - - //notify action invoked by user - wxCommandEvent dummy(EVENT_ON_DIR_SELECTED); - ProcessEvent(dummy); -} - - -template <class NameControl> -wxString DirectoryName<NameControl>::getName() const -{ - return dirName_.GetValue(); -} - - -template <class NameControl> -void DirectoryName<NameControl>::setName(const wxString& dirname) -{ - setDirectoryName(dirname, &dirName_, dirName_, staticText_); -} - - -//explicit template instantiations -namespace zen -{ -template class DirectoryName<wxTextCtrl>; -template class DirectoryName<FolderHistoryBox>; -} diff --git a/ui/dir_name.h b/ui/dir_name.h deleted file mode 100644 index 21f2b574..00000000 --- a/ui/dir_name.h +++ /dev/null @@ -1,64 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef DRAGANDDROP_H_INCLUDED -#define DRAGANDDROP_H_INCLUDED - -#include <vector> -#include <wx/event.h> -#include <wx/sizer.h> -#include <wx+/file_drop.h> -#include <wx/stattext.h> -#include <wx/button.h> - -namespace zen -{ -//handle drag and drop, tooltip, label and manual input, coordinating a wxWindow, wxButton, and wxComboBox/wxTextCtrl -/* -Reasons NOT to use wxDirPickerCtrl, but wxButton instead: - - Crash on GTK 2: http://favapps.wordpress.com/2012/06/11/freefilesync-crash-in-linux-when-syncing-solved/ - - still uses outdated ::SHBrowseForFolder() (even on Windows 7) - - selection dialog remembers size, but NOT position => if user enlarges window, the next time he opens the dialog it may leap out of visible screen - - hard-codes "Browse" button label -*/ - -extern const wxEventType EVENT_ON_DIR_SELECTED; //directory is changed by the user (except manual type-in) -extern const wxEventType EVENT_ON_DIR_MANUAL_CORRECTION; //manual type-in -//example: wnd.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MyDlg::OnDirSelected), nullptr, this); - -template <class NameControl> //NameControl may be wxTextCtrl, FolderHistoryBox -class DirectoryName: public wxEvtHandler -{ -public: - DirectoryName(wxWindow& dropWindow, - wxButton& selectButton, - NameControl& dirName, - wxStaticText* staticText = nullptr, //optional - wxWindow* dropWindow2 = nullptr); // - - ~DirectoryName(); - - wxString getName() const; - void setName(const wxString& dirname); - -private: - virtual bool acceptDrop(const std::vector<wxString>& droppedFiles, const wxPoint& clientPos, const wxWindow& wnd) { return true; }; //return true if drop should be processed - - void onMouseWheel (wxMouseEvent& event); - void onFilesDropped (FileDropEvent& event); - void onWriteDirManually(wxCommandEvent& event); - void onSelectDir (wxCommandEvent& event); - - wxWindow& dropWindow_; - wxWindow* dropWindow2_; - wxButton& selectButton_; - NameControl& dirName_; - wxStaticText* staticText_; //optional -}; -} - - -#endif // DRAGANDDROP_H_INCLUDED diff --git a/ui/exec_finished_box.cpp b/ui/exec_finished_box.cpp deleted file mode 100644 index cbbfa17d..00000000 --- a/ui/exec_finished_box.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "exec_finished_box.h" -#include <deque> -#include <zen/i18n.h> -#include <algorithm> -#include <zen/stl_tools.h> -#ifdef ZEN_WIN -#include <zen/win_ver.h> -#endif - -using namespace zen; - - -namespace -{ -const std::wstring cmdTxtCloseProgressDlg = L"Close progress dialog"; //special command //mark for extraction: _("Close progress dialog") - -const std::wstring separationLine(L"---------------------------------------------------------------------------------------------------------------"); - -std::vector<std::pair<std::wstring, std::wstring>> getDefaultCommands() //(gui name/command) pairs -{ - std::vector<std::pair<std::wstring, std::wstring>> output; - - auto addEntry = [&](const std::wstring& name, const std::wstring& value) { output.push_back(std::make_pair(name, value)); }; - -#ifdef ZEN_WIN - if (zen::vistaOrLater()) - { - addEntry(_("Standby" ), L"rundll32.exe powrprof.dll,SetSuspendState Sleep"); //suspend/Suspend to RAM/sleep - addEntry(_("Log off" ), L"shutdown /l"); - addEntry(_("Shut down"), L"shutdown /s /t 60"); - //addEntry(_("Hibernate"), L"shutdown /h"); //Suspend to disk -> Standby is better anyway - } - else //XP - { - addEntry(_("Standby"), L"rundll32.exe powrprof.dll,SetSuspendState"); //this triggers standby OR hibernate, depending on whether hibernate setting is active! - addEntry(_("Log off" ), L"shutdown -l"); - addEntry(_("Shut down"), L"shutdown -s -t 60"); - //no suspend on XP? - } - -#elif defined ZEN_LINUX - addEntry(_("Standby" ), L"sudo pm-suspend"); - addEntry(_("Log off" ), L"gnome-session-quit"); //alternative requiring admin: sudo killall Xorg - addEntry(_("Shut down"), L"dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.RequestShutdown"); - //alternative requiring admin: sudo shutdown -h 1 - //addEntry(_("Hibernate"), L"sudo pm-hibernate"); - //alternative: "pmi action suspend" and "pmi action hibernate", require "sudo apt-get install powermanagement-interaface" - -#elif defined ZEN_MAC - addEntry(_("Standby" ), L"osascript -e \'tell application \"System Events\" to sleep\'"); - addEntry(_("Log off" ), L"osascript -e \'tell application \"System Events\" to log out\'"); - addEntry(_("Shut down"), L"osascript -e \'tell application \"System Events\" to shut down\'"); -#endif - return output; -} - -const wxEventType wxEVT_VALIDATE_USER_SELECTION = wxNewEventType(); -} - - -bool isCloseProgressDlgCommand(const std::wstring& value) -{ - std::wstring tmp = value; - trim(tmp); - return tmp == cmdTxtCloseProgressDlg; -} - - -ExecFinishedBox::ExecFinishedBox(wxWindow* parent, - wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, - int n, - const wxString choices[], - long style, - const wxValidator& validator, - const wxString& name) : - wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name), - history_(nullptr), - historyMax_(0), - defaultCommands(getDefaultCommands()) -{ - //##################################### - /*##*/ SetMinSize(wxSize(150, -1)); //## workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox - //##################################### - - Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (ExecFinishedBox::OnKeyEvent ), nullptr, this); - Connect(wxEVT_LEFT_DOWN, wxEventHandler (ExecFinishedBox::OnUpdateList), nullptr, this); - Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(ExecFinishedBox::OnSelection ), nullptr, this); - Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (ExecFinishedBox::OnMouseWheel), nullptr, this); - - Connect(wxEVT_VALIDATE_USER_SELECTION, wxCommandEventHandler(ExecFinishedBox::OnValidateSelection), nullptr, this); -} - - -void ExecFinishedBox::addItemHistory() -{ - if (history_) - { - std::wstring command = getValue(); - trim(command); - - bool skipCmd = command == separationLine || //do not add sep. line - command == cmdTxtCloseProgressDlg || //do not add special command - command.empty(); - - //do not add built-in commands to history - if (!skipCmd) - { - for (auto it = defaultCommands.begin(); it != defaultCommands.end(); ++it) - if (command == it->first || - command == it->second) - { - skipCmd = true; - break; - } - } - - if (!skipCmd) - history_->insert(history_->begin(), command); - - if (history_->size() > historyMax_) - history_->resize(historyMax_); - } -} - - -std::wstring ExecFinishedBox::getValue() const -{ - const std::wstring value = zen::copyStringTo<std::wstring>(GetValue()); - - { - std::wstring tmp = value; - trim(tmp); - if (tmp == implementation::translate(cmdTxtCloseProgressDlg)) //have this symbolic constant translated properly - return cmdTxtCloseProgressDlg; - } - - return value; -} - - -void ExecFinishedBox::setValue(const std::wstring& value) -{ - std::wstring tmp = value; - trim(tmp); - - if (tmp == cmdTxtCloseProgressDlg) - setValueAndUpdateList(implementation::translate(cmdTxtCloseProgressDlg)); //have this symbolic constant translated properly - else - setValueAndUpdateList(value); -} - -//set value and update list are technically entangled: see potential bug description below -void ExecFinishedBox::setValueAndUpdateList(const std::wstring& value) -{ - //it may be a little lame to update the list on each mouse-button click, but it should be working and we dont't have to manipulate wxComboBox internals - - std::deque<std::wstring> items; - - //1. special command - items.push_back(implementation::translate(cmdTxtCloseProgressDlg)); - - //2. built in commands - for (auto it = defaultCommands.begin(); it != defaultCommands.end(); ++it) - items.push_back(it->first); - - //3. history elements - if (history_ && !history_->empty()) - { - items.push_back(separationLine); - items.insert(items.end(), history_->begin(), history_->end()); - std::sort(items.end() - history_->size(), items.end()); - } - - //attention: if the target value is not part of the dropdown list, SetValue() will look for a string that *starts with* this value: - //e.g. if the dropdown list contains "222" SetValue("22") will erroneously set and select "222" instead, while "111" would be set correctly! - // -> by design on Windows! - if (std::find(items.begin(), items.end(), value) == items.end()) - { - if (!value.empty()) - items.push_front(separationLine); - items.push_front(value); - } - - Clear(); - std::for_each(items.begin(), items.end(), [&](const std::wstring& item) { this->Append(item); }); - //this->SetSelection(wxNOT_FOUND); //don't select anything - SetValue(value); //preserve main text! -} - - -void ExecFinishedBox::OnSelection(wxCommandEvent& event) -{ - wxCommandEvent dummy2(wxEVT_VALIDATE_USER_SELECTION); //we cannot replace built-in commands at this position in call stack, so defer to a later time! - if (auto handler = GetEventHandler()) - handler->AddPendingEvent(dummy2); - - event.Skip(); -} - - -void ExecFinishedBox::OnValidateSelection(wxCommandEvent& event) -{ - const auto& value = getValue(); - - if (value == separationLine) - setValueAndUpdateList(std::wstring()); - else - for (auto it = defaultCommands.begin(); it != defaultCommands.end(); ++it) - if (it->first == value) - return setValueAndUpdateList(it->second); //replace GUI name by actual command string -} - - -void ExecFinishedBox::OnUpdateList(wxEvent& event) -{ - setValue(getValue()); - event.Skip(); -} - - -void ExecFinishedBox::OnKeyEvent(wxKeyEvent& event) -{ - switch (event.GetKeyCode()) - { - case WXK_DELETE: - case WXK_NUMPAD_DELETE: - { - //try to delete the currently selected config history item - int pos = this->GetCurrentSelection(); - if (0 <= pos && pos < static_cast<int>(this->GetCount()) && - //what a mess...: - (GetValue() != GetString(pos) || //avoid problems when a character shall be deleted instead of list item - GetValue() == wxEmptyString)) //exception: always allow removing empty entry - { - const std::wstring selValue = copyStringTo<std::wstring>(GetString(pos)); - - if (history_ && std::find(history_->begin(), history_->end(), selValue) != history_->end()) //only history elements may be deleted - { - //save old (selected) value: deletion seems to have influence on this - const wxString currentVal = this->GetValue(); - //this->SetSelection(wxNOT_FOUND); - - //delete selected row - vector_remove_if(*history_, [&](const std::wstring& item) { return item == selValue; }); - - SetString(pos, wxString()); //in contrast to Delete(), this one does not kill the drop-down list and gives a nice visual feedback! - //Delete(pos); - - //(re-)set value - SetValue(currentVal); - } - - //eat up key event - return; - } - } - break; - - case WXK_UP: - case WXK_NUMPAD_UP: - case WXK_DOWN: - case WXK_NUMPAD_DOWN: - case WXK_PAGEUP: - case WXK_NUMPAD_PAGEUP: - case WXK_PAGEDOWN: - case WXK_NUMPAD_PAGEDOWN: - return; //swallow -> using these keys gives a weird effect due to this weird control - } - event.Skip(); -} diff --git a/ui/exec_finished_box.h b/ui/exec_finished_box.h deleted file mode 100644 index 2a69faef..00000000 --- a/ui/exec_finished_box.h +++ /dev/null @@ -1,60 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef EXEC_FINISHED_BOX_18947773210473214 -#define EXEC_FINISHED_BOX_18947773210473214 - -#include <vector> -#include <string> -#include <map> -#include <wx/combobox.h> -#include <zen/string_tools.h> - -//combobox with history function + functionality to delete items (DEL) - -//special command -bool isCloseProgressDlgCommand(const std::wstring& value); - - -class ExecFinishedBox : public wxComboBox -{ -public: - ExecFinishedBox(wxWindow* parent, - wxWindowID id, - const wxString& value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - int n = 0, - const wxString choices[] = nullptr, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxComboBoxNameStr); - - void initHistory(std::vector<std::wstring>& history, size_t historyMax) { history_ = &history; historyMax_ = historyMax; } - void addItemHistory(); //adds current item to history - - // use these two accessors instead of GetValue()/SetValue(): - std::wstring getValue() const; - void setValue(const std::wstring& value); - //required for setting value correctly + Linux to ensure the dropdown is shown as being populated - -private: - void OnKeyEvent(wxKeyEvent& event); - void OnMouseWheel(wxMouseEvent& event) {} //swallow! this gives confusing UI feedback anyway - void OnSelection(wxCommandEvent& event); - void OnValidateSelection(wxCommandEvent& event); - void OnUpdateList(wxEvent& event); - - void setValueAndUpdateList(const std::wstring& value); - - std::vector<std::wstring>* history_; - size_t historyMax_; - - const std::vector<std::pair<std::wstring, std::wstring>> defaultCommands; -}; - - -#endif //EXEC_FINISHED_BOX_18947773210473214 diff --git a/ui/folder_history_box.cpp b/ui/folder_history_box.cpp deleted file mode 100644 index 4676aa43..00000000 --- a/ui/folder_history_box.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "folder_history_box.h" -#include <list> -#include <zen/scope_guard.h> -#include <wx+/string_conv.h> -#include "../lib/resolve_path.h" -#ifdef ZEN_LINUX -#include <gtk/gtk.h> -#endif - -using namespace zen; - - -FolderHistoryBox::FolderHistoryBox(wxWindow* parent, - wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, - int n, - const wxString choices[], - long style, - const wxValidator& validator, - const wxString& name) : - wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name) -{ - //##################################### - /*##*/ SetMinSize(wxSize(150, -1)); //## workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox - //##################################### - - Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (FolderHistoryBox::OnKeyEvent ), nullptr, this); - - warn_static("mac") - warn_static("linux") - -#if defined ZEN_WIN - //on Win, this mouse click event only fires, when clicking on the small down arrow, NOT when clicking on the text field - //thanks to wxWidgets' non-portability it's exactly the converse on Linux! - Connect(wxEVT_LEFT_DOWN, wxEventHandler(FolderHistoryBox::OnRequireHistoryUpdate), nullptr, this); -#elif defined ZEN_LINUX || defined ZEN_MAC - /* - we can't attach to wxEVT_COMMAND_TEXT_UPDATED, since setValueAndUpdateList() will implicitly emit wxEVT_COMMAND_TEXT_UPDATED again when calling Clear()! - => Crash on Suse/X11/wxWidgets 2.9.4 on startup (setting a flag to guard against recursion does not work, still crash) - - On OS attaching to wxEVT_LEFT_DOWN leads to occasional crashes, especially when double-clicking - */ -#endif - -#ifdef ZEN_LINUX - //file drag and drop directly into the text control unhelpfully inserts in format "file://..<cr><nl>" - //1. this format's implementation is a mess: http://www.lephpfacile.com/manuel-php-gtk/tutorials.filednd.urilist.php - //2. even if we handle "drag-data-received" for "text/uri-list" this doesn't consider logic in dirname.cpp - //=> disable all drop events on the text control (disables text drop, too, but not a big loss) - //=> all drops are nicely propagated as regular file drop events like they should have been in the first place! - if (GtkWidget* widget = GetConnectWidget()) - ::gtk_drag_dest_unset(widget); -#endif -} - - -void FolderHistoryBox::OnRequireHistoryUpdate(wxEvent& event) -{ - setValueAndUpdateList(GetValue()); - event.Skip(); -} - -//set value and update list are technically entangled: see potential bug description below -void FolderHistoryBox::setValueAndUpdateList(const wxString& dirname) -{ - //populate selection list.... - std::vector<wxString> dirList; - { - //add some aliases to allow user changing to volume name and back, if possible - std::vector<Zstring> aliases = getDirectoryAliases(toZ(dirname)); //may block when resolving [<volume name>] - std::transform(aliases.begin(), aliases.end(), std::back_inserter(dirList), [](const Zstring& str) { return utfCvrtTo<wxString>(str); }); - } - if (sharedHistory_.get()) - { - std::vector<Zstring> tmp = sharedHistory_->getList(); - std::sort(tmp.begin(), tmp.end(), LessFilename()); - - if (!dirList.empty() && !tmp.empty()) - dirList.push_back(FolderHistory::separationLine()); - - std::transform(tmp.begin(), tmp.end(), std::back_inserter(dirList), [](const Zstring& str) { return utfCvrtTo<wxString>(str); }); - } - - //########################################################################################### - - //attention: if the target value is not part of the dropdown list, SetValue() will look for a string that *starts with* this value: - //e.g. if the dropdown list contains "222" SetValue("22") will erroneously set and select "222" instead, while "111" would be set correctly! - // -> by design on Windows! - if (std::find(dirList.begin(), dirList.end(), dirname) == dirList.end()) - dirList.insert(dirList.begin(), dirname); - - Clear(); //emits yet another wxEVT_COMMAND_TEXT_UPDATED on Suse/X11/wxWidgets 2.9.4!!! - std::for_each(dirList.begin(), dirList.end(), [&](const wxString& dir) { this->Append(dir); }); - //this->SetSelection(wxNOT_FOUND); //don't select anything - this->SetValue(dirname); //preserve main text! -} - - -void FolderHistoryBox::OnKeyEvent(wxKeyEvent& event) -{ - const int keyCode = event.GetKeyCode(); - if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE) - { - //try to delete the currently selected config history item - int pos = this->GetCurrentSelection(); - if (0 <= pos && pos < static_cast<int>(this->GetCount()) && - //what a mess...: - (GetValue() != GetString(pos) || //avoid problems when a character shall be deleted instead of list item - GetValue() == wxEmptyString)) //exception: always allow removing empty entry - { - //save old (selected) value: deletion seems to have influence on this - const wxString currentVal = this->GetValue(); - //this->SetSelection(wxNOT_FOUND); - - //delete selected row - if (sharedHistory_.get()) - sharedHistory_->delItem(toZ(GetString(pos))); - SetString(pos, wxString()); //in contrast to Delete(), this one does not kill the drop-down list and gives a nice visual feedback! - //Delete(pos); - - //(re-)set value - this->SetValue(currentVal); - - //eat up key event - return; - } - } - event.Skip(); -} diff --git a/ui/folder_history_box.h b/ui/folder_history_box.h deleted file mode 100644 index 9ffa2d74..00000000 --- a/ui/folder_history_box.h +++ /dev/null @@ -1,97 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef CUSTOMCOMBOBOX_H_INCLUDED -#define CUSTOMCOMBOBOX_H_INCLUDED - -#include <wx/combobox.h> -#include <memory> -#include <zen/zstring.h> -#include <zen/stl_tools.h> -#include <zen/utf.h> - -//combobox with history function + functionality to delete items (DEL) - - -class FolderHistory -{ -public: - FolderHistory() : maxSize_(0) {} - - FolderHistory(const std::vector<Zstring>& dirnames, size_t maxSize) : - maxSize_(maxSize), - dirnames_(dirnames) - { - if (dirnames_.size() > maxSize_) //keep maximal size of history list - dirnames_.resize(maxSize_); - } - - const std::vector<Zstring>& getList() const { return dirnames_; } - - static const wxString separationLine() { return L"---------------------------------------------------------------------------------------------------------------"; } - - void addItem(const Zstring& dirname) - { - if (dirname.empty() || dirname == zen::utfCvrtTo<Zstring>(separationLine())) - return; - - Zstring nameTmp = dirname; - zen::trim(nameTmp); - - //insert new folder or put it to the front if already existing - auto it = std::find_if(dirnames_.begin(), dirnames_.end(), - [&](const Zstring& entry) { return ::EqualFilename()(entry, nameTmp); }); - - if (it != dirnames_.end()) - dirnames_.erase(it); - dirnames_.insert(dirnames_.begin(), nameTmp); - - if (dirnames_.size() > maxSize_) //keep maximal size of history list - dirnames_.resize(maxSize_); - } - - void delItem(const Zstring& dirname) { zen::vector_remove_if(dirnames_, [&](const Zstring& entry) { return ::EqualFilename()(entry, dirname); }); } - -private: - - size_t maxSize_; - std::vector<Zstring> dirnames_; -}; - - -class FolderHistoryBox : public wxComboBox -{ -public: - FolderHistoryBox(wxWindow* parent, - wxWindowID id, - const wxString& value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - int n = 0, - const wxString choices[] = nullptr, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxComboBoxNameStr); - - void init(const std::shared_ptr<FolderHistory>& sharedHistory) { sharedHistory_ = sharedHistory; } - - void setValue(const wxString& dirname) - { - setValueAndUpdateList(dirname); //required for setting value correctly; Linux: ensure the dropdown is shown as being populated - } - - // GetValue - -private: - void OnKeyEvent(wxKeyEvent& event); - void OnRequireHistoryUpdate(wxEvent& event); - void setValueAndUpdateList(const wxString& dirname); - - std::shared_ptr<FolderHistory> sharedHistory_; -}; - - -#endif // CUSTOMCOMBOBOX_H_INCLUDED diff --git a/ui/folder_history_types.h b/ui/folder_history_types.h deleted file mode 100644 index 23766413..00000000 --- a/ui/folder_history_types.h +++ /dev/null @@ -1,25 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef FOLDER_HIST_TYPES_32481457137432143214 -#define FOLDER_HIST_TYPES_32481457137432143214 - -//#include <ctime> -#include <zen/zstring.h> - - -namespace zen -{ -struct ConfigHistoryItem -{ - explicit ConfigHistoryItem(const Zstring& name) : configFile(name) {} - ConfigHistoryItem() {} - Zstring configFile; - //time_t lastSyncTime; -}; -} - -#endif //FOLDER_HIST_TYPES_32481457137432143214 diff --git a/ui/folder_pair.h b/ui/folder_pair.h deleted file mode 100644 index be01e79d..00000000 --- a/ui/folder_pair.h +++ /dev/null @@ -1,221 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef FOLDERPAIR_H_89341750847252345 -#define FOLDERPAIR_H_89341750847252345 - -#include <wx/event.h> -#include <wx/menu.h> -#include <wx+/context_menu.h> -#include <wx+/bitmap_button.h> -#include <wx+/image_tools.h> -#include <wx+/image_resources.h> -#include "dir_name.h" -#include "small_dlgs.h" -#include "sync_cfg.h" -#include "../lib/norm_filter.h" -#include "../structures.h" - -namespace zen -{ -//basic functionality for handling alternate folder pair configuration: change sync-cfg/filter cfg, right-click context menu, button icons... - -template <class GuiPanel> -class FolderPairPanelBasic : private wxEvtHandler -{ -public: - typedef std::shared_ptr<const CompConfig> AltCompCfgPtr; - typedef std::shared_ptr<const SyncConfig> AltSyncCfgPtr; - - void setConfig(AltCompCfgPtr compConfig, AltSyncCfgPtr syncCfg, const FilterConfig& filter) - { - altCompConfig = compConfig; - altSyncConfig = syncCfg; - localFilter = filter; - refreshButtons(); - } - - AltCompCfgPtr getAltCompConfig() const { return altCompConfig; } - AltSyncCfgPtr getAltSyncConfig() const { return altSyncConfig; } - FilterConfig getAltFilterConfig() const { return localFilter; } - - - FolderPairPanelBasic(GuiPanel& basicPanel) : //takes reference on basic panel to be enhanced - basicPanel_(basicPanel) - { - //register events for removal of alternate configuration - basicPanel_.m_bpButtonAltCompCfg ->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnAltCompCfgContext ), nullptr, this); - basicPanel_.m_bpButtonAltSyncCfg ->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgContext ), nullptr, this); - basicPanel_.m_bpButtonLocalFilter->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnLocalFilterCfgContext), nullptr, this); - - basicPanel_.m_bpButtonAltCompCfg-> Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnAltCompCfg ), nullptr, this); - basicPanel_.m_bpButtonAltSyncCfg-> Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfg ), nullptr, this); - basicPanel_.m_bpButtonLocalFilter->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnLocalFilterCfg), nullptr, this); - - basicPanel_.m_bpButtonRemovePair->SetBitmapLabel(getResourceImage(L"item_remove")); - } - -private: - void refreshButtons() - { - if (altCompConfig.get()) - { - setImage(*basicPanel_.m_bpButtonAltCompCfg, getResourceImage(L"cfg_compare_small")); - basicPanel_.m_bpButtonAltCompCfg->SetToolTip(_("Alternate comparison settings") + L" (" + getVariantName(altCompConfig->compareVar) + L")"); - } - else - { - setImage(*basicPanel_.m_bpButtonAltCompCfg, greyScale(getResourceImage(L"cfg_compare_small"))); - basicPanel_.m_bpButtonAltCompCfg->SetToolTip(_("Alternate comparison settings")); - } - - if (altSyncConfig.get()) - { - setImage(*basicPanel_.m_bpButtonAltSyncCfg, getResourceImage(L"cfg_sync_small")); - basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(_("Alternate synchronization settings") + L" (" + getVariantName(altSyncConfig->directionCfg.var) + L")"); - } - else - { - setImage(*basicPanel_.m_bpButtonAltSyncCfg, greyScale(getResourceImage(L"cfg_sync_small"))); - basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(_("Alternate synchronization settings")); - } - - if (!isNullFilter(localFilter)) - { - setImage(*basicPanel_.m_bpButtonLocalFilter, getResourceImage(L"filter_small")); - basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("Local filter") + L" (" + _("Active") + L")"); - } - else - { - setImage(*basicPanel_.m_bpButtonLocalFilter, greyScale(getResourceImage(L"filter_small"))); - basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("Local filter") + L" (" + _("None") + L")"); - } - } - - void OnAltCompCfgContext(wxCommandEvent& event) - { - auto removeAltCompCfg = [&] - { - this->altCompConfig.reset(); //"this->" galore: workaround GCC compiler bugs - this->refreshButtons(); - this->onAltCompCfgChange(); - }; - - ContextMenu menu; - menu.addItem(_("Remove alternate settings"), removeAltCompCfg, nullptr, altCompConfig.get() != nullptr); - menu.popup(basicPanel_); - } - - void OnAltSyncCfgContext(wxCommandEvent& event) - { - auto removeAltSyncCfg = [&] - { - this->altSyncConfig.reset(); - this->refreshButtons(); - this->onAltSyncCfgChange(); - }; - - ContextMenu menu; - menu.addItem(_("Remove alternate settings"), removeAltSyncCfg, nullptr, altSyncConfig.get() != nullptr); - menu.popup(basicPanel_); - } - - void OnLocalFilterCfgContext(wxCommandEvent& event) - { - auto removeLocalFilterCfg = [&] - { - this->localFilter = FilterConfig(); - this->refreshButtons(); - this->onLocalFilterCfgChange(); - }; - - std::unique_ptr<FilterConfig>& filterCfgOnClipboard = getFilterCfgOnClipboardRef(); - - auto copyFilter = [&] { filterCfgOnClipboard = make_unique<FilterConfig>(this->localFilter); }; - auto pasteFilter = [&] - { - if (filterCfgOnClipboard) - { - this->localFilter = *filterCfgOnClipboard; - this->refreshButtons(); - this->onLocalFilterCfgChange(); - } - }; - - ContextMenu menu; - menu.addItem(_("Clear filter settings"), removeLocalFilterCfg, nullptr, !isNullFilter(localFilter)); - menu.addSeparator(); - menu.addItem( _("Copy"), copyFilter, nullptr, !isNullFilter(localFilter)); - menu.addItem( _("Paste"), pasteFilter, nullptr, filterCfgOnClipboard.get() != nullptr); - menu.popup(basicPanel_); - } - - - virtual MainConfiguration getMainConfig() const = 0; - virtual wxWindow* getParentWindow() = 0; - virtual std::unique_ptr<FilterConfig>& getFilterCfgOnClipboardRef() = 0; - - virtual void onAltCompCfgChange() = 0; - virtual void onAltSyncCfgChange() = 0; - virtual void onLocalFilterCfgChange() = 0; - - void OnAltCompCfg(wxCommandEvent& event) - { - const MainConfiguration mainCfg = getMainConfig(); - - CompConfig cmpCfg = altCompConfig.get() ? *altCompConfig : mainCfg.cmpConfig; - - if (showCompareCfgDialog(getParentWindow(), cmpCfg, _("Alternate Comparison Settings")) == ReturnSmallDlg::BUTTON_OKAY) - { - altCompConfig = std::make_shared<CompConfig>(cmpCfg); - refreshButtons(); - onAltCompCfgChange(); - } - } - - void OnAltSyncCfg(wxCommandEvent& event) - { - const MainConfiguration mainCfg = getMainConfig(); - - CompConfig cmpCfg = altCompConfig.get() ? *altCompConfig : mainCfg.cmpConfig; - SyncConfig syncCfg = altSyncConfig.get() ? *altSyncConfig : mainCfg.syncCfg; - - if (showSyncConfigDlg(getParentWindow(), - cmpCfg.compareVar, - syncCfg, - _("Alternate Synchronization Settings"), - nullptr, - nullptr) == ReturnSyncConfig::BUTTON_OKAY) //optional input parameter - { - altSyncConfig = std::make_shared<SyncConfig>(syncCfg); - refreshButtons(); - onAltSyncCfgChange(); - } - } - - void OnLocalFilterCfg(wxCommandEvent& event) - { - FilterConfig localFiltTmp = localFilter; - - if (showFilterDialog(getParentWindow(), localFiltTmp, _("Local Filter")) == ReturnSmallDlg::BUTTON_OKAY) - { - localFilter = localFiltTmp; - refreshButtons(); - onLocalFilterCfgChange(); - } - } - - GuiPanel& basicPanel_; //panel to be enhanced by this template - - //alternate configuration attached to it - AltCompCfgPtr altCompConfig; //optional - AltSyncCfgPtr altSyncConfig; // - FilterConfig localFilter; -}; -} - - -#endif //FOLDERPAIR_H_89341750847252345 diff --git a/ui/grid_view.cpp b/ui/grid_view.cpp deleted file mode 100644 index e1e16e47..00000000 --- a/ui/grid_view.cpp +++ /dev/null @@ -1,548 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "grid_view.h" -#include "sorting.h" -#include "../synchronization.h" -#include <zen/stl_tools.h> -//#include <zen/perf.h> - -using namespace zen; - - -template <class StatusResult> -void getNumbers(const FileSystemObject& fsObj, StatusResult& result) -{ - struct GetValues : public FSObjectVisitor - { - GetValues(StatusResult& res) : result_(res) {} - - virtual void visit(const FilePair& fileObj) - { - if (!fileObj.isEmpty<LEFT_SIDE>()) - { - result_.filesizeLeftView += fileObj.getFileSize<LEFT_SIDE>(); - ++result_.filesOnLeftView; - } - if (!fileObj.isEmpty<RIGHT_SIDE>()) - { - result_.filesizeRightView += fileObj.getFileSize<RIGHT_SIDE>(); - ++result_.filesOnRightView; - } - } - - virtual void visit(const SymlinkPair& linkObj) - { - if (!linkObj.isEmpty<LEFT_SIDE>()) - ++result_.filesOnLeftView; - - if (!linkObj.isEmpty<RIGHT_SIDE>()) - ++result_.filesOnRightView; - } - - virtual void visit(const DirPair& dirObj) - { - if (!dirObj.isEmpty<LEFT_SIDE>()) - ++result_.foldersOnLeftView; - - if (!dirObj.isEmpty<RIGHT_SIDE>()) - ++result_.foldersOnRightView; - } - StatusResult& result_; - } getVal(result); - fsObj.accept(getVal); -} - - -template <class Predicate> -void GridView::updateView(Predicate pred) -{ - viewRef.clear(); - rowPositions.clear(); - rowPositionsFirstChild.clear(); - - std::for_each(sortedRef.begin(), sortedRef.end(), - [&](const RefIndex& ref) - { - if (const FileSystemObject* fsObj = FileSystemObject::retrieve(ref.objId)) - if (pred(*fsObj)) - { - //save row position for direct random access to FilePair or DirPair - this->rowPositions.insert(std::make_pair(ref.objId, viewRef.size())); //costs: 0.28 µs per call - MSVC based on std::set - //"this->" required by two-pass lookup as enforced by GCC 4.7 - - //save row position to identify first child *on sorted subview* of DirPair or BaseDirPair in case latter are filtered out - const HierarchyObject* parent = &fsObj->parent(); - for (;;) //map all yet unassociated parents to this row - { - const auto rv = this->rowPositionsFirstChild.insert(std::make_pair(parent, viewRef.size())); - if (!rv.second) - break; - - if (auto dirObj = dynamic_cast<const DirPair*>(parent)) - parent = &(dirObj->parent()); - else - break; - } - - //build subview - this->viewRef.push_back(ref.objId); - } - }); -} - - -ptrdiff_t GridView::findRowDirect(FileSystemObject::ObjectIdConst objId) const -{ - auto it = rowPositions.find(objId); - return it != rowPositions.end() ? it->second : -1; -} - -ptrdiff_t GridView::findRowFirstChild(const HierarchyObject* hierObj) const -{ - auto it = rowPositionsFirstChild.find(hierObj); - return it != rowPositionsFirstChild.end() ? it->second : -1; -} - - -GridView::StatusCmpResult::StatusCmpResult() : - existsLeftOnly (false), - existsRightOnly (false), - existsLeftNewer (false), - existsRightNewer(false), - existsDifferent (false), - existsEqual (false), - existsConflict (false), - filesOnLeftView (0), - foldersOnLeftView (0), - filesOnRightView (0), - foldersOnRightView(0) {} - - -GridView::StatusCmpResult GridView::updateCmpResult(bool hideFiltered, //maps sortedRef to viewRef - bool leftOnlyFilesActive, - bool rightOnlyFilesActive, - bool leftNewerFilesActive, - bool rightNewerFilesActive, - bool differentFilesActive, - bool equalFilesActive, - bool conflictFilesActive) -{ - StatusCmpResult output; - - updateView([&](const FileSystemObject& fsObj) -> bool - { - if (hideFiltered && !fsObj.isActive()) - return false; - - switch (fsObj.getCategory()) - { - case FILE_LEFT_SIDE_ONLY: - output.existsLeftOnly = true; - if (!leftOnlyFilesActive) return false; - break; - case FILE_RIGHT_SIDE_ONLY: - output.existsRightOnly = true; - if (!rightOnlyFilesActive) return false; - break; - case FILE_LEFT_NEWER: - output.existsLeftNewer = true; - if (!leftNewerFilesActive) return false; - break; - case FILE_RIGHT_NEWER: - output.existsRightNewer = true; - if (!rightNewerFilesActive) return false; - break; - case FILE_DIFFERENT: - output.existsDifferent = true; - if (!differentFilesActive) return false; - break; - case FILE_EQUAL: - case FILE_DIFFERENT_METADATA: //= sub-category of equal - output.existsEqual = true; - if (!equalFilesActive) return false; - break; - case FILE_CONFLICT: - output.existsConflict = true; - if (!conflictFilesActive) return false; - break; - } - //calculate total number of bytes for each side - getNumbers(fsObj, output); - return true; - }); - - return output; -} - - -GridView::StatusSyncPreview::StatusSyncPreview() : - existsSyncCreateLeft (false), - existsSyncCreateRight(false), - existsSyncDeleteLeft (false), - existsSyncDeleteRight(false), - existsSyncDirLeft (false), - existsSyncDirRight (false), - existsSyncDirNone (false), - existsSyncEqual (false), - existsConflict (false), - filesOnLeftView (0), - foldersOnLeftView (0), - filesOnRightView (0), - foldersOnRightView(0) {} - - -GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //maps sortedRef to viewRef - bool syncCreateLeftActive, - bool syncCreateRightActive, - bool syncDeleteLeftActive, - bool syncDeleteRightActive, - bool syncDirOverwLeftActive, - bool syncDirOverwRightActive, - bool syncDirNoneActive, - bool syncEqualActive, - bool conflictFilesActive) -{ - StatusSyncPreview output; - - updateView([&](const FileSystemObject& fsObj) -> bool - { - if (hideFiltered && !fsObj.isActive()) - return false; - - switch (fsObj.getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - output.existsSyncCreateLeft = true; - if (!syncCreateLeftActive) return false; - break; - case SO_CREATE_NEW_RIGHT: - output.existsSyncCreateRight = true; - if (!syncCreateRightActive) return false; - break; - case SO_DELETE_LEFT: - output.existsSyncDeleteLeft = true; - if (!syncDeleteLeftActive) return false; - break; - case SO_DELETE_RIGHT: - output.existsSyncDeleteRight = true; - if (!syncDeleteRightActive) return false; - break; - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: //no extra button on screen - case SO_MOVE_RIGHT_SOURCE: - case SO_MOVE_RIGHT_TARGET: - output.existsSyncDirRight = true; - if (!syncDirOverwRightActive) return false; - break; - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: //no extra button on screen - case SO_MOVE_LEFT_TARGET: - case SO_MOVE_LEFT_SOURCE: - output.existsSyncDirLeft = true; - if (!syncDirOverwLeftActive) return false; - break; - case SO_DO_NOTHING: - output.existsSyncDirNone = true; - if (!syncDirNoneActive) return false; - break; - case SO_EQUAL: - output.existsSyncEqual = true; - if (!syncEqualActive) return false; - break; - case SO_UNRESOLVED_CONFLICT: - output.existsConflict = true; - if (!conflictFilesActive) return false; - break; - } - - //calculate total number of bytes for each side - getNumbers(fsObj, output); - return true; - }); - - return output; -} - - -std::vector<FileSystemObject*> GridView::getAllFileRef(const std::set<size_t>& rows) -{ - std::vector<FileSystemObject*> output; - - auto iterLast = rows.lower_bound(rowsOnView()); //loop over valid rows only! - std::for_each(rows.begin(), iterLast, - [&](size_t pos) - { - if (FileSystemObject* fsObj = FileSystemObject::retrieve(viewRef[pos])) - output.push_back(fsObj); - }); - return output; -} - - -void GridView::removeInvalidRows() -{ - viewRef.clear(); - rowPositions.clear(); - rowPositionsFirstChild.clear(); - - //remove rows that have been deleted meanwhile - vector_remove_if(sortedRef, [&](const RefIndex& refIdx) { return FileSystemObject::retrieve(refIdx.objId) == nullptr; }); -} - - -class GridView::SerializeHierarchy -{ -public: - static void execute(HierarchyObject& hierObj, std::vector<GridView::RefIndex>& sortedRef, size_t index) { SerializeHierarchy(sortedRef, index).recurse(hierObj); } - -private: - SerializeHierarchy(std::vector<GridView::RefIndex>& sortedRef, size_t index) : - index_(index), - sortedRef_(sortedRef) {} - - void recurse(HierarchyObject& hierObj) - { - for (FilePair& fileObj : hierObj.refSubFiles()) - sortedRef_.push_back(RefIndex(index_, fileObj.getId())); - for (SymlinkPair& linkObj : hierObj.refSubLinks()) - sortedRef_.push_back(RefIndex(index_, linkObj.getId())); - for (DirPair& dirObj : hierObj.refSubDirs()) - { - sortedRef_.push_back(RefIndex(index_, dirObj.getId())); - recurse(dirObj); //add recursion here to list sub-objects directly below parent! - } - } - - size_t index_; - std::vector<GridView::RefIndex>& sortedRef_; -}; - - -void GridView::setData(FolderComparison& folderCmp) -{ - //clear everything - std::vector<FileSystemObject::ObjectId>().swap(viewRef); //free mem - std::vector<RefIndex>().swap(sortedRef); // - currentSort.reset(); - - folderPairCount = std::count_if(begin(folderCmp), end(folderCmp), - [](const BaseDirPair& baseObj) //count non-empty pairs to distinguish single/multiple folder pair cases - { - return !baseObj.getBaseDirPf<LEFT_SIDE >().empty() || - !baseObj.getBaseDirPf<RIGHT_SIDE>().empty(); - }); - - for (auto it = begin(folderCmp); it != end(folderCmp); ++it) - SerializeHierarchy::execute(*it, sortedRef, it - begin(folderCmp)); -} - - -//------------------------------------ SORTING TEMPLATES ------------------------------------------------ -template <bool ascending> -class GridView::LessRelativeName : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - //presort by folder pair - if (a.folderIndex != b.folderIndex) - return ascending ? - a.folderIndex < b.folderIndex : - a.folderIndex > b.folderIndex; - - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessRelativeName<ascending>(*fsObjA, *fsObjB); - } -}; - - -template <bool ascending, zen::SelectedSide side> -class GridView::LessShortFileName : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessShortFileName<ascending, side>(*fsObjA, *fsObjB); - } -}; - - -template <bool ascending, zen::SelectedSide side> -class GridView::LessFilesize : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessFilesize<ascending, side>(*fsObjA, *fsObjB); - } -}; - - -template <bool ascending, zen::SelectedSide side> -class GridView::LessFiletime : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessFiletime<ascending, side>(*fsObjA, *fsObjB); - } -}; - - -template <bool ascending, zen::SelectedSide side> -class GridView::LessExtension : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessExtension<ascending, side>(*fsObjA, *fsObjB); - } -}; - - -template <bool ascending> -class GridView::LessCmpResult : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessCmpResult<ascending>(*fsObjA, *fsObjB); - } -}; - - -template <bool ascending> -class GridView::LessSyncDirection : public std::binary_function<RefIndex, RefIndex, bool> -{ -public: - bool operator()(const RefIndex a, const RefIndex b) const - { - const FileSystemObject* fsObjA = FileSystemObject::retrieve(a.objId); - const FileSystemObject* fsObjB = FileSystemObject::retrieve(b.objId); - if (!fsObjA) //invalid rows shall appear at the end - return false; - else if (!fsObjB) - return true; - - return lessSyncDirection<ascending>(*fsObjA, *fsObjB); - } -}; - -//------------------------------------------------------------------------------------------------------- -bool GridView::getDefaultSortDirection(ColumnTypeRim type) //true: ascending; false: descending -{ - switch (type) - { - case COL_TYPE_SIZE: - case COL_TYPE_DATE: - return false; - - case COL_TYPE_DIRECTORY: - case COL_TYPE_FULL_PATH: - case COL_TYPE_REL_PATH: - case COL_TYPE_FILENAME: - case COL_TYPE_EXTENSION: - return true; - } - assert(false); - return true; -} - - -void GridView::sortView(ColumnTypeRim type, bool onLeft, bool ascending) -{ - viewRef.clear(); - rowPositions.clear(); - rowPositionsFirstChild.clear(); - currentSort = make_unique<SortInfo>(type, onLeft, ascending); - - switch (type) - { - case COL_TYPE_FULL_PATH: - case COL_TYPE_REL_PATH: - if ( ascending) std::sort(sortedRef.begin(), sortedRef.end(), LessRelativeName<true>()); - else if (!ascending) std::sort(sortedRef.begin(), sortedRef.end(), LessRelativeName<false>()); - break; - case COL_TYPE_FILENAME: - if ( ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<true, LEFT_SIDE >()); - else if ( ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<true, RIGHT_SIDE>()); - else if (!ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<false, LEFT_SIDE >()); - else if (!ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<false, RIGHT_SIDE>()); - break; - case COL_TYPE_SIZE: - if ( ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<true, LEFT_SIDE >()); - else if ( ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<true, RIGHT_SIDE>()); - else if (!ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<false, LEFT_SIDE >()); - else if (!ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<false, RIGHT_SIDE>()); - break; - case COL_TYPE_DATE: - if ( ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<true, LEFT_SIDE >()); - else if ( ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<true, RIGHT_SIDE>()); - else if (!ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<false, LEFT_SIDE >()); - else if (!ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<false, RIGHT_SIDE>()); - break; - case COL_TYPE_EXTENSION: - if ( ascending && onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<true, LEFT_SIDE >()); - else if ( ascending && !onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<true, RIGHT_SIDE>()); - else if (!ascending && onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<false, LEFT_SIDE >()); - else if (!ascending && !onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<false, RIGHT_SIDE>()); - break; - //case SORT_BY_CMP_RESULT: - // if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessCmpResult<true >()); - // else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessCmpResult<false>()); - // break; - //case SORT_BY_SYNC_DIRECTION: - // if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessSyncDirection<true >()); - // else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessSyncDirection<false>()); - // break; - case COL_TYPE_DIRECTORY: - if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), [](const RefIndex a, const RefIndex b) { return a.folderIndex < b.folderIndex; }); - else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), [](const RefIndex a, const RefIndex b) { return a.folderIndex > b.folderIndex; }); - break; - } -} diff --git a/ui/grid_view.h b/ui/grid_view.h deleted file mode 100644 index 0cef5dea..00000000 --- a/ui/grid_view.h +++ /dev/null @@ -1,202 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef GRIDVIEW_H_INCLUDED -#define GRIDVIEW_H_INCLUDED - -#include <set> -#include "column_attr.h" -#include "../file_hierarchy.h" - - -namespace zen -{ -//grid view of FolderComparison -class GridView -{ -public: - GridView() : folderPairCount(0) {} - - //direct data access via row number - const FileSystemObject* getObject(size_t row) const; //returns nullptr if object is not found; complexity: constant! - /**/ - FileSystemObject* getObject(size_t row); // - size_t rowsOnView() const { return viewRef .size(); } //only visible elements - size_t rowsTotal () const { return sortedRef.size(); } //total rows available - - //get references to FileSystemObject: no nullptr-check needed! Everything's bound. - std::vector<FileSystemObject*> getAllFileRef(const std::set<size_t>& rows); - - struct StatusCmpResult - { - StatusCmpResult(); - - bool existsLeftOnly; - bool existsRightOnly; - bool existsLeftNewer; - bool existsRightNewer; - bool existsDifferent; - bool existsEqual; - bool existsConflict; - - unsigned int filesOnLeftView; - unsigned int foldersOnLeftView; - unsigned int filesOnRightView; - unsigned int foldersOnRightView; - - zen::UInt64 filesizeLeftView; - zen::UInt64 filesizeRightView; - }; - - //comparison results view - StatusCmpResult updateCmpResult(bool hideFiltered, - bool leftOnlyFilesActive, - bool rightOnlyFilesActive, - bool leftNewerFilesActive, - bool rightNewerFilesActive, - bool differentFilesActive, - bool equalFilesActive, - bool conflictFilesActive); - - struct StatusSyncPreview - { - StatusSyncPreview(); - - bool existsSyncCreateLeft; - bool existsSyncCreateRight; - bool existsSyncDeleteLeft; - bool existsSyncDeleteRight; - bool existsSyncDirLeft; - bool existsSyncDirRight; - bool existsSyncDirNone; - bool existsSyncEqual; - bool existsConflict; - - unsigned int filesOnLeftView; - unsigned int foldersOnLeftView; - unsigned int filesOnRightView; - unsigned int foldersOnRightView; - - zen::UInt64 filesizeLeftView; - zen::UInt64 filesizeRightView; - }; - - //synchronization preview - StatusSyncPreview updateSyncPreview(bool hideFiltered, - bool syncCreateLeftActive, - bool syncCreateRightActive, - bool syncDeleteLeftActive, - bool syncDeleteRightActive, - bool syncDirOverwLeftActive, - bool syncDirOverwRightActive, - bool syncDirNoneActive, - bool syncEqualActive, - bool conflictFilesActive); - - void setData(FolderComparison& newData); - void removeInvalidRows(); //remove rows that have been deleted meanwhile: call after manual deletion and synchronization! - - //sorting... - bool static getDefaultSortDirection(zen::ColumnTypeRim type); //true: ascending; false: descending - - void sortView(zen::ColumnTypeRim type, bool onLeft, bool ascending); //always call this method for sorting, never sort externally! - - struct SortInfo - { - SortInfo(zen::ColumnTypeRim type, bool onLeft, bool ascending) : type_(type), onLeft_(onLeft), ascending_(ascending) {} - zen::ColumnTypeRim type_; - bool onLeft_; - bool ascending_; - }; - const SortInfo* getSortInfo() const { return currentSort.get(); } //return nullptr if currently not sorted - - ptrdiff_t findRowDirect(FileSystemObject::ObjectIdConst objId) const; // find an object's row position on view list directly, return < 0 if not found - ptrdiff_t findRowFirstChild(const HierarchyObject* hierObj) const; // find first child of DirPair or BaseDirPair *on sorted sub view* - //"hierObj" may be invalid, it is NOT dereferenced, return < 0 if not found - - size_t getFolderPairCount() const { return folderPairCount; } //count non-empty pairs to distinguish single/multiple folder pair cases - -private: - struct RefIndex - { - RefIndex(size_t folderInd, FileSystemObject::ObjectId id) : - folderIndex(folderInd), - objId(id) {} - size_t folderIndex; //because of alignment there's no benefit in using "unsigned int" in 64-bit code here! - FileSystemObject::ObjectId objId; - }; - - template <class Predicate> void updateView(Predicate pred); - - - zen::hash_map<FileSystemObject::ObjectIdConst, size_t> rowPositions; //find row positions on sortedRef directly - zen::hash_map<const void*, size_t> rowPositionsFirstChild; //find first child on sortedRef of a hierarchy object - //void* instead of HierarchyObject*: these are weak pointers and should *never be dereferenced*! - - std::vector<FileSystemObject::ObjectId> viewRef; //partial view on sortedRef - /* /|\ - | (update...) - | */ - std::vector<RefIndex> sortedRef; //flat view of weak pointers on folderCmp; may be sorted - /* /|\ - | (setData...) - | */ - //std::shared_ptr<FolderComparison> folderCmp; //actual comparison data: owned by GridView! - size_t folderPairCount; //number of non-empty folder pairs - - - class SerializeHierarchy; - - //sorting classes - template <bool ascending> - class LessRelativeName; - - template <bool ascending, SelectedSide side> - class LessShortFileName; - - template <bool ascending, SelectedSide side> - class LessFilesize; - - template <bool ascending, SelectedSide side> - class LessFiletime; - - template <bool ascending, SelectedSide side> - class LessExtension; - - template <bool ascending> - class LessCmpResult; - - template <bool ascending> - class LessSyncDirection; - - std::unique_ptr<SortInfo> currentSort; -}; - - - - - - - -//##################### implementation ######################################### - -inline -const FileSystemObject* GridView::getObject(size_t row) const -{ - return row < viewRef.size() ? - FileSystemObject::retrieve(viewRef[row]) : nullptr; -} - -inline -FileSystemObject* GridView::getObject(size_t row) -{ - //code re-use of const method: see Meyers Effective C++ - return const_cast<FileSystemObject*>(static_cast<const GridView&>(*this).getObject(row)); -} -} - - -#endif // GRIDVIEW_H_INCLUDED diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp deleted file mode 100644 index 717a8535..00000000 --- a/ui/gui_generated.cpp +++ /dev/null @@ -1,3505 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) -// http://www.wxformbuilder.org/ -// -// PLEASE DO "NOT" EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#include "../wx+/bitmap_button.h" -#include "../wx+/graph.h" -#include "../wx+/grid.h" -#include "../wx+/toggle_button.h" -#include "exec_finished_box.h" -#include "folder_history_box.h" -#include "triple_splitter.h" - -#include "gui_generated.h" - -/////////////////////////////////////////////////////////////////////////// - -MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( 640,400 ), wxDefaultSize ); - - m_menubar1 = new wxMenuBar( 0 ); - m_menuFile = new wxMenu(); - m_menuItemNew = new wxMenuItem( m_menuFile, wxID_NEW, wxString( _("&New") ) + wxT('\t') + wxT("Ctrl+N"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemNew ); - - m_menuItemLoad = new wxMenuItem( m_menuFile, wxID_OPEN, wxString( _("&Open...") ) + wxT('\t') + wxT("Ctrl+O"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemLoad ); - - m_menuItemSave = new wxMenuItem( m_menuFile, wxID_SAVE, wxString( _("&Save") ) + wxT('\t') + wxT("Ctrl+S"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSave ); - - m_menuItemSaveAs = new wxMenuItem( m_menuFile, wxID_SAVEAS, wxString( _("Save &as...") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSaveAs ); - - m_menuItem7 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("Save as &batch job...") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem7 ); - - m_menuFile->AppendSeparator(); - - m_menuItem10 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("1. &Compare") ) + wxT('\t') + wxT("F5"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem10 ); - - m_menuItem11 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("2. &Synchronize") ) + wxT('\t') + wxT("F8"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem11 ); - - m_menuFile->AppendSeparator(); - - wxMenuItem* m_menuItem4; - m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("&Quit") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem4 ); - - m_menubar1->Append( m_menuFile, _("&Program") ); - - m_menuTools = new wxMenu(); - m_menuItemGlobSett = new wxMenuItem( m_menuTools, wxID_PREFERENCES, wxString( _("&Global settings") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItemGlobSett ); - - m_menuTools->AppendSeparator(); - - m_menuLanguages = new wxMenu(); - m_menuTools->Append( -1, _("&Language"), m_menuLanguages ); - - wxMenuItem* m_menuItem15; - m_menuItem15 = new wxMenuItem( m_menuTools, wxID_FIND, wxString( _("&Find...") ) + wxT('\t') + wxT("Ctrl+F"), wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItem15 ); - - wxMenuItem* m_menuItem5; - m_menuItem5 = new wxMenuItem( m_menuTools, wxID_ANY, wxString( _("&Export file list...") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuTools->Append( m_menuItem5 ); - - m_menubar1->Append( m_menuTools, _("&Tools") ); - - m_menuHelp = new wxMenu(); - m_menuItemManual = new wxMenuItem( m_menuHelp, wxID_HELP, wxString( _("&View help") ) + wxT('\t') + wxT("F1"), wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemManual ); - - m_menuCheckVersion = new wxMenu(); - m_menuItemCheckVersionNow = new wxMenuItem( m_menuCheckVersion, wxID_ANY, wxString( _("&Check now") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuCheckVersion->Append( m_menuItemCheckVersionNow ); - - m_menuItemCheckVersionAuto = new wxMenuItem( m_menuCheckVersion, wxID_ANY, wxString( _("Check &automatically once a week") ) , wxEmptyString, wxITEM_CHECK ); - m_menuCheckVersion->Append( m_menuItemCheckVersionAuto ); - m_menuItemCheckVersionAuto->Check( true ); - - m_menuHelp->Append( -1, _("&Check for new version"), m_menuCheckVersion ); - - m_menuHelp->AppendSeparator(); - - m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About") ) + wxT('\t') + wxT("Shift+F1"), wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemAbout ); - - m_menubar1->Append( m_menuHelp, _("&Help") ); - - this->SetMenuBar( m_menubar1 ); - - bSizerPanelHolder = new wxBoxSizer( wxVERTICAL ); - - m_panelTopButtons = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxRAISED_BORDER|wxTAB_TRAVERSAL ); - bSizerTopButtons = new wxBoxSizer( wxHORIZONTAL ); - - - bSizerTopButtons->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer1721; - bSizer1721 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonCompare->SetDefault(); - m_buttonCompare->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_buttonCompare->SetToolTip( _("dummy") ); - - bSizer1721->Add( m_buttonCompare, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_buttonCancel = new zen::BitmapTextButton( m_panelTopButtons, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( 180,-1 ), 0 ); - m_buttonCancel->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_buttonCancel->Enable( false ); - m_buttonCancel->Hide(); - - bSizer1721->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - m_bpButtonCmpConfig->SetToolTip( _("dummy") ); - - bSizer1721->Add( m_bpButtonCmpConfig, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 3 ); - - - bSizerTopButtons->Add( bSizer1721, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 4 ); - - - bSizerTopButtons->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer1731; - bSizer1731 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - m_bpButtonSyncConfig->SetToolTip( _("dummy") ); - - bSizer1731->Add( m_bpButtonSyncConfig, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); - - m_buttonSync = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Synchronize"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_buttonSync->SetToolTip( _("dummy") ); - - bSizer1731->Add( m_buttonSync, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerTopButtons->Add( bSizer1731, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 4 ); - - - bSizerTopButtons->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - m_panelTopButtons->SetSizer( bSizerTopButtons ); - m_panelTopButtons->Layout(); - bSizerTopButtons->Fit( m_panelTopButtons ); - bSizerPanelHolder->Add( m_panelTopButtons, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_panelDirectoryPairs = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1601; - bSizer1601 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer91; - bSizer91 = new wxBoxSizer( wxHORIZONTAL ); - - m_panelTopLeft = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelTopLeft->SetMinSize( wxSize( 1,-1 ) ); - - wxFlexGridSizer* fgSizer8; - fgSizer8 = new wxFlexGridSizer( 0, 2, 0, 0 ); - fgSizer8->AddGrowableCol( 1 ); - fgSizer8->SetFlexibleDirection( wxBOTH ); - fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); - - - fgSizer8->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextResolvedPathL = new wxStaticText( m_panelTopLeft, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextResolvedPathL->Wrap( -1 ); - fgSizer8->Add( m_staticTextResolvedPathL, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); - - wxBoxSizer* bSizer159; - bSizer159 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); - - bSizer159->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - - bSizer159->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - fgSizer8->Add( bSizer159, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryLeft = new FolderHistoryBox( m_panelTopLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer182->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonSelectDirLeft = new wxButton( m_panelTopLeft, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectDirLeft->SetToolTip( _("Select a folder") ); - - bSizer182->Add( m_buttonSelectDirLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - fgSizer8->Add( bSizer182, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - m_panelTopLeft->SetSizer( fgSizer8 ); - m_panelTopLeft->Layout(); - fgSizer8->Fit( m_panelTopLeft ); - bSizer91->Add( m_panelTopLeft, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelTopMiddle = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1771; - bSizer1771 = new wxBoxSizer( wxVERTICAL ); - - - bSizer1771->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bpButtonSwapSides = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW ); - m_bpButtonSwapSides->SetToolTip( _("Swap sides") ); - - bSizer1771->Add( m_bpButtonSwapSides, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonAltCompCfg = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer160->Add( m_bpButtonAltCompCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer160->Add( m_bpButtonLocalFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 2 ); - - m_bpButtonAltSyncCfg = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer160->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer1771->Add( bSizer160, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer1771->Add( 0, 0, 1, wxEXPAND, 5 ); - - - m_panelTopMiddle->SetSizer( bSizer1771 ); - m_panelTopMiddle->Layout(); - bSizer1771->Fit( m_panelTopMiddle ); - bSizer91->Add( m_panelTopMiddle, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_panelTopRight = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelTopRight->SetMinSize( wxSize( 1,-1 ) ); - - wxBoxSizer* bSizer183; - bSizer183 = new wxBoxSizer( wxVERTICAL ); - - m_staticTextResolvedPathR = new wxStaticText( m_panelTopRight, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextResolvedPathR->Wrap( -1 ); - bSizer183->Add( m_staticTextResolvedPathR, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); - - wxBoxSizer* bSizer179; - bSizer179 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryRight = new FolderHistoryBox( m_panelTopRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer179->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonSelectDirRight = new wxButton( m_panelTopRight, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectDirRight->SetToolTip( _("Select a folder") ); - - bSizer179->Add( m_buttonSelectDirRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer183->Add( bSizer179, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - m_panelTopRight->SetSizer( bSizer183 ); - m_panelTopRight->Layout(); - bSizer183->Fit( m_panelTopRight ); - bSizer91->Add( m_panelTopRight, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - - bSizer1601->Add( bSizer91, 0, wxEXPAND, 5 ); - - m_scrolledWindowFolderPairs = new wxScrolledWindow( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxHSCROLL|wxVSCROLL ); - m_scrolledWindowFolderPairs->SetScrollRate( 10, 10 ); - m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1,0 ) ); - - bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); - - - m_scrolledWindowFolderPairs->SetSizer( bSizerAddFolderPairs ); - m_scrolledWindowFolderPairs->Layout(); - bSizerAddFolderPairs->Fit( m_scrolledWindowFolderPairs ); - bSizer1601->Add( m_scrolledWindowFolderPairs, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - m_panelDirectoryPairs->SetSizer( bSizer1601 ); - m_panelDirectoryPairs->Layout(); - bSizer1601->Fit( m_panelDirectoryPairs ); - bSizerPanelHolder->Add( m_panelDirectoryPairs, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_gridNavi = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridNavi->SetScrollRate( 5, 5 ); - bSizerPanelHolder->Add( m_gridNavi, 1, wxEXPAND, 5 ); - - m_panelCenter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1711; - bSizer1711 = new wxBoxSizer( wxVERTICAL ); - - m_splitterMain = new zen::TripleSplitter( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1781; - bSizer1781 = new wxBoxSizer( wxHORIZONTAL ); - - m_gridMainL = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMainL->SetScrollRate( 5, 5 ); - bSizer1781->Add( m_gridMainL, 1, wxEXPAND, 5 ); - - m_gridMainC = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMainC->SetScrollRate( 5, 5 ); - bSizer1781->Add( m_gridMainC, 0, wxEXPAND, 5 ); - - m_gridMainR = new zen::Grid( m_splitterMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMainR->SetScrollRate( 5, 5 ); - bSizer1781->Add( m_gridMainR, 1, wxEXPAND, 5 ); - - - m_splitterMain->SetSizer( bSizer1781 ); - m_splitterMain->Layout(); - bSizer1781->Fit( m_splitterMain ); - bSizer1711->Add( m_splitterMain, 1, wxEXPAND, 5 ); - - m_panelStatusBar = new wxPanel( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer451; - bSizer451 = new wxBoxSizer( wxHORIZONTAL ); - - bSizer451->SetMinSize( wxSize( -1,22 ) ); - bSizerFileStatus = new wxBoxSizer( wxHORIZONTAL ); - - bSizerStatusLeft = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer53; - bSizer53 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizerStatusLeftDirectories = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapSmallDirectoryLeft = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusLeftDirectories->Add( m_bitmapSmallDirectoryLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusLeftDirectories->Add( 2, 0, 0, 0, 5 ); - - m_staticTextStatusLeftDirs = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeftDirs->Wrap( -1 ); - bSizerStatusLeftDirectories->Add( m_staticTextStatusLeftDirs, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer53->Add( bSizerStatusLeftDirectories, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizerStatusLeftFiles = new wxBoxSizer( wxHORIZONTAL ); - - - bSizerStatusLeftFiles->Add( 10, 0, 0, 0, 5 ); - - m_bitmapSmallFileLeft = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusLeftFiles->Add( m_bitmapSmallFileLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusLeftFiles->Add( 2, 0, 0, 0, 5 ); - - m_staticTextStatusLeftFiles = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeftFiles->Wrap( -1 ); - bSizerStatusLeftFiles->Add( m_staticTextStatusLeftFiles, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusLeftFiles->Add( 4, 0, 0, 0, 5 ); - - m_staticTextStatusLeftBytes = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeftBytes->Wrap( -1 ); - bSizerStatusLeftFiles->Add( m_staticTextStatusLeftBytes, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer53->Add( bSizerStatusLeftFiles, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusLeft->Add( bSizer53, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticline9 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerStatusLeft->Add( m_staticline9, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP, 2 ); - - - bSizerFileStatus->Add( bSizerStatusLeft, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextStatusMiddle = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusMiddle->Wrap( -1 ); - bSizerFileStatus->Add( m_staticTextStatusMiddle, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizerStatusRight = new wxBoxSizer( wxHORIZONTAL ); - - m_staticline10 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizerStatusRight->Add( m_staticline10, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP, 2 ); - - wxBoxSizer* bSizer52; - bSizer52 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizerStatusRightDirectories = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapSmallDirectoryRight = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusRightDirectories->Add( m_bitmapSmallDirectoryRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusRightDirectories->Add( 2, 0, 0, 0, 5 ); - - m_staticTextStatusRightDirs = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRightDirs->Wrap( -1 ); - bSizerStatusRightDirectories->Add( m_staticTextStatusRightDirs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer52->Add( bSizerStatusRightDirectories, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizerStatusRightFiles = new wxBoxSizer( wxHORIZONTAL ); - - - bSizerStatusRightFiles->Add( 10, 0, 0, 0, 5 ); - - m_bitmapSmallFileRight = new wxStaticBitmap( m_panelStatusBar, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizerStatusRightFiles->Add( m_bitmapSmallFileRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusRightFiles->Add( 2, 0, 0, 0, 5 ); - - m_staticTextStatusRightFiles = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRightFiles->Wrap( -1 ); - bSizerStatusRightFiles->Add( m_staticTextStatusRightFiles, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusRightFiles->Add( 4, 0, 0, 0, 5 ); - - m_staticTextStatusRightBytes = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRightBytes->Wrap( -1 ); - bSizerStatusRightFiles->Add( m_staticTextStatusRightBytes, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer52->Add( bSizerStatusRightFiles, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatusRight->Add( bSizer52, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerFileStatus->Add( bSizerStatusRight, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer451->Add( bSizerFileStatus, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticTextFullStatus = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFullStatus->Wrap( -1 ); - m_staticTextFullStatus->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer451->Add( m_staticTextFullStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - m_panelStatusBar->SetSizer( bSizer451 ); - m_panelStatusBar->Layout(); - bSizer451->Fit( m_panelStatusBar ); - bSizer1711->Add( m_panelStatusBar, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - - m_panelCenter->SetSizer( bSizer1711 ); - m_panelCenter->Layout(); - bSizer1711->Fit( m_panelCenter ); - bSizerPanelHolder->Add( m_panelCenter, 1, wxEXPAND, 5 ); - - m_panelSearch = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1713; - bSizer1713 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - m_bpButtonHideSearch->SetToolTip( _("Close search bar") ); - - bSizer1713->Add( m_bpButtonHideSearch, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_staticText101 = new wxStaticText( m_panelSearch, wxID_ANY, _("Find:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText101->Wrap( -1 ); - bSizer1713->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220,-1 ), 0|wxWANTS_CHARS ); - m_textCtrlSearchTxt->SetMaxLength( 0 ); - bSizer1713->Add( m_textCtrlSearchTxt, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_checkBoxMatchCase = new wxCheckBox( m_panelSearch, wxID_ANY, _("Match case"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer1713->Add( m_checkBoxMatchCase, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - m_panelSearch->SetSizer( bSizer1713 ); - m_panelSearch->Layout(); - bSizer1713->Fit( m_panelSearch ); - bSizerPanelHolder->Add( m_panelSearch, 0, 0, 5 ); - - m_panelConfig = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - bSizerConfig = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer151; - bSizer151 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - m_bpButtonOpen->SetToolTip( _("dummy") ); - - bSizer151->Add( m_bpButtonOpen, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - m_bpButtonSave->SetToolTip( _("dummy") ); - - bSizer151->Add( m_bpButtonSave, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonBatchJob = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - m_bpButtonBatchJob->SetToolTip( _("Save as batch job") ); - - bSizer151->Add( m_bpButtonBatchJob, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerConfig->Add( bSizer151, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_NEEDED_SB ); - m_listBoxHistory->SetMinSize( wxSize( -1,40 ) ); - - bSizerConfig->Add( m_listBoxHistory, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - m_panelConfig->SetSizer( bSizerConfig ); - m_panelConfig->Layout(); - bSizerConfig->Fit( m_panelConfig ); - bSizerPanelHolder->Add( m_panelConfig, 0, 0, 5 ); - - m_panelFilter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer171; - bSizer171 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonFilter = new wxBitmapButton( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); - bSizer171->Add( m_bpButtonFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_checkBoxHideExcluded = new wxCheckBox( m_panelFilter, wxID_ANY, _("Hide excluded items"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxHideExcluded->SetToolTip( _("Show filtered or temporarily excluded files") ); - - bSizer171->Add( m_checkBoxHideExcluded, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - m_panelFilter->SetSizer( bSizer171 ); - m_panelFilter->Layout(); - bSizer171->Fit( m_panelFilter ); - bSizerPanelHolder->Add( m_panelFilter, 0, 0, 5 ); - - m_panelStatistics = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - bSizer1801 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer1801->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizerStatistics = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer1712; - bSizer1712 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - - bSizer1712->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer1712->Add( 5, 2, 0, 0, 5 ); - - - bSizer1712->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateLeft->Wrap( -1 ); - m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - - bSizer1712->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerStatistics->Add( bSizer1712, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be overwritten") ); - - bSizer172->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer172->Add( 5, 2, 0, 0, 5 ); - - - bSizer172->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateLeft->Wrap( -1 ); - m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be overwritten") ); - - bSizer172->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerStatistics->Add( bSizer172, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - - wxBoxSizer* bSizer173; - bSizer173 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - - bSizer173->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer173->Add( 5, 2, 0, 0, 5 ); - - - bSizer173->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteLeft->Wrap( -1 ); - m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - - bSizer173->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatistics->Add( bSizer173, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - - bSizerData = new wxBoxSizer( wxVERTICAL ); - - m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapData->SetToolTip( _("Total bytes to copy") ); - - bSizerData->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerData->Add( 5, 2, 0, 0, 5 ); - - - bSizerData->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextData->Wrap( -1 ); - m_staticTextData->SetToolTip( _("Total bytes to copy") ); - - bSizerData->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatistics->Add( bSizerData, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - - wxBoxSizer* bSizer176; - bSizer176 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - - bSizer176->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer176->Add( 5, 2, 0, 0, 5 ); - - - bSizer176->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteRight->Wrap( -1 ); - m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - - bSizer176->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatistics->Add( bSizer176, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - - wxBoxSizer* bSizer177; - bSizer177 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateRight->SetToolTip( _("Number of files that will be overwritten") ); - - bSizer177->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer177->Add( 5, 2, 0, 0, 5 ); - - - bSizer177->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateRight->Wrap( -1 ); - m_staticTextUpdateRight->SetToolTip( _("Number of files that will be overwritten") ); - - bSizer177->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatistics->Add( bSizer177, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizerStatistics->Add( 5, 5, 0, 0, 5 ); - - wxBoxSizer* bSizer178; - bSizer178 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - - bSizer178->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer178->Add( 5, 2, 0, 0, 5 ); - - - bSizer178->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateRight->Wrap( -1 ); - m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - - bSizer178->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStatistics->Add( bSizer178, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer1801->Add( bSizerStatistics, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer1801->Add( 0, 0, 1, wxEXPAND, 5 ); - - - m_panelStatistics->SetSizer( bSizer1801 ); - m_panelStatistics->Layout(); - bSizer1801->Fit( m_panelStatistics ); - bSizerPanelHolder->Add( m_panelStatistics, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelViewFilter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - bSizerViewFilter = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonViewTypeSyncAction = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonViewTypeSyncAction, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerViewFilter->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bpButtonShowCreateLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowUpdateLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowDeleteLeft = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowDeleteLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowLeftOnly = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowLeftOnly, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowLeftNewer = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowLeftNewer, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowEqual = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowEqual, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowDifferent = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowDifferent, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowDoNothing = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowDoNothing, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowRightNewer = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowRightNewer, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowRightOnly = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowRightOnly, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowDeleteRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowDeleteRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowUpdateRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowCreateRight = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonShowConflict = new ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizerViewFilter->Add( m_bpButtonShowConflict, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerViewFilter->Add( 0, 0, 1, wxEXPAND, 5 ); - - - m_panelViewFilter->SetSizer( bSizerViewFilter ); - m_panelViewFilter->Layout(); - bSizerViewFilter->Fit( m_panelViewFilter ); - bSizerPanelHolder->Add( m_panelViewFilter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - this->SetSizer( bSizerPanelHolder ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::OnClose ) ); - this->Connect( m_menuItemNew->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigNew ) ); - this->Connect( m_menuItemLoad->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigLoad ) ); - this->Connect( m_menuItemSave->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigSave ) ); - this->Connect( m_menuItemSaveAs->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigSaveAs ) ); - this->Connect( m_menuItem7->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveAsBatchJob ) ); - this->Connect( m_menuItem10->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ) ); - this->Connect( m_menuItem11->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ) ); - this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) ); - this->Connect( m_menuItemGlobSett->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); - this->Connect( m_menuItem15->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuFindItem ) ); - this->Connect( m_menuItem5->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); - this->Connect( m_menuItemManual->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnShowHelp ) ); - this->Connect( m_menuItemCheckVersionNow->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ) ); - this->Connect( m_menuItemCheckVersionAuto->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersionAutomatically ) ); - this->Connect( m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); - m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); - m_bpButtonCmpConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), NULL, this ); - m_bpButtonCmpConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnCompSettingsContext ), NULL, this ); - m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this ); - m_bpButtonSyncConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnSyncSettingsContext ), NULL, this ); - m_buttonSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this ); - m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this ); - m_bpButtonRemovePair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRemoveTopFolderPair ), NULL, this ); - m_bpButtonSwapSides->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this ); - m_bpButtonHideSearch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideSearchPanel ), NULL, this ); - m_textCtrlSearchTxt->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( MainDialogGenerated::OnSearchGridEnter ), NULL, this ); - m_bpButtonOpen->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConfigLoad ), NULL, this ); - m_bpButtonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConfigSave ), NULL, this ); - m_bpButtonBatchJob->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveAsBatchJob ), NULL, this ); - m_listBoxHistory->Connect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this ); - m_listBoxHistory->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this ); - m_listBoxHistory->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistoryDoubleClick ), NULL, this ); - m_listBoxHistory->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnCfgHistoryRightClick ), NULL, this ); - m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this ); - m_bpButtonFilter->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnGlobalFilterContext ), NULL, this ); - m_checkBoxHideExcluded->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnShowExcluded ), NULL, this ); - m_bpButtonViewTypeSyncAction->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewType ), NULL, this ); - m_bpButtonShowCreateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowCreateLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowUpdateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowUpdateLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowDeleteLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowDeleteLeft->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowLeftOnly->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowLeftNewer->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowEqual->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowEqual->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowDifferent->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowDoNothing->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowDoNothing->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowRightNewer->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowRightOnly->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowDeleteRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowDeleteRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowUpdateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowUpdateRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowCreateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowCreateRight->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); - m_bpButtonShowConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnToggleViewButton ), NULL, this ); - m_bpButtonShowConflict->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnViewButtonRightClick ), NULL, this ); -} - -MainDialogGenerated::~MainDialogGenerated() -{ -} - -CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer136; - bSizer136 = new wxBoxSizer( wxVERTICAL ); - - m_panel36 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel36->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer159; - bSizer159 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxVERTICAL ); - - m_staticText91 = new wxStaticText( m_panel36, wxID_ANY, _("Select a variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText91->Wrap( -1 ); - bSizer182->Add( m_staticText91, 0, wxALL, 5 ); - - wxFlexGridSizer* fgSizer16; - fgSizer16 = new wxFlexGridSizer( 2, 2, 5, 5 ); - fgSizer16->SetFlexibleDirection( wxBOTH ); - fgSizer16->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_bitmapByTime = new wxStaticBitmap( m_panel36, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapByTime->SetToolTip( _("Identify equal files by comparing modification time and size.") ); - - fgSizer16->Add( m_bitmapByTime, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_toggleBtnTimeSize = new wxToggleButton( m_panel36, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_toggleBtnTimeSize->SetValue( true ); - m_toggleBtnTimeSize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_toggleBtnTimeSize->SetToolTip( _("Identify equal files by comparing modification time and size.") ); - - fgSizer16->Add( m_toggleBtnTimeSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_bitmapByContent = new wxStaticBitmap( m_panel36, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapByContent->SetToolTip( _("Identify equal files by comparing the file content.") ); - - fgSizer16->Add( m_bitmapByContent, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_toggleBtnContent = new wxToggleButton( m_panel36, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_toggleBtnContent->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_toggleBtnContent->SetToolTip( _("Identify equal files by comparing the file content.") ); - - fgSizer16->Add( m_toggleBtnContent, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer182->Add( fgSizer16, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer159->Add( bSizer182, 0, wxALL, 5 ); - - m_staticline33 = new wxStaticLine( m_panel36, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer159->Add( m_staticline33, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); - - m_staticText92 = new wxStaticText( m_panel36, wxID_ANY, _("Symbolic links:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText92->Wrap( -1 ); - bSizer172->Add( m_staticText92, 0, wxBOTTOM, 5 ); - - wxArrayString m_choiceHandleSymlinksChoices; - m_choiceHandleSymlinks = new wxChoice( m_panel36, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleSymlinksChoices, 0 ); - m_choiceHandleSymlinks->SetSelection( -1 ); - bSizer172->Add( m_choiceHandleSymlinks, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_hyperlink24 = new wxHyperlinkCtrl( m_panel36, wxID_ANY, _("More information"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - bSizer172->Add( m_hyperlink24, 0, wxTOP, 5 ); - - - bSizer159->Add( bSizer172, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 10 ); - - - m_panel36->SetSizer( bSizer159 ); - m_panel36->Layout(); - bSizer159->Fit( m_panel36 ); - bSizer136->Add( m_panel36, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline14 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer136->Add( m_staticline14, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer136->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - - - this->SetSizer( bSizer136 ); - this->Layout(); - bSizer136->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); - m_toggleBtnTimeSize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnTimeSizeDouble ), NULL, this ); - m_toggleBtnTimeSize->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); - m_toggleBtnContent->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnContentDouble ), NULL, this ); - m_toggleBtnContent->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); - m_choiceHandleSymlinks->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); - m_hyperlink24->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( CmpCfgDlgGenerated::OnHelpComparisonSettings ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnCancel ), NULL, this ); -} - -CmpCfgDlgGenerated::~CmpCfgDlgGenerated() -{ -} - -SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer7; - bSizer7 = new wxBoxSizer( wxVERTICAL ); - - m_panel37 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel37->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer29; - bSizer29 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer183; - bSizer183 = new wxBoxSizer( wxVERTICAL ); - - m_staticText86 = new wxStaticText( m_panel37, wxID_ANY, _("Select a variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText86->Wrap( -1 ); - bSizer183->Add( m_staticText86, 0, wxALL, 5 ); - - wxFlexGridSizer* fgSizer1; - fgSizer1 = new wxFlexGridSizer( 4, 2, 5, 5 ); - fgSizer1->SetFlexibleDirection( wxBOTH ); - fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxBoxSizer* bSizer171; - bSizer171 = new wxBoxSizer( wxVERTICAL ); - - - bSizer171->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_toggleBtnTwoWay = new wxToggleButton( m_panel37, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_toggleBtnTwoWay->SetValue( true ); - m_toggleBtnTwoWay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer171->Add( m_toggleBtnTwoWay, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer171->Add( 0, 0, 1, wxEXPAND, 5 ); - - - fgSizer1->Add( bSizer171, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticTextAutomatic = new wxStaticText( m_panel37, wxID_ANY, _("Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextAutomatic->Wrap( 480 ); - fgSizer1->Add( m_staticTextAutomatic, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); - - - bSizer172->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_toggleBtnMirror = new wxToggleButton( m_panel37, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_toggleBtnMirror->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer172->Add( m_toggleBtnMirror, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer172->Add( 0, 0, 1, wxEXPAND, 5 ); - - - fgSizer1->Add( bSizer172, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextMirror = new wxStaticText( m_panel37, wxID_ANY, _("Create a mirror backup of the left folder which exactly matches the right folder after synchronization."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMirror->Wrap( 480 ); - fgSizer1->Add( m_staticTextMirror, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer173; - bSizer173 = new wxBoxSizer( wxVERTICAL ); - - - bSizer173->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_toggleBtnUpdate = new wxToggleButton( m_panel37, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_toggleBtnUpdate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer173->Add( m_toggleBtnUpdate, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer173->Add( 0, 0, 1, wxEXPAND, 5 ); - - - fgSizer1->Add( bSizer173, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticTextUpdate = new wxStaticText( m_panel37, wxID_ANY, _("Copy new and updated files to the right folder."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdate->Wrap( 480 ); - fgSizer1->Add( m_staticTextUpdate, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer1741; - bSizer1741 = new wxBoxSizer( wxVERTICAL ); - - - bSizer1741->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_toggleBtnCustom = new wxToggleButton( m_panel37, wxID_ANY, _("Custom"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_toggleBtnCustom->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer1741->Add( m_toggleBtnCustom, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer1741->Add( 0, 0, 1, wxEXPAND, 5 ); - - - fgSizer1->Add( bSizer1741, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextCustom = new wxStaticText( m_panel37, wxID_ANY, _("Configure your own synchronization rules."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCustom->Wrap( 480 ); - fgSizer1->Add( m_staticTextCustom, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer183->Add( fgSizer1, 0, wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer1751; - bSizer1751 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer1751->Add( 8, 0, 0, 0, 5 ); - - m_checkBoxDetectMove = new wxCheckBox( m_panel37, wxID_ANY, _("Detect moved files"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxDetectMove->SetValue(true); - m_checkBoxDetectMove->SetToolTip( _("Requires database files. Not supported by all file systems.") ); - - bSizer1751->Add( m_checkBoxDetectMove, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - - - bSizer183->Add( bSizer1751, 0, wxEXPAND, 5 ); - - - bSizer29->Add( bSizer183, 0, wxALL, 5 ); - - m_staticline32 = new wxStaticLine( m_panel37, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer29->Add( m_staticline32, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer184; - bSizer184 = new wxBoxSizer( wxVERTICAL ); - - m_staticText87 = new wxStaticText( m_panel37, wxID_ANY, _("Delete files:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText87->Wrap( -1 ); - bSizer184->Add( m_staticText87, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer180; - bSizer180 = new wxBoxSizer( wxHORIZONTAL ); - - m_toggleBtnPermanent = new wxToggleButton( m_panel37, wxID_ANY, _("Permanent"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnPermanent->SetToolTip( _("Delete or overwrite files permanently") ); - - bSizer180->Add( m_toggleBtnPermanent, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_toggleBtnRecycler = new wxToggleButton( m_panel37, wxID_ANY, _("Recycle bin"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnRecycler->SetToolTip( _("Back up deleted and overwritten files in the recycle bin") ); - - bSizer180->Add( m_toggleBtnRecycler, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_toggleBtnVersioning = new wxToggleButton( m_panel37, wxID_ANY, _("Versioning"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnVersioning->SetToolTip( _("Move files to a user-defined folder") ); - - bSizer180->Add( m_toggleBtnVersioning, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer184->Add( bSizer180, 0, wxTOP, 5 ); - - m_panelVersioning = new wxPanel( m_panel37, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelVersioning->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer191; - bSizer191 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer156; - bSizer156 = new wxBoxSizer( wxHORIZONTAL ); - - m_versioningFolder = new FolderHistoryBox( m_panelVersioning, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer156->Add( m_versioningFolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonSelectDirVersioning = new wxButton( m_panelVersioning, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectDirVersioning->SetToolTip( _("Select a folder") ); - - bSizer156->Add( m_buttonSelectDirVersioning, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer191->Add( bSizer156, 1, wxEXPAND|wxBOTTOM, 5 ); - - bSizer192 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText93 = new wxStaticText( m_panelVersioning, wxID_ANY, _("Naming convention:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText93->Wrap( -1 ); - bSizer192->Add( m_staticText93, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - wxArrayString m_choiceVersioningStyleChoices; - m_choiceVersioningStyle = new wxChoice( m_panelVersioning, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVersioningStyleChoices, 0 ); - m_choiceVersioningStyle->SetSelection( 0 ); - bSizer192->Add( m_choiceVersioningStyle, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_staticTextNamingCvtPart1 = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextNamingCvtPart1->Wrap( -1 ); - m_staticTextNamingCvtPart1->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - bSizer192->Add( m_staticTextNamingCvtPart1, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextNamingCvtPart2Bold = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextNamingCvtPart2Bold->Wrap( -1 ); - m_staticTextNamingCvtPart2Bold->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_staticTextNamingCvtPart2Bold->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - bSizer192->Add( m_staticTextNamingCvtPart2Bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextNamingCvtPart3 = new wxStaticText( m_panelVersioning, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextNamingCvtPart3->Wrap( -1 ); - m_staticTextNamingCvtPart3->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - bSizer192->Add( m_staticTextNamingCvtPart3, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer192->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_hyperlink17 = new wxHyperlinkCtrl( m_panelVersioning, wxID_ANY, _("Show examples"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - bSizer192->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - - bSizer191->Add( bSizer192, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - m_panelVersioning->SetSizer( bSizer191 ); - m_panelVersioning->Layout(); - bSizer191->Fit( m_panelVersioning ); - bSizer184->Add( m_panelVersioning, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP, 5 ); - - - bSizer29->Add( bSizer184, 0, wxALL|wxEXPAND, 10 ); - - bSizerExtraConfig = new wxBoxSizer( wxVERTICAL ); - - m_staticline321 = new wxStaticLine( m_panel37, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerExtraConfig->Add( m_staticline321, 0, wxEXPAND, 5 ); - - bSizer179 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer174; - bSizer174 = new wxBoxSizer( wxVERTICAL ); - - m_staticText88 = new wxStaticText( m_panel37, wxID_ANY, _("Handle errors:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText88->Wrap( -1 ); - bSizer174->Add( m_staticText88, 0, wxBOTTOM, 5 ); - - wxBoxSizer* bSizer175; - bSizer175 = new wxBoxSizer( wxHORIZONTAL ); - - m_toggleBtnErrorIgnore = new wxToggleButton( m_panel37, wxID_ANY, _("Ignore"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnErrorIgnore->SetToolTip( _("Hide all error and warning messages") ); - - bSizer175->Add( m_toggleBtnErrorIgnore, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_toggleBtnErrorPopup = new wxToggleButton( m_panel37, wxID_ANY, _("Pop-up"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnErrorPopup->SetToolTip( _("Show pop-up on errors or warnings") ); - - bSizer175->Add( m_toggleBtnErrorPopup, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer174->Add( bSizer175, 0, 0, 5 ); - - - bSizer179->Add( bSizer174, 0, wxALL, 10 ); - - m_staticline36 = new wxStaticLine( m_panel37, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer179->Add( m_staticline36, 0, wxEXPAND, 5 ); - - bSizerOnCompletion = new wxBoxSizer( wxVERTICAL ); - - m_staticText89 = new wxStaticText( m_panel37, wxID_ANY, _("On completion:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText89->Wrap( -1 ); - bSizerOnCompletion->Add( m_staticText89, 0, wxBOTTOM, 5 ); - - m_comboBoxExecFinished = new ExecFinishedBox( m_panel37, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizerOnCompletion->Add( m_comboBoxExecFinished, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer179->Add( bSizerOnCompletion, 1, wxALL, 10 ); - - - bSizerExtraConfig->Add( bSizer179, 0, wxEXPAND, 5 ); - - - bSizer29->Add( bSizerExtraConfig, 0, wxEXPAND, 5 ); - - - bSizer181->Add( bSizer29, 0, wxEXPAND, 5 ); - - m_staticline31 = new wxStaticLine( m_panel37, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer181->Add( m_staticline31, 0, wxEXPAND, 5 ); - - bSizerConfig = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer18011; - bSizer18011 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextHeaderCategory1 = new wxStaticText( m_panel37, wxID_ANY, _("Category"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); - m_staticTextHeaderCategory1->Wrap( -1 ); - bSizer18011->Add( m_staticTextHeaderCategory1, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer18011->Add( 5, 0, 0, 0, 5 ); - - m_staticTextHeaderAction1 = new wxStaticText( m_panel37, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT ); - m_staticTextHeaderAction1->Wrap( -1 ); - bSizer18011->Add( m_staticTextHeaderAction1, 1, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerConfig->Add( bSizer18011, 0, wxEXPAND, 5 ); - - - bSizerConfig->Add( 0, 5, 0, 0, 5 ); - - m_bitmapDatabase = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerConfig->Add( m_bitmapDatabase, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 10 ); - - wxBoxSizer* sbSizerKeepWidthStableIfSyncDirsNotShown; - sbSizerKeepWidthStableIfSyncDirsNotShown = new wxBoxSizer( wxHORIZONTAL ); - - - sbSizerKeepWidthStableIfSyncDirsNotShown->Add( 45, 0, 0, 0, 5 ); - - - sbSizerKeepWidthStableIfSyncDirsNotShown->Add( 5, 0, 0, 0, 5 ); - - - sbSizerKeepWidthStableIfSyncDirsNotShown->Add( 46, 0, 0, 0, 5 ); - - - bSizerConfig->Add( sbSizerKeepWidthStableIfSyncDirsNotShown, 0, 0, 5 ); - - sbSizerSyncDirections = new wxBoxSizer( wxVERTICAL ); - - bSizerLeftOnly = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeftOnly = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapLeftOnly->SetToolTip( _("Item exists on left side only") ); - - bSizerLeftOnly->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerLeftOnly->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLeftOnly = new wxBitmapButton( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - bSizerLeftOnly->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizerSyncDirections->Add( bSizerLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizerRightOnly = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapRightOnly = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapRightOnly->SetToolTip( _("Item exists on right side only") ); - - bSizerRightOnly->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerRightOnly->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonRightOnly = new wxBitmapButton( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - bSizerRightOnly->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizerSyncDirections->Add( bSizerRightOnly, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizerLeftNewer = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeftNewer = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapLeftNewer->SetToolTip( _("Left side is newer") ); - - bSizerLeftNewer->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerLeftNewer->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonLeftNewer = new wxBitmapButton( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - bSizerLeftNewer->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizerSyncDirections->Add( bSizerLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizerRightNewer = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapRightNewer = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapRightNewer->SetToolTip( _("Right side is newer") ); - - bSizerRightNewer->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerRightNewer->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonRightNewer = new wxBitmapButton( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - bSizerRightNewer->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizerSyncDirections->Add( bSizerRightNewer, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizerDifferent = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapDifferent = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapDifferent->SetToolTip( _("Items have different content") ); - - bSizerDifferent->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerDifferent->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonDifferent = new wxBitmapButton( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - bSizerDifferent->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizerSyncDirections->Add( bSizerDifferent, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizerConflict = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapConflict = new wxStaticBitmap( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapConflict->SetToolTip( _("Conflict/item cannot be categorized") ); - - bSizerConflict->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerConflict->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonConflict = new wxBitmapButton( m_panel37, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 46,46 ), wxBU_AUTODRAW ); - bSizerConflict->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizerSyncDirections->Add( bSizerConflict, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizerConfig->Add( sbSizerSyncDirections, 0, wxEXPAND, 5 ); - - - bSizer181->Add( bSizerConfig, 0, wxALL|wxEXPAND, 10 ); - - - m_panel37->SetSizer( bSizer181 ); - m_panel37->Layout(); - bSizer181->Fit( m_panel37 ); - bSizer7->Add( m_panel37, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline15 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer7->Add( m_staticline15, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonOK = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOK->SetDefault(); - m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer7->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - - - this->SetSizer( bSizer7 ); - this->Layout(); - bSizer7->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); - m_toggleBtnTwoWay->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncTwoWayDouble ), NULL, this ); - m_toggleBtnTwoWay->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncTwoWay ), NULL, this ); - m_toggleBtnMirror->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncMirrorDouble ), NULL, this ); - m_toggleBtnMirror->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); - m_toggleBtnUpdate->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncUpdateDouble ), NULL, this ); - m_toggleBtnUpdate->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); - m_toggleBtnCustom->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncCustomDouble ), NULL, this ); - m_toggleBtnCustom->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); - m_checkBoxDetectMove->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnToggleDetectMovedFiles ), NULL, this ); - m_toggleBtnPermanent->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDeletionPermanent ), NULL, this ); - m_toggleBtnRecycler->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDeletionRecycler ), NULL, this ); - m_toggleBtnVersioning->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDeletionVersioning ), NULL, this ); - m_choiceVersioningStyle->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnParameterChange ), NULL, this ); - m_hyperlink17->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( SyncCfgDlgGenerated::OnHelpVersioning ), NULL, this ); - m_toggleBtnErrorIgnore->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnErrorIgnore ), NULL, this ); - m_toggleBtnErrorPopup->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnErrorPopup ), NULL, this ); - m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExLeftSideOnly ), NULL, this ); - m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExRightSideOnly ), NULL, this ); - m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnLeftNewer ), NULL, this ); - m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnRightNewer ), NULL, this ); - m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDifferent ), NULL, this ); - m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnConflict ), NULL, this ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnCancel ), NULL, this ); -} - -SyncCfgDlgGenerated::~SyncCfgDlgGenerated() -{ -} - -SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapSync = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapSync, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("Start synchronization now?"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( -1 ); - bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - - - bSizer134->Add( bSizer72, 0, 0, 5 ); - - m_staticline371 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline371, 0, wxEXPAND, 5 ); - - m_panelStatistics = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer185->Add( 0, 0, 1, 0, 5 ); - - m_staticline38 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer185->Add( m_staticline38, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer162; - bSizer162 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer182; - bSizer182 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText84 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText84->Wrap( -1 ); - bSizer182->Add( m_staticText84, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - - bSizer182->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextVariant = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextVariant->Wrap( -1 ); - m_staticTextVariant->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer182->Add( m_staticTextVariant, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - bSizer182->Add( 0, 0, 1, wxEXPAND, 5 ); - - - bSizer162->Add( bSizer182, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); - - m_staticline14 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer162->Add( m_staticline14, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxVERTICAL ); - - m_staticText83 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Statistics"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText83->Wrap( -1 ); - bSizer181->Add( m_staticText83, 0, wxALL, 5 ); - - wxFlexGridSizer* fgSizer11; - fgSizer11 = new wxFlexGridSizer( 2, 7, 2, 5 ); - fgSizer11->SetFlexibleDirection( wxBOTH ); - fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - - fgSizer11->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer11->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - - fgSizer11->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapData->SetToolTip( _("Total bytes to copy") ); - - fgSizer11->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - - fgSizer11->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdateRight->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer11->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - - fgSizer11->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateLeft->Wrap( -1 ); - m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") ); - - fgSizer11->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateLeft->Wrap( -1 ); - m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer11->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteLeft->Wrap( -1 ); - m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") ); - - fgSizer11->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextData->Wrap( -1 ); - m_staticTextData->SetToolTip( _("Total bytes to copy") ); - - fgSizer11->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDeleteRight->Wrap( -1 ); - m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") ); - - fgSizer11->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextUpdateRight->Wrap( -1 ); - m_staticTextUpdateRight->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer11->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCreateRight->Wrap( -1 ); - m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") ); - - fgSizer11->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer181->Add( fgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer162->Add( bSizer181, 0, wxEXPAND|wxALL, 5 ); - - - bSizer185->Add( bSizer162, 0, 0, 5 ); - - - m_panelStatistics->SetSizer( bSizer185 ); - m_panelStatistics->Layout(); - bSizer185->Fit( m_panelStatistics ); - bSizer134->Add( m_panelStatistics, 0, wxEXPAND, 5 ); - - m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer164; - bSizer164 = new wxBoxSizer( wxVERTICAL ); - - m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("&Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer164->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonStartSync = new wxButton( this, wxID_OK, _("&Start"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonStartSync->SetDefault(); - m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer164->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - - - bSizer134->Add( bSizer164, 1, wxEXPAND, 5 ); - - - this->SetSizer( bSizer134 ); - this->Layout(); - bSizer134->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::OnClose ) ); - m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnStartSync ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnCancel ), NULL, this ); -} - -SyncConfirmationDlgGenerated::~SyncConfirmationDlgGenerated() -{ -} - -FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer74; - bSizer74 = new wxBoxSizer( wxHORIZONTAL ); - - m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelLeft->SetMinSize( wxSize( 1,-1 ) ); - - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - - bSizer134->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_directoryLeft = new FolderHistoryBox( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer134->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonSelectDirLeft = new wxButton( m_panelLeft, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectDirLeft->SetToolTip( _("Select a folder") ); - - bSizer134->Add( m_buttonSelectDirLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - m_panelLeft->SetSizer( bSizer134 ); - m_panelLeft->Layout(); - bSizer134->Fit( m_panelLeft ); - bSizer74->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxEXPAND, 5 ); - - m_panel20 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer95->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bpButtonAltCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer95->Add( m_bpButtonAltCompCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer95->Add( m_bpButtonLocalFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 2 ); - - m_bpButtonAltSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer95->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer95->Add( 0, 0, 1, wxEXPAND, 5 ); - - - m_panel20->SetSizer( bSizer95 ); - m_panel20->Layout(); - bSizer95->Fit( m_panel20 ); - bSizer74->Add( m_panel20, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelRight->SetMinSize( wxSize( 1,-1 ) ); - - wxBoxSizer* bSizer135; - bSizer135 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryRight = new FolderHistoryBox( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer135->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonSelectDirRight = new wxButton( m_panelRight, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectDirRight->SetToolTip( _("Select a folder") ); - - bSizer135->Add( m_buttonSelectDirRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - m_panelRight->SetSizer( bSizer135 ); - m_panelRight->Layout(); - bSizer135->Fit( m_panelRight ); - bSizer74->Add( m_panelRight, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, 5 ); - - - this->SetSizer( bSizer74 ); - this->Layout(); - bSizer74->Fit( this ); -} - -FolderPairPanelGenerated::~FolderPairPanelGenerated() -{ -} - -CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer40; - bSizer40 = new wxBoxSizer( wxVERTICAL ); - - - bSizer40->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, wxTE_READONLY ); - m_textCtrlStatus->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - bSizer40->Add( m_textCtrlStatus, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); - bSizer40->Add( m_gauge2, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer162StretchSpeedAndRemTimeIndependently; - bSizer162StretchSpeedAndRemTimeIndependently = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer157; - bSizer157 = new wxBoxSizer( wxVERTICAL ); - - bSizerFilesFound = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText321 = new wxStaticText( this, wxID_ANY, _("Items found:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText321->Wrap( -1 ); - bSizerFilesFound->Add( m_staticText321, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextScanned->Wrap( -1 ); - m_staticTextScanned->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerFilesFound->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - - bSizer157->Add( bSizerFilesFound, 0, 0, 5 ); - - bSizerFilesRemaining = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText46 = new wxStaticText( this, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText46->Wrap( -1 ); - bSizerFilesRemaining->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 ); - - wxBoxSizer* bSizer154; - bSizer154 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFilesRemaining->Wrap( -1 ); - m_staticTextFilesRemaining->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer154->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDataRemaining->Wrap( -1 ); - bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - - bSizerFilesRemaining->Add( bSizer154, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - - bSizer157->Add( bSizerFilesRemaining, 0, 0, 5 ); - - - bSizer162StretchSpeedAndRemTimeIndependently->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer162StretchSpeedAndRemTimeIndependently->Add( 0, 0, 1, wxEXPAND, 5 ); - - sSizerSpeed = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText104->Wrap( -1 ); - sSizerSpeed->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSpeed->Wrap( -1 ); - m_staticTextSpeed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - sSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - - bSizer162StretchSpeedAndRemTimeIndependently->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( bSizer162StretchSpeedAndRemTimeIndependently, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer163; - bSizer163 = new wxBoxSizer( wxHORIZONTAL ); - - sSizerTimeRemaining = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextTimeRemFixed = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeRemFixed->Wrap( -1 ); - sSizerTimeRemaining->Add( m_staticTextTimeRemFixed, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextRemTime = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRemTime->Wrap( -1 ); - m_staticTextRemTime->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - sSizerTimeRemaining->Add( m_staticTextRemTime, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - - bSizer163->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer163->Add( 0, 0, 1, wxEXPAND, 5 ); - - sSizerTimeElapsed = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText37; - m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText37->Wrap( -1 ); - sSizerTimeElapsed->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - sSizerTimeElapsed->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - - bSizer163->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( bSizer163, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - - - bSizer40->Add( 0, 0, 1, wxEXPAND, 5 ); - - - this->SetSizer( bSizer40 ); - this->Layout(); - bSizer40->Fit( this ); -} - -CompareProgressDlgGenerated::~CompareProgressDlgGenerated() -{ -} - -SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - bSizerRoot = new wxBoxSizer( wxVERTICAL ); - - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer42->Add( 32, 0, 0, 0, 5 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bitmapStatus = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), 0 ); - bSizer42->Add( m_bitmapStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); - - m_staticTextPhase = new wxStaticText( this, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextPhase->Wrap( -1 ); - m_staticTextPhase->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer42->Add( m_staticTextPhase, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 ); - - m_animCtrlSyncing = new wxAnimationCtrl( this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 32,32 ), wxAC_DEFAULT_STYLE ); - bSizer42->Add( m_animCtrlSyncing, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bpButtonMinimizeToTray = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), wxBU_AUTODRAW ); - m_bpButtonMinimizeToTray->SetToolTip( _("Minimize to notification area") ); - - bSizer42->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerRoot->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - bSizerStatusText = new wxBoxSizer( wxVERTICAL ); - - m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatus->Wrap( -1 ); - bSizerStatusText->Add( m_staticTextStatus, 0, wxEXPAND|wxLEFT, 10 ); - - - bSizerStatusText->Add( 0, 5, 0, 0, 5 ); - - - bSizerRoot->Add( bSizerStatusText, 0, wxEXPAND, 5 ); - - wxStaticLine* m_staticlineHeader; - m_staticlineHeader = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerRoot->Add( m_staticlineHeader, 0, wxEXPAND, 5 ); - - m_panelProgress = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelProgress->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer173; - bSizer173 = new wxBoxSizer( wxVERTICAL ); - - bSizer171 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer171->Add( 10, 0, 0, 0, 5 ); - - wxBoxSizer* bSizer164; - bSizer164 = new wxBoxSizer( wxVERTICAL ); - - m_panelItemsProcessed = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelItemsProcessed->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer165; - bSizer165 = new wxBoxSizer( wxVERTICAL ); - - - bSizer165->Add( 0, 5, 0, 0, 5 ); - - wxStaticText* m_staticText96; - m_staticText96 = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("Items processed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText96->Wrap( -1 ); - bSizer165->Add( m_staticText96, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer169; - bSizer169 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextProcessedObj = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextProcessedObj->Wrap( -1 ); - m_staticTextProcessedObj->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer169->Add( m_staticTextProcessedObj, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextDataProcessed = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDataProcessed->Wrap( -1 ); - bSizer169->Add( m_staticTextDataProcessed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - - bSizer165->Add( bSizer169, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer165->Add( 0, 5, 0, 0, 5 ); - - - m_panelItemsProcessed->SetSizer( bSizer165 ); - m_panelItemsProcessed->Layout(); - bSizer165->Fit( m_panelItemsProcessed ); - bSizer164->Add( m_panelItemsProcessed, 0, wxEXPAND|wxTOP, 7 ); - - m_panelItemsRemaining = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelItemsRemaining->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxVERTICAL ); - - - bSizer166->Add( 0, 5, 0, 0, 5 ); - - wxStaticText* m_staticText97; - m_staticText97 = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText97->Wrap( -1 ); - bSizer166->Add( m_staticText97, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer170; - bSizer170 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextRemainingObj = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextRemainingObj->Wrap( -1 ); - m_staticTextRemainingObj->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer170->Add( m_staticTextRemainingObj, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextDataRemaining = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDataRemaining->Wrap( -1 ); - bSizer170->Add( m_staticTextDataRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - - bSizer166->Add( bSizer170, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer166->Add( 0, 5, 0, 0, 5 ); - - - m_panelItemsRemaining->SetSizer( bSizer166 ); - m_panelItemsRemaining->Layout(); - bSizer166->Fit( m_panelItemsRemaining ); - bSizer164->Add( m_panelItemsRemaining, 0, wxTOP|wxEXPAND, 7 ); - - m_panelTimeRemaining = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelTimeRemaining->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer167; - bSizer167 = new wxBoxSizer( wxVERTICAL ); - - - bSizer167->Add( 0, 5, 0, 0, 5 ); - - wxStaticText* m_staticText98; - m_staticText98 = new wxStaticText( m_panelTimeRemaining, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText98->Wrap( -1 ); - bSizer167->Add( m_staticText98, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_staticTextRemTime = new wxStaticText( m_panelTimeRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRemTime->Wrap( -1 ); - m_staticTextRemTime->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer167->Add( m_staticTextRemTime, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer167->Add( 0, 5, 0, 0, 5 ); - - - m_panelTimeRemaining->SetSizer( bSizer167 ); - m_panelTimeRemaining->Layout(); - bSizer167->Fit( m_panelTimeRemaining ); - bSizer164->Add( m_panelTimeRemaining, 0, wxTOP|wxEXPAND, 7 ); - - wxPanel* m_panelTimeElapsed; - m_panelTimeElapsed = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelTimeElapsed->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer168; - bSizer168 = new wxBoxSizer( wxVERTICAL ); - - - bSizer168->Add( 0, 5, 0, 0, 5 ); - - wxStaticText* m_staticText961; - m_staticText961 = new wxStaticText( m_panelTimeElapsed, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText961->Wrap( -1 ); - bSizer168->Add( m_staticText961, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_staticTextTimeElapsed = new wxStaticText( m_panelTimeElapsed, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer168->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer168->Add( 0, 5, 0, 0, 5 ); - - - m_panelTimeElapsed->SetSizer( bSizer168 ); - m_panelTimeElapsed->Layout(); - bSizer168->Fit( m_panelTimeElapsed ); - bSizer164->Add( m_panelTimeElapsed, 0, wxTOP|wxEXPAND, 7 ); - - - bSizer171->Add( bSizer164, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer171->Add( 10, 0, 0, 0, 5 ); - - wxBoxSizer* bSizer161; - bSizer161 = new wxBoxSizer( wxVERTICAL ); - - - bSizer161->Add( 0, 15, 0, 0, 5 ); - - m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_panelGraphBytes->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - bSizer161->Add( m_panelGraphBytes, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_panelGraphItems = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_panelGraphItems->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - bSizer161->Add( m_panelGraphItems, 1, wxEXPAND, 5 ); - - - bSizer161->Add( 430, 0, 0, 0, 5 ); - - - bSizer171->Add( bSizer161, 1, wxEXPAND, 5 ); - - - bSizer171->Add( 0, 230, 0, 0, 5 ); - - - bSizer173->Add( bSizer171, 1, wxEXPAND, 5 ); - - - m_panelProgress->SetSizer( bSizer173 ); - m_panelProgress->Layout(); - bSizer173->Fit( m_panelProgress ); - bSizerRoot->Add( m_panelProgress, 1, wxEXPAND, 5 ); - - m_notebookResult = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_FIXEDWIDTH ); - - bSizerRoot->Add( m_notebookResult, 1, wxEXPAND, 5 ); - - m_staticlineFooter = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizerRoot->Add( m_staticlineFooter, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxHORIZONTAL ); - - bSizerExecFinished = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText87 = new wxStaticText( this, wxID_ANY, _("On completion:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText87->Wrap( -1 ); - bSizerExecFinished->Add( m_staticText87, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_comboBoxExecFinished = new ExecFinishedBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizerExecFinished->Add( m_comboBoxExecFinished, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer160->Add( bSizerExecFinished, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer160->Add( 0, 0, 0, 0, 5 ); - - - bSizerStdButtons->Add( bSizer160, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonClose->SetDefault(); - m_buttonClose->Enable( false ); - - bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - m_buttonStop = new wxButton( this, wxID_CANCEL, _("Stop"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonStop, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizerRoot->Add( bSizerStdButtons, 0, wxALIGN_RIGHT|wxEXPAND, 5 ); - - - this->SetSizer( bSizerRoot ); - this->Layout(); - bSizerRoot->Fit( this ); -} - -SyncProgressPanelGenerated::~SyncProgressPanelGenerated() -{ -} - -LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer179; - bSizer179 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer153; - bSizer153 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer154; - bSizer154 = new wxBoxSizer( wxVERTICAL ); - - m_bpButtonErrors = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW ); - bSizer154->Add( m_bpButtonErrors, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonWarnings = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW ); - bSizer154->Add( m_bpButtonWarnings, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonInfo = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW ); - bSizer154->Add( m_bpButtonInfo, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer153->Add( bSizer154, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer153->Add( m_staticline13, 0, wxEXPAND, 5 ); - - m_gridMessages = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_gridMessages->SetScrollRate( 5, 5 ); - bSizer153->Add( m_gridMessages, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer179->Add( bSizer153, 1, wxEXPAND, 5 ); - - - this->SetSizer( bSizer179 ); - this->Layout(); - bSizer179->Fit( this ); - - // Connect Events - m_bpButtonErrors->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::OnErrors ), NULL, this ); - m_bpButtonWarnings->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::OnWarnings ), NULL, this ); - m_bpButtonInfo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LogPanelGenerated::OnInfo ), NULL, this ); -} - -LogPanelGenerated::~LogPanelGenerated() -{ -} - -BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer54; - bSizer54 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapBatchJob = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer72->Add( m_bitmapBatchJob, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - - m_staticTextDescr = new wxStaticText( this, wxID_ANY, _("Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDescr->Wrap( 520 ); - bSizer72->Add( m_staticTextDescr, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - - - bSizer54->Add( bSizer72, 0, 0, 5 ); - - m_staticline18 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline18, 0, wxEXPAND, 5 ); - - m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer180; - bSizer180 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer171; - bSizer171 = new wxBoxSizer( wxVERTICAL ); - - m_staticText82 = new wxStaticText( m_panel35, wxID_ANY, _("Handle errors:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText82->Wrap( -1 ); - bSizer171->Add( m_staticText82, 0, wxALL, 5 ); - - wxBoxSizer* bSizer169; - bSizer169 = new wxBoxSizer( wxHORIZONTAL ); - - m_toggleBtnErrorIgnore = new wxToggleButton( m_panel35, wxID_ANY, _("Ignore"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnErrorIgnore->SetToolTip( _("Hide all error and warning messages") ); - - bSizer169->Add( m_toggleBtnErrorIgnore, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_toggleBtnErrorPopup = new wxToggleButton( m_panel35, wxID_ANY, _("Pop-up"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnErrorPopup->SetToolTip( _("Show pop-up on errors or warnings") ); - - bSizer169->Add( m_toggleBtnErrorPopup, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_toggleBtnErrorStop = new wxToggleButton( m_panel35, wxID_ANY, _("Stop"), wxDefaultPosition, wxDefaultSize, 0 ); - m_toggleBtnErrorStop->SetToolTip( _("Stop synchronization at first error") ); - - bSizer169->Add( m_toggleBtnErrorStop, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer171->Add( bSizer169, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer180->Add( bSizer171, 0, wxALL, 5 ); - - m_staticline26 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer180->Add( m_staticline26, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer170; - bSizer170 = new wxBoxSizer( wxVERTICAL ); - - m_checkBoxShowProgress = new wxCheckBox( m_panel35, wxID_ANY, _("Show progress dialog"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer170->Add( m_checkBoxShowProgress, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer179; - bSizer179 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText81 = new wxStaticText( m_panel35, wxID_ANY, _("On completion:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText81->Wrap( -1 ); - bSizer179->Add( m_staticText81, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_comboBoxExecFinished = new ExecFinishedBox( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer179->Add( m_comboBoxExecFinished, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer170->Add( bSizer179, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer180->Add( bSizer170, 1, wxALL, 5 ); - - - bSizer172->Add( bSizer180, 0, wxEXPAND, 5 ); - - m_staticline25 = new wxStaticLine( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer172->Add( m_staticline25, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer191; - bSizer191 = new wxBoxSizer( wxVERTICAL ); - - m_checkBoxGenerateLogfile = new wxCheckBox( m_panel35, wxID_ANY, _("Save log:"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer191->Add( m_checkBoxGenerateLogfile, 0, wxEXPAND|wxBOTTOM, 5 ); - - m_panelLogfile = new wxPanel( m_panel35, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelLogfile->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer1721; - bSizer1721 = new wxBoxSizer( wxHORIZONTAL ); - - m_logfileDir = new FolderHistoryBox( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - bSizer1721->Add( m_logfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonSelectLogfileDir = new wxButton( m_panelLogfile, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonSelectLogfileDir->SetToolTip( _("Select a folder") ); - - bSizer1721->Add( m_buttonSelectLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_checkBoxLogfilesLimit = new wxCheckBox( m_panelLogfile, wxID_ANY, _("Limit:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxLogfilesLimit->SetToolTip( _("Limit maximum number of log files") ); - - bSizer1721->Add( m_checkBoxLogfilesLimit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_spinCtrlLogfileLimit = new wxSpinCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 ); - m_spinCtrlLogfileLimit->SetToolTip( _("Limit maximum number of log files") ); - - bSizer1721->Add( m_spinCtrlLogfileLimit, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - m_panelLogfile->SetSizer( bSizer1721 ); - m_panelLogfile->Layout(); - bSizer1721->Fit( m_panelLogfile ); - bSizer191->Add( m_panelLogfile, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer172->Add( bSizer191, 0, wxEXPAND|wxALL, 10 ); - - m_hyperlink17 = new wxHyperlinkCtrl( m_panel35, wxID_ANY, _("How can I schedule a batch job?"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - bSizer172->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - - - m_panel35->SetSizer( bSizer172 ); - m_panel35->Layout(); - bSizer172->Fit( m_panel35 ); - bSizer54->Add( m_panel35, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer54->Add( m_staticline13, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - - bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_buttonSaveAs = new wxButton( this, wxID_SAVE, _("Save &as..."), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonSaveAs->SetDefault(); - m_buttonSaveAs->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonSaveAs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer54->Add( bSizerStdButtons, 0, wxALIGN_RIGHT|wxEXPAND, 5 ); - - - this->SetSizer( bSizer54 ); - this->Layout(); - bSizer54->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::OnClose ) ); - m_toggleBtnErrorIgnore->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnErrorIgnore ), NULL, this ); - m_toggleBtnErrorPopup->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnErrorPopup ), NULL, this ); - m_toggleBtnErrorStop->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnErrorStop ), NULL, this ); - m_checkBoxGenerateLogfile->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnToggleGenerateLogfile ), NULL, this ); - m_checkBoxLogfilesLimit->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnToggleLogfilesLimit ), NULL, this ); - m_hyperlink17->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( BatchDlgGenerated::OnHelpScheduleBatch ), NULL, this ); - m_buttonSaveAs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); -} - -BatchDlgGenerated::~BatchDlgGenerated() -{ -} - -DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapDeleteType = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer72->Add( m_bitmapDeleteType, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0|wxNO_BORDER ); - m_staticTextHeader->Wrap( -1 ); - bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - - - bSizer24->Add( bSizer72, 0, 0, 5 ); - - m_staticline91 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline91, 0, wxEXPAND, 5 ); - - m_panel31 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel31->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer185->Add( 60, 0, 0, 0, 5 ); - - m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 ); - - m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 480,200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER ); - bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - m_panel31->SetSizer( bSizer185 ); - m_panel31->Layout(); - bSizer185->Fit( m_panel31 ); - bSizer24->Add( m_panel31, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer99; - bSizer99 = new wxBoxSizer( wxVERTICAL ); - - m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("&Recycle bin"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer99->Add( m_checkBoxUseRecycler, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_checkBoxDeleteBothSides = new wxCheckBox( this, wxID_ANY, _("Delete on both sides"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxDeleteBothSides->Hide(); - m_checkBoxDeleteBothSides->SetToolTip( _("Delete on both sides even if the file is selected on one side only") ); - - bSizer99->Add( m_checkBoxDeleteBothSides, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM|wxLEFT, 5 ); - - - bSizerStdButtons->Add( bSizer99, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonOK = new wxButton( this, wxID_OK, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOK->SetDefault(); - m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer24->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - - - this->SetSizer( bSizer24 ); - this->Layout(); - bSizer24->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::OnClose ) ); - m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnUseRecycler ), NULL, this ); - m_checkBoxDeleteBothSides->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnDelOnBothSides ), NULL, this ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnOK ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnCancel ), NULL, this ); -} - -DeleteDlgGenerated::~DeleteDlgGenerated() -{ -} - -FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer21; - bSizer21 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapFilter = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer72->Add( m_bitmapFilter, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - - m_staticText44 = new wxStaticText( this, wxID_ANY, _("Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticText44->Wrap( 480 ); - bSizer72->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - - - bSizer21->Add( bSizer72, 0, 0, 5 ); - - m_staticline17 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer21->Add( m_staticline17, 0, wxEXPAND, 5 ); - - m_panel38 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel38->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer159; - bSizer159 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxVERTICAL ); - - - bSizer166->Add( 0, 10, 0, 0, 5 ); - - wxBoxSizer* bSizer1661; - bSizer1661 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapInclude = new wxStaticBitmap( m_panel38, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); - bSizer1661->Add( m_bitmapInclude, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - wxBoxSizer* bSizer173; - bSizer173 = new wxBoxSizer( wxVERTICAL ); - - m_staticText78 = new wxStaticText( m_panel38, wxID_ANY, _("Include:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText78->Wrap( -1 ); - bSizer173->Add( m_staticText78, 0, 0, 5 ); - - m_textCtrlInclude = new wxTextCtrl( m_panel38, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - m_textCtrlInclude->SetMinSize( wxSize( 280,-1 ) ); - - bSizer173->Add( m_textCtrlInclude, 1, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 5 ); - - - bSizer1661->Add( bSizer173, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer166->Add( bSizer1661, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxLEFT, 5 ); - - m_staticline22 = new wxStaticLine( m_panel38, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline22, 0, wxEXPAND, 5 ); - - - bSizer166->Add( 0, 10, 0, 0, 5 ); - - wxBoxSizer* bSizer1651; - bSizer1651 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapExclude = new wxStaticBitmap( m_panel38, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); - bSizer1651->Add( m_bitmapExclude, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - wxBoxSizer* bSizer174; - bSizer174 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer189; - bSizer189 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText77 = new wxStaticText( m_panel38, wxID_ANY, _("Exclude:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText77->Wrap( -1 ); - bSizer189->Add( m_staticText77, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer189->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_hyperlink17 = new wxHyperlinkCtrl( m_panel38, wxID_ANY, _("Show examples"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - bSizer189->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - - bSizer174->Add( bSizer189, 0, wxEXPAND, 5 ); - - m_textCtrlExclude = new wxTextCtrl( m_panel38, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - bSizer174->Add( m_textCtrlExclude, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP, 5 ); - - - bSizer1651->Add( bSizer174, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer166->Add( bSizer1651, 2, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxLEFT, 5 ); - - - bSizer159->Add( bSizer166, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticline24 = new wxStaticLine( m_panel38, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer159->Add( m_staticline24, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer167; - bSizer167 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapFilterDate = new wxStaticBitmap( m_panel38, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 34,34 ), 0 ); - bSizer167->Add( m_bitmapFilterDate, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - wxBoxSizer* bSizer165; - bSizer165 = new wxBoxSizer( wxVERTICAL ); - - m_staticText79 = new wxStaticText( m_panel38, wxID_ANY, _("Time span:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText79->Wrap( -1 ); - bSizer165->Add( m_staticText79, 0, wxBOTTOM, 5 ); - - m_spinCtrlTimespan = new wxSpinCtrl( m_panel38, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer165->Add( m_spinCtrlTimespan, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxArrayString m_choiceUnitTimespanChoices; - m_choiceUnitTimespan = new wxChoice( m_panel38, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitTimespanChoices, 0 ); - m_choiceUnitTimespan->SetSelection( 0 ); - bSizer165->Add( m_choiceUnitTimespan, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer167->Add( bSizer165, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer160->Add( bSizer167, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); - - m_staticline23 = new wxStaticLine( m_panel38, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer160->Add( m_staticline23, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer168; - bSizer168 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapFilterSize = new wxStaticBitmap( m_panel38, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), 0 ); - bSizer168->Add( m_bitmapFilterSize, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxVERTICAL ); - - m_staticText80 = new wxStaticText( m_panel38, wxID_ANY, _("File size:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText80->Wrap( -1 ); - bSizer158->Add( m_staticText80, 0, wxBOTTOM, 5 ); - - wxBoxSizer* bSizer162; - bSizer162 = new wxBoxSizer( wxVERTICAL ); - - m_staticText101 = new wxStaticText( m_panel38, wxID_ANY, _("Minimum:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText101->Wrap( -1 ); - bSizer162->Add( m_staticText101, 0, wxBOTTOM, 2 ); - - m_spinCtrlMinSize = new wxSpinCtrl( m_panel38, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer162->Add( m_spinCtrlMinSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxArrayString m_choiceUnitMinSizeChoices; - m_choiceUnitMinSize = new wxChoice( m_panel38, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMinSizeChoices, 0 ); - m_choiceUnitMinSize->SetSelection( 0 ); - bSizer162->Add( m_choiceUnitMinSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer158->Add( bSizer162, 0, wxBOTTOM|wxEXPAND, 5 ); - - wxBoxSizer* bSizer163; - bSizer163 = new wxBoxSizer( wxVERTICAL ); - - m_staticText102 = new wxStaticText( m_panel38, wxID_ANY, _("Maximum:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText102->Wrap( -1 ); - bSizer163->Add( m_staticText102, 0, wxBOTTOM, 2 ); - - m_spinCtrlMaxSize = new wxSpinCtrl( m_panel38, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer163->Add( m_spinCtrlMaxSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxArrayString m_choiceUnitMaxSizeChoices; - m_choiceUnitMaxSize = new wxChoice( m_panel38, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMaxSizeChoices, 0 ); - m_choiceUnitMaxSize->SetSelection( 0 ); - bSizer163->Add( m_choiceUnitMaxSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer158->Add( bSizer163, 0, wxEXPAND, 5 ); - - - bSizer168->Add( bSizer158, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer160->Add( bSizer168, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); - - - bSizer159->Add( bSizer160, 0, wxEXPAND, 5 ); - - - m_panel38->SetSizer( bSizer159 ); - m_panel38->Layout(); - bSizer159->Fit( m_panel38 ); - bSizer21->Add( m_panel38, 1, wxEXPAND, 5 ); - - m_staticline16 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer21->Add( m_staticline16, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonClear = new wxButton( this, wxID_DEFAULT, _("&Clear"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonClear, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); - - - bSizerStdButtons->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonOk = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOk->SetDefault(); - m_buttonOk->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonOk, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer21->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - - - this->SetSizer( bSizer21 ); - this->Layout(); - bSizer21->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); - m_textCtrlInclude->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( FilterDlgGenerated::OnUpdateNameFilter ), NULL, this ); - m_hyperlink17->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( FilterDlgGenerated::OnHelpShowExamples ), NULL, this ); - m_textCtrlExclude->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( FilterDlgGenerated::OnUpdateNameFilter ), NULL, this ); - m_choiceUnitTimespan->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( FilterDlgGenerated::OnUpdateChoice ), NULL, this ); - m_choiceUnitMinSize->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( FilterDlgGenerated::OnUpdateChoice ), NULL, this ); - m_choiceUnitMaxSize->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( FilterDlgGenerated::OnUpdateChoice ), NULL, this ); - m_buttonClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnClear ), NULL, this ); - m_buttonOk->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnCancel ), NULL, this ); -} - -FilterDlgGenerated::~FilterDlgGenerated() -{ -} - -GlobalSettingsDlgGenerated::GlobalSettingsDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer72->Add( m_bitmapSettings, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); - - m_staticText44 = new wxStaticText( this, wxID_ANY, _("The following settings are used for all synchronization jobs."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticText44->Wrap( 500 ); - bSizer72->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 10 ); - - - bSizer95->Add( bSizer72, 0, 0, 5 ); - - m_staticline20 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer95->Add( m_staticline20, 0, wxEXPAND, 5 ); - - m_panel39 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel39->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer186; - bSizer186 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer160; - bSizer160 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer176; - bSizer176 = new wxBoxSizer( wxHORIZONTAL ); - - m_checkBoxFailSafe = new wxCheckBox( m_panel39, wxID_ANY, _("Fail-safe file copy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxFailSafe->SetValue(true); - m_checkBoxFailSafe->SetToolTip( _("Copy to a temporary file (*.ffs_tmp) before overwriting target.\nThis guarantees a consistent state even in case of a serious error.") ); - - bSizer176->Add( m_checkBoxFailSafe, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticText91 = new wxStaticText( m_panel39, wxID_ANY, _("(recommended)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText91->Wrap( -1 ); - m_staticText91->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - bSizer176->Add( m_staticText91, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer160->Add( bSizer176, 0, wxEXPAND, 5 ); - - bSizerLockedFiles = new wxBoxSizer( wxHORIZONTAL ); - - m_checkBoxCopyLocked = new wxCheckBox( m_panel39, wxID_ANY, _("Copy locked files"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxCopyLocked->SetValue(true); - m_checkBoxCopyLocked->SetToolTip( _("Copy shared or locked files using the Volume Shadow Copy Service.") ); - - bSizerLockedFiles->Add( m_checkBoxCopyLocked, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticText92 = new wxStaticText( m_panel39, wxID_ANY, _("(requires administrator rights)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText92->Wrap( -1 ); - m_staticText92->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - bSizerLockedFiles->Add( m_staticText92, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer160->Add( bSizerLockedFiles, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer178; - bSizer178 = new wxBoxSizer( wxHORIZONTAL ); - - m_checkBoxCopyPermissions = new wxCheckBox( m_panel39, wxID_ANY, _("Copy file access permissions"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxCopyPermissions->SetValue(true); - m_checkBoxCopyPermissions->SetToolTip( _("Transfer file and folder permissions.") ); - - bSizer178->Add( m_checkBoxCopyPermissions, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_staticText93 = new wxStaticText( m_panel39, wxID_ANY, _("(requires administrator rights)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText93->Wrap( -1 ); - m_staticText93->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - bSizer178->Add( m_staticText93, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer160->Add( bSizer178, 0, wxEXPAND, 5 ); - - - bSizer186->Add( bSizer160, 0, wxEXPAND|wxALL, 5 ); - - m_staticline39 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer186->Add( m_staticline39, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer188; - bSizer188 = new wxBoxSizer( wxVERTICAL ); - - m_staticText95 = new wxStaticText( m_panel39, wxID_ANY, _("Automatic retry on error:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText95->Wrap( -1 ); - bSizer188->Add( m_staticText95, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); - - wxFlexGridSizer* fgSizer6; - fgSizer6 = new wxFlexGridSizer( 0, 2, 5, 5 ); - fgSizer6->SetFlexibleDirection( wxBOTH ); - fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_staticText96 = new wxStaticText( m_panel39, wxID_ANY, _("Retry count:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText96->Wrap( -1 ); - fgSizer6->Add( m_staticText96, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_spinCtrlAutoRetryCount = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 0, 2000000000, 4 ); - fgSizer6->Add( m_spinCtrlAutoRetryCount, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextAutoRetryDelay = new wxStaticText( m_panel39, wxID_ANY, _("Delay (in seconds):"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextAutoRetryDelay->Wrap( -1 ); - fgSizer6->Add( m_staticTextAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_spinCtrlAutoRetryDelay = new wxSpinCtrl( m_panel39, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - fgSizer6->Add( m_spinCtrlAutoRetryDelay, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer188->Add( fgSizer6, 0, wxLEFT, 10 ); - - - bSizer186->Add( bSizer188, 0, wxALL, 10 ); - - - bSizer166->Add( bSizer186, 0, wxEXPAND, 5 ); - - m_staticline191 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline191, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxVERTICAL ); - - m_staticText85 = new wxStaticText( m_panel39, wxID_ANY, _("Customize context menu:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText85->Wrap( -1 ); - bSizer181->Add( m_staticText85, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); - - m_gridCustomCommand = new wxGrid( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - - // Grid - m_gridCustomCommand->CreateGrid( 5, 2 ); - m_gridCustomCommand->EnableEditing( true ); - m_gridCustomCommand->EnableGridLines( true ); - m_gridCustomCommand->EnableDragGridSize( false ); - m_gridCustomCommand->SetMargins( 0, 0 ); - - // Columns - m_gridCustomCommand->SetColSize( 0, 165 ); - m_gridCustomCommand->SetColSize( 1, 196 ); - m_gridCustomCommand->EnableDragColMove( false ); - m_gridCustomCommand->EnableDragColSize( true ); - m_gridCustomCommand->SetColLabelSize( 20 ); - m_gridCustomCommand->SetColLabelValue( 0, _("Description") ); - m_gridCustomCommand->SetColLabelValue( 1, _("Command line") ); - m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Rows - m_gridCustomCommand->EnableDragRowSize( false ); - m_gridCustomCommand->SetRowLabelSize( 1 ); - m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); - - // Label Appearance - - // Cell Defaults - m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); - bSizer181->Add( m_gridCustomCommand, 1, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer193; - bSizer193 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer193->Add( m_bpButtonAddRow, 0, 0, 5 ); - - m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 25,25 ), wxBU_AUTODRAW ); - bSizer193->Add( m_bpButtonRemoveRow, 0, 0, 5 ); - - - bSizer193->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_hyperlink17 = new wxHyperlinkCtrl( m_panel39, wxID_ANY, _("Show examples"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - bSizer193->Add( m_hyperlink17, 0, wxLEFT, 5 ); - - - bSizer181->Add( bSizer193, 0, wxTOP|wxEXPAND, 5 ); - - - bSizer166->Add( bSizer181, 1, wxEXPAND|wxALL, 10 ); - - m_staticline192 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer166->Add( m_staticline192, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer1881; - bSizer1881 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonResetDialogs = new zen::BitmapTextButton( m_panel39, wxID_ANY, _("Restore hidden windows"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer1881->Add( m_buttonResetDialogs, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); - - m_staticline40 = new wxStaticLine( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer1881->Add( m_staticline40, 0, wxEXPAND, 5 ); - - - bSizer166->Add( bSizer1881, 0, 0, 5 ); - - - m_panel39->SetSizer( bSizer166 ); - m_panel39->Layout(); - bSizer166->Fit( m_panel39 ); - bSizer95->Add( m_panel39, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer95->Add( m_staticline36, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonDefault = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonDefault, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizerStdButtons->Add( 0, 0, 1, 0, 5 ); - - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer95->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); - - - this->SetSizer( bSizer95 ); - this->Layout(); - bSizer95->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); - m_spinCtrlAutoRetryCount->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnToggleAutoRetryCount ), NULL, this ); - m_bpButtonAddRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnAddRow ), NULL, this ); - m_bpButtonRemoveRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnRemoveRow ), NULL, this ); - m_hyperlink17->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( GlobalSettingsDlgGenerated::OnHelpShowExamples ), NULL, this ); - m_buttonResetDialogs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnResetDialogs ), NULL, this ); - m_buttonDefault->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnDefault ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnCancel ), NULL, this ); -} - -GlobalSettingsDlgGenerated::~GlobalSettingsDlgGenerated() -{ -} - -TooltipDialogGenerated::TooltipDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeft = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer158->Add( m_bitmapLeft, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextMain = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMain->Wrap( 600 ); - bSizer158->Add( m_staticTextMain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - this->SetSizer( bSizer158 ); - this->Layout(); - bSizer158->Fit( this ); -} - -TooltipDialogGenerated::~TooltipDialogGenerated() -{ -} - -SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer96; - bSizer96 = new wxBoxSizer( wxVERTICAL ); - - m_panel35 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel35->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer98; - bSizer98 = new wxBoxSizer( wxHORIZONTAL ); - - m_calendarFrom = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxNO_BORDER ); - bSizer98->Add( m_calendarFrom, 0, wxTOP|wxBOTTOM|wxLEFT, 10 ); - - m_calendarTo = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxNO_BORDER ); - bSizer98->Add( m_calendarTo, 0, wxALL, 10 ); - - - m_panel35->SetSizer( bSizer98 ); - m_panel35->Layout(); - bSizer98->Fit( m_panel35 ); - bSizer96->Add( m_panel35, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizerStdButtons->Add( m_buttonOkay, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer96->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - - - this->SetSizer( bSizer96 ); - this->Layout(); - bSizer96->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SelectTimespanDlgGenerated::OnClose ) ); - m_calendarFrom->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::OnChangeSelectionFrom ), NULL, this ); - m_calendarTo->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::OnChangeSelectionTo ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectTimespanDlgGenerated::OnOkay ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SelectTimespanDlgGenerated::OnCancel ), NULL, this ); -} - -SelectTimespanDlgGenerated::~SelectTimespanDlgGenerated() -{ -} - -AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer31; - bSizer31 = new wxBoxSizer( wxVERTICAL ); - - m_panel41 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel41->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer162; - bSizer162 = new wxBoxSizer( wxVERTICAL ); - - m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer162->Add( m_bitmapLogo, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticline341 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer162->Add( m_staticline341, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer174; - bSizer174 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer187; - bSizer187 = new wxBoxSizer( wxVERTICAL ); - - m_staticText96 = new wxStaticText( m_panel41, wxID_ANY, _("Source code written in C++ using:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText96->Wrap( -1 ); - bSizer187->Add( m_staticText96, 0, wxALL, 5 ); - - wxBoxSizer* bSizer171; - bSizer171 = new wxBoxSizer( wxHORIZONTAL ); - - m_hyperlink11 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("MS Visual C++"), wxT("http://msdn.microsoft.com/library/60k1461a.aspx"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink11->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink11->SetToolTip( _("http://msdn.microsoft.com/library/60k1461a.aspx") ); - - bSizer171->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink9 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("MinGW"), wxT("http://www.mingw.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink9->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink9->SetToolTip( _("http://www.mingw.org") ); - - bSizer171->Add( m_hyperlink9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink10 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Code::Blocks"), wxT("http://www.codeblocks.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink10->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink10->SetToolTip( _("http://www.codeblocks.org") ); - - bSizer171->Add( m_hyperlink10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink7 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("wxWidgets"), wxT("http://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink7->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink7->SetToolTip( _("http://www.wxwidgets.org") ); - - bSizer171->Add( m_hyperlink7, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink14 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("wxFormBuilder"), wxT("http://wxformbuilder.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink14->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink14->SetToolTip( _("http://wxformbuilder.org") ); - - bSizer171->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer187->Add( bSizer171, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer172; - bSizer172 = new wxBoxSizer( wxHORIZONTAL ); - - m_hyperlink15 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("zen::Xml"), wxT("http://zenxml.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink15->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink15->SetToolTip( _("http://zenxml.sourceforge.net") ); - - bSizer172->Add( m_hyperlink15, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink13 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Boost"), wxT("http://www.boost.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink13->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink13->SetToolTip( _("http://www.boost.org") ); - - bSizer172->Add( m_hyperlink13, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink16 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Artistic Style"), wxT("http://astyle.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink16->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink16->SetToolTip( _("http://astyle.sourceforge.net") ); - - bSizer172->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink12 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Google Test"), wxT("http://code.google.com/p/googletest"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink12->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink12->SetToolTip( _("http://code.google.com/p/googletest") ); - - bSizer172->Add( m_hyperlink12, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink18 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Unicode NSIS"), wxT("http://www.scratchpaper.com"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink18->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink18->SetToolTip( _("http://www.scratchpaper.com") ); - - bSizer172->Add( m_hyperlink18, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer187->Add( bSizer172, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer181->Add( bSizer187, 0, wxALL|wxEXPAND, 5 ); - - m_panelDonate = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panelDonate->SetBackgroundColour( wxColour( 153, 170, 187 ) ); - - wxBoxSizer* bSizer183; - bSizer183 = new wxBoxSizer( wxVERTICAL ); - - m_panel39 = new wxPanel( m_panelDonate, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel39->SetBackgroundColour( wxColour( 221, 221, 255 ) ); - - wxBoxSizer* bSizer184; - bSizer184 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer184->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_animCtrlWink = new wxAnimationCtrl( m_panel39, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 48,48 ), wxAC_DEFAULT_STYLE ); - bSizer184->Add( m_animCtrlWink, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer178; - bSizer178 = new wxBoxSizer( wxVERTICAL ); - - m_staticText83 = new wxStaticText( m_panel39, wxID_ANY, _("If you like FreeFileSync"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText83->Wrap( -1 ); - m_staticText83->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - m_staticText83->SetForegroundColour( wxColour( 0, 0, 0 ) ); - - bSizer178->Add( m_staticText83, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_buttonDonate = new wxButton( m_panel39, wxID_ANY, _("Donate with PayPal"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonDonate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) ); - m_buttonDonate->SetToolTip( _("http://freefilesync.sourceforge.net/donate.php") ); - - bSizer178->Add( m_buttonDonate, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer184->Add( bSizer178, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer184->Add( 0, 0, 1, wxEXPAND, 5 ); - - - m_panel39->SetSizer( bSizer184 ); - m_panel39->Layout(); - bSizer184->Fit( m_panel39 ); - bSizer183->Add( m_panel39, 0, wxEXPAND|wxALL, 5 ); - - - m_panelDonate->SetSizer( bSizer183 ); - m_panelDonate->Layout(); - bSizer183->Fit( m_panelDonate ); - bSizer181->Add( m_panelDonate, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer186; - bSizer186 = new wxBoxSizer( wxVERTICAL ); - - m_staticText94 = new wxStaticText( m_panel41, wxID_ANY, _("Feedback and suggestions are welcome"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText94->Wrap( -1 ); - bSizer186->Add( m_staticText94, 0, wxALL, 5 ); - - wxBoxSizer* bSizer166; - bSizer166 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer166->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bitmap9 = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmap9->SetToolTip( _("Homepage") ); - - bSizer166->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_hyperlink1 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("freefilesync.sf.net"), wxT("http://freefilesync.sf.net/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink1->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, true, wxEmptyString ) ); - m_hyperlink1->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - bSizer166->Add( m_hyperlink1, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer166->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bitmap10 = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_bitmap10->SetToolTip( _("Email") ); - - bSizer166->Add( m_bitmap10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_hyperlink2 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("zenju@gmx.de"), wxT("mailto:zenju@gmx.de"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, true, wxEmptyString ) ); - m_hyperlink2->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - bSizer166->Add( m_hyperlink2, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer166->Add( 0, 0, 1, wxEXPAND, 5 ); - - - bSizer186->Add( bSizer166, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer181->Add( bSizer186, 0, wxALL|wxEXPAND, 5 ); - - m_staticline34 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer181->Add( m_staticline34, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer185; - bSizer185 = new wxBoxSizer( wxVERTICAL ); - - m_staticText93 = new wxStaticText( m_panel41, wxID_ANY, _("Published under the GNU General Public License"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText93->Wrap( -1 ); - bSizer185->Add( m_staticText93, 0, wxALL, 5 ); - - wxBoxSizer* bSizer1671; - bSizer1671 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap13 = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer1671->Add( m_bitmap13, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink5 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("http://www.gnu.org/licenses/gpl.html"), wxT("http://www.gnu.org/licenses/gpl.html"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink5->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - bSizer1671->Add( m_hyperlink5, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer185->Add( bSizer1671, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - - bSizer181->Add( bSizer185, 0, wxALL|wxEXPAND, 5 ); - - - bSizer174->Add( bSizer181, 0, 0, 5 ); - - m_staticline37 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer174->Add( m_staticline37, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer177; - bSizer177 = new wxBoxSizer( wxVERTICAL ); - - m_staticText54 = new wxStaticText( m_panel41, wxID_ANY, _("Many thanks for localization:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText54->Wrap( 200 ); - m_staticText54->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); - - bSizer177->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - - bSizer177->Add( 0, 5, 0, 0, 5 ); - - m_scrolledWindowTranslators = new wxScrolledWindow( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxVSCROLL ); - m_scrolledWindowTranslators->SetScrollRate( 10, 10 ); - m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_scrolledWindowTranslators->SetMinSize( wxSize( 220,-1 ) ); - - fgSizerTranslators = new wxFlexGridSizer( 0, 2, 2, 10 ); - fgSizerTranslators->SetFlexibleDirection( wxBOTH ); - fgSizerTranslators->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - m_scrolledWindowTranslators->SetSizer( fgSizerTranslators ); - m_scrolledWindowTranslators->Layout(); - fgSizerTranslators->Fit( m_scrolledWindowTranslators ); - bSizer177->Add( m_scrolledWindowTranslators, 1, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxEXPAND, 5 ); - - - bSizer174->Add( bSizer177, 0, wxEXPAND|wxTOP|wxLEFT, 5 ); - - - bSizer162->Add( bSizer174, 0, 0, 5 ); - - - m_panel41->SetSizer( bSizer162 ); - m_panel41->Layout(); - bSizer162->Fit( m_panel41 ); - bSizer31->Add( m_panel41, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer31->Add( m_staticline36, 0, wxEXPAND, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonClose->SetDefault(); - bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer31->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - - - this->SetSizer( bSizer31 ); - this->Layout(); - bSizer31->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); - m_buttonDonate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnDonate ), NULL, this ); - m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); -} - -AboutDlgGenerated::~AboutDlgGenerated() -{ -} diff --git a/ui/gui_generated.h b/ui/gui_generated.h deleted file mode 100644 index 04aed9a9..00000000 --- a/ui/gui_generated.h +++ /dev/null @@ -1,880 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Oct 8 2012) -// http://www.wxformbuilder.org/ -// -// PLEASE DO "NOT" EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#ifndef __GUI_GENERATED_H__ -#define __GUI_GENERATED_H__ - -#include <wx/artprov.h> -#include <wx/xrc/xmlres.h> -#include <wx/intl.h> -class ExecFinishedBox; -class FolderHistoryBox; -class ToggleButton; -namespace zen { class BitmapTextButton; } -namespace zen { class Graph2D; } -namespace zen { class Grid; } -namespace zen { class TripleSplitter; } - -#include <wx/string.h> -#include <wx/bitmap.h> -#include <wx/image.h> -#include <wx/icon.h> -#include <wx/menu.h> -#include <wx/gdicmn.h> -#include <wx/font.h> -#include <wx/colour.h> -#include <wx/settings.h> -#include <wx/button.h> -#include <wx/bmpbuttn.h> -#include <wx/sizer.h> -#include <wx/panel.h> -#include <wx/stattext.h> -#include <wx/combobox.h> -#include <wx/scrolwin.h> -#include <wx/statbmp.h> -#include <wx/statline.h> -#include <wx/textctrl.h> -#include <wx/checkbox.h> -#include <wx/listbox.h> -#include <wx/frame.h> -#include <wx/tglbtn.h> -#include <wx/choice.h> -#include <wx/hyperlink.h> -#include <wx/dialog.h> -#include <wx/gauge.h> -#include <wx/animate.h> -#include <wx/notebook.h> -#include <wx/spinctrl.h> -#include <wx/grid.h> -#include <wx/calctrl.h> - -#include "zen/i18n.h" - -/////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -/// Class MainDialogGenerated -/////////////////////////////////////////////////////////////////////////////// -class MainDialogGenerated : public wxFrame -{ -private: - -protected: - wxMenuBar* m_menubar1; - wxMenu* m_menuFile; - wxMenuItem* m_menuItemNew; - wxMenuItem* m_menuItemLoad; - wxMenuItem* m_menuItemSave; - wxMenuItem* m_menuItemSaveAs; - wxMenuItem* m_menuItem7; - wxMenuItem* m_menuItem10; - wxMenuItem* m_menuItem11; - wxMenu* m_menuTools; - wxMenuItem* m_menuItemGlobSett; - wxMenu* m_menuLanguages; - wxMenu* m_menuHelp; - wxMenuItem* m_menuItemManual; - wxMenu* m_menuCheckVersion; - wxMenuItem* m_menuItemCheckVersionNow; - wxMenuItem* m_menuItemCheckVersionAuto; - wxMenuItem* m_menuItemAbout; - wxBoxSizer* bSizerPanelHolder; - wxPanel* m_panelTopButtons; - wxBoxSizer* bSizerTopButtons; - zen::BitmapTextButton* m_buttonCompare; - zen::BitmapTextButton* m_buttonCancel; - wxBitmapButton* m_bpButtonCmpConfig; - wxBitmapButton* m_bpButtonSyncConfig; - zen::BitmapTextButton* m_buttonSync; - wxPanel* m_panelDirectoryPairs; - wxStaticText* m_staticTextResolvedPathL; - wxBitmapButton* m_bpButtonAddPair; - wxButton* m_buttonSelectDirLeft; - wxPanel* m_panelTopMiddle; - wxBitmapButton* m_bpButtonSwapSides; - wxStaticText* m_staticTextResolvedPathR; - wxButton* m_buttonSelectDirRight; - wxScrolledWindow* m_scrolledWindowFolderPairs; - wxBoxSizer* bSizerAddFolderPairs; - zen::Grid* m_gridNavi; - wxPanel* m_panelCenter; - zen::TripleSplitter* m_splitterMain; - zen::Grid* m_gridMainL; - zen::Grid* m_gridMainC; - zen::Grid* m_gridMainR; - wxPanel* m_panelStatusBar; - wxBoxSizer* bSizerFileStatus; - wxBoxSizer* bSizerStatusLeft; - wxBoxSizer* bSizerStatusLeftDirectories; - wxStaticBitmap* m_bitmapSmallDirectoryLeft; - wxStaticText* m_staticTextStatusLeftDirs; - wxBoxSizer* bSizerStatusLeftFiles; - wxStaticBitmap* m_bitmapSmallFileLeft; - wxStaticText* m_staticTextStatusLeftFiles; - wxStaticText* m_staticTextStatusLeftBytes; - wxStaticLine* m_staticline9; - wxStaticText* m_staticTextStatusMiddle; - wxBoxSizer* bSizerStatusRight; - wxStaticLine* m_staticline10; - wxBoxSizer* bSizerStatusRightDirectories; - wxStaticBitmap* m_bitmapSmallDirectoryRight; - wxStaticText* m_staticTextStatusRightDirs; - wxBoxSizer* bSizerStatusRightFiles; - wxStaticBitmap* m_bitmapSmallFileRight; - wxStaticText* m_staticTextStatusRightFiles; - wxStaticText* m_staticTextStatusRightBytes; - wxStaticText* m_staticTextFullStatus; - wxPanel* m_panelSearch; - wxBitmapButton* m_bpButtonHideSearch; - wxStaticText* m_staticText101; - wxTextCtrl* m_textCtrlSearchTxt; - wxCheckBox* m_checkBoxMatchCase; - wxPanel* m_panelConfig; - wxBoxSizer* bSizerConfig; - wxBitmapButton* m_bpButtonOpen; - wxBitmapButton* m_bpButtonSave; - wxBitmapButton* m_bpButtonBatchJob; - wxListBox* m_listBoxHistory; - wxPanel* m_panelFilter; - wxBitmapButton* m_bpButtonFilter; - wxCheckBox* m_checkBoxHideExcluded; - wxPanel* m_panelStatistics; - wxBoxSizer* bSizer1801; - wxStaticBitmap* m_bitmapCreateLeft; - wxStaticText* m_staticTextCreateLeft; - wxStaticBitmap* m_bitmapUpdateLeft; - wxStaticText* m_staticTextUpdateLeft; - wxStaticBitmap* m_bitmapDeleteLeft; - wxStaticText* m_staticTextDeleteLeft; - wxStaticBitmap* m_bitmapData; - wxStaticText* m_staticTextData; - wxStaticBitmap* m_bitmapDeleteRight; - wxStaticText* m_staticTextDeleteRight; - wxStaticBitmap* m_bitmapUpdateRight; - wxStaticText* m_staticTextUpdateRight; - wxStaticBitmap* m_bitmapCreateRight; - wxStaticText* m_staticTextCreateRight; - wxPanel* m_panelViewFilter; - wxBoxSizer* bSizerViewFilter; - ToggleButton* m_bpButtonViewTypeSyncAction; - ToggleButton* m_bpButtonShowCreateLeft; - ToggleButton* m_bpButtonShowUpdateLeft; - ToggleButton* m_bpButtonShowDeleteLeft; - ToggleButton* m_bpButtonShowLeftOnly; - ToggleButton* m_bpButtonShowLeftNewer; - ToggleButton* m_bpButtonShowEqual; - ToggleButton* m_bpButtonShowDifferent; - ToggleButton* m_bpButtonShowDoNothing; - ToggleButton* m_bpButtonShowRightNewer; - ToggleButton* m_bpButtonShowRightOnly; - ToggleButton* m_bpButtonShowDeleteRight; - ToggleButton* m_bpButtonShowUpdateRight; - ToggleButton* m_bpButtonShowCreateRight; - ToggleButton* m_bpButtonShowConflict; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnConfigNew( wxCommandEvent& event ) { event.Skip(); } - virtual void OnConfigLoad( wxCommandEvent& event ) { event.Skip(); } - virtual void OnConfigSave( wxCommandEvent& event ) { event.Skip(); } - virtual void OnConfigSaveAs( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSaveAsBatchJob( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCompare( wxCommandEvent& event ) { event.Skip(); } - virtual void OnStartSync( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuQuit( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuGlobalSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuFindItem( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuExportFileList( wxCommandEvent& event ) { event.Skip(); } - virtual void OnShowHelp( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuCheckVersion( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuCheckVersionAutomatically( wxCommandEvent& event ) { event.Skip(); } - virtual void OnMenuAbout( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCmpSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCompSettingsContext( wxMouseEvent& event ) { event.Skip(); } - virtual void OnSyncSettings( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSyncSettingsContext( wxMouseEvent& event ) { event.Skip(); } - virtual void OnAddFolderPair( wxCommandEvent& event ) { event.Skip(); } - virtual void OnRemoveTopFolderPair( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSwapSides( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHideSearchPanel( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSearchGridEnter( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCfgHistoryKeyEvent( wxKeyEvent& event ) { event.Skip(); } - virtual void OnLoadFromHistory( wxCommandEvent& event ) { event.Skip(); } - virtual void OnLoadFromHistoryDoubleClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCfgHistoryRightClick( wxMouseEvent& event ) { event.Skip(); } - virtual void OnConfigureFilter( wxCommandEvent& event ) { event.Skip(); } - virtual void OnGlobalFilterContext( wxMouseEvent& event ) { event.Skip(); } - virtual void OnShowExcluded( wxCommandEvent& event ) { event.Skip(); } - virtual void OnToggleViewType( wxCommandEvent& event ) { event.Skip(); } - virtual void OnToggleViewButton( wxCommandEvent& event ) { event.Skip(); } - virtual void OnViewButtonRightClick( wxMouseEvent& event ) { event.Skip(); } - - -public: - wxPanel* m_panelTopLeft; - wxBitmapButton* m_bpButtonRemovePair; - FolderHistoryBox* m_directoryLeft; - wxBitmapButton* m_bpButtonAltCompCfg; - wxBitmapButton* m_bpButtonLocalFilter; - wxBitmapButton* m_bpButtonAltSyncCfg; - wxPanel* m_panelTopRight; - FolderHistoryBox* m_directoryRight; - wxBoxSizer* bSizerStatistics; - wxBoxSizer* bSizerData; - - MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 900,600 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); - - ~MainDialogGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class CmpCfgDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class CmpCfgDlgGenerated : public wxDialog -{ -private: - -protected: - wxPanel* m_panel36; - wxStaticText* m_staticText91; - wxStaticBitmap* m_bitmapByTime; - wxToggleButton* m_toggleBtnTimeSize; - wxStaticBitmap* m_bitmapByContent; - wxToggleButton* m_toggleBtnContent; - wxStaticLine* m_staticline33; - wxStaticText* m_staticText92; - wxChoice* m_choiceHandleSymlinks; - wxHyperlinkCtrl* m_hyperlink24; - wxStaticLine* m_staticline14; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnTimeSizeDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void OnTimeSize( wxCommandEvent& event ) { event.Skip(); } - virtual void OnContentDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void OnContent( wxCommandEvent& event ) { event.Skip(); } - virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHelpComparisonSettings( wxHyperlinkEvent& event ) { event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); - ~CmpCfgDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class SyncCfgDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class SyncCfgDlgGenerated : public wxDialog -{ -private: - -protected: - wxPanel* m_panel37; - wxStaticText* m_staticText86; - wxToggleButton* m_toggleBtnTwoWay; - wxStaticText* m_staticTextAutomatic; - wxToggleButton* m_toggleBtnMirror; - wxStaticText* m_staticTextMirror; - wxToggleButton* m_toggleBtnUpdate; - wxStaticText* m_staticTextUpdate; - wxToggleButton* m_toggleBtnCustom; - wxStaticText* m_staticTextCustom; - wxCheckBox* m_checkBoxDetectMove; - wxStaticLine* m_staticline32; - wxStaticText* m_staticText87; - wxToggleButton* m_toggleBtnPermanent; - wxToggleButton* m_toggleBtnRecycler; - wxToggleButton* m_toggleBtnVersioning; - wxPanel* m_panelVersioning; - FolderHistoryBox* m_versioningFolder; - wxButton* m_buttonSelectDirVersioning; - wxBoxSizer* bSizer192; - wxStaticText* m_staticText93; - wxChoice* m_choiceVersioningStyle; - wxStaticText* m_staticTextNamingCvtPart1; - wxStaticText* m_staticTextNamingCvtPart2Bold; - wxStaticText* m_staticTextNamingCvtPart3; - wxHyperlinkCtrl* m_hyperlink17; - wxBoxSizer* bSizerExtraConfig; - wxStaticLine* m_staticline321; - wxBoxSizer* bSizer179; - wxStaticText* m_staticText88; - wxToggleButton* m_toggleBtnErrorIgnore; - wxToggleButton* m_toggleBtnErrorPopup; - wxStaticLine* m_staticline36; - wxBoxSizer* bSizerOnCompletion; - wxStaticText* m_staticText89; - ExecFinishedBox* m_comboBoxExecFinished; - wxStaticLine* m_staticline31; - wxBoxSizer* bSizerConfig; - wxStaticText* m_staticTextHeaderCategory1; - wxStaticText* m_staticTextHeaderAction1; - wxStaticBitmap* m_bitmapDatabase; - wxBoxSizer* sbSizerSyncDirections; - wxBoxSizer* bSizerLeftOnly; - wxStaticBitmap* m_bitmapLeftOnly; - wxBitmapButton* m_bpButtonLeftOnly; - wxBoxSizer* bSizerRightOnly; - wxStaticBitmap* m_bitmapRightOnly; - wxBitmapButton* m_bpButtonRightOnly; - wxBoxSizer* bSizerLeftNewer; - wxStaticBitmap* m_bitmapLeftNewer; - wxBitmapButton* m_bpButtonLeftNewer; - wxBoxSizer* bSizerRightNewer; - wxStaticBitmap* m_bitmapRightNewer; - wxBitmapButton* m_bpButtonRightNewer; - wxBoxSizer* bSizerDifferent; - wxStaticBitmap* m_bitmapDifferent; - wxBitmapButton* m_bpButtonDifferent; - wxBoxSizer* bSizerConflict; - wxStaticBitmap* m_bitmapConflict; - wxBitmapButton* m_bpButtonConflict; - wxStaticLine* m_staticline15; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOK; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnSyncTwoWayDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void OnSyncTwoWay( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSyncMirrorDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void OnSyncMirror( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSyncUpdateDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void OnSyncUpdate( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSyncCustomDouble( wxMouseEvent& event ) { event.Skip(); } - virtual void OnSyncCustom( wxCommandEvent& event ) { event.Skip(); } - virtual void OnToggleDetectMovedFiles( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDeletionPermanent( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDeletionRecycler( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDeletionVersioning( wxCommandEvent& event ) { event.Skip(); } - virtual void OnParameterChange( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHelpVersioning( wxHyperlinkEvent& event ) { event.Skip(); } - virtual void OnErrorIgnore( wxCommandEvent& event ) { event.Skip(); } - virtual void OnErrorPopup( wxCommandEvent& event ) { event.Skip(); } - virtual void OnExLeftSideOnly( wxCommandEvent& event ) { event.Skip(); } - virtual void OnExRightSideOnly( wxCommandEvent& event ) { event.Skip(); } - virtual void OnLeftNewer( wxCommandEvent& event ) { event.Skip(); } - virtual void OnRightNewer( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDifferent( wxCommandEvent& event ) { event.Skip(); } - virtual void OnConflict( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~SyncCfgDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class SyncConfirmationDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class SyncConfirmationDlgGenerated : public wxDialog -{ -private: - -protected: - wxStaticBitmap* m_bitmapSync; - wxStaticText* m_staticTextHeader; - wxStaticLine* m_staticline371; - wxPanel* m_panelStatistics; - wxStaticLine* m_staticline38; - wxStaticText* m_staticText84; - wxStaticText* m_staticTextVariant; - wxStaticLine* m_staticline14; - wxStaticText* m_staticText83; - wxStaticBitmap* m_bitmapCreateLeft; - wxStaticBitmap* m_bitmapUpdateLeft; - wxStaticBitmap* m_bitmapDeleteLeft; - wxStaticBitmap* m_bitmapData; - wxStaticBitmap* m_bitmapDeleteRight; - wxStaticBitmap* m_bitmapUpdateRight; - wxStaticBitmap* m_bitmapCreateRight; - wxStaticText* m_staticTextCreateLeft; - wxStaticText* m_staticTextUpdateLeft; - wxStaticText* m_staticTextDeleteLeft; - wxStaticText* m_staticTextData; - wxStaticText* m_staticTextDeleteRight; - wxStaticText* m_staticTextUpdateRight; - wxStaticText* m_staticTextCreateRight; - wxStaticLine* m_staticline12; - wxCheckBox* m_checkBoxDontShowAgain; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonStartSync; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnStartSync( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("FreeFileSync"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~SyncConfirmationDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class FolderPairPanelGenerated -/////////////////////////////////////////////////////////////////////////////// -class FolderPairPanelGenerated : public wxPanel -{ -private: - -protected: - wxButton* m_buttonSelectDirLeft; - wxButton* m_buttonSelectDirRight; - -public: - wxPanel* m_panelLeft; - wxBitmapButton* m_bpButtonRemovePair; - FolderHistoryBox* m_directoryLeft; - wxPanel* m_panel20; - wxBitmapButton* m_bpButtonAltCompCfg; - wxBitmapButton* m_bpButtonLocalFilter; - wxBitmapButton* m_bpButtonAltSyncCfg; - wxPanel* m_panelRight; - FolderHistoryBox* m_directoryRight; - - FolderPairPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0 ); - ~FolderPairPanelGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class CompareProgressDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class CompareProgressDlgGenerated : public wxPanel -{ -private: - -protected: - wxTextCtrl* m_textCtrlStatus; - wxGauge* m_gauge2; - wxBoxSizer* bSizer42; - wxBoxSizer* bSizerFilesFound; - wxStaticText* m_staticText321; - wxStaticText* m_staticTextScanned; - wxBoxSizer* bSizerFilesRemaining; - wxStaticText* m_staticText46; - wxStaticText* m_staticTextFilesRemaining; - wxStaticText* m_staticTextDataRemaining; - wxBoxSizer* sSizerSpeed; - wxStaticText* m_staticText104; - wxStaticText* m_staticTextSpeed; - wxBoxSizer* sSizerTimeRemaining; - wxStaticText* m_staticTextTimeRemFixed; - wxStaticText* m_staticTextRemTime; - wxBoxSizer* sSizerTimeElapsed; - wxStaticText* m_staticTextTimeElapsed; - -public: - - CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxRAISED_BORDER ); - ~CompareProgressDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class SyncProgressPanelGenerated -/////////////////////////////////////////////////////////////////////////////// -class SyncProgressPanelGenerated : public wxPanel -{ -private: - -protected: - wxBoxSizer* bSizer42; - wxBoxSizer* bSizer171; - wxStaticText* m_staticText87; - -public: - wxBoxSizer* bSizerRoot; - wxStaticBitmap* m_bitmapStatus; - wxStaticText* m_staticTextPhase; - wxAnimationCtrl* m_animCtrlSyncing; - wxBitmapButton* m_bpButtonMinimizeToTray; - wxBoxSizer* bSizerStatusText; - wxStaticText* m_staticTextStatus; - wxPanel* m_panelProgress; - wxPanel* m_panelItemsProcessed; - wxStaticText* m_staticTextProcessedObj; - wxStaticText* m_staticTextDataProcessed; - wxPanel* m_panelItemsRemaining; - wxStaticText* m_staticTextRemainingObj; - wxStaticText* m_staticTextDataRemaining; - wxPanel* m_panelTimeRemaining; - wxStaticText* m_staticTextRemTime; - wxStaticText* m_staticTextTimeElapsed; - zen::Graph2D* m_panelGraphBytes; - zen::Graph2D* m_panelGraphItems; - wxNotebook* m_notebookResult; - wxStaticLine* m_staticlineFooter; - wxBoxSizer* bSizerStdButtons; - wxBoxSizer* bSizerExecFinished; - ExecFinishedBox* m_comboBoxExecFinished; - wxButton* m_buttonClose; - wxButton* m_buttonPause; - wxButton* m_buttonStop; - - SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~SyncProgressPanelGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class LogPanelGenerated -/////////////////////////////////////////////////////////////////////////////// -class LogPanelGenerated : public wxPanel -{ -private: - -protected: - ToggleButton* m_bpButtonErrors; - ToggleButton* m_bpButtonWarnings; - ToggleButton* m_bpButtonInfo; - wxStaticLine* m_staticline13; - zen::Grid* m_gridMessages; - - // Virtual event handlers, overide them in your derived class - virtual void OnErrors( wxCommandEvent& event ) { event.Skip(); } - virtual void OnWarnings( wxCommandEvent& event ) { event.Skip(); } - virtual void OnInfo( wxCommandEvent& event ) { event.Skip(); } - - -public: - - LogPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL ); - ~LogPanelGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class BatchDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class BatchDlgGenerated : public wxDialog -{ -private: - -protected: - wxStaticBitmap* m_bitmapBatchJob; - wxStaticText* m_staticTextDescr; - wxStaticLine* m_staticline18; - wxPanel* m_panel35; - wxStaticText* m_staticText82; - wxToggleButton* m_toggleBtnErrorIgnore; - wxToggleButton* m_toggleBtnErrorPopup; - wxToggleButton* m_toggleBtnErrorStop; - wxStaticLine* m_staticline26; - wxCheckBox* m_checkBoxShowProgress; - wxStaticText* m_staticText81; - ExecFinishedBox* m_comboBoxExecFinished; - wxStaticLine* m_staticline25; - wxCheckBox* m_checkBoxGenerateLogfile; - wxPanel* m_panelLogfile; - wxButton* m_buttonSelectLogfileDir; - wxCheckBox* m_checkBoxLogfilesLimit; - wxSpinCtrl* m_spinCtrlLogfileLimit; - wxHyperlinkCtrl* m_hyperlink17; - wxStaticLine* m_staticline13; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonSaveAs; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnErrorIgnore( wxCommandEvent& event ) { event.Skip(); } - virtual void OnErrorPopup( wxCommandEvent& event ) { event.Skip(); } - virtual void OnErrorStop( wxCommandEvent& event ) { event.Skip(); } - virtual void OnToggleGenerateLogfile( wxCommandEvent& event ) { event.Skip(); } - virtual void OnToggleLogfilesLimit( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHelpScheduleBatch( wxHyperlinkEvent& event ) { event.Skip(); } - virtual void OnSaveBatchJob( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - FolderHistoryBox* m_logfileDir; - - BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Save as Batch Job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~BatchDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class DeleteDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class DeleteDlgGenerated : public wxDialog -{ -private: - -protected: - wxStaticBitmap* m_bitmapDeleteType; - wxStaticText* m_staticTextHeader; - wxStaticLine* m_staticline91; - wxPanel* m_panel31; - wxStaticLine* m_staticline42; - wxTextCtrl* m_textCtrlFileList; - wxStaticLine* m_staticline9; - wxBoxSizer* bSizerStdButtons; - wxCheckBox* m_checkBoxUseRecycler; - wxCheckBox* m_checkBoxDeleteBothSides; - wxButton* m_buttonOK; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnUseRecycler( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDelOnBothSides( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOK( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); - ~DeleteDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class FilterDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class FilterDlgGenerated : public wxDialog -{ -private: - -protected: - wxStaticBitmap* m_bitmapFilter; - wxStaticText* m_staticText44; - wxStaticLine* m_staticline17; - wxPanel* m_panel38; - wxStaticBitmap* m_bitmapInclude; - wxStaticText* m_staticText78; - wxTextCtrl* m_textCtrlInclude; - wxStaticLine* m_staticline22; - wxStaticBitmap* m_bitmapExclude; - wxStaticText* m_staticText77; - wxHyperlinkCtrl* m_hyperlink17; - wxTextCtrl* m_textCtrlExclude; - wxStaticLine* m_staticline24; - wxStaticBitmap* m_bitmapFilterDate; - wxStaticText* m_staticText79; - wxSpinCtrl* m_spinCtrlTimespan; - wxChoice* m_choiceUnitTimespan; - wxStaticLine* m_staticline23; - wxStaticBitmap* m_bitmapFilterSize; - wxStaticText* m_staticText80; - wxStaticText* m_staticText101; - wxSpinCtrl* m_spinCtrlMinSize; - wxChoice* m_choiceUnitMinSize; - wxStaticText* m_staticText102; - wxSpinCtrl* m_spinCtrlMaxSize; - wxChoice* m_choiceUnitMaxSize; - wxStaticLine* m_staticline16; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonClear; - wxButton* m_buttonOk; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnUpdateNameFilter( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHelpShowExamples( wxHyperlinkEvent& event ) { event.Skip(); } - virtual void OnUpdateChoice( wxCommandEvent& event ) { event.Skip(); } - virtual void OnClear( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - FilterDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); - ~FilterDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class GlobalSettingsDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class GlobalSettingsDlgGenerated : public wxDialog -{ -private: - -protected: - wxStaticBitmap* m_bitmapSettings; - wxStaticText* m_staticText44; - wxStaticLine* m_staticline20; - wxPanel* m_panel39; - wxCheckBox* m_checkBoxFailSafe; - wxStaticText* m_staticText91; - wxBoxSizer* bSizerLockedFiles; - wxCheckBox* m_checkBoxCopyLocked; - wxStaticText* m_staticText92; - wxCheckBox* m_checkBoxCopyPermissions; - wxStaticText* m_staticText93; - wxStaticLine* m_staticline39; - wxStaticText* m_staticText95; - wxStaticText* m_staticText96; - wxSpinCtrl* m_spinCtrlAutoRetryCount; - wxStaticText* m_staticTextAutoRetryDelay; - wxSpinCtrl* m_spinCtrlAutoRetryDelay; - wxStaticLine* m_staticline191; - wxStaticText* m_staticText85; - wxGrid* m_gridCustomCommand; - wxBitmapButton* m_bpButtonAddRow; - wxBitmapButton* m_bpButtonRemoveRow; - wxHyperlinkCtrl* m_hyperlink17; - wxStaticLine* m_staticline192; - zen::BitmapTextButton* m_buttonResetDialogs; - wxStaticLine* m_staticline40; - wxStaticLine* m_staticline36; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonDefault; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnToggleAutoRetryCount( wxCommandEvent& event ) { event.Skip(); } - virtual void OnAddRow( wxCommandEvent& event ) { event.Skip(); } - virtual void OnRemoveRow( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHelpShowExamples( wxHyperlinkEvent& event ) { event.Skip(); } - virtual void OnResetDialogs( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDefault( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - GlobalSettingsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Global Settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~GlobalSettingsDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class TooltipDialogGenerated -/////////////////////////////////////////////////////////////////////////////// -class TooltipDialogGenerated : public wxDialog -{ -private: - -protected: - -public: - wxStaticBitmap* m_bitmapLeft; - wxStaticText* m_staticTextMain; - - TooltipDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~TooltipDialogGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class SelectTimespanDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class SelectTimespanDlgGenerated : public wxDialog -{ -private: - -protected: - wxPanel* m_panel35; - wxCalendarCtrl* m_calendarFrom; - wxCalendarCtrl* m_calendarTo; - wxStaticLine* m_staticline21; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonOkay; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnChangeSelectionFrom( wxCalendarEvent& event ) { event.Skip(); } - virtual void OnChangeSelectionTo( wxCalendarEvent& event ) { event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - -public: - - SelectTimespanDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Select Time Span"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~SelectTimespanDlgGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// -/// Class AboutDlgGenerated -/////////////////////////////////////////////////////////////////////////////// -class AboutDlgGenerated : public wxDialog -{ -private: - -protected: - wxPanel* m_panel41; - wxStaticBitmap* m_bitmapLogo; - wxStaticLine* m_staticline341; - wxStaticText* m_staticText96; - wxHyperlinkCtrl* m_hyperlink11; - wxHyperlinkCtrl* m_hyperlink9; - wxHyperlinkCtrl* m_hyperlink10; - wxHyperlinkCtrl* m_hyperlink7; - wxHyperlinkCtrl* m_hyperlink14; - wxHyperlinkCtrl* m_hyperlink15; - wxHyperlinkCtrl* m_hyperlink13; - wxHyperlinkCtrl* m_hyperlink16; - wxHyperlinkCtrl* m_hyperlink12; - wxHyperlinkCtrl* m_hyperlink18; - wxPanel* m_panelDonate; - wxPanel* m_panel39; - wxAnimationCtrl* m_animCtrlWink; - wxStaticText* m_staticText83; - wxButton* m_buttonDonate; - wxStaticText* m_staticText94; - wxStaticBitmap* m_bitmap9; - wxHyperlinkCtrl* m_hyperlink1; - wxStaticBitmap* m_bitmap10; - wxHyperlinkCtrl* m_hyperlink2; - wxStaticLine* m_staticline34; - wxStaticText* m_staticText93; - wxStaticBitmap* m_bitmap13; - wxHyperlinkCtrl* m_hyperlink5; - wxStaticLine* m_staticline37; - wxStaticText* m_staticText54; - wxScrolledWindow* m_scrolledWindowTranslators; - wxFlexGridSizer* fgSizerTranslators; - wxStaticLine* m_staticline36; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonClose; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnDonate( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOK( wxCommandEvent& event ) { event.Skip(); } - - -public: - - AboutDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~AboutDlgGenerated(); - -}; - -#endif //__GUI_GENERATED_H__ diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp deleted file mode 100644 index f161b87b..00000000 --- a/ui/gui_status_handler.cpp +++ /dev/null @@ -1,479 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "gui_status_handler.h" -#include <zen/shell_execute.h> -#include <wx/app.h> -#include <wx/wupdlock.h> -#include <wx+/bitmap_button.h> -#include <wx+/popup_dlg.h> -#include "main_dlg.h" -#include "exec_finished_box.h" -#include "../lib/generate_logfile.h" -#include "../lib/resolve_path.h" -#include "../lib/status_handler_impl.h" - -using namespace zen; -using namespace xmlAccess; - - -CompareStatusHandler::CompareStatusHandler(MainDialog& dlg) : - mainDlg(dlg), - ignoreErrors(false) -{ - { -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(&mainDlg); //leads to GUI corruption problems on Linux/OS X! -#endif - - //display status panel during compare - mainDlg.compareStatus->init(*this); //clear old values before showing panel - mainDlg.auiMgr.GetPane(mainDlg.compareStatus->getAsWindow()).Show(); - mainDlg.auiMgr.Update(); - } - - mainDlg.Update(); //don't wait until idle event! - - //register keys - mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this); - mainDlg.m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this); -} - - -CompareStatusHandler::~CompareStatusHandler() -{ - //unregister keys - mainDlg.Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this); - mainDlg.m_buttonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this); - - mainDlg.compareStatus->finalize(); - mainDlg.auiMgr.GetPane(mainDlg.compareStatus->getAsWindow()).Hide(); - mainDlg.auiMgr.Update(); -} - - -void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event) -{ - const int keyCode = event.GetKeyCode(); - if (keyCode == WXK_ESCAPE) - { - wxCommandEvent dummy; - OnAbortCompare(dummy); - } - - event.Skip(); -} - - -void CompareStatusHandler::initNewPhase(int objectsTotal, Int64 dataTotal, Phase phaseID) -{ - StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID); - - switch (currentPhase()) - { - case PHASE_NONE: - case PHASE_SYNCHRONIZING: - assert(false); - case PHASE_SCANNING: - break; - case PHASE_COMPARING_CONTENT: - { -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(&mainDlg); //leads to GUI corruption problems on Linux/OS X! -#endif - mainDlg.compareStatus->switchToCompareBytewise(); - mainDlg.Layout(); //show progress bar... - mainDlg.Refresh(); //remove distortion... - } - break; - } -} - - -ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring& errorMessage, size_t retryNumber) -{ - //no need to implement auto-retry here: 1. user is watching 2. comparison is fast - //=> similar behavior like "ignoreErrors" which does not honor sync settings - - if (ignoreErrors) - return ProcessCallback::IGNORE_ERROR; - - forceUiRefresh(); - - bool ignoreNextErrors = false; - switch (showConfirmationDialog3(&mainDlg, DialogInfoType::ERROR2, PopupDialogCfg3(). - setDetailInstructions(errorMessage). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors"), ConfirmationButton3::DONT_DO_IT), - _("&Ignore"), _("&Retry"))) - { - case ConfirmationButton3::DO_IT: //ignore - ignoreErrors = ignoreNextErrors; - return ProcessCallback::IGNORE_ERROR; - - case ConfirmationButton3::DONT_DO_IT: //retry - return ProcessCallback::RETRY; - - case ConfirmationButton3::CANCEL: - abortThisProcess(); - break; - } - - assert(false); - return ProcessCallback::IGNORE_ERROR; //dummy return value -} - - -void CompareStatusHandler::reportFatalError(const std::wstring& errorMessage) -{ - forceUiRefresh(); - showNotificationDialog(&mainDlg, DialogInfoType::ERROR2, PopupDialogCfg().setTitle(_("Serious Error")).setDetailInstructions(errorMessage)); -} - - -void CompareStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) -{ - if (!warningActive || ignoreErrors) //if errors are ignored, then warnings should also - return; - - forceUiRefresh(); - - //show pop-up and ask user how to handle warning - bool dontWarnAgain = false; - switch (showConfirmationDialog(&mainDlg, DialogInfoType::WARNING, - PopupDialogCfg().setDetailInstructions(warningMessage). - setCheckBox(dontWarnAgain, _("&Don't show this warning again")), - _("&Ignore"))) - { - case ConfirmationButton::DO_IT: - warningActive = !dontWarnAgain; - break; - case ConfirmationButton::CANCEL: - abortThisProcess(); - break; - } -} - - -void CompareStatusHandler::forceUiRefresh() -{ - mainDlg.compareStatus->updateStatusPanelNow(); -} - - -void CompareStatusHandler::OnAbortCompare(wxCommandEvent& event) -{ - requestAbortion(); -} - - -void CompareStatusHandler::abortThisProcess() -{ - requestAbortion(); //just make sure... - throw GuiAbortProcess(); -} - -//######################################################################################################## - -SyncStatusHandler::SyncStatusHandler(wxFrame* parentDlg, - size_t lastSyncsLogFileSizeMax, - OnGuiError handleError, - size_t automaticRetryCount, - size_t automaticRetryDelay, - const std::wstring& jobName, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory) : - progressDlg(createProgressDialog(*this, [this] { this->onProgressDialogTerminate(); }, *this, parentDlg, true, jobName, execWhenFinished, execFinishedHistory)), - lastSyncsLogFileSizeMax_(lastSyncsLogFileSizeMax), - handleError_(handleError), - automaticRetryCount_(automaticRetryCount), - automaticRetryDelay_(automaticRetryDelay), - jobName_(jobName) -{ - totalTime.Start(); //measure total time -} - - -SyncStatusHandler::~SyncStatusHandler() -{ - //------------ "on completion" command conceptually is part of the sync, not cleanup -------------------------------------- - - //decide whether to stay on status screen or exit immediately... - bool showFinalResults = true; - - if (progressDlg) - { - //execute "on completion" command (even in case of ignored errors) - if (!abortIsRequested()) //if aborted (manually), we don't execute the command - { - const std::wstring finalCommand = progressDlg->getExecWhenFinishedCommand(); //final value (after possible user modification) - if (!finalCommand.empty()) - { - if (isCloseProgressDlgCommand(finalCommand)) - showFinalResults = false; //take precedence over current visibility status - else - try - { - tryReportingError([&] { shellExecute2(expandMacros(utfCvrtTo<Zstring>(finalCommand)), EXEC_TYPE_SYNC); }, //throw FileError, throw X? - *this); - } - catch (...) {} - } - } - } - //------------ end of sync: begin of cleanup -------------------------------------- - - const int totalErrors = errorLog.getItemCount(TYPE_ERROR | TYPE_FATAL_ERROR); //evaluate before finalizing log - const int totalWarnings = errorLog.getItemCount(TYPE_WARNING); - - //finalize error log - std::wstring finalStatus; - if (abortIsRequested()) - { - finalStatus = _("Synchronization stopped"); - errorLog.logMsg(finalStatus, TYPE_ERROR); - } - else if (totalErrors > 0) - { - finalStatus = _("Synchronization completed with errors"); - errorLog.logMsg(finalStatus, TYPE_ERROR); - } - else if (totalWarnings > 0) - { - finalStatus = _("Synchronization completed with warnings"); - errorLog.logMsg(finalStatus, TYPE_WARNING); //give status code same warning priority as display category! - } - else - { - if (getObjectsTotal(PHASE_SYNCHRONIZING) == 0 && //we're past "initNewPhase(PHASE_SYNCHRONIZING)" at this point! - getDataTotal (PHASE_SYNCHRONIZING) == 0) - finalStatus = _("Nothing to synchronize"); //even if "ignored conflicts" occurred! - else - finalStatus = _("Synchronization completed successfully"); - errorLog.logMsg(finalStatus, TYPE_INFO); - } - - const SummaryInfo summary = - { - jobName_, finalStatus, - getObjectsCurrent(PHASE_SYNCHRONIZING), getDataCurrent(PHASE_SYNCHRONIZING), - getObjectsTotal (PHASE_SYNCHRONIZING), getDataTotal (PHASE_SYNCHRONIZING), - totalTime.Time() / 1000 - }; - - try - { - saveToLastSyncsLog(summary, errorLog, lastSyncsLogFileSizeMax_); //throw FileError - } - catch (FileError&) {} - - if (progressDlg) - { - //notify to progressDlg that current process has ended - if (showFinalResults) - { - if (abortIsRequested()) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_ABORTED, errorLog); //enable okay and close events - else if (totalErrors > 0) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_ERROR, errorLog); - else if (totalWarnings > 0) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_WARNINGS, errorLog); - else - progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_SUCCESS, errorLog); - } - else - progressDlg->closeWindowDirectly(); - - //wait until progress dialog notified shutdown via onProgressDialogTerminate() - //-> required since it has our "this" pointer captured in lambda "notifyWindowTerminate"! - //-> nicely manages dialog lifetime - while (progressDlg) - { - wxTheApp->Yield(); //*first* refresh GUI (removing flicker) before sleeping! - boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL)); - } - } -} - - -void SyncStatusHandler::initNewPhase(int objectsTotal, Int64 dataTotal, Phase phaseID) -{ - assert(phaseID == PHASE_SYNCHRONIZING); - StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID); - if (progressDlg) - progressDlg->initNewPhase(); //call after "StatusHandler::initNewPhase" -} - - -void SyncStatusHandler::updateProcessedData(int objectsDelta, Int64 dataDelta) -{ - StatusHandler::updateProcessedData(objectsDelta, dataDelta); - if (progressDlg) - progressDlg->notifyProgressChange(); //noexcept - //note: this method should NOT throw in order to properly allow undoing setting of statistics! -} - - -void SyncStatusHandler::reportInfo(const std::wstring& text) -{ - StatusHandler::reportInfo(text); - errorLog.logMsg(text, TYPE_INFO); -} - - -ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& errorMessage, size_t retryNumber) -{ - //auto-retry - if (retryNumber < automaticRetryCount_) - { - errorLog.logMsg(errorMessage + L"\n=> " + - _P("Automatic retry in 1 second...", "Automatic retry in %x seconds...", automaticRetryDelay_), TYPE_INFO); - //delay - const int iterations = static_cast<int>(1000 * automaticRetryDelay_ / UI_UPDATE_INTERVAL); //always round down: don't allow for negative remaining time below - for (int i = 0; i < iterations; ++i) - { - reportStatus(_("Error") + L": " + _P("Automatic retry in 1 second...", "Automatic retry in %x seconds...", - (1000 * automaticRetryDelay_ - i * UI_UPDATE_INTERVAL + 999) / 1000)); //integer round up - boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL)); - } - return ProcessCallback::RETRY; - } - - - //always, except for "retry": - zen::ScopeGuard guardWriteLog = zen::makeGuard([&] { errorLog.logMsg(errorMessage, TYPE_ERROR); }); - - switch (handleError_) - { - case ON_GUIERROR_POPUP: - { - if (!progressDlg) abortThisProcess(); - PauseTimers dummy(*progressDlg); - forceUiRefresh(); - - bool ignoreNextErrors = false; - switch (showConfirmationDialog3(progressDlg->getWindowIfVisible(), DialogInfoType::ERROR2, PopupDialogCfg3(). - setDetailInstructions(errorMessage). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors"), ConfirmationButton3::DONT_DO_IT), - _("&Ignore"), _("&Retry"))) - { - case ConfirmationButton3::DO_IT: //ignore - if (ignoreNextErrors) //falsify only - handleError_ = ON_GUIERROR_IGNORE; - return ProcessCallback::IGNORE_ERROR; - - case ConfirmationButton3::DONT_DO_IT: //retry - guardWriteLog.dismiss(); - errorLog.logMsg(errorMessage + L"\n=> " + _("Retrying operation..."), TYPE_INFO); //explain why there are duplicate "doing operation X" info messages in the log! - return ProcessCallback::RETRY; - - case ConfirmationButton3::CANCEL: - abortThisProcess(); - break; - } - } - break; - - case ON_GUIERROR_IGNORE: - return ProcessCallback::IGNORE_ERROR; - } - - assert(false); - return ProcessCallback::IGNORE_ERROR; //dummy value -} - - -void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage) -{ - errorLog.logMsg(errorMessage, TYPE_FATAL_ERROR); - - switch (handleError_) - { - case ON_GUIERROR_POPUP: - { - if (!progressDlg) abortThisProcess(); - PauseTimers dummy(*progressDlg); - forceUiRefresh(); - - bool ignoreNextErrors = false; - switch (showConfirmationDialog(progressDlg->getWindowIfVisible(), DialogInfoType::ERROR2, - PopupDialogCfg().setTitle(_("Serious Error")). - setDetailInstructions(errorMessage). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors")), - _("&Ignore"))) - { - case ConfirmationButton::DO_IT: - if (ignoreNextErrors) //falsify only - handleError_ = ON_GUIERROR_IGNORE; - break; - case ConfirmationButton::CANCEL: - abortThisProcess(); - break; - } - } - break; - - case ON_GUIERROR_IGNORE: - break; - } -} - - -void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) -{ - errorLog.logMsg(warningMessage, TYPE_WARNING); - - if (!warningActive) - return; - - switch (handleError_) - { - case ON_GUIERROR_POPUP: - { - if (!progressDlg) abortThisProcess(); - PauseTimers dummy(*progressDlg); - forceUiRefresh(); - - bool dontWarnAgain = false; - switch (showConfirmationDialog(progressDlg->getWindowIfVisible(), DialogInfoType::WARNING, - PopupDialogCfg().setDetailInstructions(warningMessage). - setCheckBox(dontWarnAgain, _("&Don't show this warning again")), - _("&Ignore"))) - { - case ConfirmationButton::DO_IT: - warningActive = !dontWarnAgain; - break; - case ConfirmationButton::CANCEL: - abortThisProcess(); - break; - } - } - break; - - case ON_GUIERROR_IGNORE: - break; //if errors are ignored, then warnings should be, too - } -} - - -void SyncStatusHandler::forceUiRefresh() -{ - if (progressDlg) - progressDlg->updateGui(); -} - - -void SyncStatusHandler::abortThisProcess() -{ - requestAbortion(); //just make sure... - throw GuiAbortProcess(); //abort can be triggered by progressDlg -} - - -void SyncStatusHandler::onProgressDialogTerminate() -{ - //it's responsibility of "progressDlg" to call requestAbortion() when closing dialog - progressDlg = nullptr; -} diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h deleted file mode 100644 index fbbf827f..00000000 --- a/ui/gui_status_handler.h +++ /dev/null @@ -1,86 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef GUISTATUSHANDLER_H_INCLUDED -#define GUISTATUSHANDLER_H_INCLUDED - -#include <wx/event.h> -#include <zen/error_log.h> -#include <wx/stopwatch.h> -#include "progress_indicator.h" -#include "../lib/status_handler.h" -#include "../lib/process_xml.h" -#include "main_dlg.h" - - -//Exception class used to abort the "compare" and "sync" process -class GuiAbortProcess {}; - -//classes handling sync and compare error as well as status information - -//CompareStatusHandler(CompareProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! -class CompareStatusHandler : private wxEvtHandler, public zen::StatusHandler //throw GuiAbortProcess -{ -public: - CompareStatusHandler(MainDialog& dlg); - ~CompareStatusHandler(); - - virtual void initNewPhase(int objectsTotal, zen::Int64 dataTotal, Phase phaseID); - virtual void forceUiRefresh(); - - virtual Response reportError(const std::wstring& text, size_t retryNumber); - virtual void reportFatalError(const std::wstring& errorMessage); - virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); - -private: - void OnKeyPressed(wxKeyEvent& event); - void OnAbortCompare(wxCommandEvent& event); //handle abort button click - virtual void abortThisProcess(); //throw GuiAbortProcess - - MainDialog& mainDlg; - bool ignoreErrors; -}; - - -//SyncStatusHandler(SyncProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! -class SyncStatusHandler : public zen::StatusHandler -{ -public: - SyncStatusHandler(wxFrame* parentDlg, - size_t lastSyncsLogFileSizeMax, - xmlAccess::OnGuiError handleError, - size_t automaticRetryCount, - size_t automaticRetryDelay, - const std::wstring& jobName, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory); - ~SyncStatusHandler(); - - virtual void initNewPhase (int objectsTotal, zen::Int64 dataTotal, Phase phaseID); - virtual void updateProcessedData(int objectsDelta, zen::Int64 dataDelta); - virtual void reportInfo(const std::wstring& text); - virtual void forceUiRefresh(); - - virtual Response reportError(const std::wstring& text, size_t retryNumber); - virtual void reportFatalError(const std::wstring& errorMessage); - virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); - -private: - virtual void abortThisProcess(); //throw GuiAbortProcess - void onProgressDialogTerminate(); - - SyncProgressDialog* progressDlg; //managed to have shorter lifetime than this handler! - const size_t lastSyncsLogFileSizeMax_; - xmlAccess::OnGuiError handleError_; - zen::ErrorLog errorLog; - const size_t automaticRetryCount_; - const size_t automaticRetryDelay_; - const std::wstring jobName_; - wxStopWatch totalTime; -}; - - -#endif // GUISTATUSHANDLER_H_INCLUDED diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp deleted file mode 100644 index 8ca9cc0b..00000000 --- a/ui/main_dlg.cpp +++ /dev/null @@ -1,4547 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "main_dlg.h" -#include <zen/format_unit.h> -#include <zen/file_handling.h> -#include <zen/serialize.h> -//#include <zen/perf.h> -#include <zen/thread.h> -#include <zen/shell_execute.h> -#include <wx/clipbrd.h> -#include <wx/wupdlock.h> -#include <wx/sound.h> -#include <wx/filedlg.h> -#include <wx/display.h> -#include <wx+/context_menu.h> -#include <wx+/string_conv.h> -#include <wx+/bitmap_button.h> -#include <wx+/app_main.h> -#include <wx+/toggle_button.h> -#include <wx+/mouse_move_dlg.h> -#include <wx+/no_flicker.h> -#include <wx+/rtl.h> -#include <wx+/font_size.h> -#include <wx+/popup_dlg.h> -#include <wx+/image_resources.h> -#include "check_version.h" -#include "gui_status_handler.h" -#include "sync_cfg.h" -#include "small_dlgs.h" -#include "progress_indicator.h" -#include "folder_pair.h" -#include "search.h" -#include "batch_config.h" -#include "triple_splitter.h" -#include "app_icon.h" -//#include "config_history.h" -#include "../comparison.h" -#include "../synchronization.h" -#include "../algorithm.h" -#include "../lib/resolve_path.h" -#include "../lib/ffs_paths.h" -#include "../lib/help_provider.h" -#include "../lib/lock_holder.h" -#include "../lib/localization.h" - -#ifdef ZEN_MAC -#include <ApplicationServices/ApplicationServices.h> -#endif - -using namespace zen; -using namespace std::rel_ops; - - -namespace -{ -struct wxClientHistoryData : public wxClientData //we need a wxClientData derived class to tell wxWidgets to take object ownership! -{ - wxClientHistoryData(const Zstring& cfgFile, int lastUseIndex) : cfgFile_(cfgFile), lastUseIndex_(lastUseIndex) {} - - Zstring cfgFile_; - int lastUseIndex_; //support sorting history by last usage, the higher the index the more recent the usage -}; - -IconBuffer::IconSize convert(xmlAccess::FileIconSize isize) -{ - using namespace xmlAccess; - switch (isize) - { - case ICON_SIZE_SMALL: - return IconBuffer::SIZE_SMALL; - case ICON_SIZE_MEDIUM: - return IconBuffer::SIZE_MEDIUM; - case ICON_SIZE_LARGE: - return IconBuffer::SIZE_LARGE; - } - return IconBuffer::SIZE_SMALL; -} -} - - -class DirectoryNameMainImpl : public DirectoryName<FolderHistoryBox> -{ -public: - DirectoryNameMainImpl(MainDialog& mainDlg, - wxWindow& dropWindow1, - Grid& dropGrid, - wxButton& dirSelectButton, - FolderHistoryBox& dirName, - wxStaticText& staticText) : - DirectoryName(dropWindow1, dirSelectButton, dirName, &staticText, &dropGrid.getMainWin()), - mainDlg_(mainDlg) {} - - virtual bool acceptDrop(const std::vector<wxString>& droppedFiles, const wxPoint& clientPos, const wxWindow& wnd) - { - if (std::any_of(droppedFiles.begin(), droppedFiles.end(), [](const wxString& filename) - { - using namespace xmlAccess; - switch (getXmlType(utfCvrtTo<Zstring>(filename))) //throw() - { - case XML_TYPE_GUI: - case XML_TYPE_BATCH: - return true; - case XML_TYPE_GLOBAL: - case XML_TYPE_OTHER: - break; - } - return false; - })) - { - mainDlg_.loadConfiguration(toZ(droppedFiles)); - return false; - } - - //=> return true: change directory selection via drag and drop - return true; - } - -private: - DirectoryNameMainImpl(const DirectoryNameMainImpl&); - DirectoryNameMainImpl& operator=(const DirectoryNameMainImpl&); - - MainDialog& mainDlg_; -}; - -//------------------------------------------------------------------ -/* class hierarchy: - - template<> - FolderPairPanelBasic - /|\ - | - template<> - FolderPairCallback FolderPairPanelGenerated - /|\ /|\ - _________|________ ________| - | | | - FolderPairFirst FolderPairPanel -*/ - -template <class GuiPanel> -class FolderPairCallback : public FolderPairPanelBasic<GuiPanel> //implements callback functionality to MainDialog as imposed by FolderPairPanelBasic -{ -public: - FolderPairCallback(GuiPanel& basicPanel, MainDialog& mainDialog) : - FolderPairPanelBasic<GuiPanel>(basicPanel), //pass FolderPairPanelGenerated part... - mainDlg(mainDialog) {} - -private: - virtual MainConfiguration getMainConfig() const { return mainDlg.getConfig().mainCfg; } - virtual wxWindow* getParentWindow() { return &mainDlg; } - virtual std::unique_ptr<FilterConfig>& getFilterCfgOnClipboardRef() { return mainDlg.filterCfgOnClipboard; } - - virtual void onAltCompCfgChange () { mainDlg.applyCompareConfig(); } - virtual void onAltSyncCfgChange () { mainDlg.applySyncConfig(); } - virtual void onLocalFilterCfgChange() { mainDlg.applyFilterConfig(); } //re-apply filter - - MainDialog& mainDlg; -}; - - -class FolderPairPanel : - public FolderPairPanelGenerated, //FolderPairPanel "owns" FolderPairPanelGenerated! - public FolderPairCallback<FolderPairPanelGenerated> -{ -public: - FolderPairPanel(wxWindow* parent, MainDialog& mainDialog) : - FolderPairPanelGenerated(parent), - FolderPairCallback<FolderPairPanelGenerated>(static_cast<FolderPairPanelGenerated&>(*this), mainDialog), //pass FolderPairPanelGenerated part... - dirNameLeft (*m_panelLeft, *m_buttonSelectDirLeft, *m_directoryLeft), - dirNameRight(*m_panelRight, *m_buttonSelectDirRight, *m_directoryRight) - { - dirNameLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - dirNameRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - - dirNameLeft .Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); - dirNameRight.Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); - } - - void setValues(const Zstring& leftDir, - const Zstring& rightDir, - AltCompCfgPtr cmpCfg, - AltSyncCfgPtr syncCfg, - const FilterConfig& filter) - { - setConfig(cmpCfg, syncCfg, filter); - dirNameLeft .setName(toWx(leftDir)); - dirNameRight.setName(toWx(rightDir)); - } - Zstring getLeftDir () const { return toZ(dirNameLeft .getName()); } - Zstring getRightDir() const { return toZ(dirNameRight.getName()); } - -private: - //support for drag and drop - DirectoryName<FolderHistoryBox> dirNameLeft; - DirectoryName<FolderHistoryBox> dirNameRight; -}; - - -class FolderPairFirst : public FolderPairCallback<MainDialogGenerated> -{ -public: - FolderPairFirst(MainDialog& mainDialog) : - FolderPairCallback<MainDialogGenerated>(mainDialog, mainDialog), - - //prepare drag & drop - dirNameLeft(mainDialog, - *mainDialog.m_panelTopLeft, - *mainDialog.m_gridMainL, - *mainDialog.m_buttonSelectDirLeft, - *mainDialog.m_directoryLeft, - *mainDialog.m_staticTextResolvedPathL), - dirNameRight(mainDialog, - *mainDialog.m_panelTopRight, - *mainDialog.m_gridMainR, - *mainDialog.m_buttonSelectDirRight, - *mainDialog.m_directoryRight, - *mainDialog.m_staticTextResolvedPathR) - { - dirNameLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - dirNameRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - - dirNameLeft .Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); - dirNameRight.Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); - } - - void setValues(const Zstring& leftDir, - const Zstring& rightDir, - AltCompCfgPtr cmpCfg, - AltSyncCfgPtr syncCfg, - const FilterConfig& filter) - { - setConfig(cmpCfg, syncCfg, filter); - dirNameLeft .setName(toWx(leftDir)); - dirNameRight.setName(toWx(rightDir)); - } - Zstring getLeftDir () const { return toZ(dirNameLeft .getName()); } - Zstring getRightDir() const { return toZ(dirNameRight.getName()); } - -private: - //support for drag and drop - DirectoryNameMainImpl dirNameLeft; - DirectoryNameMainImpl dirNameRight; -}; - - -#ifdef ZEN_WIN -class PanelMoveWindow : public MouseMoveWindow -{ -public: - PanelMoveWindow(MainDialog& mainDlg) : - MouseMoveWindow(mainDlg, false), //don't include main dialog itself, thereby prevent various mouse capture lost issues - mainDlg_(mainDlg) {} - - virtual bool allowMove(const wxMouseEvent& event) - { - if (wxPanel* panel = dynamic_cast<wxPanel*>(event.GetEventObject())) - { - const wxAuiPaneInfo& paneInfo = mainDlg_.auiMgr.GetPane(panel); - if (paneInfo.IsOk() && - paneInfo.IsFloating()) - return false; //prevent main dialog move - } - - return true; //allow dialog move - } - -private: - MainDialog& mainDlg_; -}; -#endif - - -namespace -{ -//workaround for wxWidgets bug failing to update menu item bitmaps (affects Windows- and Linux-build) -void setMenuItemImage(wxMenuItem*& menuItem, const wxBitmap& bmp) -{ - assert(menuItem->GetKind() == wxITEM_NORMAL); - - //support polling - if (isEqual(bmp, menuItem->GetBitmap())) - return; - - if (wxMenu* menu = menuItem->GetMenu()) - { - int pos = menu->GetMenuItems().IndexOf(menuItem); - if (pos != wxNOT_FOUND) - { - /* - menu->Remove(menuItem); ->this simple sequence crashes on Kubuntu x64, wxWidgets 2.9.2 - menu->Insert(pos, menuItem); - */ - const bool enabled = menuItem->IsEnabled(); - wxMenuItem* newItem = new wxMenuItem(menu, menuItem->GetId(), menuItem->GetItemLabel()); - - newItem->SetBitmap(bmp); -#ifdef __WXMSW__ //not availabe on wxGTK or wxOSX - //for some inconceivable reason wxWidgets is not consistent with itself and renders disabled icons - //just greyscale instead of brightened like bitmap buttons; much better: - newItem->SetDisabledBitmap(bmp.ConvertToDisabled()); -#endif - bool isDestroyed = menu->Destroy(menuItem); //actual workaround - assert(isDestroyed); - (void)isDestroyed; - menuItem = menu->Insert(pos, newItem); //don't forget to update input item pointer! - - if (!enabled) - menuItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason - } - } -} - -//################################################################################################################################## - -xmlAccess::XmlGlobalSettings retrieveGlobalCfgFromDisk() //blocks on GUI on errors! -{ - using namespace xmlAccess; - XmlGlobalSettings globalCfg; - try - { - if (fileExists(getGlobalConfigFile())) - readConfig(globalCfg); //throw FfsXmlError - //else: globalCfg already has default values - } - catch (const FfsXmlError& e) - { - assert(false); - if (e.getSeverity() != FfsXmlError::WARNING) //ignore parsing errors: should be migration problems only *cross-fingers* - showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); //no parent window: main dialog not yet created! - } - return globalCfg; -} -} - - -void MainDialog::create() -{ - using namespace xmlAccess; - const XmlGlobalSettings globalSettings = retrieveGlobalCfgFromDisk(); - - std::vector<Zstring> filenames = globalSettings.gui.lastUsedConfigFiles; //2. now try last used files - - //------------------------------------------------------------------------------------------ - //check existence of all files in parallel: - RunUntilFirstHit<NullType> findFirstMissing; - - std::for_each(filenames.begin(), filenames.end(), [&](const Zstring& filename) - { - findFirstMissing.addJob([=] { return filename.empty() /*ever empty??*/ || !fileExists(filename) ? zen::make_unique<NullType>() : nullptr; }); - }); - //potentially slow network access: give all checks 500ms to finish - const bool allFilesExist = findFirstMissing.timedWait(boost::posix_time::milliseconds(500)) && //false: time elapsed - !findFirstMissing.get(); //no missing - if (!allFilesExist) - filenames.clear(); //we do NOT want to show an error due to last config file missing on application start! - //------------------------------------------------------------------------------------------ - - if (filenames.empty()) - { - if (zen::fileExists(lastRunConfigName())) //3. try to load auto-save config - filenames.push_back(lastRunConfigName()); - } - - XmlGuiConfig guiCfg; //structure to receive gui settings with default values - - if (filenames.empty()) - { - //add default exclusion filter: this is only ever relevant when creating new configurations! - //a default XmlGuiConfig does not need these user-specific exclusions! - Zstring& excludeFilter = guiCfg.mainCfg.globalFilter.excludeFilter; - if (!excludeFilter.empty() && !endsWith(excludeFilter, Zstr("\n"))) - excludeFilter += Zstr("\n"); - excludeFilter += globalSettings.gui.defaultExclusionFilter; - } - else - try - { - readAnyConfig(filenames, guiCfg); //throw FfsXmlError - } - catch (const FfsXmlError& e) - { - if (e.getSeverity() == FfsXmlError::WARNING) - showNotificationDialog(nullptr, DialogInfoType::WARNING, PopupDialogCfg().setDetailInstructions(e.toString())); - //what about simulating changed config on parsing errors???? - else - showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - } - - //------------------------------------------------------------------------------------------ - - create(guiCfg, filenames, &globalSettings, false); -} - - -void MainDialog::create(const xmlAccess::XmlGuiConfig& guiCfg, - const std::vector<Zstring>& referenceFiles, - const xmlAccess::XmlGlobalSettings* globalSettings, - bool startComparison) -{ - const xmlAccess::XmlGlobalSettings& globSett = globalSettings ? *globalSettings : retrieveGlobalCfgFromDisk(); - try - { - //we need to set language *before* creating MainDialog! - setLanguage(globSett.programLanguage); //throw FileError - } - catch (const FileError& e) - { - showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - //continue! - } - - MainDialog* frame = new MainDialog(guiCfg, referenceFiles, globSett, startComparison); - frame->Show(); -#ifdef ZEN_MAC - ProcessSerialNumber psn = { 0, kCurrentProcess }; - ::SetFrontProcess(&psn); //call before TransformProcessType() so that OSX menu is updated correctly - ::TransformProcessType(&psn, kProcessTransformToForegroundApplication); //show dock icon, even if we're not an application bundle - //if the executable is not yet in a bundle or if it is called through a launcher, we need to set focus manually: -#endif -} - - -MainDialog::MainDialog(const xmlAccess::XmlGuiConfig& guiCfg, - const std::vector<Zstring>& referenceFiles, - const xmlAccess::XmlGlobalSettings& globalSettings, - bool startComparison) : - MainDialogGenerated(nullptr), - folderHistoryLeft (std::make_shared<FolderHistory>()), //make sure it is always bound - folderHistoryRight(std::make_shared<FolderHistory>()), // - focusWindowAfterSearch(nullptr) -{ - m_directoryLeft ->init(folderHistoryLeft); - m_directoryRight->init(folderHistoryRight); - - //setup sash: detach + reparent: - m_splitterMain->SetSizer(nullptr); //alas wxFormbuilder doesn't allow us to have child windows without a sizer, so we have to remove it here - m_splitterMain->setupWindows(m_gridMainL, m_gridMainC, m_gridMainR); - -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - setRelativeFontSize(*m_buttonCompare, 1.4); - setRelativeFontSize(*m_buttonSync, 1.4); - setRelativeFontSize(*m_buttonCancel, 1.4); - - //---------------- support for dockable gui style -------------------------------- - bSizerPanelHolder->Detach(m_panelTopButtons); - bSizerPanelHolder->Detach(m_panelDirectoryPairs); - bSizerPanelHolder->Detach(m_gridNavi); - bSizerPanelHolder->Detach(m_panelCenter); - bSizerPanelHolder->Detach(m_panelConfig); - bSizerPanelHolder->Detach(m_panelFilter); - bSizerPanelHolder->Detach(m_panelViewFilter); - bSizerPanelHolder->Detach(m_panelStatistics); - - auiMgr.SetManagedWindow(this); - auiMgr.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE); - - compareStatus = make_unique<CompareProgressDialog>(*this); //integrate the compare status panel (in hidden state) - - //caption required for all panes that can be manipulated by the users => used by context menu - auiMgr.AddPane(m_panelCenter, - wxAuiPaneInfo().Name(L"Panel3").CenterPane().PaneBorder(false)); - - auiMgr.AddPane(m_panelDirectoryPairs, - wxAuiPaneInfo().Name(L"Panel2").Layer(2).Top().Caption(_("Folder Pairs")).CaptionVisible(false).PaneBorder(false).Gripper()); - - auiMgr.AddPane(m_panelSearch, - wxAuiPaneInfo().Name(L"PanelFind").Layer(2).Bottom().Caption(_("Find")).CaptionVisible(false).PaneBorder(false).Gripper().MinSize(200, m_bpButtonHideSearch->GetSize().GetHeight()).Hide()); - - auiMgr.AddPane(m_gridNavi, - wxAuiPaneInfo().Name(L"Panel10").Layer(3).Left().Position(1).Caption(_("Overview")).MinSize(300, m_gridNavi->GetSize().GetHeight())); //MinSize(): just default size, see comment below - - auiMgr.AddPane(m_panelConfig, - wxAuiPaneInfo().Name(L"Panel4").Layer(3).Left().Position(2).Caption(_("Configuration")).MinSize(m_listBoxHistory->GetSize().GetWidth(), m_panelConfig->GetSize().GetHeight())); - - auiMgr.AddPane(m_panelTopButtons, - wxAuiPaneInfo().Name(L"Panel1").Layer(4).Top().Row(1).Caption(_("Main Bar")).CaptionVisible(false).PaneBorder(false).Gripper().MinSize(-1, m_panelTopButtons->GetSize().GetHeight())); - //note: min height is calculated incorrectly by wxAuiManager if panes with and without caption are in the same row => use smaller min-size - - auiMgr.AddPane(compareStatus->getAsWindow(), - wxAuiPaneInfo().Name(L"Panel9").Layer(4).Top().Row(2).CaptionVisible(false).PaneBorder(false).Hide()); - - auiMgr.AddPane(m_panelFilter, - wxAuiPaneInfo().Name(L"Panel5").Layer(4).Bottom().Position(1).Caption(_("Filter Files")).MinSize(m_bpButtonFilter->GetSize().GetWidth(), m_panelFilter->GetSize().GetHeight())); - - auiMgr.AddPane(m_panelViewFilter, - wxAuiPaneInfo().Name(L"Panel6").Layer(4).Bottom().Position(2).Caption(_("Select View")).MinSize(m_bpButtonShowDoNothing->GetSize().GetWidth(), m_panelViewFilter->GetSize().GetHeight())); - - auiMgr.AddPane(m_panelStatistics, - wxAuiPaneInfo().Name(L"Panel7").Layer(4).Bottom().Position(3).Caption(_("Statistics")).MinSize(m_bitmapData->GetSize().GetWidth() + m_staticTextData->GetSize().GetWidth(), m_panelStatistics->GetSize().GetHeight())); - - auiMgr.Update(); - - //give panel captions bold typeface - if (wxAuiDockArt* artProvider = auiMgr.GetArtProvider()) - { - wxFont font = artProvider->GetFont(wxAUI_DOCKART_CAPTION_FONT); - font.SetWeight(wxFONTWEIGHT_BOLD); - font.SetPointSize(wxNORMAL_FONT->GetPointSize()); //= larger than the wxAuiDockArt default; looks better on OS X - artProvider->SetFont(wxAUI_DOCKART_CAPTION_FONT, font); - - //accessibility: fix wxAUI drawing black text on black background on high-contrast color schemes: - artProvider->SetColor(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - } - - auiMgr.GetPane(m_gridNavi).MinSize(-1, -1); //we successfully tricked wxAuiManager into setting an initial Window size :> incomplete API anyone?? - auiMgr.Update(); // - - defaultPerspective = auiMgr.SavePerspective(); - //---------------------------------------------------------------------------------- - //register view layout context menu - m_panelTopButtons->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), nullptr, this); - m_panelConfig ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), nullptr, this); - m_panelFilter ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), nullptr, this); - m_panelViewFilter->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), nullptr, this); - m_panelStatistics->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), nullptr, this); - m_panelStatusBar ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), nullptr, this); - //---------------------------------------------------------------------------------- - - //sort grids - m_gridMainL->Connect(EVENT_GRID_COL_LABEL_MOUSE_LEFT, GridClickEventHandler(MainDialog::onGridLabelLeftClickL ), nullptr, this); - m_gridMainC->Connect(EVENT_GRID_COL_LABEL_MOUSE_LEFT, GridClickEventHandler(MainDialog::onGridLabelLeftClickC ), nullptr, this); - m_gridMainR->Connect(EVENT_GRID_COL_LABEL_MOUSE_LEFT, GridClickEventHandler(MainDialog::onGridLabelLeftClickR ), nullptr, this); - - m_gridMainL->Connect(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, GridClickEventHandler(MainDialog::onGridLabelContextL ), nullptr, this); - m_gridMainC->Connect(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, GridClickEventHandler(MainDialog::onGridLabelContextC ), nullptr, this); - m_gridMainR->Connect(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, GridClickEventHandler(MainDialog::onGridLabelContextR ), nullptr, this); - - //grid context menu - m_gridMainL->Connect(EVENT_GRID_MOUSE_RIGHT_UP, GridClickEventHandler(MainDialog::onMainGridContextL), nullptr, this); - m_gridMainC->Connect(EVENT_GRID_MOUSE_RIGHT_UP, GridClickEventHandler(MainDialog::onMainGridContextC), nullptr, this); - m_gridMainR->Connect(EVENT_GRID_MOUSE_RIGHT_UP, GridClickEventHandler(MainDialog::onMainGridContextR), nullptr, this); - m_gridNavi ->Connect(EVENT_GRID_MOUSE_RIGHT_UP, GridClickEventHandler(MainDialog::onNaviGridContext ), nullptr, this); - - m_gridMainL->Connect(EVENT_GRID_MOUSE_LEFT_DOUBLE, GridClickEventHandler(MainDialog::onGridDoubleClickL), nullptr, this ); - m_gridMainR->Connect(EVENT_GRID_MOUSE_LEFT_DOUBLE, GridClickEventHandler(MainDialog::onGridDoubleClickR), nullptr, this ); - - m_gridNavi->Connect(EVENT_GRID_SELECT_RANGE, GridRangeSelectEventHandler(MainDialog::onNaviSelection), nullptr, this); - //---------------------------------------------------------------------------------- - - m_panelSearch->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnSearchPanelKeyPressed), nullptr, this); - - //set tool tips with (non-translated!) short cut hint - m_bpButtonOpen ->SetToolTip(_("Open...") + L" (Ctrl+O)"); - m_bpButtonSave ->SetToolTip(_("Save") + L" (Ctrl+S)"); - m_buttonCompare ->SetToolTip(_("Compare both sides") + L" (F5)"); - m_bpButtonCmpConfig ->SetToolTip(_("Comparison settings") + L" (F6)"); - m_bpButtonSyncConfig->SetToolTip(_("Synchronization settings") + L" (F7)"); - m_buttonSync ->SetToolTip(_("Start synchronization") + L" (F8)"); - - gridDataView = std::make_shared<GridView>(); - treeDataView = std::make_shared<TreeView>(); - - cleanedUp = false; - processingGlobalKeyEvent = false; - -#ifdef ZEN_WIN - new PanelMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere... //ownership passed to "this" -#endif - - //set icons for this dialog - SetIcon(getFfsIcon()); //set application icon - - m_bpButtonSyncConfig->SetBitmapLabel(getResourceImage(L"cfg_sync")); - m_bpButtonCmpConfig ->SetBitmapLabel(getResourceImage(L"cfg_compare")); - m_bpButtonOpen ->SetBitmapLabel(getResourceImage(L"load")); - m_bpButtonBatchJob ->SetBitmapLabel(getResourceImage(L"batch")); - m_bpButtonAddPair ->SetBitmapLabel(getResourceImage(L"item_add")); - m_bpButtonHideSearch->SetBitmapLabel(getResourceImage(L"close_panel")); - - //we can't use a wxButton for cancel: it's rendered smaller on OS X than a wxBitmapButton! - setBitmapTextLabel(*m_buttonCancel, wxImage(), m_buttonCancel->GetLabel()); - - { - IconBuffer tmp(IconBuffer::SIZE_SMALL); - const wxBitmap& bmpFile = tmp.genericFileIcon(); - const wxBitmap& bmpDir = tmp.genericDirIcon(); - - m_bitmapSmallDirectoryLeft ->SetBitmap(bmpDir); - m_bitmapSmallFileLeft ->SetBitmap(bmpFile); - m_bitmapSmallDirectoryRight->SetBitmap(bmpDir); - m_bitmapSmallFileRight ->SetBitmap(bmpFile); - } - - //menu icons: workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build) - setMenuItemImage(m_menuItem10, getResourceImage(L"compare_small")); - setMenuItemImage(m_menuItem11, getResourceImage(L"sync_small")); - - setMenuItemImage(m_menuItemLoad, getResourceImage(L"load_small")); - setMenuItemImage(m_menuItemSave, getResourceImage(L"save_small")); - - setMenuItemImage(m_menuItemGlobSett, getResourceImage(L"settings_small")); - setMenuItemImage(m_menuItem7, getResourceImage(L"batch_small")); - - setMenuItemImage(m_menuItemManual, getResourceImage(L"help_small")); - setMenuItemImage(m_menuItemAbout, getResourceImage(L"about_small")); - - if (!manualProgramUpdateRequired()) - { - m_menuItemCheckVersionNow ->Enable(false); - m_menuItemCheckVersionAuto->Enable(false); - - //wxFormbuilder doesn't give us a wxMenuItem for m_menuCheckVersion, so we need this abomination: - wxMenuItemList& items = m_menuHelp->GetMenuItems(); - for (auto it = items.begin(); it != items.end(); ++it) - if ((*it)->GetSubMenu() == m_menuCheckVersion) - (*it)->Enable(false); - } - - //create language selection menu - std::for_each(zen::ExistingTranslations::get().begin(), ExistingTranslations::get().end(), - [&](const ExistingTranslations::Entry& entry) - { - wxMenuItem* newItem = new wxMenuItem(m_menuLanguages, wxID_ANY, entry.languageName); - newItem->SetBitmap(getResourceImage(entry.languageFlag)); - - //map menu item IDs with language IDs: evaluated when processing event handler - languageMenuItemMap.insert(std::make_pair(newItem->GetId(), entry.languageID)); - - //connect event - this->Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnMenuLanguageSwitch)); - m_menuLanguages->Append(newItem); - }); - - //notify about (logical) application main window => program won't quit, but stay on this dialog - zen::setMainWindow(this); - - //init handling of first folder pair - firstFolderPair = make_unique<FolderPairFirst>(*this); - - initViewFilterButtons(); - - //init grid settings - gridview::init(*m_gridMainL, *m_gridMainC, *m_gridMainR, gridDataView); - treeview::init(*m_gridNavi, treeDataView); - //config_history::init(*m_gridConfigHistory, lastRunConfigName()); - - //initialize and load configuration - setGlobalCfgOnInit(globalSettings); - setConfig(guiCfg, referenceFiles); - - //support for CTRL + C and DEL on grids - m_gridMainL->getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGridButtonEventL), nullptr, this); - m_gridMainC->getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGridButtonEventC), nullptr, this); - m_gridMainR->getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGridButtonEventR), nullptr, this); - - m_gridNavi->getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onTreeButtonEvent), nullptr, this); - - //register global hotkeys (without explicit menu entry) - wxTheApp->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this); - wxTheApp->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this); //capture direction keys - - //drag & drop on navi panel - setupFileDrop(*m_gridNavi); - m_gridNavi->Connect(EVENT_DROP_FILE, FileDropEventHandler(MainDialog::onNaviPanelFilesDropped), nullptr, this); - - timerForAsyncTasks.Connect(wxEVT_TIMER, wxEventHandler(MainDialog::onProcessAsyncTasks), nullptr, this); - - //Connect(wxEVT_SIZE, wxSizeEventHandler(MainDialog::OnResize), nullptr, this); - //Connect(wxEVT_MOVE, wxSizeEventHandler(MainDialog::OnResize), nullptr, this); - - //calculate witdh of folder pair manually (if scrollbars are visible) - m_panelTopLeft->Connect(wxEVT_SIZE, wxEventHandler(MainDialog::OnResizeLeftFolderWidth), nullptr, this); - - //dynamically change sizer direction depending on size - m_panelConfig ->Connect(wxEVT_SIZE, wxEventHandler(MainDialog::OnResizeConfigPanel), nullptr, this); - m_panelViewFilter->Connect(wxEVT_SIZE, wxEventHandler(MainDialog::OnResizeViewPanel), nullptr, this); - m_panelStatistics->Connect(wxEVT_SIZE, wxEventHandler(MainDialog::OnResizeStatisticsPanel), nullptr, this); - wxSizeEvent dummy3; - OnResizeConfigPanel (dummy3); //call once on window creation - OnResizeViewPanel (dummy3); // - OnResizeStatisticsPanel(dummy3); // - - //event handler for manual (un-)checking of rows and setting of sync direction - m_gridMainC->Connect(EVENT_GRID_CHECK_ROWS, CheckRowsEventHandler (MainDialog::onCheckRows), nullptr, this); - m_gridMainC->Connect(EVENT_GRID_SYNC_DIRECTION, SyncDirectionEventHandler(MainDialog::onSetSyncDirection), nullptr, this); - - //mainly to update row label sizes... - updateGui(); - - //register regular check for update on next idle event - Connect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), nullptr, this); - - //asynchronous call to wxWindow::Layout(): fix superfluous frame on right and bottom when FFS is started in fullscreen mode - Connect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnLayoutWindowAsync), nullptr, this); - wxCommandEvent evtDummy; //call once before OnLayoutWindowAsync() - OnResizeLeftFolderWidth(evtDummy); // - - //---------------------------------------------------------------------------------------------------------------------------------------------------------------- - //some convenience: if FFS is started with a *.ffs_gui file as commandline parameter AND all directories contained exist, comparison shall be started right away - if (startComparison) - { - const zen::MainConfiguration currMainCfg = getConfig().mainCfg; - - //------------------------------------------------------------------------------------------ - //check existence of all directories in parallel! - RunUntilFirstHit<NullType> findFirstMissing; - - //harmonize checks with comparison.cpp:: checkForIncompleteInput() - //we're really doing two checks: 1. check directory existence 2. check config validity -> don't mix them! - bool havePartialPair = false; - bool haveFullPair = false; - - auto addDirCheck = [&](const FolderPairEnh& fp) - { - const Zstring dirLeft = getFormattedDirectoryName(fp.leftDirectory ); //should not block!? - const Zstring dirRight = getFormattedDirectoryName(fp.rightDirectory); // - - if (dirLeft.empty() != dirRight.empty()) //only skip check if both sides are empty! - havePartialPair = true; - else if (!dirLeft.empty()) - haveFullPair = true; - - if (!dirLeft.empty()) - findFirstMissing.addJob([=] { return !dirExists(dirLeft ) ? zen::make_unique<NullType>() : nullptr; }); - if (!dirRight.empty()) - findFirstMissing.addJob([=] { return !dirExists(dirRight) ? zen::make_unique<NullType>() : nullptr; }); - }; - - addDirCheck(currMainCfg.firstPair); - std::for_each(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(), addDirCheck); - //------------------------------------------------------------------------------------------ - - if (havePartialPair != haveFullPair) //either all pairs full or all half-filled -> validity check! - { - //potentially slow network access: give all checks 500ms to finish - const bool allFilesExist = findFirstMissing.timedWait(boost::posix_time::milliseconds(500)) && //true: have result - !findFirstMissing.get(); //no missing - if (allFilesExist) - if (wxEvtHandler* evtHandler = m_buttonCompare->GetEventHandler()) - { - wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); - evtHandler->AddPendingEvent(dummy2); //simulate button click on "compare" - } - } - } -} - - -MainDialog::~MainDialog() -{ - try //save "GlobalSettings.xml" - { - xmlAccess::writeConfig(getGlobalCfgBeforeExit()); //throw FfsXmlError - } - catch (const xmlAccess::FfsXmlError& e) - { - showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - } - - try //save "LastRun.ffs_gui" - { - xmlAccess::writeConfig(getConfig(), lastRunConfigName()); //throw FfsXmlError - } - //don't annoy users on read-only drives: it's enough to show a single error message when saving global config - catch (const xmlAccess::FfsXmlError&) {} - - //important! event source wxTheApp is NOT dependent on this instance -> disconnect! - wxTheApp->Disconnect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this); - wxTheApp->Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this); - -#ifdef ZEN_MAC - //more (non-portable) wxWidgets crap: wxListBox leaks wxClientData, both of the following functions fail to clean up: - // src/common/ctrlsub.cpp:: wxItemContainer::~wxItemContainer() -> empty function body!!! - // src/osx/listbox_osx.cpp: wxListBox::~wxListBox() - //=> finally a manual wxItemContainer::Clear() will render itself useful: - m_listBoxHistory->Clear(); -#endif - - auiMgr.UnInit(); - - //no need for wxEventHandler::Disconnect() here; event sources are components of this window and are destroyed, too -} - -//------------------------------------------------------------------------------------------------------------------------------------- - -void MainDialog::onQueryEndSession() -{ - try { xmlAccess::writeConfig(getGlobalCfgBeforeExit()); } - catch (const xmlAccess::FfsXmlError&) {} //we try our best do to something useful in this extreme situation - no reason to notify or even log errors here! - - try { xmlAccess::writeConfig(getConfig(), lastRunConfigName()); } - catch (const xmlAccess::FfsXmlError&) {} -} - - -void MainDialog::setGlobalCfgOnInit(const xmlAccess::XmlGlobalSettings& globalSettings) -{ - globalCfg = globalSettings; - - //caveat set/get language asymmmetry! setLanguage(globalSettings.programLanguage); //throw FileError - //we need to set langugabe before creating this class! - - //set dialog size and position: - // - width/height are invalid if the window is minimized (eg x,y == -32000; height = 28, width = 160) - // - multi-monitor setups: dialog may be placed on second monitor which is currently turned off - if (globalSettings.gui.dlgSize.GetWidth () > 0 && - globalSettings.gui.dlgSize.GetHeight() > 0) - { - //calculate how much of the dialog will be visible on screen - const int dialogAreaTotal = globalSettings.gui.dlgSize.GetWidth() * globalSettings.gui.dlgSize.GetHeight(); - int dialogAreaVisible = 0; - - const int monitorCount = wxDisplay::GetCount(); - for (int i = 0; i < monitorCount; ++i) - { - wxRect intersection = wxDisplay(i).GetClientArea().Intersect(wxRect(globalSettings.gui.dlgPos, globalSettings.gui.dlgSize)); - dialogAreaVisible = std::max(dialogAreaVisible, intersection.GetWidth() * intersection.GetHeight()); - } - - if (dialogAreaVisible > 0.1 * dialogAreaTotal) //at least 10% of the dialog should be visible! - SetSize(wxRect(globalSettings.gui.dlgPos, globalSettings.gui.dlgSize)); - else - { - SetSize(wxRect(globalSettings.gui.dlgSize)); - Centre(); - } - } - else - Centre(); - - Maximize(globalSettings.gui.isMaximized); - - //set column attributes - m_gridMainL ->setColumnConfig(gridview::convertConfig(globalSettings.gui.columnAttribLeft)); - m_gridMainR ->setColumnConfig(gridview::convertConfig(globalSettings.gui.columnAttribRight)); - m_splitterMain->setSashOffset(globalSettings.gui.sashOffset); - - m_gridNavi->setColumnConfig(treeview::convertConfig(globalSettings.gui.columnAttribNavi)); - treeview::setShowPercentage(*m_gridNavi, globalSettings.gui.showPercentBar); - - treeDataView->setSortDirection(globalSettings.gui.naviLastSortColumn, globalSettings.gui.naviLastSortAscending); - - //-------------------------------------------------------------------------------- - //load list of last used configuration files - //config_history::setItems(*m_gridConfigHistory, globalSettings.gui.lastUsedConfigFiles2); - - std::vector<Zstring> cfgFileNames; - std::transform(globalSettings.gui.cfgFileHistory.rbegin(), globalSettings.gui.cfgFileHistory.rend(), std::back_inserter(cfgFileNames), - [](const ConfigHistoryItem& item) { return item.configFile; }); - //list is stored with last used files first in xml, however addFileToCfgHistory() needs them last!!! - - cfgFileNames.push_back(lastRunConfigName()); //make sure <Last session> is always part of history list (if existing) - addFileToCfgHistory(cfgFileNames); - - removeObsoleteCfgHistoryItems(cfgFileNames); //remove non-existent items (we need this only on startup) - //-------------------------------------------------------------------------------- - - //load list of last used folders - *folderHistoryLeft = FolderHistory(globalSettings.gui.folderHistoryLeft, globalSettings.gui.folderHistMax); - *folderHistoryRight = FolderHistory(globalSettings.gui.folderHistoryRight, globalSettings.gui.folderHistMax); - - //show/hide file icons - gridview::setupIcons(*m_gridMainL, *m_gridMainC, *m_gridMainR, globalSettings.gui.showIcons, convert(globalSettings.gui.iconSize)); - - //------------------------------------------------------------------------------------------------ - m_checkBoxMatchCase->SetValue(globalCfg.gui.textSearchRespectCase); - - //wxAuiManager erroneously loads panel captions, we don't want that - typedef std::vector<std::pair<wxString, wxString>> CaptionNameMapping; - CaptionNameMapping captionNameMap; - const wxAuiPaneInfoArray& paneArray = auiMgr.GetAllPanes(); - for (size_t i = 0; i < paneArray.size(); ++i) - captionNameMap.push_back(std::make_pair(paneArray[i].caption, paneArray[i].name)); - - auiMgr.LoadPerspective(globalSettings.gui.guiPerspectiveLast); - - //restore original captions - for (auto it = captionNameMap.begin(); it != captionNameMap.end(); ++it) - auiMgr.GetPane(it->second).Caption(it->first); - - //if MainDialog::onQueryEndSession() is called while comparison is active, this panel is saved and restored as "visible" - auiMgr.GetPane(compareStatus->getAsWindow()).Hide(); - - auiMgr.GetPane(m_panelSearch).Hide(); //no need to show it on startup - - m_menuItemCheckVersionAuto->Check(globalCfg.gui.lastUpdateCheck != -1); - - auiMgr.Update(); -} - - -xmlAccess::XmlGlobalSettings MainDialog::getGlobalCfgBeforeExit() -{ - Freeze(); //no need to Thaw() again!! - - xmlAccess::XmlGlobalSettings globalSettings = globalCfg; - - globalSettings.programLanguage = getLanguage(); - - //retrieve column attributes - globalSettings.gui.columnAttribLeft = gridview::convertConfig(m_gridMainL->getColumnConfig()); - globalSettings.gui.columnAttribRight = gridview::convertConfig(m_gridMainR->getColumnConfig()); - globalSettings.gui.sashOffset = m_splitterMain->getSashOffset(); - - globalSettings.gui.columnAttribNavi = treeview::convertConfig(m_gridNavi->getColumnConfig()); - globalSettings.gui.showPercentBar = treeview::getShowPercentage(*m_gridNavi); - - const std::pair<ColumnTypeNavi, bool> sortInfo = treeDataView->getSortDirection(); - globalSettings.gui.naviLastSortColumn = sortInfo.first; - globalSettings.gui.naviLastSortAscending = sortInfo.second; - - //-------------------------------------------------------------------------------- - //write list of last used configuration files - std::map<int, Zstring> historyDetail; //(cfg-file/last use index) - for (unsigned int i = 0; i < m_listBoxHistory->GetCount(); ++i) - if (auto clientString = dynamic_cast<const wxClientHistoryData*>(m_listBoxHistory->GetClientObject(i))) - historyDetail.insert(std::make_pair(clientString->lastUseIndex_, clientString->cfgFile_)); - else - assert(false); - - //sort by last use; put most recent items *first* (looks better in xml than the reverse) - std::vector<ConfigHistoryItem> history; - std::transform(historyDetail.rbegin(), historyDetail.rend(), std::back_inserter(history), [](const std::pair<const int, Zstring>& item) { return ConfigHistoryItem(item.second); }); - - if (history.size() > globalSettings.gui.cfgFileHistMax) //erase oldest elements - history.resize(globalSettings.gui.cfgFileHistMax); - - globalSettings.gui.cfgFileHistory = history; - //-------------------------------------------------------------------------------- - globalSettings.gui.lastUsedConfigFiles = activeConfigFiles; - //globalSettings.gui.lastUsedConfigFiles2 = config_history::getItems(*m_gridConfigHistory); - - //write list of last used folders - globalSettings.gui.folderHistoryLeft = folderHistoryLeft ->getList(); - globalSettings.gui.folderHistoryRight = folderHistoryRight->getList(); - - globalSettings.gui.textSearchRespectCase = m_checkBoxMatchCase->GetValue(); - - globalSettings.gui.guiPerspectiveLast = auiMgr.SavePerspective(); - - //we need to portably retrieve non-iconized, non-maximized size and position (non-portable: GetWindowPlacement()) - //call *after* wxAuiManager::SavePerspective()! - if (IsIconized()) - Iconize(false); - - globalSettings.gui.isMaximized = IsMaximized(); //evaluate AFTER uniconizing! - - if (IsMaximized()) - Maximize(false); - - globalSettings.gui.dlgSize = GetSize(); - globalSettings.gui.dlgPos = GetPosition(); - - return globalSettings; -} - - -void MainDialog::setSyncDirManually(const std::vector<FileSystemObject*>& selection, SyncDirection direction) -{ - if (!selection.empty()) - { - std::for_each(selection.begin(), selection.end(), - [&](FileSystemObject* fsObj) - { - setSyncDirectionRec(direction, *fsObj); //set new direction (recursively) - zen::setActiveStatus(true, *fsObj); //works recursively for directories - }); - - updateGui(); - } -} - - -void MainDialog::setFilterManually(const std::vector<FileSystemObject*>& selection, bool setIncluded) -{ - //if hidefiltered is active, there should be no filtered elements on screen => current element was filtered out - assert(!currentCfg.hideExcludedItems || !setIncluded); - - if (!selection.empty()) - { - std::for_each(selection.begin(), selection.end(), - [&](FileSystemObject* fsObj) { zen::setActiveStatus(setIncluded, *fsObj); }); //works recursively for directories - - updateGuiDelayedIf(currentCfg.hideExcludedItems); //show update GUI before removing rows - } -} - - -namespace -{ -//perf: wxString doesn't model exponential growth and so is unusable for large data sets -typedef Zbase<wchar_t> zxString; //guaranteed exponential growth -} - -void MainDialog::copySelectionToClipboard(const std::vector<const Grid*>& gridRefs) -{ - try - { - zxString clipboardString; - - auto addSelection = [&](const Grid& grid) - { - if (auto prov = grid.getDataProvider()) - { - std::vector<Grid::ColumnAttribute> colAttr = grid.getColumnConfig(); - vector_remove_if(colAttr, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; }); - if (!colAttr.empty()) - { - const std::vector<size_t> selection = grid.getSelectedRows(); - std::for_each(selection.begin(), selection.end(), - [&](size_t row) - { - std::for_each(colAttr.begin(), colAttr.end() - 1, - [&](const Grid::ColumnAttribute& ca) - { - clipboardString += copyStringTo<zxString>(prov->getValue(row, ca.type_)); - clipboardString += L'\t'; - }); - clipboardString += copyStringTo<zxString>(prov->getValue(row, colAttr.back().type_)); - clipboardString += L'\n'; - }); - } - } - }; - - for (auto it = gridRefs.begin(); it != gridRefs.end(); ++it) - addSelection(**it); - - //finally write to clipboard - if (!clipboardString.empty()) - if (wxClipboard::Get()->Open()) - { - ZEN_ON_SCOPE_EXIT(wxClipboard::Get()->Close()); - wxClipboard::Get()->SetData(new wxTextDataObject(copyStringTo<wxString>(clipboardString))); //ownership passed - } - } - catch (const std::bad_alloc& e) - { - showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setMainInstructions(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()))); - } -} - - -std::vector<FileSystemObject*> MainDialog::getGridSelection(bool fromLeft, bool fromRight) const -{ - std::set<size_t> selectedRows; - - auto addSelection = [&](const Grid& grid) - { - const std::vector<size_t>& sel = grid.getSelectedRows(); - selectedRows.insert(sel.begin(), sel.end()); - }; - - if (fromLeft) - addSelection(*m_gridMainL); - - if (fromRight) - addSelection(*m_gridMainR); - - return gridDataView->getAllFileRef(selectedRows); -} - - -std::vector<FileSystemObject*> MainDialog::getTreeSelection() const -{ - std::vector<FileSystemObject*> output; - - const std::vector<size_t>& sel = m_gridNavi->getSelectedRows(); - std::for_each(sel.begin(), sel.end(), - [&](size_t row) - { - if (std::unique_ptr<TreeView::Node> node = treeDataView->getLine(row)) - { - if (auto root = dynamic_cast<const TreeView::RootNode*>(node.get())) - { - //select first level of child elements - for (auto& fsObj : root->baseDirObj_.refSubDirs ()) output.push_back(&fsObj); - for (auto& fsObj : root->baseDirObj_.refSubFiles()) output.push_back(&fsObj); - for (auto& fsObj : root->baseDirObj_.refSubLinks()) output.push_back(&fsObj); - } - else if (auto dir = dynamic_cast<const TreeView::DirNode*>(node.get())) - output.push_back(&(dir->dirObj_)); - else if (auto file = dynamic_cast<const TreeView::FilesNode*>(node.get())) - output.insert(output.end(), file->filesAndLinks_.begin(), file->filesAndLinks_.end()); - } - }); - return output; -} - - -//Exception class used to abort the "compare" and "sync" process -class AbortDeleteProcess {}; - -class ManualDeletionHandler : private wxEvtHandler, public DeleteFilesHandler //throw AbortDeleteProcess -{ -public: - ManualDeletionHandler(MainDialog& main) : - mainDlg(main), - abortRequested(false), - ignoreErrors(false) - { - mainDlg.disableAllElements(true); //disable everything except abort button - - //register abort button - mainDlg.m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion), nullptr, this ); - mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), nullptr, this); - } - - ~ManualDeletionHandler() - { - //de-register abort button - mainDlg.Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), nullptr, this); - mainDlg.m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion ), nullptr, this ); - - mainDlg.enableAllElements(); - } - - virtual Response reportError(const std::wstring& msg) - { - if (ignoreErrors) - return DeleteFilesHandler::IGNORE_ERROR; - - forceUiRefresh(); - bool ignoreNextErrors = false; - switch (showConfirmationDialog3(&mainDlg, DialogInfoType::ERROR2, PopupDialogCfg3(). - setDetailInstructions(msg). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors"), ConfirmationButton3::DONT_DO_IT), - _("&Ignore"), _("&Retry"))) - { - case ConfirmationButton3::DO_IT: //ignore - ignoreErrors = ignoreNextErrors; - return DeleteFilesHandler::IGNORE_ERROR; - - case ConfirmationButton3::DONT_DO_IT: //retry - return DeleteFilesHandler::RETRY; - - case ConfirmationButton3::CANCEL: - throw AbortDeleteProcess(); - } - - assert (false); - return DeleteFilesHandler::IGNORE_ERROR; //dummy return value - } - - virtual void reportWarning(const std::wstring& msg, bool& warningActive) - { - if (!warningActive || ignoreErrors) - return; - - forceUiRefresh(); - bool dontWarnAgain = false; - switch (showConfirmationDialog(&mainDlg, DialogInfoType::WARNING, PopupDialogCfg(). - setDetailInstructions(msg). - setCheckBox(dontWarnAgain, _("&Don't show this warning again")), _("&Ignore"))) - { - case ConfirmationButton::DO_IT: - warningActive = !dontWarnAgain; - break; - case ConfirmationButton::CANCEL: - throw AbortDeleteProcess(); - } - } - - virtual void reportStatus (const std::wstring& msg) - { - statusMsg = msg; - requestUiRefresh(); - } - -private: - virtual void requestUiRefresh() - { - if (updateUiIsAllowed()) //test if specific time span between ui updates is over - forceUiRefresh(); - - if (abortRequested) //test after (implicit) call to wxApp::Yield() - throw AbortDeleteProcess(); - } - - void forceUiRefresh() - { - //std::wstring msg = toGuiString(deletionCount) + - mainDlg.setStatusBarFullText(statusMsg); - wxTheApp->Yield(); - } - - //context: C callstack message loop => throw()! - void OnAbortDeletion(wxCommandEvent& event) //handle abort button click - { - abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw zen::AbortThisProcess()) - } - - void OnKeyPressed(wxKeyEvent& event) - { - const int keyCode = event.GetKeyCode(); - if (keyCode == WXK_ESCAPE) - { - abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw zen::AbortThisProcess()) - return; - } - - event.Skip(); - } - - MainDialog& mainDlg; - - bool abortRequested; - bool ignoreErrors; - //size_t deletionCount; // - std::wstring statusMsg; //status reporting -}; - - -void MainDialog::deleteSelectedFiles(const std::vector<FileSystemObject*>& selectionLeft, - const std::vector<FileSystemObject*>& selectionRight) -{ - bool deleteOnBothSides = false; //let's keep this disabled by default -> don't save - //=> clenup empty selection on either side: - std::vector<FileSystemObject*> selectionLeftTmp; - std::vector<FileSystemObject*> selectionRightTmp; - std::copy_if(selectionLeft .begin(), selectionLeft .end(), std::back_inserter(selectionLeftTmp ), [](const FileSystemObject* fsObj) { return !fsObj->isEmpty<LEFT_SIDE >(); }); - std::copy_if(selectionRight.begin(), selectionRight.end(), std::back_inserter(selectionRightTmp), [](const FileSystemObject* fsObj) { return !fsObj->isEmpty<RIGHT_SIDE>(); }); - - if (!selectionLeftTmp.empty() || !selectionRightTmp.empty()) - { - wxWindow* oldFocus = wxWindow::FindFocus(); - ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus();) - - if (zen::showDeleteDialog(this, - selectionLeftTmp, - selectionRightTmp, - deleteOnBothSides, - globalCfg.gui.useRecyclerForManualDeletion) == ReturnSmallDlg::BUTTON_OKAY) - { - //wxBusyCursor dummy; -> redundant: progress already shown in status bar! - try - { - //handle errors when deleting files/folders - ManualDeletionHandler statusHandler(*this); - - zen::deleteFromGridAndHD(selectionLeftTmp, - selectionRightTmp, - folderCmp, - extractDirectionCfg(getConfig().mainCfg), - deleteOnBothSides, - globalCfg.gui.useRecyclerForManualDeletion, - statusHandler, - globalCfg.optDialogs.warningRecyclerMissing); - - gridview::clearSelection(*m_gridMainL, *m_gridMainC, *m_gridMainR); //do not clear, if aborted! - } - catch (AbortDeleteProcess&) {} - - //remove rows that are empty: just a beautification, invalid rows shouldn't cause issues - gridDataView->removeInvalidRows(); - - //redraw grid neccessary to update new dimensions and for UI-Backend data linkage - updateGui(); //call immediately after deleteFromGridAndHD!!! - } - } -} - - -namespace -{ -template <SelectedSide side> -Zstring getExistingParentFolder(const FileSystemObject& fsObj) -{ - const DirPair* dirObj = dynamic_cast<const DirPair*>(&fsObj); - if (!dirObj) - dirObj = dynamic_cast<const DirPair*>(&fsObj.parent()); - - while (dirObj) - { - if (!dirObj->isEmpty<side>()) - return dirObj->getFullName<side>(); - - dirObj = dynamic_cast<const DirPair*>(&dirObj->parent()); - } - return fsObj.getBaseDirPf<side>(); -} -} - -void MainDialog::openExternalApplication(const wxString& commandline, const std::vector<FileSystemObject*>& selection, bool leftSide) -{ - if (commandline.empty()) - return; - - auto selectionTmp = selection; - - const bool openFileBrowserRequested = [&]() -> bool - { - xmlAccess::XmlGlobalSettings::Gui dummy; - return !dummy.externelApplications.empty() && dummy.externelApplications[0].second == commandline; - }(); - - //support fallback instead of an error in this special case - if (openFileBrowserRequested) - { - if (selectionTmp.size() > 1) //do not open more than one explorer instance! - selectionTmp.resize(1); // - - if (selectionTmp.empty() || - (leftSide && selectionTmp[0]->isEmpty<LEFT_SIDE >()) || - (!leftSide && selectionTmp[0]->isEmpty<RIGHT_SIDE>())) - { - Zstring fallbackDir; - if (selectionTmp.empty()) - fallbackDir = leftSide ? - getFormattedDirectoryName(firstFolderPair->getLeftDir()) : - getFormattedDirectoryName(firstFolderPair->getRightDir()); - - else - fallbackDir = leftSide ? - getExistingParentFolder<LEFT_SIDE >(*selectionTmp[0]) : - getExistingParentFolder<RIGHT_SIDE>(*selectionTmp[0]); - - try - { -#ifdef ZEN_WIN - shellExecute2(L"\"" + fallbackDir + L"\"", EXEC_TYPE_ASYNC); //throw FileError -#elif defined ZEN_LINUX - shellExecute2("xdg-open \"" + fallbackDir + "\"", EXEC_TYPE_ASYNC); // -#elif defined ZEN_MAC - shellExecute2("open \"" + fallbackDir + "\"", EXEC_TYPE_ASYNC); // -#endif - } - catch (const FileError& e) { showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); } - return; - } - } - - const size_t massInvokeThreshold = 10; //more than this is likely a user mistake - - if (selectionTmp.size() > massInvokeThreshold) - if (globalCfg.optDialogs.confirmExternalCommandMassInvoke) - { - bool dontAskAgain = false; - switch (showConfirmationDialog(this, DialogInfoType::WARNING, PopupDialogCfg(). - setTitle(_("Confirm")). - setMainInstructions(replaceCpy(_P("Do you really want to execute the command %y for one item?", - "Do you really want to execute the command %y for %x items?", selectionTmp.size()), - L"%y", L'\"' + commandline + L'\"')). - setCheckBox(dontAskAgain, _("&Don't show this warning again")), - _("&Execute"))) - { - case ConfirmationButton::DO_IT: - globalCfg.optDialogs.confirmExternalCommandMassInvoke = !dontAskAgain; - break; - case ConfirmationButton::CANCEL: - return; - } - } - - //regular command evaluation - for (const FileSystemObject* fsObj : selectionTmp) //context menu calls this function only if selection is not empty! - { - Zstring path1 = fsObj->getBaseDirPf<LEFT_SIDE>() + fsObj->getObjRelativeName(); //full path, even if item is not existing! - Zstring dir1 = beforeLast(path1, FILE_NAME_SEPARATOR); //Win: wrong for root paths like "C:\file.txt" - - Zstring path2 = fsObj->getBaseDirPf<RIGHT_SIDE>() + fsObj->getObjRelativeName(); - Zstring dir2 = beforeLast(path2, FILE_NAME_SEPARATOR); - - if (!leftSide) - { - std::swap(path1, path2); - std::swap(dir1, dir2); - } - - Zstring command = utfCvrtTo<Zstring>(commandline); - replace(command, Zstr("%item_path%"), path1); - replace(command, Zstr("%item2_path%"), path2); - replace(command, Zstr("%item_folder%"), dir1 ); - replace(command, Zstr("%item2_folder%"), dir2 ); - - auto cmdExp = expandMacros(command); - try - { - //caveat: spawning too many threads asynchronously can easily kill a user's desktop session on Ubuntu! - shellExecute2(cmdExp, selectionTmp.size() > massInvokeThreshold ? EXEC_TYPE_SYNC : EXEC_TYPE_ASYNC); //throw FileError - } - catch (const FileError& e) { showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); } - } -} - - -void MainDialog::setStatusBarFileStatistics(size_t filesOnLeftView, - size_t foldersOnLeftView, - size_t filesOnRightView, - size_t foldersOnRightView, - zen::UInt64 filesizeLeftView, - zen::UInt64 filesizeRightView) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(m_panelStatusBar); //leads to GUI corruption problems on Linux/OS X! -#endif - - //select state - bSizerFileStatus->Show(true); - m_staticTextFullStatus->Hide(); - - //update status information - bSizerStatusLeftDirectories->Show(foldersOnLeftView > 0); - bSizerStatusLeftFiles ->Show(filesOnLeftView > 0); - - setText(*m_staticTextStatusLeftDirs, _P("1 directory", "%x directories", foldersOnLeftView)); - setText(*m_staticTextStatusLeftFiles, _P("1 file", "%x files", filesOnLeftView)); - setText(*m_staticTextStatusLeftBytes, L"(" + filesizeToShortString(to<Int64>(filesizeLeftView)) + L")"); - //------------------------------------------------------------------------------ - bSizerStatusRightDirectories->Show(foldersOnRightView > 0); - bSizerStatusRightFiles ->Show(filesOnRightView > 0); - - setText(*m_staticTextStatusRightDirs, _P("1 directory", "%x directories", foldersOnRightView)); - setText(*m_staticTextStatusRightFiles, _P("1 file", "%x files", filesOnRightView)); - setText(*m_staticTextStatusRightBytes, L"(" + filesizeToShortString(to<Int64>(filesizeRightView)) + L")"); - //------------------------------------------------------------------------------ - wxString statusMiddleNew; - if (gridDataView->rowsTotal() > 0) - { - statusMiddleNew = _P("%y of 1 row in view", "%y of %x rows in view", gridDataView->rowsTotal()); - replace(statusMiddleNew, L"%y", toGuiString(gridDataView->rowsOnView()), false); //%x is already used as plural form placeholder! - } - - //fill middle text (considering flashStatusInformation()) - if (oldStatusMsgs.empty()) - setText(*m_staticTextStatusMiddle, statusMiddleNew); - else - oldStatusMsgs.front() = statusMiddleNew; - - m_panelStatusBar->Layout(); -} - - -void MainDialog::setStatusBarFullText(const wxString& msg) -{ - const bool needLayoutUpdate = !m_staticTextFullStatus->IsShown(); - //select state - bSizerFileStatus->Show(false); - m_staticTextFullStatus->Show(); - - //update status information - setText(*m_staticTextFullStatus, msg); - m_panelStatusBar->Layout(); - - if (needLayoutUpdate) - auiMgr.Update(); //fix status bar height (needed on OS X) -} - - -void MainDialog::flashStatusInformation(const wxString& text) -{ - oldStatusMsgs.push_back(m_staticTextStatusMiddle->GetLabel()); - - m_staticTextStatusMiddle->SetLabel(text); - m_staticTextStatusMiddle->SetForegroundColour(wxColour(31, 57, 226)); //highlight color: blue - m_staticTextStatusMiddle->SetFont(m_staticTextStatusMiddle->GetFont().Bold()); - - m_panelStatusBar->Layout(); - //if (needLayoutUpdate) auiMgr.Update(); -> not needed here, this is called anyway in updateGui() - - processAsync2([] { boost::this_thread::sleep(boost::posix_time::millisec(2500)); }, - [this] { this->restoreStatusInformation(); }); -} - - -void MainDialog::restoreStatusInformation() -{ - if (!oldStatusMsgs.empty()) - { - wxString oldMsg = oldStatusMsgs.back(); - oldStatusMsgs.pop_back(); - - if (oldStatusMsgs.empty()) //restore original status text - { - m_staticTextStatusMiddle->SetLabel(oldMsg); - m_staticTextStatusMiddle->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //reset color - - wxFont fnt = m_staticTextStatusMiddle->GetFont(); - fnt.SetWeight(wxFONTWEIGHT_NORMAL); - m_staticTextStatusMiddle->SetFont(fnt); - - m_panelStatusBar->Layout(); - } - } -} - - -void MainDialog::onProcessAsyncTasks(wxEvent& event) -{ - //schedule and run long-running tasks asynchronously - asyncTasks.evalResults(); //process results on GUI queue - if (asyncTasks.empty()) - timerForAsyncTasks.Stop(); -} - - -void MainDialog::disableAllElements(bool enableAbort) -{ - //disables all elements (except abort button) that might receive user input during long-running processes: - //when changing consider: comparison, synchronization, manual deletion - - EnableCloseButton(false); //not allowed for synchronization! progress indicator is top window! -> not honored on OS X! - - //OS X: wxWidgets portability promise is again a mess: http://wxwidgets.10942.n7.nabble.com/Disable-panel-and-appropriate-children-windows-linux-macos-td35357.html - - m_menubar1->EnableTop(0, false); - m_menubar1->EnableTop(1, false); - m_menubar1->EnableTop(2, false); - m_bpButtonCmpConfig ->Disable(); - m_bpButtonSyncConfig ->Disable(); - m_buttonSync ->Disable(); - m_panelDirectoryPairs->Disable(); - m_splitterMain ->Disable(); //includes m_panelCenter, but not m_panelStatusBar! - m_panelViewFilter ->Disable(); - m_panelFilter ->Disable(); - m_panelConfig ->Disable(); - m_panelStatistics ->Disable(); - m_gridNavi ->Disable(); - - if (enableAbort) - { - //show abort button - m_buttonCancel->Enable(); - m_buttonCancel->Show(); - if (m_buttonCancel->IsShownOnScreen()) - m_buttonCancel->SetFocus(); - m_buttonCompare->Disable(); - m_buttonCompare->Hide(); - m_panelTopButtons->Layout(); - } - else - m_panelTopButtons->Disable(); -} - - -void MainDialog::enableAllElements() -{ - //wxGTK, yet another QOI issue: some stupid bug, keeps moving main dialog to top!! - - EnableCloseButton(true); - - m_menubar1->EnableTop(0, true); - m_menubar1->EnableTop(1, true); - m_menubar1->EnableTop(2, true); - m_bpButtonCmpConfig ->Enable(); - m_bpButtonSyncConfig ->Enable(); - m_buttonSync ->Enable(); - m_panelDirectoryPairs->Enable(); - m_splitterMain ->Enable(); - m_panelViewFilter ->Enable(); - m_panelFilter ->Enable(); - m_panelConfig ->Enable(); - m_panelStatistics ->Enable(); - m_gridNavi ->Enable(); - - //show compare button - m_buttonCancel->Disable(); - m_buttonCancel->Hide(); - m_buttonCompare->Enable(); - m_buttonCompare->Show(); - - m_panelTopButtons->Enable(); - m_panelTopButtons->Layout(); - - //at least wxWidgets on OS X fails to do this after enabling: - Refresh(); -} - - -namespace -{ -void updateSizerOrientation(wxBoxSizer& sizer, wxWindow& window, double horizontalWeight) -{ - const int newOrientation = window.GetSize().GetWidth() * horizontalWeight > window.GetSize().GetHeight() ? wxHORIZONTAL : wxVERTICAL; //check window NOT sizer width! - if (sizer.GetOrientation() != newOrientation) - { - sizer.SetOrientation(newOrientation); - window.Layout(); - } -} -} - - -void MainDialog::OnResizeConfigPanel(wxEvent& event) -{ - updateSizerOrientation(*bSizerConfig, *m_panelConfig, 0.5); - event.Skip(); -} - - -void MainDialog::OnResizeViewPanel(wxEvent& event) -{ - updateSizerOrientation(*bSizerViewFilter, *m_panelViewFilter, 1.0); - event.Skip(); -} - - -void MainDialog::OnResizeStatisticsPanel(wxEvent& event) -{ - //updateSizerOrientation(*bSizerStatistics, *m_panelStatistics); - - //we need something more fancy: - const int parentOrient = m_panelStatistics->GetSize().GetWidth() > m_panelStatistics->GetSize().GetHeight() ? wxHORIZONTAL : wxVERTICAL; //check window NOT sizer width! - if (bSizerStatistics->GetOrientation() != parentOrient) - { - bSizerStatistics->SetOrientation(parentOrient); - - //apply opposite orientation for child sizers - const int childOrient = parentOrient == wxHORIZONTAL ? wxVERTICAL : wxHORIZONTAL; - wxSizerItemList& sl = bSizerStatistics->GetChildren(); - for (auto it = sl.begin(); it != sl.end(); ++it) //yet another wxWidgets bug keeps us from using std::for_each - { - wxSizerItem& szItem = **it; - if (auto sizerChild = dynamic_cast<wxBoxSizer*>(szItem.GetSizer())) - if (sizerChild->GetOrientation() != childOrient) - sizerChild->SetOrientation(childOrient); - } - m_panelStatistics->Layout(); - } - - event.Skip(); -} - - -void MainDialog::OnResizeLeftFolderWidth(wxEvent& event) -{ - //adapt left-shift display distortion caused by scrollbars for multiple folder pairs - const int width = m_panelTopLeft->GetSize().GetWidth(); - std::for_each(additionalFolderPairs.begin(), additionalFolderPairs.end(), - [&](FolderPairPanel* panel) - { - panel->m_panelLeft->SetMinSize(wxSize(width, -1)); - }); - - event.Skip(); -} - - -void MainDialog::onTreeButtonEvent(wxKeyEvent& event) -{ - int keyCode = event.GetKeyCode(); - if (m_gridNavi->GetLayoutDirection() == wxLayout_RightToLeft) - { - if (keyCode == WXK_LEFT) - keyCode = WXK_RIGHT; - else if (keyCode == WXK_RIGHT) - keyCode = WXK_LEFT; - else if (keyCode == WXK_NUMPAD_LEFT) - keyCode = WXK_NUMPAD_RIGHT; - else if (keyCode == WXK_NUMPAD_RIGHT) - keyCode = WXK_NUMPAD_LEFT; - } - - if (event.ControlDown()) - switch (keyCode) - { - case 'C': - case WXK_INSERT: //CTRL + C || CTRL + INS - { - std::vector<const Grid*> gridRefs; - gridRefs.push_back(m_gridNavi); - copySelectionToClipboard(gridRefs); - } - return; - } - else if (event.AltDown()) - switch (keyCode) - { - case WXK_NUMPAD_LEFT: - case WXK_LEFT: //ALT + <- - setSyncDirManually(getTreeSelection(), SyncDirection::LEFT); - return; - - case WXK_NUMPAD_RIGHT: - case WXK_RIGHT: //ALT + -> - setSyncDirManually(getTreeSelection(), SyncDirection::RIGHT); - return; - - case WXK_NUMPAD_UP: - case WXK_NUMPAD_DOWN: - case WXK_UP: /* ALT + /|\ */ - case WXK_DOWN: /* ALT + \|/ */ - setSyncDirManually(getTreeSelection(), SyncDirection::NONE); - return; - } - - else - switch (keyCode) - { - case WXK_SPACE: - case WXK_NUMPAD_SPACE: - { - const std::vector<FileSystemObject*>& selection = getTreeSelection(); - if (!selection.empty()) - setFilterManually(selection, !selection[0]->isActive()); - } - return; - - case WXK_DELETE: - case WXK_NUMPAD_DELETE: - deleteSelectedFiles(getTreeSelection(), getTreeSelection()); - return; - } - - event.Skip(); //unknown keypress: propagate -} - - -void MainDialog::onGridButtonEventL(wxKeyEvent& event) -{ - onGridButtonEvent(event, *m_gridMainL, true); -} -void MainDialog::onGridButtonEventC(wxKeyEvent& event) -{ - onGridButtonEvent(event, *m_gridMainC, true); -} -void MainDialog::onGridButtonEventR(wxKeyEvent& event) -{ - onGridButtonEvent(event, *m_gridMainR, false); -} - -void MainDialog::onGridButtonEvent(wxKeyEvent& event, Grid& grid, bool leftSide) -{ - int keyCode = event.GetKeyCode(); - if (grid.GetLayoutDirection() == wxLayout_RightToLeft) - { - if (keyCode == WXK_LEFT) - keyCode = WXK_RIGHT; - else if (keyCode == WXK_RIGHT) - keyCode = WXK_LEFT; - else if (keyCode == WXK_NUMPAD_LEFT) - keyCode = WXK_NUMPAD_RIGHT; - else if (keyCode == WXK_NUMPAD_RIGHT) - keyCode = WXK_NUMPAD_LEFT; - } - - if (event.ControlDown()) - switch (keyCode) - { - case 'C': - case WXK_INSERT: //CTRL + C || CTRL + INS - { - std::vector<const Grid*> gridRefs; - gridRefs.push_back(m_gridMainL); - gridRefs.push_back(m_gridMainR); - copySelectionToClipboard(gridRefs); - } - return; // -> swallow event! don't allow default grid commands! - } - - else if (event.AltDown()) - switch (keyCode) - { - case WXK_NUMPAD_LEFT: - case WXK_LEFT: //ALT + <- - setSyncDirManually(getGridSelection(), SyncDirection::LEFT); - return; - - case WXK_NUMPAD_RIGHT: - case WXK_RIGHT: //ALT + -> - setSyncDirManually(getGridSelection(), SyncDirection::RIGHT); - return; - - case WXK_NUMPAD_UP: - case WXK_NUMPAD_DOWN: - case WXK_UP: /* ALT + /|\ */ - case WXK_DOWN: /* ALT + \|/ */ - setSyncDirManually(getGridSelection(), SyncDirection::NONE); - return; - } - - else - switch (keyCode) - { - case WXK_DELETE: - case WXK_NUMPAD_DELETE: - deleteSelectedFiles(getGridSelection(true, false), - getGridSelection(false, true)); - return; - - case WXK_SPACE: - case WXK_NUMPAD_SPACE: - { - const std::vector<FileSystemObject*>& selection = getGridSelection(); - if (!selection.empty()) - setFilterManually(selection, !selection[0]->isActive()); - } - return; - - case WXK_RETURN: - case WXK_NUMPAD_ENTER: - if (!globalCfg.gui.externelApplications.empty()) - openExternalApplication(globalCfg.gui.externelApplications[0].second, //open with first external application - getGridSelection(), leftSide); - return; - } - - event.Skip(); //unknown keypress: propagate -} - - -bool isComponentOf(const wxWindow* child, const wxWindow* top) -{ - for (const wxWindow* wnd = child; wnd != nullptr; wnd = wnd->GetParent()) - if (wnd == top) - return true; - return false; -} - - -void MainDialog::OnGlobalKeyEvent(wxKeyEvent& event) //process key events without explicit menu entry :) -{ - //avoid recursion!!! -> this ugly construct seems to be the only (portable) way to avoid re-entrancy - //recursion may happen in multiple situations: e.g. modal dialogs, wxGrid::ProcessEvent()! - if (processingGlobalKeyEvent || - !IsShown() || - !IsActive() || - !IsEnabled() || - !m_gridMainL->IsEnabled() || // - !m_gridMainC->IsEnabled() || //only handle if main window is in use - !m_gridMainR->IsEnabled()) // - { - event.Skip(); - return; - } - - processingGlobalKeyEvent = true; - ZEN_ON_SCOPE_EXIT(processingGlobalKeyEvent = false;) - //---------------------------------------------------- - - const int keyCode = event.GetKeyCode(); - - //CTRL + X - //if (event.ControlDown()) - // switch (keyCode) - // { - // case 'F': //CTRL + F - // showFindPanel(); - // return; //-> swallow event! - // } - - switch (keyCode) - { - case WXK_F3: - case WXK_NUMPAD_F3: - startFindNext(); - return; //-> swallow event! - - case WXK_F6: - { - wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); //simulate button click - if (wxEvtHandler* evtHandler = m_bpButtonCmpConfig->GetEventHandler()) - evtHandler->ProcessEvent(dummy2); //synchronous call - } - return; //-> swallow event! - - case WXK_F7: - { - wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); //simulate button click - if (wxEvtHandler* evtHandler = m_bpButtonSyncConfig->GetEventHandler()) - evtHandler->ProcessEvent(dummy2); //synchronous call - } - return; //-> swallow event! - - case WXK_F9: - setViewTypeSyncAction(!m_bpButtonViewTypeSyncAction->isActive()); - return; //-> swallow event! - - case WXK_F10: - { - wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); //simulate button click - if (wxEvtHandler* evtHandler = m_bpButtonFilter->GetEventHandler()) - evtHandler->ProcessEvent(dummy2); //synchronous call - } - return; //-> swallow event! - - //redirect certain (unhandled) keys directly to grid! - case WXK_UP: - case WXK_DOWN: - case WXK_LEFT: - case WXK_RIGHT: - case WXK_NUMPAD_UP: - case WXK_NUMPAD_DOWN: - case WXK_NUMPAD_LEFT: - case WXK_NUMPAD_RIGHT: - - case WXK_PAGEUP: - case WXK_PAGEDOWN: - case WXK_HOME: - case WXK_END: - case WXK_NUMPAD_PAGEUP: - case WXK_NUMPAD_PAGEDOWN: - case WXK_NUMPAD_HOME: - case WXK_NUMPAD_END: - { - const wxWindow* focus = wxWindow::FindFocus(); - if (!isComponentOf(focus, m_gridMainL ) && // - !isComponentOf(focus, m_gridMainC ) && //don't propagate keyboard commands if grid is already in focus - !isComponentOf(focus, m_gridMainR ) && // - !isComponentOf(focus, m_gridNavi ) && - !isComponentOf(focus, m_listBoxHistory) && //don't propagate if selecting config - !isComponentOf(focus, m_directoryLeft ) && //don't propagate if changing directory field - !isComponentOf(focus, m_directoryRight) && - !isComponentOf(focus, m_panelSearch ) && - !isComponentOf(focus, m_scrolledWindowFolderPairs)) - if (wxEvtHandler* evtHandler = m_gridMainL->getMainWin().GetEventHandler()) - { - m_gridMainL->SetFocus(); - - event.SetEventType(wxEVT_KEY_DOWN); //the grid event handler doesn't expect wxEVT_CHAR_HOOK! - evtHandler->ProcessEvent(event); //propagating event catched at wxTheApp to child leads to recursion, but we prevented it... - event.Skip(false); //definitively handled now! - return; - } - } - break; - } - - event.Skip(); -} - - -void MainDialog::onNaviSelection(GridRangeSelectEvent& event) -{ - //scroll m_gridMain to user's new selection on m_gridNavi - ptrdiff_t leadRow = -1; - if (event.rowFirst_ != event.rowLast_) - if (std::unique_ptr<TreeView::Node> node = treeDataView->getLine(event.rowFirst_)) - { - if (const TreeView::RootNode* root = dynamic_cast<const TreeView::RootNode*>(node.get())) - leadRow = gridDataView->findRowFirstChild(&(root->baseDirObj_)); - else if (const TreeView::DirNode* dir = dynamic_cast<const TreeView::DirNode*>(node.get())) - { - leadRow = gridDataView->findRowDirect(&(dir->dirObj_)); - if (leadRow < 0) //directory was filtered out! still on tree view (but NOT on grid view) - leadRow = gridDataView->findRowFirstChild(&(dir->dirObj_)); - } - else if (const TreeView::FilesNode* files = dynamic_cast<const TreeView::FilesNode*>(node.get())) - { - assert(!files->filesAndLinks_.empty()); - if (!files->filesAndLinks_.empty()) - leadRow = gridDataView->findRowDirect(files->filesAndLinks_[0]->getId()); - } - } - - if (leadRow >= 0) - { - leadRow = std::max<ptrdiff_t>(0, leadRow - 1); //scroll one more row - - m_gridMainL->scrollTo(leadRow); //scroll all of them (includes the "scroll master") - m_gridMainC->scrollTo(leadRow); // - m_gridMainR->scrollTo(leadRow); // - - m_gridNavi->getMainWin().Update(); //draw cursor immediately rather than on next idle event (required for slow CPUs, netbook) - } - - //get selection on navigation tree and set corresponding markers on main grid - hash_set<const FileSystemObject*> markedFilesAndLinks; //mark files/symlinks directly - hash_set<const HierarchyObject*> markedContainer; //mark full container including child-objects - - const std::vector<size_t>& selection = m_gridNavi->getSelectedRows(); - std::for_each(selection.begin(), selection.end(), - [&](size_t row) - { - if (std::unique_ptr<TreeView::Node> node = treeDataView->getLine(row)) - { - if (const TreeView::RootNode* root = dynamic_cast<const TreeView::RootNode*>(node.get())) - markedContainer.insert(&(root->baseDirObj_)); - else if (const TreeView::DirNode* dir = dynamic_cast<const TreeView::DirNode*>(node.get())) - markedContainer.insert(&(dir->dirObj_)); - else if (const TreeView::FilesNode* files = dynamic_cast<const TreeView::FilesNode*>(node.get())) - markedFilesAndLinks.insert(files->filesAndLinks_.begin(), files->filesAndLinks_.end()); - } - }); - - gridview::setNavigationMarker(*m_gridMainL, std::move(markedFilesAndLinks), std::move(markedContainer)); - - event.Skip(); -} - - -void MainDialog::onNaviGridContext(GridClickEvent& event) -{ - const auto& selection = getTreeSelection(); //referenced by lambdas! - ContextMenu menu; - - //---------------------------------------------------------------------------------------------------- - if (!selection.empty()) - //std::any_of(selection.begin(), selection.end(), [](const FileSystemObject* fsObj){ return fsObj->getSyncOperation() != SO_EQUAL; })) -> doesn't consider directories - { - auto getImage = [&](SyncDirection dir, SyncOperation soDefault) - { - return mirrorIfRtl(getSyncOpImage(selection[0]->getSyncOperation() != SO_EQUAL ? - selection[0]->testSyncOperation(dir) : soDefault)); - }; - const wxBitmap opRight = getImage(SyncDirection::RIGHT, SO_OVERWRITE_RIGHT); - const wxBitmap opNone = getImage(SyncDirection::NONE, SO_DO_NOTHING ); - const wxBitmap opLeft = getImage(SyncDirection::LEFT, SO_OVERWRITE_LEFT ); - - wxString shortCutLeft = L"\tAlt+Left"; - wxString shortCutRight = L"\tAlt+Right"; - if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) - std::swap(shortCutLeft, shortCutRight); - - menu.addItem(_("Set direction:") + L" ->" + shortCutRight, [this, &selection] { setSyncDirManually(selection, SyncDirection::RIGHT); }, &opRight); - menu.addItem(_("Set direction:") + L" -" L"\tAlt+Down", [this, &selection] { setSyncDirManually(selection, SyncDirection::NONE); }, &opNone); - menu.addItem(_("Set direction:") + L" <-" + shortCutLeft, [this, &selection] { setSyncDirManually(selection, SyncDirection::LEFT); }, &opLeft); - //Gtk needs a direction, "<-", because it has no context menu icons! - //Gtk requires "no spaces" for shortcut identifiers! - menu.addSeparator(); - } - - //---------------------------------------------------------------------------------------------------- - //FILE FILTER - auto addFilterMenu = [&](const std::wstring& label, const wxString& iconName, bool include) - { - if (selection.size() == 1) - { - ContextMenu submenu; - - const bool isDir = dynamic_cast<const DirPair*>(selection[0]) != nullptr; - - //by short name - Zstring labelShort = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + selection[0]->getObjShortName(); - if (isDir) - labelShort += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); - submenu.addItem(utfCvrtTo<wxString>(labelShort), [this, &selection, include] { filterShortname(*selection[0], include); }); - - //by relative path - Zstring labelRel = FILE_NAME_SEPARATOR + selection[0]->getObjRelativeName(); - if (isDir) - labelRel += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); - submenu.addItem(utfCvrtTo<wxString>(labelRel), [this, &selection, include] { filterItems(selection, include); }); - - menu.addSubmenu(label, submenu, &getResourceImage(iconName)); - } - else if (selection.size() > 1) - { - //by relative path - menu.addItem(label + L" <" + _("multiple selection") + L">", - [this, &selection, include] { filterItems(selection, include); }, &getResourceImage(iconName)); - } - }; - addFilterMenu(_("Include via filter:"), L"filter_include_small", true); - addFilterMenu(_("Exclude via filter:"), L"filter_exclude_small", false); - - //---------------------------------------------------------------------------------------------------- - if (!selection.empty()) - { - if (selection[0]->isActive()) - menu.addItem(_("Exclude temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, false); }, &getResourceImage(L"checkboxFalse")); - else - menu.addItem(_("Include temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, true); }, &getResourceImage(L"checkboxTrue")); - } - else - menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false); - - //---------------------------------------------------------------------------------------------------- - //CONTEXT_DELETE_FILES - menu.addSeparator(); - - menu.addItem(_("Delete") + L"\tDel", [&] { deleteSelectedFiles(selection, selection); }, nullptr, !selection.empty()); - - menu.popup(*this); -} - - -void MainDialog::onMainGridContextC(GridClickEvent& event) -{ - ContextMenu menu; - - menu.addItem(_("Include all"), [&] - { - zen::setActiveStatus(true, folderCmp); - updateGui(); - }, nullptr, gridDataView->rowsTotal() > 0); - - menu.addItem(_("Exclude all"), [&] - { - zen::setActiveStatus(false, folderCmp); - updateGuiDelayedIf(currentCfg.hideExcludedItems); //show update GUI before removing rows - }, nullptr, gridDataView->rowsTotal() > 0); - - menu.popup(*this); -} - -void MainDialog::onMainGridContextL(GridClickEvent& event) -{ - onMainGridContextRim(true); -} - -void MainDialog::onMainGridContextR(GridClickEvent& event) -{ - onMainGridContextRim(false); -} - -void MainDialog::onMainGridContextRim(bool leftSide) -{ - const auto& selection = getGridSelection(); //referenced by lambdas! - ContextMenu menu; - - if (!selection.empty()) - { - auto getImage = [&](SyncDirection dir, SyncOperation soDefault) - { - return mirrorIfRtl(getSyncOpImage(selection[0]->getSyncOperation() != SO_EQUAL ? - selection[0]->testSyncOperation(dir) : soDefault)); - }; - const wxBitmap opRight = getImage(SyncDirection::RIGHT, SO_OVERWRITE_RIGHT); - const wxBitmap opNone = getImage(SyncDirection::NONE, SO_DO_NOTHING ); - const wxBitmap opLeft = getImage(SyncDirection::LEFT, SO_OVERWRITE_LEFT ); - - wxString shortCutLeft = L"\tAlt+Left"; - wxString shortCutRight = L"\tAlt+Right"; - if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) - std::swap(shortCutLeft, shortCutRight); - - menu.addItem(_("Set direction:") + L" ->" + shortCutRight, [this, &selection] { setSyncDirManually(selection, SyncDirection::RIGHT); }, &opRight); - menu.addItem(_("Set direction:") + L" -" L"\tAlt+Down", [this, &selection] { setSyncDirManually(selection, SyncDirection::NONE); }, &opNone); - menu.addItem(_("Set direction:") + L" <-" + shortCutLeft, [this, &selection] { setSyncDirManually(selection, SyncDirection::LEFT); }, &opLeft); - //Gtk needs a direction, "<-", because it has no context menu icons! - //Gtk requires "no spaces" for shortcut identifiers! - menu.addSeparator(); - } - - //---------------------------------------------------------------------------------------------------- - //FILE FILTER - auto addFilterMenu = [&](const wxString& label, const wxString& iconName, bool include) - { - if (selection.size() == 1) - { - ContextMenu submenu; - - const bool isDir = dynamic_cast<const DirPair*>(selection[0]) != nullptr; - - //by extension - if (!isDir) - { - const Zstring filename = afterLast(selection[0]->getObjRelativeName(), FILE_NAME_SEPARATOR); - if (contains(filename, Zchar('.'))) //be careful: afterLast returns the whole string if '.' is not found! - { - const Zstring extension = afterLast(filename, Zchar('.')); - submenu.addItem(L"*." + utfCvrtTo<wxString>(extension), - [this, extension, include] { filterExtension(extension, include); }); - } - } - - //by short name - Zstring labelShort = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + selection[0]->getObjShortName(); - if (isDir) - labelShort += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); - submenu.addItem(utfCvrtTo<wxString>(labelShort), [this, &selection, include] { filterShortname(*selection[0], include); }); - - //by relative path - Zstring labelRel = FILE_NAME_SEPARATOR + selection[0]->getObjRelativeName(); - if (isDir) - labelRel += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); - submenu.addItem(utfCvrtTo<wxString>(labelRel), [this, &selection, include] { filterItems(selection, include); }); - - menu.addSubmenu(label, submenu, &getResourceImage(iconName)); - } - else if (selection.size() > 1) - { - //by relative path - menu.addItem(label + L" <" + _("multiple selection") + L">", - [this, &selection, include] { filterItems(selection, include); }, &getResourceImage(iconName)); - } - }; - addFilterMenu(_("Include via filter:"), L"filter_include_small", true); - addFilterMenu(_("Exclude via filter:"), L"filter_exclude_small", false); - - //---------------------------------------------------------------------------------------------------- - if (!selection.empty()) - { - if (selection[0]->isActive()) - menu.addItem(_("Exclude temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, false); }, &getResourceImage(L"checkboxFalse")); - else - menu.addItem(_("Include temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, true); }, &getResourceImage(L"checkboxTrue")); - } - else - menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false); - - //---------------------------------------------------------------------------------------------------- - //CONTEXT_EXTERNAL_APP - if (!globalCfg.gui.externelApplications.empty()) - { - menu.addSeparator(); - - for (auto it = globalCfg.gui.externelApplications.begin(); - it != globalCfg.gui.externelApplications.end(); - ++it) - { - //translate default external apps on the fly: 1. "open in explorer" 2. "start directly" - wxString description = zen::implementation::translate(it->first); - if (description.empty()) - description = L" "; //wxWidgets doesn't like empty items - - const wxString command = it->second; //COPY into lambda - - auto openApp = [this, &selection, leftSide, command] { openExternalApplication(command, selection, leftSide); }; - - if (it == globalCfg.gui.externelApplications.begin()) - description += L"\tEnter"; - - menu.addItem(description, openApp, nullptr, !selection.empty()); - } - } - //---------------------------------------------------------------------------------------------------- - //CONTEXT_DELETE_FILES - menu.addSeparator(); - - menu.addItem(_("Delete") + L"\tDel", [this] - { - deleteSelectedFiles( - getGridSelection(true, false), - getGridSelection(false, true)); - }, nullptr, !selection.empty()); - - menu.popup(*this); -} - - - -void MainDialog::filterPhrase(const Zstring& phrase, bool include, bool addNewLine) -{ - Zstring& filterString = [&]() -> Zstring& - { - if (include) - { - Zstring& includeFilter = currentCfg.mainCfg.globalFilter.includeFilter; - if (NameFilter::isNull(includeFilter, FilterConfig().excludeFilter)) //fancy way of checking for "*" include - includeFilter.clear(); - return includeFilter; - } - else - return currentCfg.mainCfg.globalFilter.excludeFilter; - }(); - - if (addNewLine) - { - if (!filterString.empty() && !endsWith(filterString, Zstr("\n"))) - filterString += Zstr("\n"); - filterString += phrase; - } - else - { - if (!filterString.empty() && !endsWith(filterString, Zstr("\n")) && !endsWith(filterString, Zstr(";"))) - filterString += Zstr("\n"); - filterString += phrase + Zstr(";"); //';' is appended to 'mark' that next exclude extension entry won't write to new line - } - - updateGlobalFilterButton(); - if (include) - applyFilterConfig(); //user's temporary exclusions lost! - else //do not fully apply filter, just exclude new items: preserve user's temporary exclusions - { - std::for_each(begin(folderCmp), end(folderCmp), [&](BaseDirPair& baseDirObj) { addHardFiltering(baseDirObj, phrase); }); - updateGui(); - } -} - - -void MainDialog::filterExtension(const Zstring& extension, bool include) -{ - assert(!extension.empty()); - filterPhrase(Zstr("*.") + extension, include, false); -} - - -void MainDialog::filterShortname(const FileSystemObject& fsObj, bool include) -{ - Zstring phrase = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + fsObj.getObjShortName(); - const bool isDir = dynamic_cast<const DirPair*>(&fsObj) != nullptr; - if (isDir) - phrase += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); //include filter: * required; exclude filter: * optional, but let's still apply it! - - filterPhrase(phrase, include, true); -} - - -void MainDialog::filterItems(const std::vector<FileSystemObject*>& selection, bool include) -{ - if (!selection.empty()) - { - Zstring phrase; - for (auto it = selection.begin(); it != selection.end(); ++it) - { - FileSystemObject* fsObj = *it; - - if (it != selection.begin()) - phrase += Zstr("\n"); - - //#pragma warning(suppress: 6011) -> fsObj bound in this context! - phrase += FILE_NAME_SEPARATOR + fsObj->getObjRelativeName(); - - const bool isDir = dynamic_cast<const DirPair*>(fsObj) != nullptr; - if (isDir) - phrase += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); //include filter: * required; exclude filter: * optional, but let's still apply it! - } - filterPhrase(phrase, include, true); - } -} - - -void MainDialog::onGridLabelContextC(GridClickEvent& event) -{ - ContextMenu menu; - - const bool actionView = m_bpButtonViewTypeSyncAction->isActive(); - menu.addRadio(_("Category") + (actionView ? L"\tF9" : L""), [&] { setViewTypeSyncAction(false); }, !actionView); - menu.addRadio(_("Action") + (!actionView ? L"\tF9" : L""), [&] { setViewTypeSyncAction(true ); }, actionView); - - //menu.addItem(_("Category") + L"\tF9", [&] { setViewTypeSyncAction(false); }, m_bpButtonViewTypeSyncAction->isActive() ? nullptr : &getResourceImage(L"compare_small")); - //menu.addItem(_("Action"), [&] { setViewTypeSyncAction(true ); }, m_bpButtonViewTypeSyncAction->isActive() ? &getResourceImage(L"sync_small") : nullptr); - menu.popup(*this); -} - - -void MainDialog::onGridLabelContextL(GridClickEvent& event) -{ - onGridLabelContext(*m_gridMainL, static_cast<ColumnTypeRim>(event.colType_), getDefaultColumnAttributesLeft()); -} -void MainDialog::onGridLabelContextR(GridClickEvent& event) -{ - onGridLabelContext(*m_gridMainR, static_cast<ColumnTypeRim>(event.colType_), getDefaultColumnAttributesRight()); -} - - -void MainDialog::onGridLabelContext(Grid& grid, ColumnTypeRim type, const std::vector<ColumnAttributeRim>& defaultColumnAttributes) -{ - ContextMenu menu; - - auto toggleColumn = [&](ColumnType ct) - { - auto colAttr = grid.getColumnConfig(); - - for (Grid::ColumnAttribute& ca : colAttr) - if (ca.type_ == ct) - { - ca.visible_ = !ca.visible_; - grid.setColumnConfig(colAttr); - return; - } - }; - - if (const GridData* prov = grid.getDataProvider()) - for (const Grid::ColumnAttribute& ca : grid.getColumnConfig()) - menu.addCheckBox(prov->getColumnLabel(ca.type_), [ca, toggleColumn] { toggleColumn(ca.type_); }, - ca.visible_, ca.type_ != static_cast<ColumnType>(COL_TYPE_FILENAME)); //do not allow user to hide file name column! - //---------------------------------------------------------------------------------------------- - menu.addSeparator(); - - auto setDefault = [&] - { - grid.setColumnConfig(gridview::convertConfig(defaultColumnAttributes)); - }; - menu.addItem(_("&Default"), setDefault); //'&' -> reuse text from "default" buttons elsewhere - //---------------------------------------------------------------------------------------------- - menu.addSeparator(); - menu.addCheckBox(_("Show icons:"), [&] - { - globalCfg.gui.showIcons = !globalCfg.gui.showIcons; - gridview::setupIcons(*m_gridMainL, *m_gridMainC, *m_gridMainR, globalCfg.gui.showIcons, convert(globalCfg.gui.iconSize)); - - }, globalCfg.gui.showIcons); - - auto setIconSize = [&](xmlAccess::FileIconSize sz) - { - globalCfg.gui.iconSize = sz; - gridview::setupIcons(*m_gridMainL, *m_gridMainC, *m_gridMainR, globalCfg.gui.showIcons, convert(sz)); - }; - auto addSizeEntry = [&](const wxString& label, xmlAccess::FileIconSize sz) - { - auto setIconSize2 = setIconSize; //bring into scope - menu.addRadio(label, [sz, setIconSize2] { setIconSize2(sz); }, globalCfg.gui.iconSize == sz, globalCfg.gui.showIcons); - }; - addSizeEntry(L" " + _("Small" ), xmlAccess::ICON_SIZE_SMALL ); - addSizeEntry(L" " + _("Medium"), xmlAccess::ICON_SIZE_MEDIUM); - addSizeEntry(L" " + _("Large" ), xmlAccess::ICON_SIZE_LARGE ); - //---------------------------------------------------------------------------------------------- - if (type == COL_TYPE_DATE) - { - menu.addSeparator(); - - auto selectTimeSpan = [&] - { - if (showSelectTimespanDlg(this, manualTimeSpanFrom, manualTimeSpanTo) == ReturnSmallDlg::BUTTON_OKAY) - { - applyTimeSpanFilter(folderCmp, manualTimeSpanFrom, manualTimeSpanTo); //overwrite current active/inactive settings - //updateGuiDelayedIf(currentCfg.hideExcludedItems); //show update GUI before removing rows - updateGui(); - } - }; - menu.addItem(_("Select time span..."), selectTimeSpan); - } - - menu.popup(*this); -} - - -void MainDialog::OnContextSetLayout(wxMouseEvent& event) -{ - ContextMenu menu; - - menu.addItem(_("Default view"), [&] - { - m_splitterMain->setSashOffset(0); - auiMgr.LoadPerspective(defaultPerspective); - updateGuiForFolderPair(); - }); - //---------------------------------------------------------------------------------------- - std::vector<std::pair<wxString, wxString>> captionNameMap; //(caption, identifier) - - const wxAuiPaneInfoArray& paneArray = auiMgr.GetAllPanes(); - for (size_t i = 0; i < paneArray.size(); ++i) - if (!paneArray[i].IsShown() && !paneArray[i].name.empty() && - paneArray[i].window != compareStatus->getAsWindow() && - paneArray[i].window != m_panelSearch) - captionNameMap.push_back(std::make_pair(paneArray[i].caption, paneArray[i].name)); - - if (!captionNameMap.empty()) - menu.addSeparator(); - - auto showPanel = [&](const wxString& identifier) - { - auiMgr.GetPane(identifier).Show(); - auiMgr.Update(); - }; - - for (auto it = captionNameMap.begin(); it != captionNameMap.end(); ++it) - { - const wxString label = replaceCpy(_("Show \"%x\""), L"%x", it->first); - const wxString identifier = it->second; - - menu.addItem(label, [showPanel, identifier] { showPanel(identifier); }); - } - - menu.popup(*this); -} - - -void MainDialog::OnCompSettingsContext(wxMouseEvent& event) -{ - ContextMenu menu; - - auto setVariant = [&](CompareVariant var) - { - currentCfg.mainCfg.cmpConfig.compareVar = var; - applyCompareConfig(true); //true: switchMiddleGrid - }; - - auto currentVar = getConfig().mainCfg.cmpConfig.compareVar; - - menu.addRadio(_("File time and size"), [&] { setVariant(CMP_BY_TIME_SIZE); }, currentVar == CMP_BY_TIME_SIZE); - menu.addRadio(_("File content" ), [&] { setVariant(CMP_BY_CONTENT); }, currentVar == CMP_BY_CONTENT); - - menu.popup(*this); -} - - -void MainDialog::OnSyncSettingsContext(wxMouseEvent& event) -{ - ContextMenu menu; - - auto setVariant = [&](DirectionConfig::Variant var) - { - currentCfg.mainCfg.syncCfg.directionCfg.var = var; - applySyncConfig(); - }; - - const auto currentVar = getConfig().mainCfg.syncCfg.directionCfg.var; - - menu.addRadio(L"<- " + _("Two way") + L" ->" , [&] { setVariant(DirectionConfig::TWOWAY); }, currentVar == DirectionConfig::TWOWAY); - menu.addRadio( _("Mirror") + L" ->>", [&] { setVariant(DirectionConfig::MIRROR); }, currentVar == DirectionConfig::MIRROR); - menu.addRadio( _("Update") + L" ->" , [&] { setVariant(DirectionConfig::UPDATE); }, currentVar == DirectionConfig::UPDATE); - menu.addRadio( _("Custom") , [&] { setVariant(DirectionConfig::CUSTOM); }, currentVar == DirectionConfig::CUSTOM); - - menu.popup(*this); -} - - -void MainDialog::onNaviPanelFilesDropped(FileDropEvent& event) -{ - loadConfiguration(toZ(event.getFiles())); - event.Skip(); -} - - -void MainDialog::onDirSelected(wxCommandEvent& event) -{ - //left and right directory text-control and dirpicker are synchronized by MainFolderDragDrop automatically - clearGrid(); //disable the sync button - event.Skip(); -} - - -void MainDialog::onDirManualCorrection(wxCommandEvent& event) -{ - updateUnsavedCfgStatus(); - event.Skip(); -} - - -wxString getFormattedHistoryElement(const Zstring& filename) -{ - Zstring output = afterLast(filename, FILE_NAME_SEPARATOR); - if (endsWith(output, Zstr(".ffs_gui"))) - output = beforeLast(output, Zstr('.')); - return utfCvrtTo<wxString>(output); -} - - -void MainDialog::addFileToCfgHistory(const std::vector<Zstring>& filenames) -{ - //determine highest "last use" index number of m_listBoxHistory - int lastUseIndexMax = 0; - for (unsigned int i = 0; i < m_listBoxHistory->GetCount(); ++i) - if (auto histData = dynamic_cast<const wxClientHistoryData*>(m_listBoxHistory->GetClientObject(i))) - if (histData->lastUseIndex_ > lastUseIndexMax) - lastUseIndexMax = histData->lastUseIndex_; - - std::deque<bool> selections(m_listBoxHistory->GetCount()); //items to select after update of history list - - for (auto it = filenames.begin(); it != filenames.end(); ++it) - { - const Zstring& filename = *it; - - //Do we need to additionally check for aliases of the same physical files here? (and aliases for lastRunConfigName?) - - const auto itemPos = [&]() -> std::pair<wxClientHistoryData*, unsigned int> - { - for (unsigned int i = 0; i < m_listBoxHistory->GetCount(); ++i) - if (auto histData = dynamic_cast<wxClientHistoryData*>(m_listBoxHistory->GetClientObject(i))) - { - if (EqualFilename()(filename, histData->cfgFile_)) - return std::make_pair(histData, i); - } - else - assert(false); - return std::make_pair(nullptr, 0); - }(); - - if (itemPos.first) //update - { - itemPos.first->lastUseIndex_ = ++lastUseIndexMax; - selections[itemPos.second] = true; - } - else //insert - { - wxString label; - unsigned int newPos = 0; - - if (EqualFilename()(filename, lastRunConfigName())) - label = L"<" + _("Last session") + L">"; - else - { - //workaround wxWidgets 2.9 bug on GTK screwing up the client data if the list box is sorted: - label = getFormattedHistoryElement(filename); - //"linear insertion sort": - for (; newPos < m_listBoxHistory->GetCount(); ++newPos) - if (label.CmpNoCase(m_listBoxHistory->GetString(newPos)) < 0) - break; - } - - assert(!m_listBoxHistory->IsSorted()); - m_listBoxHistory->Insert(label, newPos, new wxClientHistoryData(filename, ++lastUseIndexMax)); - - selections.insert(selections.begin() + newPos, true); - } - } - - assert(selections.size() == m_listBoxHistory->GetCount()); - - //do not apply selections immediately but only when needed! - //this prevents problems with m_listBoxHistory losing keyboard selection focus if identical selection is redundantly reapplied - for (int pos = 0; pos < static_cast<int>(selections.size()); ++pos) - if (m_listBoxHistory->IsSelected(pos) != selections[pos]) - m_listBoxHistory->SetSelection(pos, selections[pos]); -} - - -void MainDialog::removeObsoleteCfgHistoryItems(const std::vector<Zstring>& filenames) -{ - //don't use wxString: NOT thread-safe! (e.g. non-atomic ref-count) - - auto getMissingFilesAsync = [filenames]() -> std::vector<Zstring> - { - //boost::this_thread::sleep(boost::posix_time::millisec(5000)); - - //check existence of all config files in parallel! - std::list<boost::unique_future<bool>> fileEx; - - for (auto it = filenames.begin(); it != filenames.end(); ++it) //avoid VC11 compiler issues with std::for_each - { - const Zstring filename = *it; //don't reference iterator in lambda! - fileEx.push_back(zen::async2<bool>([=] { return fileExists(filename); })); - } - - //potentially slow network access => limit maximum wait time! - wait_for_all_timed(fileEx.begin(), fileEx.end(), boost::posix_time::milliseconds(1000)); - - std::vector<Zstring> missingFiles; - - auto itFut = fileEx.begin(); - for (auto it = filenames.begin(); it != filenames.end(); ++it, (void)++itFut) //void: prevent ADL from dragging in boost's ,-overload: "MSVC warning C4913: user defined binary operator ',' exists but no overload could convert all operands" - if (itFut->is_ready() && !itFut->get()) //remove only files that are confirmed to be non-existent - missingFiles.push_back(*it); - - return missingFiles; - }; - - processAsync(getMissingFilesAsync, [this](const std::vector<Zstring>& files) { removeCfgHistoryItems(files); }); -} - - -void MainDialog::removeCfgHistoryItems(const std::vector<Zstring>& filenames) -{ - std::for_each(filenames.begin(), filenames.end(), [&](const Zstring& filename) - { - const int histSize = m_listBoxHistory->GetCount(); - for (int i = 0; i < histSize; ++i) - if (auto histData = dynamic_cast<wxClientHistoryData*>(m_listBoxHistory->GetClientObject(i))) - if (EqualFilename()(filename, histData->cfgFile_)) - { - m_listBoxHistory->Delete(i); - break; - } - }); -} - - -void MainDialog::updateUnsavedCfgStatus() -{ - const Zstring activeCfgFilename = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstring(); - - const bool haveUnsavedCfg = lastConfigurationSaved != getConfig(); - - //update save config button - const bool allowSave = haveUnsavedCfg || - activeConfigFiles.size() > 1; - - auto makeBrightGrey = [](const wxBitmap& bmp) -> wxBitmap - { - wxImage img = bmp.ConvertToImage().ConvertToGreyscale(1.0/3, 1.0/3, 1.0/3); //treat all channels equally! - brighten(img, 80); - return img; - }; - //setImage(*m_bpButtonSave, greyScale(getResourceImage(L"save"))); - - setImage(*m_bpButtonSave, allowSave ? getResourceImage(L"save") : makeBrightGrey(getResourceImage(L"save"))); - m_bpButtonSave->Enable(allowSave); - m_menuItemSave->Enable(allowSave); //bitmap is automatically greyscaled on Win7 (introducing a crappy looking shift), but not on XP - - //set main dialog title - wxString title; - if (haveUnsavedCfg) - title += L'*'; - - if (!activeCfgFilename.empty()) - title += toWx(activeCfgFilename); - else if (activeConfigFiles.size() > 1) - { - const wchar_t* EM_DASH = L" \u2014 "; - title += xmlAccess::extractJobName(activeConfigFiles[0]); - std::for_each(activeConfigFiles.begin() + 1, activeConfigFiles.end(), [&](const Zstring& filename) { title += EM_DASH + xmlAccess::extractJobName(filename); }); - } - else - title += L"FreeFileSync - " + _("Folder Comparison and Synchronization"); - - SetTitle(title); -} - - -void MainDialog::OnConfigSave(wxCommandEvent& event) -{ - const Zstring activeCfgFilename = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstring(); - - //if we work on a single named configuration document: save directly if changed - //else: always show file dialog - if (!activeCfgFilename.empty()) - { - using namespace xmlAccess; - - switch (getXmlType(activeCfgFilename)) //throw() - { - case XML_TYPE_GUI: - trySaveConfig(&activeCfgFilename); - return; - case XML_TYPE_BATCH: - trySaveBatchConfig(&activeCfgFilename); - return; - case XML_TYPE_GLOBAL: - case XML_TYPE_OTHER: - assert(false); - return; - } - } - - trySaveConfig(nullptr); -} - - -void MainDialog::OnConfigSaveAs(wxCommandEvent& event) -{ - trySaveConfig(nullptr); -} - - -void MainDialog::OnSaveAsBatchJob(wxCommandEvent& event) -{ - trySaveBatchConfig(nullptr); -} - - -bool MainDialog::trySaveConfig(const Zstring* fileNameGui) //return true if saved successfully -{ - Zstring targetFilename; - - if (fileNameGui) - { - targetFilename = *fileNameGui; - assert(endsWith(targetFilename, Zstr(".ffs_gui"))); - } - else - { - Zstring defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstr("SyncSettings.ffs_gui"); - //attention: activeConfigFiles may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config! - if (endsWith(defaultFileName, Zstr(".ffs_batch"))) - replace(defaultFileName, Zstr(".ffs_batch"), Zstr(".ffs_gui"), false); - - wxFileDialog filePicker(this, //put modal dialog on stack: creating this on freestore leads to memleak! - wxEmptyString, - //OS X really needs dir/file separated like this: - utfCvrtTo<wxString>(beforeLast(defaultFileName, FILE_NAME_SEPARATOR)), //default dir; empty string if / not found - utfCvrtTo<wxString>(afterLast (defaultFileName, FILE_NAME_SEPARATOR)), //default file; whole string if / not found - wxString(L"FreeFileSync (*.ffs_gui)|*.ffs_gui") + L"|" +_("All files") + L" (*.*)|*", - wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - if (filePicker.ShowModal() != wxID_OK) - return false; - targetFilename = toZ(filePicker.GetPath()); - } - - const xmlAccess::XmlGuiConfig guiCfg = getConfig(); - - try - { - xmlAccess::writeConfig(guiCfg, targetFilename); //throw FfsXmlError - setLastUsedConfig(targetFilename, guiCfg); - - flashStatusInformation(_("Configuration saved")); - return true; - } - catch (const xmlAccess::FfsXmlError& e) - { - showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - return false; - } -} - - -bool MainDialog::trySaveBatchConfig(const Zstring* fileNameBatch) -{ - //essentially behave like trySaveConfig(): the collateral damage of not saving GUI-only settings "hideExcludedItems, m_bpButtonViewTypeSyncAction" is negliable - - const xmlAccess::XmlGuiConfig guiCfg = getConfig(); - - Zstring targetFilename; - xmlAccess::XmlBatchConfig batchCfg; - - if (fileNameBatch) - { - targetFilename = *fileNameBatch; - batchCfg = convertGuiToBatchPreservingExistingBatch(guiCfg, *fileNameBatch); - assert(endsWith(targetFilename, Zstr(".ffs_batch"))); - } - else - { - const Zstring activeCfgFilename = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstring(); - batchCfg = convertGuiToBatchPreservingExistingBatch(guiCfg, activeCfgFilename); - - //let user change batch config: this should change batch-exclusive settings only, else the "setLastUsedConfig" below would be somewhat of a lie - if (!customizeBatchConfig(this, - batchCfg, //in/out - globalCfg.gui.onCompletionHistory, - globalCfg.gui.onCompletionHistoryMax)) - return false; - - Zstring defaultFileName = !activeCfgFilename.empty() ? activeCfgFilename : Zstr("BatchRun.ffs_batch"); - //attention: activeConfigFiles may be a *.ffs_gui file! We don't want to overwrite it with a BATCH config! - if (endsWith(defaultFileName, Zstr(".ffs_gui"))) - replace(defaultFileName, Zstr(".ffs_gui"), Zstr(".ffs_batch")); - - wxFileDialog filePicker(this, //put modal dialog on stack: creating this on freestore leads to memleak! - wxEmptyString, - //OS X really needs dir/file separated like this: - utfCvrtTo<wxString>(beforeLast(defaultFileName, FILE_NAME_SEPARATOR)), //default dir; empty string if / not found - utfCvrtTo<wxString>(afterLast (defaultFileName, FILE_NAME_SEPARATOR)), //default file; whole string if / not found - _("FreeFileSync batch") + L" (*.ffs_batch)|*.ffs_batch" + L"|" +_("All files") + L" (*.*)|*", - wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - if (filePicker.ShowModal() != wxID_OK) - return false; - targetFilename = toZ(filePicker.GetPath()); - } - - try - { - xmlAccess::writeConfig(batchCfg, targetFilename); //throw FfsXmlError - - setLastUsedConfig(targetFilename, guiCfg); //[!] behave as if we had saved guiCfg - flashStatusInformation(_("Configuration saved")); - return true; - } - catch (const xmlAccess::FfsXmlError& e) - { - showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - return false; - } -} - - -bool MainDialog::saveOldConfig() //return false on user abort -{ - if (lastConfigurationSaved != getConfig()) - { - const Zstring activeCfgFilename = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstring(); - - //notify user about changed settings - if (globalCfg.optDialogs.popupOnConfigChange) - if (!activeCfgFilename.empty()) - //only if check is active and non-default config file loaded - { - bool neverSaveChanges = false; - switch (showConfirmationDialog3(this, DialogInfoType::INFO, PopupDialogCfg3(). - setTitle(toWx(activeCfgFilename)). - setMainInstructions(replaceCpy(_("Do you want to save changes to %x?"), L"%x", fmtFileName(afterLast(activeCfgFilename, FILE_NAME_SEPARATOR)))). - setCheckBox(neverSaveChanges, _("Never save &changes"), ConfirmationButton3::DO_IT), - _("&Save"), _("Do&n't save"))) - { - case ConfirmationButton3::DO_IT: //save - using namespace xmlAccess; - switch (getXmlType(activeCfgFilename)) //throw() - { - case XML_TYPE_GUI: - return trySaveConfig(&activeCfgFilename); - case XML_TYPE_BATCH: - return trySaveBatchConfig(&activeCfgFilename); - case XML_TYPE_GLOBAL: - case XML_TYPE_OTHER: - assert(false); - return false; - } - break; - - case ConfirmationButton3::DONT_DO_IT: //don't save - globalCfg.optDialogs.popupOnConfigChange = !neverSaveChanges; - break; - - case ConfirmationButton3::CANCEL: - return false; - } - } - - //discard current reference file(s), this ensures next app start will load <last session> instead of the original non-modified config selection - setLastUsedConfig(std::vector<Zstring>(), lastConfigurationSaved); - //this seems to make theoretical sense also: the job of this function is to make sure current (volatile) config and reference file name are in sync - // => if user does not save cfg, it is not attached to a physical file names anymore! - } - return true; -} - - -void MainDialog::OnConfigLoad(wxCommandEvent& event) -{ - const Zstring activeCfgFilename = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstring(); - - wxFileDialog filePicker(this, - wxEmptyString, - utfCvrtTo<wxString>(beforeLast(activeCfgFilename, FILE_NAME_SEPARATOR)), //set default dir: empty string if "activeConfigFiles" is empty or has no path separator - wxEmptyString, - wxString(L"FreeFileSync (*.ffs_gui; *.ffs_batch)|*.ffs_gui;*.ffs_batch") + L"|" +_("All files") + L" (*.*)|*", - wxFD_OPEN | wxFD_MULTIPLE); - - if (filePicker.ShowModal() == wxID_OK) - { - wxArrayString tmp; - filePicker.GetPaths(tmp); - std::vector<wxString> filenames(tmp.begin(), tmp.end()); - - loadConfiguration(toZ(filenames)); - } -} - - -void MainDialog::OnConfigNew(wxCommandEvent& event) -{ - if (!saveOldConfig()) //notify user about changed settings - return; - - xmlAccess::XmlGuiConfig newConfig; - - //add default exclusion filter: this is only ever relevant when creating new configurations! - //a default XmlGuiConfig does not need these user-specific exclusions! - Zstring& excludeFilter = newConfig.mainCfg.globalFilter.excludeFilter; - if (!excludeFilter.empty() && !endsWith(excludeFilter, Zstr("\n"))) - excludeFilter += Zstr("\n"); - excludeFilter += globalCfg.gui.defaultExclusionFilter; - - setConfig(newConfig, std::vector<Zstring>()); -} - - -void MainDialog::OnLoadFromHistory(wxCommandEvent& event) -{ - wxArrayInt selections; - m_listBoxHistory->GetSelections(selections); - - std::vector<Zstring> filenames; - std::for_each(selections.begin(), selections.end(), - [&](int pos) - { - if (auto histData = dynamic_cast<const wxClientHistoryData*>(m_listBoxHistory->GetClientObject(pos))) - filenames.push_back(histData->cfgFile_); - else - assert(false); - }); - - if (!filenames.empty()) - loadConfiguration(filenames); - - //user changed m_listBoxHistory selection so it's this method's responsibility to synchronize with activeConfigFiles: - //- if user cancelled saving old config - //- there's an error loading new config - //- filenames is empty and user tried to unselect the current config - addFileToCfgHistory(activeConfigFiles); -} - - -void MainDialog::OnLoadFromHistoryDoubleClick(wxCommandEvent& event) -{ - wxArrayInt selections; - m_listBoxHistory->GetSelections(selections); - - std::vector<Zstring> filenames; - std::for_each(selections.begin(), selections.end(), [&](int pos) - { - if (auto histData = dynamic_cast<const wxClientHistoryData*>(m_listBoxHistory->GetClientObject(pos))) - filenames.push_back(histData->cfgFile_); - else - assert(false); - }); - - if (!filenames.empty()) - if (loadConfiguration(filenames)) - { - //simulate button click on "compare" - wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); - if (wxEvtHandler* evtHandler = m_buttonCompare->GetEventHandler()) - evtHandler->ProcessEvent(dummy2); //synchronous call - } - - //synchronize m_listBoxHistory and activeConfigFiles, see OnLoadFromHistory() - addFileToCfgHistory(activeConfigFiles); -} - - -bool MainDialog::loadConfiguration(const std::vector<Zstring>& filenames) -{ - if (filenames.empty()) - return true; - - if (!saveOldConfig()) - return false; //cancelled by user - - //load XML - xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!! - try - { - //allow reading batch configurations also - xmlAccess::readAnyConfig(filenames, newGuiCfg); //throw FfsXmlError - - setConfig(newGuiCfg, filenames); - //flashStatusInformation(("Configuration loaded")); -> irrelevant!? - return true; - } - catch (const xmlAccess::FfsXmlError& e) - { - if (e.getSeverity() == xmlAccess::FfsXmlError::WARNING) - { - showNotificationDialog(this, DialogInfoType::WARNING, PopupDialogCfg().setDetailInstructions(e.toString())); - setConfig(newGuiCfg, filenames); - setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config due to parsing errors - } - else - showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - return false; - } -} - -void MainDialog::deleteSelectedCfgHistoryItems() -{ - wxArrayInt tmp; - m_listBoxHistory->GetSelections(tmp); - - std::set<int> selections(tmp.begin(), tmp.end()); //sort ascending! - //delete starting with high positions: - std::for_each(selections.rbegin(), selections.rend(), [&](int pos) { m_listBoxHistory->Delete(pos); }); - - //set active selection on next element to allow "batch-deletion" by holding down DEL key - if (!selections.empty() && m_listBoxHistory->GetCount() > 0) - { - int newSelection = *selections.begin(); - if (newSelection >= static_cast<int>(m_listBoxHistory->GetCount())) - newSelection = m_listBoxHistory->GetCount() - 1; - m_listBoxHistory->SetSelection(newSelection); - } -} - - -void MainDialog::OnCfgHistoryRightClick(wxMouseEvent& event) -{ - ContextMenu menu; - menu.addItem(_("Delete") + L"\tDel", [this] { deleteSelectedCfgHistoryItems(); }); - menu.popup(*this); -} - - -void MainDialog::OnCfgHistoryKeyEvent(wxKeyEvent& event) -{ - const int keyCode = event.GetKeyCode(); - if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE) - { - deleteSelectedCfgHistoryItems(); - return; //"swallow" event - } - event.Skip(); -} - - -void MainDialog::OnClose(wxCloseEvent& event) -{ - //attention: system shutdown: is handled in onQueryEndSession()! - - //regular destruction handling - if (event.CanVeto()) - { - const bool cancelled = !saveOldConfig(); //notify user about changed settings - if (cancelled) - { - //attention: this Veto() will NOT cancel system shutdown since saveOldConfig() blocks on modal dialog - - event.Veto(); - return; - } - } - - Destroy(); -} - - -void MainDialog::onCheckRows(CheckRowsEvent& event) -{ - std::set<size_t> selectedRows; - - const size_t rowLast = std::min(event.rowLast_, gridDataView->rowsOnView()); //consider dummy rows - for (size_t i = event.rowFirst_; i < rowLast; ++i) - selectedRows.insert(i); - - if (!selectedRows.empty()) - { - std::vector<FileSystemObject*> objects = gridDataView->getAllFileRef(selectedRows); - setFilterManually(objects, event.setIncluded_); - } -} - - -void MainDialog::onSetSyncDirection(SyncDirectionEvent& event) -{ - std::set<size_t> selectedRows; - - const size_t rowLast = std::min(event.rowLast_, gridDataView->rowsOnView()); //consider dummy rows - for (size_t i = event.rowFirst_; i < rowLast; ++i) - selectedRows.insert(i); - - if (!selectedRows.empty()) - { - std::vector<FileSystemObject*> objects = gridDataView->getAllFileRef(selectedRows); - setSyncDirManually(objects, event.direction_); - } -} - - -void MainDialog::setLastUsedConfig(const Zstring& filename, const xmlAccess::XmlGuiConfig& guiConfig) -{ - std::vector<Zstring> filenames; - filenames.push_back(filename); - setLastUsedConfig(filenames, guiConfig); -} - - -void MainDialog::setLastUsedConfig(const std::vector<Zstring>& filenames, - const xmlAccess::XmlGuiConfig& guiConfig) -{ - activeConfigFiles = filenames; - lastConfigurationSaved = guiConfig; - - addFileToCfgHistory(activeConfigFiles); //put filename on list of last used config files - - updateUnsavedCfgStatus(); -} - - -void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg, const std::vector<Zstring>& referenceFiles) -{ - currentCfg = newGuiCfg; - - //evaluate new settings... - - //(re-)set view filter buttons - setViewFilterDefault(); - - updateGlobalFilterButton(); - - //set first folder pair - firstFolderPair->setValues(currentCfg.mainCfg.firstPair.leftDirectory, - currentCfg.mainCfg.firstPair.rightDirectory, - currentCfg.mainCfg.firstPair.altCmpConfig, - currentCfg.mainCfg.firstPair.altSyncConfig, - currentCfg.mainCfg.firstPair.localFilter); - - //folderHistoryLeft->addItem(currentCfg.mainCfg.firstPair.leftDirectory); - //folderHistoryRight->addItem(currentCfg.mainCfg.firstPair.rightDirectory); - - setAddFolderPairs(currentCfg.mainCfg.additionalPairs); - - //read GUI layout - m_checkBoxHideExcluded->SetValue(currentCfg.hideExcludedItems); - - setViewTypeSyncAction(currentCfg.highlightSyncAction); - - clearGrid(); //+ update GUI! - - setLastUsedConfig(referenceFiles, newGuiCfg); -} - - -inline -FolderPairEnh getEnhancedPair(const FolderPairPanel* panel) -{ - return FolderPairEnh(panel->getLeftDir(), - panel->getRightDir(), - panel->getAltCompConfig(), - panel->getAltSyncConfig(), - panel->getAltFilterConfig()); -} - - -xmlAccess::XmlGuiConfig MainDialog::getConfig() const -{ - xmlAccess::XmlGuiConfig guiCfg = currentCfg; - - //load settings whose ownership lies not in currentCfg: - - //first folder pair - guiCfg.mainCfg.firstPair = FolderPairEnh(firstFolderPair->getLeftDir(), - firstFolderPair->getRightDir(), - firstFolderPair->getAltCompConfig(), - firstFolderPair->getAltSyncConfig(), - firstFolderPair->getAltFilterConfig()); - - //add additional pairs - guiCfg.mainCfg.additionalPairs.clear(); - std::transform(additionalFolderPairs.begin(), additionalFolderPairs.end(), - std::back_inserter(guiCfg.mainCfg.additionalPairs), getEnhancedPair); - - //sync preview - guiCfg.highlightSyncAction = m_bpButtonViewTypeSyncAction->isActive(); - - return guiCfg; -} - - -const Zstring& MainDialog::lastRunConfigName() -{ - static Zstring instance = zen::getConfigDir() + Zstr("LastRun.ffs_gui"); - return instance; -} - - -void MainDialog::updateGuiDelayedIf(bool condition) -{ - const int delay = 400; - - if (condition) - { - gridview::refresh(*m_gridMainL, *m_gridMainC, *m_gridMainR); - m_gridMainL->Update(); - m_gridMainC->Update(); - m_gridMainR->Update(); - - wxMilliSleep(delay); //some delay to show the changed GUI before removing rows from sight - } - - updateGui(); -} - - -void MainDialog::OnShowExcluded(wxCommandEvent& event) -{ - //toggle showing filtered rows - currentCfg.hideExcludedItems = !currentCfg.hideExcludedItems; - //make sure, checkbox and value are in sync - m_checkBoxHideExcluded->SetValue(currentCfg.hideExcludedItems); - - updateGui(); -} - - -void MainDialog::OnConfigureFilter(wxCommandEvent& event) -{ - if (showFilterDialog(this, currentCfg.mainCfg.globalFilter, _("Filter")) == ReturnSmallDlg::BUTTON_OKAY) - { - updateGlobalFilterButton(); //refresh global filter icon - applyFilterConfig(); //re-apply filter - } - - //event.Skip() -} - - -void MainDialog::OnGlobalFilterContext(wxMouseEvent& event) -{ - auto clearFilter = [&] - { - currentCfg.mainCfg.globalFilter = FilterConfig(); - updateGlobalFilterButton(); //refresh global filter icon - applyFilterConfig(); //re-apply filter - }; - auto copyFilter = [&] { filterCfgOnClipboard = make_unique<FilterConfig>(currentCfg.mainCfg.globalFilter); }; - auto pasteFilter = [&] - { - if (filterCfgOnClipboard) - { - currentCfg.mainCfg.globalFilter = *filterCfgOnClipboard; - updateGlobalFilterButton(); //refresh global filter icon - applyFilterConfig(); //re-apply filter - } - }; - - ContextMenu menu; - menu.addItem( _("Clear filter settings"), clearFilter, nullptr, !isNullFilter(currentCfg.mainCfg.globalFilter)); - menu.addSeparator(); - menu.addItem( _("Copy"), copyFilter, nullptr, !isNullFilter(currentCfg.mainCfg.globalFilter)); - menu.addItem( _("Paste"), pasteFilter, nullptr, filterCfgOnClipboard.get() != nullptr); - menu.popup(*this); -} - - -void MainDialog::OnToggleViewType(wxCommandEvent& event) -{ - setViewTypeSyncAction(!m_bpButtonViewTypeSyncAction->isActive()); //toggle view -} - - -void MainDialog::OnToggleViewButton(wxCommandEvent& event) -{ - if (auto button = dynamic_cast<ToggleButton*>(event.GetEventObject())) - { - button->toggle(); - updateGui(); - } - else - assert(false); -} - - -inline -wxBitmap buttonPressed(const std::string& name) -{ - wxBitmap background = getResourceImage(L"buttonPressed"); - return mirrorIfRtl( - layOver(getResourceImage(utfCvrtTo<wxString>(name)), background)); -} - - -inline -wxBitmap buttonReleased(const std::string& name) -{ - wxImage output = getResourceImage(utfCvrtTo<wxString>(name)).ConvertToImage().ConvertToGreyscale(1.0/3, 1.0/3, 1.0/3); //treat all channels equally! - //zen::moveImage(output, 1, 0); //move image right one pixel - - brighten(output, 80); - return mirrorIfRtl(output); -} - - -void MainDialog::initViewFilterButtons() -{ - m_bpButtonViewTypeSyncAction->init(getResourceImage(L"viewtype_sync_action"), getResourceImage(L"viewtype_cmp_result")); - //tooltip is updated dynamically in setViewTypeSyncAction() - - auto initButton = [](ToggleButton& btn, const char* imgName, const wxString& tooltip) { btn.init(buttonPressed(imgName), buttonReleased(imgName)); btn.SetToolTip(tooltip); }; - - //compare result buttons - initButton(*m_bpButtonShowLeftOnly, "cat_left_only", _("Show files that exist on left side only")); - initButton(*m_bpButtonShowRightOnly, "cat_right_only", _("Show files that exist on right side only")); - initButton(*m_bpButtonShowLeftNewer, "cat_left_newer", _("Show files that are newer on left")); - initButton(*m_bpButtonShowRightNewer, "cat_right_newer", _("Show files that are newer on right")); - initButton(*m_bpButtonShowEqual, "cat_equal", _("Show files that are equal")); - initButton(*m_bpButtonShowDifferent, "cat_different", _("Show files that are different")); - initButton(*m_bpButtonShowConflict, "cat_conflict", _("Show conflicts")); - - //sync preview buttons - initButton(*m_bpButtonShowCreateLeft, "so_create_left", _("Show files that will be created on the left side")); - initButton(*m_bpButtonShowCreateRight, "so_create_right", _("Show files that will be created on the right side")); - initButton(*m_bpButtonShowDeleteLeft, "so_delete_left", _("Show files that will be deleted on the left side")); - initButton(*m_bpButtonShowDeleteRight, "so_delete_right", _("Show files that will be deleted on the right side")); - initButton(*m_bpButtonShowUpdateLeft, "so_update_left", _("Show files that will be overwritten on left side")); - initButton(*m_bpButtonShowUpdateRight, "so_update_right", _("Show files that will be overwritten on right side")); - initButton(*m_bpButtonShowDoNothing, "so_none", _("Show files that won't be copied")); -} - - -void MainDialog::setViewFilterDefault() -{ - auto setButton = [](ToggleButton* tb, bool value) { tb->setActive(value); }; - - const auto& def = globalCfg.gui.viewFilterDefault; - setButton(m_bpButtonShowLeftOnly, def.leftOnly); - setButton(m_bpButtonShowRightOnly, def.rightOnly); - setButton(m_bpButtonShowLeftNewer, def.leftNewer); - setButton(m_bpButtonShowRightNewer, def.rightNewer); - setButton(m_bpButtonShowEqual, def.equal); - setButton(m_bpButtonShowDifferent, def.different); - setButton(m_bpButtonShowConflict, def.conflict); - - setButton(m_bpButtonShowCreateLeft, def.createLeft); - setButton(m_bpButtonShowCreateRight,def.createRight); - setButton(m_bpButtonShowUpdateLeft, def.updateLeft); - setButton(m_bpButtonShowUpdateRight,def.updateRight); - setButton(m_bpButtonShowDeleteLeft, def.deleteLeft); - setButton(m_bpButtonShowDeleteRight,def.deleteRight); - setButton(m_bpButtonShowDoNothing, def.doNothing); -} - - -void MainDialog::OnViewButtonRightClick(wxMouseEvent& event) -{ - auto setButtonDefault = [](const ToggleButton* tb, bool& defaultValue) - { - if (tb->IsShown()) - defaultValue = tb->isActive(); - }; - - auto setDefault = [&] - { - auto& def = globalCfg.gui.viewFilterDefault; - setButtonDefault(m_bpButtonShowLeftOnly, def.leftOnly); - setButtonDefault(m_bpButtonShowRightOnly, def.rightOnly); - setButtonDefault(m_bpButtonShowLeftNewer, def.leftNewer); - setButtonDefault(m_bpButtonShowRightNewer, def.rightNewer); - setButtonDefault(m_bpButtonShowEqual, def.equal); - setButtonDefault(m_bpButtonShowDifferent, def.different); - setButtonDefault(m_bpButtonShowConflict, def.conflict); - - setButtonDefault(m_bpButtonShowCreateLeft, def.createLeft); - setButtonDefault(m_bpButtonShowCreateRight, def.createRight); - setButtonDefault(m_bpButtonShowUpdateLeft, def.updateLeft); - setButtonDefault(m_bpButtonShowUpdateRight, def.updateRight); - setButtonDefault(m_bpButtonShowDeleteLeft, def.deleteLeft); - setButtonDefault(m_bpButtonShowDeleteRight, def.deleteRight); - setButtonDefault(m_bpButtonShowDoNothing, def.doNothing); - }; - - ContextMenu menu; - menu.addItem( _("Set as default"), setDefault); - menu.popup(*this); -} - - -void MainDialog::updateGlobalFilterButton() -{ - //global filter: test for Null-filter - if (!isNullFilter(currentCfg.mainCfg.globalFilter)) - { - setImage(*m_bpButtonFilter, getResourceImage(L"filter")); - m_bpButtonFilter->SetToolTip(_("Filter") + L" (F10) (" + _("Active") + L")"); - } - else - { - setImage(*m_bpButtonFilter, greyScale(getResourceImage(L"filter"))); - m_bpButtonFilter->SetToolTip(_("Filter") + L" (F10) (" + _("None") + L")"); - } -} - - -void MainDialog::OnCompare(wxCommandEvent& event) -{ - //PERF_START; - - //wxBusyCursor dummy; -> redundant: progress already shown in progress dialog! - - wxWindow* oldFocus = wxWindow::FindFocus(); - ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus();); //e.g. keep focus on main grid after pressing F5 - - int scrollPosX = 0; - int scrollPosY = 0; - m_gridMainL->GetViewStart(&scrollPosX, &scrollPosY); //preserve current scroll position - ZEN_ON_SCOPE_EXIT( - m_gridMainL->Scroll(scrollPosX, scrollPosY); // - m_gridMainR->Scroll(scrollPosX, scrollPosY); //restore - m_gridMainC->Scroll(-1, scrollPosY); ) // - - clearGrid(); //avoid memory peak by clearing old data first - - disableAllElements(true); //CompareStatusHandler will internally process Window messages, so avoid unexpected callbacks! - auto app = wxTheApp; //fix lambda/wxWigets/VC fuck up - ZEN_ON_SCOPE_EXIT(app->Yield(); enableAllElements()); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks - - try - { - //class handling status display and error messages - CompareStatusHandler statusHandler(*this); - - const std::vector<zen::FolderPairCfg> cmpConfig = zen::extractCompareCfg(getConfig().mainCfg); - - //GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization - std::unique_ptr<LockHolder> dirLocks; - - //COMPARE DIRECTORIES - compare(globalCfg.fileTimeTolerance, - globalCfg.optDialogs, - true, //allow pw prompt - globalCfg.runWithBackgroundPriority, - globalCfg.createLockFile, - dirLocks, - cmpConfig, - folderCmp, - statusHandler); //throw GuiAbortProcess - } - catch (GuiAbortProcess&) - { - // if (m_buttonCompare->IsShownOnScreen()) m_buttonCompare->SetFocus(); - updateGui(); //refresh grid in ANY case! (also on abort) - return; - } - - gridDataView->setData(folderCmp); //update view on data - treeDataView->setData(folderCmp); // - updateGui(); - - // if (m_buttonSync->IsShownOnScreen()) m_buttonSync->SetFocus(); - - gridview::clearSelection(*m_gridMainL, *m_gridMainC, *m_gridMainR); - m_gridNavi->clearSelection(); - - //play (optional) sound notification after sync has completed (GUI and batch mode) - //const Zstring soundFile = zen::getResourceDir() + Zstr("Compare_Complete.wav"); - //if (fileExists(soundFile)) - // wxSound::Play(toWx(soundFile), wxSOUND_ASYNC); - - //add to folder history after successful comparison only - folderHistoryLeft ->addItem(toZ(m_directoryLeft ->GetValue())); - folderHistoryRight->addItem(toZ(m_directoryRight->GetValue())); - - //prepare status information - if (allElementsEqual(folderCmp)) - flashStatusInformation(_("All folders are in sync")); -} - - -void MainDialog::updateTopButtonImages() -{ - auto updateButton = [&](wxBitmapButton& btn, const wxBitmap& bmp, const wxString& variantName, bool makeGrey) - { - wxImage labelImage = createImageFromText(btn.GetLabel(), btn.GetFont(), wxSystemSettings::GetColour(makeGrey ? wxSYS_COLOUR_GRAYTEXT : wxSYS_COLOUR_BTNTEXT)); - wxImage variantImage = createImageFromText(variantName, wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxBOLD), wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); - - wxImage descrImage = stackImages(labelImage, variantImage, ImageStackLayout::VERTICAL, ImageStackAlignment::CENTER); - const wxImage& iconImage = makeGrey ? greyScale(bmp.ConvertToImage()) : bmp.ConvertToImage(); - - wxImage dynImage = btn.GetLayoutDirection() != wxLayout_RightToLeft ? - stackImages(iconImage, descrImage, ImageStackLayout::HORIZONTAL, ImageStackAlignment::CENTER, 5) : - stackImages(descrImage, iconImage, ImageStackLayout::HORIZONTAL, ImageStackAlignment::CENTER, 5); - - //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work corretly - wxSize minSize = dynImage.GetSize() + wxSize(10, 10); //add border space - minSize.x = std::max(minSize.x, 180); - btn.SetMinSize(minSize); - - btn.SetBitmapLabel(wxBitmap(dynImage)); - //SetLabel() calls confuse wxBitmapButton in the disabled state and it won't show the image! workaround: - btn.SetBitmapDisabled(wxBitmap(dynImage.ConvertToDisabled())); - }; - - updateButton(*m_buttonCompare, getResourceImage(L"compare"), getConfig().mainCfg.getCompVariantName(), false); - updateButton(*m_buttonSync, getResourceImage(L"sync"), getConfig().mainCfg.getSyncVariantName(), folderCmp.empty()); - - m_panelTopButtons->Layout(); -} - - -void MainDialog::updateGui() -{ - updateGridViewData(); //update gridDataView and write status information - - updateStatistics(); - - updateUnsavedCfgStatus(); - - updateTopButtonImages(); - - auiMgr.Update(); //fix small display distortion, if view filter panel is empty -} - - -void MainDialog::clearGrid() -{ - folderCmp.clear(); - gridDataView->setData(folderCmp); - treeDataView->setData(folderCmp); - - updateGui(); -} - - -void MainDialog::updateStatistics() -{ - //update preview of item count and bytes to be transferred: - const SyncStatistics st(folderCmp); - - setText(*m_staticTextData, filesizeToShortString(st.getDataToProcess())); - if (st.getDataToProcess() == 0) - m_bitmapData->SetBitmap(greyScale(getResourceImage(L"data"))); - else - m_bitmapData->SetBitmap(getResourceImage(L"data")); - - auto setValue = [](wxStaticText& txtControl, int value, wxStaticBitmap& bmpControl, const wchar_t* bmpName) - { - setText(txtControl, toGuiString(value)); - - if (value == 0) - bmpControl.SetBitmap(greyScale(mirrorIfRtl(getResourceImage(bmpName)))); - else - bmpControl.SetBitmap(mirrorIfRtl(getResourceImage(bmpName))); - }; - - setValue(*m_staticTextCreateLeft, st.getCreate<LEFT_SIDE >(), *m_bitmapCreateLeft, L"so_create_left_small"); - setValue(*m_staticTextUpdateLeft, st.getUpdate<LEFT_SIDE >(), *m_bitmapUpdateLeft, L"so_update_left_small"); - setValue(*m_staticTextDeleteLeft, st.getDelete<LEFT_SIDE >(), *m_bitmapDeleteLeft, L"so_delete_left_small"); - setValue(*m_staticTextCreateRight, st.getCreate<RIGHT_SIDE>(), *m_bitmapCreateRight, L"so_create_right_small"); - setValue(*m_staticTextUpdateRight, st.getUpdate<RIGHT_SIDE>(), *m_bitmapUpdateRight, L"so_update_right_small"); - setValue(*m_staticTextDeleteRight, st.getDelete<RIGHT_SIDE>(), *m_bitmapDeleteRight, L"so_delete_right_small"); - - m_panelStatistics->Layout(); - m_panelStatistics->Refresh(); //fix small mess up on RTL layout -} - - -void MainDialog::OnSyncSettings(wxCommandEvent& event) -{ - ExecWhenFinishedCfg ewfCfg = { ¤tCfg.mainCfg.onCompletion, - &globalCfg.gui.onCompletionHistory, - globalCfg.gui.onCompletionHistoryMax - }; - - if (showSyncConfigDlg(this, - currentCfg.mainCfg.cmpConfig.compareVar, - currentCfg.mainCfg.syncCfg, - _("Synchronization Settings"), - ¤tCfg.handleError, - &ewfCfg) == ReturnSyncConfig::BUTTON_OKAY) //optional input parameter - { - applySyncConfig(); - } -} - - -void MainDialog::applyCompareConfig(bool switchMiddleGrid) -{ - clearGrid(); //+ GUI update - - //convenience: change sync view - if (switchMiddleGrid) - switch (currentCfg.mainCfg.cmpConfig.compareVar) - { - case CMP_BY_TIME_SIZE: - setViewTypeSyncAction(true); - break; - case CMP_BY_CONTENT: - setViewTypeSyncAction(false); - break; - } -} - - -void MainDialog::OnCmpSettings(wxCommandEvent& event) -{ - //show window right next to the compare-config button - //wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); - //windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; - - CompConfig cmpConfigNew = currentCfg.mainCfg.cmpConfig; - - if (zen::showCompareCfgDialog(this, cmpConfigNew, _("Comparison Settings")) == ReturnSmallDlg::BUTTON_OKAY && - //check if settings were changed at all - cmpConfigNew != currentCfg.mainCfg.cmpConfig) - { - currentCfg.mainCfg.cmpConfig = cmpConfigNew; - - applyCompareConfig(true); //true: switchMiddleGrid - } -} - - -void MainDialog::OnStartSync(wxCommandEvent& event) -{ - if (folderCmp.empty()) - { - //quick sync: simulate button click on "compare" - wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); - if (wxEvtHandler* evtHandler = m_buttonCompare->GetEventHandler()) - evtHandler->ProcessEvent(dummy2); //synchronous call - - if (folderCmp.empty()) //check if user aborted or error occurred, ect... - return; - } - - //show sync preview/confirmation dialog - if (globalCfg.optDialogs.confirmSyncStart) - { - bool dontShowAgain = false; - - if (zen::showSyncConfirmationDlg(this, - getConfig().mainCfg.getSyncVariantName(), - zen::SyncStatistics(folderCmp), - dontShowAgain) != ReturnSmallDlg::BUTTON_OKAY) - return; - - globalCfg.optDialogs.confirmSyncStart = !dontShowAgain; - } - - try - { - //PERF_START; - const Zstring activeCfgFilename = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstring(); - - const auto& guiCfg = getConfig(); - - disableAllElements(false); //SyncStatusHandler will internally process Window messages, so avoid unexpected callbacks! - ZEN_ON_SCOPE_EXIT(enableAllElements()); - - //class handling status updates and error messages - SyncStatusHandler statusHandler(this, //throw GuiAbortProcess - globalCfg.lastSyncsLogFileSizeMax, - currentCfg.handleError, - globalCfg.automaticRetryCount, - globalCfg.automaticRetryDelay, - xmlAccess::extractJobName(activeCfgFilename), - guiCfg.mainCfg.onCompletion, - globalCfg.gui.onCompletionHistory); - - //wxBusyCursor dummy; -> redundant: progress already shown in progress dialog! - - //GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization - std::unique_ptr<LockHolder> dirLocks; - if (globalCfg.createLockFile) - { - std::set<Zstring, LessFilename> dirnamesExisting; - for (auto it = begin(folderCmp); it != end(folderCmp); ++it) - { - if (it->isExisting<LEFT_SIDE>()) //do NOT check directory existence again! - dirnamesExisting.insert(it->getBaseDirPf<LEFT_SIDE >()); - if (it->isExisting<RIGHT_SIDE>()) - dirnamesExisting.insert(it->getBaseDirPf<RIGHT_SIDE>()); - } - dirLocks = make_unique<LockHolder>(dirnamesExisting, globalCfg.optDialogs.warningDirectoryLockFailed, statusHandler); - } - - //START SYNCHRONIZATION - const std::vector<zen::FolderPairSyncCfg> syncProcessCfg = zen::extractSyncCfg(guiCfg.mainCfg); - if (syncProcessCfg.size() != folderCmp.size()) - throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__)); - //should never happen: sync button is deactivated if they are not in sync - - synchronize(localTime(), - globalCfg.optDialogs, - globalCfg.verifyFileCopy, - globalCfg.copyLockedFiles, - globalCfg.copyFilePermissions, - globalCfg.failsafeFileCopy, - globalCfg.runWithBackgroundPriority, - syncProcessCfg, - folderCmp, - statusHandler); - } - catch (GuiAbortProcess&) - { - //do NOT disable the sync button: user might want to try to sync the REMAINING rows - } //enableSynchronization(false); - - //remove empty rows: just a beautification, invalid rows shouldn't cause issues - gridDataView->removeInvalidRows(); - - updateGui(); -} - - -void MainDialog::onGridDoubleClickL(GridClickEvent& event) -{ - onGridDoubleClickRim(event.row_, true); -} -void MainDialog::onGridDoubleClickR(GridClickEvent& event) -{ - onGridDoubleClickRim(event.row_, false); -} - -void MainDialog::onGridDoubleClickRim(size_t row, bool leftSide) -{ - if (!globalCfg.gui.externelApplications.empty()) - { - std::vector<FileSystemObject*> selection; - if (FileSystemObject* fsObj = gridDataView->getObject(row)) //selection must be a list of BOUND pointers! - selection.push_back(fsObj); - - openExternalApplication(globalCfg.gui.externelApplications[0].second, selection, leftSide); - } -} - - -void MainDialog::onGridLabelLeftClick(bool onLeft, ColumnTypeRim type) -{ - auto sortInfo = gridDataView->getSortInfo(); - - bool sortAscending = GridView::getDefaultSortDirection(type); - if (sortInfo && sortInfo->onLeft_ == onLeft && sortInfo->type_ == type) - sortAscending = !sortInfo->ascending_; - - gridDataView->sortView(type, onLeft, sortAscending); - - gridview::clearSelection(*m_gridMainL, *m_gridMainC, *m_gridMainR); - updateGui(); //refresh gridDataView -} - -void MainDialog::onGridLabelLeftClickL(GridClickEvent& event) -{ - onGridLabelLeftClick(true, static_cast<ColumnTypeRim>(event.colType_)); -} -void MainDialog::onGridLabelLeftClickR(GridClickEvent& event) -{ - onGridLabelLeftClick(false, static_cast<ColumnTypeRim>(event.colType_)); -} - - -void MainDialog::onGridLabelLeftClickC(GridClickEvent& event) -{ - //sorting middle grid is more or less useless: therefore let's toggle view instead! - setViewTypeSyncAction(!m_bpButtonViewTypeSyncAction->isActive()); //toggle view -} - - -void MainDialog::OnSwapSides(wxCommandEvent& event) -{ - //swap directory names: first pair - firstFolderPair->setValues(firstFolderPair->getRightDir(), // swap directories - firstFolderPair->getLeftDir(), // - firstFolderPair->getAltCompConfig(), - firstFolderPair->getAltSyncConfig(), - firstFolderPair->getAltFilterConfig()); - - //additional pairs - for (auto it = additionalFolderPairs.begin(); it != additionalFolderPairs.end(); ++it) - { - FolderPairPanel* panel = *it; - panel->setValues(panel->getRightDir(), // swap directories - panel->getLeftDir(), // - panel->getAltCompConfig(), - panel->getAltSyncConfig(), - panel->getAltFilterConfig()); - } - - //swap view filter - bool tmp = m_bpButtonShowLeftOnly->isActive(); - m_bpButtonShowLeftOnly->setActive(m_bpButtonShowRightOnly->isActive()); - m_bpButtonShowRightOnly->setActive(tmp); - - tmp = m_bpButtonShowLeftNewer->isActive(); - m_bpButtonShowLeftNewer->setActive(m_bpButtonShowRightNewer->isActive()); - m_bpButtonShowRightNewer->setActive(tmp); - - /* for sync preview and "mirror" variant swapping may create strange effect: - tmp = m_bpButtonShowCreateLeft->isActive(); - m_bpButtonShowCreateLeft->setActive(m_bpButtonShowCreateRight->isActive()); - m_bpButtonShowCreateRight->setActive(tmp); - - tmp = m_bpButtonShowDeleteLeft->isActive(); - m_bpButtonShowDeleteLeft->setActive(m_bpButtonShowDeleteRight->isActive()); - m_bpButtonShowDeleteRight->setActive(tmp); - - tmp = m_bpButtonShowUpdateLeft->isActive(); - m_bpButtonShowUpdateLeft->setActive(m_bpButtonShowUpdateRight->isActive()); - m_bpButtonShowUpdateRight->setActive(tmp); - */ - - //swap grid information - zen::swapGrids(getConfig().mainCfg, folderCmp); - - updateGui(); -} - - -void MainDialog::updateGridViewData() -{ - size_t filesOnLeftView = 0; - size_t foldersOnLeftView = 0; - size_t filesOnRightView = 0; - size_t foldersOnRightView = 0; - zen::UInt64 filesizeLeftView; - zen::UInt64 filesizeRightView; - - //disable all buttons per default - m_bpButtonShowLeftOnly ->Show(false); - m_bpButtonShowRightOnly ->Show(false); - m_bpButtonShowLeftNewer ->Show(false); - m_bpButtonShowRightNewer->Show(false); - m_bpButtonShowDifferent ->Show(false); - m_bpButtonShowEqual ->Show(false); - m_bpButtonShowConflict ->Show(false); - - m_bpButtonShowCreateLeft ->Show(false); - m_bpButtonShowCreateRight->Show(false); - m_bpButtonShowDeleteLeft ->Show(false); - m_bpButtonShowDeleteRight->Show(false); - m_bpButtonShowUpdateLeft ->Show(false); - m_bpButtonShowUpdateRight->Show(false); - m_bpButtonShowDoNothing ->Show(false); - - if (m_bpButtonViewTypeSyncAction->isActive()) - { - const GridView::StatusSyncPreview result = gridDataView->updateSyncPreview(currentCfg.hideExcludedItems, - m_bpButtonShowCreateLeft ->isActive(), - m_bpButtonShowCreateRight->isActive(), - m_bpButtonShowDeleteLeft ->isActive(), - m_bpButtonShowDeleteRight->isActive(), - m_bpButtonShowUpdateLeft ->isActive(), - m_bpButtonShowUpdateRight->isActive(), - m_bpButtonShowDoNothing ->isActive(), - m_bpButtonShowEqual ->isActive(), - m_bpButtonShowConflict ->isActive()); - filesOnLeftView = result.filesOnLeftView; - foldersOnLeftView = result.foldersOnLeftView; - filesOnRightView = result.filesOnRightView; - foldersOnRightView = result.foldersOnRightView; - filesizeLeftView = result.filesizeLeftView; - filesizeRightView = result.filesizeRightView; - - - //sync preview buttons - m_bpButtonShowCreateLeft ->Show(result.existsSyncCreateLeft); - m_bpButtonShowCreateRight ->Show(result.existsSyncCreateRight); - m_bpButtonShowDeleteLeft ->Show(result.existsSyncDeleteLeft); - m_bpButtonShowDeleteRight ->Show(result.existsSyncDeleteRight); - m_bpButtonShowUpdateLeft ->Show(result.existsSyncDirLeft); - m_bpButtonShowUpdateRight ->Show(result.existsSyncDirRight); - m_bpButtonShowDoNothing ->Show(result.existsSyncDirNone); - m_bpButtonShowEqual ->Show(result.existsSyncEqual); - m_bpButtonShowConflict ->Show(result.existsConflict); - - const bool anyViewFilterButtonShown = m_bpButtonShowCreateLeft ->IsShown() || - m_bpButtonShowCreateRight->IsShown() || - m_bpButtonShowDeleteLeft ->IsShown() || - m_bpButtonShowDeleteRight->IsShown() || - m_bpButtonShowUpdateLeft ->IsShown() || - m_bpButtonShowUpdateRight->IsShown() || - m_bpButtonShowDoNothing ->IsShown() || - m_bpButtonShowEqual ->IsShown() || - m_bpButtonShowConflict ->IsShown(); - m_bpButtonViewTypeSyncAction->Show(anyViewFilterButtonShown); - - if (anyViewFilterButtonShown) - { - m_panelViewFilter->Show(); - m_panelViewFilter->Layout(); - } - else - m_panelViewFilter->Hide(); - } - else - { - const GridView::StatusCmpResult result = gridDataView->updateCmpResult(currentCfg.hideExcludedItems, - m_bpButtonShowLeftOnly ->isActive(), - m_bpButtonShowRightOnly ->isActive(), - m_bpButtonShowLeftNewer ->isActive(), - m_bpButtonShowRightNewer->isActive(), - m_bpButtonShowDifferent ->isActive(), - m_bpButtonShowEqual ->isActive(), - m_bpButtonShowConflict ->isActive()); - filesOnLeftView = result.filesOnLeftView; - foldersOnLeftView = result.foldersOnLeftView; - filesOnRightView = result.filesOnRightView; - foldersOnRightView = result.foldersOnRightView; - filesizeLeftView = result.filesizeLeftView; - filesizeRightView = result.filesizeRightView; - - //comparison result view buttons - m_bpButtonShowLeftOnly ->Show(result.existsLeftOnly); - m_bpButtonShowRightOnly ->Show(result.existsRightOnly); - m_bpButtonShowLeftNewer ->Show(result.existsLeftNewer); - m_bpButtonShowRightNewer->Show(result.existsRightNewer); - m_bpButtonShowDifferent ->Show(result.existsDifferent); - m_bpButtonShowEqual ->Show(result.existsEqual); - m_bpButtonShowConflict ->Show(result.existsConflict); - - const bool anyViewFilterButtonShown = m_bpButtonShowLeftOnly ->IsShown() || - m_bpButtonShowRightOnly ->IsShown() || - m_bpButtonShowLeftNewer ->IsShown() || - m_bpButtonShowRightNewer->IsShown() || - m_bpButtonShowDifferent ->IsShown() || - m_bpButtonShowEqual ->IsShown() || - m_bpButtonShowConflict ->IsShown(); - m_bpButtonViewTypeSyncAction->Show(anyViewFilterButtonShown); - - if (anyViewFilterButtonShown) - { - m_panelViewFilter->Show(); - m_panelViewFilter->Layout(); - } - else - m_panelViewFilter->Hide(); - } - //all three grids retrieve their data directly via gridDataView - gridview::refresh(*m_gridMainL, *m_gridMainC, *m_gridMainR); - - //navigation tree - if (m_bpButtonViewTypeSyncAction->isActive()) - treeDataView->updateSyncPreview(currentCfg.hideExcludedItems, - m_bpButtonShowCreateLeft ->isActive(), - m_bpButtonShowCreateRight->isActive(), - m_bpButtonShowDeleteLeft ->isActive(), - m_bpButtonShowDeleteRight->isActive(), - m_bpButtonShowUpdateLeft ->isActive(), - m_bpButtonShowUpdateRight->isActive(), - m_bpButtonShowDoNothing ->isActive(), - m_bpButtonShowEqual ->isActive(), - m_bpButtonShowConflict ->isActive()); - else - treeDataView->updateCmpResult(currentCfg.hideExcludedItems, - m_bpButtonShowLeftOnly ->isActive(), - m_bpButtonShowRightOnly ->isActive(), - m_bpButtonShowLeftNewer ->isActive(), - m_bpButtonShowRightNewer->isActive(), - m_bpButtonShowDifferent ->isActive(), - m_bpButtonShowEqual ->isActive(), - m_bpButtonShowConflict ->isActive()); - m_gridNavi->Refresh(); - - //update status bar information - setStatusBarFileStatistics(filesOnLeftView, - foldersOnLeftView, - filesOnRightView, - foldersOnRightView, - filesizeLeftView, - filesizeRightView); -} - - -void MainDialog::applyFilterConfig() -{ - applyFiltering(folderCmp, getConfig().mainCfg); - updateGui(); - //updateGuiDelayedIf(currentCfg.hideExcludedItems); //show update GUI before removing rows -} - - -void MainDialog::applySyncConfig() -{ - zen::redetermineSyncDirection(getConfig().mainCfg, folderCmp, - [&](const std::wstring& warning) - { - bool& warningActive = globalCfg.optDialogs.warningDatabaseError; - if (warningActive) - { - bool dontWarnAgain = false; - - showNotificationDialog(this, DialogInfoType::WARNING, PopupDialogCfg().setDetailInstructions(warning).setCheckBox(dontWarnAgain, _("&Don't show this warning again"))); - warningActive = !dontWarnAgain; - } - }); - - updateGui(); -} - - -void MainDialog::OnMenuFindItem(wxCommandEvent& event) //CTRL + F -{ - showFindPanel(); -} - - -void MainDialog::OnSearchGridEnter(wxCommandEvent& event) -{ - startFindNext(); -} - - -void MainDialog::OnHideSearchPanel(wxCommandEvent& event) -{ - hideFindPanel(); -} - - -void MainDialog::OnSearchPanelKeyPressed(wxKeyEvent& event) -{ - switch (event.GetKeyCode()) - { - case WXK_RETURN: - case WXK_NUMPAD_ENTER: //catches ENTER keys while focus is on *any* part of m_panelSearch! Seems to obsolete OnHideSearchPanel()! - startFindNext(); - return; - case WXK_ESCAPE: - hideFindPanel(); - return; - } - event.Skip(); -} - - -void MainDialog::showFindPanel() //CTRL + F or F3 with empty search phrase -{ - auiMgr.GetPane(m_panelSearch).Show(); - auiMgr.Update(); - - m_textCtrlSearchTxt->SelectAll(); - - wxWindow* focus = wxWindow::FindFocus(); //restore when closing panel! - if (!isComponentOf(focus, m_panelSearch)) - focusWindowAfterSearch = focus == &m_gridMainR->getMainWin() ? focus : &m_gridMainL->getMainWin(); - //don't save pointer to arbitrary window: it might not exist anymore when hideFindPanel() uses it!!! (e.g. some folder pair panel) - m_textCtrlSearchTxt->SetFocus(); -} - - -void MainDialog::hideFindPanel() -{ - auiMgr.GetPane(m_panelSearch).Hide(); - auiMgr.Update(); - - if (focusWindowAfterSearch) - { - focusWindowAfterSearch->SetFocus(); - focusWindowAfterSearch = nullptr; - } -} - - -void MainDialog::startFindNext() //F3 or ENTER in m_textCtrlSearchTxt -{ - const wxString& searchString = m_textCtrlSearchTxt->GetValue(); - - if (searchString.empty()) - showFindPanel(); - else - { - Grid* grid1 = m_gridMainL; - Grid* grid2 = m_gridMainR; - - wxWindow* focus = wxWindow::FindFocus(); - if ((isComponentOf(focus, m_panelSearch) ? focusWindowAfterSearch : focus) == &m_gridMainR->getMainWin()) - std::swap(grid1, grid2); //select side to start search at grid cursor position - - wxBeginBusyCursor(wxHOURGLASS_CURSOR); - const std::pair<const Grid*, ptrdiff_t> result = findGridMatch(*grid1, *grid2, searchString, - m_checkBoxMatchCase->GetValue()); //parameter owned by GUI, *not* globalCfg structure! => we should better implement a getGlocalCfg()! - wxEndBusyCursor(); - - if (Grid* grid = const_cast<Grid*>(result.first)) //grid wasn't const when passing to findAndSelectNext(), so this is safe - { - assert(result.second >= 0); - - gridview::setScrollMaster(*grid); - grid->setGridCursor(result.second); - - focusWindowAfterSearch = &grid->getMainWin(); - - if (!isComponentOf(wxWindow::FindFocus(), m_panelSearch)) - grid->getMainWin().SetFocus(); - } - else - { - showFindPanel(); - showNotificationDialog(this, DialogInfoType::INFO, PopupDialogCfg(). - setTitle(_("Find")). - setMainInstructions(replaceCpy(_("Cannot find %x"), L"%x", L"\"" + searchString + L"\"", false))); - } - } -} - - -void MainDialog::OnAddFolderPair(wxCommandEvent& event) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - std::vector<FolderPairEnh> newPairs; - newPairs.push_back(getConfig().mainCfg.firstPair); - - //clear first pair - const FolderPairEnh cfgEmpty; - firstFolderPair->setValues(cfgEmpty.leftDirectory, - cfgEmpty.rightDirectory, - cfgEmpty.altCmpConfig, - cfgEmpty.altSyncConfig, - cfgEmpty.localFilter); - - //keep sequence to update GUI as last step - addAddFolderPair(newPairs, true); //add pair in front of additonal pairs -} - - -void MainDialog::OnRemoveTopFolderPair(wxCommandEvent& event) -{ - if (!additionalFolderPairs.empty()) - { -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - //get settings from second folder pair - const FolderPairEnh cfgSecond = getEnhancedPair(additionalFolderPairs[0]); - - //reset first pair - firstFolderPair->setValues(cfgSecond.leftDirectory, - cfgSecond.rightDirectory, - cfgSecond.altCmpConfig, - cfgSecond.altSyncConfig, - cfgSecond.localFilter); - - removeAddFolderPair(0); //remove second folder pair (first of additional folder pairs) - } -} - - -void MainDialog::OnRemoveFolderPair(wxCommandEvent& event) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - const wxObject* const eventObj = event.GetEventObject(); //find folder pair originating the event - for (auto it = additionalFolderPairs.begin(); it != additionalFolderPairs.end(); ++it) - if (eventObj == (*it)->m_bpButtonRemovePair) - { - removeAddFolderPair(it - additionalFolderPairs.begin()); - break; - } -} - - -void MainDialog::updateGuiForFolderPair() -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - //adapt delete top folder pair button - m_bpButtonRemovePair->Show(!additionalFolderPairs.empty()); - m_panelTopLeft->Layout(); - - //adapt local filter and sync cfg for first folder pair - const bool showLocalCfgFirstPair = !additionalFolderPairs.empty() || - firstFolderPair->getAltCompConfig().get() != nullptr || - firstFolderPair->getAltSyncConfig().get() != nullptr || - !isNullFilter(firstFolderPair->getAltFilterConfig()); - - m_bpButtonAltCompCfg ->Show(showLocalCfgFirstPair); - m_bpButtonAltSyncCfg ->Show(showLocalCfgFirstPair); - m_bpButtonLocalFilter->Show(showLocalCfgFirstPair); - setImage(*m_bpButtonSwapSides, getResourceImage(showLocalCfgFirstPair ? L"swap_slim" : L"swap")); - - //update sub-panel sizes for calculations below!!! - m_panelTopMiddle->GetSizer()->SetSizeHints(m_panelTopMiddle); //~=Fit() + SetMinSize() - - int addPairMinimalHeight = 0; - int addPairOptimalHeight = 0; - if (!additionalFolderPairs.empty()) - { - const int pairHeight = additionalFolderPairs[0]->GetSize().GetHeight(); - addPairMinimalHeight = std::min<double>(1.5, additionalFolderPairs.size()) * pairHeight; //have 1.5 * height indicate that more folders are there - addPairOptimalHeight = std::min<double>(globalCfg.gui.maxFolderPairsVisible - 1 + 0.5, //subtract first/main folder pair and add 0.5 to indicate additional folders - additionalFolderPairs.size()) * pairHeight; - - addPairOptimalHeight = std::max(addPairOptimalHeight, addPairMinimalHeight); //implicitly handle corrupted values for "maxFolderPairsVisible" - } - - const int firstPairHeight = std::max(m_panelDirectoryPairs->ClientToWindowSize(m_panelTopLeft ->GetSize()).GetHeight(), //include m_panelDirectoryPairs window borders! - m_panelDirectoryPairs->ClientToWindowSize(m_panelTopMiddle->GetSize()).GetHeight()); // - - //######################################################################################################################## - //wxAUI hack: set minimum height to desired value, then call wxAuiPaneInfo::Fixed() to apply it - auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, firstPairHeight + addPairOptimalHeight); - auiMgr.GetPane(m_panelDirectoryPairs).Fixed(); - auiMgr.Update(); - - //now make resizable again - auiMgr.GetPane(m_panelDirectoryPairs).Resizable(); - auiMgr.Update(); - //######################################################################################################################## - - //make sure user cannot fully shrink additional folder pairs - auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, firstPairHeight + addPairMinimalHeight); - auiMgr.Update(); - - //it seems there is no GetSizer()->SetSizeHints(this)/Fit() required due to wxAui "magic" - //=> *massive* perf improvement on OS X! -} - - -void MainDialog::addAddFolderPair(const std::vector<FolderPairEnh>& newPairs, bool addFront) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //leads to GUI corruption problems on Linux/OS X! -#endif - - std::vector<FolderPairPanel*> newEntries; - - std::for_each(newPairs.begin(), newPairs.end(), - [&](const FolderPairEnh& enhPair) - { - //add new folder pair - FolderPairPanel* newPair = new FolderPairPanel(m_scrolledWindowFolderPairs, *this); - - //init dropdown history - newPair->m_directoryLeft ->init(folderHistoryLeft); - newPair->m_directoryRight->init(folderHistoryRight); - - //set width of left folder panel - const int width = m_panelTopLeft->GetSize().GetWidth(); - newPair->m_panelLeft->SetMinSize(wxSize(width, -1)); - - if (addFront) - { - bSizerAddFolderPairs->Insert(0, newPair, 0, wxEXPAND); - additionalFolderPairs.insert(additionalFolderPairs.begin(), newPair); - } - else - { - bSizerAddFolderPairs->Add(newPair, 0, wxEXPAND); - additionalFolderPairs.push_back(newPair); - } - newEntries.push_back(newPair); - - //register events - newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), nullptr, this); - }); - - updateGuiForFolderPair(); - - //wxComboBox screws up miserably if width/height is smaller than the magic number 4! Problem occurs when trying to set tooltip - //so we have to update window sizes before setting configuration: - for (auto it = newPairs.begin(); it != newPairs.end(); ++it)//set alternate configuration - newEntries[it - newPairs.begin()]->setValues(it->leftDirectory, - it->rightDirectory, - it->altCmpConfig, - it->altSyncConfig, - it->localFilter); - clearGrid(); //+ GUI update -} - - -void MainDialog::removeAddFolderPair(size_t pos) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //leads to GUI corruption problems on Linux/OS X! -#endif - - if (pos < additionalFolderPairs.size()) - { - FolderPairPanel* panel = additionalFolderPairs[pos]; - - bSizerAddFolderPairs->Detach(panel); //Remove() does not work on Window*, so do it manually - additionalFolderPairs.erase(additionalFolderPairs.begin() + pos); - //more (non-portable) wxWidgets bullshit: on OS X wxWindow::Destroy() screws up and calls "operator delete" directly rather than - //the deferred deletion it is expected to do (and which is implemented correctly on Windows and Linux) - //http://bb10.com/python-wxpython-devel/2012-09/msg00004.html - //=> since we're in a mouse button callback of a sub-component of "panel" we need to delay deletion ourselves: - processAsync2([] {}, [panel] { panel->Destroy(); }); - } - - updateGuiForFolderPair(); - - clearGrid(); //+ GUI update -} - - -void MainDialog::setAddFolderPairs(const std::vector<zen::FolderPairEnh>& newPairs) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //leads to GUI corruption problems on Linux/OS X! -#endif - - additionalFolderPairs.clear(); - bSizerAddFolderPairs->Clear(true); - - //updateGuiForFolderPair(); -> already called in addAddFolderPair() - - addAddFolderPair(newPairs); -} - - -//######################################################################################################## - - -//menu events -void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event) -{ - zen::showGlobalSettingsDlg(this, globalCfg); -} - - -void MainDialog::OnMenuExportFileList(wxCommandEvent& event) -{ - //get a filename - wxFileDialog filePicker(this, //creating this on freestore leads to memleak! - wxEmptyString, - wxEmptyString, - L"FileList.csv", //default file name - _("Comma-separated values") + L" (*.csv)|*.csv" + L"|" +_("All files") + L" (*.*)|*", - wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - if (filePicker.ShowModal() != wxID_OK) - return; - - wxBusyCursor dummy; - - const Zstring filename = utfCvrtTo<Zstring>(filePicker.GetPath()); - - //http://en.wikipedia.org/wiki/Comma-separated_values - const lconv* localInfo = ::localeconv(); //always bound according to doc - const bool haveCommaAsDecimalSep = std::string(localInfo->decimal_point) == ","; - - const char CSV_SEP = haveCommaAsDecimalSep ? ';' : ','; - - auto fmtValue = [&](const wxString& val) -> Utf8String - { - Utf8String&& tmp = utfCvrtTo<Utf8String>(val); - - if (contains(tmp, CSV_SEP)) - return '\"' + tmp + '\"'; - else - return tmp; - }; - - Utf8String header; //perf: wxString doesn't model exponential growth and so is out, std::string doesn't give performance guarantee! - header += BYTE_ORDER_MARK_UTF8; - - //base folders - header += fmtValue(_("Folder Pairs")) + '\n' ; - std::for_each(begin(folderCmp), end(folderCmp), - [&](BaseDirPair& baseDirObj) - { - header += utfCvrtTo<Utf8String>(baseDirObj.getBaseDirPf<LEFT_SIDE >()) + CSV_SEP; - header += utfCvrtTo<Utf8String>(baseDirObj.getBaseDirPf<RIGHT_SIDE>()) + '\n'; - }); - header += '\n'; - - //write header - auto provLeft = m_gridMainL->getDataProvider(); - auto provMiddle = m_gridMainC->getDataProvider(); - auto provRight = m_gridMainR->getDataProvider(); - - auto colAttrLeft = m_gridMainL->getColumnConfig(); - auto colAttrMiddle = m_gridMainC->getColumnConfig(); - auto colAttrRight = m_gridMainR->getColumnConfig(); - - vector_remove_if(colAttrLeft , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; }); - vector_remove_if(colAttrMiddle, [](const Grid::ColumnAttribute& ca) { return !ca.visible_ || static_cast<ColumnTypeMiddle>(ca.type_) == COL_TYPE_CHECKBOX; }); - vector_remove_if(colAttrRight , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; }); - - if (provLeft && provMiddle && provRight) - { - std::for_each(colAttrLeft.begin(), colAttrLeft.end(), - [&](const Grid::ColumnAttribute& ca) - { - header += fmtValue(provLeft->getColumnLabel(ca.type_)); - header += CSV_SEP; - }); - std::for_each(colAttrMiddle.begin(), colAttrMiddle.end(), - [&](const Grid::ColumnAttribute& ca) - { - header += fmtValue(provMiddle->getColumnLabel(ca.type_)); - header += CSV_SEP; - }); - if (!colAttrRight.empty()) - { - std::for_each(colAttrRight.begin(), colAttrRight.end() - 1, - [&](const Grid::ColumnAttribute& ca) - { - header += fmtValue(provRight->getColumnLabel(ca.type_)); - header += CSV_SEP; - }); - header += fmtValue(provRight->getColumnLabel(colAttrRight.back().type_)); - } - header += '\n'; - - try - { - //write file - FileOutput fileOut(filename, zen::FileOutput::ACC_OVERWRITE); //throw FileError - - replace(header, '\n', LINE_BREAK); - fileOut.write(&*header.begin(), header.size()); //throw FileError - - //main grid: write rows one after the other instead of creating one big string: memory allocation might fail; think 1 million rows! - /* - performance test case "export 600.000 rows" to CSV: - aproach 1. assemble single temporary string, then write file: 4.6s - aproach 2. write to buffered file output directly for each row: 6.4s - */ - const size_t rowCount = m_gridMainL->getRowCount(); - for (size_t row = 0; row < rowCount; ++row) - { - Utf8String tmp; - - std::for_each(colAttrLeft.begin(), colAttrLeft.end(), - [&](const Grid::ColumnAttribute& ca) - { - tmp += fmtValue(provLeft->getValue(row, ca.type_)); - tmp += CSV_SEP; - }); - std::for_each(colAttrMiddle.begin(), colAttrMiddle.end(), - [&](const Grid::ColumnAttribute& ca) - { - tmp += fmtValue(provMiddle->getValue(row, ca.type_)); - tmp += CSV_SEP; - }); - std::for_each(colAttrRight.begin(), colAttrRight.end(), - [&](const Grid::ColumnAttribute& ca) - { - tmp += fmtValue(provRight->getValue(row, ca.type_)); - tmp += CSV_SEP; - }); - tmp += '\n'; - - replace(tmp, '\n', LINE_BREAK); - fileOut.write(&*tmp.begin(), tmp.size()); //throw FileError - } - - flashStatusInformation(_("File list exported")); - } - catch (const FileError& e) - { - showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); - } - } -} - - -void MainDialog::OnMenuCheckVersion(wxCommandEvent& event) -{ - zen::checkForUpdateNow(this); -} - - -void MainDialog::OnMenuCheckVersionAutomatically(wxCommandEvent& event) -{ - globalCfg.gui.lastUpdateCheck = globalCfg.gui.lastUpdateCheck == -1 ? 0 : -1; - m_menuItemCheckVersionAuto->Check(globalCfg.gui.lastUpdateCheck != -1); - zen::checkForUpdatePeriodically(this, globalCfg.gui.lastUpdateCheck, [&] { flashStatusInformation(_("Searching for program updates...")); }); -} - - -void MainDialog::OnRegularUpdateCheck(wxIdleEvent& event) -{ - //execute just once per startup! - Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), nullptr, this); - - if (manualProgramUpdateRequired()) - zen::checkForUpdatePeriodically(this, globalCfg.gui.lastUpdateCheck, [&] { flashStatusInformation(_("Searching for program updates...")); }); -} - - -void MainDialog::OnLayoutWindowAsync(wxIdleEvent& event) -{ - //execute just once per startup! - Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnLayoutWindowAsync), nullptr, this); - -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - //adjust folder pair distortion on startup - std::for_each(additionalFolderPairs.begin(), additionalFolderPairs.end(), - [](FolderPairPanel* panel) { panel->Layout(); }); - - m_panelTopButtons->Layout(); - Layout(); //strangely this layout call works if called in next idle event only - auiMgr.Update(); //fix view filter distortion -} - - -void MainDialog::OnMenuAbout(wxCommandEvent& event) -{ - zen::showAboutDialog(this); -} - - -void MainDialog::OnShowHelp(wxCommandEvent& event) -{ - zen::displayHelpEntry(this); -} - -//######################################################################################################### - -//language selection -void MainDialog::switchProgramLanguage(int langID) -{ - //create new dialog with respect to new language - xmlAccess::XmlGlobalSettings newGlobalCfg = getGlobalCfgBeforeExit(); - newGlobalCfg.programLanguage = langID; - - //show new dialog, then delete old one - MainDialog::create(getConfig(), activeConfigFiles, &newGlobalCfg, false); - - //we don't use Close(): - //1. we don't want to show the prompt to save current config in OnClose() - //2. after getGlobalCfgBeforeExit() the old main dialog is invalid so we want to force deletion - Destroy(); -} - - -void MainDialog::OnMenuLanguageSwitch(wxCommandEvent& event) -{ - std::map<MenuItemID, LanguageID>::const_iterator it = languageMenuItemMap.find(event.GetId()); - if (it != languageMenuItemMap.end()) - switchProgramLanguage(it->second); -} - -//######################################################################################################### - -void MainDialog::setViewTypeSyncAction(bool value) -{ - //if (m_bpButtonViewTypeSyncAction->isActive() == value) return; support polling -> what about initialization? - - m_bpButtonViewTypeSyncAction->setActive(value); - m_bpButtonViewTypeSyncAction->SetToolTip((value ? _("Action") : _("Category")) + L" (F9)"); - - //toggle display of sync preview in middle grid - gridview::highlightSyncAction(*m_gridMainC, value); - - updateGui(); -} diff --git a/ui/main_dlg.h b/ui/main_dlg.h deleted file mode 100644 index 110f42b6..00000000 --- a/ui/main_dlg.h +++ /dev/null @@ -1,314 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef MAINDIALOG_H -#define MAINDIALOG_H - -#include <map> -#include <set> -#include <stack> -#include <memory> -#include <zen/int64.h> -#include <zen/async_task.h> -#include <wx+/file_drop.h> -#include <wx/aui/aui.h> -#include "gui_generated.h" -#include "custom_grid.h" -#include "tree_view.h" -#include "folder_history_box.h" -#include "../lib/process_xml.h" - -class FolderPairFirst; -class FolderPairPanel; -class CompareProgressDialog; - - -class MainDialog : public MainDialogGenerated -{ -public: - //default behavior, application start, restores last used config - static void create(); - - //when loading dynamically assembled config, - //when switching language, - //or switching from batch run to GUI on warnings - static void create(const xmlAccess::XmlGuiConfig& guiCfg, - const std::vector<Zstring>& referenceFiles, - const xmlAccess::XmlGlobalSettings* globalSettings, //optional: take over ownership => save on exit - bool startComparison); - - void disableAllElements(bool enableAbort); //dis-/enables all elements (except abort button) that might receive user input - void enableAllElements(); //during long-running processes: comparison, deletion - - void onQueryEndSession(); //last chance to do something useful before killing the application! - -private: - MainDialog(const xmlAccess::XmlGuiConfig& guiCfg, - const std::vector<Zstring>& referenceFiles, - const xmlAccess::XmlGlobalSettings& globalSettings, //take over ownership => save on exit - bool startComparison); - ~MainDialog(); - - friend class CompareStatusHandler; - friend class SyncStatusHandler; - friend class ManualDeletionHandler; - friend class FolderPairFirst; - friend class FolderPairPanel; - friend class DirectoryNameMainImpl; - template <class GuiPanel> - friend class FolderPairCallback; - friend class PanelMoveWindow; - - //configuration load/save - void setLastUsedConfig(const Zstring& filename, const xmlAccess::XmlGuiConfig& guiConfig); - void setLastUsedConfig(const std::vector<Zstring>& filenames, const xmlAccess::XmlGuiConfig& guiConfig); - - xmlAccess::XmlGuiConfig getConfig() const; - void setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg, const std::vector<Zstring>& referenceFiles); - - void setGlobalCfgOnInit(const xmlAccess::XmlGlobalSettings& globalSettings); //messes with Maximize(), window sizes, so call just once! - xmlAccess::XmlGlobalSettings getGlobalCfgBeforeExit(); //destructive "get" thanks to "Iconize(false), Maximize(false)" - - bool loadConfiguration(const std::vector<Zstring>& filenames); //return true if loaded successfully - - bool trySaveConfig (const Zstring* fileNameGui); //return true if saved successfully - bool trySaveBatchConfig(const Zstring* fileNameBatch); // - bool saveOldConfig(); //return false on user abort - - static const Zstring& lastRunConfigName(); - - xmlAccess::XmlGuiConfig lastConfigurationSaved; //support for: "Save changed configuration?" dialog - //used when saving configuration - std::vector<Zstring> activeConfigFiles; //name of currently loaded config file (may be more than 1) - - void updateGlobalFilterButton(); - - void initViewFilterButtons(); - void setViewFilterDefault(); - - void addFileToCfgHistory(const std::vector<Zstring>& filenames); //= update/insert + apply selection - void removeObsoleteCfgHistoryItems(const std::vector<Zstring>& filenames); - void removeCfgHistoryItems(const std::vector<Zstring>& filenames); - - void addAddFolderPair(const std::vector<zen::FolderPairEnh>& newPairs, bool addFront = false); - void removeAddFolderPair(size_t pos); - void setAddFolderPairs(const std::vector<zen::FolderPairEnh>& newPairs); - - void updateGuiForFolderPair(); //helper method: add usability by showing/hiding buttons related to folder pairs - - //main method for putting gridDataView on UI: updates data respecting current view settings - void updateGui(); //kitchen-sink update - void updateGuiDelayedIf(bool condition); // 400 ms delay - - void updateGridViewData(); // - void updateStatistics(); // more fine-grained updaters - void updateUnsavedCfgStatus(); // - void updateTopButtonImages(); // - - //context menu functions - std::vector<zen::FileSystemObject*> getGridSelection(bool fromLeft = true, bool fromRight = true) const; - std::vector<zen::FileSystemObject*> getTreeSelection() const; - - void setSyncDirManually(const std::vector<zen::FileSystemObject*>& selection, zen::SyncDirection direction); - void setFilterManually(const std::vector<zen::FileSystemObject*>& selection, bool setIncluded); - void copySelectionToClipboard(const std::vector<const zen::Grid*>& gridRefs); - void deleteSelectedFiles(const std::vector<zen::FileSystemObject*>& selectionLeft, - const std::vector<zen::FileSystemObject*>& selectionRight); - - void openExternalApplication(const wxString& commandline, const std::vector<zen::FileSystemObject*>& selection, bool leftSide); //selection may be empty - - //don't use wxWidgets idle handling => repeated idle requests/consumption hogs 100% cpu! - void onProcessAsyncTasks(wxEvent& event); - - template <class Fun, class Fun2> - void processAsync(Fun doAsync, Fun2 evalOnGui) { asyncTasks.add(doAsync, evalOnGui); timerForAsyncTasks.Start(50); /*timer interval in [ms] */ } - template <class Fun, class Fun2> - void processAsync2(Fun doAsync, Fun2 evalOnGui) { asyncTasks.add2(doAsync, evalOnGui); timerForAsyncTasks.Start(50); /*timer interval in [ms] */ } - - //status bar supports one of the following two states at a time: - void setStatusBarFullText(const wxString& msg); - void setStatusBarFileStatistics(size_t filesOnLeftView, size_t foldersOnLeftView, size_t filesOnRightView, size_t foldersOnRightView, zen::UInt64 filesizeLeftView, zen::UInt64 filesizeRightView); - - void flashStatusInformation(const wxString& msg); //temporarily show different status (only valid for setStatusBarFullText) - void restoreStatusInformation(); //called automatically after a few seconds - - //events - void onGridButtonEventL(wxKeyEvent& event); - void onGridButtonEventC(wxKeyEvent& event); - void onGridButtonEventR(wxKeyEvent& event); - void onGridButtonEvent (wxKeyEvent& event, zen::Grid& grid, bool leftSide); - - void onTreeButtonEvent (wxKeyEvent& event); - void OnContextSetLayout(wxMouseEvent& event); - void OnGlobalKeyEvent (wxKeyEvent& event); - - virtual void OnCompSettingsContext(wxMouseEvent& event) override; - virtual void OnSyncSettingsContext(wxMouseEvent& event) override; - virtual void OnGlobalFilterContext(wxMouseEvent& event) override; - virtual void OnViewButtonRightClick(wxMouseEvent& event) override; - - void applyCompareConfig(bool switchMiddleGrid = false); - - //context menu handler methods - void onMainGridContextL(zen::GridClickEvent& event); - void onMainGridContextC(zen::GridClickEvent& event); - void onMainGridContextR(zen::GridClickEvent& event); - void onMainGridContextRim(bool leftSide); - - void onNaviGridContext(zen::GridClickEvent& event); - - void onNaviSelection(zen::GridRangeSelectEvent& event); - - void onNaviPanelFilesDropped(zen::FileDropEvent& event); - - void onDirSelected(wxCommandEvent& event); - void onDirManualCorrection(wxCommandEvent& event); - - void onCheckRows (zen::CheckRowsEvent& event); - void onSetSyncDirection(zen::SyncDirectionEvent& event); - - void onGridDoubleClickL(zen::GridClickEvent& event); - void onGridDoubleClickR(zen::GridClickEvent& event); - void onGridDoubleClickRim(size_t row, bool leftSide); - - void onGridLabelLeftClickC(zen::GridClickEvent& event); - void onGridLabelLeftClickL(zen::GridClickEvent& event); - void onGridLabelLeftClickR(zen::GridClickEvent& event); - void onGridLabelLeftClick(bool onLeft, zen::ColumnTypeRim type); - - void onGridLabelContextL(zen::GridClickEvent& event); - void onGridLabelContextC(zen::GridClickEvent& event); - void onGridLabelContextR(zen::GridClickEvent& event); - void onGridLabelContext(zen::Grid& grid, zen::ColumnTypeRim type, const std::vector<zen::ColumnAttributeRim>& defaultColumnAttributes); - - virtual void OnToggleViewType (wxCommandEvent& event) override; - virtual void OnToggleViewButton(wxCommandEvent& event) override; - - virtual void OnConfigNew (wxCommandEvent& event) override; - virtual void OnConfigSave (wxCommandEvent& event) override; - virtual void OnConfigSaveAs (wxCommandEvent& event) override; - virtual void OnSaveAsBatchJob (wxCommandEvent& event) override; - virtual void OnConfigLoad (wxCommandEvent& event) override; - virtual void OnLoadFromHistory(wxCommandEvent& event) override; - virtual void OnLoadFromHistoryDoubleClick(wxCommandEvent& event); - - void deleteSelectedCfgHistoryItems(); - - virtual void OnCfgHistoryRightClick(wxMouseEvent& event) override; - void OnCfgHistoryKeyEvent (wxKeyEvent& event) override; - void OnRegularUpdateCheck (wxIdleEvent& event); - void OnLayoutWindowAsync (wxIdleEvent& event); - - void OnResizeLeftFolderWidth(wxEvent& event); - void OnResizeConfigPanel (wxEvent& event); - void OnResizeViewPanel (wxEvent& event); - void OnResizeStatisticsPanel(wxEvent& event); - virtual void OnShowExcluded (wxCommandEvent& event) override; - virtual void OnConfigureFilter (wxCommandEvent& event) override; - virtual void OnSwapSides (wxCommandEvent& event) override; - virtual void OnCompare (wxCommandEvent& event) override; - virtual void OnSyncSettings (wxCommandEvent& event) override; - virtual void OnCmpSettings (wxCommandEvent& event) override; - virtual void OnStartSync (wxCommandEvent& event) override; - virtual void OnClose (wxCloseEvent& event) override; - - void filterExtension(const Zstring& extension, bool include); - void filterShortname(const zen::FileSystemObject& fsObj, bool include); - void filterItems(const std::vector<zen::FileSystemObject*>& selection, bool include); - void filterPhrase(const Zstring& phrase, bool include, bool addNewLine); - - virtual void OnAddFolderPair (wxCommandEvent& event) override; - void OnRemoveFolderPair (wxCommandEvent& event); - virtual void OnRemoveTopFolderPair(wxCommandEvent& event) override; - - void applyFilterConfig(); - void applySyncConfig(); - - void showFindPanel(); //CTRL + F - void hideFindPanel(); - void startFindNext(); //F3 - - virtual void OnSearchGridEnter(wxCommandEvent& event) override; - virtual void OnHideSearchPanel(wxCommandEvent& event) override; - void OnSearchPanelKeyPressed(wxKeyEvent& event); - - //menu events - virtual void OnMenuGlobalSettings(wxCommandEvent& event) override; - virtual void OnMenuExportFileList(wxCommandEvent& event) override; - virtual void OnMenuFindItem (wxCommandEvent& event) override; - virtual void OnMenuCheckVersion (wxCommandEvent& event) override; - virtual void OnMenuCheckVersionAutomatically(wxCommandEvent& event) override; - virtual void OnMenuAbout (wxCommandEvent& event) override; - virtual void OnShowHelp (wxCommandEvent& event) override; - virtual void OnMenuQuit (wxCommandEvent& event) override { Close(); } - - void OnMenuLanguageSwitch(wxCommandEvent& event); - - void switchProgramLanguage(int langID); - - typedef int MenuItemID; - typedef int LanguageID; - std::map<MenuItemID, LanguageID> languageMenuItemMap; //needed to attach menu item events - - //*********************************************** - //application variables are stored here: - - //global settings shared by GUI and batch mode - xmlAccess::XmlGlobalSettings globalCfg; - - //UI view of FolderComparison structure (partially owns folderCmp) - std::shared_ptr<zen::GridView> gridDataView; //always bound! - std::shared_ptr<zen::TreeView> treeDataView; // - - //the prime data structure of this tool *bling*: - zen::FolderComparison folderCmp; //optional!: sync button not available if empty - - void clearGrid(); - - //------------------------------------- - //program configuration - xmlAccess::XmlGuiConfig currentCfg; - - //folder pairs: - std::unique_ptr<FolderPairFirst> firstFolderPair; //always bound!!! - std::vector<FolderPairPanel*> additionalFolderPairs; //additional pairs to the first pair - //------------------------------------- - - //*********************************************** - //status information - std::list<wxString> oldStatusMsgs; //the first one is the original/non-flash status message - - //compare status panel (hidden on start, shown when comparing) - std::unique_ptr<CompareProgressDialog> compareStatus; //always bound - - bool cleanedUp; - - bool processingGlobalKeyEvent; //indicator to notify recursion in OnGlobalKeyEvent() - - //toggle to display configuration preview instead of comparison result: - //for read access use: m_bpButtonViewTypeSyncAction->isActive() - //when changing value use: - void setViewTypeSyncAction(bool value); - - wxAuiManager auiMgr; //implement dockable GUI design - - wxString defaultPerspective; - - zen::Int64 manualTimeSpanFrom, manualTimeSpanTo; //buffer manual time span selection at session level - - std::shared_ptr<FolderHistory> folderHistoryLeft; //shared by all wxComboBox dropdown controls - std::shared_ptr<FolderHistory> folderHistoryRight; //always bound! - - //schedule and run long-running tasks asynchronously, but process results on GUI queue - zen::AsyncTasks asyncTasks; - wxTimer timerForAsyncTasks; //don't use wxWidgets idle handling => repeated idle requests/consumption hogs 100% cpu! - - std::unique_ptr<zen::FilterConfig> filterCfgOnClipboard; //copy/paste of filter config - - wxWindow* focusWindowAfterSearch; //used to restore focus after search panel is closed -}; - -#endif // MAINDIALOG_H diff --git a/ui/osx_dock.h b/ui/osx_dock.h deleted file mode 100644 index 62237524..00000000 --- a/ui/osx_dock.h +++ /dev/null @@ -1,17 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef OSX_DOCK_837210847312534 -#define OSX_DOCK_837210847312534 - -#include <zen/sys_error.h> - -namespace osx -{ -void dockIconSetText(const char* str); //throw SysError -} - -#endif //OSX_DOCK_837210847312534 diff --git a/ui/osx_dock.mm b/ui/osx_dock.mm deleted file mode 100644 index 8f42ae88..00000000 --- a/ui/osx_dock.mm +++ /dev/null @@ -1,24 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "osx_dock.h" -#include <Cocoa/Cocoa.h> -#include <zen/osx_throw_exception.h> - - -void osx::dockIconSetText(const char* str) //throw SysError -{ - @try - { - NSString* label = [NSString stringWithCString:str encoding:NSUTF8StringEncoding]; - //stringWithCString returns string which is already set to autorelease! - [[NSApp dockTile] setBadgeLabel:label]; //label may be nil - } - @catch (NSException* e) - { - throwSysError(e); //throw SysError - } -} diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp deleted file mode 100644 index efbb62f0..00000000 --- a/ui/progress_indicator.cpp +++ /dev/null @@ -1,2004 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "progress_indicator.h" -#include <memory> -#include <wx/imaglist.h> -#include <wx/stopwatch.h> -#include <wx/wupdlock.h> -#include <wx/sound.h> -#include <wx/clipbrd.h> -#include <wx/dcclient.h> -#include <wx/dataobj.h> //wxTextDataObject -#include <zen/basic_math.h> -#include <zen/format_unit.h> -#include <zen/scope_guard.h> -#include <wx+/grid.h> -#include <wx+/mouse_move_dlg.h> -#include <wx+/toggle_button.h> -#include <wx+/image_tools.h> -#include <wx+/graph.h> -#include <wx+/context_menu.h> -#include <wx+/no_flicker.h> -#include <wx+/font_size.h> -#include <wx+/std_button_order.h> -#include <wx+/popup_dlg.h> -#include <wx+/image_resources.h> -#include <zen/file_handling.h> -#include <zen/thread.h> -#include "gui_generated.h" -#include "../lib/ffs_paths.h" -#include "../lib/perf_check.h" -#include "tray_icon.h" -#include "taskbar.h" -#include "exec_finished_box.h" -#include "app_icon.h" -#ifdef ZEN_MAC -#include <ApplicationServices/ApplicationServices.h> -#endif - -using namespace zen; - - -namespace -{ -const int GAUGE_FULL_RANGE = 50000; - -//window size used for statistics in milliseconds -const int WINDOW_REMAINING_TIME = 60000; //some scenarios have dropouts of 40 seconds -> 60 sec. window size handles them well -const int WINDOW_BYTES_PER_SEC = 5000; // -} - - -class CompareProgressDialog::Pimpl : public CompareProgressDlgGenerated -{ -public: - Pimpl(wxFrame& parentWindow); - - void init(const Statistics& syncStat); //constructor/destructor semantics, but underlying Window is reused - void finalize(); // - - void switchToCompareBytewise(); - void updateStatusPanelNow(); - -private: - wxFrame& parentWindow_; - wxString titleTextBackup; - - wxStopWatch timeElapsed; - long binCompStartMs; //begin of binary comparison phase in [ms] - - const Statistics* syncStat_; //only bound while sync is running - - std::unique_ptr<Taskbar> taskbar_; - std::unique_ptr<PerfCheck> perf; //estimate remaining time - - long lastStatCallSpeed; //used for calculating intervals between showing and collecting perf samples -}; - - -CompareProgressDialog::Pimpl::Pimpl(wxFrame& parentWindow) : - CompareProgressDlgGenerated(&parentWindow), - parentWindow_(parentWindow), - binCompStartMs(0), - syncStat_(nullptr), - lastStatCallSpeed(-1000000) //some big number -{ - //init(); -> needed? -} - - -void CompareProgressDialog::Pimpl::init(const Statistics& syncStat) -{ - syncStat_ = &syncStat; - titleTextBackup = parentWindow_.GetTitle(); - - try //try to get access to Windows 7/Ubuntu taskbar - { - taskbar_ = make_unique<Taskbar>(parentWindow_); - } - catch (const TaskbarNotAvailable&) {} - - //initialize gauge - m_gauge2->SetRange(GAUGE_FULL_RANGE); - m_gauge2->SetValue(0); - - perf.reset(); - timeElapsed.Start(); //measure total time - - //initially hide status that's relevant for comparing bytewise only - bSizerFilesFound ->Show(true); - bSizerFilesRemaining->Show(false); - sSizerSpeed ->Show(false); - sSizerTimeRemaining ->Show(false); - - updateStatusPanelNow(); - - m_gauge2->Hide(); - bSizer42->Layout(); - Layout(); -} - - -void CompareProgressDialog::Pimpl::finalize() -{ - syncStat_ = nullptr; - parentWindow_.SetTitle(titleTextBackup); - taskbar_.reset(); -} - - -void CompareProgressDialog::Pimpl::switchToCompareBytewise() -{ - //start to measure perf - perf = make_unique<PerfCheck>(WINDOW_REMAINING_TIME, WINDOW_BYTES_PER_SEC); - lastStatCallSpeed = -1000000; //some big number - - binCompStartMs = timeElapsed.Time(); - - //show status for comparing bytewise - bSizerFilesFound ->Show(false); - bSizerFilesRemaining->Show(true); - sSizerSpeed ->Show(true); - sSizerTimeRemaining ->Show(true); - - m_gauge2->Show(); - bSizer42->Layout(); - Layout(); -} - - -void CompareProgressDialog::Pimpl::updateStatusPanelNow() -{ - if (!syncStat_) //no comparison running!! - return; - - const wxString& scannedObjects = toGuiString(syncStat_->getObjectsCurrent(ProcessCallback::PHASE_SCANNING)); - - auto setTitle = [&](const wxString& title) - { - if (parentWindow_.GetTitle() != title) - parentWindow_.SetTitle(title); - }; - - bool layoutChanged = false; //avoid screen flicker by calling layout() only if necessary - const long timeNow = timeElapsed.Time(); - - //status texts - setText(*m_textCtrlStatus, replaceCpy(syncStat_->currentStatusText(), L'\n', L' ')); //no layout update for status texts! - - //write status information to taskbar, parent title ect. - switch (syncStat_->currentPhase()) - { - case ProcessCallback::PHASE_NONE: - case ProcessCallback::PHASE_SCANNING: - //dialog caption, taskbar - setTitle(scannedObjects + L" - " + _("Scanning...")); - if (taskbar_.get()) //support Windows 7 taskbar - taskbar_->setStatus(Taskbar::STATUS_INDETERMINATE); - break; - - case ProcessCallback::PHASE_COMPARING_CONTENT: - { - auto objectsCurrent = syncStat_->getObjectsCurrent(ProcessCallback::PHASE_COMPARING_CONTENT); - auto objectsTotal = syncStat_->getObjectsTotal (ProcessCallback::PHASE_COMPARING_CONTENT); - auto dataCurrent = syncStat_->getDataCurrent (ProcessCallback::PHASE_COMPARING_CONTENT); - auto dataTotal = syncStat_->getDataTotal (ProcessCallback::PHASE_COMPARING_CONTENT); - - //add both data + obj-count, to handle "deletion-only" cases - const double fraction = dataTotal + objectsTotal == 0 ? 0 : std::max(0.0, to<double>(dataCurrent + objectsCurrent) / to<double>(dataTotal + objectsTotal)); - - //dialog caption, taskbar - setTitle(fractionToString(fraction) + wxT(" - ") + _("Comparing content...")); - if (taskbar_.get()) - { - taskbar_->setProgress(fraction); - taskbar_->setStatus(Taskbar::STATUS_NORMAL); - } - - //progress indicator, shown for binary comparison only - m_gauge2->SetValue(numeric::round(fraction * GAUGE_FULL_RANGE)); - - //remaining objects and bytes for file comparison - setText(*m_staticTextFilesRemaining, toGuiString(objectsTotal - objectsCurrent), &layoutChanged); - setText(*m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged); - - //remaining time and speed: only visible during binary comparison - assert(perf); - if (perf) - if (numeric::dist(lastStatCallSpeed, timeNow) >= 500) - { - lastStatCallSpeed = timeNow; - - if (numeric::dist(binCompStartMs, timeNow) >= 1000) //discard stats for first second: probably messy - perf->addSample(objectsCurrent, to<double>(dataCurrent), timeNow); - - //current speed -> Win 7 copy uses 1 sec update interval instead - Opt<std::wstring> bps = perf->getBytesPerSecond(); - setText(*m_staticTextSpeed, bps ? *bps : L"-", &layoutChanged); - - //remaining time: display with relative error of 10% - based on samples taken every 0.5 sec only - //-> call more often than once per second to correctly show last few seconds countdown, but don't call too often to avoid occasional jitter - Opt<std::wstring> rt = perf->getRemainingTime(to<double>(dataTotal - dataCurrent)); - setText(*m_staticTextRemTime, rt ? *rt : L"-", &layoutChanged); - } - } - break; - - case ProcessCallback::PHASE_SYNCHRONIZING: - assert(false); - break; - } - - //nr of scanned objects - setText(*m_staticTextScanned, scannedObjects, &layoutChanged); - - //time elapsed - const long timeElapSec = timeNow / 1000; - setText(*m_staticTextTimeElapsed, - timeElapSec < 3600 ? - wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") : - wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged); - - if (layoutChanged) - bSizer42->Layout(); - - //do the ui update - wxTheApp->Yield(); -} - -//######################################################################################## - -//redirect to implementation -CompareProgressDialog::CompareProgressDialog(wxFrame& parentWindow) : - pimpl(new Pimpl(parentWindow)) {} //owned by parentWindow - -wxWindow* CompareProgressDialog::getAsWindow() -{ - return pimpl; -} - -void CompareProgressDialog::init(const Statistics& syncStat) -{ - pimpl->init(syncStat); -} - -void CompareProgressDialog::finalize() -{ - pimpl->finalize(); -} - -void CompareProgressDialog::switchToCompareBytewise() -{ - pimpl->switchToCompareBytewise(); -} - -void CompareProgressDialog::updateStatusPanelNow() -{ - pimpl->updateStatusPanelNow(); -} -//######################################################################################## - -namespace -{ -inline -wxBitmap buttonPressed(const std::string& name) -{ - wxBitmap background = getResourceImage(L"log button pressed"); - return layOver(getResourceImage(utfCvrtTo<wxString>(name)), background); -} - - -inline -wxBitmap buttonReleased(const std::string& name) -{ - wxImage output = greyScale(getResourceImage(utfCvrtTo<wxString>(name))).ConvertToImage(); - //getResourceImage(utfCvrtTo<wxString>(name)).ConvertToImage().ConvertToGreyscale(1.0/3, 1.0/3, 1.0/3); //treat all channels equally! - //brighten(output, 30); - - //zen::moveImage(output, 1, 0); //move image right one pixel - return output; -} - - -//a vector-view on ErrorLog considering multi-line messages: prepare consumption by Grid -class MessageView -{ -public: - MessageView(const ErrorLog& log) : log_(log) {} - - size_t rowsOnView() const { return viewRef.size(); } - - struct LogEntryView - { - time_t time; - MessageType type; - MsgString messageLine; - bool firstLine; //if LogEntry::message spans multiple rows - }; - bool getEntry(size_t row, LogEntryView& out) const - { - if (row < viewRef.size()) - { - const Line& line = viewRef[row]; - out.time = line.entry_->time; - out.type = line.entry_->type; - out.messageLine = extractLine(line.entry_->message, line.rowNumber_); - out.firstLine = line.rowNumber_ == 0; //this is virtually always correct, unless first line of the original message is empty! - return true; - } - return false; - } - - void updateView(int includedTypes) //TYPE_INFO | TYPE_WARNING, ect. see error_log.h - { - viewRef.clear(); - - for (auto it = log_.begin(); it != log_.end(); ++it) - if (it->type & includedTypes) - { - assert_static((IsSameType<GetCharType<MsgString>::Type, wchar_t>::value)); - assert(!startsWith(it->message, L'\n')); - - size_t rowNumber = 0; - bool lastCharNewline = true; - for (const wchar_t c : it->message) - if (c == L'\n') - { - if (!lastCharNewline) //do not reference empty lines! - viewRef.push_back(Line(&*it, rowNumber)); - ++rowNumber; - lastCharNewline = true; - } - else - lastCharNewline = false; - - if (!lastCharNewline) - viewRef.push_back(Line(&*it, rowNumber)); - } - } - -private: - static MsgString extractLine(const MsgString& message, size_t textRow) - { - auto iter1 = message.begin(); - for (;;) - { - auto iter2 = std::find_if(iter1, message.end(), [](wchar_t c) { return c == L'\n'; }); - if (textRow == 0) - return iter1 == message.end() ? MsgString() : MsgString(&*iter1, iter2 - iter1); //must not dereference iterator pointing to "end"! - - if (iter2 == message.end()) - { - assert(false); - return MsgString(); - } - - iter1 = iter2 + 1; //skip newline - --textRow; - } - } - - struct Line - { - Line(const LogEntry* entry, size_t rowNumber) : entry_(entry), rowNumber_(rowNumber) {} - const LogEntry* entry_; //always bound! - size_t rowNumber_; //LogEntry::message may span multiple rows - }; - - std::vector<Line> viewRef; //partial view on log_ - /* /|\ - | updateView() - | */ - const ErrorLog log_; -}; - -//----------------------------------------------------------------------------- - -enum ColumnTypeMsg -{ - COL_TYPE_MSG_TIME, - COL_TYPE_MSG_CATEGORY, - COL_TYPE_MSG_TEXT, -}; - -//Grid data implementation referencing MessageView -class GridDataMessages : public GridData -{ -public: - GridDataMessages(const std::shared_ptr<MessageView>& msgView) : msgView_(msgView) {} - - virtual size_t getRowCount() const { return msgView_ ? msgView_->rowsOnView() : 0; } - - virtual wxString getValue(size_t row, ColumnType colType) const - { - MessageView::LogEntryView entry = {}; - if (msgView_ && msgView_->getEntry(row, entry)) - switch (static_cast<ColumnTypeMsg>(colType)) - { - case COL_TYPE_MSG_TIME: - if (entry.firstLine) - return formatTime<wxString>(FORMAT_TIME, localTime(entry.time)); - break; - - case COL_TYPE_MSG_CATEGORY: - if (entry.firstLine) - switch (entry.type) - { - case TYPE_INFO: - return _("Info"); - case TYPE_WARNING: - return _("Warning"); - case TYPE_ERROR: - return _("Error"); - case TYPE_FATAL_ERROR: - return _("Serious Error"); - } - break; - - case COL_TYPE_MSG_TEXT: - return copyStringTo<wxString>(entry.messageLine); - } - return wxEmptyString; - } - - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool selected) override - { - wxRect rectTmp = rect; - - const wxColor colorGridLine = wxColour(192, 192, 192); //light grey - - wxDCPenChanger dummy2(dc, wxPen(colorGridLine, 1, wxSOLID)); - const bool drawBottomLine = [&]() -> bool //don't separate multi-line messages - { - MessageView::LogEntryView nextEntry = {}; - if (msgView_ && msgView_->getEntry(row + 1, nextEntry)) - return nextEntry.firstLine; - return true; - }(); - - if (drawBottomLine) - { - dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight() + wxPoint(1, 0)); - --rectTmp.height; - } - - //-------------------------------------------------------- - - MessageView::LogEntryView entry = {}; - if (msgView_ && msgView_->getEntry(row, entry)) - switch (static_cast<ColumnTypeMsg>(colType)) - { - case COL_TYPE_MSG_TIME: - drawCellText(dc, rectTmp, getValue(row, colType), true, wxALIGN_CENTER); - break; - - case COL_TYPE_MSG_CATEGORY: - if (entry.firstLine) - switch (entry.type) - { - case TYPE_INFO: - dc.DrawLabel(wxString(), getResourceImage(L"msg_info_small"), rectTmp, wxALIGN_CENTER); - break; - case TYPE_WARNING: - dc.DrawLabel(wxString(), getResourceImage(L"msg_warning_small"), rectTmp, wxALIGN_CENTER); - break; - case TYPE_ERROR: - case TYPE_FATAL_ERROR: - dc.DrawLabel(wxString(), getResourceImage(L"msg_error_small"), rectTmp, wxALIGN_CENTER); - break; - } - break; - - case COL_TYPE_MSG_TEXT: - { - rectTmp.x += COLUMN_GAP_LEFT; - rectTmp.width -= COLUMN_GAP_LEFT; - drawCellText(dc, rectTmp, getValue(row, colType), true); - } - break; - } - } - - virtual int getBestSize(wxDC& dc, size_t row, ColumnType colType) override - { - // -> synchronize renderCell() <-> getBestSize() - - MessageView::LogEntryView entry = {}; - if (msgView_ && msgView_->getEntry(row, entry)) - switch (static_cast<ColumnTypeMsg>(colType)) - { - case COL_TYPE_MSG_TIME: - return 2 * COLUMN_GAP_LEFT + dc.GetTextExtent(getValue(row, colType)).GetWidth(); - - case COL_TYPE_MSG_CATEGORY: - return getResourceImage(L"msg_info_small").GetWidth(); - - case COL_TYPE_MSG_TEXT: - return COLUMN_GAP_LEFT + dc.GetTextExtent(getValue(row, colType)).GetWidth(); - } - return 0; - } - - static int getColumnTimeDefaultWidth(Grid& grid) - { - wxClientDC dc(&grid.getMainWin()); - dc.SetFont(grid.getMainWin().GetFont()); - return 2 * COLUMN_GAP_LEFT + dc.GetTextExtent(formatTime<wxString>(FORMAT_TIME)).GetWidth(); - } - - static int getColumnCategoryDefaultWidth() - { - return getResourceImage(L"msg_info_small").GetWidth(); - } - - static int getRowDefaultHeight(const Grid& grid) - { - return std::max(getResourceImage(L"msg_info_small").GetHeight(), grid.getMainWin().GetCharHeight() + 2) + 1; //+ some space + bottom border - } - - virtual wxString getToolTip(size_t row, ColumnType colType) const override - { - MessageView::LogEntryView entry = {}; - if (msgView_ && msgView_->getEntry(row, entry)) - switch (static_cast<ColumnTypeMsg>(colType)) - { - case COL_TYPE_MSG_TIME: - case COL_TYPE_MSG_TEXT: - break; - - case COL_TYPE_MSG_CATEGORY: - return getValue(row, colType); - } - return wxEmptyString; - } - - virtual wxString getColumnLabel(ColumnType colType) const { return wxEmptyString; } - -private: - const std::shared_ptr<MessageView> msgView_; -}; -} - - -class LogPanel : public LogPanelGenerated -{ -public: - LogPanel(wxWindow* parent, const ErrorLog& log) : LogPanelGenerated(parent), - msgView(std::make_shared<MessageView>(log)) - { - const int errorCount = log.getItemCount(TYPE_ERROR | TYPE_FATAL_ERROR); - const int warningCount = log.getItemCount(TYPE_WARNING); - const int infoCount = log.getItemCount(TYPE_INFO); - - auto initButton = [](ToggleButton& btn, const char* imgName, const wxString& tooltip) { btn.init(buttonPressed(imgName), buttonReleased(imgName)); btn.SetToolTip(tooltip); }; - - initButton(*m_bpButtonErrors, "msg_error", _("Error" ) + wxString::Format(L" (%d)", errorCount )); - initButton(*m_bpButtonWarnings, "msg_warning", _("Warning") + wxString::Format(L" (%d)", warningCount)); - initButton(*m_bpButtonInfo, "msg_info", _("Info" ) + wxString::Format(L" (%d)", infoCount )); - - m_bpButtonErrors ->setActive(true); - m_bpButtonWarnings->setActive(true); - m_bpButtonInfo ->setActive(errorCount + warningCount == 0); - - m_bpButtonErrors ->Show(errorCount != 0); - m_bpButtonWarnings->Show(warningCount != 0); - m_bpButtonInfo ->Show(infoCount != 0); - - //init grid, determine default sizes - const int rowHeight = GridDataMessages::getRowDefaultHeight(*m_gridMessages); - const int colMsgTimeWidth = GridDataMessages::getColumnTimeDefaultWidth(*m_gridMessages); - const int colMsgCategoryWidth = GridDataMessages::getColumnCategoryDefaultWidth(); - - m_gridMessages->setDataProvider(std::make_shared<GridDataMessages>(msgView)); - m_gridMessages->setColumnLabelHeight(0); - m_gridMessages->showRowLabel(false); - m_gridMessages->setRowHeight(rowHeight); - std::vector<Grid::ColumnAttribute> attr; - attr.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_MSG_TIME ), colMsgTimeWidth, 0)); - attr.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_MSG_CATEGORY), colMsgCategoryWidth, 0)); - attr.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_MSG_TEXT ), -colMsgTimeWidth - colMsgCategoryWidth, 1)); - m_gridMessages->setColumnConfig(attr); - - //support for CTRL + C - m_gridMessages->getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(LogPanel::onGridButtonEvent), nullptr, this); - - m_gridMessages->Connect(EVENT_GRID_MOUSE_RIGHT_UP, GridClickEventHandler(LogPanel::onMsgGridContext), nullptr, this); - - updateGrid(); - } - -private: - virtual void OnErrors(wxCommandEvent& event) - { - m_bpButtonErrors->toggle(); - updateGrid(); - } - - virtual void OnWarnings(wxCommandEvent& event) - { - m_bpButtonWarnings->toggle(); - updateGrid(); - } - - virtual void OnInfo(wxCommandEvent& event) - { - m_bpButtonInfo->toggle(); - updateGrid(); - } - - void updateGrid() - { - int includedTypes = 0; - if (m_bpButtonErrors->isActive()) - includedTypes |= TYPE_ERROR | TYPE_FATAL_ERROR; - - if (m_bpButtonWarnings->isActive()) - includedTypes |= TYPE_WARNING; - - if (m_bpButtonInfo->isActive()) - includedTypes |= TYPE_INFO; - - msgView->updateView(includedTypes); //update MVC "model" - m_gridMessages->Refresh(); //update MVC "view" - } - - void onGridButtonEvent(wxKeyEvent& event) - { - int keyCode = event.GetKeyCode(); - - if (event.ControlDown()) - switch (keyCode) - { - case 'C': - case WXK_INSERT: //CTRL + C || CTRL + INS - copySelectionToClipboard(); - return; // -> swallow event! don't allow default grid commands! - } - - event.Skip(); //unknown keypress: propagate - } - - void onMsgGridContext(GridClickEvent& event) - { - const std::vector<size_t> selection = m_gridMessages->getSelectedRows(); - - ContextMenu menu; - menu.addItem(_("Copy") + L"\tCtrl+C", [this] { copySelectionToClipboard(); }, nullptr, !selection.empty()); - menu.popup(*this); - } - - void copySelectionToClipboard() - { - try - { - typedef Zbase<wchar_t> zxString; //guaranteed exponential growth, unlike wxString - zxString clipboardString; - - if (auto prov = m_gridMessages->getDataProvider()) - { - std::vector<Grid::ColumnAttribute> colAttr = m_gridMessages->getColumnConfig(); - vector_remove_if(colAttr, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; }); - if (!colAttr.empty()) - { - const std::vector<size_t> selection = m_gridMessages->getSelectedRows(); - std::for_each(selection.begin(), selection.end(), - [&](size_t row) - { -#ifdef _MSC_VER - typedef zxString zxString; //workaround MSVC compiler bug! -#endif - std::for_each(colAttr.begin(), --colAttr.end(), - [&](const Grid::ColumnAttribute& ca) - { - clipboardString += copyStringTo<zxString>(prov->getValue(row, ca.type_)); - clipboardString += L'\t'; - }); - clipboardString += copyStringTo<zxString>(prov->getValue(row, colAttr.back().type_)); - clipboardString += L'\n'; - }); - } - } - - //finally write to clipboard - if (!clipboardString.empty()) - if (wxClipboard::Get()->Open()) - { - ZEN_ON_SCOPE_EXIT(wxClipboard::Get()->Close()); - wxClipboard::Get()->SetData(new wxTextDataObject(copyStringTo<wxString>(clipboardString))); //ownership passed - } - } - catch (const std::bad_alloc& e) - { - showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setMainInstructions(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()))); - } - } - - std::shared_ptr<MessageView> msgView; //bound! -}; - -//######################################################################################## - -namespace -{ -class CurveDataStatistics : public SparseCurveData -{ -public: - CurveDataStatistics() : SparseCurveData(true), /*true: add steps*/ timeNow(0) {} - - void clear() { samples.clear(); timeNow = 0; } - - void addRecord(long timeNowMs, double value) - { - //samples.clear(); - //samples.insert(std::make_pair(-1000, 0)); - //samples.insert(std::make_pair(0, 0)); - //samples.insert(std::make_pair(1, 1)); - //samples.insert(std::make_pair(1000, 0)); - //return; - - timeNow = timeNowMs; - - //don't allow for more samples per second than there are UI updates (handles duplicate inserts, too!) - if (!samples.empty() && timeNowMs / UI_UPDATE_INTERVAL == samples.rbegin()->first / UI_UPDATE_INTERVAL) - { - samples.rbegin()->second = value; - return; - } - - samples.insert(samples.end(), std::make_pair(timeNowMs, value)); //time is "expected" to be monotonously ascending - //documentation differs about whether "hint" should be before or after the to be inserted element! - //however "std::map<>::end()" is interpreted correctly by GCC and VS2010 - - if (samples.size() > MAX_BUFFER_SIZE) //limit buffer size - samples.erase(samples.begin()); - } - -private: - virtual std::pair<double, double> getRangeX() const override - { - if (samples.empty()) return std::make_pair(0.0, 0.0); - - double upperEndMs = std::max(timeNow, samples.rbegin()->first); - - //report some additional width by 5% elapsed time to make graph recalibrate before hitting the right border - //caveat: graph for batch mode binary comparison does NOT start at elapsed time 0!! PHASE_COMPARING_CONTENT and PHASE_SYNCHRONIZING! - //=> consider width of current sample set! - upperEndMs += 0.05 *(upperEndMs - samples.begin()->first); - - return std::make_pair(samples.begin()->first / 1000.0, //need not start with 0, e.g. "binary comparison, graph reset, followed by sync" - upperEndMs / 1000.0); - } - - virtual Opt<CurvePoint> getLessEq(double x) const override //x: seconds since begin - { - const long timex = std::floor(x * 1000); - //------ add artifical last sample value ------- - if (!samples.empty() && samples.rbegin()->first < timeNow) - if (timeNow <= timex) - return CurvePoint(timeNow / 1000.0, samples.rbegin()->second); - //-------------------------------------------------- - - //find first key > x, then go one step back: => samples must be a std::map, NOT std::multimap!!! - auto it = samples.upper_bound(timex); - if (it == samples.begin()) - return NoValue(); - //=> samples not empty in this context - --it; - return CurvePoint(it->first / 1000.0, it->second); - } - - virtual Opt<CurvePoint> getGreaterEq(double x) const override - { - const long timex = std::ceil(x * 1000); - //------ add artifical last sample value ------- - if (!samples.empty() && samples.rbegin()->first < timeNow) - if (samples.rbegin()->first < timex && timex <= timeNow) - return CurvePoint(timeNow / 1000.0, samples.rbegin()->second); - //-------------------------------------------------- - - auto it = samples.lower_bound(timex); - if (it == samples.end()) - return NoValue(); - return CurvePoint(it->first / 1000.0, it->second); - } - - static const size_t MAX_BUFFER_SIZE = 2500000; //sizeof(single node) worst case ~ 3 * 8 byte ptr + 16 byte key/value = 40 byte - - std::map<long, double> samples; //time, unit: [ms] !don't use std::multimap, see getLessEq() - long timeNow; //help create an artificial record at the end of samples to visualize current time! -}; - - -class CurveDataCurrentValue : public CurveData -{ -public: - CurveDataCurrentValue() : x(0), yCurrent_(0), yTotal_(0) {} - - void setValue(long xTimeNowMs, double yCurrent, double yTotal) { x = xTimeNowMs / 1000.0; yCurrent_ = yCurrent; yTotal_ = yTotal; } - -private: - virtual std::pair<double, double> getRangeX() const override { return std::make_pair(x, x); } //conceptually just a vertical line! - - virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override - { - //points.push_back(CurvePoint(-1, 0)); - //points.push_back(CurvePoint(0, 0)); - //points.push_back(CurvePoint(0.0001, 1)); - //points.push_back(CurvePoint(1, 0)); - //return; - - if (x <= maxX) - { - points.push_back(CurvePoint(x, 0)); - points.push_back(CurvePoint(x, yCurrent_)); - points.push_back(CurvePoint(maxX, yCurrent_)); - points.push_back(CurvePoint(x, yCurrent_)); - points.push_back(CurvePoint(x, yTotal_)); - } - } - - double x; //time elapsed in seconds - double yCurrent_; //current bytes/items - double yTotal_; -}; - - -class CurveDataTotalValue : public CurveData -{ -public: - CurveDataTotalValue () : x(0), yTotal_(0) {} - - void setValue(long xTimeNowMs, double yTotal) { x = xTimeNowMs / 1000.0; yTotal_ = yTotal; } - -private: - virtual std::pair<double, double> getRangeX() const override { return std::make_pair(x, x); } //conceptually just a vertical line! - - virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override - { - if (x <= maxX) - { - points.push_back(CurvePoint(x, yTotal_)); - points.push_back(CurvePoint(maxX, yTotal_)); - } - } - - double x; //time elapsed in seconds - double yTotal_; -}; - - -const double stretchDefaultBlockSize = 1.4; //enlarge block default size - - -struct LabelFormatterBytes : public LabelFormatter -{ - virtual double getOptimalBlockSize(double bytesProposed) const - { - bytesProposed *= stretchDefaultBlockSize; //enlarge block default size - - if (bytesProposed <= 1) //never smaller than 1 byte - return 1; - - //round to next number which is a convenient to read block size - const double k = std::floor(std::log(bytesProposed) / std::log(2.0)); - const double e = std::pow(2.0, k); - if (numeric::isNull(e)) - return 0; - const double a = bytesProposed / e; //bytesProposed = a * 2^k with a in [1, 2) - assert(1 <= a && a < 2); - const double steps[] = { 1, 2 }; - return e * numeric::nearMatch(a, std::begin(steps), std::end(steps)); - } - - virtual wxString formatText(double value, double optimalBlockSize) const { return filesizeToShortString(Int64(value)); }; -}; - - -struct LabelFormatterItemCount : public LabelFormatter -{ - virtual double getOptimalBlockSize(double itemsProposed) const - { - itemsProposed *= stretchDefaultBlockSize; //enlarge block default size - - const double steps[] = { 1, 2, 5, 10 }; - if (itemsProposed <= 10) - return numeric::nearMatch(itemsProposed, std::begin(steps), std::end(steps)); //similar to nextNiceNumber(), but without the 2.5 step! - return nextNiceNumber(itemsProposed); - } - - virtual wxString formatText(double value, double optimalBlockSize) const - { - return toGuiString(numeric::round(value)); //not enough room for a "%x items" representation - }; -}; - - -struct LabelFormatterTimeElapsed : public LabelFormatter -{ - LabelFormatterTimeElapsed(bool drawLabel) : drawLabel_(drawLabel) {} - - virtual double getOptimalBlockSize(double secProposed) const - { - const double stepsSec[] = { 20, 30, 60 }; //20 sec: minimum block size; (no 15: avoid flicker between 10<->15<->20 sec blocks) - if (secProposed <= 60) - return numeric::nearMatch(secProposed, std::begin(stepsSec), std::end(stepsSec)); - - const double stepsMin[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; //nice numbers for minutes - if (secProposed <= 3600) - return 60.0 * numeric::nearMatch(secProposed / 60, std::begin(stepsMin), std::end(stepsMin)); - - if (secProposed <= 3600 * 24) - return nextNiceNumber(secProposed / 3600) * 3600; //round up to full hours - - return nextNiceNumber(secProposed / (24 * 3600)) * 24 * 3600; //round to full days - } - - virtual wxString formatText(double timeElapsed, double optimalBlockSize) const - { - if (!drawLabel_) return wxString(); - return timeElapsed < 60 ? - _P("1 sec", "%x sec", numeric::round(timeElapsed)) : - timeElapsed < 3600 ? - wxTimeSpan::Seconds(timeElapsed).Format( L"%M:%S") : - wxTimeSpan::Seconds(timeElapsed).Format(L"%H:%M:%S"); - } - -private: - bool drawLabel_; -}; -} - - -template <class TopLevelDialog> //can be a wxFrame or wxDialog -class SyncProgressDialogImpl : public TopLevelDialog, public SyncProgressDialog -/*we need derivation, not composition! - 1. SyncProgressDialogImpl IS a wxFrame/wxDialog - 2. implement virtual ~wxFrame() - 3. event handling below assumes lifetime is larger-equal than wxFrame's -*/ -{ -public: - SyncProgressDialogImpl(long style, //wxFrame/wxDialog style - const std::function<wxFrame*(TopLevelDialog& progDlg)>& getTaskbarFrame, - AbortCallback& abortCb, - const std::function<void()>& notifyWindowTerminate, - const Statistics& syncStat, - wxFrame* parentFrame, - bool showProgress, - const wxString& jobName, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory); - virtual ~SyncProgressDialogImpl(); - - //call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater - virtual void processHasFinished(SyncResult resultId, const ErrorLog& log); - virtual void closeWindowDirectly(); - - virtual wxWindow* getWindowIfVisible() { return this->IsShown() ? this : nullptr; } - //workaround OS X bug: if "this" is used as parent window for a modal dialog then this dialog will erroneously un-hide its parent! - - virtual void initNewPhase(); - virtual void notifyProgressChange(); - virtual void updateGui() { updateGuiInt(true); } - - virtual std::wstring getExecWhenFinishedCommand() const { return pnl.m_comboBoxExecFinished->getValue(); } - - virtual void stopTimer() //halt all internal counters! - { - pnl.m_animCtrlSyncing->Stop(); - timeElapsed.Pause (); - } - virtual void resumeTimer() - { - pnl.m_animCtrlSyncing->Play(); - timeElapsed.Resume(); - } - -private: - void updateGuiInt(bool allowYield); - - void OnKeyPressed(wxKeyEvent& event); - void OnOkay (wxCommandEvent& event); - void OnPause (wxCommandEvent& event); - void OnCancel (wxCommandEvent& event); - void OnClose (wxCloseEvent& event); - void OnIconize(wxIconizeEvent& event); - void OnMinimizeToTray(wxCommandEvent& event) { minimizeToTray(); } - - void minimizeToTray(); - void resumeFromSystray(); - - void updateDialogStatus(); - void setExternalStatus(const wxString& status, const wxString& progress); //progress may be empty! - - SyncProgressPanelGenerated& pnl; //wxPanel containing the GUI controls of *this - - const wxString jobName_; - wxStopWatch timeElapsed; - - wxFrame* parentFrame_; //optional - - std::function<void()> notifyWindowTerminate_; //call once in OnClose(), NOT in destructor which is called far too late somewhere in wxWidgets main loop! - - bool wereDead; //after wxWindow::Delete, which is equal to "delete this" on OS X! - - //status variables - const Statistics* syncStat_; // - AbortCallback* abortCb_; //valid only while sync is running - bool paused_; //valid only while sync is running - SyncResult finalResult; //set after sync - - //remaining time - std::unique_ptr<PerfCheck> perf; - long lastStatCallSpeed; //used for calculating intervals between collecting perf samples - //help calculate total speed - long phaseStartMs; //begin of current phase in [ms] - - std::shared_ptr<CurveDataStatistics> curveDataBytes; - std::shared_ptr<CurveDataStatistics> curveDataItems; - - std::shared_ptr<CurveDataTotalValue > curveDataBytesTotal; - std::shared_ptr<CurveDataCurrentValue> curveDataBytesCurrent; - std::shared_ptr<CurveDataTotalValue > curveDataItemsTotal; - std::shared_ptr<CurveDataCurrentValue> curveDataItemsCurrent; - - wxString parentFrameTitleBackup; - std::unique_ptr<FfsTrayIcon> trayIcon; //optional: if filled all other windows should be hidden and conversely - std::unique_ptr<Taskbar> taskbar_; -}; - - -template <class TopLevelDialog> -SyncProgressDialogImpl<TopLevelDialog>::SyncProgressDialogImpl(long style, //wxFrame/wxDialog style - const std::function<wxFrame*(TopLevelDialog& progDlg)>& getTaskbarFrame, - AbortCallback& abortCb, - const std::function<void()>& notifyWindowTerminate, - const Statistics& syncStat, - wxFrame* parentFrame, - bool showProgress, - const wxString& jobName, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory) : - TopLevelDialog(parentFrame, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, style), //title is overwritten anyway in setExternalStatus() - pnl(*new SyncProgressPanelGenerated(this)), //ownership passed to "this" - jobName_ (jobName), - parentFrame_(parentFrame), - notifyWindowTerminate_(notifyWindowTerminate), - wereDead(false), - syncStat_ (&syncStat), - abortCb_ (&abortCb), - paused_ (false), - finalResult(RESULT_ABORTED), //dummy value - lastStatCallSpeed(-1000000), //some big number - phaseStartMs(0) -{ - assert_static((IsSameType<TopLevelDialog, wxFrame >::value || - IsSameType<TopLevelDialog, wxDialog>::value)); - assert((IsSameType<TopLevelDialog, wxFrame>::value == !parentFrame)); - - //finish construction of this dialog: - this->SetMinSize(wxSize(470, 280)); //== minimum size! no idea why SetMinSize() is not used... - wxBoxSizer* bSizer170 = new wxBoxSizer(wxVERTICAL); - bSizer170->Add(&pnl, 1, wxEXPAND); - this->SetSizer(bSizer170); //pass ownership - //this->Layout(); - //bSizer170->Fit(this); - this->Centre(wxBOTH); - - //lifetime of event sources is subset of this instance's lifetime => no wxEvtHandler::Disconnect() needed - this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler (SyncProgressDialogImpl<TopLevelDialog>::OnClose)); - this->Connect(wxEVT_ICONIZE, wxIconizeEventHandler(SyncProgressDialogImpl<TopLevelDialog>::OnIconize)); - this->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(SyncProgressDialogImpl::OnKeyPressed), nullptr, this); - pnl.m_buttonClose->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnOkay ), NULL, this); - pnl.m_buttonPause->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnPause ), NULL, this); - pnl.m_buttonStop ->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnCancel), NULL, this); - pnl.m_bpButtonMinimizeToTray->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnMinimizeToTray), NULL, this); - -#ifdef ZEN_WIN - new MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - - assert(pnl.m_buttonClose->GetId() == wxID_OK); //we cannot use wxID_CLOSE else Esc key won't work: yet another wxWidgets bug?? - - setRelativeFontSize(*pnl.m_staticTextPhase, 1.5); - - if (parentFrame_) - parentFrameTitleBackup = parentFrame_->GetTitle(); //save old title (will be used as progress indicator) - - pnl.m_animCtrlSyncing->SetAnimation(getResourceAnimation(L"working")); - pnl.m_animCtrlSyncing->Play(); - - this->EnableCloseButton(false); //this is NOT honored on OS X or during system shutdown on Windows! - - timeElapsed.Start(); //measure total time - - if (wxFrame* frame = getTaskbarFrame(*this)) - try //try to get access to Windows 7/Ubuntu taskbar - { - taskbar_ = make_unique<Taskbar>(*frame); //throw TaskbarNotAvailable - } - catch (const TaskbarNotAvailable&) {} - - //hide "processed" statistics until end of process - pnl.m_notebookResult ->Hide(); - pnl.m_panelItemsProcessed->Hide(); - pnl.m_buttonClose ->Show(false); - //set std order after button visibility was set - setStandardButtonOrder(*pnl.bSizerStdButtons, StdButtons().setAffirmative(pnl.m_buttonPause).setCancel(pnl.m_buttonStop)); - - pnl.m_bpButtonMinimizeToTray->SetBitmapLabel(getResourceImage(L"minimize_to_tray")); - - //init graph - curveDataBytes = std::make_shared<CurveDataStatistics>(); - curveDataItems = std::make_shared<CurveDataStatistics>(); - curveDataBytesTotal = std::make_shared<CurveDataTotalValue>(); - curveDataBytesCurrent = std::make_shared<CurveDataCurrentValue>(); - curveDataItemsTotal = std::make_shared<CurveDataTotalValue>(); - curveDataItemsCurrent = std::make_shared<CurveDataCurrentValue>(); - - const int xLabelHeight = 18; //we need to use the same height for both graphs to make sure they stretch evenly - const int yLabelWidth = 70; - pnl.m_panelGraphBytes->setAttributes(Graph2D::MainAttributes(). - setLabelX(Graph2D::X_LABEL_BOTTOM, xLabelHeight, std::make_shared<LabelFormatterTimeElapsed>(true)). - setLabelY(Graph2D::Y_LABEL_RIGHT, yLabelWidth, std::make_shared<LabelFormatterBytes>()). - setSelectionMode(Graph2D::SELECT_NONE)); - - pnl.m_panelGraphItems->setAttributes(Graph2D::MainAttributes(). - setLabelX(Graph2D::X_LABEL_BOTTOM, xLabelHeight, std::make_shared<LabelFormatterTimeElapsed>(false)). - setLabelY(Graph2D::Y_LABEL_RIGHT, yLabelWidth, std::make_shared<LabelFormatterItemCount>()). - setSelectionMode(Graph2D::SELECT_NONE)); - - //pnl.m_panelGraphBytes->setAttributes(Graph2D::MainAttributes().setMinX(-1).setMaxX(1).setMinY(-1).setMaxY(1)); - - pnl.m_panelGraphBytes->setCurve(curveDataBytes, Graph2D::CurveAttributes().setLineWidth(2). - fillCurveArea(wxColor(205, 255, 202)). //faint green - setColor (wxColor( 20, 200, 0))); //medium green - - pnl.m_panelGraphItems->setCurve(curveDataItems, Graph2D::CurveAttributes().setLineWidth(2). - fillCurveArea(wxColor(198, 206, 255)). //faint blue - setColor (wxColor( 90, 120, 255))); //medium blue - - pnl.m_panelGraphBytes->addCurve(curveDataBytesTotal, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(12, 128, 0))); //dark green - pnl.m_panelGraphBytes->addCurve(curveDataBytesCurrent, Graph2D::CurveAttributes().setLineWidth(1).setColor(wxColor(12, 128, 0))); // - - pnl.m_panelGraphItems->addCurve(curveDataItemsTotal, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(53, 25, 255))); //dark blue - pnl.m_panelGraphItems->addCurve(curveDataItemsCurrent, Graph2D::CurveAttributes().setLineWidth(1).setColor(wxColor(53, 25, 255))); // - - //allow changing on completion command - pnl.m_comboBoxExecFinished->initHistory(execFinishedHistory, execFinishedHistory.size()); //-> we won't use addItemHistory() later - pnl.m_comboBoxExecFinished->setValue(execWhenFinished); - - updateDialogStatus(); //null-status will be shown while waiting for dir locks - - this->GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - pnl.Layout(); - - if (showProgress) - { - this->Show(); -#ifdef ZEN_MAC - ProcessSerialNumber psn = { 0, kCurrentProcess }; - ::SetFrontProcess(&psn); //call before TransformProcessType() so that OSX menu is updated correctly - ::TransformProcessType(&psn, kProcessTransformToForegroundApplication); //show dock icon (consider non-silent batch mode) -#endif - - pnl.m_buttonStop->SetFocus(); //don't steal focus when starting in sys-tray! - - //clear gui flicker, remove dummy texts: window must be visible to make this work! - updateGuiInt(true); //at least on OS X a real Yield() is required to flush pending GUI updates; Update() is not enough - } - else - minimizeToTray(); -} - - -template <class TopLevelDialog> -SyncProgressDialogImpl<TopLevelDialog>::~SyncProgressDialogImpl() -{ - if (parentFrame_) - { - parentFrame_->SetTitle(parentFrameTitleBackup); //restore title text - - //make sure main dialog is shown again if still "minimized to systray"! see SyncProgressDialog::closeWindowDirectly() - parentFrame_->Show(); -#ifdef ZEN_MAC - ProcessSerialNumber psn = { 0, kCurrentProcess }; - ::SetFrontProcess(&psn); //call before TransformProcessType() so that OSX menu is updated correctly - //why isn't this covered by wxWindows::Raise()?? - ::TransformProcessType(&psn, kProcessTransformToForegroundApplication); //show dock icon (consider GUI mode with "close progress dialog") -#endif - //if (parentFrame_->IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize! - // parentFrame_->Iconize(false); - } - - //our client is NOT expecting a second call via notifyWindowTerminate_()! -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::OnKeyPressed(wxKeyEvent& event) -{ - const int keyCode = event.GetKeyCode(); - if (keyCode == WXK_ESCAPE) - { - wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); - - //simulate click on abort button - if (pnl.m_buttonStop->IsShown()) //delegate to "cancel" button if available - { - if (wxEvtHandler* handler = pnl.m_buttonStop->GetEventHandler()) - handler->ProcessEvent(dummy); - return; - } - else if (pnl.m_buttonClose->IsShown()) - { - if (wxEvtHandler* handler = pnl.m_buttonClose->GetEventHandler()) - handler->ProcessEvent(dummy); - return; - } - } - - event.Skip(); -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::initNewPhase() -{ - updateDialogStatus(); //evaluates "syncStat_->currentPhase()" - - //reset graphs (e.g. after binary comparison) - curveDataBytesTotal ->setValue(0, 0); - curveDataBytesCurrent->setValue(0, 0, 0); - curveDataItemsTotal ->setValue(0, 0); - curveDataItemsCurrent->setValue(0, 0, 0); - curveDataBytes->clear(); - curveDataItems->clear(); - - notifyProgressChange(); - - //start new measurement - perf = make_unique<PerfCheck>(WINDOW_REMAINING_TIME, WINDOW_BYTES_PER_SEC); - lastStatCallSpeed = -1000000; //some big number - - phaseStartMs = timeElapsed.Time(); - - updateGuiInt(false); -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::notifyProgressChange() //noexcept! -{ - if (syncStat_) //sync running - switch (syncStat_->currentPhase()) - { - case ProcessCallback::PHASE_NONE: - assert(false); - case ProcessCallback::PHASE_SCANNING: - break; - case ProcessCallback::PHASE_COMPARING_CONTENT: - case ProcessCallback::PHASE_SYNCHRONIZING: - curveDataBytes->addRecord(timeElapsed.Time(), to<double>(syncStat_->getDataCurrent (syncStat_->currentPhase()))); - curveDataItems->addRecord(timeElapsed.Time(), syncStat_->getObjectsCurrent(syncStat_->currentPhase())); - break; - } -} - - -namespace -{ -#ifdef ZEN_WIN -enum Zorder -{ - ZORDER_CORRECT, - ZORDER_WRONG, - ZORDER_INDEFINITE, -}; - -Zorder evaluateZorder(const wxWindow& top, const wxWindow& bottom) -{ - HWND hTop = static_cast<HWND>(top.GetHWND()); - HWND hBottom = static_cast<HWND>(bottom.GetHWND()); - assert(hTop && hBottom); - - for (HWND hAbove = hBottom; hAbove; hAbove = ::GetNextWindow(hAbove, GW_HWNDPREV)) //GW_HWNDPREV means "to foreground" - if (hAbove == hTop) - return ZORDER_CORRECT; - - for (HWND hAbove = hTop; hAbove; hAbove = ::GetNextWindow(hAbove, GW_HWNDPREV)) - if (hAbove == hBottom) - return ZORDER_WRONG; - - return ZORDER_INDEFINITE; -} -#endif - - -std::wstring getDialogPhaseText(const Statistics* syncStat, bool paused, SyncProgressDialog::SyncResult finalResult) -{ - if (syncStat) //sync running - { - if (paused) - return _("Paused"); - else - switch (syncStat->currentPhase()) - { - case ProcessCallback::PHASE_NONE: - return _("Initializing..."); //dialog is shown *before* sync starts, so this text may be visible! - case ProcessCallback::PHASE_SCANNING: - return _("Scanning..."); - case ProcessCallback::PHASE_COMPARING_CONTENT: - return _("Comparing content..."); - case ProcessCallback::PHASE_SYNCHRONIZING: - return _("Synchronizing..."); - } - } - else //sync finished - switch (finalResult) - { - case SyncProgressDialog::RESULT_ABORTED: - return _("Stopped"); - case SyncProgressDialog::RESULT_FINISHED_WITH_ERROR: - case SyncProgressDialog::RESULT_FINISHED_WITH_WARNINGS: - case SyncProgressDialog::RESULT_FINISHED_WITH_SUCCESS: - return _("Completed"); - } - return std::wstring(); -} -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::setExternalStatus(const wxString& status, const wxString& progress) //progress may be empty! -{ - //sys tray: order "top-down": jobname, status, progress - wxString systrayTooltip = jobName_.empty() ? status : L"\"" + jobName_ + L"\"\n" + status; - if (!progress.empty()) - systrayTooltip += L" " + progress; - - //window caption/taskbar; inverse order: progress, status, jobname - wxString title = progress.empty() ? status : progress + L" - " + status; - if (!jobName_.empty()) - title += L" - \"" + jobName_ + L"\""; - - //systray tooltip, if window is minimized - if (trayIcon.get()) - trayIcon->setToolTip(systrayTooltip); - - //show text in dialog title (and at the same time in taskbar) - if (parentFrame_) - { - if (parentFrame_->GetTitle() != title) - parentFrame_->SetTitle(title); - } - - //always set a title: we don't wxGTK to show "nameless window" instead - if (this->GetTitle() != title) - this->SetTitle(title); -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::updateGuiInt(bool allowYield) -{ - if (!syncStat_) //sync not running - return; - - bool layoutChanged = false; //avoid screen flicker by calling layout() only if necessary - const long timeNow = timeElapsed.Time(); - - //sync status text - setText(*pnl.m_staticTextStatus, replaceCpy(syncStat_->currentStatusText(), L'\n', L' ')); //no layout update for status texts! - - switch (syncStat_->currentPhase()) //no matter if paused or not - { - case ProcessCallback::PHASE_NONE: - case ProcessCallback::PHASE_SCANNING: - //dialog caption, taskbar, systray tooltip - setExternalStatus(getDialogPhaseText(syncStat_, paused_, finalResult), toGuiString(syncStat_->getObjectsCurrent(ProcessCallback::PHASE_SCANNING))); //status text may be "paused"! - - //progress indicators - if (trayIcon.get()) trayIcon->setProgress(1); //100% = regular FFS logo - - //ignore graphs: should already have been cleared in initNewPhase() - - //remaining objects and data - setText(*pnl.m_staticTextRemainingObj , L"-", &layoutChanged); - setText(*pnl.m_staticTextDataRemaining, L"", &layoutChanged); - - //remaining time and speed - setText(*pnl.m_staticTextRemTime, L"-", &layoutChanged); - pnl.m_panelGraphBytes->setAttributes(pnl.m_panelGraphBytes->getAttributes().setCornerText(wxString(), Graph2D::CORNER_TOP_LEFT)); - pnl.m_panelGraphItems->setAttributes(pnl.m_panelGraphItems->getAttributes().setCornerText(wxString(), Graph2D::CORNER_TOP_LEFT)); - break; - - case ProcessCallback::PHASE_COMPARING_CONTENT: - case ProcessCallback::PHASE_SYNCHRONIZING: - { - const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase()); - const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase()); - const Int64 dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase()); - const Int64 dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase()); - - //add both data + obj-count, to handle "deletion-only" cases - const double fraction = dataTotal + itemsTotal == 0 ? 1 : std::max(0.0, to<double>(dataCurrent + itemsCurrent) / to<double>(dataTotal + itemsTotal)); - //yes, this may legitimately become < 0: failed rename operation falls-back to copy + delete, reducing "dataCurrent" to potentially < 0! - //---------------------------------------------------------------------------------------------------- - - //dialog caption, taskbar, systray tooltip - setExternalStatus(getDialogPhaseText(syncStat_, paused_, finalResult), fractionToString(fraction)); //status text may be "paused"! - - //progress indicators - if (trayIcon.get()) trayIcon->setProgress(fraction); - if (taskbar_.get()) taskbar_->setProgress(fraction); - - //constant line graph - curveDataBytesTotal ->setValue(timeNow, to<double>(dataTotal)); - curveDataBytesCurrent->setValue(timeNow, to<double>(dataCurrent), to<double>(dataTotal)); - curveDataItemsTotal ->setValue(timeNow, itemsTotal); - curveDataItemsCurrent->setValue(timeNow, itemsCurrent, itemsTotal); - //even though notifyProgressChange() already set the latest data, let's add another sample to have all curves consider "timeNow" - //no problem with adding too many records: CurveDataStatistics will remove duplicate entries! - curveDataBytes->addRecord(timeNow, to<double>(dataCurrent)); - curveDataItems->addRecord(timeNow, itemsCurrent); - - //remaining objects and data - setText(*pnl.m_staticTextRemainingObj, toGuiString(itemsTotal - itemsCurrent), &layoutChanged); - setText(*pnl.m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged); - //it's possible data remaining becomes shortly negative if last file synced has ADS data and the dataTotal was not yet corrected! - - //remaining time and speed - assert(perf); - if (perf) - if (numeric::dist(lastStatCallSpeed, timeNow) >= 500) - { - lastStatCallSpeed = timeNow; - - if (numeric::dist(phaseStartMs, timeNow) >= 1000) //discard stats for first second: probably messy - perf->addSample(itemsCurrent, to<double>(dataCurrent), timeNow); - - //current speed -> Win 7 copy uses 1 sec update interval instead - Opt<std::wstring> bps = perf->getBytesPerSecond(); - Opt<std::wstring> ips = perf->getItemsPerSecond(); - pnl.m_panelGraphBytes->setAttributes(pnl.m_panelGraphBytes->getAttributes().setCornerText(bps ? *bps : L"", Graph2D::CORNER_TOP_LEFT)); - pnl.m_panelGraphItems->setAttributes(pnl.m_panelGraphItems->getAttributes().setCornerText(ips ? *ips : L"", Graph2D::CORNER_TOP_LEFT)); - //setText(*pnl.m_staticTextSpeed, perf->getBytesPerSecond(), &layoutChanged); - - //remaining time: display with relative error of 10% - based on samples taken every 0.5 sec only - //-> call more often than once per second to correctly show last few seconds countdown, but don't call too often to avoid occasional jitter - Opt<std::wstring> rt = perf->getRemainingTime(to<double>(dataTotal - dataCurrent)); - setText(*pnl.m_staticTextRemTime, rt ? *rt : L"-", &layoutChanged); - } - } - break; - } - - pnl.m_panelGraphBytes->Refresh(); - pnl.m_panelGraphItems->Refresh(); - - //time elapsed - const long timeElapSec = timeNow / 1000; - setText(*pnl.m_staticTextTimeElapsed, - timeElapSec < 3600 ? - wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") : - wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged); - - //adapt layout after content changes above - if (layoutChanged) - { - pnl.m_panelProgress->Layout(); - //small statistics panels: - //pnl.m_panelItemsProcessed->Layout(); - pnl.m_panelItemsRemaining->Layout(); - pnl.m_panelTimeRemaining ->Layout(); - //pnl.m_panelTimeElapsed->Layout(); -> needed? - } - -#ifdef ZEN_WIN - //workaround Windows 7 bug messing up z-order after temporary application hangs: https://sourceforge.net/tracker/index.php?func=detail&aid=3376523&group_id=234430&atid=1093080 - //This is still needed no matter if wxDialog or wxPanel is used! (2013-07) - if (parentFrame_) - if (evaluateZorder(*this, *parentFrame_) == ZORDER_WRONG) - { - HWND hProgress = static_cast<HWND>(this->GetHWND()); - if (::IsWindowVisible(hProgress)) - { - ::ShowWindow(hProgress, SW_HIDE); //make Windows recalculate z-order - ::ShowWindow(hProgress, SW_SHOW); // - } - } -#endif - - if (allowYield) - { - //support for pause button - if (paused_) - { - /* - ZEN_ON_SCOPE_EXIT(resumeTimer()); -> crashes on Fedora; WHY??? - => likely compiler bug!!! - 1. no crash on Fedora for: ZEN_ON_SCOPE_EXIT(this->resumeTimer()); - 1. no crash if we derive from wxFrame instead of template "TopLevelDialog" - 2. no crash on Ubuntu GCC - 3. following makes GCC crash already during compilation: auto dfd = zen::makeGuard([this]{ resumeTimer(); }); - */ - - stopTimer(); - - while (paused_) - { - wxTheApp->Yield(); //receive UI message that end pause OR forceful termination! - //*first* refresh GUI (removing flicker) before sleeping! - boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL)); - } - //if SyncProgressDialogImpl::OnClose() already wxWindow::Destroy() on OS X then this instance is already toast! - if (wereDead) - return; //GTFO and don't call this->resumeTimer() - - resumeTimer(); - } - else - /* - /|\ - | keep this sequence to ensure one full progress update before entering pause mode! - \|/ - */ - wxTheApp->Yield(); //receive UI message that sets pause status OR forceful termination! - } - else - this->Update(); //don't wait until next idle event (who knows what blocking process comes next?) -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::updateDialogStatus() //depends on "syncStat_, paused_, finalResult" -{ - const wxString dlgStatusTxt = getDialogPhaseText(syncStat_, paused_, finalResult); - - pnl.m_staticTextPhase->SetLabel(dlgStatusTxt); - - //status bitmap - if (syncStat_) //sync running - { - auto setStatusBitmap = [&](const wchar_t* bmpName) - { - pnl.m_animCtrlSyncing->Hide(); - pnl.m_bitmapStatus->SetBitmap(getResourceImage(bmpName)); - pnl.m_bitmapStatus->SetToolTip(dlgStatusTxt); - pnl.m_bitmapStatus->Show(); - }; - - if (paused_) - setStatusBitmap(L"status_pause"); - else - switch (syncStat_->currentPhase()) - { - case ProcessCallback::PHASE_NONE: - pnl.m_animCtrlSyncing->Hide(); - pnl.m_bitmapStatus->Hide(); - break; - - case ProcessCallback::PHASE_SCANNING: - setStatusBitmap(L"status_scanning"); - break; - - case ProcessCallback::PHASE_COMPARING_CONTENT: - setStatusBitmap(L"status_binary_compare"); - break; - - case ProcessCallback::PHASE_SYNCHRONIZING: - pnl.m_bitmapStatus->SetBitmap(getResourceImage(L"status_syncing")); - pnl.m_bitmapStatus->SetToolTip(dlgStatusTxt); - pnl.m_bitmapStatus->Show(); - pnl.m_animCtrlSyncing->Show(); - pnl.m_animCtrlSyncing->SetToolTip(dlgStatusTxt); - break; - } - } - else //sync finished - { - auto setStatusBitmap = [&](const wchar_t* bmpName, const std::wstring& tooltip) - { - pnl.m_animCtrlSyncing->Hide(); - pnl.m_bitmapStatus->SetBitmap(getResourceImage(bmpName)); - pnl.m_bitmapStatus->Show(); - pnl.m_bitmapStatus->SetToolTip(tooltip); - }; - switch (finalResult) - { - case RESULT_ABORTED: - setStatusBitmap(L"status_aborted", _("Synchronization stopped")); - break; - - case RESULT_FINISHED_WITH_ERROR: - setStatusBitmap(L"status_finished_errors", _("Synchronization completed with errors")); - break; - - case RESULT_FINISHED_WITH_WARNINGS: - setStatusBitmap(L"status_finished_warnings", _("Synchronization completed with warnings")); - break; - - case RESULT_FINISHED_WITH_SUCCESS: - setStatusBitmap(L"status_finished_success", _("Synchronization completed successfully")); - break; - } - } - - //show status on Windows 7 taskbar - if (taskbar_.get()) - { - if (syncStat_) //sync running - { - if (paused_) - taskbar_->setStatus(Taskbar::STATUS_PAUSED); - else - switch (syncStat_->currentPhase()) - { - case ProcessCallback::PHASE_NONE: - case ProcessCallback::PHASE_SCANNING: - taskbar_->setStatus(Taskbar::STATUS_INDETERMINATE); - break; - - case ProcessCallback::PHASE_COMPARING_CONTENT: - case ProcessCallback::PHASE_SYNCHRONIZING: - taskbar_->setStatus(Taskbar::STATUS_NORMAL); - break; - } - } - else //sync finished - switch (finalResult) - { - case RESULT_ABORTED: - case RESULT_FINISHED_WITH_ERROR: - taskbar_->setStatus(Taskbar::STATUS_ERROR); - break; - - case RESULT_FINISHED_WITH_WARNINGS: - case RESULT_FINISHED_WITH_SUCCESS: - taskbar_->setStatus(Taskbar::STATUS_NORMAL); - break; - } - } - - //pause button - if (syncStat_) //sync running - pnl.m_buttonPause->SetLabel(paused_ ? _("&Continue") : _("&Pause")); - - pnl.Layout(); - this->Refresh(); //a few pixels below the status text need refreshing -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::closeWindowDirectly() //this should really be called: do not call back + schedule deletion -{ - paused_ = false; //you never know? - //ATTENTION: dialog may live a little longer, so watch callbacks! - //e.g. wxGTK calls OnIconize after wxWindow::Close() (better not ask why) and before physical destruction! => indirectly calls updateDialogStatus(), which reads syncStat_!!! - syncStat_ = nullptr; - abortCb_ = nullptr; - //resumeFromSystray(); -> NO, instead ~SyncProgressDialogImpl() makes sure that main dialog is shown again! - - this->Close(); //generate close event: do NOT destroy window unconditionally! -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::processHasFinished(SyncResult resultId, const ErrorLog& log) //essential to call this in StatusHandler derived class destructor -{ - //at the LATEST(!) to prevent access to currentStatusHandler - //enable okay and close events; may be set in this method ONLY - -#if (defined __WXGTK__ || defined __WXOSX__) - //In wxWidgets 2.9.3 upwards, the wxWindow::Reparent() below fails on GTK and OS X if window is frozen! http://forums.codeblocks.org/index.php?topic=13388.45 -#else - wxWindowUpdateLocker dummy(this); //badly needed on Windows -#endif - - paused_ = false; //you never know? - - //update numbers one last time (as if sync were still running) - notifyProgressChange(); //make one last graph entry at the *current* time - updateGuiInt(false); - - switch (syncStat_->currentPhase()) //no matter if paused or not - { - case ProcessCallback::PHASE_NONE: - case ProcessCallback::PHASE_SCANNING: - //set overall speed -> not needed - //items processed -> not needed - break; - - case ProcessCallback::PHASE_COMPARING_CONTENT: - case ProcessCallback::PHASE_SYNCHRONIZING: - { - const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase()); - const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase()); - const Int64 dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase()); - const Int64 dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase()); - assert(dataCurrent <= dataTotal); - - //set overall speed (instead of current speed) - const long timeDelta = timeElapsed.Time() - phaseStartMs; //we need to consider "time within current phase" not total "timeElapsed"! - - const wxString overallBytesPerSecond = timeDelta == 0 ? wxString() : filesizeToShortString(dataCurrent * 1000 / timeDelta) + _("/sec"); - const wxString overallItemsPerSecond = timeDelta == 0 ? wxString() : replaceCpy(_("%x items/sec"), L"%x", formatThreeDigitPrecision(itemsCurrent * 1000.0 / timeDelta)); - - pnl.m_panelGraphBytes->setAttributes(pnl.m_panelGraphBytes->getAttributes().setCornerText(overallBytesPerSecond, Graph2D::CORNER_TOP_LEFT)); - pnl.m_panelGraphItems->setAttributes(pnl.m_panelGraphItems->getAttributes().setCornerText(overallItemsPerSecond, Graph2D::CORNER_TOP_LEFT)); - - //show new element "items processed" - pnl.m_panelItemsProcessed->Show(); - pnl.m_staticTextProcessedObj ->SetLabel(toGuiString(itemsCurrent)); - pnl.m_staticTextDataProcessed->SetLabel(L"(" + filesizeToShortString(dataCurrent) + L")"); - - //hide remaining elements... - if (itemsCurrent == itemsTotal && //...if everything was processed successfully - dataCurrent == dataTotal) - pnl.m_panelItemsRemaining->Hide(); - } - break; - } - - //------- change class state ------- - finalResult = resultId; - - syncStat_ = nullptr; - abortCb_ = nullptr; - //---------------------------------- - - updateDialogStatus(); - setExternalStatus(getDialogPhaseText(syncStat_, paused_, finalResult), wxString()); - - resumeFromSystray(); //if in tray mode... - - this->EnableCloseButton(true); - - pnl.m_bpButtonMinimizeToTray->Hide(); - pnl.m_buttonStop->Disable(); - pnl.m_buttonStop->Hide(); - pnl.m_buttonPause->Disable(); - pnl.m_buttonPause->Hide(); - pnl.m_buttonClose->Show(); - pnl.m_buttonClose->Enable(); - - pnl.m_buttonClose->SetFocus(); - - pnl.bSizerExecFinished->Show(false); - - //set std order after button visibility was set - setStandardButtonOrder(*pnl.bSizerStdButtons, StdButtons().setAffirmative(pnl.m_buttonClose)); - - //hide current operation status - pnl.bSizerStatusText->Show(false); - - //show and prepare final statistics - pnl.m_notebookResult->Show(); - -#if defined ZEN_WIN || defined ZEN_LINUX - pnl.m_staticlineFooter->Hide(); //win: m_notebookResult already has a window frame -#endif - - //hide remaining time - pnl.m_panelTimeRemaining->Hide(); - - //1. re-arrange graph into results listbook - const bool wasDetached = pnl.bSizerRoot->Detach(pnl.m_panelProgress); - assert(wasDetached); - (void)wasDetached; - pnl.m_panelProgress->Reparent(pnl.m_notebookResult); - pnl.m_notebookResult->AddPage(pnl.m_panelProgress, _("Statistics"), true); - - //2. log file - const size_t posLog = 1; - assert(pnl.m_notebookResult->GetPageCount() == 1); - LogPanel* logPanel = new LogPanel(pnl.m_notebookResult, log); //owned by m_notebookResult - pnl.m_notebookResult->AddPage(logPanel, _("Log"), false); - //bSizerHoldStretch->Insert(0, logPanel, 1, wxEXPAND); - - //show log instead of graph if errors occurred! (not required for ignored warnings) - if (log.getItemCount(TYPE_ERROR | TYPE_FATAL_ERROR) > 0) - pnl.m_notebookResult->ChangeSelection(posLog); - - //GetSizer()->SetSizeHints(this); //~=Fit() //not a good idea: will shrink even if window is maximized or was enlarged by the user - pnl.Layout(); - - pnl.m_panelProgress->Layout(); - //small statistics panels: - pnl.m_panelItemsProcessed->Layout(); - pnl.m_panelItemsRemaining->Layout(); - //pnl.m_panelTimeRemaining->Layout(); - //pnl.m_panelTimeElapsed->Layout(); -> needed? - - //play (optional) sound notification after sync has completed -> only play when waiting on results dialog, seems to be pointless otherwise! - switch (finalResult) - { - case SyncProgressDialog::RESULT_ABORTED: - break; - case SyncProgressDialog::RESULT_FINISHED_WITH_ERROR: - case SyncProgressDialog::RESULT_FINISHED_WITH_WARNINGS: - case SyncProgressDialog::RESULT_FINISHED_WITH_SUCCESS: - { - const Zstring soundFile = getResourceDir() + Zstr("Sync_Complete.wav"); - if (fileExists(soundFile)) - wxSound::Play(utfCvrtTo<wxString>(soundFile), wxSOUND_ASYNC); //warning: this may fail and show a wxWidgets error message! => must not play when running FFS as a service! - } - break; - } - - //Raise(); -> don't! user may be watching a movie in the meantime ;) note: resumeFromSystray() also calls Raise()! -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::OnOkay(wxCommandEvent& event) -{ - this->Close(); //generate close event: do NOT destroy window unconditionally! -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::OnCancel(wxCommandEvent& event) -{ - paused_ = false; - updateDialogStatus(); //update status + pause button - - //no Layout() or UI-update here to avoid cascaded Yield()-call - if (abortCb_) - abortCb_->requestAbortion(); -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::OnPause(wxCommandEvent& event) -{ - paused_ = !paused_; - updateDialogStatus(); //update status + pause button -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::OnClose(wxCloseEvent& event) -{ - //this event handler may be called *during* sync, e.g. due to a system shutdown (Windows), anytime (OS X) - //try to stop sync gracefully and cross fingers: - if (abortCb_) - abortCb_->requestAbortion(); - //Note: we must NOT veto dialog destruction, else we will cancel system shutdown if this dialog is application main window (like in batch mode) - - notifyWindowTerminate_(); //don't wait until delayed "Destroy()" finally calls destructor -> avoid calls to processHasFinished()/closeWindowDirectly() - - paused_ = false; //[!] we could be pausing here! - - //now that we notified window termination prematurely, and since processHasFinished()/closeWindowDirectly() won't be called, make sure we don't call back, too! - //e.g. the second notifyWindowTerminate_() in ~SyncProgressDialogImpl()!!! - syncStat_ = nullptr; - abortCb_ = nullptr; - - wereDead = true; - this->Destroy(); //wxWidgets OS X: simple "delete"!!!!!!! -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::OnIconize(wxIconizeEvent& event) -{ - /* - propagate progress dialog minimize/maximize to parent - ----------------------------------------------------- - Fedora/Debian/Ubuntu: - - wxDialog cannot be minimized - - worse, wxGTK sends stray iconize events *after* wxDialog::Destroy() - - worse, on Fedora an iconize event is issued directly after calling Close() - - worse, even wxDialog::Hide() causes iconize event! - => nothing to do - SUSE: - - wxDialog can be minimized (it just vanishes!) and in general also minimizes parent: except for our progress wxDialog!!! - - worse, wxDialog::Hide() causes iconize event - - probably the same issues with stray iconize events like Fedora/Debian/Ubuntu - - minimize button is always shown, even if wxMINIMIZE_BOX is omitted! - => nothing to do - Mac OS X: - - wxDialog can be minimized and automatically minimizes parent - - no iconize events seen by wxWidgets! - => nothing to do - Windows: - - wxDialog can be minimized but does not also minimize parent - - iconize events only seen for manual minimize - => propagate event to parent - */ -#ifdef ZEN_WIN - if (parentFrame_) - if (parentFrame_->IsIconized() != event.IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize! - parentFrame_->Iconize(event.IsIconized()); -#endif - event.Skip(); -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::minimizeToTray() -{ - if (!trayIcon.get()) - { - trayIcon = make_unique<FfsTrayIcon>([this] { this->resumeFromSystray(); }); //FfsTrayIcon lifetime is a subset of "this"'s lifetime! - //we may destroy FfsTrayIcon even while in the FfsTrayIcon callback!!!! - - updateGuiInt(false); //set tray tooltip + progress: e.g. no updates while paused - - this->Hide(); - if (parentFrame_) - parentFrame_->Hide(); -#ifdef ZEN_MAC - //hide dock icon: else user is able to forcefully show the hidden main dialog by clicking on the icon!! - ProcessSerialNumber psn = { 0, kCurrentProcess }; - ::TransformProcessType(&psn, kProcessTransformToUIElementApplication); -#endif - } -} - - -template <class TopLevelDialog> -void SyncProgressDialogImpl<TopLevelDialog>::resumeFromSystray() -{ - if (trayIcon) - { - trayIcon.reset(); - - if (parentFrame_) - { - //if (parentFrame_->IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize! - // parentFrame_->Iconize(false); - parentFrame_->Show(); - parentFrame_->Raise(); - } - - //if (IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize! - // Iconize(false); - this->Show(); - this->Raise(); - this->SetFocus(); - - updateDialogStatus(); //restore Windows 7 task bar status (e.g. required in pause mode) - updateGuiInt(false); //restore Windows 7 task bar progress (e.g. required in pause mode) - -#ifdef ZEN_MAC - ProcessSerialNumber psn = { 0, kCurrentProcess }; - ::SetFrontProcess(&psn); //call before TransformProcessType() so that OSX menu is updated correctly - //why isn't this covered by wxWindows::Raise()?? - ::TransformProcessType(&psn, kProcessTransformToForegroundApplication); //show dock icon again -#endif - } -} - -//######################################################################################## - -SyncProgressDialog* createProgressDialog(zen::AbortCallback& abortCb, - const std::function<void()>& notifyWindowTerminate, //note: user closing window cannot be prevented on OS X! (And neither on Windows during system shutdown!) - const zen::Statistics& syncStat, - wxFrame* parentWindow, //may be nullptr - bool showProgress, - const wxString& jobName, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory) -{ - if (parentWindow) //sync from GUI - return new SyncProgressDialogImpl<wxDialog>(wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER, - [&](wxDialog& progDlg) { return parentWindow; }, abortCb, - notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, execWhenFinished, execFinishedHistory); - else //FFS batch job - { - auto dlg = new SyncProgressDialogImpl<wxFrame>(wxDEFAULT_FRAME_STYLE, - [](wxFrame& progDlg) { return &progDlg; }, abortCb, - notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, execWhenFinished, execFinishedHistory); - - //only top level windows should have an icon: - dlg->SetIcon(getFfsIcon()); - return dlg; - } -} diff --git a/ui/progress_indicator.h b/ui/progress_indicator.h deleted file mode 100644 index e2dbb99c..00000000 --- a/ui/progress_indicator.h +++ /dev/null @@ -1,92 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef PROGRESSINDICATOR_H_INCLUDED -#define PROGRESSINDICATOR_H_INCLUDED - -#include <functional> -#include <zen/error_log.h> -//#include <zen/zstring.h> -#include <wx/frame.h> -#include "../lib/status_handler.h" -//#include "main_dlg.h" - - -class CompareProgressDialog -{ -public: - CompareProgressDialog(wxFrame& parentWindow); //CompareProgressDialog will be owned by parentWindow! - - wxWindow* getAsWindow(); //convenience! don't abuse! - - void init(const zen::Statistics& syncStat); //begin of sync: make visible, set pointer to "syncStat", initialize all status values - void finalize(); //end of sync: hide again, clear pointer to "syncStat" - - void switchToCompareBytewise(); - void updateStatusPanelNow(); - -private: - class Pimpl; - Pimpl* const pimpl; -}; - - -//SyncStatusHandler will internally process Window messages => disable GUI controls to avoid unexpected callbacks! - -struct SyncProgressDialog -{ - enum SyncResult - { - RESULT_ABORTED, - RESULT_FINISHED_WITH_ERROR, - RESULT_FINISHED_WITH_WARNINGS, - RESULT_FINISHED_WITH_SUCCESS - }; - //essential to call one of these two methods in StatusUpdater derived class' destructor at the LATEST(!) - //to prevent access to callback to updater (e.g. request abort) - virtual void processHasFinished(SyncResult resultId, const zen::ErrorLog& log) = 0; //sync finished, still dialog may live on - virtual void closeWindowDirectly() = 0; //don't wait for user - - //--------------------------------------------------------------------------- - - virtual wxWindow* getWindowIfVisible() = 0; //may be nullptr; don't abuse, use as parent for modal dialogs only! - - virtual void initNewPhase() = 0; //call after "StatusHandler::initNewPhase" - virtual void notifyProgressChange() = 0; //throw (), required by graph! - virtual void updateGui() = 0; //update GUI and process Window messages - - virtual std::wstring getExecWhenFinishedCommand() const = 0; //final value (after possible user modification) - - virtual void stopTimer() = 0; //halt all internal timers! - virtual void resumeTimer() = 0; // - -protected: - ~SyncProgressDialog() {} -}; - - -SyncProgressDialog* createProgressDialog(zen::AbortCallback& abortCb, - const std::function<void()>& notifyWindowTerminate, //note: user closing window cannot be prevented on OS X! (And neither on Windows during system shutdown!) - const zen::Statistics& syncStat, - wxFrame* parentWindow, //may be nullptr - bool showProgress, - const wxString& jobName, - const std::wstring& execWhenFinished, - std::vector<std::wstring>& execFinishedHistory); //changing parameter! -//DON'T delete the pointer! it will be deleted by the user clicking "OK/Cancel"/wxWindow::Destroy() after processHasFinished() or closeWindowDirectly() - - -class PauseTimers -{ -public: - PauseTimers(SyncProgressDialog& ss) : ss_(ss) { ss_.stopTimer(); } - ~PauseTimers() { ss_.resumeTimer(); } -private: - SyncProgressDialog& ss_; -}; - - -#endif // PROGRESSINDICATOR_H_INCLUDED diff --git a/ui/search.cpp b/ui/search.cpp deleted file mode 100644 index c834b934..00000000 --- a/ui/search.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "search.h" -#include <zen/string_tools.h> - - -using namespace zen; - -namespace -{ -template <bool respectCase> -class ContainsMatch -{ -public: - ContainsMatch(const wxString& textToFind) : textToFind_(textToFind) {} - bool operator()(const wxString& phrase) const { return contains(phrase, textToFind_); } - -private: - wxString textToFind_; -}; - - -template <> -class ContainsMatch<false> -{ -public: - ContainsMatch(const wxString& textToFind) : textToFind_(textToFind) { textToFind_.MakeUpper(); } - bool operator()(wxString&& phrase) const - { - //wxWidgets::MakeUpper() is inefficient! But performance is not THAT important for this high-level search functionality - phrase.MakeUpper(); - return contains(phrase, textToFind_); - } - -private: - wxString textToFind_; -}; - -//########################################################################################### - -template <bool respectCase> -ptrdiff_t findRow(const Grid& grid, //return -1 if no matching row found - const wxString& searchString, - size_t rowFirst, //specify area to search: - size_t rowLast) // [rowFirst, rowLast) -{ - if (auto prov = grid.getDataProvider()) - { - std::vector<Grid::ColumnAttribute> colAttr = grid.getColumnConfig(); - vector_remove_if(colAttr, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; }); - if (!colAttr.empty()) - { - const ContainsMatch<respectCase> containsMatch(searchString); - - for (size_t row = rowFirst; row < rowLast; ++row) - for (auto iterCol = colAttr.begin(); iterCol != colAttr.end(); ++iterCol) - if (containsMatch(prov->getValue(row, iterCol->type_))) - return row; - } - } - return -1; -} -} - - -std::pair<const Grid*, ptrdiff_t> zen::findGridMatch(const Grid& grid1, const Grid& grid2, const wxString& searchString, bool respectCase) -{ - const size_t rowCountL = grid1.getRowCount(); - const size_t rowCountR = grid2.getRowCount(); - auto cursorPos = grid1.getGridCursor(); //(row, component pos) - - std::pair<const Grid*, ptrdiff_t> result(nullptr, -1); - - size_t cursorRowL = cursorPos.first; - if (cursorRowL >= rowCountL) - cursorRowL = 0; - { - auto finishSearch = [&](const Grid& grid, size_t rowFirst, size_t rowLast) -> bool - { - const ptrdiff_t targetRow = respectCase ? - findRow<true>( grid, searchString, rowFirst, rowLast) : - findRow<false>(grid, searchString, rowFirst, rowLast); - if (targetRow >= 0) - { - result = std::make_pair(&grid, targetRow); - return true; - } - return false; - }; - - if (!finishSearch(grid1, cursorRowL + 1, rowCountL)) - if (!finishSearch(grid2, 0, rowCountR)) - finishSearch(grid1, 0, cursorRowL + 1); - } - return result; -}
\ No newline at end of file diff --git a/ui/search.h b/ui/search.h deleted file mode 100644 index 1adf3d01..00000000 --- a/ui/search.h +++ /dev/null @@ -1,18 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef SEARCH_H_423905762345342526587 -#define SEARCH_H_423905762345342526587 - -#include <wx+/grid.h> - -namespace zen -{ -std::pair<const Grid*, ptrdiff_t> findGridMatch(const Grid& grid1, const Grid& grid2, const wxString& searchString, bool respectCase); -//returns (grid/row) where the value was found, (nullptr, -1) if not found -} - -#endif //SEARCH_H_423905762345342526587 diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp deleted file mode 100644 index df2e3e7a..00000000 --- a/ui/small_dlgs.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "small_dlgs.h" -#include <wx/wupdlock.h> -#include <zen/format_unit.h> -#include <zen/build_info.h> -#include <zen/tick_count.h> -#include <zen/stl_tools.h> -#include <wx+/choice_enum.h> -#include <wx+/bitmap_button.h> -#include <wx+/rtl.h> -#include <wx+/no_flicker.h> -#include <wx+/mouse_move_dlg.h> -#include <wx+/image_tools.h> -#include <wx+/font_size.h> -#include <wx+/std_button_order.h> -#include <wx+/popup_dlg.h> -#include <wx+/image_resources.h> -#include "gui_generated.h" -#include "custom_grid.h" -#include "../algorithm.h" -#include "../synchronization.h" -#include "../lib/help_provider.h" -#include "../lib/hard_filter.h" -#include "../version/version.h" - -using namespace zen; - - -class AboutDlg : public AboutDlgGenerated -{ -public: - AboutDlg(wxWindow* parent); - -private: - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnOK (wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_OKAY); } - virtual void OnDonate(wxCommandEvent& event) { wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/donate.php"); } -}; - - -AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent) -{ - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonClose)); - - setRelativeFontSize(*m_buttonDonate, 1.25); - - assert(m_buttonClose->GetId() == wxID_OK); //we cannot use wxID_CLOSE else Esc key won't work: yet another wxWidgets bug?? - - m_bitmap9 ->SetBitmap(getResourceImage(L"website")); - m_bitmap10->SetBitmap(getResourceImage(L"email")); - m_bitmap13->SetBitmap(getResourceImage(L"gpl")); - //m_bitmapSmiley->SetBitmap(getResourceImage(L"smiley")); - - m_animCtrlWink->SetAnimation(getResourceAnimation(L"wink")); - m_animCtrlWink->Play(); - - //create language credits - for (auto it = ExistingTranslations::get().begin(); it != ExistingTranslations::get().end(); ++it) - { - //flag - wxStaticBitmap* staticBitmapFlag = new wxStaticBitmap(m_scrolledWindowTranslators, wxID_ANY, getResourceImage(it->languageFlag), wxDefaultPosition, wxSize(-1, 11), 0 ); - fgSizerTranslators->Add(staticBitmapFlag, 0, wxALIGN_CENTER); - - //translator name - wxStaticText* staticTextTranslator = new wxStaticText(m_scrolledWindowTranslators, wxID_ANY, it->translatorName, wxDefaultPosition, wxDefaultSize, 0 ); - staticTextTranslator->Wrap(-1); - fgSizerTranslators->Add(staticTextTranslator, 0, wxALIGN_CENTER_VERTICAL); - - staticBitmapFlag ->SetToolTip(it->languageName); - staticTextTranslator->SetToolTip(it->languageName); - } - fgSizerTranslators->Fit(m_scrolledWindowTranslators); - -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //-> put *after* creating credits -#endif - - //build information - wxString build = __TDATE__; -#if wxUSE_UNICODE - build += L" - Unicode"; -#else - build += L" - ANSI"; -#endif //wxUSE_UNICODE - - //compile time info about 32/64-bit build - if (zen::is64BitBuild) - build += L" x64"; - else - build += L" x86"; - assert_static(zen::is32BitBuild || zen::is64BitBuild); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - - //generate logo: put *after* first Fit() - Layout(); //make sure m_panelLogo has final width (required by wxGTK) - - wxBitmap bmpLogo; - { - wxImage tmp = getResourceImage(L"logo").ConvertToImage(); - tmp.Resize(wxSize(GetClientSize().GetWidth(), tmp.GetHeight()), wxPoint(0, 0), 255, 255, 255); //enlarge to fit full width - bmpLogo = wxBitmap(tmp); - } - { - wxMemoryDC dc(bmpLogo); - - wxImage labelImage = createImageFromText(wxString(L"FreeFileSync ") + zen::currentVersion, - wxFont(wxNORMAL_FONT->GetPointSize() * 1.8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, L"Tahoma"), - *wxBLACK); //accessibility: align foreground/background colors! - wxImage buildImage = createImageFromText(replaceCpy(_("Build: %x"), L"%x", build), - *wxNORMAL_FONT, - *wxBLACK); - wxImage dynImage = stackImages(labelImage, buildImage, ImageStackLayout::VERTICAL, ImageStackAlignment::CENTER, 0); - - dc.DrawBitmap(dynImage, wxPoint((bmpLogo.GetWidth () - dynImage.GetWidth ()) / 2, - (bmpLogo.GetHeight() - dynImage.GetHeight()) / 2)); - } - m_bitmapLogo->SetBitmap(bmpLogo); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - m_buttonClose->SetFocus(); //on GTK ESC is only associated with wxID_OK correctly if we set at least *any* focus at all!!! -} - - -void zen::showAboutDialog(wxWindow* parent) -{ - AboutDlg aboutDlg(parent); - aboutDlg.ShowModal(); -} - -//######################################################################################## - -class FilterDlg : public FilterDlgGenerated -{ -public: - FilterDlg(wxWindow* parent, - FilterConfig& filter, - const wxString& title); - ~FilterDlg() {} - -private: - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnHelpShowExamples(wxHyperlinkEvent& event) { displayHelpEntry(L"html/Exclude Items.html", this); } - virtual void OnClear (wxCommandEvent& event); - virtual void OnOkay (wxCommandEvent& event); - virtual void OnUpdateChoice(wxCommandEvent& event) { updateGui(); } - virtual void OnUpdateNameFilter(wxCommandEvent& event) { updateGui(); } - - void updateGui(); - void setFilter(const FilterConfig& filter); - FilterConfig getFilter() const; - void onKeyEvent(wxKeyEvent& event); - - FilterConfig& outputRef; - - EnumDescrList<UnitTime> enumTimeDescr; - EnumDescrList<UnitSize> enumSizeDescr; -}; - - -FilterDlg::FilterDlg(wxWindow* parent, - FilterConfig& filter, - const wxString& title) : - FilterDlgGenerated(parent), - outputRef(filter) //just hold reference -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOk).setCancel(m_buttonCancel)); - - SetTitle(title); - -#ifndef __WXGTK__ //wxWidgets holds portability promise by not supporting for multi-line controls...not - m_textCtrlInclude->SetMaxLength(0); //allow large filter entries! - m_textCtrlExclude->SetMaxLength(0); // -#endif - - m_textCtrlInclude->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(FilterDlg::onKeyEvent), nullptr, this); - m_textCtrlExclude->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(FilterDlg::onKeyEvent), nullptr, this); - - enumTimeDescr. - add(UTIME_NONE, L"(" + _("None") + L")"). //meta options should be enclosed in parentheses - add(UTIME_TODAY, _("Today")). - // add(UTIME_THIS_WEEK, _("This week")). - add(UTIME_THIS_MONTH, _("This month")). - add(UTIME_THIS_YEAR, _("This year")). - add(UTIME_LAST_X_DAYS, _("Last x days")); - - enumSizeDescr. - add(USIZE_NONE, L"(" + _("None") + L")"). //meta options should be enclosed in parentheses - add(USIZE_BYTE, _("Byte")). - add(USIZE_KB, _("KB")). - add(USIZE_MB, _("MB")); - - m_bitmapFilter->SetBitmap(getResourceImage(L"filter")); - - setFilter(filter); - - m_buttonOk->SetFocus(); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - Layout(); -} - - -void FilterDlg::onKeyEvent(wxKeyEvent& event) -{ - const int keyCode = event.GetKeyCode(); - - if (event.ControlDown()) - switch (keyCode) - { - case 'A': //CTRL + A - if (auto textCtrl = dynamic_cast<wxTextCtrl*>(event.GetEventObject())) - textCtrl->SetSelection(-1, -1); //select all - return; - } - event.Skip(); -} - - -void FilterDlg::updateGui() -{ - FilterConfig activeCfg = getFilter(); - - auto setStatusBitmap = [&](wxStaticBitmap& staticBmp, const wxString& bmpName, bool active) - { - if (active) - staticBmp.SetBitmap(getResourceImage(bmpName)); - else - staticBmp.SetBitmap(greyScale(getResourceImage(bmpName))); - }; - setStatusBitmap(*m_bitmapInclude, L"filter_include", !NameFilter::isNull(activeCfg.includeFilter, FilterConfig().excludeFilter)); - setStatusBitmap(*m_bitmapExclude, L"filter_exclude", !NameFilter::isNull(FilterConfig().includeFilter, activeCfg.excludeFilter)); - setStatusBitmap(*m_bitmapFilterDate, L"clock", activeCfg.unitTimeSpan != UTIME_NONE); - setStatusBitmap(*m_bitmapFilterSize, L"size", activeCfg.unitSizeMin != USIZE_NONE || activeCfg.unitSizeMax != USIZE_NONE); - - m_spinCtrlTimespan->Enable(activeCfg.unitTimeSpan == UTIME_LAST_X_DAYS); - m_spinCtrlMinSize ->Enable(activeCfg.unitSizeMin != USIZE_NONE); - m_spinCtrlMaxSize ->Enable(activeCfg.unitSizeMax != USIZE_NONE); - - m_buttonClear->Enable(!(activeCfg == FilterConfig())); -} - - -void FilterDlg::setFilter(const FilterConfig& filter) -{ - m_textCtrlInclude->ChangeValue(utfCvrtTo<wxString>(filter.includeFilter)); - m_textCtrlExclude->ChangeValue(utfCvrtTo<wxString>(filter.excludeFilter)); - - setEnumVal(enumTimeDescr, *m_choiceUnitTimespan, filter.unitTimeSpan); - setEnumVal(enumSizeDescr, *m_choiceUnitMinSize, filter.unitSizeMin); - setEnumVal(enumSizeDescr, *m_choiceUnitMaxSize, filter.unitSizeMax); - - m_spinCtrlTimespan->SetValue(static_cast<int>(filter.timeSpan)); - m_spinCtrlMinSize ->SetValue(static_cast<int>(filter.sizeMin)); - m_spinCtrlMaxSize ->SetValue(static_cast<int>(filter.sizeMax)); - - updateGui(); -} - - -FilterConfig FilterDlg::getFilter() const -{ - return FilterConfig(utfCvrtTo<Zstring>(m_textCtrlInclude->GetValue()), - utfCvrtTo<Zstring>(m_textCtrlExclude->GetValue()), - m_spinCtrlTimespan->GetValue(), - getEnumVal(enumTimeDescr, *m_choiceUnitTimespan), - m_spinCtrlMinSize->GetValue(), - getEnumVal(enumSizeDescr, *m_choiceUnitMinSize), - m_spinCtrlMaxSize->GetValue(), - getEnumVal(enumSizeDescr, *m_choiceUnitMaxSize)); -} - - -void FilterDlg::OnClear(wxCommandEvent& event) -{ - setFilter(FilterConfig()); -} - - -void FilterDlg::OnOkay(wxCommandEvent& event) -{ - FilterConfig cfg = getFilter(); - - //parameter validation: - - //include filter must not be empty: - { - Zstring tmp = cfg.includeFilter; - trim(tmp); - if (tmp.empty()) - cfg.includeFilter = FilterConfig().includeFilter; //no need to show error message, just correct user input - } - - //apply config: - outputRef = cfg; - - //when leaving dialog: filter and redraw grid, if filter is active - EndModal(ReturnSmallDlg::BUTTON_OKAY); -} - - -ReturnSmallDlg::ButtonPressed zen::showFilterDialog(wxWindow* parent, FilterConfig& filter, const wxString& title) -{ - FilterDlg filterDlg(parent, - filter, - title); - return static_cast<ReturnSmallDlg::ButtonPressed>(filterDlg.ShowModal()); -} - -//######################################################################################## - -class DeleteDialog : public DeleteDlgGenerated -{ -public: - DeleteDialog(wxWindow* parent, - const std::vector<zen::FileSystemObject*>& rowsOnLeft, - const std::vector<zen::FileSystemObject*>& rowsOnRight, - bool& deleteOnBothSides, - bool& useRecycleBin); - -private: - virtual void OnOK(wxCommandEvent& event); - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnDelOnBothSides(wxCommandEvent& event); - virtual void OnUseRecycler(wxCommandEvent& event); - - void updateGui(); - - const std::vector<zen::FileSystemObject*>& rowsToDeleteOnLeft; - const std::vector<zen::FileSystemObject*>& rowsToDeleteOnRight; - bool& outRefdeleteOnBothSides; - bool& outRefuseRecycleBin; - const TickVal tickCountStartup; -}; - - -DeleteDialog::DeleteDialog(wxWindow* parent, - const std::vector<FileSystemObject*>& rowsOnLeft, - const std::vector<FileSystemObject*>& rowsOnRight, - bool& deleteOnBothSides, - bool& useRecycleBin) : - DeleteDlgGenerated(parent), - rowsToDeleteOnLeft(rowsOnLeft), - rowsToDeleteOnRight(rowsOnRight), - outRefdeleteOnBothSides(deleteOnBothSides), - outRefuseRecycleBin(useRecycleBin), - tickCountStartup(getTicks()) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOK).setCancel(m_buttonCancel)); - - setMainInstructionFont(*m_staticTextHeader); - - m_checkBoxDeleteBothSides->SetValue(deleteOnBothSides); - m_checkBoxUseRecycler->SetValue(useRecycleBin); - - //if both sides contain same rows this checkbox is superfluous - if (rowsToDeleteOnLeft == rowsToDeleteOnRight) - { - m_checkBoxDeleteBothSides->Show(false); - m_checkBoxDeleteBothSides->SetValue(true); - } - -#ifndef __WXGTK__ //wxWidgets holds portability promise by not supporting for multi-line controls...not - m_textCtrlFileList->SetMaxLength(0); //allow large entries! -#endif - - updateGui(); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - Layout(); - - m_buttonOK->SetFocus(); -} - - -void DeleteDialog::updateGui() -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - const std::pair<Zstring, int> delInfo = zen::deleteFromGridAndHDPreview(rowsToDeleteOnLeft, - rowsToDeleteOnRight, - m_checkBoxDeleteBothSides->GetValue()); - wxString header; - if (m_checkBoxUseRecycler->GetValue()) - { - header = _P("Do you really want to move the following item to the recycle bin?", - "Do you really want to move the following %x items to the recycle bin?", delInfo.second); - m_bitmapDeleteType->SetBitmap(getResourceImage(L"delete_recycler")); - m_buttonOK->SetLabel(_("Move")); //no access key needed: use ENTER! - } - else - { - header = _P("Do you really want to delete the following item?", - "Do you really want to delete the following %x items?", delInfo.second); - m_bitmapDeleteType->SetBitmap(getResourceImage(L"delete_permanently")); - m_buttonOK->SetLabel(_("Delete")); - } - m_staticTextHeader->SetLabel(header); - //it seems like Wrap() needs to be reapplied after SetLabel() - m_staticTextHeader->Wrap(460); - - const wxString& fileList = utfCvrtTo<wxString>(delInfo.first); - m_textCtrlFileList->ChangeValue(fileList); - /* - There is a nasty bug on wxGTK under Ubuntu: If a multi-line wxTextCtrl contains so many lines that scrollbars are shown, - it re-enables all windows that are supposed to be disabled during the current modal loop! - This only affects Ubuntu/wxGTK! No such issue on Debian/wxGTK or Suse/wxGTK - => another Unity problem like the following? - http://trac.wxwidgets.org/ticket/14823 "Menu not disabled when showing modal dialogs in wxGTK under Unity" - */ - - Layout(); - Refresh(); //needed after m_buttonOK label change -} - - -void DeleteDialog::OnOK(wxCommandEvent& event) -{ - //additional safety net, similar to Windows Explorer: time delta between DEL and ENTER must be at least 50ms to avoid accidental deletion! - const TickVal now = getTicks(); //0 on error - std::int64_t tps = ticksPerSec(); // - if (now.isValid() && tickCountStartup.isValid() && tps != 0) - if (dist(tickCountStartup, now) * 1000 / tps < 50) - return; - - outRefuseRecycleBin = m_checkBoxUseRecycler->GetValue(); - if (rowsToDeleteOnLeft != rowsToDeleteOnRight) - outRefdeleteOnBothSides = m_checkBoxDeleteBothSides->GetValue(); - - EndModal(ReturnSmallDlg::BUTTON_OKAY); -} - -void DeleteDialog::OnDelOnBothSides(wxCommandEvent& event) -{ - updateGui(); -} - -void DeleteDialog::OnUseRecycler(wxCommandEvent& event) -{ - updateGui(); -} - - -ReturnSmallDlg::ButtonPressed zen::showDeleteDialog(wxWindow* parent, - const std::vector<zen::FileSystemObject*>& rowsOnLeft, - const std::vector<zen::FileSystemObject*>& rowsOnRight, - bool& deleteOnBothSides, - bool& useRecycleBin) -{ - DeleteDialog confirmDeletion(parent, - rowsOnLeft, - rowsOnRight, - deleteOnBothSides, - useRecycleBin); - return static_cast<ReturnSmallDlg::ButtonPressed>(confirmDeletion.ShowModal()); -} - -//######################################################################################## - -class SyncConfirmationDlg : public SyncConfirmationDlgGenerated -{ -public: - SyncConfirmationDlg(wxWindow* parent, - const wxString& variantName, - const zen::SyncStatistics& st, - bool& dontShowAgain); -private: - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnStartSync(wxCommandEvent& event); - - bool& m_dontShowAgain; -}; - - -SyncConfirmationDlg::SyncConfirmationDlg(wxWindow* parent, - const wxString& variantName, - const SyncStatistics& st, - bool& dontShowAgain) : - SyncConfirmationDlgGenerated(parent), - m_dontShowAgain(dontShowAgain) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonStartSync).setCancel(m_buttonCancel)); - - setMainInstructionFont(*m_staticTextHeader); - m_bitmapSync->SetBitmap(getResourceImage(L"sync")); - - m_staticTextVariant->SetLabel(variantName); - m_checkBoxDontShowAgain->SetValue(dontShowAgain); - - //update preview of item count and bytes to be transferred: - setText(*m_staticTextData, filesizeToShortString(st.getDataToProcess())); - if (st.getDataToProcess() == 0) - m_bitmapData->SetBitmap(greyScale(getResourceImage(L"data"))); - else - m_bitmapData->SetBitmap(getResourceImage(L"data")); - - auto setValue = [](wxStaticText& txtControl, int value, wxStaticBitmap& bmpControl, const wchar_t* bmpName) - { - setText(txtControl, toGuiString(value)); - - if (value == 0) - bmpControl.SetBitmap(greyScale(mirrorIfRtl(getResourceImage(bmpName)))); - else - bmpControl.SetBitmap(mirrorIfRtl(getResourceImage(bmpName))); - }; - - setValue(*m_staticTextCreateLeft, st.getCreate<LEFT_SIDE >(), *m_bitmapCreateLeft, L"so_create_left_small"); - setValue(*m_staticTextUpdateLeft, st.getUpdate<LEFT_SIDE >(), *m_bitmapUpdateLeft, L"so_update_left_small"); - setValue(*m_staticTextDeleteLeft, st.getDelete<LEFT_SIDE >(), *m_bitmapDeleteLeft, L"so_delete_left_small"); - setValue(*m_staticTextCreateRight, st.getCreate<RIGHT_SIDE>(), *m_bitmapCreateRight, L"so_create_right_small"); - setValue(*m_staticTextUpdateRight, st.getUpdate<RIGHT_SIDE>(), *m_bitmapUpdateRight, L"so_update_right_small"); - setValue(*m_staticTextDeleteRight, st.getDelete<RIGHT_SIDE>(), *m_bitmapDeleteRight, L"so_delete_right_small"); - - m_panelStatistics->Layout(); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - m_buttonStartSync->SetFocus(); -} - - -void SyncConfirmationDlg::OnStartSync(wxCommandEvent& event) -{ - m_dontShowAgain = m_checkBoxDontShowAgain->GetValue(); - EndModal(ReturnSmallDlg::BUTTON_OKAY); -} - - -ReturnSmallDlg::ButtonPressed zen::showSyncConfirmationDlg(wxWindow* parent, - const wxString& variantName, - const zen::SyncStatistics& statistics, - bool& dontShowAgain) -{ - SyncConfirmationDlg dlg(parent, - variantName, - statistics, - dontShowAgain); - return static_cast<ReturnSmallDlg::ButtonPressed>(dlg.ShowModal()); -} - -//######################################################################################## - -class CompareCfgDialog : public CmpCfgDlgGenerated -{ -public: - CompareCfgDialog(wxWindow* parent, CompConfig& cmpConfig, const wxString& caption); - -private: - virtual void OnOkay(wxCommandEvent& event); - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnHelpComparisonSettings(wxHyperlinkEvent& event) { displayHelpEntry(L"html/Comparison Settings.html", this); } - - virtual void OnTimeSize(wxCommandEvent& event) { compareVar = CMP_BY_TIME_SIZE; updateGui(); } - virtual void OnContent (wxCommandEvent& event) { compareVar = CMP_BY_CONTENT; updateGui(); } - - virtual void OnTimeSizeDouble(wxMouseEvent& event); - virtual void OnContentDouble(wxMouseEvent& event); - - void updateGui(); - - CompConfig& cmpConfigOut; //for output only - CompareVariant compareVar; - zen::EnumDescrList<SymLinkHandling> enumDescrHandleSyml; -}; - - -CompareCfgDialog::CompareCfgDialog(wxWindow* parent, - CompConfig& cmpConfig, const wxString& title) : - CmpCfgDlgGenerated(parent), - cmpConfigOut(cmpConfig), - compareVar(cmpConfig.compareVar) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); - - setRelativeFontSize(*m_toggleBtnTimeSize, 1.25); - setRelativeFontSize(*m_toggleBtnContent, 1.25); - - SetTitle(title); - - enumDescrHandleSyml. - add(SYMLINK_EXCLUDE, _("Exclude")). - add(SYMLINK_USE_DIRECTLY, _("Direct")). - add(SYMLINK_FOLLOW_LINK, _("Follow")); - - setEnumVal(enumDescrHandleSyml, *m_choiceHandleSymlinks, cmpConfig.handleSymlinks); - - //move dialog up so that compare-config button and first config-variant are on same level - // Move(wxPoint(position.x, std::max(0, position.y - (m_buttonTimeSize->GetScreenPosition() - GetScreenPosition()).y))); - - updateGui(); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - m_buttonOkay->SetFocus(); -} - - -void CompareCfgDialog::updateGui() -{ - //update toggle buttons -> they have no parameter-ownership at all! - m_toggleBtnTimeSize->SetValue(false); - m_toggleBtnContent ->SetValue(false); - - switch (compareVar) - { - case CMP_BY_TIME_SIZE: - m_toggleBtnTimeSize->SetValue(true); - break; - case CMP_BY_CONTENT: - m_toggleBtnContent->SetValue(true); - break; - } - - auto setBitmap = [](wxStaticBitmap& bmpCtrl, bool active, const wxBitmap& bmp) - { - if (active) - bmpCtrl.SetBitmap(bmp); - else - bmpCtrl.SetBitmap(greyScale(bmp)); - }; - setBitmap(*m_bitmapByTime, compareVar == CMP_BY_TIME_SIZE, getResourceImage(L"clock")); - setBitmap(*m_bitmapByContent, compareVar == CMP_BY_CONTENT, getResourceImage(L"cmpByContent")); -} - - -void CompareCfgDialog::OnOkay(wxCommandEvent& event) -{ - cmpConfigOut.compareVar = compareVar; - cmpConfigOut.handleSymlinks = getEnumVal(enumDescrHandleSyml, *m_choiceHandleSymlinks); - - EndModal(ReturnSmallDlg::BUTTON_OKAY); -} - - -void CompareCfgDialog::OnTimeSizeDouble(wxMouseEvent& event) -{ - wxCommandEvent dummy; - OnTimeSize(dummy); - OnOkay(dummy); -} - - -void CompareCfgDialog::OnContentDouble(wxMouseEvent& event) -{ - wxCommandEvent dummy; - OnContent(dummy); - OnOkay(dummy); -} - - -ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog(wxWindow* parent, CompConfig& cmpConfig, const wxString& title) -{ - CompareCfgDialog syncDlg(parent, cmpConfig, title); - return static_cast<ReturnSmallDlg::ButtonPressed>(syncDlg.ShowModal()); -} - -//######################################################################################## - -class GlobalSettingsDlg : public GlobalSettingsDlgGenerated -{ -public: - GlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings); - -private: - virtual void OnOkay(wxCommandEvent& event); - virtual void OnResetDialogs(wxCommandEvent& event); - virtual void OnDefault(wxCommandEvent& event); - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnAddRow(wxCommandEvent& event); - virtual void OnRemoveRow(wxCommandEvent& event); - virtual void OnHelpShowExamples(wxHyperlinkEvent& event) { displayHelpEntry(L"html/External Applications.html", this); } - void onResize(wxSizeEvent& event); - void updateGui(); - - virtual void OnToggleAutoRetryCount(wxCommandEvent& event) { updateGui(); } - - void setExtApp(const xmlAccess::ExternalApps& extApp); - xmlAccess::ExternalApps getExtApp(); - - xmlAccess::XmlGlobalSettings& settings; -}; - - -GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings) : - GlobalSettingsDlgGenerated(parent), - settings(globalSettings) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); - - //setMainInstructionFont(*m_staticTextHeader); - - m_bitmapSettings ->SetBitmap (getResourceImage(L"settings")); - m_bpButtonAddRow ->SetBitmapLabel(getResourceImage(L"item_add")); - m_bpButtonRemoveRow ->SetBitmapLabel(getResourceImage(L"item_remove")); - setBitmapTextLabel(*m_buttonResetDialogs, getResourceImage(L"reset_dialogs").ConvertToImage(), m_buttonResetDialogs->GetLabel()); - - m_checkBoxFailSafe ->SetValue(globalSettings.failsafeFileCopy); - m_checkBoxCopyLocked ->SetValue(globalSettings.copyLockedFiles); - m_checkBoxCopyPermissions->SetValue(globalSettings.copyFilePermissions); - - m_spinCtrlAutoRetryCount->SetValue(globalSettings.automaticRetryCount); - m_spinCtrlAutoRetryDelay->SetValue(globalSettings.automaticRetryDelay); - - setExtApp(globalSettings.gui.externelApplications); - - updateGui(); - -#ifdef ZEN_WIN - m_checkBoxCopyPermissions->SetLabel(_("Copy NTFS permissions")); -#elif defined ZEN_LINUX || defined ZEN_MAC - bSizerLockedFiles->Show(false); -#endif - - const wxString toolTip = wxString(_("Integrate external applications into context menu. The following macros are available:")) + L"\n\n" + - L"%item_path% \t" + _("- full file or folder name") + L"\n" + - L"%item_folder% \t" + _("- folder part only") + L"\n" + - L"%item2_path% \t" + _("- Other side's counterpart to %item_path%") + L"\n" + - L"%item2_folder% \t" + _("- Other side's counterpart to %item_folder%"); - - m_gridCustomCommand->GetGridWindow()->SetToolTip(toolTip); - m_gridCustomCommand->GetGridColLabelWindow()->SetToolTip(toolTip); - m_gridCustomCommand->SetMargins(0, 0); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - Layout(); - - //automatically fit column width to match total grid width - Connect(wxEVT_SIZE, wxSizeEventHandler(GlobalSettingsDlg::onResize), nullptr, this); - wxSizeEvent dummy; - onResize(dummy); - - m_buttonOkay->SetFocus(); -} - - -void GlobalSettingsDlg::onResize(wxSizeEvent& event) -{ - const int widthTotal = m_gridCustomCommand->GetGridWindow()->GetClientSize().GetWidth(); - - if (widthTotal >= 0 && m_gridCustomCommand->GetCols() == 2) - { - const int w0 = widthTotal * 2 / 5; //ratio 2 : 3 - const int w1 = widthTotal - w0; - m_gridCustomCommand->SetColumnWidth(0, w0); - m_gridCustomCommand->SetColumnWidth(1, w1); - - m_gridCustomCommand->Refresh(); //required on Ubuntu - } - - event.Skip(); -} - - -void GlobalSettingsDlg::updateGui() -{ - const bool autoRetryActive = m_spinCtrlAutoRetryCount->GetValue() > 0; - m_staticTextAutoRetryDelay->Enable(autoRetryActive); - m_spinCtrlAutoRetryDelay->Enable(autoRetryActive); -} - - -void GlobalSettingsDlg::OnOkay(wxCommandEvent& event) -{ - //write global settings only when okay-button is pressed! - settings.failsafeFileCopy = m_checkBoxFailSafe->GetValue(); - settings.copyLockedFiles = m_checkBoxCopyLocked->GetValue(); - settings.copyFilePermissions = m_checkBoxCopyPermissions->GetValue(); - - settings.automaticRetryCount = m_spinCtrlAutoRetryCount->GetValue(); - settings.automaticRetryDelay = m_spinCtrlAutoRetryDelay->GetValue(); - - settings.gui.externelApplications = getExtApp(); - - EndModal(ReturnSmallDlg::BUTTON_OKAY); -} - - -void GlobalSettingsDlg::OnResetDialogs(wxCommandEvent& event) -{ - switch (showConfirmationDialog(this, DialogInfoType::INFO, - PopupDialogCfg().setMainInstructions(_("Restore all hidden windows and warnings?")), - _("&Restore"))) - { - case ConfirmationButton::DO_IT: - settings.optDialogs.resetDialogs(); - break; - case ConfirmationButton::CANCEL: - break; - } -} - - -void GlobalSettingsDlg::OnDefault(wxCommandEvent& event) -{ - xmlAccess::XmlGlobalSettings defaultCfg; - - m_checkBoxFailSafe ->SetValue(defaultCfg.failsafeFileCopy); - m_checkBoxCopyLocked ->SetValue(defaultCfg.copyLockedFiles); - m_checkBoxCopyPermissions->SetValue(defaultCfg.copyFilePermissions); - - m_spinCtrlAutoRetryCount->SetValue(defaultCfg.automaticRetryCount); - m_spinCtrlAutoRetryDelay->SetValue(defaultCfg.automaticRetryDelay); - - setExtApp(defaultCfg.gui.externelApplications); - - updateGui(); -} - - -void GlobalSettingsDlg::setExtApp(const xmlAccess::ExternalApps& extApp) -{ - auto extAppTmp = extApp; - vector_remove_if(extAppTmp, [](decltype(extAppTmp[0])& entry) { return entry.first.empty() && entry.second.empty(); }); - - extAppTmp.resize(extAppTmp.size() + 1); //append empty row to facilitate insertions - - const int rowCount = m_gridCustomCommand->GetNumberRows(); - if (rowCount > 0) - m_gridCustomCommand->DeleteRows(0, rowCount); - - m_gridCustomCommand->AppendRows(static_cast<int>(extAppTmp.size())); - for (auto it = extAppTmp.begin(); it != extAppTmp.end(); ++it) - { - const int row = it - extAppTmp.begin(); - m_gridCustomCommand->SetCellValue(row, 0, it->first); //description - m_gridCustomCommand->SetCellValue(row, 1, it->second); //commandline - } -} - - -xmlAccess::ExternalApps GlobalSettingsDlg::getExtApp() -{ - xmlAccess::ExternalApps output; - for (int i = 0; i < m_gridCustomCommand->GetNumberRows(); ++i) - { - auto description = copyStringTo<std::wstring>(m_gridCustomCommand->GetCellValue(i, 0)); - auto commandline = copyStringTo<std::wstring>(m_gridCustomCommand->GetCellValue(i, 1)); - - if (!description.empty() || !commandline.empty()) - output.push_back(std::make_pair(description, commandline)); - } - return output; -} - - -void GlobalSettingsDlg::OnAddRow(wxCommandEvent& event) -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - const int selectedRow = m_gridCustomCommand->GetGridCursorRow(); - if (0 <= selectedRow && selectedRow < m_gridCustomCommand->GetNumberRows()) - m_gridCustomCommand->InsertRows(selectedRow); - else - m_gridCustomCommand->AppendRows(); -} - - -void GlobalSettingsDlg::OnRemoveRow(wxCommandEvent& event) -{ - if (m_gridCustomCommand->GetNumberRows() > 0) - { -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! -#endif - - const int selectedRow = m_gridCustomCommand->GetGridCursorRow(); - if (0 <= selectedRow && selectedRow < m_gridCustomCommand->GetNumberRows()) - m_gridCustomCommand->DeleteRows(selectedRow); - else - m_gridCustomCommand->DeleteRows(m_gridCustomCommand->GetNumberRows() - 1); - } -} - - -ReturnSmallDlg::ButtonPressed zen::showGlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings) -{ - GlobalSettingsDlg settingsDlg(parent, globalSettings); - return static_cast<ReturnSmallDlg::ButtonPressed>(settingsDlg.ShowModal()); -} - -//######################################################################################## - -class SelectTimespanDlg : public SelectTimespanDlgGenerated -{ -public: - SelectTimespanDlg(wxWindow* parent, Int64& timeFrom, Int64& timeTo); - -private: - virtual void OnOkay(wxCommandEvent& event); - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - - virtual void OnChangeSelectionFrom(wxCalendarEvent& event) - { - if (m_calendarFrom->GetDate() > m_calendarTo->GetDate()) - m_calendarTo->SetDate(m_calendarFrom->GetDate()); - } - virtual void OnChangeSelectionTo(wxCalendarEvent& event) - { - if (m_calendarFrom->GetDate() > m_calendarTo->GetDate()) - m_calendarFrom->SetDate(m_calendarTo->GetDate()); - } - - Int64& timeFrom_; - Int64& timeTo_; -}; - - -wxDateTime utcToLocalDateTime(time_t utcTime) -{ - //wxDateTime models local(!) time (in contrast to what documentation says), but this constructor takes time_t UTC - return wxDateTime(utcTime); -} - -time_t localDateTimeToUtc(const wxDateTime& localTime) -{ - return localTime.GetTicks(); -} - - -SelectTimespanDlg::SelectTimespanDlg(wxWindow* parent, Int64& timeFrom, Int64& timeTo) : - SelectTimespanDlgGenerated(parent), - timeFrom_(timeFrom), - timeTo_(timeTo) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); - - long style = wxCAL_SHOW_HOLIDAYS | wxCAL_SHOW_SURROUNDING_WEEKS; - -#ifdef ZEN_WIN - DWORD firstDayOfWeek = 0; - if (::GetLocaleInfo(LOCALE_USER_DEFAULT, //__in LCID Locale, - LOCALE_IFIRSTDAYOFWEEK | // first day of week specifier, 0-6, 0=Monday, 6=Sunday - LOCALE_RETURN_NUMBER, //__in LCTYPE LCType, - reinterpret_cast<LPTSTR>(&firstDayOfWeek), //__out LPTSTR lpLCData, - sizeof(firstDayOfWeek) / sizeof(TCHAR)) > 0 && //__in int cchData - firstDayOfWeek == 6) - style |= wxCAL_SUNDAY_FIRST; - else //default -#endif - style |= wxCAL_MONDAY_FIRST; - - m_calendarFrom->SetWindowStyleFlag(style); - m_calendarTo ->SetWindowStyleFlag(style); - - //set default values - if (timeTo_ == 0) - timeTo_ = wxGetUTCTime(); // - if (timeFrom_ == 0) - timeFrom_ = timeTo_ - 7 * 24 * 3600; //default time span: one week from "now" - - m_calendarFrom->SetDate(utcToLocalDateTime(to<time_t>(timeFrom_))); - m_calendarTo ->SetDate(utcToLocalDateTime(to<time_t>(timeTo_))); - -#if wxCHECK_VERSION(2, 9, 5) - //doesn't seem to be a problem here: -#else - //wxDatePickerCtrl::BestSize() does not respect year field and trims it, both wxMSW/wxGTK - why isn't there anybody testing this wxWidgets stuff??? - wxSize minSz = m_calendarFrom->GetBestSize(); - minSz.x += 30; - m_calendarFrom->SetMinSize(minSz); - m_calendarTo ->SetMinSize(minSz); -#endif - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - m_buttonOkay->SetFocus(); -} - - -void SelectTimespanDlg::OnOkay(wxCommandEvent& event) -{ - wxDateTime from = m_calendarFrom->GetDate(); - wxDateTime to = m_calendarTo ->GetDate(); - - //align to full days - from.ResetTime(); - to += wxTimeSpan::Day(); - to.ResetTime(); //reset local(!) time - to -= wxTimeSpan::Second(); //go back to end of previous day - - timeFrom_ = localDateTimeToUtc(from); - timeTo_ = localDateTimeToUtc(to); - - /* - { - time_t current = zen::to<time_t>(timeFrom_); - struct tm* tdfewst = ::localtime(¤t); - int budfk = 3; - } - { - time_t current = zen::to<time_t>(timeTo_); - struct tm* tdfewst = ::localtime(¤t); - int budfk = 3; - } - */ - - EndModal(ReturnSmallDlg::BUTTON_OKAY); -} - - -ReturnSmallDlg::ButtonPressed zen::showSelectTimespanDlg(wxWindow* parent, Int64& timeFrom, Int64& timeTo) -{ - SelectTimespanDlg timeSpanDlg(parent, timeFrom, timeTo); - return static_cast<ReturnSmallDlg::ButtonPressed>(timeSpanDlg.ShowModal()); -} diff --git a/ui/small_dlgs.h b/ui/small_dlgs.h deleted file mode 100644 index 311a7d14..00000000 --- a/ui/small_dlgs.h +++ /dev/null @@ -1,52 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef SMALLDIALOGS_H_INCLUDED -#define SMALLDIALOGS_H_INCLUDED - -#include <wx/window.h> -//#include "../file_hierarchy.h" -#include "../lib/process_xml.h" -#include "../synchronization.h" - -namespace zen -{ -//parent window, optional: support correct dialog placement above parent on multiple monitor systems - -struct ReturnSmallDlg -{ - enum ButtonPressed - { - BUTTON_CANCEL, - BUTTON_OKAY = 1 - }; -}; - -void showAboutDialog(wxWindow* parent); - -ReturnSmallDlg::ButtonPressed showFilterDialog(wxWindow* parent, FilterConfig& filter, const wxString& caption); - -ReturnSmallDlg::ButtonPressed showDeleteDialog(wxWindow* parent, - const std::vector<FileSystemObject*>& rowsOnLeft, - const std::vector<FileSystemObject*>& rowsOnRight, - bool& deleteOnBothSides, - bool& useRecycleBin); - -ReturnSmallDlg::ButtonPressed showSyncConfirmationDlg(wxWindow* parent, - const wxString& variantName, - const SyncStatistics& statistics, - bool& dontShowAgain); - -ReturnSmallDlg::ButtonPressed showCompareCfgDialog(wxWindow* parent, CompConfig& cmpConfig, const wxString& title); - -ReturnSmallDlg::ButtonPressed showGlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings); - -ReturnSmallDlg::ButtonPressed showSelectTimespanDlg(wxWindow* parent, Int64& timeFrom, Int64& timeTo); -} - -#endif // SMALLDIALOGS_H_INCLUDED - - diff --git a/ui/sorting.h b/ui/sorting.h deleted file mode 100644 index 46477d0f..00000000 --- a/ui/sorting.h +++ /dev/null @@ -1,193 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef SORTING_H_INCLUDED -#define SORTING_H_INCLUDED - -#include <zen/assert_static.h> -#include <zen/type_tools.h> -#include "../file_hierarchy.h" - -namespace zen -{ -namespace -{ -struct CompileTimeReminder : public FSObjectVisitor -{ - virtual void visit(const FilePair& fileObj) {} - virtual void visit(const SymlinkPair& linkObj) {} - virtual void visit(const DirPair& dirObj ) {} -} checkDymanicCasts; //just a compile-time reminder to manually check dynamic casts in this file when needed -} - -inline -bool isDirectoryPair(const FileSystemObject& fsObj) -{ - return dynamic_cast<const DirPair*>(&fsObj) != nullptr; -} - - -template <bool ascending, SelectedSide side> inline -bool lessShortFileName(const FileSystemObject& a, const FileSystemObject& b) -{ - //presort types: first files, then directories then empty rows - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last - - - if (isDirectoryPair(a)) //sort directories by relative name - { - if (isDirectoryPair(b)) - return LessFilename()(a.getRelativeName<side>(), b.getRelativeName<side>()); - else - return false; - } - else - { - if (isDirectoryPair(b)) - return true; - else - return makeSortDirection(LessFilename(), Int2Type<ascending>())(a.getShortName<side>(), b.getShortName<side>()); - } -} - - -template <bool ascending> //side currently unused! -bool lessRelativeName(const FileSystemObject& a, const FileSystemObject& b) -{ - const bool isDirectoryA = isDirectoryPair(a); - const Zstring& relDirNameA = isDirectoryA ? - a.getObjRelativeName() : //directory - beforeLast(a.getObjRelativeName(), FILE_NAME_SEPARATOR); //returns empty string if ch not found - - const bool isDirectoryB = isDirectoryPair(b); - const Zstring& relDirNameB = isDirectoryB ? - b.getObjRelativeName() : //directory - beforeLast(b.getObjRelativeName(), FILE_NAME_SEPARATOR); //returns empty string if ch not found - - //compare relative names without filenames first - const int rv = cmpFileName(relDirNameA, relDirNameB); - if (rv != 0) - return makeSortDirection(std::less<int>(), Int2Type<ascending>())(rv, 0); - else //compare the filenames - { - if (isDirectoryB) //directories shall appear before files - return false; - else if (isDirectoryA) - return true; - - return LessFilename()(a.getObjShortName(), b.getObjShortName()); - } -} - - -template <bool ascending, SelectedSide side> inline -bool lessFilesize(const FileSystemObject& a, const FileSystemObject& b) -{ - //empty rows always last - if (a.isEmpty<side>()) - return false; - else if (b.isEmpty<side>()) - return true; - - const bool isDirA = dynamic_cast<const DirPair*>(&a) != nullptr; - const bool isDirB = dynamic_cast<const DirPair*>(&b) != nullptr; - - //directories second last - if (isDirA) - return false; - else if (isDirB) - return true; - - const FilePair* fileObjA = dynamic_cast<const FilePair*>(&a); - const FilePair* fileObjB = dynamic_cast<const FilePair*>(&b); - - //then symlinks - if (!fileObjA) - return false; - else if (!fileObjB) - return true; - - //return list beginning with largest files first - return makeSortDirection(std::less<UInt64>(), Int2Type<ascending>())(fileObjA->getFileSize<side>(), fileObjB->getFileSize<side>()); -} - - -template <bool ascending, SelectedSide side> inline -bool lessFiletime(const FileSystemObject& a, const FileSystemObject& b) -{ - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last - - - const FilePair* fileObjA = dynamic_cast<const FilePair*>(&a); - const FilePair* fileObjB = dynamic_cast<const FilePair*>(&b); - - const SymlinkPair* linkObjA = dynamic_cast<const SymlinkPair*>(&a); - const SymlinkPair* linkObjB = dynamic_cast<const SymlinkPair*>(&b); - - if (!fileObjA && !linkObjA) - return false; //directories last - else if (!fileObjB && !linkObjB) - return true; //directories last - - zen::Int64 dateA = fileObjA ? fileObjA->getLastWriteTime<side>() : linkObjA->getLastWriteTime<side>(); - zen::Int64 dateB = fileObjB ? fileObjB->getLastWriteTime<side>() : linkObjB->getLastWriteTime<side>(); - - //return list beginning with newest files first - return makeSortDirection(std::less<Int64>(), Int2Type<ascending>())(dateA, dateB); -} - - -template <bool ascending, SelectedSide side> inline -bool lessExtension(const FileSystemObject& a, const FileSystemObject& b) -{ - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last - - if (dynamic_cast<const DirPair*>(&a)) - return false; //directories last - else if (dynamic_cast<const DirPair*>(&b)) - return true; //directories last - - auto getExtension = [&](const FileSystemObject& fsObj) -> Zstring - { - const Zstring& shortName = fsObj.getShortName<side>(); - const size_t pos = shortName.rfind(Zchar('.')); - return pos == Zstring::npos ? Zstring() : Zstring(shortName.c_str() + pos + 1); - }; - - return makeSortDirection(LessFilename(), Int2Type<ascending>())(getExtension(a), getExtension(b)); -} - - -template <bool ascending> inline -bool lessCmpResult(const FileSystemObject& a, const FileSystemObject& b) -{ - //presort result: equal shall appear at end of list - if (a.getCategory() == FILE_EQUAL) - return false; - if (b.getCategory() == FILE_EQUAL) - return true; - - return makeSortDirection(std::less<CompareFilesResult>(), Int2Type<ascending>())(a.getCategory(), b.getCategory()); -} - - -template <bool ascending> inline -bool lessSyncDirection(const FileSystemObject& a, const FileSystemObject& b) -{ - return makeSortDirection(std::less<SyncOperation>(), Int2Type<ascending>())(a.getSyncOperation(), b.getSyncOperation()); -} -} - -#endif // SORTING_H_INCLUDED diff --git a/ui/switch_to_gui.h b/ui/switch_to_gui.h deleted file mode 100644 index 20fe81de..00000000 --- a/ui/switch_to_gui.h +++ /dev/null @@ -1,40 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef SWITCHTOGUI_H_INCLUDED -#define SWITCHTOGUI_H_INCLUDED - -#include "../lib/process_xml.h" -#include "main_dlg.h" //in "application.cpp" we have this dependency anyway! - -namespace zen -{ -//switch from FreeFileSync Batch to GUI modus: opens a new FreeFileSync GUI session asynchronously -class SwitchToGui -{ -public: - SwitchToGui(const Zstring& referenceFile, - const xmlAccess::XmlBatchConfig& batchCfg, - xmlAccess::XmlGlobalSettings& globalSettings) : - guiCfg(xmlAccess::convertBatchToGui(batchCfg)), - globalSettings_(globalSettings) - { - referenceFiles.push_back(referenceFile); - } - - void execute() const - { - MainDialog::create(guiCfg, referenceFiles, &globalSettings_, true); //new toplevel window - } - -private: - std::vector<Zstring> referenceFiles; - const xmlAccess::XmlGuiConfig guiCfg; - xmlAccess::XmlGlobalSettings& globalSettings_; -}; -} - -#endif // SWITCHTOGUI_H_INCLUDED diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp deleted file mode 100644 index 38e583fc..00000000 --- a/ui/sync_cfg.cpp +++ /dev/null @@ -1,640 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "sync_cfg.h" -#include <memory> -//#include <zen/format_unit.h> -#include <wx/wupdlock.h> -#include <wx+/mouse_move_dlg.h> -#include <wx+/rtl.h> -#include <wx+/no_flicker.h> -#include <wx+/choice_enum.h> -#include <wx+/image_tools.h> -#include <wx+/font_size.h> -#include <wx+/std_button_order.h> -#include <wx+/popup_dlg.h> -#include <wx+/image_resources.h> -#include "gui_generated.h" -#include "exec_finished_box.h" -#include "dir_name.h" -#include "../file_hierarchy.h" -#include "../lib/help_provider.h" - -using namespace zen; -using namespace xmlAccess; - - -class SyncCfgDialog : public SyncCfgDlgGenerated -{ -public: - SyncCfgDialog(wxWindow* parent, - CompareVariant compareVar, - SyncConfig& syncCfg, - const wxString& caption, - xmlAccess::OnGuiError* handleError, // - ExecWhenFinishedCfg* execWhenFinished); //optional input parameter - -private: - virtual void OnSyncTwoWay(wxCommandEvent& event) { directionCfg.var = DirectionConfig::TWOWAY; updateGui(); } - virtual void OnSyncMirror(wxCommandEvent& event) { directionCfg.var = DirectionConfig::MIRROR; updateGui(); } - virtual void OnSyncUpdate(wxCommandEvent& event) { directionCfg.var = DirectionConfig::UPDATE; updateGui(); } - virtual void OnSyncCustom(wxCommandEvent& event) { directionCfg.var = DirectionConfig::CUSTOM; updateGui(); } - - virtual void OnToggleDetectMovedFiles(wxCommandEvent& event) { directionCfg.detectMovedFiles = !directionCfg.detectMovedFiles; updateGui(); } - - virtual void OnSyncTwoWayDouble(wxMouseEvent& event); - virtual void OnSyncMirrorDouble(wxMouseEvent& event); - virtual void OnSyncUpdateDouble(wxMouseEvent& event); - virtual void OnSyncCustomDouble(wxMouseEvent& event); - - virtual void OnExLeftSideOnly (wxCommandEvent& event); - virtual void OnExRightSideOnly(wxCommandEvent& event); - virtual void OnLeftNewer (wxCommandEvent& event); - virtual void OnRightNewer (wxCommandEvent& event); - virtual void OnDifferent (wxCommandEvent& event); - virtual void OnConflict (wxCommandEvent& event); - - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSyncConfig::BUTTON_CANCEL); } - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSyncConfig::BUTTON_CANCEL); } - virtual void OnOkay (wxCommandEvent& event); - - virtual void OnParameterChange(wxCommandEvent& event) { updateGui(); } - - virtual void OnDeletionPermanent (wxCommandEvent& event) { handleDeletion = DELETE_PERMANENTLY; updateGui(); } - virtual void OnDeletionRecycler (wxCommandEvent& event) { handleDeletion = DELETE_TO_RECYCLER; updateGui(); } - virtual void OnDeletionVersioning (wxCommandEvent& event) { handleDeletion = DELETE_TO_VERSIONING; updateGui(); } - - virtual void OnErrorPopup (wxCommandEvent& event) { onGuiError = ON_GUIERROR_POPUP; updateGui(); } - virtual void OnErrorIgnore(wxCommandEvent& event) { onGuiError = ON_GUIERROR_IGNORE; updateGui(); } - - virtual void OnHelpVersioning(wxHyperlinkEvent& event) { displayHelpEntry(L"html/Versioning.html", this); } - - struct Config - { - SyncConfig syncCfg; - xmlAccess::OnGuiError onGuiError; - std::wstring onCompletion; - }; - void setConfig(const Config& cfg); - Config getConfig() const; - - void updateGui(); - - //parameters with ownership NOT within GUI controls! - DirectionConfig directionCfg; - DeletionPolicy handleDeletion; //use Recycler, delete permanently or move to user-defined location - OnGuiError onGuiError; - - //output data - SyncConfig& outSyncCfg; - xmlAccess::OnGuiError* outOptOnGuiError; - ExecWhenFinishedCfg* outOptExecWhenFinished; - - CompareVariant compareVar_; - DirectoryName<FolderHistoryBox> versioningFolder; - - EnumDescrList<VersioningStyle> enumVersioningStyle; -}; - - -void updateConfigIcons(const DirectionConfig& directionCfg, - wxBitmapButton* buttonLeftOnly, - wxBitmapButton* buttonRightOnly, - wxBitmapButton* buttonLeftNewer, - wxBitmapButton* buttonRightNewer, - wxBitmapButton* buttonDifferent, - wxBitmapButton* buttonConflict) -{ - if (directionCfg.var != DirectionConfig::TWOWAY) //automatic mode needs no sync-directions - { - const DirectionSet dirCfg = extractDirections(directionCfg); - - switch (dirCfg.exLeftSideOnly) - { - case SyncDirection::RIGHT: - buttonLeftOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_create_right"))); - buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_RIGHT)); - break; - case SyncDirection::LEFT: - buttonLeftOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_delete_left"))); - buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DELETE_LEFT)); - break; - case SyncDirection::NONE: - buttonLeftOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none"))); - buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); - break; - } - - switch (dirCfg.exRightSideOnly) - { - case SyncDirection::RIGHT: - buttonRightOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_delete_right"))); - buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DELETE_RIGHT)); - break; - case SyncDirection::LEFT: - buttonRightOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_create_left"))); - buttonRightOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_LEFT)); - break; - case SyncDirection::NONE: - buttonRightOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none"))); - buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); - break; - } - - switch (dirCfg.leftNewer) - { - case SyncDirection::RIGHT: - buttonLeftNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right"))); - buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); - break; - case SyncDirection::LEFT: - buttonLeftNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left"))); - buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); - break; - case SyncDirection::NONE: - buttonLeftNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none"))); - buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); - break; - } - - switch (dirCfg.rightNewer) - { - case SyncDirection::RIGHT: - buttonRightNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right"))); - buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); - break; - case SyncDirection::LEFT: - buttonRightNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left"))); - buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); - break; - case SyncDirection::NONE: - buttonRightNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none"))); - buttonRightNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); - break; - } - - switch (dirCfg.different) - { - case SyncDirection::RIGHT: - buttonDifferent->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right"))); - buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); - break; - case SyncDirection::LEFT: - buttonDifferent->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left"))); - buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); - break; - case SyncDirection::NONE: - buttonDifferent->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none"))); - buttonDifferent->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); - break; - } - - switch (dirCfg.conflict) - { - case SyncDirection::RIGHT: - buttonConflict->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right"))); - buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); - break; - case SyncDirection::LEFT: - buttonConflict->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left"))); - buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); - break; - case SyncDirection::NONE: - buttonConflict->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"cat_conflict"))); //silent dependency to algorithm.cpp::Redetermine!!! - buttonConflict->SetToolTip(_("Leave as unresolved conflict")); - break; - } - } -} - - -SyncCfgDialog::SyncCfgDialog(wxWindow* parent, - CompareVariant compareVar, - SyncConfig& syncCfg, - const wxString& title, - xmlAccess::OnGuiError* handleError, - ExecWhenFinishedCfg* execWhenFinished) : - SyncCfgDlgGenerated(parent), - handleDeletion(DELETE_TO_RECYCLER), // - onGuiError(ON_GUIERROR_POPUP), //dummy init - outSyncCfg(syncCfg), - outOptOnGuiError(handleError), - outOptExecWhenFinished(execWhenFinished), - compareVar_(compareVar), - versioningFolder(*m_panelVersioning, *m_buttonSelectDirVersioning, *m_versioningFolder/*, m_staticTextResolvedPath*/) -{ -#ifdef ZEN_WIN - new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" -#endif - setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOK).setCancel(m_buttonCancel)); - - SetTitle(title); - - //set icons for this dialog - m_bitmapLeftOnly ->SetBitmap(mirrorIfRtl(greyScale(getResourceImage(L"cat_left_only" )))); - m_bitmapRightOnly ->SetBitmap(mirrorIfRtl(greyScale(getResourceImage(L"cat_right_only" )))); - m_bitmapLeftNewer ->SetBitmap(mirrorIfRtl(greyScale(getResourceImage(L"cat_left_newer" )))); - m_bitmapRightNewer->SetBitmap(mirrorIfRtl(greyScale(getResourceImage(L"cat_right_newer")))); - m_bitmapDifferent ->SetBitmap(mirrorIfRtl(greyScale(getResourceImage(L"cat_different" )))); - m_bitmapConflict ->SetBitmap(mirrorIfRtl(greyScale(getResourceImage(L"cat_conflict" )))); - m_bitmapDatabase ->SetBitmap(getResourceImage(L"database")); - - m_toggleBtnTwoWay->SetLabel(L"<- " + _("Two way") + L" ->"); - m_toggleBtnMirror->SetLabel( _("Mirror") + L" ->>"); - m_toggleBtnUpdate->SetLabel( _("Update") + L" ->"); - - setRelativeFontSize(*m_toggleBtnTwoWay, 1.25); - setRelativeFontSize(*m_toggleBtnMirror, 1.25); - setRelativeFontSize(*m_toggleBtnUpdate, 1.25); - setRelativeFontSize(*m_toggleBtnCustom, 1.25); - - enumVersioningStyle. - add(VER_STYLE_REPLACE, _("Replace"), _("Move files and replace if existing")). - add(VER_STYLE_ADD_TIMESTAMP, _("Time stamp"), _("Append a timestamp to each file name")); - - //hide controls for optional parameters - if (!handleError && !execWhenFinished) //currently either both or neither are bound! - { - bSizerExtraConfig->Show(false); - Layout(); - } - - if (execWhenFinished) - m_comboBoxExecFinished->initHistory(*execWhenFinished->history, execWhenFinished->historyMax); - - Config newCfg = { syncCfg, - handleError ?* handleError : ON_GUIERROR_POPUP, - execWhenFinished ?* execWhenFinished->command : std::wstring() - }; - setConfig(newCfg); - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! - - m_buttonOK->SetFocus(); -} - -//################################################################################################################# - -void SyncCfgDialog::setConfig(const Config& cfg) -{ - directionCfg = cfg.syncCfg.directionCfg; //make working copy; ownership *not* on GUI - handleDeletion = cfg.syncCfg.handleDeletion; - - versioningFolder.setName(utfCvrtTo<wxString>(cfg.syncCfg.versioningDirectory)); - setEnumVal(enumVersioningStyle, *m_choiceVersioningStyle, cfg.syncCfg.versioningStyle); - - ////map single parameter "version limit" to both checkbox and spin ctrl: - //m_checkBoxVersionsLimit->SetValue(cfg.syncCfg.versionCountLimit >= 0); - //m_spinCtrlVersionsLimit->SetValue(cfg.syncCfg.versionCountLimit >= 0 ? cfg.syncCfg.versionCountLimit : 10 /*SyncConfig().versionCountLimit*/); - - onGuiError = cfg.onGuiError; - - m_comboBoxExecFinished->setValue(cfg.onCompletion); - - updateGui(); -} - - -SyncCfgDialog::Config SyncCfgDialog::getConfig() const -{ - Config output; - - //write configuration to main dialog - output.syncCfg.directionCfg = directionCfg; - output.syncCfg.handleDeletion = handleDeletion; - output.syncCfg.versioningDirectory = utfCvrtTo<Zstring>(versioningFolder.getName()); - output.syncCfg.versioningStyle = getEnumVal(enumVersioningStyle, *m_choiceVersioningStyle), - - //get single parameter "version limit" from both checkbox and spin ctrl: - // output.syncCfg.versionCountLimit = m_checkBoxVersionsLimit->GetValue() ? m_spinCtrlVersionsLimit->GetValue() : -1; - - output.onGuiError = onGuiError; - - output.onCompletion = m_comboBoxExecFinished->getValue(); - return output; -} - - -void SyncCfgDialog::updateGui() -{ -#ifdef ZEN_WIN - wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! - wxWindowUpdateLocker dummy2(m_panelVersioning); - wxWindowUpdateLocker dummy3(m_bpButtonLeftOnly); - wxWindowUpdateLocker dummy4(m_bpButtonRightOnly); - wxWindowUpdateLocker dummy5(m_bpButtonLeftNewer); - wxWindowUpdateLocker dummy6(m_bpButtonRightNewer); - wxWindowUpdateLocker dummy7(m_bpButtonDifferent); - wxWindowUpdateLocker dummy8(m_bpButtonConflict); -#endif - - const Config cfg = getConfig(); //resolve parameter ownership: some on GUI controls, others member variables - - updateConfigIcons(cfg.syncCfg.directionCfg, - m_bpButtonLeftOnly, - m_bpButtonRightOnly, - m_bpButtonLeftNewer, - m_bpButtonRightNewer, - m_bpButtonDifferent, - m_bpButtonConflict); - - //selecting "detect move files" does not always make sense: - m_checkBoxDetectMove->Enable(detectMovedFilesSelectable(directionCfg)); - m_checkBoxDetectMove->SetValue(detectMovedFilesEnabled(directionCfg)); //parameter NOT owned by checkbox! - - //display only relevant sync options - m_bitmapDatabase ->Show(cfg.syncCfg.directionCfg.var == DirectionConfig::TWOWAY); - sbSizerSyncDirections->Show(cfg.syncCfg.directionCfg.var != DirectionConfig::TWOWAY); - - switch (compareVar_) //sbSizerSyncDirections->Show resets child sizers! - { - case CMP_BY_TIME_SIZE: - bSizerDifferent ->Show(false); - break; - - case CMP_BY_CONTENT: - bSizerLeftNewer ->Show(false); - bSizerRightNewer->Show(false); - break; - } - bSizerConfig->Layout(); //[!] - - //update toggle buttons -> they have no parameter-ownership at all! - m_staticTextAutomatic->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); - m_staticTextMirror ->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); - m_staticTextUpdate ->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); - m_staticTextCustom ->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); - - m_toggleBtnTwoWay->SetValue(false); - m_toggleBtnMirror->SetValue(false); - m_toggleBtnUpdate->SetValue(false); - m_toggleBtnCustom->SetValue(false); - - switch (cfg.syncCfg.directionCfg.var) - { - case DirectionConfig::TWOWAY: - m_toggleBtnTwoWay->SetValue(true); - m_staticTextAutomatic->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - break; - case DirectionConfig::MIRROR: - m_toggleBtnMirror->SetValue(true); - m_staticTextMirror->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - break; - case DirectionConfig::UPDATE: - m_toggleBtnUpdate->SetValue(true); - m_staticTextUpdate->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - break; - case DirectionConfig::CUSTOM: - m_toggleBtnCustom->SetValue(true); - m_staticTextCustom->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - break; - } - - m_toggleBtnPermanent ->SetValue(false); - m_toggleBtnRecycler ->SetValue(false); - m_toggleBtnVersioning->SetValue(false); - switch (cfg.syncCfg.handleDeletion) - { - case DELETE_PERMANENTLY: - m_toggleBtnPermanent->SetValue(true); - break; - case DELETE_TO_RECYCLER: - m_toggleBtnRecycler->SetValue(true); - break; - case DELETE_TO_VERSIONING: - m_toggleBtnVersioning->SetValue(true); - break; - } - - const bool versioningSelected = cfg.syncCfg.handleDeletion == DELETE_TO_VERSIONING; - m_panelVersioning->Show(versioningSelected); - - if (versioningSelected) - { - updateTooltipEnumVal(enumVersioningStyle, *m_choiceVersioningStyle); - - const std::wstring pathSep = utfCvrtTo<std::wstring>(FILE_NAME_SEPARATOR); - switch (cfg.syncCfg.versioningStyle) - { - case VER_STYLE_REPLACE: - setText(*m_staticTextNamingCvtPart1, pathSep + _("Folder") + pathSep + _("File") + L".doc"); - setText(*m_staticTextNamingCvtPart2Bold, L""); - setText(*m_staticTextNamingCvtPart3, L""); - break; - - case VER_STYLE_ADD_TIMESTAMP: - setText(*m_staticTextNamingCvtPart1, pathSep + _("Folder") + pathSep + _("File") + L".doc "); - setText(*m_staticTextNamingCvtPart2Bold, _("YYYY-MM-DD hhmmss")); - setText(*m_staticTextNamingCvtPart3, L".doc"); - break; - } - } - - //m_spinCtrlVersionsLimit->Enable(m_checkBoxVersionsLimit->GetValue()); //enabled status is *not* directly dependent from resolved config! (but transitively) - - m_toggleBtnErrorIgnore->SetValue(false); - m_toggleBtnErrorPopup ->SetValue(false); - switch (cfg.onGuiError) - { - case ON_GUIERROR_IGNORE: - m_toggleBtnErrorIgnore->SetValue(true); - break; - case ON_GUIERROR_POPUP: - m_toggleBtnErrorPopup->SetValue(true); - break; - } - - Layout(); - Refresh(); //removes a few artifacts when toggling display of versioning folder - - GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() - //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! -} - - -void SyncCfgDialog::OnOkay(wxCommandEvent& event) -{ - const Config cfg = getConfig(); - - //parameter validation: - - //check if user-defined directory for deletion was specified - if (cfg.syncCfg.handleDeletion == zen::DELETE_TO_VERSIONING) - { - Zstring versioningDir = cfg.syncCfg.versioningDirectory; - trim(versioningDir); - if (versioningDir.empty()) - { - showNotificationDialog(this, DialogInfoType::INFO, PopupDialogCfg().setMainInstructions(_("Please enter a target folder for versioning."))); - //don't show error icon to follow "Windows' encouraging tone" - m_panelVersioning->SetFocus(); - return; - } - } - - //apply config: - outSyncCfg = cfg.syncCfg; - - if (outOptOnGuiError) - *outOptOnGuiError = cfg.onGuiError; - - if (outOptExecWhenFinished) - { - *outOptExecWhenFinished->command = cfg.onCompletion; - //a good place to commit current "on completion" history item - m_comboBoxExecFinished->addItemHistory(); - } - - EndModal(ReturnSyncConfig::BUTTON_OKAY); -} - - -void SyncCfgDialog::OnSyncTwoWayDouble(wxMouseEvent& event) -{ - wxCommandEvent dummy; - OnSyncTwoWay(dummy); - OnOkay(dummy); -} - -void SyncCfgDialog::OnSyncMirrorDouble(wxMouseEvent& event) -{ - wxCommandEvent dummy; - OnSyncMirror(dummy); - OnOkay(dummy); -} - -void SyncCfgDialog::OnSyncUpdateDouble(wxMouseEvent& event) -{ - wxCommandEvent dummy; - OnSyncUpdate(dummy); - OnOkay(dummy); -} - -void SyncCfgDialog::OnSyncCustomDouble(wxMouseEvent& event) -{ - wxCommandEvent dummy; - OnSyncCustom(dummy); - OnOkay(dummy); -} - -namespace -{ -void toggleSyncDirection(SyncDirection& current) -{ - switch (current) - { - case SyncDirection::RIGHT: - current = SyncDirection::LEFT; - break; - case SyncDirection::LEFT: - current = SyncDirection::NONE; - break; - case SyncDirection::NONE: - current = SyncDirection::RIGHT; - break; - } -} - - -void pressCustomDir(DirectionConfig& directionCfg, SyncDirection& syncdir) -{ - switch (directionCfg.var) - { - case DirectionConfig::TWOWAY: - assert(false); - break; - case DirectionConfig::MIRROR: - case DirectionConfig::UPDATE: - directionCfg.custom = extractDirections(directionCfg); - directionCfg.var = DirectionConfig::CUSTOM; - toggleSyncDirection(syncdir); - break; - case DirectionConfig::CUSTOM: - toggleSyncDirection(syncdir); - - //some config optimization: if custom settings happen to match "mirror" or "update", just switch variant - const DirectionSet setMirror = [] - { - DirectionConfig mirrorCfg; - mirrorCfg.var = DirectionConfig::MIRROR; - return extractDirections(mirrorCfg); - }(); - - const DirectionSet setUpdate = [] - { - DirectionConfig updateCfg; - updateCfg.var = DirectionConfig::UPDATE; - return extractDirections(updateCfg); - }(); - - const DirectionSet currentSet = extractDirections(directionCfg); - if (currentSet == setMirror) - directionCfg.var = DirectionConfig::MIRROR; - else if (currentSet == setUpdate) - directionCfg.var = DirectionConfig::UPDATE; - break; - } -} -} - -void SyncCfgDialog::OnExLeftSideOnly(wxCommandEvent& event ) -{ - pressCustomDir(directionCfg, directionCfg.custom.exLeftSideOnly); - updateGui(); -} - - -void SyncCfgDialog::OnExRightSideOnly(wxCommandEvent& event ) -{ - pressCustomDir(directionCfg, directionCfg.custom.exRightSideOnly); - updateGui(); -} - - -void SyncCfgDialog::OnLeftNewer(wxCommandEvent& event ) -{ - pressCustomDir(directionCfg, directionCfg.custom.leftNewer); - updateGui(); -} - - -void SyncCfgDialog::OnRightNewer(wxCommandEvent& event ) -{ - pressCustomDir(directionCfg, directionCfg.custom.rightNewer); - updateGui(); -} - - -void SyncCfgDialog::OnDifferent(wxCommandEvent& event ) -{ - pressCustomDir(directionCfg, directionCfg.custom.different); - updateGui(); -} - - -void SyncCfgDialog::OnConflict(wxCommandEvent& event) -{ - pressCustomDir(directionCfg, directionCfg.custom.conflict); - updateGui(); -} - - -ReturnSyncConfig::ButtonPressed zen::showSyncConfigDlg(wxWindow* parent, - CompareVariant compareVar, - SyncConfig& syncCfg, - const wxString& title, - xmlAccess::OnGuiError* handleError, // - ExecWhenFinishedCfg* execWhenFinished) //optional input parameter -{ - SyncCfgDialog syncDlg(parent, - compareVar, - syncCfg, - title, - handleError, - execWhenFinished); - return static_cast<ReturnSyncConfig::ButtonPressed>(syncDlg.ShowModal()); -} diff --git a/ui/sync_cfg.h b/ui/sync_cfg.h deleted file mode 100644 index e56a533b..00000000 --- a/ui/sync_cfg.h +++ /dev/null @@ -1,41 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef SYNCCONFIG_H_INCLUDED -#define SYNCCONFIG_H_INCLUDED - -#include <wx/window.h> -#include "../lib/process_xml.h" - - -namespace zen -{ -struct ReturnSyncConfig -{ - enum ButtonPressed - { - BUTTON_CANCEL, - BUTTON_OKAY - }; -}; - -struct ExecWhenFinishedCfg -{ - std::wstring* command; //*must* be bound! - std::vector<std::wstring>* history; // - size_t historyMax; -}; - - -ReturnSyncConfig::ButtonPressed showSyncConfigDlg(wxWindow* parent, - CompareVariant compareVar, - SyncConfig& syncCfg, - const wxString& title, - xmlAccess::OnGuiError* handleError, // - ExecWhenFinishedCfg* execWhenFinished); //optional input parameter -} - -#endif // SYNCCONFIG_H_INCLUDED diff --git a/ui/taskbar.cpp b/ui/taskbar.cpp deleted file mode 100644 index e6aadc90..00000000 --- a/ui/taskbar.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "taskbar.h" - -#ifdef ZEN_WIN -#include <zen/dll.h> -#include <zen/win_ver.h> -#include "Taskbar_Seven/taskbar.h" - -#elif defined HAVE_UBUNTU_UNITY -#include <unity/unity/unity.h> - -#elif defined ZEN_MAC -#include <zen/basic_math.h> -#include <zen/string_tools.h> -#include "osx_dock.h" -#endif - -using namespace zen; - - -#ifdef ZEN_WIN -using namespace tbseven; - - -class Taskbar::Pimpl //throw TaskbarNotAvailable -{ -public: - Pimpl(const wxFrame& window) : - assocWindow(window.GetHWND()), - setStatus_ (getDllName(), funName_setStatus), - setProgress_(getDllName(), funName_setProgress) - { - if (!assocWindow || !setProgress_ || !setStatus_) - throw TaskbarNotAvailable(); - - if (!zen::win7OrLater()) - throw TaskbarNotAvailable(); - } - - ~Pimpl() { setStatus_(assocWindow, tbseven::STATUS_NOPROGRESS); } - - void setStatus(Status status) - { - TaskBarStatus tbSevenStatus = tbseven::STATUS_NORMAL; - switch (status) - { - case Taskbar::STATUS_INDETERMINATE: - tbSevenStatus = tbseven::STATUS_INDETERMINATE; - break; - case Taskbar::STATUS_NORMAL: - tbSevenStatus = tbseven::STATUS_NORMAL; - break; - case Taskbar::STATUS_ERROR: - tbSevenStatus = tbseven::STATUS_ERROR; - break; - case Taskbar::STATUS_PAUSED: - tbSevenStatus = tbseven::STATUS_PAUSED; - break; - } - - setStatus_(assocWindow, tbSevenStatus); - } - - void setProgress(double fraction) - { - setProgress_(assocWindow, fraction * 100000, 100000); - } - -private: - void* assocWindow; //HWND - const DllFun<FunType_setStatus> setStatus_; - const DllFun<FunType_setProgress> setProgress_; -}; - -#elif defined HAVE_UBUNTU_UNITY //Ubuntu unity -namespace -{ -const char FFS_DESKTOP_FILE[] = "freefilesync.desktop"; -} - -class Taskbar::Pimpl //throw (TaskbarNotAvailable) -{ -public: - Pimpl(const wxFrame& window) : - tbEntry(unity_launcher_entry_get_for_desktop_id(FFS_DESKTOP_FILE)) - //tbEntry(unity_launcher_entry_get_for_app_uri("application://freefilesync.desktop")) - { - if (!tbEntry) - throw TaskbarNotAvailable(); - } - - ~Pimpl() { setStatus(STATUS_INDETERMINATE); } //it seems UnityLauncherEntry* does not need destruction - - void setStatus(Status status) - { - switch (status) - { - case Taskbar::STATUS_ERROR: - unity_launcher_entry_set_urgent(tbEntry, true); - break; - - case Taskbar::STATUS_INDETERMINATE: - unity_launcher_entry_set_urgent(tbEntry, false); - unity_launcher_entry_set_progress_visible(tbEntry, false); - break; - - case Taskbar::STATUS_NORMAL: - unity_launcher_entry_set_urgent(tbEntry, false); - unity_launcher_entry_set_progress_visible(tbEntry, true); - break; - - case Taskbar::STATUS_PAUSED: - unity_launcher_entry_set_urgent(tbEntry, false); - break; - } - } - - void setProgress(double fraction) - { - unity_launcher_entry_set_progress(tbEntry, fraction); - } - -private: - UnityLauncherEntry* tbEntry; -}; - -#elif defined ZEN_MAC -class Taskbar::Pimpl -{ -public: - Pimpl(const wxFrame& window) {} - - ~Pimpl() { setDockText(""); } - - void setStatus(Status status) {} - - void setProgress(double fraction) - { - //no decimal places to make output less noisy - setDockText((numberTo<std::string>(numeric::round(fraction * 100.0)) + '%').c_str()); //no need to internationalize fraction!? - } - -private: - void setDockText(const char* str) - { - try - { - osx::dockIconSetText(str); //throw SysError - } - catch (const zen::SysError& e) { assert(false); } - } -}; - - -#else //no taskbar support -class Taskbar::Pimpl -{ -public: - Pimpl(const wxFrame& window) { throw TaskbarNotAvailable(); } - void setStatus(Status status) {} - void setProgress(double fraction) {} -}; -#endif - -//######################################################################################################## - -Taskbar::Taskbar(const wxFrame& window) : pimpl_(new Pimpl(window)) {} //throw TaskbarNotAvailable -Taskbar::~Taskbar() {} - -void Taskbar::setStatus(Status status) { pimpl_->setStatus(status); } -void Taskbar::setProgress(double fraction) { pimpl_->setProgress(fraction); } diff --git a/ui/taskbar.h b/ui/taskbar.h deleted file mode 100644 index 82e08656..00000000 --- a/ui/taskbar.h +++ /dev/null @@ -1,51 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef TASKBARPROGRESS_H_INCLUDED -#define TASKBARPROGRESS_H_INCLUDED - -#include <memory> -#include <wx/frame.h> - -/* -Windows 7; show progress in windows superbar via ITaskbarList3 Interface: http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx - -Ubuntu: use Unity interface (optional) - -Define HAVE_UBUNTU_UNITY and set: - Compiler flag: `pkg-config --cflags unity` - Linker flag: `pkg-config --libs unity` -*/ - -namespace zen -{ -class TaskbarNotAvailable {}; - -class Taskbar -{ -public: - Taskbar(const wxFrame& window); //throw TaskbarNotAvailable - ~Taskbar(); - - enum Status - { - STATUS_INDETERMINATE, - STATUS_NORMAL, - STATUS_ERROR, - STATUS_PAUSED - }; - - void setStatus(Status status); - void setProgress(double fraction); //between [0, 1] - -private: - class Pimpl; - std::unique_ptr<Pimpl> pimpl_; -}; - -} - -#endif // TASKBARPROGRESS_H_INCLUDED diff --git a/ui/tray_icon.cpp b/ui/tray_icon.cpp deleted file mode 100644 index 28842a80..00000000 --- a/ui/tray_icon.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "tray_icon.h" -#include <zen/basic_math.h> -#include <zen/i18n.h> -#include <wx/taskbar.h> -#include <wx/menu.h> -#include <wx/icon.h> //req. by Linux -#include <wx+/image_tools.h> -#include <wx+/image_resources.h> - -using namespace zen; - - -namespace -{ -void fillRange(wxImage& img, int pixelFirst, int pixelLast, const wxColor& col) //tolerant input range -{ - if (img.IsOk()) - { - const int width = img.GetWidth (); - const int height = img.GetHeight(); - - if (width > 0 && height > 0) - { - pixelFirst = std::max(pixelFirst, 0); - pixelLast = std::min(pixelLast, width * height); - - if (pixelFirst < pixelLast) - { - unsigned char* const bytesBegin = img.GetData() + pixelFirst * 3; - unsigned char* const bytesEnd = img.GetData() + pixelLast * 3; - - for (unsigned char* bytePos = bytesBegin; bytePos < bytesEnd; bytePos += 3) - { - bytePos[0] = col.Red (); - bytePos[1] = col.Green(); - bytePos[2] = col.Blue (); - } - - if (img.HasAlpha()) //make progress indicator fully opaque: - std::fill(img.GetAlpha() + pixelFirst, img.GetAlpha() + pixelLast, wxIMAGE_ALPHA_OPAQUE); - } - } - } -} - - -wxIcon generateProgressIcon(const wxImage& logo, double fraction) //generate icon with progress indicator -{ - if (!logo.IsOk() || logo.GetWidth() <= 0 || logo.GetHeight() <= 0) - return wxIcon(); - - const int pixelCount = logo.GetWidth() * logo.GetHeight(); - const int startFillPixel = numeric::confineCpy(numeric::round(fraction * pixelCount), 0, pixelCount); - - //minor optimization - static std::pair<int, wxIcon> buffer = std::make_pair(-1, wxNullIcon); - - if (buffer.first != startFillPixel) - { - wxImage genImage(logo.Copy()); //workaround wxWidgets' screwed-up design from hell: their copy-construction implements reference-counting WITHOUT copy-on-write! - - //gradually make FFS icon brighter while nearing completion - zen::brighten(genImage, -200 * (1 - fraction)); - - //fill black border row - if (startFillPixel <= pixelCount - genImage.GetWidth()) - { - /* - -------- - ---bbbbb - bbbbSyyy S : start yellow remainder - yyyyyyyy - */ - int bStart = startFillPixel - genImage.GetWidth(); - if (bStart % genImage.GetWidth() != 0) //add one more black pixel, see ascii-art - --bStart; - fillRange(genImage, bStart, startFillPixel, *wxBLACK); - } - else if (startFillPixel < pixelCount) - { - //special handling for last row - /* - -------- - -------- - ---bbbbb - ---bSyyy S : start yellow remainder - */ - int bStart = startFillPixel - genImage.GetWidth() - 1; - int bEnd = (bStart / genImage.GetWidth() + 1) * genImage.GetWidth(); - - fillRange(genImage, bStart, bEnd, *wxBLACK); - fillRange(genImage, startFillPixel - 1, startFillPixel, *wxBLACK); - } - - //fill yellow remainder - fillRange(genImage, startFillPixel, pixelCount, wxColour(240, 200, 0)); - - buffer.second.CopyFromBitmap(wxBitmap(genImage)); - } - - return buffer.second; -} - -//------------------------------------------------------------------------------------------------ - -enum Selection -{ - CONTEXT_RESTORE = 1 //wxWidgets: "A MenuItem ID of zero does not work under Mac" -}; -} - - -class FfsTrayIcon::TaskBarImpl : public wxTaskBarIcon -{ -public: - TaskBarImpl(const std::function<void()>& onRequestResume) : onRequestResume_(onRequestResume) - { - Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxEventHandler(TaskBarImpl::OnDoubleClick), nullptr, this); - - //Windows User Experience Guidelines: show the context menu rather than doing *nothing* on single left clicks; however: - //MSDN: "Double-clicking the left mouse button actually generates a sequence of four messages: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, and WM_LBUTTONUP." - //Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645606%28v=vs.85%29.aspx - //=> the only way to distinguish single left click and double-click is to wait wxSystemSettings::GetMetric(wxSYS_DCLICK_MSEC) (480ms) which is way too long! - } - - //virtual ~TaskBarImpl(){} - - void dontCallbackAnymore() { onRequestResume_ = nullptr; } - -private: - virtual wxMenu* CreatePopupMenu() - { - if (!onRequestResume_) - return nullptr; - - wxMenu* contextMenu = new wxMenu; - - wxMenuItem* defaultItem = new wxMenuItem(contextMenu, CONTEXT_RESTORE, _("&Restore")); - //wxWidgets font messup: - //1. font must be set *before* wxMenu::Append()! - //2. don't use defaultItem->GetFont(); making it bold creates a huge font size for some reason -#ifdef ZEN_WIN //no wxMenuItem::SetFont() on Linux and OS X: wasn't wxWidgets supposed to be *portable* at some point in time????? - defaultItem->SetFont(wxNORMAL_FONT->Bold()); //make default selection bold/align with double-click -#endif - contextMenu->Append(defaultItem); - - //event handling - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TaskBarImpl::OnContextMenuSelection), nullptr, this); - - return contextMenu; //ownership transferred to caller - } - - void OnContextMenuSelection(wxCommandEvent& event) - { - switch (static_cast<Selection>(event.GetId())) - { - case CONTEXT_RESTORE: - if (onRequestResume_) - onRequestResume_(); - break; - } - } - - void OnDoubleClick(wxEvent& event) - { - if (onRequestResume_) - onRequestResume_(); - } - - //void OnLeftDownClick(wxEvent& event) - //{ - // //copied from wxTaskBarIconBase::OnRightButtonDown() - // if (wxMenu* menu = CreatePopupMenu()) - // { - // PopupMenu(menu); - // delete menu; - // } - //} - - std::function<void()> onRequestResume_; -}; - - -FfsTrayIcon::FfsTrayIcon(const std::function<void()>& onRequestResume) : - trayIcon(new TaskBarImpl(onRequestResume)), - activeFraction(1), //show FFS logo by default -#if defined ZEN_WIN || defined ZEN_MAC //16x16 seems to be the only size that is shown correctly on OS X - logo(getResourceImage(L"FFS_tray_16x16").ConvertToImage()) -#elif defined ZEN_LINUX - logo(getResourceImage(L"FFS_tray_24x24").ConvertToImage()) -#endif -{ - trayIcon->SetIcon(generateProgressIcon(logo, activeFraction), L"FreeFileSync"); -} - - -FfsTrayIcon::~FfsTrayIcon() -{ - trayIcon->dontCallbackAnymore(); //TaskBarImpl has longer lifetime than FfsTrayIcon: avoid callback! - - /* - This is not working correctly on OS X! It seems both wxTaskBarIcon::RemoveIcon() and ~wxTaskBarIcon() are broken and do NOT immediately - remove the icon from the system tray! Only some time later in the event loop which called these functions they will be removed. - Maybe some system component has still shared ownership? Objective C auto release pools are freed at the end of the current event loop... - Anyway, wxWidgets fails to disconnect the wxTaskBarIcon event handlers before calling "[m_statusitem release]"! - - => !!!clicking on the icon after ~wxTaskBarIcon ran crashes the application!!! - - - if ~wxTaskBarIcon() ran from the SyncProgressDialog::updateGui() event loop (e.g. user manually clicking the icon) => icon removed on return - - if ~wxTaskBarIcon() ran from SyncProgressDialog::closeWindowDirectly() => leaves the icon dangling until user closes this dialog and outter event loop runs! - */ - - trayIcon->RemoveIcon(); //required on Windows: unlike on OS X, wxPendingDelete does not kick in before main event loop! - //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking) - wxPendingDelete.Append(trayIcon); //identical to wxTaskBarIconBase::Destroy() in wxWidgets 2.9.5 -} - - -void FfsTrayIcon::setToolTip(const wxString& toolTip) -{ - activeToolTip = toolTip; - trayIcon->SetIcon(generateProgressIcon(logo, activeFraction), activeToolTip); //another wxWidgets design bug: non-orthogonal method! -} - - -void FfsTrayIcon::setProgress(double fraction) -{ - activeFraction = fraction; - trayIcon->SetIcon(generateProgressIcon(logo, activeFraction), activeToolTip); -} diff --git a/ui/tray_icon.h b/ui/tray_icon.h deleted file mode 100644 index 24c97eb0..00000000 --- a/ui/tray_icon.h +++ /dev/null @@ -1,45 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef TRAYICON_H_84217830427534285 -#define TRAYICON_H_84217830427534285 - -#include <functional> -#include <wx/image.h> - -/* -show tray icon with progress during lifetime of this instance - -ATTENTION: wxWidgets never assumes that an object indirectly destroys itself while processing an event! - this includes wxEvtHandler-derived objects!!! - it seems ProcessEvent() works (on Windows), but AddPendingEvent() will crash since it uses "this" after the event processing! - -=> don't derive from wxEvtHandler or any other wxWidgets object here!!!!!! -=> use simple std::function as callback instead => instance may now be safely deleted in callback! -*/ - -class FfsTrayIcon -{ -public: - FfsTrayIcon(const std::function<void()>& onRequestResume); //callback only held during lifetime of this instance - ~FfsTrayIcon(); - - void setToolTip(const wxString& toolTip); - void setProgress(double fraction); //number between [0, 1], for small progress indicator - -private: - FfsTrayIcon(const FfsTrayIcon&); //=delete - FfsTrayIcon& operator=(const FfsTrayIcon&); //=delete - - class TaskBarImpl; - TaskBarImpl* trayIcon; - - wxString activeToolTip; - double activeFraction; - wxImage logo; -}; - -#endif //TRAYICON_H_84217830427534285 diff --git a/ui/tree_view.cpp b/ui/tree_view.cpp deleted file mode 100644 index 01eb8696..00000000 --- a/ui/tree_view.cpp +++ /dev/null @@ -1,1334 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include <set> -#include "tree_view.h" -#include <wx/settings.h> -#include <wx/menu.h> -#include <zen/i18n.h> -#include <zen/utf.h> -#include <zen/stl_tools.h> -#include <zen/format_unit.h> -#include <wx+/rtl.h> -#include <wx+/context_menu.h> -#include <wx+/image_resources.h> -#include "../lib/icon_buffer.h" - -using namespace zen; - - -inline -void TreeView::compressNode(Container& cont) //remove single-element sub-trees -> gain clarity + usability (call *after* inclusion check!!!) -{ - if (cont.subDirs.empty() || //single files node or... - (cont.firstFileId == nullptr && //single dir node... - cont.subDirs.size() == 1 && // - cont.subDirs[0].firstFileId == nullptr && //...that is empty - cont.subDirs[0].subDirs.empty())) // - { - cont.subDirs.clear(); - cont.firstFileId = nullptr; - } -} - - -template <class Function> //(const FileSystemObject&) -> bool -void TreeView::extractVisibleSubtree(HierarchyObject& hierObj, //in - TreeView::Container& cont, //out - Function pred) -{ - auto getBytes = [](const FilePair& fileObj) -> UInt64 //MSVC screws up miserably if we put this lambda into std::for_each - { - //give accumulated bytes the semantics of a sync preview! - if (fileObj.isActive()) - switch (fileObj.getSyncDir()) - { - case SyncDirection::LEFT: - return fileObj.getFileSize<RIGHT_SIDE>(); - case SyncDirection::RIGHT: - return fileObj.getFileSize<LEFT_SIDE>(); - case SyncDirection::NONE: - break; - } - return std::max(fileObj.getFileSize<LEFT_SIDE>(), fileObj.getFileSize<RIGHT_SIDE>()); - }; - - cont.firstFileId = nullptr; - for (FilePair& fileObj : hierObj.refSubFiles()) - if (pred(fileObj)) - { - cont.bytesNet += getBytes(fileObj); - ++cont.itemCountNet; - - if (!cont.firstFileId) - cont.firstFileId = fileObj.getId(); - } - - for (SymlinkPair& linkObj : hierObj.refSubLinks()) - if (pred(linkObj)) - { - ++cont.itemCountNet; - - if (!cont.firstFileId) - cont.firstFileId = linkObj.getId(); - } - - cont.bytesGross += cont.bytesNet; - cont.itemCountGross += cont.itemCountNet; - - cont.subDirs.reserve(hierObj.refSubDirs().size()); //avoid expensive reallocations! - - for (DirPair& subDirObj : hierObj.refSubDirs()) - { - const bool included = pred(subDirObj); - - cont.subDirs.push_back(TreeView::DirNodeImpl()); // - auto& subDirView = cont.subDirs.back(); - TreeView::extractVisibleSubtree(subDirObj, subDirView, pred); - if (included) - ++subDirView.itemCountGross; - - cont.bytesGross += subDirView.bytesGross; - cont.itemCountGross += subDirView.itemCountGross; - - if (!included && !subDirView.firstFileId && subDirView.subDirs.empty()) - cont.subDirs.pop_back(); - else - { - subDirView.objId = subDirObj.getId(); - compressNode(subDirView); - } - } -} - - -namespace -{ -//generate nice percentage numbers which precisely sum up to 100 -void calcPercentage(std::vector<std::pair<UInt64, int*>>& workList) -{ - const UInt64 total = std::accumulate(workList.begin(), workList.end(), UInt64(), - [](UInt64 sum, const std::pair<UInt64, int*>& pair) { return sum + pair.first; }); - - if (total == 0U) //this case doesn't work with the error minimizing algorithm below - { - for (std::pair<UInt64, int*>& pair : workList) - *pair.second = 0; - return; - } - - int remainingPercent = 100; - for (std::pair<UInt64, int*>& pair : workList) - { - *pair.second = to<int>(pair.first * 100U / total); //round down - remainingPercent -= *pair.second; - } - assert(remainingPercent >= 0); - assert(remainingPercent < static_cast<int>(workList.size())); - - //distribute remaining percent so that overall error is minimized as much as possible: - remainingPercent = std::min(remainingPercent, static_cast<int>(workList.size())); - if (remainingPercent > 0) - { - std::nth_element(workList.begin(), workList.begin() + remainingPercent - 1, workList.end(), - [total](const std::pair<UInt64, int*>& lhs, const std::pair<UInt64, int*>& rhs) - { - return lhs.first * 100U % total > rhs.first * 100U % total; - }); - - std::for_each(workList.begin(), workList.begin() + remainingPercent, [&](std::pair<UInt64, int*>& pair) { ++*pair.second; }); - } -} -} - - -template <bool ascending> -struct TreeView::LessShortName -{ - bool operator()(const TreeLine& lhs, const TreeLine& rhs) - { - //files last (irrespective of sort direction) - if (lhs.type_ == TreeView::TYPE_FILES) - return false; - else if (rhs.type_ == TreeView::TYPE_FILES) - return true; - - if (lhs.type_ != rhs.type_) // - return lhs.type_ < rhs.type_; //shouldn't happen! Root nodes are never sorted - - switch (lhs.type_) - { - case TreeView::TYPE_ROOT: - return false; - - case TreeView::TYPE_DIRECTORY: - { - const auto* dirObjL = dynamic_cast<const DirPair*>(FileSystemObject::retrieve(static_cast<const TreeView::DirNodeImpl*>(lhs.node_)->objId)); - const auto* dirObjR = dynamic_cast<const DirPair*>(FileSystemObject::retrieve(static_cast<const TreeView::DirNodeImpl*>(rhs.node_)->objId)); - - if (!dirObjL) //might be pathologic, but it's covered - return false; - else if (!dirObjR) - return true; - - return makeSortDirection(LessFilename(), Int2Type<ascending>())(dirObjL->getObjShortName(), dirObjR->getObjShortName()); - } - - case TreeView::TYPE_FILES: - break; - } - assert(false); - return false; //:= all equal - } -}; - - -template <bool ascending> -void TreeView::sortSingleLevel(std::vector<TreeLine>& items, ColumnTypeNavi columnType) -{ - auto getBytes = [](const TreeLine& line) -> UInt64 - { - switch (line.type_) - { - case TreeView::TYPE_ROOT: - case TreeView::TYPE_DIRECTORY: - return line.node_->bytesGross; - case TreeView::TYPE_FILES: - return line.node_->bytesNet; - } - assert(false); - return 0U; - }; - - auto getCount = [](const TreeLine& line) -> int - { - switch (line.type_) - { - case TreeView::TYPE_ROOT: - case TreeView::TYPE_DIRECTORY: - return line.node_->itemCountGross; - - case TreeView::TYPE_FILES: - return line.node_->itemCountNet; - } - assert(false); - return 0; - }; - - const auto lessBytes = [&](const TreeLine& lhs, const TreeLine& rhs) { return getBytes(lhs) < getBytes(rhs); }; - const auto lessCount = [&](const TreeLine& lhs, const TreeLine& rhs) { return getCount(lhs) < getCount(rhs); }; - - switch (columnType) - { - case COL_TYPE_NAVI_BYTES: - std::sort(items.begin(), items.end(), makeSortDirection(lessBytes, Int2Type<ascending>())); - break; - - case COL_TYPE_NAVI_DIRECTORY: - std::sort(items.begin(), items.end(), LessShortName<ascending>()); - break; - - case COL_TYPE_NAVI_ITEM_COUNT: - std::sort(items.begin(), items.end(), makeSortDirection(lessCount, Int2Type<ascending>())); - break; - } -} - - -void TreeView::getChildren(const Container& cont, unsigned int level, std::vector<TreeLine>& output) -{ - output.clear(); - output.reserve(cont.subDirs.size() + 1); //keep pointers in "workList" valid - std::vector<std::pair<UInt64, int*>> workList; - - std::for_each(cont.subDirs.begin(), cont.subDirs.end(), - [&output, level, &workList](const DirNodeImpl& subDir) - { - output.push_back(TreeView::TreeLine(level, 0, &subDir, TreeView::TYPE_DIRECTORY)); - workList.push_back(std::make_pair(subDir.bytesGross, &output.back().percent_)); - }); - - if (cont.firstFileId) - { - output.push_back(TreeLine(level, 0, &cont, TreeView::TYPE_FILES)); - workList.push_back(std::make_pair(cont.bytesNet, &output.back().percent_)); - } - calcPercentage(workList); - - if (sortAscending) - sortSingleLevel<true>(output, sortColumn); - else - sortSingleLevel<false>(output, sortColumn); -} - - -void TreeView::applySubView(std::vector<RootNodeImpl>&& newView) -{ - //preserve current node expansion status - auto getHierAlias = [](const TreeView::TreeLine& tl) -> const HierarchyObject* - { - switch (tl.type_) - { - case TreeView::TYPE_ROOT: - return static_cast<const RootNodeImpl*>(tl.node_)->baseDirObj.get(); - - case TreeView::TYPE_DIRECTORY: - if (auto dirObj = dynamic_cast<const DirPair*>(FileSystemObject::retrieve(static_cast<const DirNodeImpl*>(tl.node_)->objId))) - return dirObj; - break; - - case TreeView::TYPE_FILES: - break; //none!!! - } - return nullptr; - }; - - zen::hash_set<const HierarchyObject*> expandedNodes; - if (!flatTree.empty()) - { - auto it = flatTree.begin(); - for (auto iterNext = flatTree.begin() + 1; iterNext != flatTree.end(); ++iterNext, ++it) - if (it->level_ < iterNext->level_) - if (auto hierObj = getHierAlias(*it)) - expandedNodes.insert(hierObj); - } - - //update view on full data - folderCmpView.swap(newView); //newView may be an alias for folderCmpView! see sorting! - - //set default flat tree - flatTree.clear(); - - if (folderCmp.size() == 1) //single folder pair case (empty pairs were already removed!) do NOT use folderCmpView for this check! - { - if (!folderCmpView.empty()) //it may really be! - getChildren(folderCmpView[0], 0, flatTree); //do not show root - } - else - { - std::vector<std::pair<UInt64, int*>> workList; - flatTree.reserve(folderCmpView.size()); //keep pointers in "workList" valid - - std::for_each(folderCmpView.begin(), folderCmpView.end(), - [&](const RootNodeImpl& root) - { - flatTree.push_back(TreeView::TreeLine(0, 0, &root, TreeView::TYPE_ROOT)); - workList.push_back(std::make_pair(root.bytesGross, &flatTree.back().percent_)); - }); - - calcPercentage(workList); - } - - //restore node expansion status - for (size_t row = 0; row < flatTree.size(); ++row) //flatTree size changes during loop! - { - const TreeLine& line = flatTree[row]; - - if (auto hierObj = getHierAlias(line)) - if (expandedNodes.find(hierObj) != expandedNodes.end()) - { - std::vector<TreeLine> newLines; - getChildren(*line.node_, line.level_ + 1, newLines); - - flatTree.insert(flatTree.begin() + row + 1, newLines.begin(), newLines.end()); - } - } -} - - -template <class Predicate> -void TreeView::updateView(Predicate pred) -{ - //update view on full data - std::vector<RootNodeImpl> newView; - newView.reserve(folderCmp.size()); //avoid expensive reallocations! - - std::for_each(folderCmp.begin(), folderCmp.end(), - [&](const std::shared_ptr<BaseDirPair>& baseObj) - { - newView.push_back(TreeView::RootNodeImpl()); - RootNodeImpl& root = newView.back(); - this->extractVisibleSubtree(*baseObj, root, pred); //"this->" is bogus for a static method, but GCC screws this one up - - //warning: the following lines are almost 1:1 copy from extractVisibleSubtree: - //however we *cannot* reuse code here; this were only possible if we could replace "std::vector<RootNodeImpl>" by "Container"! - if (!root.firstFileId && root.subDirs.empty()) - newView.pop_back(); - else - { - root.baseDirObj = baseObj; - this->compressNode(root); //"this->" required by two-pass lookup as enforced by GCC 4.7 - } - }); - - lastViewFilterPred = pred; - applySubView(std::move(newView)); -} - - -void TreeView::setSortDirection(ColumnTypeNavi colType, bool ascending) //apply permanently! -{ - sortColumn = colType; - sortAscending = ascending; - - //reapply current view - applySubView(std::move(folderCmpView)); -} - - -bool TreeView::getDefaultSortDirection(ColumnTypeNavi colType) -{ - switch (colType) - { - case COL_TYPE_NAVI_BYTES: - return false; - case COL_TYPE_NAVI_DIRECTORY: - return true; - case COL_TYPE_NAVI_ITEM_COUNT: - return false; - } - assert(false); - return true; -} - - -TreeView::NodeStatus TreeView::getStatus(size_t row) const -{ - if (row < flatTree.size()) - { - if (row + 1 < flatTree.size() && flatTree[row + 1].level_ > flatTree[row].level_) - return TreeView::STATUS_EXPANDED; - - //it's either reduced or empty - switch (flatTree[row].type_) - { - case TreeView::TYPE_DIRECTORY: - case TreeView::TYPE_ROOT: - return flatTree[row].node_->firstFileId || !flatTree[row].node_->subDirs.empty() ? TreeView::STATUS_REDUCED : TreeView::STATUS_EMPTY; - - case TreeView::TYPE_FILES: - return TreeView::STATUS_EMPTY; - } - } - return TreeView::STATUS_EMPTY; -} - - -void TreeView::expandNode(size_t row) -{ - if (getStatus(row) != TreeView::STATUS_REDUCED) - { - assert(false); - return; - } - - if (row < flatTree.size()) - { - std::vector<TreeLine> newLines; - - switch (flatTree[row].type_) - { - case TreeView::TYPE_ROOT: - case TreeView::TYPE_DIRECTORY: - getChildren(*flatTree[row].node_, flatTree[row].level_ + 1, newLines); - break; - case TreeView::TYPE_FILES: - break; - } - flatTree.insert(flatTree.begin() + row + 1, newLines.begin(), newLines.end()); - } -} - - -void TreeView::reduceNode(size_t row) -{ - if (row < flatTree.size()) - { - const unsigned int parentLevel = flatTree[row].level_; - - bool done = false; - flatTree.erase(std::remove_if(flatTree.begin() + row + 1, flatTree.end(), - [&](const TreeLine& line) -> bool - { - if (done) - return false; - if (line.level_ > parentLevel) - return true; - else - { - done = true; - return false; - } - }), flatTree.end()); - } -} - - -ptrdiff_t TreeView::getParent(size_t row) const -{ - if (row < flatTree.size()) - { - const auto level = flatTree[row].level_; - - while (row-- > 0) - if (flatTree[row].level_ < level) - return row; - } - return -1; -} - - -void TreeView::updateCmpResult(bool hideFiltered, - bool leftOnlyFilesActive, - bool rightOnlyFilesActive, - bool leftNewerFilesActive, - bool rightNewerFilesActive, - bool differentFilesActive, - bool equalFilesActive, - bool conflictFilesActive) -{ - updateView([hideFiltered, //make sure the predicate can be stored safely! - leftOnlyFilesActive, - rightOnlyFilesActive, - leftNewerFilesActive, - rightNewerFilesActive, - differentFilesActive, - equalFilesActive, - conflictFilesActive](const FileSystemObject& fsObj) -> bool - { - if (hideFiltered && !fsObj.isActive()) - return false; - - switch (fsObj.getCategory()) - { - case FILE_LEFT_SIDE_ONLY: - return leftOnlyFilesActive; - case FILE_RIGHT_SIDE_ONLY: - return rightOnlyFilesActive; - case FILE_LEFT_NEWER: - return leftNewerFilesActive; - case FILE_RIGHT_NEWER: - return rightNewerFilesActive; - case FILE_DIFFERENT: - return differentFilesActive; - case FILE_EQUAL: - case FILE_DIFFERENT_METADATA: //= sub-category of equal - return equalFilesActive; - case FILE_CONFLICT: - return conflictFilesActive; - } - assert(false); - return true; - }); -} - - -void TreeView::updateSyncPreview(bool hideFiltered, - bool syncCreateLeftActive, - bool syncCreateRightActive, - bool syncDeleteLeftActive, - bool syncDeleteRightActive, - bool syncDirOverwLeftActive, - bool syncDirOverwRightActive, - bool syncDirNoneActive, - bool syncEqualActive, - bool conflictFilesActive) -{ - updateView([hideFiltered, //make sure the predicate can be stored safely! - syncCreateLeftActive, - syncCreateRightActive, - syncDeleteLeftActive, - syncDeleteRightActive, - syncDirOverwLeftActive, - syncDirOverwRightActive, - syncDirNoneActive, - syncEqualActive, - conflictFilesActive](const FileSystemObject& fsObj) -> bool - { - if (hideFiltered && !fsObj.isActive()) - return false; - - switch (fsObj.getSyncOperation()) - { - case SO_CREATE_NEW_LEFT: - return syncCreateLeftActive; - case SO_CREATE_NEW_RIGHT: - return syncCreateRightActive; - case SO_DELETE_LEFT: - return syncDeleteLeftActive; - case SO_DELETE_RIGHT: - return syncDeleteRightActive; - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: - case SO_MOVE_RIGHT_SOURCE: - case SO_MOVE_RIGHT_TARGET: - return syncDirOverwRightActive; - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: - case SO_MOVE_LEFT_SOURCE: - case SO_MOVE_LEFT_TARGET: - return syncDirOverwLeftActive; - case SO_DO_NOTHING: - return syncDirNoneActive; - case SO_EQUAL: - return syncEqualActive; - case SO_UNRESOLVED_CONFLICT: - return conflictFilesActive; - } - assert(false); - return true; - }); -} - - -void TreeView::setData(FolderComparison& newData) -{ - std::vector<TreeLine >().swap(flatTree); //free mem - std::vector<RootNodeImpl>().swap(folderCmpView); // - folderCmp = newData; - - //remove truly empty folder pairs as early as this: we want to distinguish single/multiple folder pair cases by looking at "folderCmp" - vector_remove_if(folderCmp, [](const std::shared_ptr<BaseDirPair>& baseObj) - { - return baseObj->getBaseDirPf<LEFT_SIDE >().empty() && - baseObj->getBaseDirPf<RIGHT_SIDE>().empty(); - }); -} - - -std::unique_ptr<TreeView::Node> TreeView::getLine(size_t row) const -{ - if (row < flatTree.size()) - { - const auto level = flatTree[row].level_; - const int percent = flatTree[row].percent_; - - switch (flatTree[row].type_) - { - case TreeView::TYPE_ROOT: - { - const auto* root = static_cast<const TreeView::RootNodeImpl*>(flatTree[row].node_); - return make_unique<TreeView::RootNode>(percent, root->bytesGross, root->itemCountGross, getStatus(row), *(root->baseDirObj)); - } - break; - - case TreeView::TYPE_DIRECTORY: - { - const auto* dir = static_cast<const TreeView::DirNodeImpl*>(flatTree[row].node_); - if (auto dirObj = dynamic_cast<DirPair*>(FileSystemObject::retrieve(dir->objId))) - return make_unique<TreeView::DirNode>(percent, dir->bytesGross, dir->itemCountGross, level, getStatus(row), *dirObj); - } - break; - - case TreeView::TYPE_FILES: - { - const auto* parentDir = flatTree[row].node_; - if (auto firstFile = FileSystemObject::retrieve(parentDir->firstFileId)) - { - std::vector<FileSystemObject*> filesAndLinks; - HierarchyObject& parent = firstFile->parent(); - - //lazy evaluation: recheck "lastViewFilterPred" again rather than buffer and bloat "lastViewFilterPred" - for (FileSystemObject& fsObj : parent.refSubFiles()) - if (lastViewFilterPred(fsObj)) - filesAndLinks.push_back(&fsObj); - - for (FileSystemObject& fsObj : parent.refSubLinks()) - if (lastViewFilterPred(fsObj)) - filesAndLinks.push_back(&fsObj); - - return make_unique<TreeView::FilesNode>(percent, parentDir->bytesNet, parentDir->itemCountNet, level, filesAndLinks); - } - } - break; - } - } - return nullptr; -} - -//########################################################################################################## - -namespace -{ -wxString getShortDisplayNameForFolderPair(const Zstring& dirLeftPf, const Zstring& dirRightPf) //post-fixed with separator -{ - assert(endsWith(dirLeftPf, FILE_NAME_SEPARATOR) || dirLeftPf .empty()); - assert(endsWith(dirRightPf, FILE_NAME_SEPARATOR) || dirRightPf.empty()); - - auto itL = dirLeftPf .end(); - auto itR = dirRightPf.end(); - - for (;;) - { - auto itLPrev = find_last(dirLeftPf .begin(), itL, FILE_NAME_SEPARATOR); - auto itRPrev = find_last(dirRightPf.begin(), itR, FILE_NAME_SEPARATOR); - - if (itLPrev == itL || - itRPrev == itR) - { - if (itLPrev == itL) - itLPrev = dirLeftPf.begin(); - else - ++itLPrev; //skip separator - if (itRPrev == itR) - itRPrev = dirRightPf.begin(); - else - ++itRPrev; - - if (equal(itLPrev, itL, itRPrev, itR)) - { - itL = itLPrev; - itR = itRPrev; - } - break; - } - - if (!equal(itLPrev, itL, itRPrev, itR)) - break; - itL = itLPrev; - itR = itRPrev; - } - - Zstring commonPostfix(itL, dirLeftPf.end()); - if (startsWith(commonPostfix, FILE_NAME_SEPARATOR)) - commonPostfix = afterFirst(commonPostfix, FILE_NAME_SEPARATOR); - if (endsWith(commonPostfix, FILE_NAME_SEPARATOR)) - commonPostfix.resize(commonPostfix.size() - 1); - - if (commonPostfix.empty()) - { - auto getLastComponent = [](const Zstring& dirPf) { return utfCvrtTo<wxString>(afterLast(beforeLast(dirPf, FILE_NAME_SEPARATOR), FILE_NAME_SEPARATOR)); }; //returns the whole string if term not found - if (dirLeftPf.empty()) - return getLastComponent(dirRightPf); - else if (dirRightPf.empty()) - return getLastComponent(dirLeftPf); - else - return getLastComponent(dirLeftPf) + L" \u2212 " + //= unicode minus - getLastComponent(dirRightPf); - } - return utfCvrtTo<wxString>(commonPostfix); -} - - -const wxColour COLOR_LEVEL0(0xcc, 0xcc, 0xff); -const wxColour COLOR_LEVEL1(0xcc, 0xff, 0xcc); -const wxColour COLOR_LEVEL2(0xff, 0xff, 0x99); - -const wxColour COLOR_LEVEL3(0xcc, 0xcc, 0xcc); -const wxColour COLOR_LEVEL4(0xff, 0xcc, 0xff); -const wxColour COLOR_LEVEL5(0x99, 0xff, 0xcc); - -const wxColour COLOR_LEVEL6(0xcc, 0xcc, 0x99); -const wxColour COLOR_LEVEL7(0xff, 0xcc, 0xcc); -const wxColour COLOR_LEVEL8(0xcc, 0xff, 0x99); - -const wxColour COLOR_LEVEL9 (0xff, 0xff, 0xcc); -const wxColour COLOR_LEVEL10(0xcc, 0xff, 0xff); -const wxColour COLOR_LEVEL11(0xff, 0xcc, 0x99); - -const wxColour COLOR_PERCENTAGE_BORDER (198, 198, 198); -const wxColour COLOR_PERCENTAGE_BACKGROUND(0xf8, 0xf8, 0xf8); - -//const wxColor COLOR_TREE_SELECTION_GRADIENT_FROM = wxColor( 89, 255, 99); //green: HSV: 88, 255, 172 -//const wxColor COLOR_TREE_SELECTION_GRADIENT_TO = wxColor(225, 255, 227); // HSV: 88, 255, 240 -const wxColor COLOR_TREE_SELECTION_GRADIENT_FROM = getColorSelectionGradientFrom(); -const wxColor COLOR_TREE_SELECTION_GRADIENT_TO = getColorSelectionGradientTo (); - -const int iconSizeSmall = IconBuffer::getSize(IconBuffer::SIZE_SMALL); - -class GridDataNavi : private wxEvtHandler, public GridData -{ -public: - GridDataNavi(Grid& grid, const std::shared_ptr<TreeView>& treeDataView) : treeDataView_(treeDataView), - fileIcon(IconBuffer(IconBuffer::SIZE_SMALL).genericFileIcon()), - dirIcon (IconBuffer(IconBuffer::SIZE_SMALL).genericDirIcon ()), - rootBmp(getResourceImage(L"rootFolder").ConvertToImage().Scale(iconSizeSmall, iconSizeSmall, wxIMAGE_QUALITY_HIGH)), - widthNodeIcon(iconSizeSmall), - widthLevelStep(widthNodeIcon), - widthNodeStatus(getResourceImage(L"nodeExpanded").GetWidth()), - grid_(grid), - showPercentBar(true) - { - grid.getMainWin().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(GridDataNavi::onKeyDown), nullptr, this); - grid.Connect(EVENT_GRID_MOUSE_LEFT_DOWN, GridClickEventHandler(GridDataNavi::onMouseLeft ), nullptr, this); - grid.Connect(EVENT_GRID_MOUSE_LEFT_DOUBLE, GridClickEventHandler(GridDataNavi::onMouseLeftDouble ), nullptr, this); - grid.Connect(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, GridClickEventHandler(GridDataNavi::onGridLabelContext), nullptr, this ); - grid.Connect(EVENT_GRID_COL_LABEL_MOUSE_LEFT, GridClickEventHandler(GridDataNavi::onGridLabelLeftClick ), nullptr, this ); - } - - void setShowPercentage(bool value) { showPercentBar = value; grid_.Refresh(); } - bool getShowPercentage() const { return showPercentBar; } - -private: - virtual size_t getRowCount() const { return treeDataView_ ? treeDataView_->linesTotal() : 0; } - - virtual wxString getToolTip(size_t row, ColumnType colType) const override - { - switch (static_cast<ColumnTypeNavi>(colType)) - { - case COL_TYPE_NAVI_BYTES: - case COL_TYPE_NAVI_ITEM_COUNT: - break; - - case COL_TYPE_NAVI_DIRECTORY: - if (treeDataView_) - if (std::unique_ptr<TreeView::Node> node = treeDataView_->getLine(row)) - if (const TreeView::RootNode* root = dynamic_cast<const TreeView::RootNode*>(node.get())) - { - const wxString& dirLeft = utfCvrtTo<wxString>(root->baseDirObj_.getBaseDirPf<LEFT_SIDE >()); - const wxString& dirRight = utfCvrtTo<wxString>(root->baseDirObj_.getBaseDirPf<RIGHT_SIDE>()); - if (dirLeft.empty()) - return dirRight; - else if (dirRight.empty()) - return dirLeft; - return dirLeft + L" \u2212 \n" + dirRight; //\u2212 = unicode minus - } - break; - } - return wxString(); - } - - virtual wxString getValue(size_t row, ColumnType colType) const - { - if (treeDataView_) - { - if (std::unique_ptr<TreeView::Node> node = treeDataView_->getLine(row)) - switch (static_cast<ColumnTypeNavi>(colType)) - { - case COL_TYPE_NAVI_BYTES: - return filesizeToShortString(to<Int64>(node->bytes_)); - - case COL_TYPE_NAVI_DIRECTORY: - if (const TreeView::RootNode* root = dynamic_cast<const TreeView::RootNode*>(node.get())) - return getShortDisplayNameForFolderPair(root->baseDirObj_.getBaseDirPf<LEFT_SIDE >(), - root->baseDirObj_.getBaseDirPf<RIGHT_SIDE>()); - else if (const TreeView::DirNode* dir = dynamic_cast<const TreeView::DirNode*>(node.get())) - return utfCvrtTo<wxString>(dir->dirObj_.getObjShortName()); - else if (dynamic_cast<const TreeView::FilesNode*>(node.get())) - return _("Files"); - break; - - case COL_TYPE_NAVI_ITEM_COUNT: - return toGuiString(node->itemCount_); - } - } - return wxString(); - } - - virtual void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override - { - wxRect rectInside = drawColumnLabelBorder(dc, rect); - drawColumnLabelBackground(dc, rectInside, highlighted); - - rectInside.x += COLUMN_GAP_LEFT; - rectInside.width -= COLUMN_GAP_LEFT; - drawColumnLabelText(dc, rectInside, getColumnLabel(colType)); - - if (treeDataView_) //draw sort marker - { - auto sortInfo = treeDataView_->getSortDirection(); - if (colType == static_cast<ColumnType>(sortInfo.first)) - { - const wxBitmap& marker = getResourceImage(sortInfo.second ? L"sortAscending" : L"sortDescending"); - wxPoint markerBegin = rectInside.GetTopLeft() + wxPoint((rectInside.width - marker.GetWidth()) / 2, 0); - dc.DrawBitmap(marker, markerBegin, true); //respect 2-pixel gap - } - } - } - - static const int GAP_SIZE = 2; - - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override - { - if (enabled) - { - if (selected) - dc.GradientFillLinear(rect, COLOR_TREE_SELECTION_GRADIENT_FROM, COLOR_TREE_SELECTION_GRADIENT_TO, wxEAST); - //ignore focus - else - clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - } - else - clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - } - - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool selected) override - { - //wxRect rectTmp= drawCellBorder(dc, rect); - wxRect rectTmp = rect; - - // Partitioning: - // ________________________________________________________________________________ - // | space | gap | percentage bar | 2 x gap | node status | gap |icon | gap | rest | - // -------------------------------------------------------------------------------- - // -> synchronize renderCell() <-> getBestSize() <-> onMouseLeft() - - if (static_cast<ColumnTypeNavi>(colType) == COL_TYPE_NAVI_DIRECTORY && treeDataView_) - { - if (std::unique_ptr<TreeView::Node> node = treeDataView_->getLine(row)) - { - ////clear first secion: - //clearArea(dc, wxRect(rect.GetTopLeft(), wxSize( - // node->level_ * widthLevelStep + GAP_SIZE + //width - // (showPercentBar ? widthPercentBar + 2 * GAP_SIZE : 0) + // - // widthNodeStatus + GAP_SIZE + widthNodeIcon + GAP_SIZE, // - // rect.height)), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - - //consume space - rectTmp.x += static_cast<int>(node->level_) * widthLevelStep; - rectTmp.width -= static_cast<int>(node->level_) * widthLevelStep; - - rectTmp.x += GAP_SIZE; - rectTmp.width -= GAP_SIZE; - - if (rectTmp.width > 0) - { - //percentage bar - if (showPercentBar) - { - const wxColour brushCol = [&]() -> wxColour - { - switch (node->level_ % 12) - { - case 0: - return COLOR_LEVEL0; - case 1: - return COLOR_LEVEL1; - case 2: - return COLOR_LEVEL2; - case 3: - return COLOR_LEVEL3; - case 4: - return COLOR_LEVEL4; - case 5: - return COLOR_LEVEL5; - case 6: - return COLOR_LEVEL6; - case 7: - return COLOR_LEVEL7; - case 8: - return COLOR_LEVEL8; - case 9: - return COLOR_LEVEL9; - case 10: - return COLOR_LEVEL10; - default: - return COLOR_LEVEL11; - } - }(); - - const wxRect areaPerc(rectTmp.x, rectTmp.y + 2, widthPercentBar, rectTmp.height - 4); - { - //clear background - wxDCPenChanger dummy (dc, COLOR_PERCENTAGE_BORDER); - wxDCBrushChanger dummy2(dc, COLOR_PERCENTAGE_BACKGROUND); - dc.DrawRectangle(areaPerc); - - //inner area - dc.SetPen (brushCol); - dc.SetBrush(brushCol); - - wxRect areaPercTmp = areaPerc; - areaPercTmp.Deflate(1); //do not include border - areaPercTmp.width = numeric::round(areaPercTmp.width * node->percent_ / 100.0); - dc.DrawRectangle(areaPercTmp); - } - - wxDCTextColourChanger dummy3(dc, *wxBLACK); //accessibility: always set both foreground AND background colors! - dc.DrawLabel(numberTo<wxString>(node->percent_) + L"%", areaPerc, wxALIGN_CENTER); - - rectTmp.x += widthPercentBar + 2 * GAP_SIZE; - rectTmp.width -= widthPercentBar + 2 * GAP_SIZE; - } - if (rectTmp.width > 0) - { - //node status - auto drawStatus = [&](const wchar_t* image) - { - const wxBitmap& bmp = getResourceImage(image); - - wxRect rectStat(rectTmp.GetTopLeft(), wxSize(bmp.GetWidth(), bmp.GetHeight())); - rectStat.y += (rectTmp.height - rectStat.height) / 2; - - //clearArea(dc, rectStat, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - clearArea(dc, rectStat, *wxWHITE); //accessibility: always set both foreground AND background colors! - drawBitmapRtlMirror(dc, bmp, rectStat, wxALIGN_CENTER, buffer); - }; - - switch (node->status_) - { - case TreeView::STATUS_EXPANDED: - drawStatus(L"nodeExpanded"); - break; - case TreeView::STATUS_REDUCED: - drawStatus(L"nodeReduced"); - break; - case TreeView::STATUS_EMPTY: - break; - } - - rectTmp.x += widthNodeStatus + GAP_SIZE; - rectTmp.width -= widthNodeStatus + GAP_SIZE; - if (rectTmp.width > 0) - { - wxBitmap nodeIcon; - bool isActive = true; - //icon - if (dynamic_cast<const TreeView::RootNode*>(node.get())) - nodeIcon = rootBmp; - else if (auto dir = dynamic_cast<const TreeView::DirNode*>(node.get())) - { - nodeIcon = dirIcon; - isActive = dir->dirObj_.isActive(); - } - else if (dynamic_cast<const TreeView::FilesNode*>(node.get())) - nodeIcon = fileIcon; - - if (isActive) - drawBitmapRtlNoMirror(dc, nodeIcon, rectTmp, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, buffer); - - else - drawBitmapRtlNoMirror(dc, wxBitmap(nodeIcon.ConvertToImage().ConvertToGreyscale(1.0 / 3, 1.0 / 3, 1.0 / 3)), //treat all channels equally! - rectTmp, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, buffer); - - rectTmp.x += widthNodeIcon + GAP_SIZE; - rectTmp.width -= widthNodeIcon + GAP_SIZE; - - if (rectTmp.width > 0) - drawCellText(dc, rectTmp, getValue(row, colType), isActive, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - } - } - } - } - } - else - { - int alignment = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL; - - //have file size and item count right-justified (but don't change for RTL languages) - if ((static_cast<ColumnTypeNavi>(colType) == COL_TYPE_NAVI_BYTES || - static_cast<ColumnTypeNavi>(colType) == COL_TYPE_NAVI_ITEM_COUNT) && grid_.GetLayoutDirection() != wxLayout_RightToLeft) - { - rectTmp.width -= 2 * GAP_SIZE; - alignment = wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL; - } - else //left-justified - { - rectTmp.x += 2 * GAP_SIZE; - rectTmp.width -= 2 * GAP_SIZE; - } - - drawCellText(dc, rectTmp, getValue(row, colType), true, alignment); - } - } - - virtual int getBestSize(wxDC& dc, size_t row, ColumnType colType) override - { - // -> synchronize renderCell() <-> getBestSize() <-> onMouseLeft() - - if (static_cast<ColumnTypeNavi>(colType) == COL_TYPE_NAVI_DIRECTORY && treeDataView_) - { - if (std::unique_ptr<TreeView::Node> node = treeDataView_->getLine(row)) - return node->level_ * widthLevelStep + GAP_SIZE + (showPercentBar ? widthPercentBar + 2 * GAP_SIZE : 0) + widthNodeStatus + GAP_SIZE - + widthNodeIcon + GAP_SIZE + dc.GetTextExtent(getValue(row, colType)).GetWidth() + - GAP_SIZE; //additional gap from right - else - return 0; - } - else - return 2 * GAP_SIZE + dc.GetTextExtent(getValue(row, colType)).GetWidth() + - 2 * GAP_SIZE; //include gap from right! - } - - virtual wxString getColumnLabel(ColumnType colType) const - { - switch (static_cast<ColumnTypeNavi>(colType)) - { - case COL_TYPE_NAVI_BYTES: - return _("Size"); - case COL_TYPE_NAVI_DIRECTORY: - return _("Name"); - case COL_TYPE_NAVI_ITEM_COUNT: - return _("Items"); - } - return wxEmptyString; - } - - void onMouseLeft(GridClickEvent& event) - { - if (treeDataView_) - { - bool clickOnNodeStatus = false; - if (static_cast<ColumnTypeNavi>(event.colType_) == COL_TYPE_NAVI_DIRECTORY) - if (std::unique_ptr<TreeView::Node> node = treeDataView_->getLine(event.row_)) - { - const int absX = grid_.CalcUnscrolledPosition(event.GetPosition()).x; - const wxRect cellArea = grid_.getCellArea(event.row_, event.colType_); - if (cellArea.width > 0 && cellArea.height > 0) - { - const int tolerance = 1; - const int xNodeStatusFirst = -tolerance + cellArea.x + static_cast<int>(node->level_) * widthLevelStep + GAP_SIZE + (showPercentBar ? widthPercentBar + 2 * GAP_SIZE : 0); - const int xNodeStatusLast = (xNodeStatusFirst + tolerance) + widthNodeStatus + tolerance; - // -> synchronize renderCell() <-> getBestSize() <-> onMouseLeft() - - if (xNodeStatusFirst <= absX && absX < xNodeStatusLast) - clickOnNodeStatus = true; - } - } - //-------------------------------------------------------------------------------------------------- - - if (clickOnNodeStatus) - switch (treeDataView_->getStatus(event.row_)) - { - case TreeView::STATUS_EXPANDED: - return reduceNode(event.row_); - case TreeView::STATUS_REDUCED: - return expandNode(event.row_); - case TreeView::STATUS_EMPTY: - break; - } - } - event.Skip(); - } - - void onMouseLeftDouble(GridClickEvent& event) - { - if (treeDataView_) - switch (treeDataView_->getStatus(event.row_)) - { - case TreeView::STATUS_EXPANDED: - return reduceNode(event.row_); - case TreeView::STATUS_REDUCED: - return expandNode(event.row_); - case TreeView::STATUS_EMPTY: - break; - } - event.Skip(); - } - - void onKeyDown(wxKeyEvent& event) - { - int keyCode = event.GetKeyCode(); - if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) - { - if (keyCode == WXK_LEFT) - keyCode = WXK_RIGHT; - else if (keyCode == WXK_RIGHT) - keyCode = WXK_LEFT; - else if (keyCode == WXK_NUMPAD_LEFT) - keyCode = WXK_NUMPAD_RIGHT; - else if (keyCode == WXK_NUMPAD_RIGHT) - keyCode = WXK_NUMPAD_LEFT; - } - - const size_t rowCount = grid_.getRowCount(); - if (rowCount == 0) return; - - size_t row = grid_.getGridCursor().first; - if (event.ShiftDown()) - ; - else if (event.ControlDown()) - ; - else - switch (keyCode) - { - case WXK_LEFT: - case WXK_NUMPAD_LEFT: - case WXK_NUMPAD_SUBTRACT: //http://msdn.microsoft.com/en-us/library/ms971323.aspx#atg_keyboardshortcuts_windows_shortcut_keys - if (treeDataView_) - switch (treeDataView_->getStatus(row)) - { - case TreeView::STATUS_EXPANDED: - return reduceNode(row); - case TreeView::STATUS_REDUCED: - case TreeView::STATUS_EMPTY: - - const int parentRow = treeDataView_->getParent(row); - if (parentRow >= 0) - grid_.setGridCursor(parentRow); - break; - } - return; //swallow event - - case WXK_RIGHT: - case WXK_NUMPAD_RIGHT: - case WXK_NUMPAD_ADD: - if (treeDataView_) - switch (treeDataView_->getStatus(row)) - { - case TreeView::STATUS_EXPANDED: - grid_.setGridCursor(std::min(rowCount - 1, row + 1)); - break; - case TreeView::STATUS_REDUCED: - return expandNode(row); - case TreeView::STATUS_EMPTY: - break; - } - return; //swallow event - } - - event.Skip(); - } - - void onGridLabelContext(GridClickEvent& event) - { - ContextMenu menu; - - //-------------------------------------------------------------------------------------------------------- - menu.addCheckBox(_("Percentage"), [this] { setShowPercentage(!getShowPercentage()); }, getShowPercentage()); - //-------------------------------------------------------------------------------------------------------- - auto toggleColumn = [&](const Grid::ColumnAttribute& ca) - { - auto colAttr = grid_.getColumnConfig(); - - for (auto it = colAttr.begin(); it != colAttr.end(); ++it) - if (it->type_ == ca.type_) - { - it->visible_ = !ca.visible_; - grid_.setColumnConfig(colAttr); - return; - } - }; - - const auto& colAttr = grid_.getColumnConfig(); - for (auto it = colAttr.begin(); it != colAttr.end(); ++it) - { - const Grid::ColumnAttribute& ca = *it; - - menu.addCheckBox(getColumnLabel(ca.type_), [ca, toggleColumn]() { toggleColumn(ca); }, - ca.visible_, ca.type_ != static_cast<ColumnType>(COL_TYPE_NAVI_DIRECTORY)); //do not allow user to hide file name column! - } - //-------------------------------------------------------------------------------------------------------- - menu.addSeparator(); - - auto setDefaultColumns = [&] - { - setShowPercentage(defaultValueShowPercentage); - grid_.setColumnConfig(treeview::convertConfig(getDefaultColumnAttributesNavi())); - }; - menu.addItem(_("&Default"), setDefaultColumns); //'&' -> reuse text from "default" buttons elsewhere - - menu.popup(grid_); - - event.Skip(); - } - - void onGridLabelLeftClick(GridClickEvent& event) - { - if (treeDataView_) - { - const auto colTypeNavi = static_cast<ColumnTypeNavi>(event.colType_); - bool sortAscending = TreeView::getDefaultSortDirection(colTypeNavi); - - const auto sortInfo = treeDataView_->getSortDirection(); - if (sortInfo.first == colTypeNavi) - sortAscending = !sortInfo.second; - - treeDataView_->setSortDirection(colTypeNavi, sortAscending); - grid_.clearSelection(); - grid_.Refresh(); - } - } - - void expandNode(size_t row) - { - treeDataView_->expandNode(row); - grid_.Refresh(); //implicitly clears selection (changed row count after expand) - grid_.setGridCursor(row); - //grid_.autoSizeColumns(); -> doesn't look as good as expected - } - - void reduceNode(size_t row) - { - treeDataView_->reduceNode(row); - grid_.Refresh(); - grid_.setGridCursor(row); - } - - std::shared_ptr<TreeView> treeDataView_; - const wxBitmap fileIcon; - const wxBitmap dirIcon; - const wxBitmap rootBmp; - std::unique_ptr<wxBitmap> buffer; //avoid costs of recreating this temporal variable - const int widthNodeIcon; - const int widthLevelStep; - const int widthNodeStatus; - static const int widthPercentBar = 60; - Grid& grid_; - bool showPercentBar; -}; -} - - -void treeview::init(Grid& grid, const std::shared_ptr<TreeView>& treeDataView) -{ - grid.setDataProvider(std::make_shared<GridDataNavi>(grid, treeDataView)); - grid.showRowLabel(false); - - const int rowHeight = std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), grid.getMainWin().GetCharHeight()) + 2; //allow 1 pixel space on top and bottom; dearly needed on OS X! - grid.setRowHeight(rowHeight); -} - - -void treeview::setShowPercentage(Grid& grid, bool value) -{ - if (auto* prov = dynamic_cast<GridDataNavi*>(grid.getDataProvider())) - prov->setShowPercentage(value); - else - assert(false); -} - - -bool treeview::getShowPercentage(const Grid& grid) -{ - if (auto* prov = dynamic_cast<const GridDataNavi*>(grid.getDataProvider())) - return prov->getShowPercentage(); - assert(false); - return true; -} - - -namespace -{ -std::vector<ColumnAttributeNavi> makeConsistent(const std::vector<ColumnAttributeNavi>& attribs) -{ - std::set<ColumnTypeNavi> usedTypes; - - std::vector<ColumnAttributeNavi> output; - //remove duplicates - std::copy_if(attribs.begin(), attribs.end(), std::back_inserter(output), - [&](const ColumnAttributeNavi& a) { return usedTypes.insert(a.type_).second; }); - - //make sure each type is existing! - const auto& defAttr = getDefaultColumnAttributesNavi(); - std::copy_if(defAttr.begin(), defAttr.end(), std::back_inserter(output), - [&](const ColumnAttributeNavi& a) { return usedTypes.insert(a.type_).second; }); - - return output; -} -} - -std::vector<Grid::ColumnAttribute> treeview::convertConfig(const std::vector<ColumnAttributeNavi>& attribs) -{ - const auto& attribClean = makeConsistent(attribs); - - std::vector<Grid::ColumnAttribute> output; - std::transform(attribClean.begin(), attribClean.end(), std::back_inserter(output), - [&](const ColumnAttributeNavi& ca) { return Grid::ColumnAttribute(static_cast<ColumnType>(ca.type_), ca.offset_, ca.stretch_, ca.visible_); }); - - return output; -} - - -std::vector<ColumnAttributeNavi> treeview::convertConfig(const std::vector<Grid::ColumnAttribute>& attribs) -{ - std::vector<ColumnAttributeNavi> output; - - std::transform(attribs.begin(), attribs.end(), std::back_inserter(output), - [&](const Grid::ColumnAttribute& ca) { return ColumnAttributeNavi(static_cast<ColumnTypeNavi>(ca.type_), ca.offset_, ca.stretch_, ca.visible_); }); - - return makeConsistent(output); -} diff --git a/ui/tree_view.h b/ui/tree_view.h deleted file mode 100644 index 719212dd..00000000 --- a/ui/tree_view.h +++ /dev/null @@ -1,186 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef TREE_H_INCLUDED_841703190201835280256673425 -#define TREE_H_INCLUDED_841703190201835280256673425 - -#include <functional> -#include <zen/optional.h> -#include <wx+/grid.h> -#include "column_attr.h" -#include "../file_hierarchy.h" - -namespace zen -{ -//tree view of FolderComparison -class TreeView -{ -public: - TreeView() : - sortColumn(defaultValueLastSortColumn), - sortAscending(defaultValueLastSortAscending) {} - - void setData(FolderComparison& newData); //set data, taking (partial) ownership - - //apply view filter: comparison results - void updateCmpResult(bool hideFiltered, - bool leftOnlyFilesActive, - bool rightOnlyFilesActive, - bool leftNewerFilesActive, - bool rightNewerFilesActive, - bool differentFilesActive, - bool equalFilesActive, - bool conflictFilesActive); - - //apply view filter: synchronization preview - void updateSyncPreview(bool hideFiltered, - bool syncCreateLeftActive, - bool syncCreateRightActive, - bool syncDeleteLeftActive, - bool syncDeleteRightActive, - bool syncDirOverwLeftActive, - bool syncDirOverwRightActive, - bool syncDirNoneActive, - bool syncEqualActive, - bool conflictFilesActive); - - enum NodeStatus - { - STATUS_EXPANDED, - STATUS_REDUCED, - STATUS_EMPTY - }; - - //--------------------------------------------------------------------- - struct Node - { - Node(int percent, UInt64 bytes, int itemCount, unsigned int level, NodeStatus status) : - percent_(percent), level_(level), status_(status), bytes_(bytes), itemCount_(itemCount) {} - virtual ~Node() {} - - const int percent_; //[0, 100] - const unsigned int level_; - const NodeStatus status_; - const UInt64 bytes_; - const int itemCount_; - }; - - struct FilesNode : public Node - { - FilesNode(int percent, UInt64 bytes, int itemCount, unsigned int level, const std::vector<FileSystemObject*>& filesAndLinks) : Node(percent, bytes, itemCount, level, STATUS_EMPTY), filesAndLinks_(filesAndLinks) {} - std::vector<FileSystemObject*> filesAndLinks_; //files or symlinks; pointers are bound! - }; - - struct DirNode : public Node - { - DirNode(int percent, UInt64 bytes, int itemCount, unsigned int level, NodeStatus status, DirPair& dirObj) : Node(percent, bytes, itemCount, level, status), dirObj_(dirObj) {} - DirPair& dirObj_; - }; - - struct RootNode : public Node - { - RootNode(int percent, UInt64 bytes, int itemCount, NodeStatus status, BaseDirPair& baseDirObj) : Node(percent, bytes, itemCount, 0, status), baseDirObj_(baseDirObj) {} - BaseDirPair& baseDirObj_; - }; - - std::unique_ptr<Node> getLine(size_t row) const; //return nullptr on error - size_t linesTotal() const { return flatTree.size(); } - - void expandNode(size_t row); - void reduceNode(size_t row); - NodeStatus getStatus(size_t row) const; - ptrdiff_t getParent(size_t row) const; //return < 0 if none - - void setSortDirection(ColumnTypeNavi colType, bool ascending); //apply permanently! - std::pair<ColumnTypeNavi, bool> getSortDirection() { return std::make_pair(sortColumn, sortAscending); } - static bool getDefaultSortDirection(ColumnTypeNavi colType); //ascending? - -private: - struct DirNodeImpl; - - struct Container - { - Container() : itemCountGross(), itemCountNet(), firstFileId(nullptr) {} - UInt64 bytesGross; - UInt64 bytesNet; //bytes for files on view in this directory only - int itemCountGross; - int itemCountNet; //number of files on view for in this directory only - - std::vector<DirNodeImpl> subDirs; - FileSystemObject::ObjectId firstFileId; //weak pointer to first FilePair or SymlinkPair - //- "compress" algorithm may hide file nodes for directories with a single included file, i.e. itemCountGross == itemCountNet == 1 - //- a HierarchyObject* would a better fit, but we need weak pointer semantics! - //- a std::vector<FileSystemObject::ObjectId> would be a better design, but we don't want a second memory structure as large as custom grid! - }; - - struct DirNodeImpl : public Container - { - DirNodeImpl() : objId(nullptr) {} - FileSystemObject::ObjectId objId; //weak pointer to DirPair - }; - - struct RootNodeImpl : public Container - { - RootNodeImpl() {} - std::shared_ptr<BaseDirPair> baseDirObj; - }; - - enum NodeType - { - TYPE_ROOT, //-> RootNodeImpl - TYPE_DIRECTORY, //-> DirNodeImpl - TYPE_FILES //-> Container - }; - - struct TreeLine - { - TreeLine(unsigned int level, int percent, const Container* node, enum NodeType type) : level_(level), percent_(percent), node_(node), type_(type) {} - - unsigned int level_; - int percent_; //[0, 100] - const Container* node_; // - NodeType type_; //we choose to increase size of "flatTree" rather than "folderCmpView" by not using dynamic polymorphism! - }; - - static void compressNode(Container& cont); - template <class Function> - static void extractVisibleSubtree(HierarchyObject& hierObj, Container& cont, Function includeObject); - void getChildren(const Container& cont, unsigned int level, std::vector<TreeLine>& output); - template <class Predicate> void updateView(Predicate pred); - void applySubView(std::vector<RootNodeImpl>&& newView); - - template <bool ascending> static void sortSingleLevel(std::vector<TreeLine>& items, ColumnTypeNavi columnType); - template <bool ascending> struct LessShortName; - - std::vector<TreeLine> flatTree; //collapsable/expandable sub-tree of folderCmpView -> always sorted! - /* /|\ - | (update...) - | */ - std::vector<RootNodeImpl> folderCmpView; //partial view on folderCmp -> unsorted (cannot be, because files are not a separate entity) - std::function<bool(const FileSystemObject& fsObj)> lastViewFilterPred; //buffer view filter predicate for lazy evaluation of files/symlinks corresponding to a TYPE_FILES node - /* /|\ - | (update...) - | */ - std::vector<std::shared_ptr<BaseDirPair>> folderCmp; //full raw data - - ColumnTypeNavi sortColumn; - bool sortAscending; -}; - - -namespace treeview -{ -void init(Grid& grid, const std::shared_ptr<TreeView>& treeDataView); - -void setShowPercentage(Grid& grid, bool value); -bool getShowPercentage(const Grid& grid); - -std::vector<Grid::ColumnAttribute> convertConfig(const std::vector<ColumnAttributeNavi >& attribs); //+ make consistent -std::vector<ColumnAttributeNavi> convertConfig(const std::vector<Grid::ColumnAttribute>& attribs); // -} -} - -#endif //TREE_H_INCLUDED_841703190201835280256673425 diff --git a/ui/triple_splitter.cpp b/ui/triple_splitter.cpp deleted file mode 100644 index fbdd22d7..00000000 --- a/ui/triple_splitter.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "triple_splitter.h" -#include <algorithm> - -using namespace zen; - - -namespace -{ -//------------ Grid Constants ------------------------------- -const int SASH_HIT_TOLERANCE = 5; //currently only a placebo! -const int SASH_SIZE = 10; -const double SASH_GRAVITY = 0.5; //value within [0, 1]; 1 := resize left only, 0 := resize right only -const int CHILD_WINDOW_MIN_SIZE = 50; //min. size of managed windows - -const wxColor COLOR_SASH_GRADIENT_FROM = wxColour(192, 192, 192); //light grey -const wxColor COLOR_SASH_GRADIENT_TO = *wxWHITE; -} - -TripleSplitter::TripleSplitter(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style) : wxWindow(parent, id, pos, size, style | wxTAB_TRAVERSAL), //tab between windows - centerOffset(0), - windowL(nullptr), - windowC(nullptr), - windowR(nullptr) -{ - Connect(wxEVT_PAINT, wxPaintEventHandler(TripleSplitter::onPaintEvent ), nullptr, this); - Connect(wxEVT_SIZE, wxSizeEventHandler (TripleSplitter::onSizeEvent ), nullptr, this); - //http://wiki.wxwidgets.org/Flicker-Free_Drawing - Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(TripleSplitter::onEraseBackGround), nullptr, this); - - SetBackgroundStyle(wxBG_STYLE_PAINT); - - Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(TripleSplitter::onMouseLeftDown ), nullptr, this); - Connect(wxEVT_LEFT_UP, wxMouseEventHandler(TripleSplitter::onMouseLeftUp ), nullptr, this); - Connect(wxEVT_MOTION, wxMouseEventHandler(TripleSplitter::onMouseMovement ), nullptr, this); - Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(TripleSplitter::onLeaveWindow ), nullptr, this); - Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(TripleSplitter::onMouseCaptureLost), nullptr, this); - Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(TripleSplitter::onMouseLeftDouble), nullptr, this); -} - - -TripleSplitter::~TripleSplitter() {} //make sure correct destructor gets created for std::unique_ptr<SashMove> - - -void TripleSplitter::updateWindowSizes() -{ - if (windowL && windowC && windowR) - { - const int centerPosX = getCenterPosX(); - const int centerWidth = getCenterWidth(); - - const wxRect clientRect = GetClientRect(); - - const int widthL = centerPosX; - const int windowRposX = widthL + centerWidth; - const int widthR = clientRect.width - windowRposX; - - windowL->SetSize(0, 0, widthL, clientRect.height); - windowC->SetSize(widthL + SASH_SIZE, 0, windowC->GetSize().GetWidth(), clientRect.height); - windowR->SetSize(windowRposX, 0, widthR, clientRect.height); - - wxClientDC dc(this); - drawSash(dc); - } -} - - -class TripleSplitter::SashMove -{ -public: - SashMove(wxWindow& wnd, int mousePosX, int centerOffset) : wnd_(wnd), mousePosX_(mousePosX), centerOffset_(centerOffset) - { - wnd_.SetCursor(wxCURSOR_SIZEWE); - wnd_.CaptureMouse(); - } - ~SashMove() - { - wnd_.SetCursor(*wxSTANDARD_CURSOR); - if (wnd_.HasCapture()) - wnd_.ReleaseMouse(); - } - int getMousePosXStart () const { return mousePosX_; } - int getCenterOffsetStart() const { return centerOffset_; } - -private: - wxWindow& wnd_; - const int mousePosX_; - const int centerOffset_; -}; - - -inline -int TripleSplitter::getCenterWidth() const -{ - return 2 * SASH_SIZE + (windowC ? windowC->GetSize().GetWidth() : 0); -} - - -int TripleSplitter::getCenterPosXOptimal() const -{ - const wxRect clientRect = GetClientRect(); - const int centerWidth = getCenterWidth(); - return (clientRect.width - centerWidth) * SASH_GRAVITY; //allowed to be negative for extreme client widths! -} - - -int TripleSplitter::getCenterPosX() const -{ - const wxRect clientRect = GetClientRect(); - const int centerWidth = getCenterWidth(); - const int centerPosXOptimal = getCenterPosXOptimal(); - - //normalize "centerPosXOptimal + centerOffset" - if (clientRect.width < 2 * CHILD_WINDOW_MIN_SIZE + centerWidth) - //use fixed "centeroffset" when "clientRect.width == 2 * CHILD_WINDOW_MIN_SIZE + centerWidth" - return centerPosXOptimal + CHILD_WINDOW_MIN_SIZE - static_cast<int>(2 * CHILD_WINDOW_MIN_SIZE * SASH_GRAVITY); //avoid rounding error - //make sure transition between conditional branches is continuous! - return std::max(CHILD_WINDOW_MIN_SIZE, //make sure centerPosXOptimal + offset is within bounds - std::min(centerPosXOptimal + centerOffset, clientRect.width - CHILD_WINDOW_MIN_SIZE - centerWidth)); -} - - -void TripleSplitter::drawSash(wxDC& dc) -{ - const int centerPosX = getCenterPosX(); - const int centerWidth = getCenterWidth(); - - auto draw = [&](wxRect rect) - { - const int sash2ndHalf = 3; - rect.width -= sash2ndHalf; - dc.GradientFillLinear(rect, COLOR_SASH_GRADIENT_FROM, COLOR_SASH_GRADIENT_TO, wxEAST); - - rect.x += rect.width; - rect.width = sash2ndHalf; - dc.GradientFillLinear(rect, COLOR_SASH_GRADIENT_FROM, COLOR_SASH_GRADIENT_TO, wxWEST); - - static_assert(SASH_SIZE > sash2ndHalf, ""); - }; - - const wxRect rectSashL(centerPosX, 0, SASH_SIZE, GetClientRect().height); - const wxRect rectSashR(centerPosX + centerWidth - SASH_SIZE, 0, SASH_SIZE, GetClientRect().height); - - draw(rectSashL); - draw(rectSashR); -} - - -bool TripleSplitter::hitOnSashLine(int posX) const -{ - const int centerPosX = getCenterPosX(); - const int centerWidth = getCenterWidth(); - - //we don't get events outside of sash, so SASH_HIT_TOLERANCE is currently *useless* - auto hitSash = [&](int sashX) { return sashX - SASH_HIT_TOLERANCE <= posX && posX < sashX + SASH_SIZE + SASH_HIT_TOLERANCE; }; - - return hitSash(centerPosX) || hitSash(centerPosX + centerWidth - SASH_SIZE); //hit one of the two sash lines -} - - -void TripleSplitter::onMouseLeftDown(wxMouseEvent& event) -{ - activeMove.reset(); - - const int posX = event.GetPosition().x; - if (hitOnSashLine(posX)) - activeMove.reset(new SashMove(*this, posX, centerOffset)); - event.Skip(); -} - - -void TripleSplitter::onMouseLeftUp(wxMouseEvent& event) -{ - activeMove.reset(); //nothing else to do, actual work done by onMouseMovement() - event.Skip(); -} - - -void TripleSplitter::onMouseMovement(wxMouseEvent& event) -{ - if (activeMove) - { - centerOffset = activeMove->getCenterOffsetStart() + event.GetPosition().x - activeMove->getMousePosXStart(); - - //CAVEAT: function getCenterPosX() normalizes centerPosX *not* centerOffset! - //This can lead to the strange effect of window not immediately resizing when centerOffset is extremely off limits - //=> normalize centerOffset right here - centerOffset = getCenterPosX() - getCenterPosXOptimal(); - - updateWindowSizes(); - Update(); //no time to wait until idle event! - } - else - { - //we receive those only while above the sash, not the managed windows (except when the managed windows are disabled!) - const int posX = event.GetPosition().x; - if (hitOnSashLine(posX)) - SetCursor(wxCURSOR_SIZEWE); //set window-local only! - else - SetCursor(*wxSTANDARD_CURSOR); - } - event.Skip(); -} - - -void TripleSplitter::onLeaveWindow(wxMouseEvent& event) -{ - //even called when moving from sash over to managed windows! - if (!activeMove) - SetCursor(*wxSTANDARD_CURSOR); - event.Skip(); -} - - -void TripleSplitter::onMouseCaptureLost(wxMouseCaptureLostEvent& event) -{ - activeMove.reset(); - updateWindowSizes(); - //event.Skip(); -> we DID handle it! -} - - -void TripleSplitter::onMouseLeftDouble(wxMouseEvent& event) -{ - const int posX = event.GetPosition().x; - if (hitOnSashLine(posX)) - { - centerOffset = 0; //reset sash according to gravity - updateWindowSizes(); - } - event.Skip(); -} diff --git a/ui/triple_splitter.h b/ui/triple_splitter.h deleted file mode 100644 index 0577dabf..00000000 --- a/ui/triple_splitter.h +++ /dev/null @@ -1,89 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef TRIPPLE_SPLIT_HEADER_8257804292846842573942534254 -#define TRIPPLE_SPLIT_HEADER_8257804292846842573942534254 - -#include <cassert> -#include <memory> -#include <wx/window.h> -#include <wx/dcclient.h> - -//a not-so-crappy splitter window - -/* manage three contained windows: - 1. left and right window are stretched - 2. middle window is fixed size - 3. middle window position can be changed via mouse with two sash lines - ----------------- - | | | | - | | | | - | | | | - ----------------- -*/ - -namespace zen -{ -class TripleSplitter : public wxWindow -{ -public: - TripleSplitter(wxWindow* parent, - wxWindowID id = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0); - - ~TripleSplitter(); - - void setupWindows(wxWindow* winL, wxWindow* winC, wxWindow* winR) - { - assert(winL->GetParent() == this && winC->GetParent() == this && winR->GetParent() == this && !GetSizer()); - windowL = winL; - windowC = winC; - windowR = winR; - updateWindowSizes(); - } - - int getSashOffset() const { return centerOffset; } - void setSashOffset(int off) { centerOffset = off; updateWindowSizes(); } - -private: - void onEraseBackGround(wxEraseEvent& event) {} - void onSizeEvent(wxSizeEvent& event) { updateWindowSizes(); event.Skip(); } - - void onPaintEvent(wxPaintEvent& event) - { - wxPaintDC dc(this); - drawSash(dc); - } - - void updateWindowSizes(); - int getCenterWidth() const; - int getCenterPosX() const; //return normalized posX - int getCenterPosXOptimal() const; - - void drawSash(wxDC& dc); - bool hitOnSashLine(int posX) const; - - void onMouseLeftDown(wxMouseEvent& event); - void onMouseLeftUp(wxMouseEvent& event); - void onMouseMovement(wxMouseEvent& event); - void onLeaveWindow(wxMouseEvent& event); - void onMouseCaptureLost(wxMouseCaptureLostEvent& event); - void onMouseLeftDouble(wxMouseEvent& event); - - class SashMove; - std::unique_ptr<SashMove> activeMove; - - int centerOffset; //offset to add after "gravity" stretching - - wxWindow* windowL; - wxWindow* windowC; - wxWindow* windowR; -}; -} - -#endif //TRIPPLE_SPLIT_HEADER_8257804292846842573942534254 diff --git a/ui/wx_form_build_hide_warnings.h b/ui/wx_form_build_hide_warnings.h deleted file mode 100644 index 71f28340..00000000 --- a/ui/wx_form_build_hide_warnings.h +++ /dev/null @@ -1,22 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef WX_FORM_BUILD_230948324234234 -#define WX_FORM_BUILD_230948324234234 - -//pamper over wxFormBuilder "sub-optimal" code - -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wunused-variable" -#ifndef __clang__ //clang seems to define __GNUC__, but doesn't support this warning -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#endif - -#elif defined _MSC_VER -#pragma warning(disable: 4189) -#endif - -#endif //WX_FORM_BUILD_230948324234234 |