summaryrefslogtreecommitdiff
path: root/RealtimeSync
diff options
context:
space:
mode:
Diffstat (limited to 'RealtimeSync')
-rw-r--r--RealtimeSync/RealtimeSync.cbp151
-rw-r--r--RealtimeSync/RealtimeSync.icobin0 -> 82726 bytes
-rw-r--r--RealtimeSync/RealtimeSync.vcproj326
-rw-r--r--RealtimeSync/RealtimeSync.xpm312
-rw-r--r--RealtimeSync/application.cpp89
-rw-r--r--RealtimeSync/application.h22
-rw-r--r--RealtimeSync/functions.cpp15
-rw-r--r--RealtimeSync/functions.h15
-rw-r--r--RealtimeSync/guiGenerated.cpp212
-rw-r--r--RealtimeSync/guiGenerated.h128
-rw-r--r--RealtimeSync/mainDialog.cpp427
-rw-r--r--RealtimeSync/mainDialog.h75
-rw-r--r--RealtimeSync/makefile57
-rw-r--r--RealtimeSync/pch.h97
-rw-r--r--RealtimeSync/resource.rc4
-rw-r--r--RealtimeSync/resources.cpp81
-rw-r--r--RealtimeSync/resources.h33
-rw-r--r--RealtimeSync/trayMenu.cpp209
-rw-r--r--RealtimeSync/trayMenu.h20
-rw-r--r--RealtimeSync/watcher.cpp198
-rw-r--r--RealtimeSync/watcher.h23
-rw-r--r--RealtimeSync/xmlFreeFileSync.cpp68
-rw-r--r--RealtimeSync/xmlFreeFileSync.h16
-rw-r--r--RealtimeSync/xmlProcessing.cpp86
-rw-r--r--RealtimeSync/xmlProcessing.h23
25 files changed, 2687 insertions, 0 deletions
diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp
new file mode 100644
index 00000000..75c1d189
--- /dev/null
+++ b/RealtimeSync/RealtimeSync.cbp
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="RealtimeSync" />
+ <Option makefile="makefile" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="Debug">
+ <Option output="..\BUILD\RealtimeSync" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="..\BUILD" />
+ <Option object_output="..\OBJ\Debug_RTS_GCC" />
+ <Option type="0" />
+ <Option compiler="gcc" />
+ <Option projectLinkerOptionsRelation="2" />
+ <Compiler>
+ <Add option="-g" />
+ <Add option="-Winvalid-pch" />
+ <Add option='-include &quot;pch.h&quot;' />
+ <Add option="-D__WXDEBUG__" />
+ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswud" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswud" />
+ </ResourceCompiler>
+ <Linker>
+ <Add library="libwxmsw28ud_core.a" />
+ <Add library="libwxmsw28ud_adv.a" />
+ <Add library="libwxbase28ud.a" />
+ <Add library="libwxpngd.a" />
+ <Add library="libwxzlibd.a" />
+ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" />
+ </Linker>
+ </Target>
+ <Target title="Release">
+ <Option output="..\BUILD\RealtimeSync" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="..\BUILD" />
+ <Option object_output="..\OBJ\Release_RTS_GCC" />
+ <Option type="0" />
+ <Option compiler="gcc" />
+ <Option projectLinkerOptionsRelation="2" />
+ <Compiler>
+ <Add option="-O3" />
+ <Add option="-DNDEBUG" />
+ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswu" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswu" />
+ </ResourceCompiler>
+ <Linker>
+ <Add option="-s" />
+ <Add library="libwxmsw28u_core.a" />
+ <Add library="libwxmsw28u_adv.a" />
+ <Add library="libwxbase28u.a" />
+ <Add library="libwxpng.a" />
+ <Add library="libwxzlib.a" />
+ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" />
+ </Linker>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-pipe" />
+ <Add option="-mthreads" />
+ <Add option='[[if (PLATFORM == PLATFORM_MSW &amp;&amp; (GetCompilerFactory().GetCompilerVersionString(_T(&quot;gcc&quot;)) &gt;= _T(&quot;4.0.0&quot;))) print(_T(&quot;-Wno-attributes&quot;));]]' />
+ <Add option="-D__GNUWIN32__" />
+ <Add option="-D__WXMSW__" />
+ <Add option="-DwxUSE_UNICODE" />
+ <Add option="-DFFS_WIN" />
+ <Add option="-DZSTRING_WIDE_CHAR" />
+ <Add option="-DTIXML_USE_STL" />
+ <Add directory="C:\Programme\C++\wxWidgets\include" />
+ <Add directory="C:\Programme\C++\wxWidgets\contrib\include" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="C:\Programme\C++\wxWidgets\include" />
+ </ResourceCompiler>
+ <Linker>
+ <Add option="-mthreads" />
+ <Add library="libkernel32.a" />
+ <Add library="libuser32.a" />
+ <Add library="libuuid.a" />
+ <Add library="libcomctl32.a" />
+ <Add library="libgdi32.a" />
+ <Add library="libole32.a" />
+ <Add library="liboleaut32.a" />
+ <Add library="libcomdlg32.a" />
+ <Add library="libws2_32.a" />
+ </Linker>
+ <Unit filename="WxWizDialog.fbp" />
+ <Unit filename="application.cpp" />
+ <Unit filename="application.h" />
+ <Unit filename="functions.cpp" />
+ <Unit filename="functions.h" />
+ <Unit filename="guiGenerated.cpp" />
+ <Unit filename="guiGenerated.h" />
+ <Unit filename="mainDialog.cpp" />
+ <Unit filename="mainDialog.h" />
+ <Unit filename="pch.h">
+ <Option compile="1" />
+ <Option weight="0" />
+ <Option target="Debug" />
+ </Unit>
+ <Unit filename="resource.rc">
+ <Option compilerVar="WINDRES" />
+ </Unit>
+ <Unit filename="resources.cpp" />
+ <Unit filename="resources.h" />
+ <Unit filename="trayMenu.cpp" />
+ <Unit filename="trayMenu.h" />
+ <Unit filename="watcher.cpp" />
+ <Unit filename="watcher.h" />
+ <Unit filename="xmlFreeFileSync.cpp" />
+ <Unit filename="xmlFreeFileSync.h" />
+ <Unit filename="xmlProcessing.cpp" />
+ <Unit filename="xmlProcessing.h" />
+ <Unit filename="..\Shared\customButton.cpp" />
+ <Unit filename="..\Shared\customButton.h" />
+ <Unit filename="..\Shared\dragAndDrop.cpp" />
+ <Unit filename="..\Shared\dragAndDrop.h" />
+ <Unit filename="..\Shared\zstring.cpp" />
+ <Unit filename="..\Shared\zstring.h" />
+ <Unit filename="..\library\processXml.cpp" />
+ <Unit filename="..\shared\fileError.h" />
+ <Unit filename="..\shared\fileHandling.cpp" />
+ <Unit filename="..\shared\fileHandling.h" />
+ <Unit filename="..\shared\fileTraverser.cpp" />
+ <Unit filename="..\shared\globalFunctions.cpp" />
+ <Unit filename="..\shared\globalFunctions.h" />
+ <Unit filename="..\shared\localization.cpp" />
+ <Unit filename="..\shared\localization.h" />
+ <Unit filename="..\shared\shadow.cpp" />
+ <Unit filename="..\shared\standardPaths.cpp" />
+ <Unit filename="..\shared\standardPaths.h" />
+ <Unit filename="..\shared\systemFunctions.cpp" />
+ <Unit filename="..\shared\systemFunctions.h" />
+ <Unit filename="..\shared\tinyxml\tinystr.cpp" />
+ <Unit filename="..\shared\tinyxml\tinyxml.cpp" />
+ <Unit filename="..\shared\tinyxml\tinyxmlerror.cpp" />
+ <Unit filename="..\shared\tinyxml\tinyxmlparser.cpp" />
+ <Unit filename="..\shared\xmlBase.cpp" />
+ <Unit filename="..\shared\xmlBase.h" />
+ <Unit filename="..\structures.cpp" />
+ <Extensions>
+ <code_completion />
+ <envvars />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
diff --git a/RealtimeSync/RealtimeSync.ico b/RealtimeSync/RealtimeSync.ico
new file mode 100644
index 00000000..8e4e556e
--- /dev/null
+++ b/RealtimeSync/RealtimeSync.ico
Binary files differ
diff --git a/RealtimeSync/RealtimeSync.vcproj b/RealtimeSync/RealtimeSync.vcproj
new file mode 100644
index 00000000..72bb7f61
--- /dev/null
+++ b/RealtimeSync/RealtimeSync.vcproj
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="RealtimeSync"
+ ProjectGUID="{517129D6-622F-4432-95A2-C4571276CE18}"
+ RootNamespace="FreeFileSync"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\OBJ\$(ConfigurationName)_RTS_VCPP"
+ IntermediateDirectory="..\OBJ\$(ConfigurationName)_RTS_VCPP"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine=""
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets\include&quot;;&quot;C:\Programme\C++\wxWidgets\lib\vc_lib\mswud&quot;"
+ PreprocessorDefinitions="wxUSE_UNICODE;__WXMSW__;FFS_WIN;__WXDEBUG__;TIXML_USE_STL;ZSTRING_WIDE_CHAR"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="0"
+ AdditionalIncludeDirectories="C:\Programme\C++\wxWidgets\include;C:\Programme\C++\wxWidgets\lib\vc_lib\mswud"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wxmsw28ud_adv.lib &#x0A;wxmsw28ud_core.lib &#x0A;wxbase28ud.lib &#x0A;wxpngd.lib&#x0A; wxzlibd.lib &#x0A;wxbase28ud_net.lib comctl32.lib ws2_32.lib Rpcrt4.lib"
+ OutputFile="..\BUILD\$(ProjectName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets\lib\vc_lib"
+ GenerateManifest="true"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="true"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="clean up"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\OBJ\$(ConfigurationName)_RTS_VCPP"
+ IntermediateDirectory="..\OBJ\$(ConfigurationName)_RTS_VCPP"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets\include&quot;;&quot;C:\Programme\C++\wxWidgets\lib\vc_lib\mswu&quot;"
+ PreprocessorDefinitions="wxUSE_UNICODE;__WXMSW__;FFS_WIN;NDEBUG;TIXML_USE_STL;ZSTRING_WIDE_CHAR"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets\include&quot;;&quot;C:\Programme\C++\wxWidgets\lib\vc_lib\mswu&quot;"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wxmsw28u_adv.lib &#x0A;wxmsw28u_core.lib &#x0A;wxbase28u.lib &#x0A;wxpng.lib &#x0A;wxzlib.lib &#x0A;wxbase28u_net.lib comctl32.lib ws2_32.lib"
+ OutputFile="..\BUILD\$(ProjectName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets\lib\vc_lib"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\application.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\customButton.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\dragAndDrop.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\fileHandling.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\fileTraverser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\functions.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\globalFunctions.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\guiGenerated.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\localization.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mainDialog.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\library\processXml.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\resources.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\shadow.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\standardPaths.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\structures.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\systemFunctions.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\tinyxml\tinystr.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\tinyxml\tinyxml.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\tinyxml\tinyxmlerror.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\tinyxml\tinyxmlparser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\trayMenu.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\watcher.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\xmlBase.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\xmlFreeFileSync.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\xmlProcessing.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\shared\zstring.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\resource.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_UNICODE;UNICODE;wxUSE_NO_MANIFEST"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_UNICODE;UNICODE;wxUSE_NO_MANIFEST"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/RealtimeSync/RealtimeSync.xpm b/RealtimeSync/RealtimeSync.xpm
new file mode 100644
index 00000000..557ef973
--- /dev/null
+++ b/RealtimeSync/RealtimeSync.xpm
@@ -0,0 +1,312 @@
+/* XPM */
+static const char* RealtimeSync_xpm[] = {
+"32 32 277 2",
+" c None",
+"! c black",
+"# c #2A0404",
+"$ c #330505",
+"% c #3D0707",
+"& c #360606",
+"' c #340606",
+"( c #500909",
+") c #630B0B",
+"* c #890F0F",
+"+ c #AC1414",
+", c #AB1414",
+"- c #9F1212",
+". c #820F0F",
+"0 c #510909",
+"1 c #2F0505",
+"2 c #530A0A",
+"3 c #8B1010",
+"4 c #E83E3E",
+"5 c #F39494",
+"6 c #F6ADAD",
+"7 c #F49B9B",
+"8 c #F07E7E",
+"9 c #EC5C5C",
+": c #E73636",
+"; c #D71818",
+"< c #AD1414",
+"= c #7C0E0E",
+"> c #410707",
+"? c #E73232",
+"@ c #FACECE",
+"A c #FCDFDF",
+"B c #F7B8B8",
+"C c #F39090",
+"D c #EF6E6E",
+"E c #EA4D4D",
+"F c #E72D2D",
+"G c #E41E1E",
+"H c #E31F1F",
+"I c #E52121",
+"J c #E31C1C",
+"K c #670C0C",
+"L c #380606",
+"M c #420808",
+"N c #6D0C0C",
+"O c #F07777",
+"P c #FEEEEE",
+"Q c #F9C6C6",
+"R c #F49D9D",
+"S c #EC5D5D",
+"T c #E83C3C",
+"U c #E62121",
+"V c #E41A1A",
+"W c #E41D1D",
+"X c #E21E1E",
+"Y c #E41C1C",
+"Z c #E51C1C",
+"[ c #C71717",
+"] c #720C0C",
+"^ c #330606",
+"_ c #640C0C",
+"` c #EF7171",
+"a c #FCE3E3",
+"b c #F6AFAF",
+"c c #F28D8D",
+"d c #E72E2E",
+"e c #E62020",
+"f c #E51A1A",
+"g c #E51F1F",
+"h c #CA1818",
+"i c #680C0C",
+"j c #260404",
+"k c #4F0909",
+"l c #540A0A",
+"m c #520909",
+"n c #E72F2F",
+"o c #FAD3D3",
+"p c #F4A0A0",
+"q c #F17E7E",
+"r c #ED5E5E",
+"s c #E93E3E",
+"t c #E62525",
+"u c #E51B1B",
+"v c #BD1616",
+"w c #941111",
+"x c #810E0E",
+"y c #830F0F",
+"z c #991111",
+"{ c #E21A1A",
+"| c #B41515",
+"} c #420707",
+"~ c #8C1010",
+" ! c #E62323",
+"!! c #C91717",
+"#! c #B21515",
+"$! c #EB5050",
+"%! c #E73030",
+"&! c #DC1919",
+"'! c #250404",
+"(! c #550A0A",
+")! c #7B0E0E",
+"*! c #BC1616",
+"+! c #860F0F",
+",! c #310505",
+"-! c #3F0707",
+".! c #F07676",
+"0! c #EB5656",
+"1! c #E62727",
+"2! c #E62424",
+"3! c #E21D1D",
+"4! c #DE1919",
+"5! c #7A0E0E",
+"6! c #470808",
+"7! c #350606",
+"8! c #5B0A0A",
+"9! c #971111",
+":! c #DF1919",
+";! c #BF1616",
+"<! c #951111",
+"=! c #EA4E4E",
+">! c #E61F1F",
+"?! c #E41B1B",
+"@! c #E31A1A",
+"A! c #D41919",
+"B! c #8D1010",
+"C! c #5D0B0B",
+"D! c #390606",
+"E! c #1F0303",
+"F! c #4E0909",
+"G! c #D61818",
+"H! c #750D0D",
+"I! c #270404",
+"J! c #6A0C0C",
+"K! c #E62222",
+"L! c #C81717",
+"M! c #790D0D",
+"N! c #290404",
+"O! c #460808",
+"P! c #770D0D",
+"Q! c #D81818",
+"R! c #A21212",
+"S! c #E52020",
+"T! c #931111",
+"U! c #7D0E0E",
+"V! c #A61313",
+"W! c #450808",
+"X! c #3A0606",
+"Y! c #570A0A",
+"Z! c #2E0505",
+"[! c #440808",
+"]! c #580A0A",
+"^! c #630C0C",
+"_! c #BA1616",
+"`! c #D51818",
+"a! c #180202",
+"b! c #EC5959",
+"c! c #F39292",
+"d! c #3C0707",
+"e! c #DF1A1A",
+"f! c #6C0C0C",
+"g! c #300505",
+"h! c #D11818",
+"i! c #FFFEFE",
+"j! c white",
+"k! c #FCDDDD",
+"l! c #8A1010",
+"m! c #D41818",
+"n! c #A91313",
+"o! c #730D0D",
+"p! c #1D0303",
+"q! c #4B0909",
+"r! c #AF1414",
+"s! c #F39797",
+"t! c #FFFBFB",
+"u! c #FFFAFA",
+"v! c #FDEBEB",
+"w! c #FCDEDE",
+"x! c #FBD4D4",
+"y! c #FBDADA",
+"z! c #EB4E4E",
+"{! c #880F0F",
+"|! c #200303",
+"}! c #600B0B",
+"~! c #F9CBCB",
+" # c #FBD7D7",
+"!# c #F8BEBE",
+"## c #F5A5A5",
+"$# c #F49C9C",
+"%# c #F39191",
+"&# c #F28989",
+"'# c #F07B7B",
+"(# c #A71313",
+")# c #700D0D",
+"*# c #140202",
+"+# c #E73333",
+",# c #F5A8A8",
+"-# c #F39393",
+".# c #F18282",
+"0# c #F07878",
+"1# c #EE6C6C",
+"2# c #ED6262",
+"3# c #EC5757",
+"4# c #E94242",
+"5# c #E94141",
+"6# c #DA1919",
+"7# c #F38E8E",
+"8# c #690C0C",
+"9# c #760D0D",
+":# c #EC5A5A",
+";# c #EA4949",
+"<# c #E93F3F",
+"=# c #E62626",
+"># c #DD1919",
+"?# c #6F0C0C",
+"@# c #2C0505",
+"A# c #FEEBEB",
+"B# c #F07D7D",
+"C# c #6B0C0C",
+"D# c #911010",
+"E# c #D21818",
+"F# c #E31B1B",
+"G# c #E11D1D",
+"H# c #400707",
+"I# c #EE6666",
+"J# c #7F0E0E",
+"K# c #5C0B0B",
+"L# c #E62828",
+"M# c #B11414",
+"N# c #F39A9A",
+"O# c #ED6565",
+"P# c #A31313",
+"Q# c #370606",
+"R# c #840F0F",
+"S# c #E21B1B",
+"T# c #E31D1D",
+"U# c #B61515",
+"V# c #ED6161",
+"W# c #EB5555",
+"X# c #490808",
+"Y# c #3B0707",
+"Z# c #650C0C",
+"[# c #9E1212",
+"]# c #E41F1F",
+"^# c #E51D1D",
+"_# c #800E0E",
+"`# c #921111",
+"a# c #4A0808",
+"b# c #320505",
+"c# c #E73535",
+"d# c #E72A2A",
+"e# c #E72B2B",
+"f# c #E42020",
+"g# c #B11515",
+"h# c #E51E1E",
+"i# c #E31E1E",
+"j# c #530909",
+"k# c #E42121",
+"l# c #610B0B",
+"m# c #4D0909",
+"n# c #DB1A1A",
+"o# c #AA1414",
+"p# c #620B0B",
+"q# c #720D0D",
+"r# c #B31515",
+"s# c #E11919",
+"t# c #C61717",
+"u# c #5A0A0A",
+"v# c #BB1616",
+"w# c #CC1818",
+"x# c #C11717",
+"y# c #850F0F",
+"z# c #1E0303",
+"{# c #2B0505",
+"|# c #560A0A",
+"}# c #5F0B0B",
+"~# c #210303",
+" $ c #170202",
+" ",
+" # $ % & # ",
+" ' ( ) * + , - . ) 0 $ ",
+" 1 2 3 4 5 6 7 8 9 : ; < = 2 # ",
+" > ) ? @ A B C D E F G H I J < K L ",
+" M N O P Q R 8 S T U V W X Y Z I [ ] & ",
+" ^ _ ` a b c D E d e G f Y g e W Y f h i j ",
+" k l l m 2 n o p q r s t u v w x y z v { f f f | 2 ",
+"} ~ d !!!#!q C ` $!%!g &!~ 0 1 '!j L (!)!*!f f f +!,! ",
+"-!*!.!0!4 1!Y 2!d 2!3!4!5!6! 7!8!9!:!f ;!2 ",
+"% <!=!: >!?!V @!{ V W A!B!C!D! E!F!x G!f H!E! ",
+"I!J!e K!?!f ?!u ?!J f f f L!M!N! O!P!Q!R!1 ",
+" l < S!f ?!u ?!J f f f f f T!# } U!V!W! ",
+" X!= V Z u ?!J f f f f f + Y! Z![!]!^!]! ",
+" 8!_!I ?!J f f f f `!T!0 a! ,!Y!#!b!c!;!l ",
+" d!P!e!Z f f f 4!+ f!X! g!]!h!R i!j!j!k!l!& ",
+" 2 +!{ f m!n!o!W!p! q!r!s!t!u!v!w!x!y!z!Y! ",
+" O!]!x {!_ > |! }!F ~! #!#b ##$#%#&#'#~ X! ",
+" & (#)#6!*# 8!+#,#-#.#0#1#2#3#=!4#5#;!(! ",
+" '!6#7#8#Z! 9#S :#;#<#: F =#I Z 3!Y >#?#@# ",
+" U!A#B#C#X! m D#E#X F#G#V G#F#J Y 3!Y T!H# ",
+" ( 2#y!I#J#O! W!K#v L#Y J f f f f f f M#0 ",
+" ,!r!$#N#O#P#]!Q# W!R#S#U T#?!T#X ?!V f f U#Y! ",
+" 8!? 1#V#W#h!y C!X#Y#q!Z#[#S#]#W G ^#G ?!* _#`#w P!a# ",
+" b#J#? c#d#e#f#h g#+ | `!g h#Y Y i#Y f V!j#^ & D!' ",
+" 6!l!J h#J W k#U K!U ]#Y ?!f f f f U#l#g! ",
+" m#{!n#e h#i#J u f f f f f f f o#p#X! ",
+" W!q#r#s#f f f f f f f f t#{!u#b# ",
+" Z!2 P!- v#w#G!h!x#o#y#p#O!z# ",
+" {#> |#}#p#}!8!m#X!~# ",
+" $ $ ",
+" "}; \ No newline at end of file
diff --git a/RealtimeSync/application.cpp b/RealtimeSync/application.cpp
new file mode 100644
index 00000000..5515ded5
--- /dev/null
+++ b/RealtimeSync/application.cpp
@@ -0,0 +1,89 @@
+/***************************************************************
+ * Purpose: Code for Application Class
+ * Author: ZenJu (zhnmju123@gmx.de)
+ * Created: 2009-07-06
+ * Copyright: ZenJu (http://sourceforge.net/projects/freefilesync/)
+ **************************************************************/
+
+#include "application.h"
+#include "mainDialog.h"
+#include <wx/event.h>
+#include "resources.h"
+#include <wx/msgdlg.h>
+#include "../shared/localization.h"
+#include "xmlFreeFileSync.h"
+#include "../shared/standardPaths.h"
+
+#ifdef FFS_LINUX
+#include <gtk/gtk.h>
+#endif
+
+IMPLEMENT_APP(Application);
+
+bool Application::OnInit()
+{
+//do not call wxApp::OnInit() to avoid using default commandline parser
+
+//Note: initialization is done in the FIRST idle event instead of OnInit. Reason: Commandline mode requires the wxApp eventhandler to be established
+//for UI update events. This is not the case at the time of OnInit().
+ Connect(wxEVT_IDLE, wxIdleEventHandler(Application::OnStartApplication), NULL, this);
+
+ return true;
+}
+
+
+void Application::OnStartApplication(wxIdleEvent& event)
+{
+ Disconnect(wxEVT_IDLE, wxIdleEventHandler(Application::OnStartApplication), NULL, this);
+
+ //if appname is not set, the default is the executable's name!
+ SetAppName(wxT("FreeFileSync")); //use a different app name, to have "GetUserDataDir()" return the same directory as for FreeFileSync
+
+#ifdef FFS_LINUX
+ ::gtk_rc_parse("styles.rc"); //remove inner border from bitmap buttons
+#endif
+
+ //set program language
+ try
+ {
+ FreeFileSync::CustomLocale::getInstance().setLanguage(RealtimeSync::getProgramLanguage());
+ }
+ catch (const xmlAccess::XmlError& error)
+ {
+ if (wxFileExists(FreeFileSync::getGlobalConfigFile()))
+ {
+ SetExitOnFrameDelete(false); //prevent error messagebox from becoming top-level window
+ if (error.getSeverity() == xmlAccess::XmlError::WARNING)
+ wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
+ else
+ wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
+ SetExitOnFrameDelete(true);
+
+ }
+ }
+
+ //try to set config/batch-filename set by %1 parameter
+ wxString cfgFilename;
+ if (argc > 1)
+ {
+ const wxString filename(argv[1]);
+
+ if (wxFileExists(filename)) //load file specified by %1 parameter:
+ cfgFilename = filename;
+ else if (wxFileExists(filename + wxT(".ffs_real")))
+ cfgFilename = filename + wxT(".ffs_real");
+ else if (wxFileExists(filename + wxT(".ffs_batch")))
+ cfgFilename = filename + wxT(".ffs_batch");
+ else
+ {
+ wxMessageBox(wxString(_("File does not exist:")) + wxT(" \"") + filename + wxT("\""), _("Error"), wxOK | wxICON_ERROR);
+ return;
+ }
+ }
+
+ GlobalResources::getInstance().load(); //loads bitmap resources on program startup
+
+ MainDialog* frame = new MainDialog(NULL, cfgFilename);
+ frame->SetIcon(*GlobalResources::getInstance().programIcon); //set application icon
+ frame->Show();
+}
diff --git a/RealtimeSync/application.h b/RealtimeSync/application.h
new file mode 100644
index 00000000..f6bfdd37
--- /dev/null
+++ b/RealtimeSync/application.h
@@ -0,0 +1,22 @@
+/***************************************************************
+ * Purpose: Defines Application Class
+ * Author: ZenJu (zhnmju123@gmx.de)
+ * Created: 2009-07-06
+ * Copyright: ZenJu (http://sourceforge.net/projects/freefilesync/)
+ **************************************************************/
+
+#ifndef REALTIMESYNCAPP_H
+#define REALTIMESYNCAPP_H
+
+#include <wx/app.h>
+
+class Application : public wxApp
+{
+public:
+ virtual bool OnInit();
+
+private:
+ void OnStartApplication(wxIdleEvent& event);
+};
+
+#endif // REALTIMESYNCAPP_H
diff --git a/RealtimeSync/functions.cpp b/RealtimeSync/functions.cpp
new file mode 100644
index 00000000..f966187e
--- /dev/null
+++ b/RealtimeSync/functions.cpp
@@ -0,0 +1,15 @@
+#include "functions.h"
+#include <wx/textctrl.h>
+#include <wx/filepicker.h>
+//#include "../shared/globalFunctions.h"
+#include "../shared/fileHandling.h"
+
+
+void RealtimeSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker)
+{
+ txtCtrl->SetValue(dirname);
+ const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(dirname.c_str());
+ if (wxDirExists(leftDirFormatted.c_str()))
+ dirPicker->SetPath(leftDirFormatted.c_str());
+}
+
diff --git a/RealtimeSync/functions.h b/RealtimeSync/functions.h
new file mode 100644
index 00000000..3d7d522f
--- /dev/null
+++ b/RealtimeSync/functions.h
@@ -0,0 +1,15 @@
+#ifndef FUNCTIONS_H_INCLUDED
+#define FUNCTIONS_H_INCLUDED
+
+#include <wx/string.h>
+
+class wxTextCtrl;
+class wxDirPickerCtrl;
+
+
+namespace RealtimeSync
+{
+ void setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker);
+}
+
+#endif // FUNCTIONS_H_INCLUDED
diff --git a/RealtimeSync/guiGenerated.cpp b/RealtimeSync/guiGenerated.cpp
new file mode 100644
index 00000000..1150ae1b
--- /dev/null
+++ b/RealtimeSync/guiGenerated.cpp
@@ -0,0 +1,212 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Apr 16 2008)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO "NOT" EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "../shared/customButton.h"
+
+#include "guiGenerated.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
+{
+ this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+
+ m_menubar1 = new wxMenuBar( 0 );
+ m_menuFile = new wxMenu();
+ wxMenuItem* m_menuItem14;
+ m_menuItem14 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("S&ave configuration") ) + wxT('\t') + wxT("CTRL-S"), wxEmptyString, wxITEM_NORMAL );
+ m_menuFile->Append( m_menuItem14 );
+
+ wxMenuItem* m_menuItem13;
+ m_menuItem13 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("&Load configuration") ) + wxT('\t') + wxT("CTRL-L"), wxEmptyString, wxITEM_NORMAL );
+ m_menuFile->Append( m_menuItem13 );
+
+ m_menuFile->AppendSeparator();
+
+ wxMenuItem* m_menuItem4;
+ m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("&Quit") ) + wxT('\t') + wxT("CTRL-Q"), wxEmptyString, wxITEM_NORMAL );
+ m_menuFile->Append( m_menuItem4 );
+
+ m_menubar1->Append( m_menuFile, _("&File") );
+
+ m_menuHelp = new wxMenu();
+ m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About...") ) + wxT('\t') + wxT("F1"), wxEmptyString, wxITEM_NORMAL );
+ m_menuHelp->Append( m_menuItemAbout );
+
+ m_menubar1->Append( m_menuHelp, _("&Help") );
+
+ this->SetMenuBar( m_menubar1 );
+
+ bSizerMain = new wxBoxSizer( wxVERTICAL );
+
+ m_panelMain = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ wxBoxSizer* bSizer1;
+ bSizer1 = new wxBoxSizer( wxVERTICAL );
+
+
+ bSizer1->Add( 0, 10, 0, 0, 5 );
+
+ m_staticText2 = new wxStaticText( m_panelMain, wxID_ANY, _("Usage: Select directories for monitoring and enter a commandline. Each time files are modified within these directories (or subdirectories) the commandline is executed."), wxDefaultPosition, wxDefaultSize, 0|wxDOUBLE_BORDER );
+ m_staticText2->Wrap( 350 );
+ bSizer1->Add( m_staticText2, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 40 );
+
+ m_staticline2 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer1->Add( m_staticline2, 0, wxTOP|wxBOTTOM|wxEXPAND, 10 );
+
+ wxBoxSizer* bSizer8;
+ bSizer8 = new wxBoxSizer( wxVERTICAL );
+
+ wxStaticBoxSizer* sbSizer5;
+ sbSizer5 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Directories to watch") ), wxVERTICAL );
+
+ m_panelMainFolder = new wxPanel( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ wxBoxSizer* bSizer114;
+ bSizer114 = new wxBoxSizer( wxHORIZONTAL );
+
+ wxBoxSizer* bSizer781;
+ bSizer781 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW );
+ m_bpButtonAddFolder->SetToolTip( _("Add folder") );
+
+ m_bpButtonAddFolder->SetToolTip( _("Add folder") );
+
+ bSizer781->Add( m_bpButtonAddFolder, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveTopFolder->SetToolTip( _("Remove folder") );
+
+ m_bpButtonRemoveTopFolder->SetToolTip( _("Remove folder") );
+
+ bSizer781->Add( m_bpButtonRemoveTopFolder, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer114->Add( bSizer781, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_txtCtrlDirectoryMain = new wxTextCtrl( m_panelMainFolder, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer114->Add( m_txtCtrlDirectoryMain, 1, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_dirPickerMain = new wxDirPickerCtrl( m_panelMainFolder, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_dirPickerMain->SetToolTip( _("Select a folder") );
+
+ bSizer114->Add( m_dirPickerMain, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_panelMainFolder->SetSizer( bSizer114 );
+ m_panelMainFolder->Layout();
+ bSizer114->Fit( m_panelMainFolder );
+ sbSizer5->Add( m_panelMainFolder, 0, wxEXPAND, 5 );
+
+ m_scrolledWinFolders = new wxScrolledWindow( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
+ m_scrolledWinFolders->SetScrollRate( 5, 5 );
+ bSizerFolders = new wxBoxSizer( wxVERTICAL );
+
+ m_scrolledWinFolders->SetSizer( bSizerFolders );
+ m_scrolledWinFolders->Layout();
+ bSizerFolders->Fit( m_scrolledWinFolders );
+ sbSizer5->Add( m_scrolledWinFolders, 0, wxEXPAND, 5 );
+
+ bSizer8->Add( sbSizer5, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+
+ bSizer1->Add( bSizer8, 1, wxEXPAND, 5 );
+
+ wxStaticBoxSizer* sbSizer3;
+ sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Commandline") ), wxVERTICAL );
+
+ m_textCtrlCommand = new wxTextCtrl( m_panelMain, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ sbSizer3->Add( m_textCtrlCommand, 0, wxEXPAND|wxBOTTOM, 5 );
+
+ bSizer1->Add( sbSizer3, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
+
+ m_staticline1 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer1->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 10 );
+
+ wxStaticBoxSizer* sbSizer4;
+ sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Delay") ), wxVERTICAL );
+
+ m_spinCtrlDelay = new wxSpinCtrl( m_panelMain, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_WRAP, 0, 2000000000, 0 );
+ m_spinCtrlDelay->SetToolTip( _("Delay between two invocations of the commandline") );
+
+ sbSizer4->Add( m_spinCtrlDelay, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ bSizer1->Add( sbSizer4, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
+
+ m_buttonStart = new wxButtonWithImage( m_panelMain, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
+ m_buttonStart->SetDefault();
+ m_buttonStart->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) );
+
+ bSizer1->Add( m_buttonStart, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_buttonCancel = new wxButton( m_panelMain, wxID_CANCEL, _("dummy"), wxDefaultPosition, wxSize( 0,0 ), 0 );
+ bSizer1->Add( m_buttonCancel, 0, 0, 5 );
+
+ m_panelMain->SetSizer( bSizer1 );
+ m_panelMain->Layout();
+ bSizer1->Fit( m_panelMain );
+ bSizerMain->Add( m_panelMain, 1, wxEXPAND, 5 );
+
+ this->SetSizer( bSizerMain );
+ this->Layout();
+ bSizerMain->Fit( this );
+
+ // Connect Events
+ this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDlgGenerated::OnClose ) );
+ this->Connect( m_menuItem14->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnSaveConfig ) );
+ this->Connect( m_menuItem13->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnLoadConfig ) );
+ this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnQuit ) );
+ this->Connect( m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnMenuAbout ) );
+ m_bpButtonAddFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnAddFolder ), NULL, this );
+ m_bpButtonRemoveTopFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnRemoveTopFolder ), NULL, this );
+ m_buttonStart->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnStart ), NULL, this );
+ m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnQuit ), NULL, this );
+}
+
+MainDlgGenerated::~MainDlgGenerated()
+{
+ // Disconnect Events
+ this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDlgGenerated::OnClose ) );
+ this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnSaveConfig ) );
+ this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnLoadConfig ) );
+ this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnQuit ) );
+ this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnMenuAbout ) );
+ m_bpButtonAddFolder->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnAddFolder ), NULL, this );
+ m_bpButtonRemoveTopFolder->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnRemoveTopFolder ), NULL, this );
+ m_buttonStart->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnStart ), NULL, this );
+ m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnQuit ), NULL, this );
+}
+
+FolderGenerated::FolderGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+{
+ wxBoxSizer* bSizer114;
+ bSizer114 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveFolder->SetToolTip( _("Remove folder") );
+
+ m_bpButtonRemoveFolder->SetToolTip( _("Remove folder") );
+
+ bSizer114->Add( m_bpButtonRemoveFolder, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ wxBoxSizer* bSizer20;
+ bSizer20 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_txtCtrlDirectory = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer20->Add( m_txtCtrlDirectory, 1, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_dirPicker = new wxDirPickerCtrl( this, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_dirPicker->SetToolTip( _("Select a folder") );
+
+ bSizer20->Add( m_dirPicker, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer114->Add( bSizer20, 1, 0, 5 );
+
+ this->SetSizer( bSizer114 );
+ this->Layout();
+ bSizer114->Fit( this );
+}
+
+FolderGenerated::~FolderGenerated()
+{
+}
diff --git a/RealtimeSync/guiGenerated.h b/RealtimeSync/guiGenerated.h
new file mode 100644
index 00000000..f62410a1
--- /dev/null
+++ b/RealtimeSync/guiGenerated.h
@@ -0,0 +1,128 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Apr 16 2008)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO "NOT" EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef __guiGenerated__
+#define __guiGenerated__
+
+#include <wx/intl.h>
+
+class wxButtonWithImage;
+
+#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/stattext.h>
+#include <wx/statline.h>
+#include <wx/bmpbuttn.h>
+#include <wx/button.h>
+#include <wx/sizer.h>
+#include <wx/textctrl.h>
+#include <wx/filepicker.h>
+#include <wx/panel.h>
+#include <wx/scrolwin.h>
+#include <wx/statbox.h>
+#include <wx/spinctrl.h>
+#include <wx/frame.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class MainDlgGenerated
+///////////////////////////////////////////////////////////////////////////////
+class MainDlgGenerated : public wxFrame
+{
+private:
+
+protected:
+ wxMenuBar* m_menubar1;
+ wxMenu* m_menuFile;
+ wxMenu* m_menuHelp;
+ wxMenuItem* m_menuItemAbout;
+ wxBoxSizer* bSizerMain;
+ wxPanel* m_panelMain;
+
+ wxStaticText* m_staticText2;
+ wxStaticLine* m_staticline2;
+ wxPanel* m_panelMainFolder;
+ wxBitmapButton* m_bpButtonAddFolder;
+ wxBitmapButton* m_bpButtonRemoveTopFolder;
+ wxTextCtrl* m_txtCtrlDirectoryMain;
+ wxScrolledWindow* m_scrolledWinFolders;
+ wxBoxSizer* bSizerFolders;
+ wxTextCtrl* m_textCtrlCommand;
+ wxStaticLine* m_staticline1;
+ wxSpinCtrl* m_spinCtrlDelay;
+ wxButtonWithImage* m_buttonStart;
+ wxButton* m_buttonCancel;
+
+ // Virtual event handlers, overide them in your derived class
+ virtual void OnClose( wxCloseEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnSaveConfig( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnLoadConfig( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnQuit( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnMenuAbout( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnAddFolder( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnRemoveTopFolder( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+ virtual void OnStart( wxCommandEvent& event )
+ {
+ event.Skip();
+ }
+
+
+public:
+ wxDirPickerCtrl* m_dirPickerMain;
+ MainDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("RealtimeSync - Automated Synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
+ ~MainDlgGenerated();
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class FolderGenerated
+///////////////////////////////////////////////////////////////////////////////
+class FolderGenerated : public wxPanel
+{
+private:
+
+protected:
+
+public:
+ wxBitmapButton* m_bpButtonRemoveFolder;
+ wxTextCtrl* m_txtCtrlDirectory;
+ wxDirPickerCtrl* m_dirPicker;
+ FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
+ ~FolderGenerated();
+
+};
+
+#endif //__guiGenerated__
diff --git a/RealtimeSync/mainDialog.cpp b/RealtimeSync/mainDialog.cpp
new file mode 100644
index 00000000..a3496b35
--- /dev/null
+++ b/RealtimeSync/mainDialog.cpp
@@ -0,0 +1,427 @@
+#include "mainDialog.h"
+#include "resources.h"
+#include "../shared/customButton.h"
+#include "../shared/standardPaths.h"
+#include "../shared/globalFunctions.h"
+#include <wx/msgdlg.h>
+#include <wx/wupdlock.h>
+#include "watcher.h"
+#include <wx/utils.h>
+#include "xmlProcessing.h"
+#include "trayMenu.h"
+#include "../shared/fileHandling.h"
+#include "xmlFreeFileSync.h"
+
+
+MainDialog::MainDialog(wxDialog *dlg, const wxString& cfgFilename)
+ : MainDlgGenerated(dlg)
+{
+ wxWindowUpdateLocker dummy(this); //avoid display distortion
+
+ m_bpButtonRemoveTopFolder->Hide();
+ m_panelMainFolder->Layout();
+
+ m_bpButtonAddFolder->SetBitmapLabel(*GlobalResources::getInstance().bitmapAddFolderPair);
+ m_bpButtonRemoveTopFolder->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
+ m_buttonStart->setBitmapFront(*GlobalResources::getInstance().bitmapStart);
+ m_buttonStart->SetFocus();
+
+ //register key event
+ Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnKeyPressed), NULL, this);
+
+ //prepare drag & drop
+ dragDropOnFolder.reset(new FreeFileSync::DragDropOnDlg(m_panelMainFolder, m_dirPickerMain, m_txtCtrlDirectoryMain));
+
+ //load config values
+ xmlAccess::XmlRealConfig newConfig;
+ bool startWatchingImmediately = false;
+
+
+ if (cfgFilename.empty())
+ try
+ {
+ RealtimeSync::readRealOrBatchConfig(lastConfigFileName(), newConfig);
+ }
+ catch (const xmlAccess::XmlError& error)
+ {
+ if (wxFileExists(lastConfigFileName())) //show error only if it's a parsing problem
+ {
+ if (error.getSeverity() == xmlAccess::XmlError::WARNING)
+ wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
+ else
+ wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
+ }
+ }
+ else
+ try
+ {
+ RealtimeSync::readRealOrBatchConfig(cfgFilename, newConfig);
+ startWatchingImmediately = true;
+ }
+ catch (const xmlAccess::XmlError& error)
+ {
+ if (error.getSeverity() == xmlAccess::XmlError::WARNING)
+ wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
+ else
+ wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
+ }
+
+ setConfiguration(newConfig);
+
+ m_buttonStart->SetFocus();
+ Fit();
+ Center();
+
+ if (startWatchingImmediately) //start watch mode directly
+ {
+ wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED);
+ this->OnStart(dummy);
+ }
+}
+
+
+MainDialog::~MainDialog()
+{
+ //save current configuration
+ const xmlAccess::XmlRealConfig currentCfg = getConfiguration();
+
+ try //write config to XML
+ {
+ writeRealConfig(currentCfg, lastConfigFileName());
+ }
+ catch (const FreeFileSync::FileError& error)
+ {
+ wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ }
+}
+
+
+void MainDialog::OnClose(wxCloseEvent &event)
+{
+ Destroy();
+}
+
+
+void MainDialog::OnQuit(wxCommandEvent &event)
+{
+ Destroy();
+}
+
+
+const wxString& MainDialog::lastConfigFileName()
+{
+ static wxString instance = FreeFileSync::getConfigDir().EndsWith(wxString(globalFunctions::FILE_NAME_SEPARATOR)) ?
+ FreeFileSync::getConfigDir() + wxT("LastRun.ffs_real") :
+ FreeFileSync::getConfigDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("LastRun.ffs_real");
+ return instance;
+}
+
+
+void MainDialog::OnMenuAbout(wxCommandEvent& event)
+{
+ //build information
+ wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__;
+#if wxUSE_UNICODE
+ build += wxT(" - Unicode)");
+#else
+ build += wxT(" - ANSI)");
+#endif //wxUSE_UNICODE
+
+ wxMessageDialog* aboutDlg = new wxMessageDialog(this, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK);
+ aboutDlg->ShowModal();
+}
+
+
+void MainDialog::OnKeyPressed(wxKeyEvent& event)
+{
+ const int keyCode = event.GetKeyCode();
+
+ if (keyCode == WXK_ESCAPE)
+ Destroy();
+
+ event.Skip();
+}
+
+
+void MainDialog::OnStart(wxCommandEvent& event)
+{
+ xmlAccess::XmlRealConfig currentCfg = getConfiguration();
+
+ Hide();
+
+ wxWindowDisabler dummy; //avoid unwanted re-entrance in the following process
+
+ switch (RealtimeSync::startDirectoryMonitor(currentCfg))
+ {
+ case RealtimeSync::QUIT:
+ {
+ Destroy();
+ return;
+ }
+ break;
+
+ case RealtimeSync::RESUME:
+ break;
+ }
+
+ Show();
+}
+
+
+void MainDialog::OnSaveConfig(wxCommandEvent& event)
+{
+ const wxString defaultFileName = wxT("Realtime.ffs_real");
+
+ wxFileDialog* filePicker = new wxFileDialog(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("RealtimeSync configuration")) + wxT(" (*.ffs_real)|*.ffs_real"), wxFD_SAVE);
+ if (filePicker->ShowModal() == wxID_OK)
+ {
+ const wxString newFileName = filePicker->GetPath();
+
+ if (wxFileExists(newFileName))
+ {
+ wxMessageDialog* messageDlg = new wxMessageDialog(this, wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""), _("Warning") , wxOK | wxCANCEL);
+
+ if (messageDlg->ShowModal() != wxID_OK)
+ {
+ OnSaveConfig(event); //retry
+ return;
+ }
+ }
+
+ const xmlAccess::XmlRealConfig currentCfg = getConfiguration();
+
+ try //write config to XML
+ {
+ writeRealConfig(currentCfg, newFileName);
+ }
+ catch (const FreeFileSync::FileError& error)
+ {
+ wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ }
+ }
+}
+
+
+void MainDialog::loadConfig(const wxString& filename)
+{
+ xmlAccess::XmlRealConfig newConfig;
+
+ try
+ {
+ RealtimeSync::readRealOrBatchConfig(filename, newConfig);
+ }
+ catch (const xmlAccess::XmlError& error)
+ {
+ if (error.getSeverity() == xmlAccess::XmlError::WARNING)
+ wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
+ else
+ {
+ wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
+ return;
+ }
+ }
+
+ setConfiguration(newConfig);
+}
+
+
+void MainDialog::OnLoadConfig(wxCommandEvent& event)
+{
+ wxFileDialog* filePicker = new wxFileDialog(this, wxEmptyString, wxEmptyString, wxEmptyString,
+ wxString(_("RealtimeSync configuration")) + wxT(" (*.ffs_real;*.ffs_batch)|*.ffs_real;*.ffs_batch"),
+ wxFD_OPEN);
+ if (filePicker->ShowModal() == wxID_OK)
+ loadConfig(filePicker->GetPath());
+}
+
+
+void MainDialog::setConfiguration(const xmlAccess::XmlRealConfig& cfg)
+{
+ //clear existing folders
+ m_txtCtrlDirectoryMain->ChangeValue(wxEmptyString);
+ m_dirPickerMain->SetPath(wxEmptyString);
+
+ clearAddFolders();
+
+ if (!cfg.directories.empty())
+ {
+ //fill top folder
+ m_txtCtrlDirectoryMain->SetValue(*cfg.directories.begin());
+
+ const wxString dirFormatted = FreeFileSync::getFormattedDirectoryName(cfg.directories.begin()->c_str()).c_str();
+ if (wxDirExists(dirFormatted))
+ m_dirPickerMain->SetPath(dirFormatted);
+
+ //fill additional folders
+ addFolder(std::vector<wxString>(cfg.directories.begin() + 1, cfg.directories.end()));
+ }
+
+ //fill commandline
+ m_textCtrlCommand->SetValue(cfg.commandline);
+
+ //set delay
+ m_spinCtrlDelay->SetValue(cfg.delay);
+}
+
+
+xmlAccess::XmlRealConfig MainDialog::getConfiguration()
+{
+ xmlAccess::XmlRealConfig output;
+
+ output.directories.push_back(m_txtCtrlDirectoryMain->GetValue());
+ for (std::vector<FolderPanel*>::const_iterator i = additionalFolders.begin(); i != additionalFolders.end(); ++i)
+ output.directories.push_back((*i)->m_txtCtrlDirectory->GetValue());
+
+ output.commandline = m_textCtrlCommand->GetValue();
+ output.delay = m_spinCtrlDelay->GetValue();;
+
+ return output;
+}
+
+
+void MainDialog::OnAddFolder(wxCommandEvent& event)
+{
+ const wxString topFolder = m_txtCtrlDirectoryMain->GetValue();
+
+ //clear existing top folder first
+ RealtimeSync::setDirectoryName(wxEmptyString, m_txtCtrlDirectoryMain, m_dirPickerMain);
+
+ std::vector<wxString> newFolders;
+ newFolders.push_back(topFolder.c_str());
+
+ addFolder(newFolders, true); //add pair in front of additonal pairs
+}
+
+
+void MainDialog::OnRemoveFolder(wxCommandEvent& event)
+{
+ //find folder pair originating the event
+ const wxObject* const eventObj = event.GetEventObject();
+ for (std::vector<FolderPanel*>::const_iterator i = additionalFolders.begin(); i != additionalFolders.end(); ++i)
+ {
+ if (eventObj == static_cast<wxObject*>((*i)->m_bpButtonRemoveFolder))
+ {
+ removeAddFolder(i - additionalFolders.begin());
+ return;
+ }
+ }
+}
+
+
+void MainDialog::OnRemoveTopFolder(wxCommandEvent& event)
+{
+ if (additionalFolders.size() > 0)
+ {
+ const wxString topDir = (*additionalFolders.begin())->m_txtCtrlDirectory->GetValue().c_str();
+ RealtimeSync::setDirectoryName(topDir, m_txtCtrlDirectoryMain, m_dirPickerMain);
+
+ removeAddFolder(0); //remove first of additional folders
+ }
+}
+
+
+#ifdef FFS_WIN
+static const size_t MAX_ADD_FOLDERS = 8;
+#elif defined FFS_LINUX
+static const size_t MAX_ADD_FOLDERS = 6;
+#endif
+
+
+void MainDialog::addFolder(const std::vector<wxString>& newFolders, bool addFront)
+{
+ if (newFolders.size() == 0)
+ return;
+
+ wxWindowUpdateLocker dummy(this); //avoid display distortion
+
+ int folderHeight = 0;
+ for (std::vector<wxString>::const_iterator i = newFolders.begin(); i != newFolders.end(); ++i)
+ {
+ //add new folder pair
+ FolderPanel* newFolder = new FolderPanel(m_scrolledWinFolders);
+ newFolder->m_bpButtonRemoveFolder->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
+
+ //get size of scrolled window
+ folderHeight = newFolder->GetSize().GetHeight();
+
+ if (addFront)
+ {
+ bSizerFolders->Insert(0, newFolder, 0, wxEXPAND, 5);
+ additionalFolders.insert(additionalFolders.begin(), newFolder);
+ }
+ else
+ {
+ bSizerFolders->Add(newFolder, 0, wxEXPAND, 5);
+ additionalFolders.push_back(newFolder);
+ }
+
+ //register events
+ newFolder->m_bpButtonRemoveFolder->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolder), NULL, this );
+
+ //insert directory name
+ RealtimeSync::setDirectoryName(*i, newFolder->m_txtCtrlDirectory, newFolder->m_dirPicker);
+ }
+
+ //set size of scrolled window
+ const int additionalRows = std::min(additionalFolders.size(), MAX_ADD_FOLDERS); //up to MAX_ADD_FOLDERS additional folders shall be shown
+ m_scrolledWinFolders->SetMinSize(wxSize( -1, folderHeight * additionalRows));
+
+ //adapt delete top folder pair button
+ m_bpButtonRemoveTopFolder->Show();
+ m_panelMainFolder->Layout();
+
+ //update controls
+ m_scrolledWinFolders->Fit(); //adjust scrolled window size
+ m_scrolledWinFolders->Layout(); //fix small layout problem
+ m_panelMain->Layout(); //adjust stuff inside scrolled window
+ Fit(); //adapt dialog size
+}
+
+
+void MainDialog::removeAddFolder(const int pos)
+{
+ wxWindowUpdateLocker dummy(this); //avoid display distortion
+
+ if (0 <= pos && pos < int(additionalFolders.size()))
+ {
+ //remove folder pairs from window
+ FolderPanel* dirToDelete = additionalFolders[pos];
+ const int folderHeight = dirToDelete->GetSize().GetHeight();
+
+ bSizerFolders->Detach(dirToDelete); //Remove() does not work on Window*, so do it manually
+ dirToDelete->Destroy(); //
+ additionalFolders.erase(additionalFolders.begin() + pos); //remove last element in vector
+
+
+ //set size of scrolled window
+ const int additionalRows = std::min(additionalFolders.size(), MAX_ADD_FOLDERS); //up to MAX_ADD_FOLDERS additional folders shall be shown
+ m_scrolledWinFolders->SetMinSize(wxSize( -1, folderHeight * additionalRows));
+
+ //adapt delete top folder pair button
+ if (additionalFolders.size() == 0)
+ {
+ m_bpButtonRemoveTopFolder->Hide();
+ m_panelMainFolder->Layout();
+ }
+
+ //update controls
+ m_scrolledWinFolders->Fit(); //adjust scrolled window size
+ m_panelMain->Layout(); //adjust stuff inside scrolled window
+ Fit(); //adapt dialog size
+ }
+}
+
+
+void MainDialog::clearAddFolders()
+{
+ wxWindowUpdateLocker dummy(this); //avoid display distortion
+
+ additionalFolders.clear();
+ bSizerFolders->Clear(true);
+
+ m_bpButtonRemoveTopFolder->Hide();
+ m_panelMainFolder->Layout();
+
+ m_scrolledWinFolders->SetMinSize(wxSize(-1, 0));
+ Fit(); //adapt dialog size
+}
diff --git a/RealtimeSync/mainDialog.h b/RealtimeSync/mainDialog.h
new file mode 100644
index 00000000..9cf44a67
--- /dev/null
+++ b/RealtimeSync/mainDialog.h
@@ -0,0 +1,75 @@
+/***************************************************************
+ * Purpose: Defines Application Frame
+ * Author: ZenJu (zhnmju123@gmx.de)
+ * Created: 2009-07-06
+ * Copyright: ZenJu (http://sourceforge.net/projects/freefilesync/)
+ **************************************************************/
+
+#ifndef REALTIMESYNCMAIN_H
+#define REALTIMESYNCMAIN_H
+
+#include "guiGenerated.h"
+#include <vector>
+#include <memory>
+#include "../shared/dragAndDrop.h"
+
+namespace xmlAccess
+{
+ struct XmlRealConfig;
+}
+
+
+class FolderPanel : public FolderGenerated
+{
+public:
+ FolderPanel(wxWindow* parent) :
+ FolderGenerated(parent),
+ dragDropOnFolder(new FreeFileSync::DragDropOnDlg(this, m_dirPicker, m_txtCtrlDirectory)) {}
+
+private:
+ //support for drag and drop
+ std::auto_ptr<FreeFileSync::DragDropOnDlg> dragDropOnFolder;
+};
+
+
+
+class MainDialog: public MainDlgGenerated
+{
+public:
+ MainDialog(wxDialog *dlg, const wxString& cfgFilename);
+ ~MainDialog();
+
+ void loadConfig(const wxString& filename);
+
+private:
+ virtual void OnClose( wxCloseEvent& event);
+ virtual void OnQuit( wxCommandEvent& event);
+ virtual void OnMenuAbout( wxCommandEvent& event);
+ virtual void OnAddFolder( wxCommandEvent& event);
+ virtual void OnRemoveFolder( wxCommandEvent& event);
+ virtual void OnRemoveTopFolder( wxCommandEvent& event);
+ virtual void OnKeyPressed( wxKeyEvent& event);
+ virtual void OnStart( wxCommandEvent& event);
+ virtual void OnSaveConfig( wxCommandEvent& event);
+ virtual void OnLoadConfig( wxCommandEvent& event);
+
+ void setConfiguration(const xmlAccess::XmlRealConfig& cfg);
+ xmlAccess::XmlRealConfig getConfiguration();
+
+ void layoutAsync(); //call Layout() asynchronously
+
+ void addFolder(const wxString& dirname, bool addFront = false);
+ void addFolder(const std::vector<wxString>& newFolders, bool addFront = false);
+ void removeAddFolder(const int pos); //keep it an int, allow negative values!
+ void clearAddFolders();
+
+ static const wxString& lastConfigFileName();
+
+ //additional folders
+ std::vector<FolderPanel*> additionalFolders; //additional pairs to the standard pair
+
+ //support for drag and drop on main folder
+ std::auto_ptr<FreeFileSync::DragDropOnDlg> dragDropOnFolder;
+};
+
+#endif // REALTIMESYNCMAIN_H
diff --git a/RealtimeSync/makefile b/RealtimeSync/makefile
new file mode 100644
index 00000000..02303ba9
--- /dev/null
+++ b/RealtimeSync/makefile
@@ -0,0 +1,57 @@
+CPPFLAGS=-Wall -pipe -DNDEBUG `wx-config --cppflags` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -DZSTRING_CHAR -O3 -pthread -c
+LINKFLAGS=`wx-config --libs` -O3 -pthread
+
+FILE_LIST= #internal list of all *.cpp files needed for compilation
+FILE_LIST+=application.cpp
+FILE_LIST+=functions.cpp
+FILE_LIST+=guiGenerated.cpp
+FILE_LIST+=mainDialog.cpp
+FILE_LIST+=resources.cpp
+FILE_LIST+=trayMenu.cpp
+FILE_LIST+=watcher.cpp
+FILE_LIST+=xmlProcessing.cpp
+FILE_LIST+=xmlFreeFileSync.cpp
+FILE_LIST+=../library/processXml.cpp
+FILE_LIST+=../structures.cpp
+FILE_LIST+=../shared/inotify/inotify-cxx.cpp
+FILE_LIST+=../shared/tinyxml/tinyxml.cpp
+FILE_LIST+=../shared/tinyxml/tinystr.cpp
+FILE_LIST+=../shared/tinyxml/tinyxmlerror.cpp
+FILE_LIST+=../shared/tinyxml/tinyxmlparser.cpp
+FILE_LIST+=../shared/globalFunctions.cpp
+FILE_LIST+=../shared/systemFunctions.cpp
+FILE_LIST+=../shared/dragAndDrop.cpp
+FILE_LIST+=../shared/zstring.cpp
+FILE_LIST+=../shared/xmlBase.cpp
+FILE_LIST+=../shared/customButton.cpp
+FILE_LIST+=../shared/fileHandling.cpp
+FILE_LIST+=../shared/fileTraverser.cpp
+FILE_LIST+=../shared/localization.cpp
+FILE_LIST+=../shared/standardPaths.cpp
+
+#list of all *.o files
+OBJECT_LIST=$(foreach file, $(FILE_LIST), OBJ/$(subst .cpp,.o,$(notdir $(file))))
+
+#build list of all dependencies
+DEP_LIST=$(foreach file, $(FILE_LIST), $(subst .cpp,.dep,$(file)))
+
+
+all: RealtimeSync
+
+init:
+ if [ ! -d OBJ ]; then mkdir OBJ; fi
+
+#remove byte ordering mark: needed by Visual C++ but an error with GCC
+removeBOM: ../tools/removeBOM.cpp
+ g++ -o removeBOM ../tools/removeBOM.cpp
+ ./removeBOM ../shared/localization.cpp
+
+%.dep : %.cpp
+ #strip path information
+ g++ $(CPPFLAGS) $< -o OBJ/$(subst .cpp,.o,$(notdir $<))
+
+RealtimeSync: init removeBOM $(DEP_LIST)
+ g++ $(LINKFLAGS) -o ../BUILD/RealtimeSync $(OBJECT_LIST)
+
+clean:
+ find OBJ -type f -exec rm {} \;
diff --git a/RealtimeSync/pch.h b/RealtimeSync/pch.h
new file mode 100644
index 00000000..22ed251f
--- /dev/null
+++ b/RealtimeSync/pch.h
@@ -0,0 +1,97 @@
+#ifndef FFS_PRECOMPILED_HEADER
+#define FFS_PRECOMPILED_HEADER
+
+//pay attention when using this file: might cause issues!
+#ifndef __WXDEBUG__
+do NOT use in release build!
+#endif
+
+//#####################################################
+// basic wxWidgets headers
+#ifndef WX_PRECOMP
+#define WX_PRECOMP
+#endif
+
+#include <wx/wxprec.h>
+
+//#####################################################
+// #include other rarely changing headers here
+
+//STL headers
+#include <string>
+#include <algorithm>
+#include <vector>
+#include <queue>
+#include <stack>
+#include <set>
+#include <map>
+#include <memory>
+#include <fstream>
+
+#ifdef FFS_LINUX
+#include <utime.h>
+#endif //FFS_LINUX
+
+//other wxWidgets headers
+#include <wx/grid.h>
+#include <wx/animate.h>
+#include <wx/app.h>
+#include <wx/arrstr.h>
+#include <wx/bitmap.h>
+#include <wx/bmpbuttn.h>
+#include <wx/button.h>
+#include <wx/checkbox.h>
+#include <wx/choice.h>
+#include <wx/clipbrd.h>
+#include <wx/cmdline.h>
+#include <wx/colour.h>
+#include <wx/config.h>
+#include <wx/dc.h>
+#include <wx/dialog.h>
+#include <wx/dir.h>
+#include <wx/dnd.h>
+#include <wx/file.h>
+#include <wx/filename.h>
+#include <wx/filepicker.h>
+#include <wx/font.h>
+#include <wx/frame.h>
+#include <wx/gauge.h>
+#include <wx/gdicmn.h>
+#include <wx/grid.h>
+#include <wx/hyperlink.h>
+#include <wx/icon.h>
+#include <wx/image.h>
+#include <wx/intl.h>
+#include <wx/log.h>
+#include <wx/menu.h>
+#include <wx/msgdlg.h>
+#include <wx/panel.h>
+#include <wx/radiobut.h>
+#include <wx/settings.h>
+#include <wx/sizer.h>
+#include <wx/statbmp.h>
+#include <wx/statbox.h>
+#include <wx/statline.h>
+#include <wx/stattext.h>
+#include <wx/stdpaths.h>
+#include <wx/stopwatch.h>
+#include <wx/stream.h>
+#include <wx/string.h>
+#include <wx/textctrl.h>
+#include <wx/thread.h>
+#include <wx/utils.h>
+#include <wx/wfstream.h>
+#include <wx/zipstrm.h>
+#include <wx/scrolwin.h>
+#include <wx/notebook.h>
+
+//other
+#include "../shared/tinyxml/tinyxml.h"
+#include <sys/stat.h>
+
+#ifdef FFS_WIN
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+#endif //FFS_WIN
+//#####################################################
+
+#endif //FFS_PRECOMPILED_HEADER
diff --git a/RealtimeSync/resource.rc b/RealtimeSync/resource.rc
new file mode 100644
index 00000000..616ea49d
--- /dev/null
+++ b/RealtimeSync/resource.rc
@@ -0,0 +1,4 @@
+#include "wx/msw/wx.rc"
+
+//naming convention to set icon sequence in executable file
+A_PROGRAM_ICON ICON DISCARDABLE "RealtimeSync.ico"
diff --git a/RealtimeSync/resources.cpp b/RealtimeSync/resources.cpp
new file mode 100644
index 00000000..638df0f6
--- /dev/null
+++ b/RealtimeSync/resources.cpp
@@ -0,0 +1,81 @@
+#include "resources.h"
+#include <wx/wfstream.h>
+#include <wx/zipstrm.h>
+#include <wx/image.h>
+#include <wx/icon.h>
+#include "../shared/globalFunctions.h"
+#include "../shared/standardPaths.h"
+
+
+const GlobalResources& GlobalResources::getInstance()
+{
+ static GlobalResources instance;
+ return instance;
+}
+
+
+GlobalResources::GlobalResources()
+{
+ //map, allocate and initialize pictures
+ bitmapResource[wxT("start red.png")] = (bitmapStart = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("add pair.png")] = (bitmapAddFolderPair = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("remove pair.png")] = (bitmapRemoveFolderPair = new wxBitmap(wxNullBitmap));
+
+ programIcon = new wxIcon(wxNullIcon);
+}
+
+
+GlobalResources::~GlobalResources()
+{
+ //free bitmap resources
+ for (std::map<wxString, wxBitmap*>::iterator i = bitmapResource.begin(); i != bitmapResource.end(); ++i)
+ delete i->second;
+
+ //free other resources
+ delete programIcon;
+}
+
+
+void GlobalResources::load() const
+{
+ wxFFileInputStream input(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("Resources.dat"));
+ if (input.IsOk()) //if not... we don't want to react too harsh here
+ {
+ //activate support for .png files
+ wxImage::AddHandler(new wxPNGHandler); //ownership passed
+
+ wxZipInputStream resourceFile(input);
+
+ std::map<wxString, wxBitmap*>::iterator bmp;
+ while (true)
+ {
+ std::auto_ptr<wxZipEntry> entry(resourceFile.GetNextEntry());
+ if (entry.get() == NULL)
+ break;
+
+ const wxString name = entry->GetName();
+
+ //search if entry is available in map
+ if ((bmp = bitmapResource.find(name)) != bitmapResource.end())
+ *(bmp->second) = wxBitmap(wxImage(resourceFile, wxBITMAP_TYPE_PNG));
+ }
+ }
+
+#ifdef FFS_WIN
+ *programIcon = wxIcon(wxT("A_PROGRAM_ICON"));
+#else
+#include "RealtimeSync.xpm"
+ *programIcon = wxIcon(RealtimeSync_xpm);
+#endif
+}
+
+
+const wxBitmap& GlobalResources::getImageByName(const wxString& imageName) const
+{
+ std::map<wxString, wxBitmap*>::const_iterator bmp = bitmapResource.find(imageName);
+ if (bmp != bitmapResource.end())
+ return *bmp->second;
+ else
+ return wxNullBitmap;
+}
+
diff --git a/RealtimeSync/resources.h b/RealtimeSync/resources.h
new file mode 100644
index 00000000..3a0cde7b
--- /dev/null
+++ b/RealtimeSync/resources.h
@@ -0,0 +1,33 @@
+#ifndef RESOURCES_H_INCLUDED
+#define RESOURCES_H_INCLUDED
+
+#include <wx/bitmap.h>
+#include <wx/string.h>
+#include <map>
+
+
+class GlobalResources
+{
+public:
+ static const GlobalResources& getInstance();
+
+ const wxBitmap& getImageByName(const wxString& imageName) const;
+
+ //image resource objects
+ wxBitmap* bitmapStart;
+ wxBitmap* bitmapAddFolderPair;
+ wxBitmap* bitmapRemoveFolderPair;
+
+ wxIcon* programIcon;
+
+ void load() const; //loads bitmap resources on program startup: logical const!
+
+private:
+ GlobalResources();
+ ~GlobalResources();
+
+ //resource mapping
+ mutable std::map<wxString, wxBitmap*> bitmapResource;
+};
+
+#endif // RESOURCES_H_INCLUDED
diff --git a/RealtimeSync/trayMenu.cpp b/RealtimeSync/trayMenu.cpp
new file mode 100644
index 00000000..5d9d2430
--- /dev/null
+++ b/RealtimeSync/trayMenu.cpp
@@ -0,0 +1,209 @@
+#include "trayMenu.h"
+#include <wx/msgdlg.h>
+#include <wx/taskbar.h>
+#include <wx/app.h>
+#include "resources.h"
+#include <memory>
+#include <wx/utils.h>
+#include <wx/menu.h>
+#include "watcher.h"
+#include <wx/timer.h>
+#include <wx/utils.h>
+#include <wx/log.h>
+
+class RtsTrayIcon;
+
+
+class WaitCallbackImpl : public RealtimeSync::WaitCallback
+{
+public:
+ WaitCallbackImpl();
+
+ virtual void requestUiRefresh();
+
+ void requestAbort()
+ {
+ m_abortRequested = true;
+ }
+
+ void requestResume()
+ {
+ m_resumeRequested = true;
+ }
+
+private:
+ std::auto_ptr<RtsTrayIcon> trayMenu;
+ bool m_abortRequested;
+ bool m_resumeRequested;
+};
+
+
+class RtsTrayIcon : public wxTaskBarIcon
+{
+public:
+ RtsTrayIcon(WaitCallbackImpl* callback) :
+ m_callback(callback)
+ {
+ wxTaskBarIcon::SetIcon(*GlobalResources::getInstance().programIcon, wxT("RealtimeSync"));
+
+ //register double-click
+ Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(RtsTrayIcon::resumeToMain), NULL, this);
+ }
+
+ void updateSysTray()
+ {
+ wxTheApp->Yield();
+ }
+
+private:
+ enum Selection
+ {
+ CONTEXT_ABORT,
+ CONTEXT_RESTORE,
+ CONTEXT_ABOUT
+ };
+
+ virtual wxMenu* CreatePopupMenu()
+ {
+ wxMenu* contextMenu = new wxMenu;
+ contextMenu->Append(CONTEXT_RESTORE, _("&Restore"));
+ contextMenu->Append(CONTEXT_ABOUT, _("&About..."));
+ contextMenu->AppendSeparator();
+ contextMenu->Append(CONTEXT_ABORT, _("&Exit"));
+ //event handling
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(RtsTrayIcon::OnContextMenuSelection), NULL, this);
+
+ return contextMenu; //ownership transferred to library
+ }
+
+ void OnContextMenuSelection(wxCommandEvent& event)
+ {
+ const int eventId = event.GetId();
+ switch (static_cast<Selection>(eventId))
+ {
+ case CONTEXT_ABORT:
+ m_callback->requestAbort();
+ break;
+ case CONTEXT_ABOUT:
+ {
+ //build information
+ wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__;
+#if wxUSE_UNICODE
+ build += wxT(" - Unicode)");
+#else
+ build += wxT(" - ANSI)");
+#endif //wxUSE_UNICODE
+
+ wxMessageDialog* aboutDlg = new wxMessageDialog(NULL, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK);
+ aboutDlg->ShowModal();
+ aboutDlg->Destroy();
+ }
+ break;
+ case CONTEXT_RESTORE:
+ m_callback->requestResume();
+ break;
+ }
+ }
+
+ void resumeToMain(wxCommandEvent& event)
+ {
+ m_callback->requestResume();
+ }
+
+ WaitCallbackImpl* m_callback;
+};
+
+
+bool updateUiIsAllowed()
+{
+ static wxLongLong lastExec = 0;
+ const wxLongLong newExec = wxGetLocalTimeMillis();
+
+ if (newExec - lastExec >= RealtimeSync::UI_UPDATE_INTERVAL) //perform ui updates not more often than necessary
+ {
+ lastExec = newExec;
+ return true;
+ }
+ return false;
+}
+
+
+class AbortThisProcess //exception class
+{
+public:
+ AbortThisProcess(bool backToMain) : m_backToMain(backToMain) {}
+
+ bool backToMainMenu() const
+ {
+ return m_backToMain;
+ }
+
+private:
+ bool m_backToMain;
+};
+
+
+
+WaitCallbackImpl::WaitCallbackImpl() :
+ m_abortRequested(false),
+ m_resumeRequested(false)
+{
+ trayMenu.reset(new RtsTrayIcon(this));
+}
+
+
+void WaitCallbackImpl::requestUiRefresh()
+{
+ if (updateUiIsAllowed())
+ trayMenu->updateSysTray();
+
+ if (m_abortRequested)
+ throw ::AbortThisProcess(false);
+
+ if (m_resumeRequested)
+ throw ::AbortThisProcess(true);
+}
+
+
+RealtimeSync::MonitorResponse RealtimeSync::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config)
+{
+ try
+ {
+ WaitCallbackImpl callback;
+
+ if (config.commandline.empty())
+ throw FreeFileSync::FileError(_("Commandline is empty!"));
+
+ long lastExec = 0;
+ while (true)
+ {
+ wxExecute(config.commandline, wxEXEC_SYNC); //execute command
+ wxLog::FlushActive(); //show wxWidgets error messages (if any)
+
+ //wait
+ waitForChanges(config.directories, &callback);
+ lastExec = wxGetLocalTime();
+
+ //some delay
+ while (wxGetLocalTime() - lastExec < static_cast<long>(config.delay))
+ {
+ callback.requestUiRefresh();
+ wxMilliSleep(RealtimeSync::UI_UPDATE_INTERVAL);
+ }
+ }
+ }
+ catch (const ::AbortThisProcess& ab)
+ {
+ if (ab.backToMainMenu())
+ return RESUME;
+ else
+ return QUIT;
+ }
+ catch (const FreeFileSync::FileError& error)
+ {
+ wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ return RESUME;
+ }
+
+ return RESUME;
+}
diff --git a/RealtimeSync/trayMenu.h b/RealtimeSync/trayMenu.h
new file mode 100644
index 00000000..04b07f8a
--- /dev/null
+++ b/RealtimeSync/trayMenu.h
@@ -0,0 +1,20 @@
+#ifndef TRAYMENU_H_INCLUDED
+#define TRAYMENU_H_INCLUDED
+
+#include "watcher.h"
+#include "xmlProcessing.h"
+
+
+namespace RealtimeSync
+{
+ enum MonitorResponse
+ {
+ RESUME,
+ QUIT
+ };
+
+ MonitorResponse startDirectoryMonitor(const xmlAccess::XmlRealConfig& config);
+}
+
+
+#endif // TRAYMENU_H_INCLUDED
diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp
new file mode 100644
index 00000000..4949f01a
--- /dev/null
+++ b/RealtimeSync/watcher.cpp
@@ -0,0 +1,198 @@
+#include "watcher.h"
+#include "../shared/systemFunctions.h"
+#include "functions.h"
+#include <wx/intl.h>
+#include <wx/filefn.h>
+#include "../shared/fileHandling.h"
+
+#ifdef FFS_WIN
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+
+#elif defined FFS_LINUX
+#include <wx/timer.h>
+#include <exception>
+#include "../shared/inotify/inotify-cxx.h"
+#include "../shared/fileTraverser.h"
+#endif
+
+
+#ifdef FFS_WIN
+class ChangeNotifications
+{
+public:
+ ~ChangeNotifications()
+ {
+ for (std::vector<HANDLE>::const_iterator i = arrayHandle.begin(); i != arrayHandle.end(); ++i)
+ if (*i != INVALID_HANDLE_VALUE)
+ ::FindCloseChangeNotification(*i);
+ }
+
+ void addHandle(const HANDLE hndl)
+ {
+ arrayHandle.push_back(hndl);
+ }
+
+ size_t getSize()
+ {
+ return arrayHandle.size();
+ }
+
+ const HANDLE* getArray()
+ {
+ return &arrayHandle[0]; //client needs to check getSize() before calling this method!
+ }
+
+private:
+ std::vector<HANDLE> arrayHandle;
+};
+
+#elif defined FFS_LINUX
+class DirsOnlyTraverser : public FreeFileSync::TraverseCallback
+{
+public:
+ DirsOnlyTraverser(std::vector<std::string>& dirs) : m_dirs(dirs) {}
+
+ virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details)
+ {
+ return TRAVERSING_CONTINUE;
+ }
+ virtual ReturnValDir onDir(const DefaultChar* shortName, const Zstring& fullName)
+ {
+ m_dirs.push_back(fullName.c_str());
+ return ReturnValDir(ReturnValDir::Continue(), this);
+ }
+ virtual ReturnValue onError(const wxString& errorText)
+ {
+ throw FreeFileSync::FileError(errorText);
+ }
+
+private:
+ std::vector<std::string>& m_dirs;
+};
+#endif
+
+
+void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCallback* statusHandler)
+{
+ if (dirNames.empty()) //pathological case, but check is needed later
+ return;
+
+#ifdef FFS_WIN
+ ChangeNotifications notifications;
+
+ for (std::vector<wxString>::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i)
+ {
+ const Zstring formattedDir = FreeFileSync::getFormattedDirectoryName(i->c_str());
+
+ if (formattedDir.empty())
+ throw FreeFileSync::FileError(_("Please fill all empty directory fields."));
+ else if (!FreeFileSync::dirExists(formattedDir))
+ throw FreeFileSync::FileError(wxString(_("Directory does not exist:")) + wxT("\n") +
+ wxT("\"") + formattedDir + wxT("\"") + wxT("\n\n") +
+ FreeFileSync::getLastErrorFormatted());
+
+ const HANDLE rv = ::FindFirstChangeNotification(
+ formattedDir.c_str(), //__in LPCTSTR lpPathName,
+ true, //__in BOOL bWatchSubtree,
+ FILE_NOTIFY_CHANGE_FILE_NAME |
+ FILE_NOTIFY_CHANGE_DIR_NAME |
+ FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE); //__in DWORD dwNotifyFilter
+
+ if (rv == INVALID_HANDLE_VALUE)
+ {
+ const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + *i + wxT("\"");
+ throw FreeFileSync::FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+ }
+
+ notifications.addHandle(rv);
+ }
+
+
+ while (true)
+ {
+ const DWORD rv = ::WaitForMultipleObjects( //NOTE: notifications.getArray() returns valid pointer, because it cannot be empty in this context
+ notifications.getSize(), //__in DWORD nCount,
+ notifications.getArray(), //__in const HANDLE *lpHandles,
+ false, //__in BOOL bWaitAll,
+ UI_UPDATE_INTERVAL); //__in DWORD dwMilliseconds
+ if (WAIT_OBJECT_0 <= rv && rv < WAIT_OBJECT_0 + notifications.getSize())
+ return; //directory change detected
+ else if (rv == WAIT_FAILED)
+ throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+ else if (rv == WAIT_TIMEOUT)
+ statusHandler->requestUiRefresh();
+ }
+
+#elif defined FFS_LINUX
+ std::vector<std::string> fullDirList;
+
+ //add all subdirectories
+ for (std::vector<wxString>::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i)
+ {
+ const Zstring formattedDir = FreeFileSync::getFormattedDirectoryName(i->c_str());
+
+ if (formattedDir.empty())
+ throw FreeFileSync::FileError(_("Please fill all empty directory fields."));
+
+ else if (!FreeFileSync::dirExists(formattedDir))
+ throw FreeFileSync::FileError(wxString(_("Directory does not exist:")) + wxT("\n") +
+ wxT("\"") + formattedDir + wxT("\"") + wxT("\n\n") +
+ FreeFileSync::getLastErrorFormatted());
+
+ fullDirList.push_back(formattedDir.c_str());
+ //get all subdirectories
+ DirsOnlyTraverser traverser(fullDirList);
+ FreeFileSync::traverseFolder(formattedDir, false, &traverser); //don't traverse into symlinks (analog to windows build)
+ }
+
+ try
+ {
+ Inotify notifications;
+ notifications.SetNonBlock(true);
+
+ for (std::vector<std::string>::const_iterator i = fullDirList.begin(); i != fullDirList.end(); ++i)
+ {
+ try
+ {
+ InotifyWatch newWatch(*i, //dummy object: InotifyWatch may be destructed safely after Inotify::Add()
+ IN_DONT_FOLLOW | //don't follow symbolic links
+ IN_ONLYDIR | //watch directories only
+ IN_CLOSE_WRITE |
+ IN_CREATE |
+ IN_DELETE |
+ IN_DELETE_SELF |
+ IN_MODIFY |
+ IN_MOVE_SELF |
+ IN_MOVED_FROM |
+ IN_MOVED_TO );
+ notifications.Add(newWatch);
+ }
+ catch (const InotifyException& e)
+ {
+ const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + *i + wxT("\"");
+ throw FreeFileSync::FileError(errorMessage + wxT("\n\n") + e.GetMessage().c_str());
+ }
+ }
+
+ while (true)
+ {
+ notifications.WaitForEvents(); //called in non-blocking mode
+
+ if (notifications.GetEventCount() > 0)
+ return; //directory change detected
+
+ wxMilliSleep(RealtimeSync::UI_UPDATE_INTERVAL);
+ statusHandler->requestUiRefresh();
+ }
+ }
+ catch (const InotifyException& e)
+ {
+ throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + e.GetMessage().c_str());
+ }
+ catch (const std::exception& e)
+ {
+ throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + e.what());
+ }
+#endif
+}
diff --git a/RealtimeSync/watcher.h b/RealtimeSync/watcher.h
new file mode 100644
index 00000000..1655eebf
--- /dev/null
+++ b/RealtimeSync/watcher.h
@@ -0,0 +1,23 @@
+#ifndef WATCHER_H_INCLUDED
+#define WATCHER_H_INCLUDED
+
+#include "functions.h"
+#include <vector>
+#include "../shared/fileError.h"
+
+
+namespace RealtimeSync
+{
+ const int UI_UPDATE_INTERVAL = 100; //perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss
+
+ class WaitCallback
+ {
+ public:
+ virtual ~WaitCallback() {}
+ virtual void requestUiRefresh() = 0; //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh()
+ };
+
+ void waitForChanges(const std::vector<wxString>& dirNames, WaitCallback* statusHandler); //throw(FreeFileSync::FileError);
+}
+
+#endif // WATCHER_H_INCLUDED
diff --git a/RealtimeSync/xmlFreeFileSync.cpp b/RealtimeSync/xmlFreeFileSync.cpp
new file mode 100644
index 00000000..36f0e2f8
--- /dev/null
+++ b/RealtimeSync/xmlFreeFileSync.cpp
@@ -0,0 +1,68 @@
+#include "xmlFreeFileSync.h"
+#include "../shared/standardPaths.h"
+#include "../shared/globalFunctions.h"
+#include "../shared/zstring.h"
+#include "functions.h"
+#include "../shared/xmlBase.h"
+
+//include FreeFileSync xml headers
+#include "../library/processXml.h"
+
+
+#ifdef FFS_WIN
+class CmpNoCase
+{
+public:
+ bool operator()(const wxString& a, const wxString& b)
+ {
+ return FreeFileSync::compareStringsWin32(a.c_str(), b.c_str(), a.length(), b.length()) < 0;
+ }
+};
+#endif
+
+
+void RealtimeSync::readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config) //throw (xmlAccess::XmlError);
+{
+ if (xmlAccess::getXmlType(filename) != xmlAccess::XML_BATCH_CONFIG)
+ {
+ xmlAccess::readRealConfig(filename, config);
+ return;
+ }
+
+ //convert batch config to RealtimeSync config
+ xmlAccess::XmlBatchConfig batchCfg;
+ try
+ {
+ xmlAccess::readBatchConfig(filename, batchCfg); //throw (xmlAccess::XmlError);
+ }
+ catch (const xmlAccess::XmlError& e)
+ {
+ if (e.getSeverity() != xmlAccess::XmlError::WARNING) //ignore parsing errors
+ throw;
+ }
+
+#ifdef FFS_WIN
+ std::set<wxString, CmpNoCase> uniqueFolders;
+#elif defined FFS_LINUX
+ std::set<wxString> uniqueFolders;
+#endif
+
+ for (std::vector<FreeFileSync::FolderPair>::const_iterator i = batchCfg.directoryPairs.begin(); i != batchCfg.directoryPairs.end(); ++i)
+ {
+ uniqueFolders.insert(i->leftDirectory.c_str());
+ uniqueFolders.insert(i->rightDirectory.c_str());
+ }
+
+ config.directories.insert(config.directories.end(), uniqueFolders.begin(), uniqueFolders.end());
+
+ config.commandline = FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("FreeFileSync.exe ") +
+ wxT("\"") + filename + wxT("\"");
+}
+
+
+int RealtimeSync::getProgramLanguage()
+{
+ xmlAccess::XmlGlobalSettings settings;
+ xmlAccess::readGlobalSettings(settings);
+ return settings.programLanguage;
+}
diff --git a/RealtimeSync/xmlFreeFileSync.h b/RealtimeSync/xmlFreeFileSync.h
new file mode 100644
index 00000000..e4e0be76
--- /dev/null
+++ b/RealtimeSync/xmlFreeFileSync.h
@@ -0,0 +1,16 @@
+#ifndef XMLFREEFILESYNC_H_INCLUDED
+#define XMLFREEFILESYNC_H_INCLUDED
+
+#include "xmlProcessing.h"
+
+
+//reuse (some of) FreeFileSync's xml files
+
+namespace RealtimeSync
+{
+ void readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config); //throw (xmlAccess::XmlError);
+
+ int getProgramLanguage(); //throw (xmlAccess::XmlError);
+}
+
+#endif // XMLFREEFILESYNC_H_INCLUDED
diff --git a/RealtimeSync/xmlProcessing.cpp b/RealtimeSync/xmlProcessing.cpp
new file mode 100644
index 00000000..7b640455
--- /dev/null
+++ b/RealtimeSync/xmlProcessing.cpp
@@ -0,0 +1,86 @@
+#include "xmlProcessing.h"
+#include <wx/filefn.h>
+#include <wx/intl.h>
+
+
+class RtsXmlParser : public xmlAccess::XmlParser
+{
+public:
+ RtsXmlParser(const TiXmlElement* rootElement) : xmlAccess::XmlParser(rootElement) {}
+
+ void readXmlRealConfig(xmlAccess::XmlRealConfig& outputCfg);
+};
+
+
+
+void readXmlRealConfig(const TiXmlDocument& doc, xmlAccess::XmlRealConfig& outputCfg);
+bool writeXmRealSettings(const xmlAccess::XmlRealConfig& outputCfg, TiXmlDocument& doc);
+
+
+void xmlAccess::readRealConfig(const wxString& filename, XmlRealConfig& config)
+{
+ //load XML
+ if (!wxFileExists(filename))
+ throw XmlError(wxString(_("File does not exist:")) + wxT(" \"") + filename + wxT("\""));
+
+ TiXmlDocument doc;
+ if (!loadXmlDocument(filename, XML_REAL_CONFIG, doc))
+ throw XmlError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\""));
+
+ RtsXmlParser parser(doc.RootElement());
+ parser.readXmlRealConfig(config); //read GUI layout configuration
+
+ if (parser.errorsOccured())
+ throw XmlError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\"\n\n") +
+ parser.getErrorMessageFormatted(), XmlError::WARNING);
+}
+
+
+void xmlAccess::writeRealConfig(const XmlRealConfig& outputCfg, const wxString& filename)
+{
+ TiXmlDocument doc;
+ getDefaultXmlDocument(XML_REAL_CONFIG, doc);
+
+ //populate and write XML tree
+ if ( !writeXmRealSettings(outputCfg, doc) || //add GUI layout configuration settings
+ !saveXmlDocument(filename, doc)) //save XML
+ throw XmlError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\""));
+ return;
+}
+
+//--------------------------------------------------------------------------------
+
+
+void RtsXmlParser::readXmlRealConfig(xmlAccess::XmlRealConfig& outputCfg)
+{
+ //read directories for monitoring
+ const TiXmlElement* directoriesToWatch = TiXmlHandleConst(root).FirstChild("Directories").ToElement();
+
+ readXmlElementLogging("Folder", directoriesToWatch, outputCfg.directories);
+
+ //commandline to execute
+ readXmlElementLogging("Commandline", root, outputCfg.commandline);
+
+ //delay
+ readXmlElementLogging("Delay", root, outputCfg.delay);
+}
+
+
+bool writeXmRealSettings(const xmlAccess::XmlRealConfig& outputCfg, TiXmlDocument& doc)
+{
+ TiXmlElement* root = doc.RootElement();
+ if (!root) return false;
+
+ //directories to monitor
+ TiXmlElement* directoriesToWatch = new TiXmlElement("Directories");
+ root->LinkEndChild(directoriesToWatch);
+ xmlAccess::addXmlElement("Folder", outputCfg.directories, directoriesToWatch);
+
+ //commandline to execute
+ xmlAccess::addXmlElement("Commandline", outputCfg.commandline, root);
+
+ //delay
+ xmlAccess::addXmlElement("Delay", outputCfg.delay, root);
+
+ return true;
+}
diff --git a/RealtimeSync/xmlProcessing.h b/RealtimeSync/xmlProcessing.h
new file mode 100644
index 00000000..90842abf
--- /dev/null
+++ b/RealtimeSync/xmlProcessing.h
@@ -0,0 +1,23 @@
+#ifndef XMLPROCESSING_H_INCLUDED
+#define XMLPROCESSING_H_INCLUDED
+
+#include <vector>
+#include <wx/string.h>
+#include "../shared/xmlBase.h"
+
+
+namespace xmlAccess
+{
+ struct XmlRealConfig
+ {
+ XmlRealConfig() : delay(5) {}
+ std::vector<wxString> directories;
+ wxString commandline;
+ unsigned int delay;
+ };
+
+ void readRealConfig(const wxString& filename, XmlRealConfig& config); //throw (xmlAccess::XmlError);
+ void writeRealConfig(const XmlRealConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError);
+}
+
+#endif // XMLPROCESSING_H_INCLUDED
bgstack15