summaryrefslogtreecommitdiff
path: root/RealtimeSync
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:04:59 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:04:59 +0200
commitf570e2f2685aa43aa518c2f8578391c1847cddbe (patch)
treeb9376b3a7e807c5e0c4cf3d5615c14034d9675d6 /RealtimeSync
parent3.2 (diff)
downloadFreeFileSync-f570e2f2685aa43aa518c2f8578391c1847cddbe.tar.gz
FreeFileSync-f570e2f2685aa43aa518c2f8578391c1847cddbe.tar.bz2
FreeFileSync-f570e2f2685aa43aa518c2f8578391c1847cddbe.zip
3.3
Diffstat (limited to 'RealtimeSync')
-rw-r--r--RealtimeSync/RealtimeSync.cbp4
-rw-r--r--RealtimeSync/RealtimeSync.vcproj33
-rw-r--r--RealtimeSync/RealtimeSync.xpm312
-rw-r--r--RealtimeSync/application.cpp28
-rw-r--r--RealtimeSync/application.h4
-rw-r--r--RealtimeSync/functions.h2
-rw-r--r--RealtimeSync/guiGenerated.cpp38
-rw-r--r--RealtimeSync/guiGenerated.h9
-rw-r--r--RealtimeSync/mainDialog.cpp32
-rw-r--r--RealtimeSync/mainDialog.h6
-rw-r--r--RealtimeSync/resources.cpp27
-rw-r--r--RealtimeSync/resources.h4
-rw-r--r--RealtimeSync/trayMenu.cpp23
-rw-r--r--RealtimeSync/trayMenu.h12
-rw-r--r--RealtimeSync/watcher.cpp335
-rw-r--r--RealtimeSync/watcher.h16
-rw-r--r--RealtimeSync/xmlFreeFileSync.h4
-rw-r--r--RealtimeSync/xmlProcessing.h18
18 files changed, 472 insertions, 435 deletions
diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp
index d15a5ab2..76eccb5e 100644
--- a/RealtimeSync/RealtimeSync.cbp
+++ b/RealtimeSync/RealtimeSync.cbp
@@ -128,11 +128,15 @@
<Unit filename="..\shared\fileError.h" />
<Unit filename="..\shared\fileHandling.cpp" />
<Unit filename="..\shared\fileHandling.h" />
+ <Unit filename="..\shared\fileID.cpp" />
<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\longPathPrefix.cpp" />
+ <Unit filename="..\shared\longPathPrefix.h" />
+ <Unit filename="..\shared\recycler.cpp" />
<Unit filename="..\shared\shadow.cpp" />
<Unit filename="..\shared\standardPaths.cpp" />
<Unit filename="..\shared\standardPaths.h" />
diff --git a/RealtimeSync/RealtimeSync.vcproj b/RealtimeSync/RealtimeSync.vcproj
index f3501a17..ddf293ea 100644
--- a/RealtimeSync/RealtimeSync.vcproj
+++ b/RealtimeSync/RealtimeSync.vcproj
@@ -69,7 +69,7 @@
<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"
+ OutputFile="..\BUILD\$(ProjectName)_$(PlatformName).exe"
LinkIncremental="2"
AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets\lib\vc_lib"
GenerateManifest="true"
@@ -129,7 +129,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="&quot;D:\Programme\C++\wxWidgets-x64\include&quot;;&quot;D:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswud&quot;;..\shared\boost_1_x"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets-x64\include&quot;;&quot;C:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswud&quot;;..\shared\boost_1_x"
PreprocessorDefinitions="wxUSE_UNICODE;__WXMSW__;FFS_WIN;__WXDEBUG__;TIXML_USE_STL;ZSTRING_WIDE_CHAR"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -145,7 +145,7 @@
<Tool
Name="VCResourceCompilerTool"
Culture="0"
- AdditionalIncludeDirectories="D:\Programme\C++\wxWidgets-x64\include;D:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswud"
+ AdditionalIncludeDirectories="C:\Programme\C++\wxWidgets-x64\include;C:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswud"
/>
<Tool
Name="VCPreLinkEventTool"
@@ -153,9 +153,9 @@
<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"
+ OutputFile="..\BUILD\$(ProjectName)_$(PlatformName).exe"
LinkIncremental="2"
- AdditionalLibraryDirectories="D:\Programme\C++\wxWidgets-x64\lib\vc_lib"
+ AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets-x64\lib\vc_lib"
GenerateManifest="true"
GenerateDebugInformation="true"
SubSystem="2"
@@ -237,7 +237,7 @@
<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"
+ OutputFile="..\BUILD\$(ProjectName)_$(PlatformName).exe"
LinkIncremental="1"
AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets\lib\vc_lib"
GenerateDebugInformation="false"
@@ -298,12 +298,13 @@
Optimization="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
- AdditionalIncludeDirectories="&quot;D:\Programme\C++\wxWidgets-x64\include&quot;;&quot;D:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswu&quot;;..\shared\boost_1_x"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets-x64\include&quot;;&quot;C:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswu&quot;;..\shared\boost_1_x"
PreprocessorDefinitions="wxUSE_UNICODE;__WXMSW__;FFS_WIN;NDEBUG;TIXML_USE_STL;ZSTRING_WIDE_CHAR"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
+ SuppressStartupBanner="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4804"
/>
@@ -313,7 +314,7 @@
<Tool
Name="VCResourceCompilerTool"
Culture="1033"
- AdditionalIncludeDirectories="&quot;D:\Programme\C++\wxWidgets-x64\include&quot;;&quot;D:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswu&quot;"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets-x64\include&quot;;&quot;C:\Programme\C++\wxWidgets-x64\lib\vc_lib\mswu&quot;"
/>
<Tool
Name="VCPreLinkEventTool"
@@ -321,9 +322,9 @@
<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"
+ OutputFile="..\BUILD\$(ProjectName)_$(PlatformName).exe"
LinkIncremental="1"
- AdditionalLibraryDirectories="D:\Programme\C++\wxWidgets-x64\lib\vc_lib"
+ AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets-x64\lib\vc_lib"
GenerateDebugInformation="false"
SubSystem="2"
OptimizeReferences="2"
@@ -383,6 +384,10 @@
>
</File>
<File
+ RelativePath="..\shared\fileID.cpp"
+ >
+ </File>
+ <File
RelativePath="..\shared\fileTraverser.cpp"
>
</File>
@@ -403,6 +408,10 @@
>
</File>
<File
+ RelativePath="..\shared\longPathPrefix.cpp"
+ >
+ </File>
+ <File
RelativePath=".\mainDialog.cpp"
>
</File>
@@ -411,6 +420,10 @@
>
</File>
<File
+ RelativePath="..\shared\recycler.cpp"
+ >
+ </File>
+ <File
RelativePath=".\resources.cpp"
>
</File>
diff --git a/RealtimeSync/RealtimeSync.xpm b/RealtimeSync/RealtimeSync.xpm
deleted file mode 100644
index 557ef973..00000000
--- a/RealtimeSync/RealtimeSync.xpm
+++ /dev/null
@@ -1,312 +0,0 @@
-/* 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
index b974fb89..68cebae0 100644
--- a/RealtimeSync/application.cpp
+++ b/RealtimeSync/application.cpp
@@ -13,6 +13,7 @@
#include "../shared/localization.h"
#include "xmlFreeFileSync.h"
#include "../shared/standardPaths.h"
+#include <wx/file.h>
#ifdef FFS_LINUX
#include <gtk/gtk.h>
@@ -80,3 +81,30 @@ void Application::OnStartApplication(wxIdleEvent& event)
frame->SetIcon(*GlobalResources::getInstance().programIcon); //set application icon
frame->Show();
}
+
+
+bool Application::OnExceptionInMainLoop()
+{
+ throw; //just re-throw exception and avoid display of additional exception messagebox: it will be caught in OnRun()
+}
+
+
+int Application::OnRun()
+{
+ try
+ {
+ wxApp::OnRun();
+ }
+ catch (const std::exception& e) //catch all STL exceptions
+ {
+ //unfortunately it's not always possible to display a message box in this erroneous situation, however (non-stream) file output always works!
+ wxFile safeOutput(FreeFileSync::getLastErrorTxtFile(), wxFile::write);
+ safeOutput.Write(wxString::FromAscii(e.what()));
+
+ wxMessageBox(wxString::FromAscii(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR);
+ return -9;
+ }
+
+ return 0; //program's return value
+}
+
diff --git a/RealtimeSync/application.h b/RealtimeSync/application.h
index e7116156b..d95cb3b4 100644
--- a/RealtimeSync/application.h
+++ b/RealtimeSync/application.h
@@ -16,11 +16,13 @@ class Application : public wxApp
{
public:
virtual bool OnInit();
+ virtual int OnRun();
+ virtual bool OnExceptionInMainLoop();
private:
void OnStartApplication(wxIdleEvent& event);
- std::auto_ptr<wxHelpController> helpController; //global help controller
+ std::auto_ptr<wxHelpController> helpController; //global help controller
};
#endif // REALTIMESYNCAPP_H
diff --git a/RealtimeSync/functions.h b/RealtimeSync/functions.h
index 3d7d522f..0001a7ec 100644
--- a/RealtimeSync/functions.h
+++ b/RealtimeSync/functions.h
@@ -9,7 +9,7 @@ class wxDirPickerCtrl;
namespace RealtimeSync
{
- void setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker);
+void setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker);
}
#endif // FUNCTIONS_H_INCLUDED
diff --git a/RealtimeSync/guiGenerated.cpp b/RealtimeSync/guiGenerated.cpp
index 7e705927..aa4a8261 100644
--- a/RealtimeSync/guiGenerated.cpp
+++ b/RealtimeSync/guiGenerated.cpp
@@ -13,7 +13,7 @@
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 );
+ this->SetSizeHints( wxSize( 420,440 ), wxDefaultSize );
m_menubar1 = new wxMenuBar( 0 );
m_menuFile = new wxMenu();
@@ -56,9 +56,35 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
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 );
+ wxStaticBoxSizer* sbSizer41;
+ sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, wxEmptyString ), wxVERTICAL );
+
+ m_staticText2 = new wxStaticText( m_panelMain, wxID_ANY, _("Usage:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText2->Wrap( -1 );
+ m_staticText2->SetFont( wxFont( 10, 74, 90, 90, true, wxT("Tahoma") ) );
+
+ sbSizer41->Add( m_staticText2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+
+ m_staticText3 = new wxStaticText( m_panelMain, wxID_ANY, _("1. Select directories to monitor."), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText3->Wrap( -1 );
+ sbSizer41->Add( m_staticText3, 0, wxLEFT, 10 );
+
+ m_staticText4 = new wxStaticText( m_panelMain, wxID_ANY, _("2. Enter a command line."), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText4->Wrap( -1 );
+ sbSizer41->Add( m_staticText4, 0, wxLEFT, 10 );
+
+ m_staticText5 = new wxStaticText( m_panelMain, wxID_ANY, _("3. Press 'Start'."), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText5->Wrap( -1 );
+ sbSizer41->Add( m_staticText5, 0, wxLEFT, 10 );
+
+ m_staticline3 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ sbSizer41->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 );
+
+ m_staticText21 = new wxStaticText( m_panelMain, wxID_ANY, _("The command line is executed each time:\n- Files within these directories (or subdirectories) are modified\n- The corresponding drive letter becomes available (USB-insert)"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText21->Wrap( -1 );
+ sbSizer41->Add( m_staticText21, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 );
+
+ bSizer1->Add( sbSizer41, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 40 );
m_staticline2 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer1->Add( m_staticline2, 0, wxTOP|wxBOTTOM|wxEXPAND, 10 );
@@ -119,7 +145,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
bSizer1->Add( bSizer8, 1, wxEXPAND, 5 );
wxStaticBoxSizer* sbSizer3;
- sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Commandline") ), wxVERTICAL );
+ sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Command line") ), wxVERTICAL );
m_textCtrlCommand = new wxTextCtrl( m_panelMain, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
sbSizer3->Add( m_textCtrlCommand, 0, wxEXPAND|wxBOTTOM, 5 );
@@ -133,7 +159,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
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 detection of changes and execution of commandline in seconds") );
+ m_spinCtrlDelay->SetToolTip( _("Delay between detection of changes and execution of command line in seconds") );
sbSizer4->Add( m_spinCtrlDelay, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 );
diff --git a/RealtimeSync/guiGenerated.h b/RealtimeSync/guiGenerated.h
index 91669af8..7be541d4 100644
--- a/RealtimeSync/guiGenerated.h
+++ b/RealtimeSync/guiGenerated.h
@@ -23,14 +23,14 @@ class wxButtonWithImage;
#include <wx/settings.h>
#include <wx/stattext.h>
#include <wx/statline.h>
+#include <wx/sizer.h>
+#include <wx/statbox.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>
@@ -52,6 +52,11 @@ class MainDlgGenerated : public wxFrame
wxPanel* m_panelMain;
wxStaticText* m_staticText2;
+ wxStaticText* m_staticText3;
+ wxStaticText* m_staticText4;
+ wxStaticText* m_staticText5;
+ wxStaticLine* m_staticline3;
+ wxStaticText* m_staticText21;
wxStaticLine* m_staticline2;
wxPanel* m_panelMainFolder;
wxBitmapButton* m_bpButtonAddFolder;
diff --git a/RealtimeSync/mainDialog.cpp b/RealtimeSync/mainDialog.cpp
index 8d9c7d7a..81af1ce0 100644
--- a/RealtimeSync/mainDialog.cpp
+++ b/RealtimeSync/mainDialog.cpp
@@ -2,7 +2,6 @@
#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"
@@ -13,6 +12,8 @@
#include "xmlFreeFileSync.h"
#include "../shared/systemConstants.h"
#include "../shared/stringConv.h"
+#include "../shared/staticAssert.h"
+#include "../shared/buildInfo.h"
using namespace FreeFileSync;
@@ -20,17 +21,17 @@ using namespace FreeFileSync;
MainDialog::MainDialog(wxDialog *dlg,
const wxString& cfgFilename,
wxHelpController& helpController)
- : MainDlgGenerated(dlg),
- helpController_(helpController)
+ : MainDlgGenerated(dlg),
+ helpController_(helpController)
{
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_bpButtonAddFolder->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("addFolderPair")));
+ m_bpButtonRemoveTopFolder->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("removeFolderPair")));
+ m_buttonStart->setBitmapFront(GlobalResources::getInstance().getImageByName(wxT("startRed")));
m_buttonStart->SetFocus();
//register key event
@@ -126,11 +127,11 @@ const wxString& MainDialog::lastConfigFileName()
void MainDialog::OnShowHelp(wxCommandEvent& event)
{
- #ifdef FFS_WIN
+#ifdef FFS_WIN
helpController_.DisplaySection(wxT("html\\advanced\\RealtimeSync.html"));
- #elif defined FFS_LINUX
+#elif defined FFS_LINUX
helpController_.DisplaySection(wxT("html/advanced/RealtimeSync.html"));
- #endif
+#endif
}
@@ -139,11 +140,18 @@ void MainDialog::OnMenuAbout(wxCommandEvent& event)
//build information
wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__;
#if wxUSE_UNICODE
- build += wxT(" - Unicode)");
+ build += wxT(" - Unicode");
#else
- build += wxT(" - ANSI)");
+ build += wxT(" - ANSI");
#endif //wxUSE_UNICODE
+ //compile time info about 32/64-bit build
+ if (Utility::is64BitBuild)
+ build += wxT(" x64)");
+ else
+ build += wxT(" x86)");
+ assert_static(Utility::is32BitBuild || Utility::is64BitBuild);
+
wxMessageDialog* aboutDlg = new wxMessageDialog(this, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK);
aboutDlg->ShowModal();
}
@@ -356,7 +364,7 @@ void MainDialog::addFolder(const std::vector<wxString>& newFolders, bool addFron
{
//add new folder pair
FolderPanel* newFolder = new FolderPanel(m_scrolledWinFolders);
- newFolder->m_bpButtonRemoveFolder->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
+ newFolder->m_bpButtonRemoveFolder->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("removeFolderPair")));
//get size of scrolled window
folderHeight = newFolder->GetSize().GetHeight();
diff --git a/RealtimeSync/mainDialog.h b/RealtimeSync/mainDialog.h
index 8447d269..8a5e87bf 100644
--- a/RealtimeSync/mainDialog.h
+++ b/RealtimeSync/mainDialog.h
@@ -16,7 +16,7 @@
namespace xmlAccess
{
- struct XmlRealConfig;
+struct XmlRealConfig;
}
@@ -24,8 +24,8 @@ class FolderPanel : public FolderGenerated
{
public:
FolderPanel(wxWindow* parent) :
- FolderGenerated(parent),
- dragDropOnFolder(new FreeFileSync::DragDropOnDlg(this, m_dirPicker, m_txtCtrlDirectory)) {}
+ FolderGenerated(parent),
+ dragDropOnFolder(new FreeFileSync::DragDropOnDlg(this, m_dirPicker, m_txtCtrlDirectory)) {}
private:
//support for drag and drop
diff --git a/RealtimeSync/resources.cpp b/RealtimeSync/resources.cpp
index fe2a5ced..eeb89563 100644
--- a/RealtimeSync/resources.cpp
+++ b/RealtimeSync/resources.cpp
@@ -19,12 +19,7 @@ const GlobalResources& GlobalResources::getInstance()
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);
+ programIcon = new wxIcon(wxNullIcon);
}
@@ -49,7 +44,6 @@ void GlobalResources::load() const
wxZipInputStream resourceFile(input);
- std::map<wxString, wxBitmap*>::iterator bmp;
while (true)
{
std::auto_ptr<wxZipEntry> entry(resourceFile.GetNextEntry());
@@ -58,24 +52,31 @@ void GlobalResources::load() const
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));
+ //generic image loading
+ if (name.EndsWith(wxT(".png")))
+ {
+ if (bitmapResource.find(name) == bitmapResource.end()) //avoid duplicate entry: prevent memory leak!
+ bitmapResource[name] = new wxBitmap(wxImage(resourceFile, wxBITMAP_TYPE_PNG));
+ }
}
}
#ifdef FFS_WIN
+ //for compatibility it seems we need to stick with a "real" icon
*programIcon = wxIcon(wxT("A_PROGRAM_ICON"));
#else
-#include "RealtimeSync.xpm"
- *programIcon = wxIcon(RealtimeSync_xpm);
+ //use big logo bitmap for better quality
+ programIcon->CopyFromBitmap(getImageByName(wxT("RealtimeSync.png")));
#endif
}
const wxBitmap& GlobalResources::getImageByName(const wxString& imageName) const
{
- std::map<wxString, wxBitmap*>::const_iterator bmp = bitmapResource.find(imageName);
+ const std::map<wxString, wxBitmap*>::const_iterator bmp = imageName.Find(wxChar('.')) == wxNOT_FOUND ? //assume .png ending if nothing else specified
+ bitmapResource.find(imageName + wxT(".png")) :
+ bitmapResource.find(imageName);
+
if (bmp != bitmapResource.end())
return *bmp->second;
else
diff --git a/RealtimeSync/resources.h b/RealtimeSync/resources.h
index 3a0cde7b..6a6cd976 100644
--- a/RealtimeSync/resources.h
+++ b/RealtimeSync/resources.h
@@ -14,10 +14,6 @@ public:
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!
diff --git a/RealtimeSync/trayMenu.cpp b/RealtimeSync/trayMenu.cpp
index 5d9d2430..01bcda48 100644
--- a/RealtimeSync/trayMenu.cpp
+++ b/RealtimeSync/trayMenu.cpp
@@ -10,6 +10,8 @@
#include <wx/timer.h>
#include <wx/utils.h>
#include <wx/log.h>
+#include "../shared/staticAssert.h"
+#include "../shared/buildInfo.h"
class RtsTrayIcon;
@@ -42,9 +44,9 @@ class RtsTrayIcon : public wxTaskBarIcon
{
public:
RtsTrayIcon(WaitCallbackImpl* callback) :
- m_callback(callback)
+ m_callback(callback)
{
- wxTaskBarIcon::SetIcon(*GlobalResources::getInstance().programIcon, wxT("RealtimeSync"));
+ wxTaskBarIcon::SetIcon(*GlobalResources::getInstance().programIcon, wxString(wxT("RealtimeSync")) + wxT(" - ") + _("Monitoring active..."));
//register double-click
Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(RtsTrayIcon::resumeToMain), NULL, this);
@@ -89,11 +91,18 @@ private:
//build information
wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__;
#if wxUSE_UNICODE
- build += wxT(" - Unicode)");
+ build += wxT(" - Unicode");
#else
- build += wxT(" - ANSI)");
+ build += wxT(" - ANSI");
#endif //wxUSE_UNICODE
+ //compile time info about 32/64-bit build
+ if (Utility::is64BitBuild)
+ build += wxT(" x64)");
+ else
+ build += wxT(" x86)");
+ assert_static(Utility::is32BitBuild || Utility::is64BitBuild);
+
wxMessageDialog* aboutDlg = new wxMessageDialog(NULL, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK);
aboutDlg->ShowModal();
aboutDlg->Destroy();
@@ -145,8 +154,8 @@ private:
WaitCallbackImpl::WaitCallbackImpl() :
- m_abortRequested(false),
- m_resumeRequested(false)
+ m_abortRequested(false),
+ m_resumeRequested(false)
{
trayMenu.reset(new RtsTrayIcon(this));
}
@@ -172,7 +181,7 @@ RealtimeSync::MonitorResponse RealtimeSync::startDirectoryMonitor(const xmlAcces
WaitCallbackImpl callback;
if (config.commandline.empty())
- throw FreeFileSync::FileError(_("Commandline is empty!"));
+ throw FreeFileSync::FileError(_("Command line is empty!"));
long lastExec = 0;
while (true)
diff --git a/RealtimeSync/trayMenu.h b/RealtimeSync/trayMenu.h
index 04b07f8a..99f2f90a 100644
--- a/RealtimeSync/trayMenu.h
+++ b/RealtimeSync/trayMenu.h
@@ -7,13 +7,13 @@
namespace RealtimeSync
{
- enum MonitorResponse
- {
- RESUME,
- QUIT
- };
+enum MonitorResponse
+{
+ RESUME,
+ QUIT
+};
- MonitorResponse startDirectoryMonitor(const xmlAccess::XmlRealConfig& config);
+MonitorResponse startDirectoryMonitor(const xmlAccess::XmlRealConfig& config);
}
diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp
index 97471397..67dae521 100644
--- a/RealtimeSync/watcher.cpp
+++ b/RealtimeSync/watcher.cpp
@@ -5,9 +5,15 @@
#include <wx/filefn.h>
#include "../shared/fileHandling.h"
#include "../shared/stringConv.h"
+#include <stdexcept>
+#include <map>
+#include <wx/timer.h>
#ifdef FFS_WIN
+//#include "../shared/fileId.h"
+//#include "Dbt.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include "../shared/longPathPrefix.h"
#elif defined FFS_LINUX
#include <wx/timer.h>
@@ -20,6 +26,191 @@ using namespace FreeFileSync;
#ifdef FFS_WIN
+/*
+template <class T> //have a disctinct static variable per class!
+class InstanceCounter //exception safety!!!! use RAII for counter inc/dec!
+{
+public:
+ InstanceCounter()
+ {
+ ++instanceCount;
+ //we're programming on global variables: only one instance of NotifyDeviceArrival allowed at a time!
+ if (instanceCount > 1)
+ throw std::logic_error("Only one instance of NotifyDeviceArrival allowed!");
+ }
+ ~InstanceCounter()
+ {
+ --instanceCount;
+ }
+private:
+ static size_t instanceCount; //this class needs to be a singleton but with variable lifetime! => count instances to check consistency
+};
+template <class T> //we need a disctinct static variable per class!
+size_t InstanceCounter<T>::instanceCount = 0;
+
+
+std::set<Zstring> driveNamesArrived; //letters of newly arrived drive names
+
+
+//convert bitmask into "real" drive-letter
+void notifyDriveFromMask (ULONG unitmask)
+{
+ for (wchar_t i = 0; i < 26; ++i)
+ {
+ if (unitmask & 0x1)
+ {
+ Zstring newDrivePath;
+ newDrivePath += DefaultChar('A') + i;
+ newDrivePath += DefaultStr(":\\");
+ driveNamesArrived.insert(newDrivePath);
+ return;
+ }
+ unitmask = unitmask >> 1;
+ }
+}
+
+
+LRESULT CALLBACK MainWndProc(
+ HWND hwnd, // handle to window
+ UINT uMsg, // message identifier
+ WPARAM wParam, // first message parameter
+ LPARAM lParam) // second message parameter
+{
+
+ //detect device arrival: http://msdn.microsoft.com/en-us/library/aa363215(VS.85).aspx
+ if (uMsg == WM_DEVICECHANGE)
+ {
+ if (wParam == DBT_DEVICEARRIVAL)
+ {
+ PDEV_BROADCAST_HDR lpdb = reinterpret_cast<PDEV_BROADCAST_HDR>(lParam);
+ if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
+ {
+ PDEV_BROADCAST_VOLUME lpdbv = reinterpret_cast<PDEV_BROADCAST_VOLUME>(lpdb);
+ //warning: lpdbv->dbcv_flags is 0 for USB-sticks!
+
+ //insert drive name notification into global variable:
+ notifyDriveFromMask(lpdbv->dbcv_unitmask);
+ }
+ }
+ }
+ //default
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+
+class NotifyDeviceArrival //e.g. insertion of USB-Stick
+{
+public:
+ NotifyDeviceArrival() :
+ parentInstance(NULL),
+ registeredClass(NULL),
+ windowHandle(NULL)
+ {
+ //get program's module handle
+ parentInstance = GetModuleHandle(NULL);
+ if (parentInstance == NULL)
+ throw FreeFileSync::FileError(wxString(("Could not start monitoring for volume arrival:")) + wxT("\n\n") +
+ FreeFileSync::getLastErrorFormatted()+ wxT(" (GetModuleHandle)"));
+
+ //register the main window class
+ WNDCLASS wc;
+ wc.style = 0;
+ wc.lpfnWndProc = MainWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = parentInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = wxT("DeviceArrivalWatcher");
+
+ registeredClass =:: RegisterClass(&wc);
+ if (registeredClass == 0)
+ throw FreeFileSync::FileError(wxString(("Could not start monitoring for volume arrival:")) + wxT("\n\n") +
+ FreeFileSync::getLastErrorFormatted()+ wxT(" (RegisterClass)"));
+
+ //create dummy-window
+ windowHandle = ::CreateWindow(
+ reinterpret_cast<LPCTSTR>(registeredClass), //LPCTSTR lpClassName OR ATOM in low-order word!
+ 0, //LPCTSTR lpWindowName,
+ 0, //DWORD dwStyle,
+ 0, //int x,
+ 0, //int y,
+ 0, //int nWidth,
+ 0, //int nHeight,
+ 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)!
+ NULL, //HMENU hMenu,
+ parentInstance, //HINSTANCE hInstance,
+ NULL); //LPVOID lpParam
+ if (windowHandle == NULL)
+ throw FreeFileSync::FileError(wxString( ("Could not start monitoring for volume arrival:")) + wxT("\n\n") +
+ FreeFileSync::getLastErrorFormatted() + wxT(" (CreateWindow)"));
+
+ //clear global variable
+ driveNamesArrived.clear();
+ }
+
+ ~NotifyDeviceArrival()
+ {
+ //clean-up in reverse order
+ if (windowHandle != NULL)
+ ::DestroyWindow(windowHandle);
+
+ if (registeredClass != 0)
+ ::UnregisterClass(reinterpret_cast<LPCTSTR>(registeredClass), //LPCTSTR lpClassName OR ATOM in low-order word!
+ parentInstance); //HINSTANCE hInstance
+ }
+
+
+ //test if one of the notifications matches one of the directory paths specified
+ bool notificationsFound(const std::vector<Zstring>& dirList) const
+ {
+ //do NOT rely on string parsing! use (volume directory) file ids!
+ std::set<Utility::FileID> notifiedIds;
+ for (std::set<Zstring>::const_iterator j = driveNamesArrived.begin(); j != driveNamesArrived.end(); ++j)
+ {
+ const Utility::FileID notifiedVolId = Utility::retrieveFileID(*j);
+ if (notifiedVolId != Utility::FileID())
+ notifiedIds.insert(notifiedVolId);
+ }
+ //clear global variable
+ driveNamesArrived.clear();
+
+ if (!notifiedIds.empty()) //minor optimization
+ {
+ for (std::vector<Zstring>::const_iterator i = dirList.begin(); i != dirList.end(); ++i)
+ {
+ //retrieve volume name
+ wchar_t volumeNameRaw[1000];
+ if (::GetVolumePathName(i->c_str(), //__in LPCTSTR lpszFileName,
+ volumeNameRaw, //__out LPTSTR lpszVolumePathName,
+ 1000)) //__in DWORD cchBufferLength
+ {
+ const Utility::FileID monitoredId = Utility::retrieveFileID(volumeNameRaw);
+ if (monitoredId != Utility::FileID())
+ {
+ if (notifiedIds.find(monitoredId) != notifiedIds.end())
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+private:
+ HINSTANCE parentInstance;
+ ATOM registeredClass;
+ HWND windowHandle;
+
+ //we're programming on global variables: only one instance of NotifyDeviceArrival allowed at a time!
+ InstanceCounter<NotifyDeviceArrival> dummy; //exception safety!!!! use RAII for counter inc/dec!
+};
+*/
+
+//--------------------------------------------------------------------------------------------------------------
class ChangeNotifications
{
public:
@@ -75,11 +266,53 @@ private:
#endif
+class NotifyDirectoryArrival //detect changes to directory availability
+{
+public:
+ //initialization
+ void addForMonitoring(const Zstring& dirName, bool isExisting) //dir-existence already checked by calling method, avoid double-checking -> consistency!
+ {
+ availablility[dirName] = isExisting;
+ }
+
+ //detection
+ bool changeDetected() //polling explicitly allowed!
+ {
+ const int UPDATE_INTERVAL = 1000; //1 second interval
+
+ static wxLongLong lastExec = 0;
+ const wxLongLong newExec = wxGetLocalTimeMillis();
+
+ if (newExec - lastExec >= UPDATE_INTERVAL)
+ {
+ lastExec = newExec;
+
+ for (std::map<Zstring, bool>::iterator i = availablility.begin(); i != availablility.end(); ++i)
+ if (FreeFileSync::dirExists(i->first) != i->second) //change in availability
+ {
+ if (i->second) //directory doesn't exist anymore: no reason to trigger the commandline! (sometimes triggered by ChangeNotifications anyway...)
+ i->second = false; //update value, so that dir-arrival will be detected next time
+ else //directory arrival: trigger commandline!
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+private:
+ std::map<Zstring, bool> availablility; //save avail. status for each directory
+};
+
+
void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCallback* statusHandler)
{
if (dirNames.empty()) //pathological case, but check is needed later
return;
+ //new: support for monitoring newly connected directories volumes (e.g.: USB-sticks)
+ NotifyDirectoryArrival monitorAvailability;
+
#ifdef FFS_WIN
ChangeNotifications notifications;
@@ -88,47 +321,58 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal
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("\"") + zToWx(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)
+ throw FreeFileSync::FileError(_("At least one directory input field is empty."));
+
+ const bool isExisting = FreeFileSync::dirExists(formattedDir);
+ if (isExisting)
{
- const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + *i + wxT("\"");
- throw FreeFileSync::FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+ const HANDLE rv = ::FindFirstChangeNotification(
+ FreeFileSync::applyLongPathPrefix(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);
}
+ //else: we silently ignore this error: it may be that the directory becomes available later, e.g. if it is a USB-stick
- notifications.addHandle(rv);
+ monitorAvailability.addForMonitoring(formattedDir, isExisting); //all directories (including not yet existing) are relevant
}
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();
+ //check for changes within directories:
+ if (notifications.getSize() > 0)
+ {
+ 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)
+ }
+
+ if (monitorAvailability.changeDetected()) //check for newly arrived devices:
+ return;
+
+ statusHandler->requestUiRefresh();
}
#elif defined FFS_LINUX
- std::vector<std::string> fullDirList;
+ std::vector<std::string> fullDirList; //including subdirectories!
//add all subdirectories
for (std::vector<wxString>::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i)
@@ -136,17 +380,19 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal
const Zstring formattedDir = FreeFileSync::getFormattedDirectoryName(wxToZ(*i));
if (formattedDir.empty())
- throw FreeFileSync::FileError(_("Please fill all empty directory fields."));
+ throw FreeFileSync::FileError(_("At least one directory input field is empty."));
- else if (!FreeFileSync::dirExists(formattedDir))
- throw FreeFileSync::FileError(wxString(_("Directory does not exist:")) + wxT("\n") +
- wxT("\"") + zToWx(formattedDir) + wxT("\"") + wxT("\n\n") +
- FreeFileSync::getLastErrorFormatted());
+ const bool isExisting = FreeFileSync::dirExists(formattedDir);
+ if (isExisting)
+ {
+ 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)
+ }
+ //else: we silently ignore this error: it may be that the directory becomes available later, e.g. if it is a USB-stick
- 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)
+ monitorAvailability.addForMonitoring(formattedDir, isExisting); //all directories (including not yet existing) are relevant
}
try
@@ -178,6 +424,7 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal
}
}
+
while (true)
{
notifications.WaitForEvents(); //called in non-blocking mode
@@ -185,6 +432,9 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal
if (notifications.GetEventCount() > 0)
return; //directory change detected
+ if (monitorAvailability.changeDetected()) //check for newly arrived devices:
+ return;
+
wxMilliSleep(RealtimeSync::UI_UPDATE_INTERVAL);
statusHandler->requestUiRefresh();
}
@@ -199,3 +449,10 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal
}
#endif
}
+
+
+
+
+
+
+
diff --git a/RealtimeSync/watcher.h b/RealtimeSync/watcher.h
index 1655eebf..2f3990c2 100644
--- a/RealtimeSync/watcher.h
+++ b/RealtimeSync/watcher.h
@@ -8,16 +8,16 @@
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
+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()
- };
+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);
+void waitForChanges(const std::vector<wxString>& dirNames, WaitCallback* statusHandler); //throw(FreeFileSync::FileError);
}
#endif // WATCHER_H_INCLUDED
diff --git a/RealtimeSync/xmlFreeFileSync.h b/RealtimeSync/xmlFreeFileSync.h
index 8de9af08..55687d93 100644
--- a/RealtimeSync/xmlFreeFileSync.h
+++ b/RealtimeSync/xmlFreeFileSync.h
@@ -8,9 +8,9 @@
namespace RealtimeSync
{
- void readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config); //throw (xmlAccess::XmlError);
+void readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config); //throw (xmlAccess::XmlError);
- int getProgramLanguage();
+int getProgramLanguage();
}
#endif // XMLFREEFILESYNC_H_INCLUDED
diff --git a/RealtimeSync/xmlProcessing.h b/RealtimeSync/xmlProcessing.h
index 90842abf..b8207973 100644
--- a/RealtimeSync/xmlProcessing.h
+++ b/RealtimeSync/xmlProcessing.h
@@ -8,16 +8,16 @@
namespace xmlAccess
{
- struct XmlRealConfig
- {
- XmlRealConfig() : delay(5) {}
- std::vector<wxString> directories;
- wxString commandline;
- unsigned int delay;
- };
+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);
+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