summaryrefslogtreecommitdiff
path: root/RealtimeSync
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:19:49 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:19:49 +0200
commitc8e0e909b4a8d18319fc65434a10dc446434817c (patch)
treeeee91e7d2ce229dd043811eae8f1e2bd78061916 /RealtimeSync
parent5.2 (diff)
downloadFreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.tar.gz
FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.tar.bz2
FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.zip
5.3
Diffstat (limited to 'RealtimeSync')
-rw-r--r--RealtimeSync/RealtimeSync.cbp2
-rw-r--r--RealtimeSync/RealtimeSync.vcxproj59
-rw-r--r--RealtimeSync/application.cpp24
-rw-r--r--RealtimeSync/gui_generated.cpp66
-rw-r--r--RealtimeSync/gui_generated.h30
-rw-r--r--RealtimeSync/main_dlg.cpp109
-rw-r--r--RealtimeSync/main_dlg.h22
-rw-r--r--RealtimeSync/resources.cpp12
-rw-r--r--RealtimeSync/tray_menu.cpp479
-rw-r--r--RealtimeSync/tray_menu.h9
-rw-r--r--RealtimeSync/watcher.cpp138
-rw-r--r--RealtimeSync/watcher.h16
-rw-r--r--RealtimeSync/xml_ffs.cpp6
-rw-r--r--RealtimeSync/xml_ffs.h3
-rw-r--r--RealtimeSync/xml_proc.cpp16
-rw-r--r--RealtimeSync/xml_proc.h5
16 files changed, 550 insertions, 446 deletions
diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp
index e1b46812..1a9469a8 100644
--- a/RealtimeSync/RealtimeSync.cbp
+++ b/RealtimeSync/RealtimeSync.cbp
@@ -81,7 +81,7 @@
<Add option="-DWXINTL_NO_GETTEXT_MACRO" />
<Add directory="C:\Programme\C++\wxWidgets\include" />
<Add directory="C:\Program Files\C++\Boost" />
- <Add directory="..\." />
+ <Add directory=".." />
</Compiler>
<ResourceCompiler>
<Add directory="C:\Programme\C++\wxWidgets\include" />
diff --git a/RealtimeSync/RealtimeSync.vcxproj b/RealtimeSync/RealtimeSync.vcxproj
index f115bac4..8a062159 100644
--- a/RealtimeSync/RealtimeSync.vcxproj
+++ b/RealtimeSync/RealtimeSync.vcxproj
@@ -49,7 +49,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>Windows7.1SDK</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -71,15 +71,15 @@
<LinkIncremental>true</LinkIncremental>
<OutDir>..\BUILD\Bin\</OutDir>
<IntDir>..\OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir>
- <TargetName>$(ProjectName)_$(PlatformName)</TargetName>
<GenerateManifest>false</GenerateManifest>
+ <TargetName>$(ProjectName)_$(PlatformName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\BUILD\Bin\</OutDir>
<IntDir>..\OBJ\$(ProjectName)_$(Configuration)_$(PlatformName)_VCPP\</IntDir>
- <TargetName>$(ProjectName)_$(PlatformName)</TargetName>
<GenerateManifest>false</GenerateManifest>
+ <TargetName>$(ProjectName)_$(PlatformName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -101,24 +101,21 @@
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;WXUSINGDLL</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..;C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_dll\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_dll\mswud;C:\Program Files\C++\Boost;..</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>wx+/pch.h</PrecompiledHeaderFile>
- <DisableSpecificWarnings>4100;4996;4267;4512</DisableSpecificWarnings>
- <MultiProcessorCompilation>false</MultiProcessorCompilation>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
+ <DisableSpecificWarnings>4100;4512</DisableSpecificWarnings>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
<PrecompiledHeaderOutputFile>$(IntDir)pch.obj</PrecompiledHeaderOutputFile>
<ForcedIncludeFiles>zen/warn_static.h;wx+/pch.h</ForcedIncludeFiles>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>wxmsw28ud_adv.lib;wxmsw28ud_core.lib;wxbase28ud.lib;wxpngd.lib;wxzlibd.lib;wxbase28ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets\lib\vc_dll;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
- <LinkStatus>
- </LinkStatus>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include</AdditionalIncludeDirectories>
@@ -131,20 +128,19 @@
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;__WXDEBUG__;WXUSINGDLL</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..;C:\Program Files\C++\wxWidgets-x64-VC11\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_dll\mswud;C:\Program Files\C++\Boost</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-x64-VC11\include;C:\Program Files\C++\wxWidgets-x64-VC11\lib\vc_dll\mswud;C:\Program Files\C++\Boost;..</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>wx+/pch.h</PrecompiledHeaderFile>
- <DisableSpecificWarnings>4100;4996;4267;4512</DisableSpecificWarnings>
- <MultiProcessorCompilation>false</MultiProcessorCompilation>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
+ <DisableSpecificWarnings>4100;4512</DisableSpecificWarnings>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
<PrecompiledHeaderOutputFile>$(IntDir)pch.obj</PrecompiledHeaderOutputFile>
<ForcedIncludeFiles>zen/warn_static.h;wx+/pch.h</ForcedIncludeFiles>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<SuppressStartupBanner>true</SuppressStartupBanner>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>wxmsw28ud_adv.lib;wxmsw28ud_core.lib;wxbase28ud.lib;wxpngd.lib;wxzlibd.lib;wxbase28ud_net.lib;comctl32.lib;ws2_32.lib;Rpcrt4.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64-VC11\lib\vc_dll;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories>
@@ -162,14 +158,12 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..;C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include;C:\Program Files\C++\wxWidgets\lib\vc_lib\mswu;C:\Program Files\C++\Boost;..</AdditionalIncludeDirectories>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <DisableSpecificWarnings>4100;4996;4267;4512</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4100;4512</DisableSpecificWarnings>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
<ForcedIncludeFiles>zen/warn_static.h</ForcedIncludeFiles>
</ClCompile>
<Link>
@@ -177,19 +171,13 @@
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalDependencies>wxbase28u.lib;wxmsw28u_adv.lib;wxmsw28u_core.lib;wxpng.lib;wxzlib.lib;wxbase28u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets\lib\vc_lib;C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
- <LinkStatus>
- </LinkStatus>
- <Profile>true</Profile>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);</PreprocessorDefinitions>
- <Culture>
- </Culture>
</ResourceCompile>
<PostBuildEvent>
<Command>"C:\Program Files\C++\CodeSigning\SignCode.cmd" "$(TargetPath)"</Command>
@@ -201,15 +189,12 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;ZEN_PLATFORM_WINDOWS;wxUSE_UNICODE;__WXMSW__;FFS_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..;C:\Program Files\C++\wxWidgets-x64-VC11\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswu;C:\Program Files\C++\Boost</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-x64\include;C:\Program Files\C++\wxWidgets-x64\lib\vc_lib\mswu;C:\Program Files\C++\Boost;..</AdditionalIncludeDirectories>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
- <DisableSpecificWarnings>4100;4996;4267;4512</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4100;4512</DisableSpecificWarnings>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<ForcedIncludeFiles>zen/warn_static.h</ForcedIncludeFiles>
</ClCompile>
<Link>
@@ -217,19 +202,13 @@
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalDependencies>wxmsw28u_adv.lib;wxmsw28u_core.lib;wxbase28u.lib;wxpng.lib;wxzlib.lib;wxbase28u_net.lib;comctl32.lib;ws2_32.lib;winmm.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64-VC11\lib\vc_lib;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories>
- <LinkStatus>
- </LinkStatus>
- <Profile>true</Profile>
+ <AdditionalLibraryDirectories>C:\Program Files\C++\wxWidgets-x64\lib\vc_lib;C:\Program Files\C++\Boost\stage64\lib</AdditionalLibraryDirectories>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>C:\Program Files\C++\wxWidgets-x64-VC11\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);WX_CPU_AMD64</PreprocessorDefinitions>
- <Culture>
- </Culture>
</ResourceCompile>
<PostBuildEvent>
<Command>"C:\Program Files\C++\CodeSigning\SignCode.cmd" "$(TargetPath)"</Command>
@@ -257,7 +236,6 @@
<ClCompile Include="application.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">wx+/pch.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="gui_generated.cpp" />
<ClCompile Include="main_dlg.cpp" />
@@ -271,8 +249,9 @@
<ResourceCompile Include="resource.rc" />
</ItemGroup>
<ItemGroup>
- <None Include="ClassDiagram.cd" />
- <None Include="WxWizDialog.fbp" />
+ <None Include="WxWizFrame.fbp">
+ <SubType>Designer</SubType>
+ </None>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/RealtimeSync/application.cpp b/RealtimeSync/application.cpp
index ead65eaa..4c477ce0 100644
--- a/RealtimeSync/application.cpp
+++ b/RealtimeSync/application.cpp
@@ -67,12 +67,12 @@ void Application::OnStartApplication(wxIdleEvent& event)
if (!fileExists(filename)) //be a little tolerant
{
if (fileExists(filename + Zstr(".ffs_real")))
- filename = filename + Zstr(".ffs_real");
+ filename += Zstr(".ffs_real");
else if (fileExists(filename + Zstr(".ffs_batch")))
- filename = filename + Zstr(".ffs_batch");
+ filename += Zstr(".ffs_batch");
else
{
- wxMessageBox(wxString(_("File does not exist:")) + wxT(" \"") + toWx(filename) + wxT("\""), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(replaceCpy(_("Cannot find file %x."), L"%x", fmtFileName(filename)), _("Error"), wxOK | wxICON_ERROR);
return;
}
}
@@ -103,11 +103,21 @@ int Application::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(toWx(zen::getConfigDir()) + wxT("LastError.txt"), wxFile::write);
- safeOutput.Write(wxString::FromAscii(e.what()));
+ //it's not always possible to display a message box, e.g. corrupted stack, however (non-stream) file output works!
+ wxFile safeOutput(toWx(getConfigDir()) + L"LastError.txt", wxFile::write);
+ safeOutput.Write(utf8CvrtTo<wxString>(e.what()));
- wxSafeShowMessage(_("An exception occurred!") + L" - RTS", wxString::FromAscii(e.what()));
+ wxSafeShowMessage(_("An exception occurred!") + L" - RTS", utf8CvrtTo<wxString>(e.what()));
+ return -9;
+ }
+ catch (...) //catch the rest
+ {
+ const wxString& msg = L"Unknown error.";
+
+ wxFile safeOutput(toWx(getConfigDir()) + L"LastError.txt", wxFile::write);
+ safeOutput.Write(msg);
+
+ wxSafeShowMessage(_("An exception occurred!"), msg);
return -9;
}
diff --git a/RealtimeSync/gui_generated.cpp b/RealtimeSync/gui_generated.cpp
index 849915a4..9bcbda52 100644
--- a/RealtimeSync/gui_generated.cpp
+++ b/RealtimeSync/gui_generated.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Feb 9 2012)
+// C++ code generated with wxFormBuilder (version Apr 10 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -164,7 +164,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
bSizer1->Add( sbSizer4, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
- m_buttonStart = new zen::BitmapButton( m_panelMain, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
+ m_buttonStart = new zen::BitmapButton( m_panelMain, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
m_buttonStart->SetDefault();
m_buttonStart->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) );
@@ -246,3 +246,65 @@ FolderGenerated::FolderGenerated( wxWindow* parent, wxWindowID id, const wxPoint
FolderGenerated::~FolderGenerated()
{
}
+
+ErrorDlgGenerated::ErrorDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
+{
+ this->SetSizeHints( wxSize( 300,160 ), wxDefaultSize );
+
+ wxBoxSizer* bSizer24;
+ bSizer24 = new wxBoxSizer( wxVERTICAL );
+
+
+ bSizer24->Add( 0, 10, 0, wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer26;
+ bSizer26 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 );
+ bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY );
+ m_textCtrl8->SetBackgroundColour( wxColour( 224, 224, 224 ) );
+
+ bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
+
+
+ bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer25;
+ bSizer25 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_buttonRetry = new wxButton( this, wxID_RETRY, _("&Retry"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonRetry->SetDefault();
+ m_buttonRetry->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ bSizer25->Add( m_buttonRetry, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_buttonAbort = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonAbort->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ bSizer25->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
+
+
+ bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
+
+
+ this->SetSizer( bSizer24 );
+ this->Layout();
+
+ this->Centre( wxBOTH );
+
+ // Connect Events
+ this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) );
+ m_buttonRetry->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this );
+ m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this );
+}
+
+ErrorDlgGenerated::~ErrorDlgGenerated()
+{
+ // Disconnect Events
+ this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) );
+ m_buttonRetry->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this );
+ m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this );
+
+}
diff --git a/RealtimeSync/gui_generated.h b/RealtimeSync/gui_generated.h
index aa0f5ad8..1989653f 100644
--- a/RealtimeSync/gui_generated.h
+++ b/RealtimeSync/gui_generated.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Feb 9 2012)
+// C++ code generated with wxFormBuilder (version Apr 10 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -34,6 +34,8 @@
#include <wx/scrolwin.h>
#include <wx/spinctrl.h>
#include <wx/frame.h>
+#include <wx/statbmp.h>
+#include <wx/dialog.h>
#include "../zen/i18n.h"
@@ -111,4 +113,30 @@ public:
};
+///////////////////////////////////////////////////////////////////////////////
+/// Class ErrorDlgGenerated
+///////////////////////////////////////////////////////////////////////////////
+class ErrorDlgGenerated : public wxDialog
+{
+private:
+
+protected:
+ wxStaticBitmap* m_bitmap10;
+ wxTextCtrl* m_textCtrl8;
+ wxButton* m_buttonRetry;
+ wxButton* m_buttonAbort;
+
+ // Virtual event handlers, overide them in your derived class
+ virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
+ virtual void OnRetry( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnAbort( wxCommandEvent& event ) { event.Skip(); }
+
+
+public:
+
+ ErrorDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Error"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 460,250 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER );
+ ~ErrorDlgGenerated();
+
+};
+
#endif //__GUI_GENERATED_H__
diff --git a/RealtimeSync/main_dlg.cpp b/RealtimeSync/main_dlg.cpp
index c91e4856..dfb1a85e 100644
--- a/RealtimeSync/main_dlg.cpp
+++ b/RealtimeSync/main_dlg.cpp
@@ -59,15 +59,15 @@ MainDialog::MainDialog(wxDialog* dlg, const wxString& cfgFileName)
if (!cfgFileName.empty() || wxFileExists(lastConfigFileName()))
try
{
- rts::readRealOrBatchConfig(currentConfigFile, newConfig);
+ rts::readRealOrBatchConfig(toZ(currentConfigFile), newConfig);
loadCfgSuccess = true;
}
catch (const xmlAccess::FfsXmlError& error)
{
if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING);
+ wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
else
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
}
const bool startWatchingImmediately = loadCfgSuccess && !cfgFileName.empty();
@@ -102,30 +102,18 @@ MainDialog::~MainDialog()
try //write config to XML
{
- writeRealConfig(currentCfg, lastConfigFileName());
+ writeRealConfig(currentCfg, toZ(lastConfigFileName()));
}
catch (const xmlAccess::FfsXmlError& error)
{
- wxMessageBox(error.toString().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
}
}
-void MainDialog::OnClose(wxCloseEvent& event)
-{
- Destroy();
-}
-
-
-void MainDialog::OnQuit(wxCommandEvent& event)
-{
- Destroy();
-}
-
-
const wxString& MainDialog::lastConfigFileName()
{
- static wxString instance = toWx(zen::getConfigDir()) + wxT("LastRun.ffs_real");
+ static wxString instance = toWx(zen::getConfigDir()) + L"LastRun.ffs_real";
return instance;
}
@@ -145,23 +133,19 @@ void MainDialog::OnMenuAbout(wxCommandEvent& event)
//build information
wxString build = __TDATE__;
#if wxUSE_UNICODE
- build += wxT(" - Unicode");
+ build += L" - Unicode";
#else
- build += wxT(" - ANSI");
+ build += L" - ANSI";
#endif //wxUSE_UNICODE
//compile time info about 32/64-bit build
if (zen::is64BitBuild)
- build += wxT(" x64");
+ build += L" x64";
else
- build += wxT(" x86");
+ build += L" x86";
assert_static(zen::is32BitBuild || zen::is64BitBuild);
- wxString buildFormatted = _("(Build: %x)");
- buildFormatted.Replace(wxT("%x"), build);
-
- wxMessageDialog* aboutDlg = new wxMessageDialog(this, wxString(L"RealtimeSync") + L"\n\n" + buildFormatted, _("About"), wxOK);
- aboutDlg->ShowModal();
+ wxMessageBox(L"RealtimeSync" L"\n\n" + replaceCpy(_("(Build: %x)"), L"%x", build), _("About"), wxOK, this);
}
@@ -170,7 +154,7 @@ void MainDialog::OnKeyPressed(wxKeyEvent& event)
const int keyCode = event.GetKeyCode();
if (keyCode == WXK_ESCAPE)
- Destroy();
+ Close();
event.Skip();
}
@@ -184,52 +168,43 @@ void MainDialog::OnStart(wxCommandEvent& event)
switch (rts::startDirectoryMonitor(currentCfg, xmlAccess::extractJobName(currentConfigFileName)))
{
- case rts::QUIT:
- {
- Destroy();
+ case rts::EXIT_APP:
+ Close();
return;
- }
- break;
- case rts::RESUME:
+ case rts::SHOW_GUI:
break;
}
-
- Show();
+ Show(); //don't show for EXIT_APP
}
void MainDialog::OnSaveConfig(wxCommandEvent& event)
{
- wxString defaultFileName = currentConfigFileName.empty() ? wxT("Realtime.ffs_real") : currentConfigFileName;
+ wxString defaultFileName = currentConfigFileName.empty() ? L"Realtime.ffs_real" : currentConfigFileName;
//attention: currentConfigFileName may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config!
- if (defaultFileName.EndsWith(wxT(".ffs_batch")))
- defaultFileName.Replace(wxT(".ffs_batch"), wxT(".ffs_real"), false);
+ if (endsWith(defaultFileName, L".ffs_batch"))
+ replace(defaultFileName, L".ffs_batch", L".ffs_real", false);
- 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();
+ wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName,
+ _("RealtimeSync configuration") + L" (*.ffs_real)|*.ffs_real",
+ wxFD_SAVE /*| wxFD_OVERWRITE_PROMPT*/);
+ if (filePicker.ShowModal() != wxID_OK)
+ return;
- if (wxFileExists(newFileName))
- {
- wxMessageDialog* messageDlg = new wxMessageDialog(this, wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""), _("Warning") , wxOK | wxCANCEL);
- if (messageDlg->ShowModal() != wxID_OK)
- return OnSaveConfig(event); //retry
- }
+ const wxString newFileName = filePicker.GetPath();
- //write config to XML
- const xmlAccess::XmlRealConfig currentCfg = getConfiguration();
- try
- {
- writeRealConfig(currentCfg, newFileName);
- setLastUsedConfig(newFileName);
- }
- catch (const zen::FileError& error)
- {
- wxMessageBox(error.toString().c_str(), _("Error"), wxOK | wxICON_ERROR);
- }
+ //write config to XML
+ const xmlAccess::XmlRealConfig currentCfg = getConfiguration();
+ try
+ {
+ writeRealConfig(currentCfg, toZ(newFileName)); //throw FfsXmlError
+ setLastUsedConfig(newFileName);
+ }
+ catch (const xmlAccess::FfsXmlError& e)
+ {
+ wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
}
}
@@ -240,7 +215,7 @@ void MainDialog::loadConfig(const wxString& filename)
try
{
- rts::readRealOrBatchConfig(filename, newConfig);
+ rts::readRealOrBatchConfig(toZ(filename), newConfig);
}
catch (const xmlAccess::FfsXmlError& error)
{
@@ -276,11 +251,11 @@ void MainDialog::setLastUsedConfig(const wxString& filename)
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());
+ wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, wxEmptyString,
+ _("RealtimeSync configuration") + L" (*.ffs_real;*.ffs_batch)|*.ffs_real;*.ffs_batch",
+ wxFD_OPEN);
+ if (filePicker.ShowModal() == wxID_OK)
+ loadConfig(filePicker.GetPath());
}
@@ -342,13 +317,11 @@ void MainDialog::OnRemoveFolder(wxCommandEvent& event)
//find folder pair originating the event
const wxObject* const eventObj = event.GetEventObject();
for (std::vector<DirectoryPanel*>::const_iterator i = dirNamesExtra.begin(); i != dirNamesExtra.end(); ++i)
- {
if (eventObj == static_cast<wxObject*>((*i)->m_bpButtonRemoveFolder))
{
removeAddFolder(i - dirNamesExtra.begin());
return;
}
- }
}
diff --git a/RealtimeSync/main_dlg.h b/RealtimeSync/main_dlg.h
index 01789a45..edc66c47 100644
--- a/RealtimeSync/main_dlg.h
+++ b/RealtimeSync/main_dlg.h
@@ -44,17 +44,17 @@ public:
void loadConfig(const wxString& filename);
private:
- virtual void OnClose( wxCloseEvent& event);
- virtual void OnQuit( wxCommandEvent& event);
- virtual void OnShowHelp( 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);
+ virtual void OnClose (wxCloseEvent& event) { Destroy(); }
+ virtual void OnQuit (wxCommandEvent& event) { Destroy(); }
+ virtual void OnShowHelp (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();
diff --git a/RealtimeSync/resources.cpp b/RealtimeSync/resources.cpp
index f81af50a..486aa8f1 100644
--- a/RealtimeSync/resources.cpp
+++ b/RealtimeSync/resources.cpp
@@ -23,7 +23,7 @@ const GlobalResources& GlobalResources::instance()
GlobalResources::GlobalResources()
{
- wxFFileInputStream input(toWx(zen::getResourceDir()) + wxT("Resources.zip"));
+ wxFFileInputStream input(toWx(zen::getResourceDir()) + L"Resources.zip");
if (input.IsOk()) //if not... we don't want to react too harsh here
{
//activate support for .png files
@@ -41,17 +41,17 @@ GlobalResources::GlobalResources()
const wxString name = entry->GetName();
//generic image loading
- if (name.EndsWith(wxT(".png")))
+ if (endsWith(name, L".png"))
bitmaps.insert(std::make_pair(name, 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"));
+ programIcon = wxIcon(L"A_PROGRAM_ICON");
#else
//use big logo bitmap for better quality
- programIcon.CopyFromBitmap(getImageInt(wxT("RealtimeSync.png")));
+ programIcon.CopyFromBitmap(getImageInt(L"RealtimeSync.png"));
#endif
}
@@ -59,8 +59,8 @@ GlobalResources::GlobalResources()
const wxBitmap& GlobalResources::getImageInt(const wxString& name) const
{
- auto iter = bitmaps.find(name.Find(L'.') == wxNOT_FOUND ? //assume .png ending if nothing else specified
- name + wxT(".png") :
+ auto iter = bitmaps.find(!contains(name, L'.') ? //assume .png ending if nothing else specified
+ name + L".png" :
name);
if (iter != bitmaps.end())
return iter->second;
diff --git a/RealtimeSync/tray_menu.cpp b/RealtimeSync/tray_menu.cpp
index e18101e0..4afef5e4 100644
--- a/RealtimeSync/tray_menu.cpp
+++ b/RealtimeSync/tray_menu.cpp
@@ -16,38 +16,42 @@
#include <wx/menu.h>
#include "watcher.h"
#include <wx/utils.h>
-#include <wx/log.h>
#include <wx/icon.h> //Linux needs this
#include <wx/timer.h>
+#include <wx+/mouse_move_dlg.h>
#include "resources.h"
#include <wx+/string_conv.h>
#include <zen/assert_static.h>
#include <zen/build_info.h>
#include <wx+/shell_execute.h>
+#include "gui_generated.h"
using namespace rts;
using namespace zen;
-class TrayIconHolder : private wxEvtHandler
+
+namespace
{
-public:
- TrayIconHolder(const wxString& jobname);
- ~TrayIconHolder();
+struct AbortCallback //never throw exceptions through a C-Layer (GUI)!
+{
+ virtual ~AbortCallback() {}
+ virtual void requestResume() = 0;
+ virtual void requestAbort() = 0;
+};
- void doUiRefreshNow();
- void showIconActive();
- void showIconWaiting();
- void requestAbort()
+//RtsTrayIcon is a dumb class whose sole purpose is to enable wxWidgets deferred deletion
+class RtsTrayIconRaw : public wxTaskBarIcon
+{
+public:
+ RtsTrayIconRaw(AbortCallback& abortCb) : abortCb_(&abortCb)
{
- m_abortRequested = true;
+ Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(RtsTrayIconRaw::OnDoubleClick), nullptr, this);
}
- void OnRequestResume(wxCommandEvent& event)
- {
- m_resumeRequested = true;
- }
+ void dontCallBackAnymore() { abortCb_ = nullptr; } //call before tray icon is marked for deferred deletion
+private:
enum Selection
{
CONTEXT_ABORT,
@@ -55,34 +59,9 @@ public:
CONTEXT_ABOUT
};
- void OnContextMenuSelection(wxCommandEvent& event);
-
-private:
- class RtsTrayIcon;
- RtsTrayIcon* trayMenu;
-
- bool m_abortRequested;
- bool m_resumeRequested;
-
- const wxString jobName_; //RTS job name, may be empty
-};
-
-
-//RtsTrayIcon shall be a dumb class whose sole purpose is to enable wxWidgets deferred deletion
-class TrayIconHolder::RtsTrayIcon : public wxTaskBarIcon
-{
-public:
- RtsTrayIcon(TrayIconHolder* parent) : parent_(parent) {}
-
- void parentHasDied() //call before tray icon is marked for deferred deletion
- {
- parent_ = nullptr;
- }
-
-private:
virtual wxMenu* CreatePopupMenu()
{
- if (!parent_)
+ if (!abortCb_)
return nullptr;
wxMenu* contextMenu = new wxMenu;
@@ -91,169 +70,150 @@ private:
contextMenu->AppendSeparator();
contextMenu->Append(CONTEXT_ABORT, _("&Exit"));
//event handling
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TrayIconHolder::OnContextMenuSelection), nullptr, parent_);
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(RtsTrayIconRaw::OnContextMenuSelection), nullptr, this);
return contextMenu; //ownership transferred to caller
}
- TrayIconHolder* parent_;
-};
-//##############################################################################################################
+ void OnContextMenuSelection(wxCommandEvent& event)
+ {
+ if (!abortCb_)
+ return;
+ switch (static_cast<Selection>(event.GetId()))
+ {
+ case CONTEXT_ABORT:
+ abortCb_->requestAbort();
+ break;
-class AbortThisProcess //exception class
-{
-public:
- AbortThisProcess(MonitorResponse command) : command_(command) {}
+ case CONTEXT_RESTORE:
+ abortCb_->requestResume();
+ break;
+
+ case CONTEXT_ABOUT:
+ {
+ //build information
+ wxString build = __TDATE__;
+#if wxUSE_UNICODE
+ build += L" - Unicode";
+#else
+ build += L" - ANSI";
+#endif //wxUSE_UNICODE
+
+ //compile time info about 32/64-bit build
+ if (zen::is64BitBuild)
+ build += L" x64";
+ else
+ build += L" x86";
+ assert_static(zen::is32BitBuild || zen::is64BitBuild);
+
+ wxMessageBox(L"RealtimeSync" L"\n\n" + replaceCpy(_("(Build: %x)"), L"%x", build), _("About"), wxOK);
+ }
+ break;
+ }
+ }
- MonitorResponse getCommand() const
+ void OnDoubleClick(wxCommandEvent& event)
{
- return command_;
+ if (abortCb_)
+ abortCb_->requestResume();
}
-private:
- MonitorResponse command_;
+ AbortCallback* abortCb_;
};
-//##############################################################################################################
-TrayIconHolder::TrayIconHolder(const wxString& jobname) :
- m_abortRequested(false),
- m_resumeRequested(false),
- jobName_(jobname)
+class TrayIconHolder
{
- trayMenu = new RtsTrayIcon(this); //not in initialization list: give it a valid parent object!
-
- showIconActive();
-
- //register double-click
- trayMenu->Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(TrayIconHolder::OnRequestResume), nullptr, this);
-}
-
+public:
+ TrayIconHolder(const wxString& jobname, AbortCallback& abortCb) :
+ jobName_(jobname)
+ {
+ trayMenu = new RtsTrayIconRaw(abortCb); //not in initialization list: give it a valid parent object!
+ showIconActive();
+ }
-TrayIconHolder::~TrayIconHolder()
-{
- trayMenu->Disconnect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(TrayIconHolder::OnRequestResume), nullptr, this);
- trayMenu->RemoveIcon(); //(try to) hide icon until final deletion takes place
- trayMenu->parentHasDied();
+ ~TrayIconHolder()
+ {
+ trayMenu->RemoveIcon(); //(try to) hide icon until final deletion takes place
+ trayMenu->dontCallBackAnymore();
- //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking)
- if (!wxPendingDelete.Member(trayMenu))
- wxPendingDelete.Append(trayMenu);
-}
+ //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking)
+ if (!wxPendingDelete.Member(trayMenu))
+ wxPendingDelete.Append(trayMenu);
+ }
+ void doUiRefreshNow()
+ {
+ wxTheApp->Yield();
+ } //yield is UI-layer which is represented by this tray icon
-void TrayIconHolder::showIconActive()
-{
- wxIcon realtimeIcon;
+ void showIconActive()
+ {
+ wxIcon realtimeIcon;
#ifdef FFS_WIN
- realtimeIcon.CopyFromBitmap(GlobalResources::getImage(wxT("RTS_tray_win.png"))); //use a 16x16 bitmap
+ realtimeIcon.CopyFromBitmap(GlobalResources::getImage(L"RTS_tray_win.png")); //use a 16x16 bitmap
#elif defined FFS_LINUX
- realtimeIcon.CopyFromBitmap(GlobalResources::getImage(wxT("RTS_tray_linux.png"))); //use a 22x22 bitmap for perfect fit
+ realtimeIcon.CopyFromBitmap(GlobalResources::getImage(L"RTS_tray_linux.png")); //use a 22x22 bitmap for perfect fit
#endif
- const wxString postFix = jobName_.empty() ? wxString() : (wxT("\n\"") + jobName_ + wxT("\""));
- trayMenu->SetIcon(realtimeIcon, _("Monitoring active...") + postFix);
-}
-
+ const wxString postFix = jobName_.empty() ? wxString() : (L"\n\"" + jobName_ + L"\"");
+ trayMenu->SetIcon(realtimeIcon, _("Monitoring active...") + postFix);
+ }
-void TrayIconHolder::showIconWaiting()
-{
- wxIcon realtimeIcon;
+ void showIconWaiting()
+ {
+ wxIcon realtimeIcon;
#ifdef FFS_WIN
- realtimeIcon.CopyFromBitmap(GlobalResources::getImage(wxT("RTS_tray_waiting_win.png"))); //use a 16x16 bitmap
+ realtimeIcon.CopyFromBitmap(GlobalResources::getImage(L"RTS_tray_waiting_win.png")); //use a 16x16 bitmap
#elif defined FFS_LINUX
- realtimeIcon.CopyFromBitmap(GlobalResources::getImage(wxT("RTS_tray_waiting_linux.png"))); //use a 22x22 bitmap for perfect fit
+ realtimeIcon.CopyFromBitmap(GlobalResources::getImage(L"RTS_tray_waiting_linux.png")); //use a 22x22 bitmap for perfect fit
#endif
- const wxString postFix = jobName_.empty() ? wxString() : (wxT("\n\"") + jobName_ + wxT("\""));
- trayMenu->SetIcon(realtimeIcon, _("Waiting for missing directories...") + postFix);
-}
-
-
-void TrayIconHolder::OnContextMenuSelection(wxCommandEvent& event)
-{
- const int eventId = event.GetId();
- switch (static_cast<Selection>(eventId))
- {
- case CONTEXT_ABORT:
- requestAbort();
- break;
- case CONTEXT_RESTORE:
- OnRequestResume(event); //just remember: never throw exceptions through a C-Layer (GUI) ;)
- break;
- case CONTEXT_ABOUT:
- {
- //build information
- wxString build = __TDATE__;
-#if wxUSE_UNICODE
- build += wxT(" - Unicode");
-#else
- build += wxT(" - ANSI");
-#endif //wxUSE_UNICODE
-
- //compile time info about 32/64-bit build
- if (zen::is64BitBuild)
- build += wxT(" x64");
- else
- build += wxT(" x86");
- assert_static(zen::is32BitBuild || zen::is64BitBuild);
-
- wxString buildFormatted = _("(Build: %x)");
- buildFormatted.Replace(wxT("%x"), build);
-
- wxMessageDialog aboutDlg(nullptr, wxString(wxT("RealtimeSync")) + wxT("\n\n") + buildFormatted, _("About"), wxOK);
- aboutDlg.ShowModal();
- }
- break;
+ const wxString postFix = jobName_.empty() ? wxString() : (L"\n\"" + jobName_ + L"\"");
+ trayMenu->SetIcon(realtimeIcon, _("Waiting for missing directories...") + postFix);
}
-}
-
-void TrayIconHolder::doUiRefreshNow()
-{
- wxTheApp->Yield();
+private:
+ RtsTrayIconRaw* trayMenu;
+ const wxString jobName_; //RTS job name, may be empty
+};
- if (m_abortRequested)
- throw ::AbortThisProcess(QUIT);
- if (m_resumeRequested)
- throw ::AbortThisProcess(RESUME);
-}
//##############################################################################################################
-namespace
-{
-std::vector<Zstring> convert(const std::vector<wxString>& dirList)
+struct AbortMonitoring//exception class
{
- std::set<Zstring, LessFilename> output;
- std::transform(dirList.begin(), dirList.end(),
- std::inserter(output, output.end()), [](const wxString & str) { return zen::toZ(str); });
- return std::vector<Zstring>(output.begin(), output.end());
-}
-}
-
+ AbortMonitoring(AbortReason reasonCode) : reasonCode_(reasonCode) {}
+ AbortReason reasonCode_;
+};
class StartSyncNowException {};
+//##############################################################################################################
-class WaitCallbackImpl : public rts::WaitCallback
+class WaitCallbackImpl : public rts::WaitCallback, private AbortCallback
{
public:
WaitCallbackImpl(const wxString& jobname) :
- trayIcon(jobname),
- nextSyncStart_(std::numeric_limits<long>::max()) {}
+ trayIcon(jobname, *this),
+ nextSyncStart_(std::numeric_limits<long>::max()),
+ resumeRequested(false),
+ abortRequested(false) {}
- void notifyAllDirectoriesExist()
- {
- trayIcon.showIconActive();
- }
+ void notifyAllDirectoriesExist() { trayIcon.showIconActive(); }
+ void notifyDirectoryMissing () { trayIcon.showIconWaiting(); }
- void notifyDirectoryMissing()
- {
- trayIcon.showIconWaiting();
- }
+ void scheduleNextSync(long nextSyncStart) { nextSyncStart_ = nextSyncStart; }
+ void clearSchedule() { nextSyncStart_ = std::numeric_limits<long>::max(); }
- virtual void requestUiRefresh() //throw StartSyncNowException()
+ //implement WaitCallback
+ virtual void requestUiRefresh() //throw StartSyncNowException, AbortMonitoring
{
+ if (resumeRequested)
+ throw AbortMonitoring(SHOW_GUI);
+
+ if (abortRequested)
+ throw AbortMonitoring(EXIT_APP);
+
if (nextSyncStart_ <= wxGetLocalTime())
throw StartSyncNowException(); //abort wait and start sync
@@ -261,16 +221,87 @@ public:
trayIcon.doUiRefreshNow();
}
- void scheduleNextSync(long nextSyncStart)
+private:
+ //implement AbortCallback: used from C-GUI call stack
+ virtual void requestResume() { resumeRequested = true; }
+ virtual void requestAbort () { abortRequested = true; }
+
+ TrayIconHolder trayIcon;
+ long nextSyncStart_;
+ bool resumeRequested;
+ bool abortRequested;
+};
+
+
+
+class ErrorDlgWithTimeout : public ErrorDlgGenerated
+{
+public:
+ ErrorDlgWithTimeout(wxWindow* parent, const wxString& messageText) :
+ ErrorDlgGenerated(parent),
+ secondsLeft(15) //give user some time to read msg!?
{
- nextSyncStart_ = nextSyncStart;
+#ifdef FFS_WIN
+ new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this"
+#endif
+ m_bitmap10->SetBitmap(GlobalResources::getImage(L"error"));
+ m_textCtrl8->SetValue(messageText);
+ m_buttonRetry->SetFocus();
+
+ //count down X seconds then automatically press "retry"
+ timer.Connect(wxEVT_TIMER, wxEventHandler(ErrorDlgWithTimeout::OnTimerEvent), nullptr, this);
+ timer.Start(1000); //timer interval in ms
+ updateButtonLabel();
}
+ enum ButtonPressed
+ {
+ BUTTON_RETRY,
+ BUTTON_ABORT
+ };
+
private:
- TrayIconHolder trayIcon;
- long nextSyncStart_;
+ void OnTimerEvent(wxEvent& event)
+ {
+ --secondsLeft;
+ if (secondsLeft < 0)
+ {
+ EndModal(BUTTON_RETRY);
+ return;
+ }
+ updateButtonLabel();
+ }
+
+ void updateButtonLabel()
+ {
+ m_buttonRetry->SetLabel(_("&Retry") + L" (" + replaceCpy(_P("1 sec", "%x sec", secondsLeft), L"%x", numberTo<std::wstring>(secondsLeft)) + L")");
+ Layout();
+ }
+
+ void OnClose(wxCloseEvent& event) { EndModal(BUTTON_ABORT); }
+ void OnRetry(wxCommandEvent& event) { EndModal(BUTTON_RETRY); }
+ void OnAbort(wxCommandEvent& event) { EndModal(BUTTON_ABORT); }
+
+ int secondsLeft;
+ wxTimer timer;
};
+
+bool reportErrorTimeout(const std::wstring& msg) //return true if timeout or user selected "retry", else abort
+{
+ ErrorDlgWithTimeout errorDlg(nullptr, msg);
+ //errorDlg.Raise(); -> don't steal focus every X seconds
+ switch (static_cast<ErrorDlgWithTimeout::ButtonPressed>(errorDlg.ShowModal()))
+ {
+ case ErrorDlgWithTimeout::BUTTON_RETRY:
+ return true;
+ case ErrorDlgWithTimeout::BUTTON_ABORT:
+ return false;
+ }
+ return false;
+}
+}
+
/*
Data Flow:
----------
@@ -278,82 +309,96 @@ Data Flow:
TrayIconHolder (GUI output)
/|\
|
-WaitCallbackImpl (higher level "interface")
+WaitCallbackImpl
/|\
|
startDirectoryMonitor() (wire dir-changes and execution of commandline)
- /|\
- |
-watcher.h (low level wait for directory changes)
*/
-rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config, const wxString& jobname)
+rts::AbortReason rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config, const wxString& jobname)
{
- Zstring lastFileChanged;
+ const std::vector<Zstring> dirList = toZ(config.directories);
+
+ auto cmdLine = config.commandline;
+ trim(cmdLine);
+
+ if (cmdLine.empty())
+ {
+ wxMessageBox(replaceCpy(_("Invalid command line: %x"), L"%x", L"\"\""), _("Error"), wxOK | wxICON_ERROR);
+ return SHOW_GUI;
+ }
+ if (dirList.empty() || std::any_of(dirList.begin(), dirList.end(), [](Zstring str) -> bool { trim(str); return str.empty(); }))
+ {
+ wxMessageBox(_("A directory input field is empty."), _("Error"), wxOK | wxICON_ERROR);
+ return SHOW_GUI;
+ }
- const std::vector<Zstring> dirList = convert(config.directories);
try
{
+ Zstring lastFileChanged;
WaitCallbackImpl callback(jobname);
- if (config.commandline.empty())
- {
- std::wstring errorMsg = _("Invalid command line: %x");
- replace(errorMsg, L"%x", L"\"" + config.commandline + L"\"");
- throw FileError(errorMsg);
- }
-
- callback.notifyDirectoryMissing();
- waitForMissingDirs(dirList, &callback);
- callback.notifyAllDirectoriesExist();
-
- while (true)
+ auto execMonitoring = [&] //throw FileError, AbortMonitoring
{
- ::wxSetEnv(L"changed_file", utf8CvrtTo<wxString>(lastFileChanged)); //some way to output what file changed to the user
- lastFileChanged.clear(); //make sure old name is not shown again after a directory reappears
-
- //execute command
- zen::shellExecute(config.commandline, zen::EXEC_TYPE_SYNC);
+ callback.clearSchedule();
- wxLog::FlushActive(); //show wxWidgets error messages (if any)
+ callback.notifyDirectoryMissing();
+ waitForMissingDirs(dirList, callback); //throw FileError, StartSyncNowException(not scheduled yet), AbortMonitoring
+ callback.notifyAllDirectoriesExist();
- callback.scheduleNextSync(std::numeric_limits<long>::max()); //next sync not scheduled (yet)
+ //schedule initial execution only AFTER waitForMissingDirs(), else StartSyncNowException might be thrown while directory checking hangs
+ callback.scheduleNextSync(wxGetLocalTime() + static_cast<long>(config.delay));
- try
+ while (true)
{
- while (true)
+ try
{
- //wait for changes (and for all directories to become available)
- WaitResult res = waitForChanges(dirList, &callback);
- switch (res.type)
+ while (true)
{
- case CHANGE_DIR_MISSING: //don't execute the commandline before all directories are available!
- callback.scheduleNextSync(std::numeric_limits<long>::max()); //next sync not scheduled (yet)
- callback.notifyDirectoryMissing();
- waitForMissingDirs(dirList, &callback);
- callback.notifyAllDirectoriesExist();
- break;
- case CHANGE_DETECTED:
- lastFileChanged = res.filename;
- break;
+ //wait for changes (and for all directories to become available)
+ WaitResult res = waitForChanges(dirList, callback); //throw FileError, StartSyncNowException, AbortMonitoring
+ switch (res.type)
+ {
+ case CHANGE_DIR_MISSING: //don't execute the commandline before all directories are available!
+ callback.clearSchedule();
+
+ callback.notifyDirectoryMissing();
+ waitForMissingDirs(dirList, callback); //throw FileError, StartSyncNowException(not scheduled yet), AbortMonitoring
+ callback.notifyAllDirectoriesExist();
+ break;
+
+ case CHANGE_DETECTED:
+ lastFileChanged = res.filename;
+ break;
+ }
+ callback.scheduleNextSync(wxGetLocalTime() + static_cast<long>(config.delay));
}
-
- callback.scheduleNextSync(wxGetLocalTime() + static_cast<long>(config.delay));
}
+ catch (StartSyncNowException&) {}
+
+ ::wxSetEnv(L"changed_file", utf8CvrtTo<wxString>(lastFileChanged)); //some way to output what file changed to the user
+ lastFileChanged.clear(); //make sure old name is not shown again after a directory reappears
+
+ //execute command
+ zen::shellExecute(cmdLine, zen::EXEC_TYPE_SYNC);
+ callback.clearSchedule();
+ }
+ };
+
+ while (true)
+ try
+ {
+ execMonitoring(); //throw FileError, AbortMonitoring
+ }
+ catch (const zen::FileError& e)
+ {
+ if (!reportErrorTimeout(e.toString())) //return true if timeout or user selected "retry", else abort
+ return SHOW_GUI;
}
- catch (StartSyncNowException&) {}
- }
- }
- catch (const ::AbortThisProcess& ab)
- {
- return ab.getCommand();
}
- catch (const zen::FileError& error)
+ catch (const AbortMonitoring& ab)
{
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
- return RESUME;
+ return ab.reasonCode_;
}
-
- return RESUME;
}
diff --git a/RealtimeSync/tray_menu.h b/RealtimeSync/tray_menu.h
index 21d26932..9c910694 100644
--- a/RealtimeSync/tray_menu.h
+++ b/RealtimeSync/tray_menu.h
@@ -13,13 +13,12 @@
namespace rts
{
-enum MonitorResponse
+enum AbortReason
{
- RESUME,
- QUIT
+ SHOW_GUI,
+ EXIT_APP
};
-
-MonitorResponse startDirectoryMonitor(const xmlAccess::XmlRealConfig& config, const wxString& jobname); //jobname may be empty
+AbortReason startDirectoryMonitor(const xmlAccess::XmlRealConfig& config, const wxString& jobname); //jobname may be empty
}
diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp
index 36ceb006..ee56bc7c 100644
--- a/RealtimeSync/watcher.cpp
+++ b/RealtimeSync/watcher.cpp
@@ -5,30 +5,31 @@
// **************************************************************************
#include "watcher.h"
+#include <set>
+#include <zen/tick_count.h>
#include <zen/file_handling.h>
#include <zen/stl_tools.h>
-#include <set>
-#include <ctime>
-#include <wx/timer.h>
-#include "../lib/resolve_path.h"
#include <zen/dir_watcher.h>
-#include <wx+/string_conv.h>
#include <zen/thread.h>
+#include <zen/assert_static.h>
+#include <wx+/string_conv.h>
+#include <wx/timer.h>
+#include "../lib/resolve_path.h"
//#include "../library/db_file.h" //SYNC_DB_FILE_ENDING -> complete file too much of a dependency; file ending too little to decouple into single header
//#include "../library/lock_holder.h" //LOCK_FILE_ENDING
-#include <wx/msgdlg.h>
using namespace zen;
+namespace
+{
+const std::int64_t TICKS_UPDATE_INTERVAL = rts::UI_UPDATE_INTERVAL* ticksPerSec() / 1000;
+TickVal lastExec = getTicks();
+};
bool rts::updateUiIsAllowed()
{
- const std::clock_t CLOCK_UPDATE_INTERVAL = UI_UPDATE_INTERVAL * CLOCKS_PER_SEC / 1000;
-
- static std::clock_t lastExec = 0;
- const std::clock_t now = std::clock(); //this is quite fast: 2 * 10^-5
-
- if (now - lastExec >= CLOCK_UPDATE_INTERVAL) //perform ui updates not more often than necessary
+ const TickVal now = getTicks(); //0 on error
+ if (now - lastExec >= TICKS_UPDATE_INTERVAL) //perform ui updates not more often than necessary
{
lastExec = now;
return true;
@@ -36,29 +37,30 @@ bool rts::updateUiIsAllowed()
return false;
}
+
namespace
{
const int CHECK_DIR_INTERVAL = 1000; //1 second interval
-}
-rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt, WaitCallback* statusHandler) //throw FileError
+std::vector<Zstring> getFormattedDirs(const std::vector<Zstring>& dirs) //throw FileError
{
- std::set<Zstring, LessFilename> dirNamesFmt;
+ std::set<Zstring, LessFilename> tmp; //make unique
- std::for_each(dirNamesNonFmt.begin(), dirNamesNonFmt.end(),
- [&](const Zstring& dirnameNonFmt)
- {
- const Zstring& dirnameFmt = zen::getFormattedDirectoryName(dirnameNonFmt);
+ std::transform(dirs.begin(), dirs.end(), std::inserter(tmp, tmp.end()),
+ [](const Zstring& dirnameNonFmt) { return getFormattedDirectoryName(dirnameNonFmt); });
- if (dirnameFmt.empty())
- throw zen::FileError(_("A directory input field is empty."));
- dirNamesFmt.insert(dirnameFmt);
- });
- if (dirNamesFmt.empty()) //pathological case, but check is needed nevertheless
- throw zen::FileError(_("A directory input field is empty."));
+ return std::vector<Zstring>(tmp.begin(), tmp.end());
+}
+}
+rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt, WaitCallback& statusHandler) //throw FileError
+{
+ const std::vector<Zstring> dirNamesFmt = getFormattedDirs(dirNamesNonFmt); //throw FileError
+ if (dirNamesFmt.empty()) //pathological case, but check is needed nevertheless
+ throw zen::FileError(_("A directory input field is empty.")); //should have been checked by caller!
+
//detect when volumes are removed/are not available anymore
std::vector<std::pair<Zstring, std::shared_ptr<DirWatcher>>> watches;
@@ -67,16 +69,24 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
const Zstring& dirnameFmt = *iter;
try
{
+ //a non-existent network path may block, so check existence asynchronously!
+ auto ftDirExists = async([=] { return zen::dirExists(dirnameFmt); });
+ while (!ftDirExists.timed_wait(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL)))
+ statusHandler.requestUiRefresh(); //may throw!
+ if (!ftDirExists.get())
+ return WaitResult(CHANGE_DIR_MISSING, dirnameFmt);
+
+
watches.push_back(std::make_pair(dirnameFmt, std::make_shared<DirWatcher>(dirnameFmt))); //throw FileError, ErrorNotExisting
}
catch (ErrorNotExisting&) //nice atomic behavior: *no* second directory existence check!!!
{
- return CHANGE_DIR_MISSING;
+ return WaitResult(CHANGE_DIR_MISSING, dirnameFmt);
}
catch (FileError&) //play safe: remedy potential FileErrors that should have been ErrorNotExisting (e.g. Linux: errors during directory traversing)
{
- if (!dirExists(dirnameFmt)) //not an atomic behavior!!!
- return CHANGE_DIR_MISSING;
+ if (!dirExists(dirnameFmt)) //file system race condition!!
+ return WaitResult(CHANGE_DIR_MISSING, dirnameFmt);
throw;
}
}
@@ -104,11 +114,11 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
//IMPORTANT CHECK: dirwatcher has problems detecting removal of top watched directories!
if (checkDirExistNow)
if (!dirExists(dirname)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED
- return CHANGE_DIR_MISSING;
+ return WaitResult(CHANGE_DIR_MISSING, dirname);
try
{
- std::vector<Zstring> changedFiles = watcher.getChanges([&] { statusHandler->requestUiRefresh(); }); //throw FileError, ErrorNotExisting
+ std::vector<Zstring> changedFiles = watcher.getChanges([&] { statusHandler.requestUiRefresh(); }); //throw FileError, ErrorNotExisting
//remove to be ignored changes
vector_remove_if(changedFiles, [](const Zstring& name)
@@ -130,67 +140,61 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
}
catch (ErrorNotExisting&) //nice atomic behavior: *no* second directory existence check!!!
{
- return CHANGE_DIR_MISSING;
+ return WaitResult(CHANGE_DIR_MISSING, dirname);
}
catch (FileError&) //play safe: remedy potential FileErrors that should have been ErrorNotExisting (e.g. Linux: errors during directory traversing)
{
- if (!dirExists(dirname)) //not an atomic behavior!!!
- return CHANGE_DIR_MISSING;
+ if (!dirExists(dirname)) //file system race condition!!
+ return WaitResult(CHANGE_DIR_MISSING, dirname);
throw;
}
}
- wxMilliSleep(rts::UI_UPDATE_INTERVAL);
- statusHandler->requestUiRefresh();
+ boost::this_thread::sleep(boost::posix_time::milliseconds(rts::UI_UPDATE_INTERVAL));
+ statusHandler.requestUiRefresh();
}
}
//support for monitoring newly connected directories volumes (e.g.: USB-sticks)
-void rts::waitForMissingDirs(const std::vector<Zstring>& dirNamesNonFmt, WaitCallback* statusHandler) //throw FileError
+void rts::waitForMissingDirs(const std::vector<Zstring>& dirNamesNonFmt, WaitCallback& statusHandler) //throw FileError
{
- wxLongLong lastCheck;
-
while (true)
{
- const wxLongLong current = wxGetLocalTimeMillis();
- if (current - lastCheck >= CHECK_DIR_INTERVAL)
- {
- lastCheck = current;
+ //support specifying volume by name => call getFormattedDirectoryName() repeatedly
+ const std::vector<Zstring>& dirNamesFmt = getFormattedDirs(dirNamesNonFmt); //throw FileError
- auto ftDirMissing = async([=]() -> bool
+ bool allExisting = true;
+ for (auto iter = dirNamesFmt.begin(); iter != dirNamesFmt.end(); ++iter)
+ {
+ const Zstring dirnameFmt = *iter;
+ auto ftDirExisting = async([=]() -> bool
{
- return std::find_if(dirNamesNonFmt.begin(), dirNamesNonFmt.end(),
- [](const Zstring& dirnameNonFmt) -> bool
- {
- //support specifying volume by name => call getFormattedDirectoryName() repeatedly
- const Zstring dirnameFmt = zen::getFormattedDirectoryName(dirnameNonFmt);
-
- if (dirnameFmt.empty())
- throw zen::FileError(_("A directory input field is empty."));
#ifdef FFS_WIN
- //1. login to network share, if necessary
- loginNetworkShare(dirnameFmt, false); //login networks shares, no PW prompt -> is this really RTS's task?
+ //1. login to network share, if necessary -> we probably do NOT want multiple concurrent runs: GUI!?
+ loginNetworkShare(dirnameFmt, false); //login networks shares, no PW prompt -> is this really RTS's job?
#endif
- //2. check dir existence
- return !zen::dirExists(dirnameFmt);
- }) != dirNamesNonFmt.end();
+ //2. check dir existence
+ return zen::dirExists(dirnameFmt);
});
- while (!ftDirMissing.timed_wait(boost::posix_time::milliseconds(rts::UI_UPDATE_INTERVAL)))
- statusHandler->requestUiRefresh(); //may throw!
+ while (!ftDirExisting.timed_wait(boost::posix_time::milliseconds(rts::UI_UPDATE_INTERVAL)))
+ statusHandler.requestUiRefresh(); //may throw!
- try
+ if (!ftDirExisting.get())
{
- if (!ftDirMissing.get()) //throw X
- return;
- }
- catch (...) //boost::future seems to map async exceptions to "some" boost exception type -> migrate this for C++11
- {
- throw zen::FileError(_("A directory input field is empty."));
+ allExisting = false;
+ break;
}
}
+ if (allExisting)
+ return;
- wxMilliSleep(rts::UI_UPDATE_INTERVAL);
- statusHandler->requestUiRefresh();
+ //wait some time...
+ assert_static(CHECK_DIR_INTERVAL % UI_UPDATE_INTERVAL == 0);
+ for (int i = 0; i < CHECK_DIR_INTERVAL / UI_UPDATE_INTERVAL; ++i)
+ {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL));
+ statusHandler.requestUiRefresh();
+ }
}
}
diff --git a/RealtimeSync/watcher.h b/RealtimeSync/watcher.h
index cb39ed20..17252535 100644
--- a/RealtimeSync/watcher.h
+++ b/RealtimeSync/watcher.h
@@ -14,8 +14,7 @@
namespace rts
{
-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; //unit: [ms]; perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss
bool updateUiIsAllowed();
@@ -33,19 +32,22 @@ enum ChangeType
CHANGE_DETECTED,
CHANGE_DIR_MISSING
};
+
struct WaitResult
{
- WaitResult(ChangeType tp, const Zstring& chgFile = Zstring()) : type(tp), filename(chgFile) {}
+ WaitResult(ChangeType tp, const Zstring& chgFile) : type(tp), filename(chgFile) {}
ChangeType type;
- Zstring filename; //filled if type == CHANGE_DETECTED
+ Zstring filename; //file or directory name
};
-WaitResult waitForChanges(const std::vector<Zstring>& dirNamesNonFmt, //non-formatted dir names that yet require call to getFormattedDirectoryName()
- WaitCallback* statusHandler); //throw(FileError)
+
+WaitResult waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
+ //non-formatted dirnames that yet require call to getFormattedDirectoryName(); empty directories must be checked by caller!
+ WaitCallback& statusHandler); //throw FileError
//wait until all directories become available (again)
void waitForMissingDirs(const std::vector<Zstring>& dirNamesNonFmt,
- WaitCallback* statusHandler); //throw(FileError)
+ WaitCallback& statusHandler); //throw FileError
}
#endif // WATCHER_H_INCLUDED
diff --git a/RealtimeSync/xml_ffs.cpp b/RealtimeSync/xml_ffs.cpp
index 6ec5f843..6572800b 100644
--- a/RealtimeSync/xml_ffs.cpp
+++ b/RealtimeSync/xml_ffs.cpp
@@ -46,7 +46,7 @@ xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& bat
}
-void rts::readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config) //throw xmlAccess::FfsXmlError;
+void rts::readRealOrBatchConfig(const Zstring& filename, xmlAccess::XmlRealConfig& config) //throw xmlAccess::FfsXmlError;
{
if (xmlAccess::getXmlType(filename) != xmlAccess::XML_TYPE_BATCH)
{
@@ -63,11 +63,11 @@ void rts::readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConf
catch (const xmlAccess::FfsXmlError& e)
{
if (e.getSeverity() == xmlAccess::FfsXmlError::WARNING)
- config = convertBatchToReal(batchCfg, toZ(filename)); //do work despite parsing errors, then re-throw
+ config = convertBatchToReal(batchCfg, filename); //do work despite parsing errors, then re-throw
throw; //
}
- config = convertBatchToReal(batchCfg, toZ(filename));
+ config = convertBatchToReal(batchCfg, filename);
}
diff --git a/RealtimeSync/xml_ffs.h b/RealtimeSync/xml_ffs.h
index abff3c10..b63c3620 100644
--- a/RealtimeSync/xml_ffs.h
+++ b/RealtimeSync/xml_ffs.h
@@ -8,13 +8,14 @@
#define XMLFREEFILESYNC_H_INCLUDED
#include "xml_proc.h"
+#include <zen/zstring.h>
//reuse (some of) FreeFileSync's xml files
namespace rts
{
-void readRealOrBatchConfig(const wxString& filename, xmlAccess::XmlRealConfig& config); //throw (xmlAccess::FfsXmlError);
+void readRealOrBatchConfig(const Zstring& filename, xmlAccess::XmlRealConfig& config); //throw FfsXmlError
int getProgramLanguage();
}
diff --git a/RealtimeSync/xml_proc.cpp b/RealtimeSync/xml_proc.cpp
index 4f9306d2..891cb2df 100644
--- a/RealtimeSync/xml_proc.cpp
+++ b/RealtimeSync/xml_proc.cpp
@@ -36,22 +36,22 @@ bool isXmlTypeRTS(const XmlDoc& doc) //throw()
}
-void xmlAccess::readRealConfig(const wxString& filename, XmlRealConfig& config)
+void xmlAccess::readRealConfig(const Zstring& filename, XmlRealConfig& config)
{
- if (!fileExists(toZ(filename)))
- throw FfsXmlError(_("File does not exist:") + L"\n\"" + toZ(filename) + L"\"");
+ if (!fileExists(filename))
+ throw FfsXmlError(replaceCpy(_("Cannot find file %x."), L"%x", fmtFileName(filename)));
XmlDoc doc;
- loadXmlDocument(toZ(filename), doc); //throw (FfsXmlError)
+ loadXmlDocument(filename, doc); //throw FfsXmlError
if (!isXmlTypeRTS(doc))
- throw FfsXmlError(_("Error parsing configuration file:") + L"\n\"" + toZ(filename) + L"\"");
+ throw FfsXmlError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtFileName(filename)));
XmlIn in(doc);
::readConfig(in, config);
if (in.errorsOccured())
- throw FfsXmlError(_("Configuration loaded partially only:") + L"\n\"" + toZ(filename) + L"\"\n\n" +
+ throw FfsXmlError(replaceCpy(_("Configuration file %x loaded partially only."), L"%x", fmtFileName(filename)) + L"\n\n" +
getErrorMessageFormatted(in), FfsXmlError::WARNING);
}
@@ -67,7 +67,7 @@ void writeConfig(const XmlRealConfig& config, XmlOut& out)
}
-void xmlAccess::writeRealConfig(const XmlRealConfig& config, const wxString& filename)
+void xmlAccess::writeRealConfig(const XmlRealConfig& config, const Zstring& filename)
{
XmlDoc doc("FreeFileSync");
doc.root().setAttribute("XmlType", "REAL");
@@ -75,5 +75,5 @@ void xmlAccess::writeRealConfig(const XmlRealConfig& config, const wxString& fil
XmlOut out(doc);
writeConfig(config, out);
- saveXmlDocument(doc, toZ(filename)); //throw (FfsXmlError)
+ saveXmlDocument(doc, filename); //throw (FfsXmlError)
}
diff --git a/RealtimeSync/xml_proc.h b/RealtimeSync/xml_proc.h
index a2e178d4..e07f9844 100644
--- a/RealtimeSync/xml_proc.h
+++ b/RealtimeSync/xml_proc.h
@@ -9,6 +9,7 @@
#include <vector>
#include <wx/string.h>
+#include <zen/zstring.h>
#include "../lib/xml_base.h"
@@ -22,8 +23,8 @@ struct XmlRealConfig
size_t delay;
};
-void readRealConfig(const wxString& filename, XmlRealConfig& config); //throw (xmlAccess::FfsXmlError);
-void writeRealConfig(const XmlRealConfig& config, const wxString& filename); //throw (xmlAccess::FfsXmlError);
+void readRealConfig(const Zstring& filename, XmlRealConfig& config); //throw FfsXmlError
+void writeRealConfig(const XmlRealConfig& config, const Zstring& filename); //throw FfsXmlError
}
#endif // XMLPROCESSING_H_INCLUDED
bgstack15