summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:26:50 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:26:50 +0200
commit669df123648aaa6aeccc70206b5417bc48b4e9ae (patch)
tree463c107a8d6405020bb304f7a7253e6b64afeee0 /ui
parent5.18 (diff)
downloadFreeFileSync-669df123648aaa6aeccc70206b5417bc48b4e9ae.tar.gz
FreeFileSync-669df123648aaa6aeccc70206b5417bc48b4e9ae.tar.bz2
FreeFileSync-669df123648aaa6aeccc70206b5417bc48b4e9ae.zip
5.19
Diffstat (limited to 'ui')
-rw-r--r--ui/Taskbar_Seven/Taskbar_Seven.vcxproj8
-rw-r--r--ui/batch_status_handler.cpp15
-rw-r--r--ui/check_version.cpp4
-rw-r--r--ui/custom_grid.cpp12
-rw-r--r--ui/dir_name.cpp2
-rw-r--r--ui/gui_generated.cpp654
-rw-r--r--ui/gui_generated.h153
-rw-r--r--ui/gui_status_handler.cpp12
-rw-r--r--ui/gui_status_handler.h3
-rw-r--r--ui/main_dlg.cpp288
-rw-r--r--ui/main_dlg.h18
-rw-r--r--ui/msg_popup.h9
-rw-r--r--ui/progress_indicator.cpp979
-rw-r--r--ui/progress_indicator.h8
-rw-r--r--ui/small_dlgs.cpp15
-rw-r--r--ui/switch_to_gui.h2
-rw-r--r--ui/sync_cfg.cpp48
-rw-r--r--ui/taskbar.cpp10
-rw-r--r--ui/taskbar.h4
-rw-r--r--ui/tray_icon.cpp224
-rw-r--r--ui/tray_icon.h38
-rw-r--r--ui/tree_view.cpp6
22 files changed, 1421 insertions, 1091 deletions
diff --git a/ui/Taskbar_Seven/Taskbar_Seven.vcxproj b/ui/Taskbar_Seven/Taskbar_Seven.vcxproj
index 8b8ab5ce..02c4b67b 100644
--- a/ui/Taskbar_Seven/Taskbar_Seven.vcxproj
+++ b/ui/Taskbar_Seven/Taskbar_Seven.vcxproj
@@ -85,7 +85,7 @@
</BuildLog>
<ClCompile>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -120,7 +120,7 @@
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -153,7 +153,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
@@ -190,7 +190,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp
index 0dfd6957..a72aab3e 100644
--- a/ui/batch_status_handler.cpp
+++ b/ui/batch_status_handler.cpp
@@ -8,8 +8,9 @@
#include <zen/file_handling.h>
#include <zen/file_traverser.h>
#include <zen/format_unit.h>
-#include <wx+/app_main.h>
+//#include <wx+/app_main.h>
#include <wx+/shell_execute.h>
+#include <wx/app.h>
#include "msg_popup.h"
#include "exec_finished_box.h"
#include "../lib/ffs_paths.h"
@@ -217,7 +218,7 @@ BatchStatusHandler::~BatchStatusHandler()
}
else
{
- if (progressDlg->getAsWindow()->IsShown())
+ if (progressDlg->getWindowIfVisible())
showFinalResults = true;
//execute "on completion" command (even in case of ignored errors)
@@ -236,7 +237,7 @@ BatchStatusHandler::~BatchStatusHandler()
if (showFinalResults) //warning: wxWindow::Show() is called within processHasFinished()!
{
//notify about (logical) application main window => program won't quit, but stay on this dialog
- setMainWindow(progressDlg->getAsWindow());
+ //setMainWindow(progressDlg->getAsWindow()); -> not required anymore since we block waiting until dialog is closed below
//notify to progressDlg that current process has ended
if (abortIsRequested())
@@ -257,7 +258,7 @@ BatchStatusHandler::~BatchStatusHandler()
//-> nicely manages dialog lifetime
while (progressDlg)
{
- updateUiNow(); //*first* refresh GUI (removing flicker) before sleeping!
+ wxTheApp->Yield(); //*first* refresh GUI (removing flicker) before sleeping!
boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL));
}
}
@@ -306,7 +307,7 @@ void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool&
forceUiRefresh();
bool dontWarnAgain = false;
- switch (showWarningDlg(progressDlg->getAsWindow(),
+ switch (showWarningDlg(progressDlg->getWindowIfVisible(),
ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_SWITCH | ReturnWarningDlg::BUTTON_CANCEL,
warningMessage + L"\n\n" + _("Press \"Switch\" to resolve issues in FreeFileSync main dialog."),
dontWarnAgain))
@@ -352,7 +353,7 @@ ProcessCallback::Response BatchStatusHandler::reportError(const std::wstring& er
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(progressDlg->getAsWindow(),
+ switch (showErrorDlg(progressDlg->getWindowIfVisible(),
ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_CANCEL,
errorMessage, &ignoreNextErrors))
{
@@ -399,7 +400,7 @@ void BatchStatusHandler::reportFatalError(const std::wstring& errorMessage)
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showFatalErrorDlg(progressDlg->getAsWindow(),
+ switch (showFatalErrorDlg(progressDlg->getWindowIfVisible(),
ReturnFatalErrorDlg::BUTTON_IGNORE | ReturnFatalErrorDlg::BUTTON_CANCEL,
errorMessage, &ignoreNextErrors))
{
diff --git a/ui/check_version.cpp b/ui/check_version.cpp
index 2e4c387a..e51c1784 100644
--- a/ui/check_version.cpp
+++ b/ui/check_version.cpp
@@ -233,11 +233,11 @@ void zen::checkForUpdateNow(wxWindow* parent)
wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/get_latest.php");
}
else
- wxMessageBox(_("FreeFileSync is up to date."), _("Information"), wxOK | wxICON_INFORMATION, parent);
+ wxMessageBox(_("FreeFileSync is up to date."), L"FreeFileSync - " + _("Information"), wxOK | wxICON_INFORMATION, parent);
break;
case GET_VER_NO_CONNECTION:
- wxMessageBox(_("Unable to connect to sourceforge.net."), _("Error"), wxOK | wxICON_ERROR, parent);
+ wxMessageBox(_("Unable to connect to sourceforge.net."), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, parent);
break;
case GET_VER_PAGE_NOT_FOUND:
diff --git a/ui/custom_grid.cpp b/ui/custom_grid.cpp
index 58e7a7e4..59e80100 100644
--- a/ui/custom_grid.cpp
+++ b/ui/custom_grid.cpp
@@ -811,19 +811,19 @@ public:
break;
case BLOCKPOS_LEFT:
{
- SyncDirectionEvent evt(rowFirst, rowLast, SYNC_DIR_LEFT);
+ SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::LEFT);
evtHandler->ProcessEvent(evt);
}
break;
case BLOCKPOS_MIDDLE:
{
- SyncDirectionEvent evt(rowFirst, rowLast, SYNC_DIR_NONE);
+ SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::NONE);
evtHandler->ProcessEvent(evt);
}
break;
case BLOCKPOS_RIGHT:
{
- SyncDirectionEvent evt(rowFirst, rowLast, SYNC_DIR_RIGHT);
+ SyncDirectionEvent evt(rowFirst, rowLast, SyncDirection::RIGHT);
evtHandler->ProcessEvent(evt);
}
break;
@@ -983,13 +983,13 @@ private:
case BLOCKPOS_CHECK_BOX:
break;
case BLOCKPOS_LEFT:
- drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_LEFT)), rect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, buffer);
+ drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SyncDirection::LEFT)), rect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, buffer);
break;
case BLOCKPOS_MIDDLE:
- drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_NONE)), rect, wxALIGN_CENTER, buffer);
+ drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SyncDirection::NONE)), rect, wxALIGN_CENTER, buffer);
break;
case BLOCKPOS_RIGHT:
- drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_RIGHT)), rect, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, buffer);
+ drawBitmapRtlMirror(dc, getSyncOpImage(fsObj->testSyncOperation(SyncDirection::RIGHT)), rect, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, buffer);
break;
}
else //default
diff --git a/ui/dir_name.cpp b/ui/dir_name.cpp
index 4a3939e9..7a068343 100644
--- a/ui/dir_name.cpp
+++ b/ui/dir_name.cpp
@@ -227,7 +227,7 @@ void DirectoryName<NameControl>::onSelectDir(wxCommandEvent& event)
errorMsg); //out, optional: call freeString() after use!
if (errorMsg)
{
- wxMessageBox(errorMsg, _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(errorMsg, /*L"FreeFileSync - " +*/ _("Error"), wxOK | wxICON_ERROR); //component used by FFS *and* RTS!
return;
}
if (cancelled || !selectedFolder)
diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp
index 3549519c..21f5f82d 100644
--- a/ui/gui_generated.cpp
+++ b/ui/gui_generated.cpp
@@ -1098,6 +1098,9 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
bSizer42 = new wxBoxSizer( wxHORIZONTAL );
+ wxBoxSizer* bSizer162StretchSpeedAndRemTimeIndependently;
+ bSizer162StretchSpeedAndRemTimeIndependently = new wxBoxSizer( wxHORIZONTAL );
+
wxBoxSizer* bSizer157;
bSizer157 = new wxBoxSizer( wxVERTICAL );
@@ -1142,10 +1145,10 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
bSizer157->Add( bSizerFilesRemaining, 0, 0, 5 );
- bSizer42->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer162StretchSpeedAndRemTimeIndependently->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 );
- bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
+ bSizer162StretchSpeedAndRemTimeIndependently->Add( 0, 0, 1, wxEXPAND, 5 );
sSizerSpeed = new wxBoxSizer( wxHORIZONTAL );
@@ -1160,11 +1163,17 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
sSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
- bSizer42->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer162StretchSpeedAndRemTimeIndependently->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer42->Add( bSizer162StretchSpeedAndRemTimeIndependently, 1, wxALIGN_CENTER_VERTICAL, 5 );
bSizer42->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ wxBoxSizer* bSizer163;
+ bSizer163 = new wxBoxSizer( wxHORIZONTAL );
+
sSizerTimeRemaining = new wxBoxSizer( wxHORIZONTAL );
m_staticTextTimeRemFixed = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
@@ -1178,10 +1187,10 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
sSizerTimeRemaining->Add( m_staticTextRemTime, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
- bSizer42->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer163->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 );
- bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
+ bSizer163->Add( 0, 0, 1, wxEXPAND, 5 );
sSizerTimeElapsed = new wxBoxSizer( wxHORIZONTAL );
@@ -1197,7 +1206,10 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
sSizerTimeElapsed->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
- bSizer42->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer163->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer42->Add( bSizer163, 1, wxALIGN_CENTER_VERTICAL, 5 );
bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
@@ -1215,17 +1227,20 @@ CompareProgressDlgGenerated::~CompareProgressDlgGenerated()
{
}
-SyncProgressDlgGenerated::SyncProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
+SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
- this->SetSizeHints( wxSize( 470,260 ), wxDefaultSize );
- this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
-
bSizerRoot = new wxBoxSizer( wxVERTICAL );
bSizer42 = new wxBoxSizer( wxHORIZONTAL );
+
+ bSizer42->Add( 32, 0, 0, 0, 5 );
+
+
+ bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
+
m_bitmapStatus = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), 0 );
- bSizer42->Add( m_bitmapStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+ bSizer42->Add( m_bitmapStatus, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 );
m_staticTextPhase = new wxStaticText( this, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextPhase->Wrap( -1 );
@@ -1236,11 +1251,32 @@ SyncProgressDlgGenerated::SyncProgressDlgGenerated( wxWindow* parent, wxWindowID
m_animCtrlSyncing = new wxAnimationCtrl( this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 32,32 ), wxAC_DEFAULT_STYLE );
m_animCtrlSyncing->SetMinSize( wxSize( 32,32 ) );
- bSizer42->Add( m_animCtrlSyncing, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+ bSizer42->Add( m_animCtrlSyncing, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 );
- bSizerRoot->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 );
+ bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ m_bpButtonMinimizeToTray = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 32,32 ), wxBU_AUTODRAW );
+ m_bpButtonMinimizeToTray->SetToolTip( _("Minimize to notification area") );
+
+ bSizer42->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizerRoot->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 );
+
+ bSizerStatusText = new wxBoxSizer( wxVERTICAL );
+
+ m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextStatus->Wrap( -1 );
+ bSizerStatusText->Add( m_staticTextStatus, 0, wxEXPAND|wxLEFT, 10 );
+
+ bSizerStatusText->Add( 0, 5, 0, 0, 5 );
+
+
+ bSizerRoot->Add( bSizerStatusText, 0, wxEXPAND, 5 );
+
+ wxStaticLine* m_staticlineHeader;
m_staticlineHeader = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerRoot->Add( m_staticlineHeader, 0, wxEXPAND, 5 );
@@ -1250,101 +1286,181 @@ SyncProgressDlgGenerated::SyncProgressDlgGenerated( wxWindow* parent, wxWindowID
wxBoxSizer* bSizer173;
bSizer173 = new wxBoxSizer( wxVERTICAL );
- m_staticTextStatus = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextStatus->Wrap( -1 );
- bSizer173->Add( m_staticTextStatus, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
-
- m_gauge1 = new wxGauge( m_panelProgress, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL );
- bSizer173->Add( m_gauge1, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
-
bSizer171 = new wxBoxSizer( wxHORIZONTAL );
bSizer171->Add( 10, 0, 0, 0, 5 );
- wxFlexGridSizer* fgSizer10;
- fgSizer10 = new wxFlexGridSizer( 0, 2, 2, 5 );
- fgSizer10->SetFlexibleDirection( wxBOTH );
- fgSizer10->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+ wxBoxSizer* bSizer164;
+ bSizer164 = new wxBoxSizer( wxVERTICAL );
+
+ m_panelItemsProcessed = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+ m_panelItemsProcessed->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+
+ wxBoxSizer* bSizer165;
+ bSizer165 = new wxBoxSizer( wxVERTICAL );
- m_staticTextLabelItemsProc = new wxStaticText( m_panelProgress, wxID_ANY, _("Items processed:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextLabelItemsProc->Wrap( -1 );
- fgSizer10->Add( m_staticTextLabelItemsProc, 0, wxALIGN_BOTTOM, 5 );
- bSizerItemsProc = new wxBoxSizer( wxHORIZONTAL );
+ bSizer165->Add( 0, 5, 0, 0, 5 );
- m_staticTextProcessedObj = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ wxStaticText* m_staticText96;
+ m_staticText96 = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("Items processed:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText96->Wrap( -1 );
+ bSizer165->Add( m_staticText96, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+
+ wxBoxSizer* bSizer169;
+ bSizer169 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticTextProcessedObj = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_staticTextProcessedObj->Wrap( -1 );
m_staticTextProcessedObj->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizerItemsProc->Add( m_staticTextProcessedObj, 0, wxALIGN_BOTTOM, 5 );
+ bSizer169->Add( m_staticTextProcessedObj, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextDataProcessed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextDataProcessed = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextDataProcessed->Wrap( -1 );
- bSizerItemsProc->Add( m_staticTextDataProcessed, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
+ bSizer169->Add( m_staticTextDataProcessed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
+
+
+ bSizer165->Add( bSizer169, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+
+
+ bSizer165->Add( 0, 5, 0, 0, 5 );
+
+ m_panelItemsProcessed->SetSizer( bSizer165 );
+ m_panelItemsProcessed->Layout();
+ bSizer165->Fit( m_panelItemsProcessed );
+ bSizer164->Add( m_panelItemsProcessed, 0, wxEXPAND|wxTOP, 7 );
- fgSizer10->Add( bSizerItemsProc, 0, wxALIGN_BOTTOM, 5 );
+ m_panelItemsRemaining = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+ m_panelItemsRemaining->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
- m_staticTextLabelItemsRem = new wxStaticText( m_panelProgress, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextLabelItemsRem->Wrap( -1 );
- fgSizer10->Add( m_staticTextLabelItemsRem, 0, wxALIGN_BOTTOM, 5 );
+ wxBoxSizer* bSizer166;
+ bSizer166 = new wxBoxSizer( wxVERTICAL );
+
+
+ bSizer166->Add( 0, 5, 0, 0, 5 );
+
+ wxStaticText* m_staticText97;
+ m_staticText97 = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText97->Wrap( -1 );
+ bSizer166->Add( m_staticText97, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
- bSizerItemsRem = new wxBoxSizer( wxHORIZONTAL );
+ wxBoxSizer* bSizer170;
+ bSizer170 = new wxBoxSizer( wxHORIZONTAL );
- m_staticTextRemainingObj = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_staticTextRemainingObj = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_staticTextRemainingObj->Wrap( -1 );
m_staticTextRemainingObj->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizerItemsRem->Add( m_staticTextRemainingObj, 0, wxALIGN_BOTTOM, 5 );
+ bSizer170->Add( m_staticTextRemainingObj, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextDataRemaining = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextDataRemaining = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextDataRemaining->Wrap( -1 );
- bSizerItemsRem->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
+ bSizer170->Add( m_staticTextDataRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
- fgSizer10->Add( bSizerItemsRem, 0, wxALIGN_BOTTOM, 5 );
+ bSizer166->Add( bSizer170, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
- m_staticText84 = new wxStaticText( m_panelProgress, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText84->Wrap( -1 );
- fgSizer10->Add( m_staticText84, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextSpeed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextSpeed->Wrap( -1 );
- m_staticTextSpeed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
+ bSizer166->Add( 0, 5, 0, 0, 5 );
- fgSizer10->Add( m_staticTextSpeed, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextLabelRemTime = new wxStaticText( m_panelProgress, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextLabelRemTime->Wrap( -1 );
- fgSizer10->Add( m_staticTextLabelRemTime, 0, wxALIGN_BOTTOM, 5 );
+ m_panelItemsRemaining->SetSizer( bSizer166 );
+ m_panelItemsRemaining->Layout();
+ bSizer166->Fit( m_panelItemsRemaining );
+ bSizer164->Add( m_panelItemsRemaining, 0, wxTOP|wxEXPAND, 7 );
+
+ m_panelTimeRemaining = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+ m_panelTimeRemaining->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+
+ wxBoxSizer* bSizer167;
+ bSizer167 = new wxBoxSizer( wxVERTICAL );
- m_staticTextRemTime = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ bSizer167->Add( 0, 5, 0, 0, 5 );
+
+ wxStaticText* m_staticText98;
+ m_staticText98 = new wxStaticText( m_panelTimeRemaining, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText98->Wrap( -1 );
+ bSizer167->Add( m_staticText98, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+
+ m_staticTextRemTime = new wxStaticText( m_panelTimeRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextRemTime->Wrap( -1 );
m_staticTextRemTime->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- fgSizer10->Add( m_staticTextRemTime, 0, wxALIGN_BOTTOM, 5 );
+ bSizer167->Add( m_staticTextRemTime, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+
- m_staticTextLabelElapsedTime = new wxStaticText( m_panelProgress, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextLabelElapsedTime->Wrap( -1 );
- fgSizer10->Add( m_staticTextLabelElapsedTime, 0, wxALIGN_BOTTOM, 5 );
+ bSizer167->Add( 0, 5, 0, 0, 5 );
- m_staticTextTimeElapsed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ m_panelTimeRemaining->SetSizer( bSizer167 );
+ m_panelTimeRemaining->Layout();
+ bSizer167->Fit( m_panelTimeRemaining );
+ bSizer164->Add( m_panelTimeRemaining, 0, wxTOP|wxEXPAND, 7 );
+
+ wxPanel* m_panelTimeElapsed;
+ m_panelTimeElapsed = new wxPanel( m_panelProgress, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+ m_panelTimeElapsed->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+
+ wxBoxSizer* bSizer168;
+ bSizer168 = new wxBoxSizer( wxVERTICAL );
+
+
+ bSizer168->Add( 0, 5, 0, 0, 5 );
+
+ wxStaticText* m_staticText961;
+ m_staticText961 = new wxStaticText( m_panelTimeElapsed, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText961->Wrap( -1 );
+ bSizer168->Add( m_staticText961, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+
+ m_staticTextTimeElapsed = new wxStaticText( m_panelTimeElapsed, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextTimeElapsed->Wrap( -1 );
m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- fgSizer10->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM, 5 );
+ bSizer168->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+
+
+ bSizer168->Add( 0, 5, 0, 0, 5 );
+
+ m_panelTimeElapsed->SetSizer( bSizer168 );
+ m_panelTimeElapsed->Layout();
+ bSizer168->Fit( m_panelTimeElapsed );
+ bSizer164->Add( m_panelTimeElapsed, 0, wxTOP|wxEXPAND, 7 );
- bSizer171->Add( fgSizer10, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer171->Add( bSizer164, 0, wxALIGN_CENTER_VERTICAL, 5 );
bSizer171->Add( 10, 0, 0, 0, 5 );
- m_panelGraph = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( 340,150 ), wxTAB_TRAVERSAL );
- m_panelGraph->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+ wxBoxSizer* bSizer161;
+ bSizer161 = new wxBoxSizer( wxVERTICAL );
+
+
+ bSizer161->Add( 0, 15, 0, 0, 5 );
+
+ m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_panelGraphBytes->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+
+ bSizer161->Add( m_panelGraphBytes, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+
+ m_panelGraphItems = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_panelGraphItems->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+
+ bSizer161->Add( m_panelGraphItems, 1, wxEXPAND, 5 );
- bSizer171->Add( m_panelGraph, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP, 10 );
+
+ bSizer161->Add( 420, 0, 0, 0, 5 );
+
+
+ bSizer171->Add( bSizer161, 1, wxEXPAND, 5 );
+
+
+ bSizer171->Add( 0, 230, 0, 0, 5 );
bSizer173->Add( bSizer171, 1, wxEXPAND, 5 );
@@ -1404,26 +1520,10 @@ SyncProgressDlgGenerated::SyncProgressDlgGenerated( wxWindow* parent, wxWindowID
this->SetSizer( bSizerRoot );
this->Layout();
bSizerRoot->Fit( this );
-
- this->Centre( wxBOTH );
-
- // Connect Events
- this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncProgressDlgGenerated::OnClose ) );
- this->Connect( wxEVT_ICONIZE, wxIconizeEventHandler( SyncProgressDlgGenerated::OnIconize ) );
- m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncProgressDlgGenerated::OnOkay ), NULL, this );
- m_buttonPause->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncProgressDlgGenerated::OnPause ), NULL, this );
- m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncProgressDlgGenerated::OnCancel ), NULL, this );
}
-SyncProgressDlgGenerated::~SyncProgressDlgGenerated()
+SyncProgressPanelGenerated::~SyncProgressPanelGenerated()
{
- // Disconnect Events
- this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncProgressDlgGenerated::OnClose ) );
- this->Disconnect( wxEVT_ICONIZE, wxIconizeEventHandler( SyncProgressDlgGenerated::OnIconize ) );
- m_buttonClose->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncProgressDlgGenerated::OnOkay ), NULL, this );
- m_buttonPause->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncProgressDlgGenerated::OnPause ), NULL, this );
- m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncProgressDlgGenerated::OnCancel ), NULL, this );
-
}
LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
@@ -1439,13 +1539,13 @@ LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxP
wxBoxSizer* bSizer154;
bSizer154 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonErrors = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), wxBU_AUTODRAW );
+ m_bpButtonErrors = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW );
bSizer154->Add( m_bpButtonErrors, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonWarnings = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), wxBU_AUTODRAW );
+ m_bpButtonWarnings = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW );
bSizer154->Add( m_bpButtonWarnings, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonInfo = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), wxBU_AUTODRAW );
+ m_bpButtonInfo = new ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 49,49 ), wxBU_AUTODRAW );
bSizer154->Add( m_bpButtonInfo, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -1481,6 +1581,200 @@ LogPanelGenerated::~LogPanelGenerated()
}
+SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
+{
+ this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+ this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+
+ wxBoxSizer* bSizer134;
+ bSizer134 = new wxBoxSizer( wxVERTICAL );
+
+ m_panelStatistics = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+
+ wxBoxSizer* bSizer169;
+ bSizer169 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bitmapSync = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer169->Add( m_bitmapSync, 0, wxALL, 10 );
+
+ m_staticline39 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+ bSizer169->Add( m_staticline39, 0, wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer162;
+ bSizer162 = new wxBoxSizer( wxVERTICAL );
+
+ wxBoxSizer* bSizer172;
+ bSizer172 = new wxBoxSizer( wxVERTICAL );
+
+ m_staticText84 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Variant"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText84->Wrap( -1 );
+ bSizer172->Add( m_staticText84, 0, wxALL, 5 );
+
+ m_staticTextVariant = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextVariant->Wrap( -1 );
+ m_staticTextVariant->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
+
+ bSizer172->Add( m_staticTextVariant, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+
+
+ bSizer172->Add( 0, 10, 0, 0, 5 );
+
+
+ bSizer162->Add( bSizer172, 0, wxEXPAND, 5 );
+
+ m_staticline14 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer162->Add( m_staticline14, 0, wxEXPAND, 5 );
+
+ m_staticText83 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Statistics"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText83->Wrap( -1 );
+ bSizer162->Add( m_staticText83, 0, wxALL, 5 );
+
+ wxFlexGridSizer* fgSizer11;
+ fgSizer11 = new wxFlexGridSizer( 2, 7, 2, 5 );
+ fgSizer11->SetFlexibleDirection( wxBOTH );
+ fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+ m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") );
+
+ fgSizer11->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be overwritten") );
+
+ fgSizer11->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") );
+
+ fgSizer11->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapData->SetToolTip( _("Total bytes to copy") );
+
+ fgSizer11->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") );
+
+ fgSizer11->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapUpdateRight->SetToolTip( _("Number of files that will be overwritten") );
+
+ fgSizer11->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") );
+
+ fgSizer11->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextCreateLeft->Wrap( -1 );
+ m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") );
+
+ fgSizer11->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextUpdateLeft->Wrap( -1 );
+ m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be overwritten") );
+
+ fgSizer11->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextDeleteLeft->Wrap( -1 );
+ m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") );
+
+ fgSizer11->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextData->Wrap( -1 );
+ m_staticTextData->SetToolTip( _("Total bytes to copy") );
+
+ fgSizer11->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextDeleteRight->Wrap( -1 );
+ m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") );
+
+ fgSizer11->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextUpdateRight->Wrap( -1 );
+ m_staticTextUpdateRight->SetToolTip( _("Number of files that will be overwritten") );
+
+ fgSizer11->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextCreateRight->Wrap( -1 );
+ m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") );
+
+ fgSizer11->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer162->Add( fgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 25 );
+
+
+ bSizer162->Add( 0, 5, 0, 0, 5 );
+
+
+ bSizer169->Add( bSizer162, 0, 0, 5 );
+
+
+ m_panelStatistics->SetSizer( bSizer169 );
+ m_panelStatistics->Layout();
+ bSizer169->Fit( m_panelStatistics );
+ bSizer134->Add( m_panelStatistics, 0, wxEXPAND, 5 );
+
+ m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer164;
+ bSizer164 = new wxBoxSizer( wxVERTICAL );
+
+ m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer164->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 );
+
+ bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
+
+ m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonStartSync->SetDefault();
+ m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
+
+ bSizerStdButtons->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
+
+
+ bSizer164->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
+
+
+ bSizer134->Add( bSizer164, 1, wxEXPAND, 5 );
+
+
+ this->SetSizer( bSizer134 );
+ this->Layout();
+ bSizer134->Fit( this );
+
+ this->Centre( wxBOTH );
+
+ // Connect Events
+ this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::OnClose ) );
+ m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnStartSync ), NULL, this );
+ m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnCancel ), NULL, this );
+}
+
+SyncConfirmationDlgGenerated::~SyncConfirmationDlgGenerated()
+{
+ // Disconnect Events
+ this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::OnClose ) );
+ m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnStartSync ), NULL, this );
+ m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnCancel ), NULL, this );
+
+}
+
CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
@@ -3191,200 +3485,6 @@ GlobalSettingsDlgGenerated::~GlobalSettingsDlgGenerated()
}
-SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
-{
- this->SetSizeHints( wxDefaultSize, wxDefaultSize );
- this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
-
- wxBoxSizer* bSizer134;
- bSizer134 = new wxBoxSizer( wxVERTICAL );
-
- m_panelStatistics = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
- m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
-
- wxBoxSizer* bSizer169;
- bSizer169 = new wxBoxSizer( wxHORIZONTAL );
-
- m_bitmapSync = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- bSizer169->Add( m_bitmapSync, 0, wxALL, 10 );
-
- m_staticline39 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
- bSizer169->Add( m_staticline39, 0, wxEXPAND, 5 );
-
- wxBoxSizer* bSizer162;
- bSizer162 = new wxBoxSizer( wxVERTICAL );
-
- wxBoxSizer* bSizer172;
- bSizer172 = new wxBoxSizer( wxVERTICAL );
-
- m_staticText84 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Variant"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText84->Wrap( -1 );
- bSizer172->Add( m_staticText84, 0, wxALL, 5 );
-
- m_staticTextVariant = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextVariant->Wrap( -1 );
- m_staticTextVariant->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
-
- bSizer172->Add( m_staticTextVariant, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
-
-
- bSizer172->Add( 0, 10, 0, 0, 5 );
-
-
- bSizer162->Add( bSizer172, 0, wxEXPAND, 5 );
-
- m_staticline14 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizer162->Add( m_staticline14, 0, wxEXPAND, 5 );
-
- m_staticText83 = new wxStaticText( m_panelStatistics, wxID_ANY, _("Statistics"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText83->Wrap( -1 );
- bSizer162->Add( m_staticText83, 0, wxALL, 5 );
-
- wxFlexGridSizer* fgSizer11;
- fgSizer11 = new wxFlexGridSizer( 2, 7, 2, 5 );
- fgSizer11->SetFlexibleDirection( wxBOTH );
- fgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
-
- m_bitmapCreateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapCreateLeft->SetToolTip( _("Number of files and folders that will be created") );
-
- fgSizer11->Add( m_bitmapCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_bitmapUpdateLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapUpdateLeft->SetToolTip( _("Number of files that will be overwritten") );
-
- fgSizer11->Add( m_bitmapUpdateLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapDeleteLeft = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") );
-
- fgSizer11->Add( m_bitmapDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapData = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapData->SetToolTip( _("Total bytes to copy") );
-
- fgSizer11->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_bitmapDeleteRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") );
-
- fgSizer11->Add( m_bitmapDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapUpdateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapUpdateRight->SetToolTip( _("Number of files that will be overwritten") );
-
- fgSizer11->Add( m_bitmapUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_bitmapCreateRight = new wxStaticBitmap( m_panelStatistics, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
- m_bitmapCreateRight->SetToolTip( _("Number of files and folders that will be created") );
-
- fgSizer11->Add( m_bitmapCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_staticTextCreateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextCreateLeft->Wrap( -1 );
- m_staticTextCreateLeft->SetToolTip( _("Number of files and folders that will be created") );
-
- fgSizer11->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_staticTextUpdateLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextUpdateLeft->Wrap( -1 );
- m_staticTextUpdateLeft->SetToolTip( _("Number of files that will be overwritten") );
-
- fgSizer11->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_staticTextDeleteLeft = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextDeleteLeft->Wrap( -1 );
- m_staticTextDeleteLeft->SetToolTip( _("Number of files and folders that will be deleted") );
-
- fgSizer11->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticTextData = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextData->Wrap( -1 );
- m_staticTextData->SetToolTip( _("Total bytes to copy") );
-
- fgSizer11->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticTextDeleteRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextDeleteRight->Wrap( -1 );
- m_staticTextDeleteRight->SetToolTip( _("Number of files and folders that will be deleted") );
-
- fgSizer11->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticTextUpdateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextUpdateRight->Wrap( -1 );
- m_staticTextUpdateRight->SetToolTip( _("Number of files that will be overwritten") );
-
- fgSizer11->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticTextCreateRight = new wxStaticText( m_panelStatistics, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextCreateRight->Wrap( -1 );
- m_staticTextCreateRight->SetToolTip( _("Number of files and folders that will be created") );
-
- fgSizer11->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
-
- bSizer162->Add( fgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 25 );
-
-
- bSizer162->Add( 0, 5, 0, 0, 5 );
-
-
- bSizer169->Add( bSizer162, 0, 0, 5 );
-
-
- m_panelStatistics->SetSizer( bSizer169 );
- m_panelStatistics->Layout();
- bSizer169->Fit( m_panelStatistics );
- bSizer134->Add( m_panelStatistics, 0, wxEXPAND, 5 );
-
- m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizer134->Add( m_staticline12, 0, wxEXPAND, 5 );
-
- wxBoxSizer* bSizer164;
- bSizer164 = new wxBoxSizer( wxVERTICAL );
-
- m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Don't show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 );
- bSizer164->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 );
-
- bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
-
- m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,30 ), 0 );
- m_buttonStartSync->SetDefault();
- m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
-
- bSizerStdButtons->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
-
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
- bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
-
-
- bSizer164->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
-
-
- bSizer134->Add( bSizer164, 1, wxEXPAND, 5 );
-
-
- this->SetSizer( bSizer134 );
- this->Layout();
- bSizer134->Fit( this );
-
- this->Centre( wxBOTH );
-
- // Connect Events
- this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::OnClose ) );
- m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnStartSync ), NULL, this );
- m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnCancel ), NULL, this );
-}
-
-SyncConfirmationDlgGenerated::~SyncConfirmationDlgGenerated()
-{
- // Disconnect Events
- this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncConfirmationDlgGenerated::OnClose ) );
- m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnStartSync ), NULL, this );
- m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncConfirmationDlgGenerated::OnCancel ), NULL, this );
-
-}
-
PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
diff --git a/ui/gui_generated.h b/ui/gui_generated.h
index 27395e33..f06ebf93 100644
--- a/ui/gui_generated.h
+++ b/ui/gui_generated.h
@@ -45,9 +45,9 @@ namespace zen{ class TripleSplitter; }
#include <wx/gauge.h>
#include <wx/animate.h>
#include <wx/notebook.h>
+#include <wx/dialog.h>
#include <wx/tglbtn.h>
#include <wx/choice.h>
-#include <wx/dialog.h>
#include <wx/spinctrl.h>
#include <wx/hyperlink.h>
#include <wx/grid.h>
@@ -290,61 +290,48 @@ class CompareProgressDlgGenerated : public wxPanel
};
///////////////////////////////////////////////////////////////////////////////
-/// Class SyncProgressDlgGenerated
+/// Class SyncProgressPanelGenerated
///////////////////////////////////////////////////////////////////////////////
-class SyncProgressDlgGenerated : public wxFrame
+class SyncProgressPanelGenerated : public wxPanel
{
private:
protected:
- wxBoxSizer* bSizerRoot;
wxBoxSizer* bSizer42;
+ wxBoxSizer* bSizer171;
+ wxStaticText* m_staticText87;
+
+ public:
+ wxBoxSizer* bSizerRoot;
wxStaticBitmap* m_bitmapStatus;
wxStaticText* m_staticTextPhase;
wxAnimationCtrl* m_animCtrlSyncing;
- wxStaticLine* m_staticlineHeader;
- wxPanel* m_panelProgress;
+ wxBitmapButton* m_bpButtonMinimizeToTray;
+ wxBoxSizer* bSizerStatusText;
wxStaticText* m_staticTextStatus;
- wxBoxSizer* bSizer171;
- wxStaticText* m_staticTextLabelItemsProc;
- wxBoxSizer* bSizerItemsProc;
+ wxPanel* m_panelProgress;
+ wxPanel* m_panelItemsProcessed;
wxStaticText* m_staticTextProcessedObj;
wxStaticText* m_staticTextDataProcessed;
- wxStaticText* m_staticTextLabelItemsRem;
- wxBoxSizer* bSizerItemsRem;
+ wxPanel* m_panelItemsRemaining;
wxStaticText* m_staticTextRemainingObj;
wxStaticText* m_staticTextDataRemaining;
- wxStaticText* m_staticText84;
- wxStaticText* m_staticTextSpeed;
- wxStaticText* m_staticTextLabelRemTime;
+ wxPanel* m_panelTimeRemaining;
wxStaticText* m_staticTextRemTime;
- wxStaticText* m_staticTextLabelElapsedTime;
wxStaticText* m_staticTextTimeElapsed;
- zen::Graph2D* m_panelGraph;
+ zen::Graph2D* m_panelGraphBytes;
+ zen::Graph2D* m_panelGraphItems;
wxNotebook* m_notebookResult;
wxStaticLine* m_staticlineFooter;
wxBoxSizer* bSizerStdButtons;
wxBoxSizer* bSizerExecFinished;
- wxStaticText* m_staticText87;
ExecFinishedBox* m_comboBoxExecFinished;
wxButton* m_buttonClose;
wxButton* m_buttonPause;
wxButton* m_buttonCancel;
- // Virtual event handlers, overide them in your derived class
- virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
- virtual void OnIconize( wxIconizeEvent& event ) { event.Skip(); }
- virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnPause( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
-
-
- public:
- wxGauge* m_gauge1;
-
- SyncProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
-
- ~SyncProgressDlgGenerated();
+ SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
+ ~SyncProgressPanelGenerated();
};
@@ -376,6 +363,54 @@ class LogPanelGenerated : public wxPanel
};
///////////////////////////////////////////////////////////////////////////////
+/// Class SyncConfirmationDlgGenerated
+///////////////////////////////////////////////////////////////////////////////
+class SyncConfirmationDlgGenerated : public wxDialog
+{
+ private:
+
+ protected:
+ wxPanel* m_panelStatistics;
+ wxStaticBitmap* m_bitmapSync;
+ wxStaticLine* m_staticline39;
+ wxStaticText* m_staticText84;
+ wxStaticText* m_staticTextVariant;
+ wxStaticLine* m_staticline14;
+ wxStaticText* m_staticText83;
+ wxStaticBitmap* m_bitmapCreateLeft;
+ wxStaticBitmap* m_bitmapUpdateLeft;
+ wxStaticBitmap* m_bitmapDeleteLeft;
+ wxStaticBitmap* m_bitmapData;
+ wxStaticBitmap* m_bitmapDeleteRight;
+ wxStaticBitmap* m_bitmapUpdateRight;
+ wxStaticBitmap* m_bitmapCreateRight;
+ wxStaticText* m_staticTextCreateLeft;
+ wxStaticText* m_staticTextUpdateLeft;
+ wxStaticText* m_staticTextDeleteLeft;
+ wxStaticText* m_staticTextData;
+ wxStaticText* m_staticTextDeleteRight;
+ wxStaticText* m_staticTextUpdateRight;
+ wxStaticText* m_staticTextCreateRight;
+ wxStaticLine* m_staticline12;
+ wxCheckBox* m_checkBoxDontShowAgain;
+ wxBoxSizer* bSizerStdButtons;
+ wxButton* m_buttonStartSync;
+ wxButton* m_buttonCancel;
+
+ // Virtual event handlers, overide them in your derived class
+ virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
+ virtual void OnStartSync( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
+
+
+ public:
+
+ SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Start synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
+ ~SyncConfirmationDlgGenerated();
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
/// Class CmpCfgDlgGenerated
///////////////////////////////////////////////////////////////////////////////
class CmpCfgDlgGenerated : public wxDialog
@@ -571,7 +606,7 @@ class BatchDlgGenerated : public wxDialog
public:
FolderHistoryBox* m_logfileDir;
- BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Save as batch job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER );
+ BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Save as batch job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~BatchDlgGenerated();
};
@@ -664,7 +699,7 @@ class MessageDlgGenerated : public wxDialog
public:
- MessageDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER );
+ MessageDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~MessageDlgGenerated();
};
@@ -698,7 +733,7 @@ class DeleteDlgGenerated : public wxDialog
public:
- DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER );
+ DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Delete"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~DeleteDlgGenerated();
};
@@ -756,7 +791,7 @@ class FilterDlgGenerated : public wxDialog
public:
- FilterDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Configure filter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER );
+ FilterDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Configure filter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~FilterDlgGenerated();
};
@@ -810,54 +845,6 @@ class GlobalSettingsDlgGenerated : public wxDialog
};
///////////////////////////////////////////////////////////////////////////////
-/// Class SyncConfirmationDlgGenerated
-///////////////////////////////////////////////////////////////////////////////
-class SyncConfirmationDlgGenerated : public wxDialog
-{
- private:
-
- protected:
- wxPanel* m_panelStatistics;
- wxStaticBitmap* m_bitmapSync;
- wxStaticLine* m_staticline39;
- wxStaticText* m_staticText84;
- wxStaticText* m_staticTextVariant;
- wxStaticLine* m_staticline14;
- wxStaticText* m_staticText83;
- wxStaticBitmap* m_bitmapCreateLeft;
- wxStaticBitmap* m_bitmapUpdateLeft;
- wxStaticBitmap* m_bitmapDeleteLeft;
- wxStaticBitmap* m_bitmapData;
- wxStaticBitmap* m_bitmapDeleteRight;
- wxStaticBitmap* m_bitmapUpdateRight;
- wxStaticBitmap* m_bitmapCreateRight;
- wxStaticText* m_staticTextCreateLeft;
- wxStaticText* m_staticTextUpdateLeft;
- wxStaticText* m_staticTextDeleteLeft;
- wxStaticText* m_staticTextData;
- wxStaticText* m_staticTextDeleteRight;
- wxStaticText* m_staticTextUpdateRight;
- wxStaticText* m_staticTextCreateRight;
- wxStaticLine* m_staticline12;
- wxCheckBox* m_checkBoxDontShowAgain;
- wxBoxSizer* bSizerStdButtons;
- wxButton* m_buttonStartSync;
- wxButton* m_buttonCancel;
-
- // Virtual event handlers, overide them in your derived class
- virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
- virtual void OnStartSync( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
-
-
- public:
-
- SyncConfirmationDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Start synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
- ~SyncConfirmationDlgGenerated();
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
/// Class PopupDialogGenerated
///////////////////////////////////////////////////////////////////////////////
class PopupDialogGenerated : public wxDialog
diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp
index db92c24c..0131af3f 100644
--- a/ui/gui_status_handler.cpp
+++ b/ui/gui_status_handler.cpp
@@ -8,6 +8,7 @@
#include <wx/wupdlock.h>
#include <wx+/shell_execute.h>
#include <wx+/button.h>
+#include <wx/app.h>
#include "msg_popup.h"
#include "main_dlg.h"
#include "exec_finished_box.h"
@@ -169,13 +170,12 @@ void CompareStatusHandler::abortThisProcess()
//########################################################################################################
-SyncStatusHandler::SyncStatusHandler(wxTopLevelWindow* parentDlg,
+SyncStatusHandler::SyncStatusHandler(wxFrame* parentDlg,
size_t lastSyncsLogFileSizeMax,
OnGuiError handleError,
const std::wstring& jobName,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory) :
- parentDlg_(parentDlg),
progressDlg(createProgressDialog(*this, [this] { this->onProgressDialogTerminate(); }, *this, parentDlg, true, jobName, execWhenFinished, execFinishedHistory)),
lastSyncsLogFileSizeMax_(lastSyncsLogFileSizeMax),
handleError_(handleError),
@@ -267,7 +267,7 @@ SyncStatusHandler::~SyncStatusHandler()
//-> nicely manages dialog lifetime
while (progressDlg)
{
- updateUiNow(); //*first* refresh GUI (removing flicker) before sleeping!
+ wxTheApp->Yield(); //*first* refresh GUI (removing flicker) before sleeping!
boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL));
}
}
@@ -313,7 +313,7 @@ ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& err
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(parentDlg_,
+ switch (showErrorDlg(progressDlg->getWindowIfVisible(),
ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_CANCEL,
errorMessage,
&ignoreNextErrors))
@@ -357,7 +357,7 @@ void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage)
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showFatalErrorDlg(parentDlg_,
+ switch (showFatalErrorDlg(progressDlg->getWindowIfVisible(),
ReturnFatalErrorDlg::BUTTON_IGNORE | ReturnFatalErrorDlg::BUTTON_CANCEL,
errorMessage, &ignoreNextErrors))
{
@@ -395,7 +395,7 @@ void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool&
forceUiRefresh();
bool dontWarnAgain = false;
- switch (showWarningDlg(parentDlg_,
+ switch (showWarningDlg(progressDlg->getWindowIfVisible(),
ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_CANCEL,
warningMessage, dontWarnAgain))
{
diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h
index f7b58f05..30efe3fb 100644
--- a/ui/gui_status_handler.h
+++ b/ui/gui_status_handler.h
@@ -49,7 +49,7 @@ private:
class SyncStatusHandler : public zen::StatusHandler
{
public:
- SyncStatusHandler(wxTopLevelWindow* parentDlg,
+ SyncStatusHandler(wxFrame* parentDlg,
size_t lastSyncsLogFileSizeMax,
xmlAccess::OnGuiError handleError,
const std::wstring& jobName,
@@ -70,7 +70,6 @@ private:
virtual void abortThisProcess(); //throw GuiAbortProcess
void onProgressDialogTerminate();
- wxTopLevelWindow* parentDlg_;
SyncProgressDialog* progressDlg; //managed to have shorter lifetime than this handler!
const size_t lastSyncsLogFileSizeMax_;
xmlAccess::OnGuiError handleError_;
diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp
index ead99c6a..eaae0545 100644
--- a/ui/main_dlg.cpp
+++ b/ui/main_dlg.cpp
@@ -8,7 +8,6 @@
#include <zen/format_unit.h>
#include <zen/file_handling.h>
#include <zen/serialize.h>
-//#include <zen/file_id.h>
//#include <zen/perf.h>
#include <zen/thread.h>
#include <wx/clipbrd.h>
@@ -97,23 +96,26 @@ public:
virtual bool acceptDrop(const std::vector<wxString>& droppedFiles, const wxPoint& clientPos, const wxWindow& wnd)
{
- if (droppedFiles.empty())
+ if (std::any_of(droppedFiles.begin(), droppedFiles.end(), [](const wxString& filename)
+ {
+ using namespace xmlAccess;
+ switch (getXmlType(utfCvrtTo<Zstring>(filename))) //throw()
+ {
+ case XML_TYPE_GUI:
+ case XML_TYPE_BATCH:
+ return true;
+ case XML_TYPE_GLOBAL:
+ case XML_TYPE_OTHER:
+ break;
+ }
return false;
-
- switch (xmlAccess::getMergeType(toZ(droppedFiles))) //throw()
+ }))
{
- case xmlAccess::MERGE_BATCH:
- case xmlAccess::MERGE_GUI:
- case xmlAccess::MERGE_GUI_BATCH:
- mainDlg_.loadConfiguration(toZ(droppedFiles));
- return false;
-
- case xmlAccess::MERGE_OTHER:
- //=> return true: change directory selection via drag and drop
- break;
+ mainDlg_.loadConfiguration(toZ(droppedFiles));
+ return false;
}
- //mainDlg_.clearGrid();
+ //=> return true: change directory selection via drag and drop
return true;
}
@@ -321,51 +323,43 @@ xmlAccess::XmlGlobalSettings retrieveGlobalCfgFromDisk() //blocks on GUI on erro
{
assert(false);
if (e.getSeverity() != FfsXmlError::WARNING) //ignore parsing errors: should be migration problems only *cross-fingers*
- wxMessageBox(e.toString(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(e.toString(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR);
}
return globalCfg;
}
}
-void MainDialog::create(const std::vector<Zstring>& cfgFileNames)
+void MainDialog::create()
{
using namespace xmlAccess;
const XmlGlobalSettings globalSettings = retrieveGlobalCfgFromDisk();
- std::vector<Zstring> filenames;
- if (!cfgFileNames.empty()) //1. this one has priority
- filenames = cfgFileNames;
- else //FFS default startup: use last used selection
- {
- filenames = globalSettings.gui.lastUsedConfigFiles; //2. now try last used files
-
- //------------------------------------------------------------------------------------------
- //check existence of all directories in parallel!
+ std::vector<Zstring> filenames = globalSettings.gui.lastUsedConfigFiles; //2. now try last used files
- RunUntilFirstHit<NullType> findFirstMissing;
+ //------------------------------------------------------------------------------------------
+ //check existence of all files in parallel:
+ RunUntilFirstHit<NullType> findFirstMissing;
- std::for_each(filenames.begin(), filenames.end(), [&](const Zstring& filename)
- {
- findFirstMissing.addJob([=] { return filename.empty() /*ever empty??*/ || !fileExists(filename) ? zen::make_unique<NullType>() : nullptr; });
- });
- //potentially slow network access: give all checks 500ms to finish
- const bool allFilesExist = findFirstMissing.timedWait(boost::posix_time::milliseconds(500)) && //false: time elapsed
- !findFirstMissing.get(); //no missing
- if (!allFilesExist)
- filenames.clear(); //we do NOT want to show an error due to last config file missing on application start!
- //------------------------------------------------------------------------------------------
+ std::for_each(filenames.begin(), filenames.end(), [&](const Zstring& filename)
+ {
+ findFirstMissing.addJob([=] { return filename.empty() /*ever empty??*/ || !fileExists(filename) ? zen::make_unique<NullType>() : nullptr; });
+ });
+ //potentially slow network access: give all checks 500ms to finish
+ const bool allFilesExist = findFirstMissing.timedWait(boost::posix_time::milliseconds(500)) && //false: time elapsed
+ !findFirstMissing.get(); //no missing
+ if (!allFilesExist)
+ filenames.clear(); //we do NOT want to show an error due to last config file missing on application start!
+ //------------------------------------------------------------------------------------------
- if (filenames.empty())
- {
- if (zen::fileExists(lastRunConfigName())) //3. try to load auto-save config
- filenames.push_back(lastRunConfigName());
- }
+ if (filenames.empty())
+ {
+ if (zen::fileExists(lastRunConfigName())) //3. try to load auto-save config
+ filenames.push_back(lastRunConfigName());
}
XmlGuiConfig guiCfg; //structure to receive gui settings with default values
- bool loadCfgSuccess = false;
if (filenames.empty())
{
//add default exclusion filter: this is only ever relevant when creating new configurations!
@@ -379,58 +373,40 @@ void MainDialog::create(const std::vector<Zstring>& cfgFileNames)
try
{
readAnyConfig(filenames, guiCfg); //throw FfsXmlError
- loadCfgSuccess = true;
}
catch (const FfsXmlError& error)
{
if (error.getSeverity() == FfsXmlError::WARNING)
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING);
+ wxMessageBox(error.toString(), L"FreeFileSync - " + _("Warning"), wxOK | wxICON_WARNING);
//what about simulating changed config on parsing errors????
else
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR);
}
- const bool startComparisonImmediately = !cfgFileNames.empty() && loadCfgSuccess;
-
//------------------------------------------------------------------------------------------
- create_impl(guiCfg, filenames, globalSettings, startComparisonImmediately);
-}
-
-
-void MainDialog::create(const xmlAccess::XmlGuiConfig& guiCfg,
- bool startComparison)
-{
- create_impl(guiCfg, std::vector<Zstring>(), retrieveGlobalCfgFromDisk(), startComparison);
+ create(guiCfg, filenames, &globalSettings, false);
}
void MainDialog::create(const xmlAccess::XmlGuiConfig& guiCfg,
const std::vector<Zstring>& referenceFiles,
- const xmlAccess::XmlGlobalSettings& globalSettings,
+ const xmlAccess::XmlGlobalSettings* globalSettings,
bool startComparison)
{
- create_impl(guiCfg, referenceFiles, globalSettings, startComparison);
-}
-
-
-void MainDialog::create_impl(const xmlAccess::XmlGuiConfig& guiCfg,
- const std::vector<Zstring>& referenceFiles,
- const xmlAccess::XmlGlobalSettings& globalSettings,
- bool startComparison)
-{
+ const xmlAccess::XmlGlobalSettings& globSett = globalSettings ? *globalSettings : retrieveGlobalCfgFromDisk();
try
{
//we need to set language *before* creating MainDialog!
- setLanguage(globalSettings.programLanguage); //throw FileError
+ setLanguage(globSett.programLanguage); //throw FileError
}
catch (const FileError& e)
{
- wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(e.toString().c_str(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR);
//continue!
}
- MainDialog* frame = new MainDialog(guiCfg, referenceFiles, globalSettings, startComparison);
+ MainDialog* frame = new MainDialog(guiCfg, referenceFiles, globSett, startComparison);
frame->Show();
}
@@ -757,7 +733,7 @@ MainDialog::~MainDialog()
}
catch (const xmlAccess::FfsXmlError& e)
{
- wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(e.toString().c_str(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, this);
}
try //save "LastRun.ffs_gui"
@@ -1026,7 +1002,7 @@ void MainDialog::copySelectionToClipboard(const std::vector<const Grid*>& gridRe
}
catch (const std::bad_alloc& e)
{
- wxMessageBox(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, this);
}
}
@@ -1064,10 +1040,9 @@ std::vector<FileSystemObject*> MainDialog::getTreeSelection() const
if (auto root = dynamic_cast<const TreeView::RootNode*>(node.get()))
{
//select first level of child elements
- std::transform(root->baseDirObj_.refSubDirs ().begin(), root->baseDirObj_.refSubDirs ().end(), std::back_inserter(output), [](FileSystemObject& fsObj) { return &fsObj; });
- std::transform(root->baseDirObj_.refSubFiles().begin(), root->baseDirObj_.refSubFiles().end(), std::back_inserter(output), [](FileSystemObject& fsObj) { return &fsObj; });
- std::transform(root->baseDirObj_.refSubLinks().begin(), root->baseDirObj_.refSubLinks().end(), std::back_inserter(output), [](FileSystemObject& fsObj) { return &fsObj; });
- //for (auto& fsObj : root->baseDirObj_.refSubLinks()) output.push_back(&fsObj); -> seriously MSVC, stop this disgrace and implement "range for"!
+ for (auto& fsObj : root->baseDirObj_.refSubDirs ()) output.push_back(&fsObj);
+ for (auto& fsObj : root->baseDirObj_.refSubFiles()) output.push_back(&fsObj);
+ for (auto& fsObj : root->baseDirObj_.refSubLinks()) output.push_back(&fsObj);
}
else if (auto dir = dynamic_cast<const TreeView::DirNode*>(node.get()))
output.push_back(&(dir->dirObj_));
@@ -1170,7 +1145,7 @@ private:
{
//std::wstring msg = toGuiString(deletionCount) +
mainDlg.setStatusBarFullText(statusMsg);
- updateUiNow();
+ wxTheApp->Yield();
}
//context: C callstack message loop => throw()!
@@ -1314,6 +1289,31 @@ void MainDialog::openExternalApplication(const wxString& commandline, const std:
}
}
+ const size_t massInvokeThreshold = 10; //more than this is likely a user mistake
+
+ if (selectionTmp.size() > massInvokeThreshold)
+ if (globalCfg.optDialogs.confirmExternalCommandMassInvoke)
+ {
+ bool dontAskAgain = false;
+ switch (showQuestionDlg(this,
+ ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL,
+ replaceCpy(replaceCpy(_P("Do you really want to execute the command %y for 1 item?",
+ "Do you really want to execute the command %y for %x items?", selectionTmp.size()),
+ L"%x", toGuiString(selectionTmp.size())), L"%y", L'\'' + commandline + L'\''),
+ QuestConfig().setCaption(_("Confirm")).setLabelYes(_("&Execute")).
+ showCheckBox(dontAskAgain, _("&Don't show this dialog again"), 0)))
+ {
+ case ReturnQuestionDlg::BUTTON_YES:
+ globalCfg.optDialogs.confirmExternalCommandMassInvoke = !dontAskAgain;
+ break;
+
+ case ReturnQuestionDlg::BUTTON_NO:
+ assert(false);
+ case ReturnQuestionDlg::BUTTON_CANCEL:
+ return;
+ }
+ }
+
//regular command evaluation
for (auto it = selectionTmp.begin(); it != selectionTmp.end(); ++it) //context menu calls this function only if selection is not empty!
{
@@ -1338,7 +1338,8 @@ void MainDialog::openExternalApplication(const wxString& commandline, const std:
replace(command, Zstr("%item2_folder%"), dir2 );
auto cmdExp = expandMacros(command);
- zen::shellExecute(cmdExp); //shows error message if command is malformed
+ //caveat: spawning too many threads asynchronously can easily kill a user's desktop session!
+ zen::shellExecute(cmdExp, selectionTmp.size() > massInvokeThreshold ? EXEC_TYPE_SYNC : EXEC_TYPE_ASYNC);
}
}
@@ -1448,27 +1449,26 @@ void MainDialog::onProcessAsyncTasks(wxEvent& event)
void MainDialog::disableAllElements(bool enableAbort)
{
+ //disables all elements (except abort button) that might receive user input during long-running processes:
//when changing consider: comparison, synchronization, manual deletion
EnableCloseButton(false); //not allowed for synchronization! progress indicator is top window! -> not honored on OS X!
- //disables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion
- m_panelViewFilter ->Disable();
+ //OS X: wxWidgets portability promise is again a mess: http://wxwidgets.10942.n7.nabble.com/Disable-panel-and-appropriate-children-windows-linux-macos-td35357.html
+
+ m_menubar1->EnableTop(0, false);
+ m_menubar1->EnableTop(1, false);
+ m_menubar1->EnableTop(2, false);
m_bpButtonCmpConfig ->Disable();
- m_panelFilter ->Disable();
- m_panelConfig ->Disable();
m_bpButtonSyncConfig ->Disable();
m_buttonSync ->Disable();
- m_gridMainL ->Disable();
- m_gridMainC ->Disable();
- m_gridMainR ->Disable();
+ m_panelDirectoryPairs->Disable();
+ m_panelCenter ->Disable();
+ m_panelViewFilter ->Disable();
+ m_panelFilter ->Disable();
+ m_panelConfig ->Disable();
m_panelStatistics ->Disable();
m_gridNavi ->Disable();
- m_panelDirectoryPairs->Disable();
- m_splitterMain ->Disable();
- m_menubar1->EnableTop(0, false);
- m_menubar1->EnableTop(1, false);
- m_menubar1->EnableTop(2, false);
if (enableAbort)
{
@@ -1492,22 +1492,19 @@ void MainDialog::enableAllElements()
EnableCloseButton(true);
- m_panelViewFilter ->Enable();
+ m_menubar1->EnableTop(0, true);
+ m_menubar1->EnableTop(1, true);
+ m_menubar1->EnableTop(2, true);
m_bpButtonCmpConfig ->Enable();
- m_panelFilter ->Enable();
- m_panelConfig ->Enable();
m_bpButtonSyncConfig ->Enable();
m_buttonSync ->Enable();
- m_gridMainL ->Enable();
- m_gridMainC ->Enable();
- m_gridMainR ->Enable();
+ m_panelDirectoryPairs->Enable();
+ m_panelCenter ->Enable();
+ m_panelViewFilter ->Enable();
+ m_panelFilter ->Enable();
+ m_panelConfig ->Enable();
m_panelStatistics ->Enable();
m_gridNavi ->Enable();
- m_panelDirectoryPairs->Enable();
- m_splitterMain ->Enable();
- m_menubar1->EnableTop(0, true);
- m_menubar1->EnableTop(1, true);
- m_menubar1->EnableTop(2, true);
//show compare button
m_buttonCancel->Disable();
@@ -1517,6 +1514,9 @@ void MainDialog::enableAllElements()
m_panelTopButtons->Layout();
m_panelTopButtons->Enable();
+
+ //at least wxWidgets on OS X fails to do this after enabling:
+ Refresh();
}
@@ -1540,12 +1540,14 @@ void MainDialog::OnResizeConfigPanel(wxEvent& event)
event.Skip();
}
+
void MainDialog::OnResizeViewPanel(wxEvent& event)
{
updateSizerOrientation(*bSizerViewFilter, *m_panelViewFilter, 1.0);
event.Skip();
}
+
void MainDialog::OnResizeStatisticsPanel(wxEvent& event)
{
//updateSizerOrientation(*bSizerStatistics, *m_panelStatistics);
@@ -1619,19 +1621,19 @@ void MainDialog::onTreeButtonEvent(wxKeyEvent& event)
{
case WXK_NUMPAD_LEFT:
case WXK_LEFT: //ALT + <-
- setSyncDirManually(getTreeSelection(), SYNC_DIR_LEFT);
+ setSyncDirManually(getTreeSelection(), SyncDirection::LEFT);
return;
case WXK_NUMPAD_RIGHT:
case WXK_RIGHT: //ALT + ->
- setSyncDirManually(getTreeSelection(), SYNC_DIR_RIGHT);
+ setSyncDirManually(getTreeSelection(), SyncDirection::RIGHT);
return;
case WXK_NUMPAD_UP:
case WXK_NUMPAD_DOWN:
case WXK_UP: /* ALT + /|\ */
case WXK_DOWN: /* ALT + \|/ */
- setSyncDirManually(getTreeSelection(), SYNC_DIR_NONE);
+ setSyncDirManually(getTreeSelection(), SyncDirection::NONE);
return;
}
@@ -1704,19 +1706,19 @@ void MainDialog::onGridButtonEvent(wxKeyEvent& event, Grid& grid, bool leftSide)
{
case WXK_NUMPAD_LEFT:
case WXK_LEFT: //ALT + <-
- setSyncDirManually(getGridSelection(), SYNC_DIR_LEFT);
+ setSyncDirManually(getGridSelection(), SyncDirection::LEFT);
return;
case WXK_NUMPAD_RIGHT:
case WXK_RIGHT: //ALT + ->
- setSyncDirManually(getGridSelection(), SYNC_DIR_RIGHT);
+ setSyncDirManually(getGridSelection(), SyncDirection::RIGHT);
return;
case WXK_NUMPAD_UP:
case WXK_NUMPAD_DOWN:
case WXK_UP: /* ALT + /|\ */
case WXK_DOWN: /* ALT + \|/ */
- setSyncDirManually(getGridSelection(), SYNC_DIR_NONE);
+ setSyncDirManually(getGridSelection(), SyncDirection::NONE);
return;
}
@@ -1920,18 +1922,18 @@ void MainDialog::onNaviGridContext(GridClickEvent& event)
return mirrorIfRtl(getSyncOpImage(selection[0]->getSyncOperation() != SO_EQUAL ?
selection[0]->testSyncOperation(dir) : soDefault));
};
- const wxBitmap opRight = getImage(SYNC_DIR_RIGHT, SO_OVERWRITE_RIGHT);
- const wxBitmap opNone = getImage(SYNC_DIR_NONE, SO_DO_NOTHING );
- const wxBitmap opLeft = getImage(SYNC_DIR_LEFT, SO_OVERWRITE_LEFT );
+ const wxBitmap opRight = getImage(SyncDirection::RIGHT, SO_OVERWRITE_RIGHT);
+ const wxBitmap opNone = getImage(SyncDirection::NONE, SO_DO_NOTHING );
+ const wxBitmap opLeft = getImage(SyncDirection::LEFT, SO_OVERWRITE_LEFT );
wxString shortCutLeft = L"\tAlt+Left";
wxString shortCutRight = L"\tAlt+Right";
if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft)
std::swap(shortCutLeft, shortCutRight);
- menu.addItem(_("Set direction:") + L" ->" + shortCutRight, [this, &selection] { setSyncDirManually(selection, SYNC_DIR_RIGHT); }, &opRight);
- menu.addItem(_("Set direction:") + L" -" L"\tAlt+Down", [this, &selection] { setSyncDirManually(selection, SYNC_DIR_NONE); }, &opNone);
- menu.addItem(_("Set direction:") + L" <-" + shortCutLeft, [this, &selection] { setSyncDirManually(selection, SYNC_DIR_LEFT); }, &opLeft);
+ menu.addItem(_("Set direction:") + L" ->" + shortCutRight, [this, &selection] { setSyncDirManually(selection, SyncDirection::RIGHT); }, &opRight);
+ menu.addItem(_("Set direction:") + L" -" L"\tAlt+Down", [this, &selection] { setSyncDirManually(selection, SyncDirection::NONE); }, &opNone);
+ menu.addItem(_("Set direction:") + L" <-" + shortCutLeft, [this, &selection] { setSyncDirManually(selection, SyncDirection::LEFT); }, &opLeft);
//Gtk needs a direction, "<-", because it has no context menu icons!
//Gtk requires "no spaces" for shortcut identifiers!
menu.addSeparator();
@@ -2012,18 +2014,18 @@ void MainDialog::onMainGridContextRim(bool leftSide)
return mirrorIfRtl(getSyncOpImage(selection[0]->getSyncOperation() != SO_EQUAL ?
selection[0]->testSyncOperation(dir) : soDefault));
};
- const wxBitmap opRight = getImage(SYNC_DIR_RIGHT, SO_OVERWRITE_RIGHT);
- const wxBitmap opNone = getImage(SYNC_DIR_NONE, SO_DO_NOTHING );
- const wxBitmap opLeft = getImage(SYNC_DIR_LEFT, SO_OVERWRITE_LEFT );
+ const wxBitmap opRight = getImage(SyncDirection::RIGHT, SO_OVERWRITE_RIGHT);
+ const wxBitmap opNone = getImage(SyncDirection::NONE, SO_DO_NOTHING );
+ const wxBitmap opLeft = getImage(SyncDirection::LEFT, SO_OVERWRITE_LEFT );
wxString shortCutLeft = L"\tAlt+Left";
wxString shortCutRight = L"\tAlt+Right";
if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft)
std::swap(shortCutLeft, shortCutRight);
- menu.addItem(_("Set direction:") + L" ->" + shortCutRight, [this, &selection] { setSyncDirManually(selection, SYNC_DIR_RIGHT); }, &opRight);
- menu.addItem(_("Set direction:") + L" -" L"\tAlt+Down", [this, &selection] { setSyncDirManually(selection, SYNC_DIR_NONE); }, &opNone);
- menu.addItem(_("Set direction:") + L" <-" + shortCutLeft, [this, &selection] { setSyncDirManually(selection, SYNC_DIR_LEFT); }, &opLeft);
+ menu.addItem(_("Set direction:") + L" ->" + shortCutRight, [this, &selection] { setSyncDirManually(selection, SyncDirection::RIGHT); }, &opRight);
+ menu.addItem(_("Set direction:") + L" -" L"\tAlt+Down", [this, &selection] { setSyncDirManually(selection, SyncDirection::NONE); }, &opNone);
+ menu.addItem(_("Set direction:") + L" <-" + shortCutLeft, [this, &selection] { setSyncDirManually(selection, SyncDirection::LEFT); }, &opLeft);
//Gtk needs a direction, "<-", because it has no context menu icons!
//Gtk requires "no spaces" for shortcut identifiers!
menu.addSeparator();
@@ -2482,7 +2484,7 @@ void MainDialog::removeObsoleteCfgHistoryItems(const std::vector<Zstring>& filen
std::vector<Zstring> missingFiles;
auto itFut = fileEx.begin();
- for (auto it = filenames.begin(); it != filenames.end(); ++it, ++itFut)
+ for (auto it = filenames.begin(); it != filenames.end(); ++it, (void)++itFut) //void: prevent ADL from dragging in boost's ,-overload: "MSVC warning C4913: user defined binary operator ',' exists but no overload could convert all operands"
if (itFut->is_ready() && !itFut->get()) //remove only files that are confirmed to be non-existent
missingFiles.push_back(*it);
@@ -2606,15 +2608,16 @@ bool MainDialog::trySaveConfig(const Zstring* fileNameGui) //return true if save
}
else
{
- wxString defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? toWx(activeConfigFiles[0]) : L"SyncSettings.ffs_gui";
+ Zstring defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : Zstr("SyncSettings.ffs_gui");
//attention: activeConfigFiles may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config!
- if (endsWith(defaultFileName, L".ffs_batch"))
- replace(defaultFileName, L".ffs_batch", L".ffs_gui", false);
+ if (endsWith(defaultFileName, Zstr(".ffs_batch")))
+ replace(defaultFileName, Zstr(".ffs_batch"), Zstr(".ffs_gui"), false);
wxFileDialog filePicker(this, //put modal dialog on stack: creating this on freestore leads to memleak!
wxEmptyString,
- wxEmptyString,
- defaultFileName,
+ //OS X really needs dir/file separated like this:
+ utfCvrtTo<wxString>(beforeLast(defaultFileName, FILE_NAME_SEPARATOR)), //default dir; empty string if / not found
+ utfCvrtTo<wxString>(afterLast (defaultFileName, FILE_NAME_SEPARATOR)), //default file; whole string if / not found
wxString(L"FreeFileSync (*.ffs_gui)|*.ffs_gui") + L"|" +_("All files") + L" (*.*)|*",
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (filePicker.ShowModal() != wxID_OK)
@@ -2634,7 +2637,7 @@ bool MainDialog::trySaveConfig(const Zstring* fileNameGui) //return true if save
}
catch (const xmlAccess::FfsXmlError& e)
{
- wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(e.toString().c_str(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, this);
return false;
}
}
@@ -2667,15 +2670,16 @@ bool MainDialog::trySaveBatchConfig(const Zstring* fileNameBatch)
globalCfg.gui.onCompletionHistoryMax))
return false;
- wxString defaultFileName = !activeCfgFilename.empty() ? toWx(activeCfgFilename) : L"BatchRun.ffs_batch";
+ Zstring defaultFileName = !activeCfgFilename.empty() ? activeCfgFilename : Zstr("BatchRun.ffs_batch");
//attention: activeConfigFiles may be a *.ffs_gui file! We don't want to overwrite it with a BATCH config!
- if (endsWith(defaultFileName, L".ffs_gui"))
- replace(defaultFileName, L".ffs_gui", L".ffs_batch");
+ if (endsWith(defaultFileName, Zstr(".ffs_gui")))
+ replace(defaultFileName, Zstr(".ffs_gui"), Zstr(".ffs_batch"));
wxFileDialog filePicker(this, //put modal dialog on stack: creating this on freestore leads to memleak!
wxEmptyString,
- wxEmptyString,
- defaultFileName,
+ //OS X really needs dir/file separated like this:
+ utfCvrtTo<wxString>(beforeLast(defaultFileName, FILE_NAME_SEPARATOR)), //default dir; empty string if / not found
+ utfCvrtTo<wxString>(afterLast (defaultFileName, FILE_NAME_SEPARATOR)), //default file; whole string if / not found
_("FreeFileSync batch") + L" (*.ffs_batch)|*.ffs_batch" + L"|" +_("All files") + L" (*.*)|*",
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (filePicker.ShowModal() != wxID_OK)
@@ -2693,7 +2697,7 @@ bool MainDialog::trySaveBatchConfig(const Zstring* fileNameBatch)
}
catch (const xmlAccess::FfsXmlError& e)
{
- wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(e.toString().c_str(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, this);
return false;
}
}
@@ -2710,7 +2714,7 @@ bool MainDialog::saveOldConfig() //return false on user abort
if (!activeCfgFilename.empty())
//only if check is active and non-default config file loaded
{
- bool neverSave = !globalCfg.optDialogs.popupOnConfigChange;
+ bool dontAskAgain = false;
switch (showQuestionDlg(this,
ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_NO | ReturnQuestionDlg::BUTTON_CANCEL,
@@ -2718,7 +2722,7 @@ bool MainDialog::saveOldConfig() //return false on user abort
QuestConfig().setCaption(toWx(activeCfgFilename)).
setLabelYes(_("&Save")).
setLabelNo(_("Do&n't save")).
- showCheckBox(neverSave, _("Never save changes"), ReturnQuestionDlg::BUTTON_YES)))
+ showCheckBox(dontAskAgain, _("Never save changes"), ReturnQuestionDlg::BUTTON_YES)))
{
case ReturnQuestionDlg::BUTTON_YES:
@@ -2736,7 +2740,7 @@ bool MainDialog::saveOldConfig() //return false on user abort
}
case ReturnQuestionDlg::BUTTON_NO:
- globalCfg.optDialogs.popupOnConfigChange = !neverSave;
+ globalCfg.optDialogs.popupOnConfigChange = !dontAskAgain;
break;
case ReturnQuestionDlg::BUTTON_CANCEL:
@@ -2759,7 +2763,7 @@ void MainDialog::OnConfigLoad(wxCommandEvent& event)
wxFileDialog filePicker(this,
wxEmptyString,
- toWx(beforeLast(activeCfgFilename, FILE_NAME_SEPARATOR)), //set default dir: empty string if "activeConfigFiles" is empty or has no path separator
+ utfCvrtTo<wxString>(beforeLast(activeCfgFilename, FILE_NAME_SEPARATOR)), //set default dir: empty string if "activeConfigFiles" is empty or has no path separator
wxEmptyString,
wxString(L"FreeFileSync (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch") + L"|" +_("All files") + L" (*.*)|*",
wxFD_OPEN | wxFD_MULTIPLE);
@@ -2866,12 +2870,12 @@ bool MainDialog::loadConfiguration(const std::vector<Zstring>& filenames)
{
if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
{
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
+ wxMessageBox(error.toString(), L"FreeFileSync - " + _("Warning"), wxOK | wxICON_WARNING, this);
setConfig(newGuiCfg, filenames);
setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config due to parsing errors
}
else
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(error.toString(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, this);
return false;
}
}
@@ -3308,7 +3312,8 @@ void MainDialog::OnCompare(wxCommandEvent& event)
clearGrid(); //avoid memory peak by clearing old data first
disableAllElements(true); //CompareStatusHandler will internally process Window messages, so avoid unexpected callbacks!
- ZEN_ON_SCOPE_EXIT(updateUiNow(); enableAllElements()); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks
+ auto app = wxTheApp; //fix lambda/wxWigets/VC fuck up
+ ZEN_ON_SCOPE_EXIT(app->Yield(); enableAllElements()); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks
try
{
@@ -4093,12 +4098,11 @@ void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event)
void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
{
//get a filename
- const wxString defaultFileName = L"FileList.csv"; //proposal
wxFileDialog filePicker(this, //creating this on freestore leads to memleak!
wxEmptyString,
wxEmptyString,
- defaultFileName,
- _("Comma separated list") + L" (*.csv)|*.csv" + L"|" +_("All files") + L" (*.*)|*",
+ L"FileList.csv", //default file name
+ _("Comma-separated values") + L" (*.csv)|*.csv" + L"|" +_("All files") + L" (*.*)|*",
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (filePicker.ShowModal() != wxID_OK)
return;
@@ -4220,7 +4224,7 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
}
catch (const FileError& e)
{
- wxMessageBox(e.toString(), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(e.toString(), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR, this);
}
}
}
@@ -4288,7 +4292,7 @@ void MainDialog::switchProgramLanguage(int langID)
newGlobalCfg.programLanguage = langID;
//show new dialog, then delete old one
- MainDialog::create(getConfig(), activeConfigFiles, newGlobalCfg, false);
+ MainDialog::create(getConfig(), activeConfigFiles, &newGlobalCfg, false);
//we don't use Close():
//1. we don't want to show the prompt to save current config in OnClose()
diff --git a/ui/main_dlg.h b/ui/main_dlg.h
index 5575cefb..b655d95e 100644
--- a/ui/main_dlg.h
+++ b/ui/main_dlg.h
@@ -29,16 +29,15 @@ class CompareProgressDialog;
class MainDialog : public MainDialogGenerated
{
public:
- //default behavior, application start
- static void create(const std::vector<Zstring>& cfgFileNames); //cfgFileNames empty: restore last config; non-empty load/merge given set of config files
+ //default behavior, application start, restores last used config
+ static void create();
- //load dynamically assembled config
- static void create(const xmlAccess::XmlGuiConfig& guiCfg, bool startComparison);
-
- //when switching language or switching from batch run to GUI on warnings
+ //when loading dynamically assembled config,
+ //when switching language,
+ //or switching from batch run to GUI on warnings
static void create(const xmlAccess::XmlGuiConfig& guiCfg,
const std::vector<Zstring>& referenceFiles,
- const xmlAccess::XmlGlobalSettings& globalSettings, //take over ownership => save on exit
+ const xmlAccess::XmlGlobalSettings* globalSettings, //optional: take over ownership => save on exit
bool startComparison);
void disableAllElements(bool enableAbort); //dis-/enables all elements (except abort button) that might receive user input
@@ -47,11 +46,6 @@ public:
void onQueryEndSession(); //last chance to do something useful before killing the application!
private:
- static void create_impl(const xmlAccess::XmlGuiConfig& guiCfg,
- const std::vector<Zstring>& referenceFiles,
- const xmlAccess::XmlGlobalSettings& globalSettings,
- bool startComparison);
-
MainDialog(const xmlAccess::XmlGuiConfig& guiCfg,
const std::vector<Zstring>& referenceFiles,
const xmlAccess::XmlGlobalSettings& globalSettings, //take over ownership => save on exit
diff --git a/ui/msg_popup.h b/ui/msg_popup.h
index 5e7ea97f..d93b5002 100644
--- a/ui/msg_popup.h
+++ b/ui/msg_popup.h
@@ -7,6 +7,7 @@
#ifndef MESSAGEPOPUP_H_820780154723456
#define MESSAGEPOPUP_H_820780154723456
+#include <zen/string_tools.h>
#include <wx/window.h>
#include <wx/string.h>
@@ -66,9 +67,11 @@ class QuestConfig
public:
QuestConfig() : checkBoxValue(), disabledButtonsWhenChecked_() {}
QuestConfig& setCaption (const wxString& label) { caption = label; return *this; }
- QuestConfig& setLabelYes(const wxString& label) { labelYes = label; return *this; }
- QuestConfig& setLabelNo (const wxString& label) { labelNo = label; return *this; }
- QuestConfig& showCheckBox(bool& value, const wxString& label, int disabledButtonsWhenChecked) { checkBoxValue = &value; checkBoxLabel = label; disabledButtonsWhenChecked_ = disabledButtonsWhenChecked; return *this; }
+ QuestConfig& setLabelYes(const wxString& label) { assert(contains(label, L"&")); labelYes = label; return *this; }
+ QuestConfig& setLabelNo (const wxString& label) { assert(contains(label, L"&")); labelNo = label; return *this; }
+ QuestConfig& showCheckBox(bool& value,
+ const wxString& label,
+ int disabledButtonsWhenChecked) { assert(contains(label, L"&")); checkBoxValue = &value; checkBoxLabel = label; disabledButtonsWhenChecked_ = disabledButtonsWhenChecked; return *this; }
private:
friend class ::QuestionDlg;
diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp
index 732b21c7..fd1c305d 100644
--- a/ui/progress_indicator.cpp
+++ b/ui/progress_indicator.cpp
@@ -26,6 +26,7 @@
#include <wx+/font_size.h>
#include <wx+/std_button_order.h>
#include <zen/file_handling.h>
+#include <zen/thread.h>
#include "gui_generated.h"
#include "../lib/ffs_paths.h"
#include "../lib/resources.h"
@@ -33,10 +34,14 @@
#include "tray_icon.h"
#include "taskbar.h"
#include "exec_finished_box.h"
-//#include <wx/msgdlg.h>
+
+#include <wx/msgdlg.h>
using namespace zen;
+warn_static("remove after test")
+#include <zen/perf.h>
+
namespace
{
@@ -51,7 +56,7 @@ const int WINDOW_BYTES_PER_SEC = 5000; //
class CompareProgressDialog::Pimpl : public CompareProgressDlgGenerated
{
public:
- Pimpl(wxTopLevelWindow& parentWindow);
+ Pimpl(wxFrame& parentWindow);
void init(const Statistics& syncStat); //constructor/destructor semantics, but underlying Window is reused
void finalize(); //
@@ -60,7 +65,7 @@ public:
void updateStatusPanelNow();
private:
- wxTopLevelWindow& parentWindow_;
+ wxFrame& parentWindow_;
wxString titleTextBackup;
wxStopWatch timeElapsed;
@@ -75,7 +80,7 @@ private:
};
-CompareProgressDialog::Pimpl::Pimpl(wxTopLevelWindow& parentWindow) :
+CompareProgressDialog::Pimpl::Pimpl(wxFrame& parentWindow) :
CompareProgressDlgGenerated(&parentWindow),
parentWindow_(parentWindow),
binCompStartMs(0),
@@ -214,11 +219,13 @@ void CompareProgressDialog::Pimpl::updateStatusPanelNow()
perf->addSample(objectsCurrent, to<double>(dataCurrent), timeNow);
//current speed -> Win 7 copy uses 1 sec update interval instead
- setText(*m_staticTextSpeed, perf->getBytesPerSecond(), &layoutChanged);
+ Opt<std::wstring> bps = perf->getBytesPerSecond();
+ setText(*m_staticTextSpeed, bps ? *bps : L"-", &layoutChanged);
//remaining time: display with relative error of 10% - based on samples taken every 0.5 sec only
//-> call more often than once per second to correctly show last few seconds countdown, but don't call too often to avoid occasional jitter
- setText(*m_staticTextRemTime, perf->getRemainingTime(to<double>(dataTotal - dataCurrent)), &layoutChanged);
+ Opt<std::wstring> rt = perf->getRemainingTime(to<double>(dataTotal - dataCurrent));
+ setText(*m_staticTextRemTime, rt ? *rt : L"-", &layoutChanged);
}
}
break;
@@ -238,17 +245,17 @@ void CompareProgressDialog::Pimpl::updateStatusPanelNow()
wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") :
wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged);
- //do the ui update
if (layoutChanged)
bSizer42->Layout();
- updateUiNow();
+ //do the ui update
+ wxTheApp->Yield();
}
//########################################################################################
//redirect to implementation
-CompareProgressDialog::CompareProgressDialog(wxTopLevelWindow& parentWindow) :
+CompareProgressDialog::CompareProgressDialog(wxFrame& parentWindow) :
pimpl(new Pimpl(parentWindow)) {} //owned by parentWindow
wxWindow* CompareProgressDialog::getAsWindow()
@@ -715,7 +722,7 @@ private:
}
catch (const std::bad_alloc& e)
{
- wxMessageBox(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()), L"FreeFileSync - " + _("Error"), wxOK | wxICON_ERROR);
}
}
@@ -726,88 +733,212 @@ private:
namespace
{
-class GraphDataBytes : public GraphData
+class CurveDataStatistics : public SparseCurveData
{
public:
- void addRecord(double currentBytes, long timeMs)
+ CurveDataStatistics() : SparseCurveData(true), timeNow(0) {}
+
+ void clear() { samples.clear(); timeNow = 0; }
+
+ void addRecord(long timeNowMs, double value)
{
- data.insert(data.end(), std::make_pair(timeMs, currentBytes));
+ warn_static("review")
+ timeNow = timeNowMs;
+ if (!samples.empty() && samples.rbegin()->second == value)
+ return; //don't insert duplicate values
+
+ samples.insert(samples.end(), std::make_pair(timeNowMs, value)); //use fact that time is monotonously ascending
//documentation differs about whether "hint" should be before or after the to be inserted element!
//however "std::map<>::end()" is interpreted correctly by GCC and VS2010
- if (data.size() > MAX_BUFFER_SIZE) //limit buffer size
- data.erase(data.begin());
+ if (samples.size() > MAX_BUFFER_SIZE) //limit buffer size
+ samples.erase(samples.begin());
}
- void clear() { data.clear(); }
+private:
+ virtual std::pair<double, double> getRangeX() const final
+ {
+ if (samples.empty()) return std::make_pair(0.0, 0.0);
- virtual double getXBegin() const { return data.empty() ? 0 : data.begin()->first / 1000.0; } //need not start with 0, e.g. "binary comparison, graph reset, followed by sync"
- virtual double getXEnd () const { return data.empty() ? 0 : (--data.end())->first / 1000.0; }
+ double upperEndMs = std::max(timeNow, samples.rbegin()->first);
-private:
- static const size_t MAX_BUFFER_SIZE = 2500000; //sizeof(single node) worst case ~ 3 * 8 byte ptr + 16 byte key/value = 40 byte
+ //request some additional width by 5% elapsed time to make graph recalibrate before hitting the right border
+ //caveat: graph for batch mode binary comparison does NOT start at elapsed time 0!! PHASE_COMPARING_CONTENT and PHASE_SYNCHRONIZING!
+ //=> consider width of current sample set!
+ upperEndMs += 0.05 *(upperEndMs - samples.begin()->first);
- virtual double getValue(double x) const //x: seconds since begin
+ return std::make_pair(samples.begin()->first / 1000.0, //need not start with 0, e.g. "binary comparison, graph reset, followed by sync"
+ upperEndMs / 1000.0);
+ }
+
+ virtual Opt<CurvePoint> getLessEq(double x) const final //x: seconds since begin
{
- auto it = data.lower_bound(x * 1000);
- if (it == data.end())
- return data.empty() ? 0 : (--data.end())->second;
- return it->second;
+ const long timex = std::floor(x * 1000);
+ //------ add artifical last sample value -------
+ if (!samples.empty() && samples.rbegin()->first < timeNow)
+ if (timeNow <= timex)
+ return CurvePoint(timeNow / 1000.0, samples.rbegin()->second);
+ //--------------------------------------------------
+
+ //find first key > x, then go one step back: => samples must be a std::map, NOT std::multimap!!!
+ auto it = samples.upper_bound(timex);
+ if (it == samples.begin())
+ return NoValue();
+ //=> samples not empty in this context
+ --it;
+ return CurvePoint(it->first / 1000.0, it->second);
}
- //example: two-element range is accessible within [0, 2)
- std::map<long, double> data;
+ virtual Opt<CurvePoint> getGreaterEq(double x) const final
+ {
+ const long timex = std::ceil(x * 1000);
+ //------ add artifical last sample value -------
+ if (!samples.empty() && samples.rbegin()->first < timeNow)
+ if (samples.rbegin()->first < timex && timex <= timeNow)
+ return CurvePoint(timeNow / 1000.0, samples.rbegin()->second);
+ //--------------------------------------------------
+
+ auto it = samples.lower_bound(timex);
+ if (it == samples.end())
+ return NoValue();
+ return CurvePoint(it->first / 1000.0, it->second);
+ }
+
+ static const size_t MAX_BUFFER_SIZE = 2500000; //sizeof(single node) worst case ~ 3 * 8 byte ptr + 16 byte key/value = 40 byte
+
+ std::map<long, double> samples; //time, unit: [ms] !don't use std::multimap, see getLessEq()
+ long timeNow; //help create an artificial record at the end of samples to visualize current time!
};
-class GraphDataConstLine : public GraphData //a constant line
+class CurveDataCurrentValue : public CurveData
{
public:
- GraphDataConstLine() : value_(0) {}
+ CurveDataCurrentValue() : x(0), yCurrent_(0), yTotal_(0) {}
- void setValue(double val) { value_ = val; }
+ void setValue(long xTimeNowMs, double yCurrent, double yTotal) { x = xTimeNowMs / 1000.0; yCurrent_ = yCurrent; yTotal_ = yTotal; }
private:
- virtual double getValue(double x) const { return value_; }
- virtual double getXBegin() const { return -std::numeric_limits<double>::infinity(); }
- virtual double getXEnd () const { return std::numeric_limits<double>::infinity(); }
+ virtual std::pair<double, double> getRangeX() const final { return std::make_pair(x, x); } //conceptually just a vertical line!
- double value_;
+ virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const final
+ {
+
+ warn_static("remove after test")
+#if 0
+ if (yTotal_ > 100)
+ {
+points.push_back(CurvePoint(0.38552801074951426,0.3861846045528107));
+points.push_back(CurvePoint(-0.5565680734345084,1.793989720937398));
+points.push_back(CurvePoint(2.85210684934041,3.339141677944872));
+points.push_back(CurvePoint(0.45404408959926135,0.7810567713436095));
+points.push_back(CurvePoint(2.303978218542433,-0.6610850551966995));
+points.push_back(CurvePoint(-2.5606633797896112,-0.4035597290287872));
+points.push_back(CurvePoint(-0.5394390537220716,0.40335295963067147));
+
+
+ //points.push_back(CurvePoint(0.2885508231771302,-1.9264175407823294));
+ //points.push_back(CurvePoint(-1.9332518577512143,0.6244007597162101));
+ //points.push_back(CurvePoint(3.116299689813205,1.6973640131005165));
+ //points.push_back(CurvePoint(0.0,0.0));
+ //points.push_back(CurvePoint(-5.993091301993007,0.5231778112837284));
+ return;
+ }
+#endif
+
+
+
+
+
+
+ if (x <= maxX)
+ {
+ points.push_back(CurvePoint(x, 0));
+ points.push_back(CurvePoint(x, yCurrent_));
+ points.push_back(CurvePoint(maxX, yCurrent_));
+ points.push_back(CurvePoint(x, yCurrent_));
+ points.push_back(CurvePoint(x, yTotal_));
+ }
+ }
+
+ double x; //time elapsed in seconds
+ double yCurrent_; //current bytes/items
+ double yTotal_;
};
-inline
-double bestFit(double val, double low, double high) { return val < (high + low) / 2 ? low : high; }
+class CurveDataTotalValue : public CurveData
+{
+public:
+ CurveDataTotalValue () : x(0), yTotal_(0) {}
+
+ void setValue(long xTimeNowMs, double yTotal) { x = xTimeNowMs / 1000.0; yTotal_ = yTotal; }
+
+private:
+ virtual std::pair<double, double> getRangeX() const final { return std::make_pair(x, x); } //conceptually just a vertical line!
+
+ virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const final
+ {
+ if (x <= maxX)
+ {
+ points.push_back(CurvePoint(x, yTotal_));
+ points.push_back(CurvePoint(maxX, yTotal_));
+ }
+ }
+
+ double x; //time elapsed in seconds
+ double yTotal_;
+};
struct LabelFormatterBytes : public LabelFormatter
{
virtual double getOptimalBlockSize(double bytesProposed) const
{
- if (bytesProposed <= 0)
- return 0;
+ if (bytesProposed <= 1) //never smaller than 1 byte
+ return 1;
- bytesProposed *= 1.5; //enlarge block default size
+ bytesProposed *= 1.4; //enlarge block default size
//round to next number which is a convenient to read block size
const double k = std::floor(std::log(bytesProposed) / std::log(2.0));
const double e = std::pow(2.0, k);
if (numeric::isNull(e))
return 0;
- const double a = bytesProposed / e; //bytesProposed = a * 2^k with a in (1, 2)
- assert(1 < a && a < 2);
- return bestFit(a, 1, 2) * e;
+ const double a = bytesProposed / e; //bytesProposed = a * 2^k with a in [1, 2)
+ assert(1 <= a && a < 2);
+ const double steps[] = { 1, 2 };
+ return e * numeric::nearMatch(a, std::begin(steps), std::end(steps));
}
virtual wxString formatText(double value, double optimalBlockSize) const { return filesizeToShortString(Int64(value)); };
};
+struct LabelFormatterItemCount : public LabelFormatter
+{
+ virtual double getOptimalBlockSize(double itemsProposed) const
+ {
+ const double steps[] = { 1, 2, 5, 10 };
+ if (itemsProposed <= 10)
+ return numeric::nearMatch(itemsProposed, std::begin(steps), std::end(steps)); //similar to nextNiceNumber(), but without the 2.5 step!
+ return nextNiceNumber(itemsProposed);
+ }
+
+ virtual wxString formatText(double value, double optimalBlockSize) const
+ {
+ return toGuiString(numeric::round(value)); //not enough room for a "%x items" representation
+ };
+};
+
+
struct LabelFormatterTimeElapsed : public LabelFormatter
{
+ LabelFormatterTimeElapsed(bool drawLabel) : drawLabel_(drawLabel) {}
+
virtual double getOptimalBlockSize(double secProposed) const
{
- const double stepsSec[] = { 10, 20, 30, 60 }; //10 sec: minimum block size; no 15: avoid flicker between 10<->15<->20 sec blocks
+ const double stepsSec[] = { 20, 30, 60 }; //20 sec: minimum block size; (no 15: avoid flicker between 10<->15<->20 sec blocks)
if (secProposed <= 60)
return numeric::nearMatch(secProposed, std::begin(stepsSec), std::end(stepsSec));
@@ -816,215 +947,302 @@ struct LabelFormatterTimeElapsed : public LabelFormatter
return 60.0 * numeric::nearMatch(secProposed / 60, std::begin(stepsMin), std::end(stepsMin));
if (secProposed <= 3600 * 24)
- return nextNiceNumber(secProposed / 3600) * 3600;
+ return nextNiceNumber(secProposed / 3600) * 3600; //round up to full hours
- return nextNiceNumber(secProposed / (24 * 3600)) * 24 * 3600; //round up to full days
+ return nextNiceNumber(secProposed / (24 * 3600)) * 24 * 3600; //round to full days
}
virtual wxString formatText(double timeElapsed, double optimalBlockSize) const
{
+ if (!drawLabel_) return wxString();
return timeElapsed < 60 ?
replaceCpy(_P("1 sec", "%x sec", numeric::round(timeElapsed)), L"%x", zen::numberTo<std::wstring>(numeric::round(timeElapsed))) :
timeElapsed < 3600 ?
wxTimeSpan::Seconds(timeElapsed).Format( L"%M:%S") :
wxTimeSpan::Seconds(timeElapsed).Format(L"%H:%M:%S");
}
-};
-//void fitHeight(wxTopLevelWindow& wnd)
-//{
-// if (wnd.IsMaximized())
-// return;
-// //Fit() height only:
-// int width = wnd.GetSize().GetWidth();
-// wnd.Fit();
-// int height = wnd.GetSize().GetHeight();
-// wnd.SetSize(wxSize(width, height));
-//}
+private:
+ bool drawLabel_;
+};
}
-class SyncProgressDialogImpl : private SyncProgressDlgGenerated, public SyncProgressDialog
+template <class TopLevelDialog> //can be a wxFrame or wxDialog
+class SyncProgressDialogImpl : private TopLevelDialog, public SyncProgressDialog
+/*we need derivation, not composition!
+ 1. SyncProgressDialogImpl IS a wxFrame/wxDialog
+ 2. implement virtual ~wxFrame()
+ 3. event handling below assumes lifetime is larger-equal than wxFrame's
+*/
{
public:
- SyncProgressDialogImpl(AbortCallback& abortCb,
+ SyncProgressDialogImpl(long style, //wxFrame/wxDialog style
+ const std::function<wxFrame*(TopLevelDialog& progDlg)>& getTaskbarFrame,
+ AbortCallback& abortCb,
const std::function<void()>& notifyWindowTerminate,
const Statistics& syncStat,
- wxTopLevelWindow* parentWindow,
+ wxFrame* parentFrame,
bool showProgress,
const wxString& jobName,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory);
- ~SyncProgressDialogImpl();
+ virtual ~SyncProgressDialogImpl();
//call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater
virtual void processHasFinished(SyncResult resultId, const ErrorLog& log);
virtual void closeWindowDirectly();
- virtual wxWindow* getAsWindow() { return this; }
+ virtual wxWindow* getWindowIfVisible() { return this->IsShown() ? this : nullptr; }
+ //workaround OS X bug: if "this" is used as parent window for a modal dialog then this dialog will erroneously un-hide its parent!
+
virtual void initNewPhase();
virtual void notifyProgressChange();
- virtual void updateGui() { updateGuiInt(true); }
-
- virtual std::wstring getExecWhenFinishedCommand() const;
+ virtual void updateGui() {
+
+
+ warn_static("remove after test")
+#if 0
+ static bool init = false;
+ static wxStopWatch sw;
+ if (!init)
+ {
+ init = true;
+ sw.Start();
+ }
+ if (sw.Time() > 1000 * 10)
+ {
+ PERF_START
+ for (int i = 0; i < 10000; ++i)
+ //for (int i = 0; i < 1000000; ++i)
+ updateGuiInt(true);
+ sw.Start();
+ sw.Pause();
+ }
+#endif
+
+
+
+
+
+
+ updateGuiInt(true); }
+
+ virtual std::wstring getExecWhenFinishedCommand() const { return pnl.m_comboBoxExecFinished->getValue(); }
virtual void stopTimer() //halt all internal counters!
{
- m_animCtrlSyncing->Stop();
+ pnl.m_animCtrlSyncing->Stop();
timeElapsed.Pause ();
}
virtual void resumeTimer()
{
- m_animCtrlSyncing->Play();
+ pnl.m_animCtrlSyncing->Play();
timeElapsed.Resume();
}
private:
void updateGuiInt(bool allowYield);
- void minimizeToTray();
void OnKeyPressed(wxKeyEvent& event);
- virtual void OnOkay (wxCommandEvent& event);
- virtual void OnPause (wxCommandEvent& event);
- virtual void OnCancel (wxCommandEvent& event);
- virtual void OnClose (wxCloseEvent& event);
- virtual void OnIconize(wxIconizeEvent& event);
-
- void updateDialogStatus();
+ void OnOkay (wxCommandEvent& event);
+ void OnPause (wxCommandEvent& event);
+ void OnCancel (wxCommandEvent& event);
+ void OnClose (wxCloseEvent& event);
+ void OnIconize(wxIconizeEvent& event);
+ void OnMinimizeToTray(wxCommandEvent& event) { minimizeToTray(); }
+ void minimizeToTray();
void resumeFromSystray();
- void OnResumeFromTray(wxCommandEvent& event);
+ void updateDialogStatus();
void setExternalStatus(const wxString& status, const wxString& progress); //progress may be empty!
+ SyncProgressPanelGenerated& pnl; //wxPanel containing the GUI controls of *this
+
const wxString jobName_;
wxStopWatch timeElapsed;
- wxTopLevelWindow* mainDialog; //optional
+ wxFrame* parentFrame_; //optional
std::function<void()> notifyWindowTerminate_; //call once in OnClose(), NOT in destructor which is called far too late somewhere in wxWidgets main loop!
+ bool wereDead; //after wxWindow::Delete, which is equal to "delete this" on OS X!
+
//status variables
const Statistics* syncStat_; //
AbortCallback* abortCb_; //valid only while sync is running
bool paused_; //valid only while sync is running
SyncResult finalResult; //set after sync
- bool isZombie; //wxGTK sends iconize event *after* wxWindow::Destroy, sigh...
-
//remaining time
std::unique_ptr<PerfCheck> perf;
long lastStatCallSpeed; //used for calculating intervals between collecting perf samples
//help calculate total speed
long phaseStartMs; //begin of current phase in [ms]
- std::shared_ptr<GraphDataBytes> graphDataBytes;
- std::shared_ptr<GraphDataConstLine> graphDataBytesTotal;
+ std::shared_ptr<CurveDataStatistics> curveDataBytes;
+ std::shared_ptr<CurveDataStatistics> curveDataItems;
- wxString titelTextBackup;
+ std::shared_ptr<CurveDataTotalValue > curveDataBytesTotal;
+ std::shared_ptr<CurveDataCurrentValue> curveDataBytesCurrent;
+ std::shared_ptr<CurveDataTotalValue > curveDataItemsTotal;
+ std::shared_ptr<CurveDataCurrentValue> curveDataItemsCurrent;
+
+ wxString parentFrameTitleBackup;
std::unique_ptr<FfsTrayIcon> trayIcon; //optional: if filled all other windows should be hidden and conversely
std::unique_ptr<Taskbar> taskbar_;
};
-SyncProgressDialogImpl::SyncProgressDialogImpl(AbortCallback& abortCb,
- const std::function<void()>& notifyWindowTerminate,
- const Statistics& syncStat,
- wxTopLevelWindow* parentWindow,
- bool showProgress,
- const wxString& jobName,
- const std::wstring& execWhenFinished,
- std::vector<std::wstring>& execFinishedHistory) :
- SyncProgressDlgGenerated(parentWindow,
- wxID_ANY,
- parentWindow ? wxString() : (wxString(L"FreeFileSync - ") + _("Folder Comparison and Synchronization")),
- wxDefaultPosition, wxDefaultSize,
- parentWindow ?
- wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT : //wxTAB_TRAVERSAL is needed for standard button handling: wxID_OK/wxID_CANCEL
- wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL),
+template <class TopLevelDialog>
+SyncProgressDialogImpl<TopLevelDialog>::SyncProgressDialogImpl(long style, //wxFrame/wxDialog style
+ const std::function<wxFrame*(TopLevelDialog& progDlg)>& getTaskbarFrame,
+ AbortCallback& abortCb,
+ const std::function<void()>& notifyWindowTerminate,
+ const Statistics& syncStat,
+ wxFrame* parentFrame,
+ bool showProgress,
+ const wxString& jobName,
+ const std::wstring& execWhenFinished,
+ std::vector<std::wstring>& execFinishedHistory) :
+ TopLevelDialog(parentFrame, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, style), //title is overwritten anyway in setExternalStatus()
+ pnl(*new SyncProgressPanelGenerated(this)), //ownership passed to "this"
jobName_ (jobName),
- mainDialog(parentWindow),
+ parentFrame_(parentFrame),
notifyWindowTerminate_(notifyWindowTerminate),
+ wereDead(false),
syncStat_ (&syncStat),
abortCb_ (&abortCb),
paused_ (false),
finalResult(RESULT_ABORTED), //dummy value
- isZombie(false),
lastStatCallSpeed(-1000000), //some big number
phaseStartMs(0)
{
+ assert_static((IsSameType<TopLevelDialog, wxFrame >::value ||
+ IsSameType<TopLevelDialog, wxDialog>::value));
+ assert((IsSameType<TopLevelDialog, wxFrame>::value == !parentFrame));
+
+ //finish construction of this dialog:
+ this->SetMinSize(wxSize(470, 280)); //== minimum size! no idea why SetMinSize() is not used...
+ wxBoxSizer* bSizer170 = new wxBoxSizer(wxVERTICAL);
+ bSizer170->Add(&pnl, 1, wxEXPAND);
+ this->SetSizer(bSizer170); //pass ownership
+ //this->Layout();
+ //bSizer170->Fit(this);
+ this->Centre(wxBOTH);
+
+ //lifetime of event sources is subset of this instance's lifetime => no wxEvtHandler::Disconnect() needed
+ this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler (SyncProgressDialogImpl<TopLevelDialog>::OnClose));
+ this->Connect(wxEVT_ICONIZE, wxIconizeEventHandler(SyncProgressDialogImpl<TopLevelDialog>::OnIconize));
+ this->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(SyncProgressDialogImpl::OnKeyPressed), nullptr, this);
+ pnl.m_buttonClose ->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnOkay ), NULL, this);
+ pnl.m_buttonPause ->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnPause ), NULL, this);
+ pnl.m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnCancel), NULL, this);
+ pnl.m_bpButtonMinimizeToTray->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SyncProgressDialogImpl::OnMinimizeToTray), NULL, this);
+
#ifdef ZEN_WIN
new MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this"
#endif
- assert(m_buttonClose->GetId() == wxID_OK); //we cannot use wxID_CLOSE else Esc key won't work: yet another wxWidgets bug??
+ assert(pnl.m_buttonClose->GetId() == wxID_OK); //we cannot use wxID_CLOSE else Esc key won't work: yet another wxWidgets bug??
- setRelativeFontSize(*m_staticTextPhase, 1.5);
+ setRelativeFontSize(*pnl.m_staticTextPhase, 1.5);
- if (mainDialog)
- titelTextBackup = mainDialog->GetTitle(); //save old title (will be used as progress indicator)
+ if (parentFrame_)
+ parentFrameTitleBackup = parentFrame_->GetTitle(); //save old title (will be used as progress indicator)
- m_animCtrlSyncing->SetAnimation(GlobalResources::instance().aniWorking);
- m_animCtrlSyncing->Play();
+ pnl.m_animCtrlSyncing->SetAnimation(GlobalResources::instance().aniWorking);
+ pnl.m_animCtrlSyncing->Play();
- SetIcon(GlobalResources::instance().programIconFFS);
-
- //initialize gauge
- m_gauge1->SetRange(GAUGE_FULL_RANGE);
- m_gauge1->SetValue(0);
+ this->SetIcon(GlobalResources::instance().programIconFFS);
- EnableCloseButton(false); //this is NOT honored on OS X or during system shutdown on Windows!
-
- if (IsShown()) //don't steal focus when starting in sys-tray!
- m_buttonCancel->SetFocus();
+ this->EnableCloseButton(false); //this is NOT honored on OS X or during system shutdown on Windows!
timeElapsed.Start(); //measure total time
- try //try to get access to Windows 7/Ubuntu taskbar
- {
- taskbar_ = make_unique<Taskbar>(mainDialog ? *static_cast<wxTopLevelWindow*>(mainDialog) : *this);
- }
- catch (const TaskbarNotAvailable&) {}
+ if (wxFrame* frame = getTaskbarFrame(*this))
+ try //try to get access to Windows 7/Ubuntu taskbar
+ {
+ taskbar_ = make_unique<Taskbar>(*frame); //throw TaskbarNotAvailable
+ }
+ catch (const TaskbarNotAvailable&) {}
//hide "processed" statistics until end of process
- m_notebookResult ->Hide();
- m_staticTextLabelItemsProc->Show(false);
- bSizerItemsProc ->Show(false);
- m_buttonClose ->Show(false);
+ pnl.m_notebookResult ->Hide();
+ pnl.m_panelItemsProcessed->Hide();
+ pnl.m_buttonClose ->Show(false);
//set std order after button visibility was set
- setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonPause).setCancel(m_buttonCancel));
+ setStandardButtonOrder(*pnl.bSizerStdButtons, StdButtons().setAffirmative(pnl.m_buttonPause).setCancel(pnl.m_buttonCancel));
- //register key event
- Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(SyncProgressDialogImpl::OnKeyPressed), nullptr, this);
+ pnl.m_bpButtonMinimizeToTray->SetBitmapLabel(getResourceImage(L"minimize_to_tray"));
//init graph
- graphDataBytes = std::make_shared<GraphDataBytes>();
- graphDataBytesTotal = std::make_shared<GraphDataConstLine>();
+ curveDataBytes = std::make_shared<CurveDataStatistics>();
+ curveDataItems = std::make_shared<CurveDataStatistics>();
+ curveDataBytesTotal = std::make_shared<CurveDataTotalValue>();
+ curveDataBytesCurrent = std::make_shared<CurveDataCurrentValue>();
+ curveDataItemsTotal = std::make_shared<CurveDataTotalValue>();
+ curveDataItemsCurrent = std::make_shared<CurveDataCurrentValue>();
+
+ const int xLabelHeight = 18; //we need to use the same height for both graphs to make sure they stretch evenly
+ const int yLabelWidth = 70;
+ pnl.m_panelGraphBytes->setAttributes(Graph2D::MainAttributes().
+ setLabelX(Graph2D::X_LABEL_BOTTOM, xLabelHeight, std::make_shared<LabelFormatterTimeElapsed>(true)).
+ setLabelY(Graph2D::Y_LABEL_RIGHT, yLabelWidth, std::make_shared<LabelFormatterBytes>()).
+ setSelectionMode(Graph2D::SELECT_NONE));
+
+ pnl.m_panelGraphItems->setAttributes(Graph2D::MainAttributes().
+ setLabelX(Graph2D::X_LABEL_BOTTOM, xLabelHeight, std::make_shared<LabelFormatterTimeElapsed>(false)).
+ setLabelY(Graph2D::Y_LABEL_RIGHT, yLabelWidth, std::make_shared<LabelFormatterItemCount>()).
+ setSelectionMode(Graph2D::SELECT_NONE));
+
+ pnl.m_panelGraphBytes->setCurve(curveDataBytes, Graph2D::CurveAttributes().setLineWidth(2).
+ fillCurveArea(wxColor(205, 255, 202)). //faint green
+ setColor (wxColor( 20, 200, 0))); //medium green
+
+ pnl.m_panelGraphItems->setCurve(curveDataItems, Graph2D::CurveAttributes().setLineWidth(2).
+ fillCurveArea(wxColor(198, 206, 255)). //faint blue
+ setColor (wxColor( 90, 120, 255))); //medium blue
+
+ pnl.m_panelGraphBytes->addCurve(curveDataBytesTotal, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(12, 128, 0))); //dark green
+ pnl.m_panelGraphBytes->addCurve(curveDataBytesCurrent, Graph2D::CurveAttributes().setLineWidth(1).setColor(wxColor(12, 128, 0))); //
+
+ pnl.m_panelGraphItems->addCurve(curveDataItemsTotal, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(53, 25, 255))); //dark blue
+ pnl.m_panelGraphItems->addCurve(curveDataItemsCurrent, Graph2D::CurveAttributes().setLineWidth(1).setColor(wxColor(53, 25, 255))); //
+
+ //allow changing on completion command
+ pnl.m_comboBoxExecFinished->initHistory(execFinishedHistory, execFinishedHistory.size()); //-> we won't use addItemHistory() later
+ pnl.m_comboBoxExecFinished->setValue(execWhenFinished);
+
+ updateDialogStatus(); //null-status will be shown while waiting for dir locks
+
+
+ warn_static("remove after test")
+#if 0
+ pnl.m_panelGraphBytes->setAttributes(Graph2D::MainAttributes().setMinX(-1).setMaxX(1).setMinY(-1).setMaxY(1));
+ pnl.m_panelGraphBytes->setCurve(curveDataBytesCurrent, Graph2D::CurveAttributes().setLineWidth(6).setColor(wxColor(12, 128, 0))
+ .fillCurveArea(wxColor(198, 206, 255)) //faint blue
+ ); //
+#endif
+
+
+
- m_panelGraph->setAttributes(Graph2D::MainAttributes().
- setLabelX(Graph2D::X_LABEL_BOTTOM, 20, std::make_shared<LabelFormatterTimeElapsed>()).
- setLabelY(Graph2D::Y_LABEL_RIGHT, 70, std::make_shared<LabelFormatterBytes>()).
- setSelectionMode(Graph2D::SELECT_NONE));
- m_panelGraph->setData(graphDataBytes,
- Graph2D::CurveAttributes().setLineWidth(2).
- setColor (wxColor( 0, 192, 0)). //medium green
- fillCurveArea(wxColor(192, 255, 192))); //faint green
- m_panelGraph->addData(graphDataBytesTotal, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(0, 64, 0))); //dark green
- //allow changing on completion command
- m_comboBoxExecFinished->initHistory(execFinishedHistory, execFinishedHistory.size()); //-> we won't use addItemHistory() later
- m_comboBoxExecFinished->setValue(execWhenFinished);
- updateDialogStatus(); //null-status will be shown while waiting for dir locks (if at all)
- Fit();
- Layout();
+
+ this->Fit();
+ pnl.Layout();
if (showProgress)
{
- Show();
+ this->Show();
+ pnl.m_buttonCancel->SetFocus(); //don't steal focus when starting in sys-tray!
+
//clear gui flicker, remove dummy texts: window must be visible to make this work!
updateGuiInt(true); //at least on OS X a real Yield() is required to flush pending GUI updates; Update() is not enough
}
@@ -1033,24 +1251,25 @@ SyncProgressDialogImpl::SyncProgressDialogImpl(AbortCallback& abortCb,
}
-SyncProgressDialogImpl::~SyncProgressDialogImpl()
+template <class TopLevelDialog>
+SyncProgressDialogImpl<TopLevelDialog>::~SyncProgressDialogImpl()
{
- if (mainDialog)
+ if (parentFrame_)
{
- mainDialog->SetTitle(titelTextBackup); //restore title text
+ parentFrame_->SetTitle(parentFrameTitleBackup); //restore title text
//make sure main dialog is shown again if still "minimized to systray"! see SyncProgressDialog::closeWindowDirectly()
- if (mainDialog->IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
- mainDialog->Iconize(false);
-
- mainDialog->Show();
+ parentFrame_->Show();
+ //if (parentFrame_->IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
+ // parentFrame_->Iconize(false);
}
//our client is NOT expecting a second call via notifyWindowTerminate_()!
}
-void SyncProgressDialogImpl::OnKeyPressed(wxKeyEvent& event)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::OnKeyPressed(wxKeyEvent& event)
{
const int keyCode = event.GetKeyCode();
if (keyCode == WXK_ESCAPE)
@@ -1058,15 +1277,15 @@ void SyncProgressDialogImpl::OnKeyPressed(wxKeyEvent& event)
wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED);
//simulate click on abort button
- if (m_buttonCancel->IsShown()) //delegate to "cancel" button if available
+ if (pnl.m_buttonCancel->IsShown()) //delegate to "cancel" button if available
{
- if (wxEvtHandler* handler = m_buttonCancel->GetEventHandler())
+ if (wxEvtHandler* handler = pnl.m_buttonCancel->GetEventHandler())
handler->ProcessEvent(dummy);
return;
}
- else if (m_buttonClose->IsShown())
+ else if (pnl.m_buttonClose->IsShown())
{
- if (wxEvtHandler* handler = m_buttonClose->GetEventHandler())
+ if (wxEvtHandler* handler = pnl.m_buttonClose->GetEventHandler())
handler->ProcessEvent(dummy);
return;
}
@@ -1076,29 +1295,33 @@ void SyncProgressDialogImpl::OnKeyPressed(wxKeyEvent& event)
}
-void SyncProgressDialogImpl::initNewPhase()
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::initNewPhase()
{
updateDialogStatus(); //evaluates "syncStat_->currentPhase()"
- //reset graph (e.g. after binary comparison)
- graphDataBytes->clear();
+ //reset graphs (e.g. after binary comparison)
+ curveDataBytesTotal ->setValue(0, 0);
+ curveDataBytesCurrent->setValue(0, 0, 0);
+ curveDataItemsTotal ->setValue(0, 0);
+ curveDataItemsCurrent->setValue(0, 0, 0);
+ curveDataBytes->clear();
+ curveDataItems->clear();
+
notifyProgressChange();
//start new measurement
perf = make_unique<PerfCheck>(WINDOW_REMAINING_TIME, WINDOW_BYTES_PER_SEC);
- lastStatCallSpeed = -1000000; //some big number
+ lastStatCallSpeed = -1000000; //some big number
phaseStartMs = timeElapsed.Time();
- //set to 0 even if totalDataToProcess is 0: due to a bug in wxGauge::SetValue, it doesn't change to determinate mode when setting the old value again
- //so give updateGui() a chance to set a different value
- m_gauge1->SetValue(0);
-
updateGuiInt(false);
}
-void SyncProgressDialogImpl::notifyProgressChange() //noexcept!
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::notifyProgressChange() //noexcept!
{
if (syncStat_) //sync running
switch (syncStat_->currentPhase())
@@ -1109,13 +1332,9 @@ void SyncProgressDialogImpl::notifyProgressChange() //noexcept!
break;
case ProcessCallback::PHASE_COMPARING_CONTENT:
case ProcessCallback::PHASE_SYNCHRONIZING:
- {
- const double currentData = to<double>(syncStat_->getDataCurrent(syncStat_->currentPhase()));
-
- //add sample for perf measurements + calc. of remaining time
- graphDataBytes->addRecord(currentData, timeElapsed.Time());
- }
- break;
+ curveDataBytes->addRecord(timeElapsed.Time(), to<double>(syncStat_->getDataCurrent (syncStat_->currentPhase())));
+ curveDataItems->addRecord(timeElapsed.Time(), syncStat_->getObjectsCurrent(syncStat_->currentPhase()));
+ break;
}
}
@@ -1140,7 +1359,7 @@ Zorder evaluateZorder(const wxWindow& top, const wxWindow& bottom)
if (hAbove == hTop)
return ZORDER_CORRECT;
- for (HWND hAbove = ::GetNextWindow(hTop, GW_HWNDPREV); hAbove; hAbove = ::GetNextWindow(hAbove, GW_HWNDPREV))
+ for (HWND hAbove = hTop; hAbove; hAbove = ::GetNextWindow(hAbove, GW_HWNDPREV))
if (hAbove == hBottom)
return ZORDER_WRONG;
@@ -1183,7 +1402,8 @@ std::wstring getDialogPhaseText(const Statistics* syncStat, bool paused, SyncPro
}
-void SyncProgressDialogImpl::setExternalStatus(const wxString& status, const wxString& progress) //progress may be empty!
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::setExternalStatus(const wxString& status, const wxString& progress) //progress may be empty!
{
//sys tray: order "top-down": jobname, status, progress
wxString newTrayInfo = jobName_.empty() ? status : L"\"" + jobName_ + L"\"\n" + status;
@@ -1200,10 +1420,10 @@ void SyncProgressDialogImpl::setExternalStatus(const wxString& status, const wxS
trayIcon->setToolTip(newTrayInfo);
//show text in dialog title (and at the same time in taskbar)
- if (mainDialog)
+ if (parentFrame_)
{
- if (mainDialog->GetTitle() != newCaption)
- mainDialog->SetTitle(newCaption);
+ if (parentFrame_->GetTitle() != newCaption)
+ parentFrame_->SetTitle(newCaption);
}
//always set a title: we don't wxGTK to show "nameless window" instead
@@ -1212,7 +1432,8 @@ void SyncProgressDialogImpl::setExternalStatus(const wxString& status, const wxS
}
-void SyncProgressDialogImpl::updateGuiInt(bool allowYield)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::updateGuiInt(bool allowYield)
{
if (!syncStat_) //sync not running
return;
@@ -1223,7 +1444,7 @@ void SyncProgressDialogImpl::updateGuiInt(bool allowYield)
const long timeNow = timeElapsed.Time();
//sync status text
- setText(*m_staticTextStatus, replaceCpy(syncStat_->currentStatusText(), L'\n', L' ')); //no layout update for status texts!
+ setText(*pnl.m_staticTextStatus, replaceCpy(syncStat_->currentStatusText(), L'\n', L' ')); //no layout update for status texts!
switch (syncStat_->currentPhase()) //no matter if paused or not
{
@@ -1233,33 +1454,30 @@ void SyncProgressDialogImpl::updateGuiInt(bool allowYield)
setExternalStatus(getDialogPhaseText(syncStat_, paused_, finalResult), toGuiString(syncStat_->getObjectsCurrent(ProcessCallback::PHASE_SCANNING))); //status text may be "paused"!
//progress indicators
- m_gauge1->Pulse();
- if (trayIcon.get()) trayIcon->setProgress(1); //1 = regular FFS logo
+ if (trayIcon.get()) trayIcon->setProgress(1); //100% = regular FFS logo
- //taskbar_ status is Taskbar::STATUS_INDETERMINATE
-
- //constant line graph
- graphDataBytesTotal->setValue(0);
+ //ignore graphs: should already have been cleared in initNewPhase()
//remaining objects and data
- setText(*m_staticTextRemainingObj , L"-", &layoutChanged);
- setText(*m_staticTextDataRemaining, L"", &layoutChanged);
+ setText(*pnl.m_staticTextRemainingObj , L"-", &layoutChanged);
+ setText(*pnl.m_staticTextDataRemaining, L"", &layoutChanged);
//remaining time and speed
- setText(*m_staticTextSpeed, L"-", &layoutChanged);
- setText(*m_staticTextRemTime, L"-", &layoutChanged);
+ setText(*pnl.m_staticTextRemTime, L"-", &layoutChanged);
+ pnl.m_panelGraphBytes->setAttributes(pnl.m_panelGraphBytes->getAttributes().setCornerText(wxString(), Graph2D::CORNER_TOP_LEFT));
+ pnl.m_panelGraphItems->setAttributes(pnl.m_panelGraphItems->getAttributes().setCornerText(wxString(), Graph2D::CORNER_TOP_LEFT));
break;
case ProcessCallback::PHASE_COMPARING_CONTENT:
case ProcessCallback::PHASE_SYNCHRONIZING:
{
- auto objectsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase());
- auto objectsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase());
- auto dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase());
- auto dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase());
+ const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase());
+ const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase());
+ const Int64 dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase());
+ const Int64 dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase());
//add both data + obj-count, to handle "deletion-only" cases
- const double fraction = dataTotal + objectsTotal == 0 ? 1 : std::max(0.0, to<double>(dataCurrent + objectsCurrent) / to<double>(dataTotal + objectsTotal));
+ const double fraction = dataTotal + itemsTotal == 0 ? 1 : std::max(0.0, to<double>(dataCurrent + itemsCurrent) / to<double>(dataTotal + itemsTotal));
//yes, this may legitimately become < 0: failed rename operation falls-back to copy + delete, reducing "dataCurrent" to potentially < 0!
//----------------------------------------------------------------------------------------------------
@@ -1267,16 +1485,22 @@ void SyncProgressDialogImpl::updateGuiInt(bool allowYield)
setExternalStatus(getDialogPhaseText(syncStat_, paused_, finalResult), fractionToString(fraction)); //status text may be "paused"!
//progress indicators
- m_gauge1->SetValue(numeric::round(fraction * GAUGE_FULL_RANGE));
if (trayIcon.get()) trayIcon->setProgress(fraction);
if (taskbar_.get()) taskbar_->setProgress(fraction);
//constant line graph
- graphDataBytesTotal->setValue(to<double>(dataTotal));
-
+ curveDataBytesTotal ->setValue(timeNow, to<double>(dataTotal));
+ curveDataBytesCurrent->setValue(timeNow, to<double>(dataCurrent), to<double>(dataTotal));
+ curveDataItemsTotal ->setValue(timeNow, itemsTotal);
+ curveDataItemsCurrent->setValue(timeNow, itemsCurrent, itemsTotal);
+ //even though notifyProgressChange() already set the latest data, let's add another sample to have all curves consider "timeNow"
+ //no problem with adding too many records: CurveDataStatistics will remove duplicate entries!
+ curveDataBytes->addRecord(timeNow, to<double>(dataCurrent));
+ curveDataItems->addRecord(timeNow, itemsCurrent);
+
//remaining objects and data
- setText(*m_staticTextRemainingObj, toGuiString(objectsTotal - objectsCurrent), &layoutChanged);
- setText(*m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged);
+ setText(*pnl.m_staticTextRemainingObj, toGuiString(itemsTotal - itemsCurrent), &layoutChanged);
+ setText(*pnl.m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged);
//it's possible data remaining becomes shortly negative if last file synced has ADS data and the dataTotal was not yet corrected!
//remaining time and speed
@@ -1287,48 +1511,52 @@ void SyncProgressDialogImpl::updateGuiInt(bool allowYield)
lastStatCallSpeed = timeNow;
if (numeric::dist(phaseStartMs, timeNow) >= 1000) //discard stats for first second: probably messy
- perf->addSample(objectsCurrent, to<double>(dataCurrent), timeNow);
+ perf->addSample(itemsCurrent, to<double>(dataCurrent), timeNow);
//current speed -> Win 7 copy uses 1 sec update interval instead
- setText(*m_staticTextSpeed, perf->getBytesPerSecond(), &layoutChanged);
+ Opt<std::wstring> bps = perf->getBytesPerSecond();
+ Opt<std::wstring> ips = perf->getItemsPerSecond();
+ pnl.m_panelGraphBytes->setAttributes(pnl.m_panelGraphBytes->getAttributes().setCornerText(bps ? *bps : L"", Graph2D::CORNER_TOP_LEFT));
+ pnl.m_panelGraphItems->setAttributes(pnl.m_panelGraphItems->getAttributes().setCornerText(ips ? *ips : L"", Graph2D::CORNER_TOP_LEFT));
+ //setText(*pnl.m_staticTextSpeed, perf->getBytesPerSecond(), &layoutChanged);
//remaining time: display with relative error of 10% - based on samples taken every 0.5 sec only
//-> call more often than once per second to correctly show last few seconds countdown, but don't call too often to avoid occasional jitter
- setText(*m_staticTextRemTime, perf->getRemainingTime(to<double>(dataTotal - dataCurrent)), &layoutChanged);
+ Opt<std::wstring> rt = perf->getRemainingTime(to<double>(dataTotal - dataCurrent));
+ setText(*pnl.m_staticTextRemTime, rt ? *rt : L"-", &layoutChanged);
}
}
break;
}
- m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMinX(graphDataBytes->getXBegin()));
- m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMaxX(graphDataBytes->getXEnd()));
- m_panelGraph->Refresh();
+ pnl.m_panelGraphBytes->Refresh();
+ pnl.m_panelGraphItems->Refresh();
//time elapsed
const long timeElapSec = timeNow / 1000;
- setText(*m_staticTextTimeElapsed,
+ setText(*pnl.m_staticTextTimeElapsed,
timeElapSec < 3600 ?
wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") :
wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged);
- //do the ui update
+ //adapt layout after content changes above
if (layoutChanged)
{
- // Layout();
- // bSizerItemsRem->Layout();
- // bSizer171->Layout();
- //bSizerProgressStat->Layout(); //
- m_panelProgress->Layout(); //both needed
- //m_panelBackground->Layout(); //we use a dummy panel as actual background: replaces simple "Layout()" call
- //-> it seems this layout is not required, and even harmful: resets m_comboBoxExecFinished dropdown while user is selecting!
+ pnl.m_panelProgress->Layout();
+ //small statistics panels:
+ //pnl.m_panelItemsProcessed->Layout();
+ pnl.m_panelItemsRemaining->Layout();
+ pnl.m_panelTimeRemaining ->Layout();
+ //pnl.m_panelTimeElapsed->Layout(); -> needed?
}
#ifdef ZEN_WIN
//workaround Windows 7 bug messing up z-order after temporary application hangs: https://sourceforge.net/tracker/index.php?func=detail&aid=3376523&group_id=234430&atid=1093080
- if (mainDialog)
- if (evaluateZorder(*this, *mainDialog) == ZORDER_WRONG)
+ //This is still needed no matter if wxDialog or wxPanel is used! (2013-07)
+ if (parentFrame_)
+ if (evaluateZorder(*this, *parentFrame_) == ZORDER_WRONG)
{
- HWND hProgress = static_cast<HWND>(GetHWND());
+ HWND hProgress = static_cast<HWND>(this->GetHWND());
if (::IsWindowVisible(hProgress))
{
::ShowWindow(hProgress, SW_HIDE); //make Windows recalculate z-order
@@ -1342,47 +1570,58 @@ void SyncProgressDialogImpl::updateGuiInt(bool allowYield)
//support for pause button
if (paused_)
{
+ /*
+ ZEN_ON_SCOPE_EXIT(resumeTimer()); -> crashes on Fedora; WHY???
+ => likely compiler bug!!!
+ 1. no crash on Fedora for: ZEN_ON_SCOPE_EXIT(this->resumeTimer());
+ 1. no crash if we derive from wxFrame instead of template "TopLevelDialog"
+ 2. no crash on Ubuntu GCC
+ 3. following makes GCC crash already during compilation: auto dfd = zen::makeGuard([this]{ resumeTimer(); });
+ */
+
stopTimer();
- ZEN_ON_SCOPE_EXIT(resumeTimer());
+
while (paused_)
{
- wxMilliSleep(UI_UPDATE_INTERVAL);
- updateUiNow(); //receive UI message that end pause
+ wxTheApp->Yield(); //receive UI message that end pause OR forceful termination!
+ //*first* refresh GUI (removing flicker) before sleeping!
+ boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL));
}
+ //if SyncProgressDialogImpl::OnClose() already wxWindow::Destroy() on OS X then this instance is already toast!
+ if (wereDead)
+ return; //GTFO and don't call this->resumeTimer()
+
+ resumeTimer();
}
- /*
- /|\
- | keep this sequence to ensure one full progress update before entering pause mode!
- \|/
- */
- updateUiNow(); //receive UI message that sets pause status
+ else
+ /*
+ /|\
+ | keep this sequence to ensure one full progress update before entering pause mode!
+ \|/
+ */
+ wxTheApp->Yield(); //receive UI message that sets pause status OR forceful termination!
}
else
- Update(); //don't wait until next idle event (who knows what blocking process comes next?)
+ this->Update(); //don't wait until next idle event (who knows what blocking process comes next?)
}
-std::wstring SyncProgressDialogImpl::getExecWhenFinishedCommand() const
-{
- return m_comboBoxExecFinished->getValue();
-}
-
-
-void SyncProgressDialogImpl::updateDialogStatus() //depends on "syncStat_, paused_, finalResult"
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::updateDialogStatus() //depends on "syncStat_, paused_, finalResult"
{
const wxString dlgStatusTxt = getDialogPhaseText(syncStat_, paused_, finalResult);
- m_staticTextPhase->SetLabel(dlgStatusTxt);
+ pnl.m_staticTextPhase->SetLabel(dlgStatusTxt);
//status bitmap
if (syncStat_) //sync running
{
auto setStatusBitmap = [&](const wchar_t* bmpName)
{
- m_animCtrlSyncing->Hide();
- m_bitmapStatus->SetBitmap(getResourceImage(bmpName));
- m_bitmapStatus->SetToolTip(dlgStatusTxt);
- m_bitmapStatus->Show();
+ pnl.m_animCtrlSyncing->Hide();
+ pnl.m_bitmapStatus->SetBitmap(getResourceImage(bmpName));
+ pnl.m_bitmapStatus->SetToolTip(dlgStatusTxt);
+ pnl.m_bitmapStatus->Show();
};
if (paused_)
@@ -1391,8 +1630,8 @@ void SyncProgressDialogImpl::updateDialogStatus() //depends on "syncStat_, pause
switch (syncStat_->currentPhase())
{
case ProcessCallback::PHASE_NONE:
- m_animCtrlSyncing->Hide();
- m_bitmapStatus->Hide();
+ pnl.m_animCtrlSyncing->Hide();
+ pnl.m_bitmapStatus->Hide();
break;
case ProcessCallback::PHASE_SCANNING:
@@ -1404,11 +1643,11 @@ void SyncProgressDialogImpl::updateDialogStatus() //depends on "syncStat_, pause
break;
case ProcessCallback::PHASE_SYNCHRONIZING:
- m_bitmapStatus->SetBitmap(getResourceImage(L"status_syncing"));
- m_bitmapStatus->SetToolTip(dlgStatusTxt);
- m_bitmapStatus->Show();
- m_animCtrlSyncing->Show();
- m_animCtrlSyncing->SetToolTip(dlgStatusTxt);
+ pnl.m_bitmapStatus->SetBitmap(getResourceImage(L"status_syncing"));
+ pnl.m_bitmapStatus->SetToolTip(dlgStatusTxt);
+ pnl.m_bitmapStatus->Show();
+ pnl.m_animCtrlSyncing->Show();
+ pnl.m_animCtrlSyncing->SetToolTip(dlgStatusTxt);
break;
}
}
@@ -1416,10 +1655,10 @@ void SyncProgressDialogImpl::updateDialogStatus() //depends on "syncStat_, pause
{
auto setStatusBitmap = [&](const wchar_t* bmpName, const std::wstring& tooltip)
{
- m_animCtrlSyncing->Hide();
- m_bitmapStatus->SetBitmap(getResourceImage(bmpName));
- m_bitmapStatus->Show();
- m_bitmapStatus->SetToolTip(tooltip);
+ pnl.m_animCtrlSyncing->Hide();
+ pnl.m_bitmapStatus->SetBitmap(getResourceImage(bmpName));
+ pnl.m_bitmapStatus->Show();
+ pnl.m_bitmapStatus->SetToolTip(tooltip);
};
switch (finalResult)
{
@@ -1479,21 +1718,15 @@ void SyncProgressDialogImpl::updateDialogStatus() //depends on "syncStat_, pause
//pause button
if (syncStat_) //sync running
- {
- if (paused_)
- m_buttonPause->SetLabel(_("Continue"));
- else
- m_buttonPause->SetLabel(_("Pause"));
- }
+ pnl.m_buttonPause->SetLabel(paused_ ? _("&Continue") : _("&Pause"));
- Layout();
- Refresh(); //a few pixels below the status text need refreshing
+ pnl.Layout();
+ this->Refresh(); //a few pixels below the status text need refreshing
}
-warn_static("osx: minimize to systray?")
-
-void SyncProgressDialogImpl::closeWindowDirectly() //this should really be called: do not call back + schedule deletion
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::closeWindowDirectly() //this should really be called: do not call back + schedule deletion
{
paused_ = false; //you never know?
//ATTENTION: dialog may live a little longer, so watch callbacks!
@@ -1502,11 +1735,12 @@ void SyncProgressDialogImpl::closeWindowDirectly() //this should really be calle
abortCb_ = nullptr;
//resumeFromSystray(); -> NO, instead ~SyncProgressDialogImpl() makes sure that main dialog is shown again!
- Close(); //generate close event: do NOT destroy window unconditionally!
+ this->Close(); //generate close event: do NOT destroy window unconditionally!
}
-void SyncProgressDialogImpl::processHasFinished(SyncResult resultId, const ErrorLog& log) //essential to call this in StatusHandler derived class destructor
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::processHasFinished(SyncResult resultId, const ErrorLog& log) //essential to call this in StatusHandler derived class destructor
{
//at the LATEST(!) to prevent access to currentStatusHandler
//enable okay and close events; may be set in this method ONLY
@@ -1530,36 +1764,30 @@ void SyncProgressDialogImpl::processHasFinished(SyncResult resultId, const Error
case ProcessCallback::PHASE_COMPARING_CONTENT:
case ProcessCallback::PHASE_SYNCHRONIZING:
{
- auto objectsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase());
- auto objectsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase());
- auto dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase());
- auto dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase());
+ const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase());
+ const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase());
+ const Int64 dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase());
+ const Int64 dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase());
assert(dataCurrent <= dataTotal);
//set overall speed (instead of current speed)
- auto getOverallBytesPerSecond = [&]() -> wxString
- {
- const long timeDelta = timeElapsed.Time() - phaseStartMs; //we need to consider "time within current phase" not total "timeElapsed"!
- if (timeDelta != 0)
- return filesizeToShortString(dataCurrent * 1000 / timeDelta) + _("/sec");
- return L"-"; //fallback
- };
+ const long timeDelta = timeElapsed.Time() - phaseStartMs; //we need to consider "time within current phase" not total "timeElapsed"!
+
+ const wxString overallBytesPerSecond = timeDelta == 0 ? wxString() : filesizeToShortString(dataCurrent * 1000 / timeDelta) + _("/sec");
+ const wxString overallItemsPerSecond = timeDelta == 0 ? wxString() : replaceCpy(_("%x items"), L"%x", formatThreeDigitPrecision(itemsCurrent * 1000.0 / timeDelta)) + _("/sec");
- m_staticTextSpeed->SetLabel(getOverallBytesPerSecond());
+ pnl.m_panelGraphBytes->setAttributes(pnl.m_panelGraphBytes->getAttributes().setCornerText(overallBytesPerSecond, Graph2D::CORNER_TOP_LEFT));
+ pnl.m_panelGraphItems->setAttributes(pnl.m_panelGraphItems->getAttributes().setCornerText(overallItemsPerSecond, Graph2D::CORNER_TOP_LEFT));
//show new element "items processed"
- m_staticTextLabelItemsProc->Show(true);
- bSizerItemsProc ->Show(true);
- m_staticTextProcessedObj ->SetLabel(toGuiString(objectsCurrent));
- m_staticTextDataProcessed->SetLabel(L"(" + filesizeToShortString(dataCurrent) + L")");
+ pnl.m_panelItemsProcessed->Show();
+ pnl.m_staticTextProcessedObj ->SetLabel(toGuiString(itemsCurrent));
+ pnl.m_staticTextDataProcessed->SetLabel(L"(" + filesizeToShortString(dataCurrent) + L")");
//hide remaining elements...
- if (objectsCurrent == objectsTotal && //...if everything was processed successfully
- dataCurrent == dataTotal)
- {
- m_staticTextLabelItemsRem->Show(false);
- bSizerItemsRem ->Show(false);
- }
+ if (itemsCurrent == itemsTotal && //...if everything was processed successfully
+ dataCurrent == dataTotal)
+ pnl.m_panelItemsRemaining->Hide();
}
break;
}
@@ -1576,62 +1804,64 @@ void SyncProgressDialogImpl::processHasFinished(SyncResult resultId, const Error
resumeFromSystray(); //if in tray mode...
- EnableCloseButton(true);
+ this->EnableCloseButton(true);
- m_buttonCancel->Disable();
- m_buttonCancel->Hide();
- m_buttonPause->Disable();
- m_buttonPause->Hide();
- m_buttonClose->Show();
- m_buttonClose->Enable();
+ pnl.m_bpButtonMinimizeToTray->Hide();
+ pnl.m_buttonCancel->Disable();
+ pnl.m_buttonCancel->Hide();
+ pnl.m_buttonPause->Disable();
+ pnl.m_buttonPause->Hide();
+ pnl.m_buttonClose->Show();
+ pnl.m_buttonClose->Enable();
- bSizerExecFinished->Show(false);
+ pnl.m_buttonClose->SetFocus();
- //set std order after button visibility was set
- setStandardButtonOrder(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonClose));
-
- if (IsShown()) //don't steal focus when residing in sys-tray!
- m_buttonClose->SetFocus();
+ pnl.bSizerExecFinished->Show(false);
- //m_animCtrlSyncing->Stop();
- //m_animCtrlSyncing->Hide();
+ //set std order after button visibility was set
+ setStandardButtonOrder(*pnl.bSizerStdButtons, StdButtons().setAffirmative(pnl.m_buttonClose));
//hide current operation status
- m_staticTextStatus->Hide();
+ pnl.bSizerStatusText->Show(false);
- //show and prepare final statistics
- m_notebookResult->Show();
+ //show and prepare final statistics
+ pnl.m_notebookResult->Show();
#if defined ZEN_WIN || defined ZEN_LINUX
- m_staticlineFooter->Hide(); //win: m_notebookResult already has a window frame
+ pnl.m_staticlineFooter->Hide(); //win: m_notebookResult already has a window frame
#endif
- //show total time
- m_staticTextLabelElapsedTime->SetLabel(_("Total time:")); //it's not "elapsed time" anymore
-
//hide remaining time
- m_staticTextLabelRemTime->Show(false);
- m_staticTextRemTime ->Show(false);
+ pnl.m_panelTimeRemaining->Hide();
//1. re-arrange graph into results listbook
- bSizerRoot->Detach(m_panelProgress);
- m_panelProgress->Reparent(m_notebookResult);
+ pnl.bSizerRoot->Detach(pnl.m_panelProgress);
+ pnl.m_panelProgress->Reparent(pnl.m_notebookResult);
#ifdef ZEN_LINUX //does not seem to be required on Win or OS X
wxTheApp->Yield(); //wxGTK 2.9.3 fails miserably at "reparent" whithout this
#endif
- m_notebookResult->AddPage(m_panelProgress, _("Statistics"), true); //AddPage() takes ownership!
+ pnl.m_notebookResult->AddPage(pnl.m_panelProgress, _("Statistics"), true); //AddPage() takes ownership!
//2. log file
const size_t posLog = 1;
- LogPanel* logPanel = new LogPanel(m_notebookResult, log); //owned by m_notebookResult
- m_notebookResult->AddPage(logPanel, _("Logging"), false);
+ LogPanel* logPanel = new LogPanel(pnl.m_notebookResult, log); //owned by m_notebookResult
+ pnl.m_notebookResult->AddPage(logPanel, _("Log"), false);
//bSizerHoldStretch->Insert(0, logPanel, 1, wxEXPAND);
//show log instead of graph if errors occurred! (not required for ignored warnings)
if (log.getItemCount(TYPE_ERROR | TYPE_FATAL_ERROR) > 0)
- m_notebookResult->ChangeSelection(posLog);
+ pnl.m_notebookResult->ChangeSelection(posLog);
+
+ //this->Fit(); //not a good idea: will shrink even if window is maximized or was enlarged by the user
+ pnl.Layout();
+
+ pnl.m_panelProgress->Layout();
+ //small statistics panels:
+ pnl.m_panelItemsProcessed->Layout();
+ pnl.m_panelItemsRemaining->Layout();
+ //pnl.m_panelTimeRemaining->Layout();
+ //pnl.m_panelTimeElapsed->Layout(); -> needed?
- Layout();
//play (optional) sound notification after sync has completed -> only play when waiting on results dialog, seems to be pointless otherwise!
switch (finalResult)
{
@@ -1648,19 +1878,19 @@ void SyncProgressDialogImpl::processHasFinished(SyncResult resultId, const Error
break;
}
- //Raise(); -> don't! user may be watching a movie in the meantime ;)
- warn_static("was ist mit resumeFromSystray:: Raise()??")
+ //Raise(); -> don't! user may be watching a movie in the meantime ;) note: resumeFromSystray() also calls Raise()!
}
-void SyncProgressDialogImpl::OnOkay(wxCommandEvent& event)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::OnOkay(wxCommandEvent& event)
{
- isZombie = true; //on Fedora an iconize event is issued *before* entering SyncProgressDialogImpl::OnClose()!!!
- Close(); //generate close event: do NOT destroy window unconditionally!
+ this->Close(); //generate close event: do NOT destroy window unconditionally!
}
-void SyncProgressDialogImpl::OnCancel(wxCommandEvent& event)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::OnCancel(wxCommandEvent& event)
{
paused_ = false;
updateDialogStatus(); //update status + pause button
@@ -1671,14 +1901,16 @@ void SyncProgressDialogImpl::OnCancel(wxCommandEvent& event)
}
-void SyncProgressDialogImpl::OnPause(wxCommandEvent& event)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::OnPause(wxCommandEvent& event)
{
paused_ = !paused_;
updateDialogStatus(); //update status + pause button
}
-void SyncProgressDialogImpl::OnClose(wxCloseEvent& event)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::OnClose(wxCloseEvent& event)
{
//this event handler may be called *during* sync, e.g. due to a system shutdown (Windows), anytime (OS X)
//try to stop sync gracefully and cross fingers:
@@ -1695,68 +1927,86 @@ void SyncProgressDialogImpl::OnClose(wxCloseEvent& event)
syncStat_ = nullptr;
abortCb_ = nullptr;
- isZombie = true; //it "lives" until cleanup in next idle event
- Destroy();
-}
-
-
-void SyncProgressDialogImpl::OnIconize(wxIconizeEvent& event)
-{
- if (isZombie) return; //wxGTK sends iconize event *after* wxWindow::Destroy, sigh...
-
- if (event.IsIconized()) //ATTENTION: iconize event is also triggered on "Restore"! (at least under Linux)
- minimizeToTray();
- else
- resumeFromSystray(); //may be initiated by "show desktop" although all windows are hidden!
+ wereDead = true;
+ this->Destroy(); //wxWidgets OS X: simple "delete"!!!!!!!
}
-void SyncProgressDialogImpl::OnResumeFromTray(wxCommandEvent& event)
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::OnIconize(wxIconizeEvent& event)
{
- resumeFromSystray();
+ /*
+ propagate progress dialog minimize/maximize to parent
+ -----------------------------------------------------
+ Fedora/Debian/Ubuntu:
+ - wxDialog cannot be minimized
+ - worse, wxGTK sends stray iconize events *after* wxDialog::Destroy()
+ - worse, on Fedora an iconize event is issued directly after calling Close()
+ - worse, even wxDialog::Hide() causes iconize event!
+ => nothing to do
+ SUSE:
+ - wxDialog can be minimized (it just vanishes!) and in general also minimizes parent: except for our progress wxDialog!!!
+ - worse, wxDialog::Hide() causes iconize event
+ - probably the same issues with stray iconize events like Fedora/Debian/Ubuntu
+ - minimize button is always shown, even if wxMINIMIZE_BOX is omitted!
+ => nothing to do
+ Mac OS X:
+ - wxDialog can be minimized and automatically minimizes parent
+ - no iconize events seen by wxWidgets!
+ => nothing to do
+ Windows:
+ - wxDialog can be minimized but does not also minimize parent
+ - iconize events only seen for manual minimize
+ => propagate event to parent
+ */
+#ifdef ZEN_WIN
+ if (parentFrame_)
+ if (parentFrame_->IsIconized() != event.IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
+ parentFrame_->Iconize(event.IsIconized());
+#endif
+ event.Skip();
}
-void SyncProgressDialogImpl::minimizeToTray()
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::minimizeToTray()
{
-// wxMessageBox(L"hi");
-
if (!trayIcon.get())
{
- trayIcon = make_unique<FfsTrayIcon>();
- trayIcon->Connect(FFS_REQUEST_RESUME_TRAY_EVENT, wxCommandEventHandler(SyncProgressDialogImpl::OnResumeFromTray), nullptr, this);
- //tray icon has shorter lifetime than this => no need to disconnect event later
+ trayIcon = make_unique<FfsTrayIcon>([this] { this->resumeFromSystray(); }); //FfsTrayIcon lifetime is a subset of "this"'s lifetime!
+ //we may destroy FfsTrayIcon even while in the FfsTrayIcon callback!!!!
updateGuiInt(false); //set tray tooltip + progress: e.g. no updates while paused
- Hide();
- if (mainDialog)
- mainDialog->Hide();
+ this->Hide();
+ if (parentFrame_)
+ parentFrame_->Hide();
}
}
-void SyncProgressDialogImpl::resumeFromSystray()
+template <class TopLevelDialog>
+void SyncProgressDialogImpl<TopLevelDialog>::resumeFromSystray()
{
if (trayIcon)
{
trayIcon.reset();
- if (mainDialog)
+ if (parentFrame_)
{
- if (mainDialog->IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
- mainDialog->Iconize(false);
- mainDialog->Show();
- mainDialog->Raise();
+ //if (parentFrame_->IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
+ // parentFrame_->Iconize(false);
+ parentFrame_->Show();
+ parentFrame_->Raise();
}
- if (IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
- Iconize(false);
- Show();
- Raise();
- SetFocus();
+ //if (IsIconized()) //caveat: if window is maximized calling Iconize(false) will erroneously un-maximize!
+ // Iconize(false);
+ this->Show();
+ this->Raise();
+ this->SetFocus();
- updateDialogStatus(); //restore Windows 7 task bar status (e.g. required in pause mode)
+ updateDialogStatus(); //restore Windows 7 task bar status (e.g. required in pause mode)
updateGuiInt(false); //restore Windows 7 task bar progress (e.g. required in pause mode)
}
}
@@ -1766,11 +2016,18 @@ void SyncProgressDialogImpl::resumeFromSystray()
SyncProgressDialog* createProgressDialog(zen::AbortCallback& abortCb,
const std::function<void()>& notifyWindowTerminate, //note: user closing window cannot be prevented on OS X! (And neither on Windows during system shutdown!)
const zen::Statistics& syncStat,
- wxTopLevelWindow* parentWindow, //may be nullptr
+ wxFrame* parentWindow, //may be nullptr
bool showProgress,
const wxString& jobName,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory)
{
- return new SyncProgressDialogImpl(abortCb, notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, execWhenFinished, execFinishedHistory);
+ if (parentWindow) //sync from GUI
+ return new SyncProgressDialogImpl<wxDialog>(wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER,
+ [&](wxDialog& progDlg) { return parentWindow; }, abortCb,
+ notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, execWhenFinished, execFinishedHistory);
+ else //FFS batch job
+ return new SyncProgressDialogImpl<wxFrame>(wxDEFAULT_FRAME_STYLE,
+ [](wxFrame& progDlg) { return &progDlg; }, abortCb,
+ notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, execWhenFinished, execFinishedHistory);
}
diff --git a/ui/progress_indicator.h b/ui/progress_indicator.h
index 0789ca80..e2dbb99c 100644
--- a/ui/progress_indicator.h
+++ b/ui/progress_indicator.h
@@ -10,7 +10,7 @@
#include <functional>
#include <zen/error_log.h>
//#include <zen/zstring.h>
-#include <wx/toplevel.h>
+#include <wx/frame.h>
#include "../lib/status_handler.h"
//#include "main_dlg.h"
@@ -18,7 +18,7 @@
class CompareProgressDialog
{
public:
- CompareProgressDialog(wxTopLevelWindow& parentWindow); //CompareProgressDialog will be owned by parentWindow!
+ CompareProgressDialog(wxFrame& parentWindow); //CompareProgressDialog will be owned by parentWindow!
wxWindow* getAsWindow(); //convenience! don't abuse!
@@ -52,7 +52,7 @@ struct SyncProgressDialog
//---------------------------------------------------------------------------
- virtual wxWindow* getAsWindow() = 0; //convenience! don't abuse!
+ virtual wxWindow* getWindowIfVisible() = 0; //may be nullptr; don't abuse, use as parent for modal dialogs only!
virtual void initNewPhase() = 0; //call after "StatusHandler::initNewPhase"
virtual void notifyProgressChange() = 0; //throw (), required by graph!
@@ -71,7 +71,7 @@ protected:
SyncProgressDialog* createProgressDialog(zen::AbortCallback& abortCb,
const std::function<void()>& notifyWindowTerminate, //note: user closing window cannot be prevented on OS X! (And neither on Windows during system shutdown!)
const zen::Statistics& syncStat,
- wxTopLevelWindow* parentWindow, //may be nullptr
+ wxFrame* parentWindow, //may be nullptr
bool showProgress,
const wxString& jobName,
const std::wstring& execWhenFinished,
diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp
index 304e4269..b7b7828b 100644
--- a/ui/small_dlgs.cpp
+++ b/ui/small_dlgs.cpp
@@ -384,10 +384,9 @@ void DeleteDialog::updateGui()
{
wxWindowUpdateLocker dummy(this); //avoid display distortion
- const std::pair<Zstring, int> delInfo = zen::deleteFromGridAndHDPreview(
- rowsToDeleteOnLeft,
- rowsToDeleteOnRight,
- m_checkBoxDeleteBothSides->GetValue());
+ const std::pair<Zstring, int> delInfo = zen::deleteFromGridAndHDPreview(rowsToDeleteOnLeft,
+ rowsToDeleteOnRight,
+ m_checkBoxDeleteBothSides->GetValue());
wxString header;
if (m_checkBoxUseRecycler->GetValue())
{
@@ -406,7 +405,13 @@ void DeleteDialog::updateGui()
const wxString& fileList = utfCvrtTo<wxString>(delInfo.first);
m_textCtrlFileList->ChangeValue(fileList);
-
+ /*
+ There is a nasty bug on wxGTK under Ubuntu: If a multi-line wxTextCtrl contains so many lines that scrollbars are shown,
+ it re-enables all windows that are supposed to be disabled during the current modal loop!
+ This only affects Ubuntu/wxGTK! No such issue on Debian/wxGTK or Suse/wxGTK
+ => another Unity problem like the following?
+ http://trac.wxwidgets.org/ticket/14823 "Menu not disabled when showing modal dialogs in wxGTK under Unity"
+ */
Layout();
}
diff --git a/ui/switch_to_gui.h b/ui/switch_to_gui.h
index a3cf6827..20fe81de 100644
--- a/ui/switch_to_gui.h
+++ b/ui/switch_to_gui.h
@@ -27,7 +27,7 @@ public:
void execute() const
{
- MainDialog::create(guiCfg, referenceFiles, globalSettings_, true); //new toplevel window
+ MainDialog::create(guiCfg, referenceFiles, &globalSettings_, true); //new toplevel window
}
private:
diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp
index 806914a3..97518be1 100644
--- a/ui/sync_cfg.cpp
+++ b/ui/sync_cfg.cpp
@@ -107,15 +107,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
switch (dirCfg.exLeftSideOnly)
{
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
buttonLeftOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_create_right")));
buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_RIGHT));
break;
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
buttonLeftOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_delete_left")));
buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DELETE_LEFT));
break;
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
buttonLeftOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none")));
buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
@@ -123,15 +123,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
switch (dirCfg.exRightSideOnly)
{
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
buttonRightOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_delete_right")));
buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DELETE_RIGHT));
break;
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
buttonRightOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_create_left")));
buttonRightOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_LEFT));
break;
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
buttonRightOnly->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none")));
buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
@@ -139,15 +139,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
switch (dirCfg.leftNewer)
{
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
buttonLeftNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right")));
buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
buttonLeftNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left")));
buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
buttonLeftNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none")));
buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
@@ -155,15 +155,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
switch (dirCfg.rightNewer)
{
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
buttonRightNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right")));
buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
buttonRightNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left")));
buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
buttonRightNewer->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none")));
buttonRightNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
@@ -171,15 +171,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
switch (dirCfg.different)
{
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
buttonDifferent->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right")));
buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
buttonDifferent->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left")));
buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
buttonDifferent->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_none")));
buttonDifferent->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
@@ -187,15 +187,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
switch (dirCfg.conflict)
{
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
buttonConflict->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_right")));
buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
buttonConflict->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"so_update_left")));
buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
buttonConflict->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"cat_conflict"))); //silent dependency to algorithm.cpp::Redetermine!!!
buttonConflict->SetToolTip(_("Leave as unresolved conflict"));
break;
@@ -495,14 +495,14 @@ void toggleSyncDirection(SyncDirection& current)
{
switch (current)
{
- case SYNC_DIR_RIGHT:
- current = SYNC_DIR_LEFT;
+ case SyncDirection::RIGHT:
+ current = SyncDirection::LEFT;
break;
- case SYNC_DIR_LEFT:
- current = SYNC_DIR_NONE;
+ case SyncDirection::LEFT:
+ current = SyncDirection::NONE;
break;
- case SYNC_DIR_NONE:
- current = SYNC_DIR_RIGHT;
+ case SyncDirection::NONE:
+ current = SyncDirection::RIGHT;
break;
}
}
diff --git a/ui/taskbar.cpp b/ui/taskbar.cpp
index 0e019d04..e6aadc90 100644
--- a/ui/taskbar.cpp
+++ b/ui/taskbar.cpp
@@ -30,7 +30,7 @@ using namespace tbseven;
class Taskbar::Pimpl //throw TaskbarNotAvailable
{
public:
- Pimpl(const wxTopLevelWindow& window) :
+ Pimpl(const wxFrame& window) :
assocWindow(window.GetHWND()),
setStatus_ (getDllName(), funName_setStatus),
setProgress_(getDllName(), funName_setProgress)
@@ -86,7 +86,7 @@ const char FFS_DESKTOP_FILE[] = "freefilesync.desktop";
class Taskbar::Pimpl //throw (TaskbarNotAvailable)
{
public:
- Pimpl(const wxTopLevelWindow& window) :
+ Pimpl(const wxFrame& window) :
tbEntry(unity_launcher_entry_get_for_desktop_id(FFS_DESKTOP_FILE))
//tbEntry(unity_launcher_entry_get_for_app_uri("application://freefilesync.desktop"))
{
@@ -133,7 +133,7 @@ private:
class Taskbar::Pimpl
{
public:
- Pimpl(const wxTopLevelWindow& window) {}
+ Pimpl(const wxFrame& window) {}
~Pimpl() { setDockText(""); }
@@ -161,7 +161,7 @@ private:
class Taskbar::Pimpl
{
public:
- Pimpl(const wxTopLevelWindow& window) { throw TaskbarNotAvailable(); }
+ Pimpl(const wxFrame& window) { throw TaskbarNotAvailable(); }
void setStatus(Status status) {}
void setProgress(double fraction) {}
};
@@ -169,7 +169,7 @@ public:
//########################################################################################################
-Taskbar::Taskbar(const wxTopLevelWindow& window) : pimpl_(new Pimpl(window)) {} //throw TaskbarNotAvailable
+Taskbar::Taskbar(const wxFrame& window) : pimpl_(new Pimpl(window)) {} //throw TaskbarNotAvailable
Taskbar::~Taskbar() {}
void Taskbar::setStatus(Status status) { pimpl_->setStatus(status); }
diff --git a/ui/taskbar.h b/ui/taskbar.h
index ad708794..82e08656 100644
--- a/ui/taskbar.h
+++ b/ui/taskbar.h
@@ -8,7 +8,7 @@
#define TASKBARPROGRESS_H_INCLUDED
#include <memory>
-#include <wx/toplevel.h>
+#include <wx/frame.h>
/*
Windows 7; show progress in windows superbar via ITaskbarList3 Interface: http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx
@@ -27,7 +27,7 @@ class TaskbarNotAvailable {};
class Taskbar
{
public:
- Taskbar(const wxTopLevelWindow& window); //throw TaskbarNotAvailable()
+ Taskbar(const wxFrame& window); //throw TaskbarNotAvailable
~Taskbar();
enum Status
diff --git a/ui/tray_icon.cpp b/ui/tray_icon.cpp
index 6a9c640c..3826458f 100644
--- a/ui/tray_icon.cpp
+++ b/ui/tray_icon.cpp
@@ -14,8 +14,6 @@
#include "../lib/resources.h"
-const wxEventType FFS_REQUEST_RESUME_TRAY_EVENT = wxNewEventType();
-
namespace
{
void fillRange(wxImage& img, int pixelFirst, int pixelLast, const wxColor& col) //tolerant input range
@@ -52,90 +50,56 @@ void fillRange(wxImage& img, int pixelFirst, int pixelLast, const wxColor& col)
wxIcon generateProgressIcon(const wxImage& logo, double fraction) //generate icon with progress indicator
{
- if (!logo.IsOk())
+ if (!logo.IsOk() || logo.GetWidth() <= 0 || logo.GetHeight() <= 0)
return wxIcon();
const int pixelCount = logo.GetWidth() * logo.GetHeight();
- const int startFillPixel = std::min(numeric::round(fraction * pixelCount), pixelCount);
+ const int startFillPixel = numeric::confineCpy(numeric::round(fraction * pixelCount), 0, pixelCount);
//minor optimization
static std::pair<int, wxIcon> buffer = std::make_pair(-1, wxNullIcon);
if (buffer.first != startFillPixel)
{
- //progress bar
- if (logo.GetWidth() > 0 &&
- logo.GetHeight() > 0)
- {
- wxImage genImage(logo.Copy()); //workaround wxWidgets' screwed-up design from hell: their copy-construction implements reference-counting WITHOUT copy-on-write!
-
- //gradually make FFS icon brighter while nearing completion
- zen::brighten(genImage, -200 * (1 - fraction));
-
- //fill black border row
- if (startFillPixel <= pixelCount - genImage.GetWidth())
- {
- /*
- --------
- ---bbbbb
- bbbbSyyy S : start yellow remainder
- yyyyyyyy
- */
- int bStart = startFillPixel - genImage.GetWidth();
- if (bStart % genImage.GetWidth() != 0) //add one more black pixel, see ascii-art
- --bStart;
- fillRange(genImage, bStart, startFillPixel, *wxBLACK);
- }
- else if (startFillPixel < pixelCount)
- {
- //special handling for last row
- /*
- --------
- --------
- ---bbbbb
- ---bSyyy S : start yellow remainder
- */
- int bStart = startFillPixel - genImage.GetWidth() - 1;
- int bEnd = (bStart / genImage.GetWidth() + 1) * genImage.GetWidth();
-
- fillRange(genImage, bStart, bEnd, *wxBLACK);
- fillRange(genImage, startFillPixel - 1, startFillPixel, *wxBLACK);
- }
+ wxImage genImage(logo.Copy()); //workaround wxWidgets' screwed-up design from hell: their copy-construction implements reference-counting WITHOUT copy-on-write!
- //fill yellow remainder
- fillRange(genImage, startFillPixel, pixelCount, wxColour(240, 200, 0));
+ //gradually make FFS icon brighter while nearing completion
+ zen::brighten(genImage, -200 * (1 - fraction));
+ //fill black border row
+ if (startFillPixel <= pixelCount - genImage.GetWidth())
+ {
/*
- const int indicatorWidth = genImage.GetWidth() * .4;
- const int indicatorXBegin = std::ceil((genImage.GetWidth() - indicatorWidth) / 2.0);
- const int indicatorYBegin = genImage.GetHeight() - indicatorHeight;
-
- //draw progress indicator: do NOT use wxDC::DrawRectangle! Doesn't respect alpha in Windows, but does in Linux!
- //We need a simple, working solution:
-
- for (int row = indicatorYBegin; row < genImage.GetHeight(); ++row)
- {
- for (int col = indicatorXBegin; col < indicatorXBegin + indicatorWidth; ++col)
- {
- unsigned char* const pixelBegin = data + (row * genImage.GetWidth() + col) * 3;
- pixelBegin[0] = 240; //red
- pixelBegin[1] = 200; //green
- pixelBegin[2] = 0; //blue
- }
- }
-
- if (genImage.HasAlpha())
- {
- unsigned char* const alpha = genImage.GetAlpha();
- //make progress indicator fully opaque:
- for (int row = indicatorYBegin; row < genImage.GetHeight(); ++row)
- ::memset(alpha + row * genImage.GetWidth() + indicatorXBegin, wxIMAGE_ALPHA_OPAQUE, indicatorWidth);
- }
+ --------
+ ---bbbbb
+ bbbbSyyy S : start yellow remainder
+ yyyyyyyy
*/
- buffer.second.CopyFromBitmap(wxBitmap(genImage));
+ int bStart = startFillPixel - genImage.GetWidth();
+ if (bStart % genImage.GetWidth() != 0) //add one more black pixel, see ascii-art
+ --bStart;
+ fillRange(genImage, bStart, startFillPixel, *wxBLACK);
+ }
+ else if (startFillPixel < pixelCount)
+ {
+ //special handling for last row
+ /*
+ --------
+ --------
+ ---bbbbb
+ ---bSyyy S : start yellow remainder
+ */
+ int bStart = startFillPixel - genImage.GetWidth() - 1;
+ int bEnd = (bStart / genImage.GetWidth() + 1) * genImage.GetWidth();
+
+ fillRange(genImage, bStart, bEnd, *wxBLACK);
+ fillRange(genImage, startFillPixel - 1, startFillPixel, *wxBLACK);
}
- else
- buffer.second = wxIcon();
+
+ //fill yellow remainder
+ fillRange(genImage, startFillPixel, pixelCount, wxColour(240, 200, 0));
+
+ buffer.second.CopyFromBitmap(wxBitmap(genImage));
}
return buffer.second;
@@ -145,7 +109,7 @@ wxIcon generateProgressIcon(const wxImage& logo, double fraction) //generate ico
enum Selection
{
- CONTEXT_RESTORE = 1, //wxWidgets: "A MenuItem ID of Zero does not work under Mac"
+ CONTEXT_RESTORE = 1, //wxWidgets: "A MenuItem ID of zero does not work under Mac"
CONTEXT_ABOUT = wxID_ABOUT
};
}
@@ -154,95 +118,107 @@ enum Selection
class FfsTrayIcon::TaskBarImpl : public wxTaskBarIcon
{
public:
- TaskBarImpl(FfsTrayIcon& parent) : parent_(&parent) {}
+ TaskBarImpl(const std::function<void()>& onRequestResume) : onRequestResume_(onRequestResume)
+ {
+ Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(TaskBarImpl::OnDoubleClick), nullptr, this); //register double-click
+ }
- void parentHasDied() { parent_ = nullptr; }
+ //virtual ~TaskBarImpl(){}
+
+ void dontCallbackAnymore() { onRequestResume_ = nullptr; }
private:
virtual wxMenu* CreatePopupMenu()
{
- if (!parent_)
+ if (!onRequestResume_)
return nullptr;
wxMenu* contextMenu = new wxMenu;
- contextMenu->Append(CONTEXT_ABOUT, _("&About"));
- contextMenu->AppendSeparator();
contextMenu->Append(CONTEXT_RESTORE, _("&Restore"));
+ contextMenu->AppendSeparator();
+ contextMenu->Append(CONTEXT_ABOUT, _("&About"));
//event handling
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FfsTrayIcon::OnContextMenuSelection), nullptr, parent_);
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TaskBarImpl::OnContextMenuSelection), nullptr, this);
return contextMenu; //ownership transferred to caller
}
- FfsTrayIcon* parent_;
+ void OnContextMenuSelection(wxCommandEvent& event)
+ {
+ switch (static_cast<Selection>(event.GetId()))
+ {
+ case CONTEXT_ABOUT:
+ {
+ //ATTENTION: the modal dialog below does NOT disable all GUI input, e.g. user may still double-click on tray icon
+ //which will implicitly destroy the tray icon while still showing the modal dialog
+ SetEvtHandlerEnabled(false);
+ ZEN_ON_SCOPE_EXIT(SetEvtHandlerEnabled(true));
+
+ zen::showAboutDialog(nullptr);
+ }
+ break;
+
+ case CONTEXT_RESTORE:
+ if (onRequestResume_)
+ onRequestResume_();
+ break;
+ }
+ }
+
+ void OnDoubleClick(wxCommandEvent& event)
+ {
+ if (onRequestResume_)
+ onRequestResume_();
+ }
+
+ std::function<void()> onRequestResume_;
};
-FfsTrayIcon::FfsTrayIcon() :
- trayIcon(new TaskBarImpl(*this)),
- fractionLast(1), //show FFS logo by default
+FfsTrayIcon::FfsTrayIcon(const std::function<void()>& onRequestResume) :
+ trayIcon(new TaskBarImpl(onRequestResume)),
+ activeFraction(1), //show FFS logo by default
#if defined ZEN_WIN || defined ZEN_MAC //16x16 seems to be the only size that is shown correctly on OS X
logo(getResourceImage(L"FFS_tray_16x16").ConvertToImage())
#elif defined ZEN_LINUX
logo(getResourceImage(L"FFS_tray_24x24").ConvertToImage())
#endif
{
- trayIcon->SetIcon(generateProgressIcon(logo, fractionLast), L"FreeFileSync");
- trayIcon->Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(FfsTrayIcon::OnDoubleClick), nullptr, this); //register double-click
+ trayIcon->SetIcon(generateProgressIcon(logo, activeFraction), L"FreeFileSync");
}
FfsTrayIcon::~FfsTrayIcon()
{
- trayIcon->RemoveIcon(); //hide icon until final deletion takes place
- trayIcon->Disconnect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(FfsTrayIcon::OnDoubleClick), nullptr, this);
- trayIcon->parentHasDied(); //TaskBarImpl (potentially) has longer lifetime than FfsTrayIcon: avoid callback!
-
- //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking)
- if (!wxPendingDelete.Member(trayIcon))
- wxPendingDelete.Append(trayIcon);
-}
+ trayIcon->dontCallbackAnymore(); //TaskBarImpl has longer lifetime than FfsTrayIcon: avoid callback!
+ /*
+ This is not working correctly on OS X! It seems both wxTaskBarIcon::RemoveIcon() and ~wxTaskBarIcon() are broken and do NOT immediately
+ remove the icon from the system tray! Only some time later in the event loop which called these functions they will be removed.
+ Maybe some system component has still shared ownership? Objective C auto release pools are freed at the end of the current event loop...
+ Anyway, wxWidgets fails to disconnect the wxTaskBarIcon event handlers before calling "[m_statusitem release]"!
-void FfsTrayIcon::setToolTip(const wxString& toolTip)
-{
- toolTipLast = toolTip;
- trayIcon->SetIcon(generateProgressIcon(logo, fractionLast), toolTip); //another wxWidgets design bug: non-orthogonal method!
-}
+ => !!!clicking on the icon after ~wxTaskBarIcon ran crashes the application!!!
+ - if ~wxTaskBarIcon() ran from the SyncProgressDialog::updateGui() event loop (e.g. user manually clicking the icon) => icon removed on return
+ - if ~wxTaskBarIcon() ran from SyncProgressDialog::closeWindowDirectly() => leaves the icon dangling until user closes this dialog and outter event loop runs!
+ */
-void FfsTrayIcon::setProgress(double fraction)
-{
- fractionLast = fraction;
- trayIcon->SetIcon(generateProgressIcon(logo, fraction), toolTipLast);
+ trayIcon->RemoveIcon(); //required on Windows: unlike on OS X, wxPendingDelete does not kick in before main event loop!
+ //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking)
+ wxPendingDelete.Append(trayIcon);
}
-void FfsTrayIcon::OnContextMenuSelection(wxCommandEvent& event)
+void FfsTrayIcon::setToolTip(const wxString& toolTip)
{
- switch (static_cast<Selection>(event.GetId()))
- {
- case CONTEXT_ABOUT:
- {
- //ATTENTION: the modal dialog below does NOT disable all GUI input, e.g. user may still double-click on tray icon
- //which will implicitly destroy the tray icon while still showing the modal dialog
- trayIcon->SetEvtHandlerEnabled(false);
- zen::showAboutDialog(nullptr);
- trayIcon->SetEvtHandlerEnabled(true);
- }
- break;
- case CONTEXT_RESTORE:
- {
- wxCommandEvent dummy(FFS_REQUEST_RESUME_TRAY_EVENT);
- ProcessEvent(dummy);
- }
- }
+ activeToolTip = toolTip;
+ trayIcon->SetIcon(generateProgressIcon(logo, activeFraction), activeToolTip); //another wxWidgets design bug: non-orthogonal method!
}
-void FfsTrayIcon::OnDoubleClick(wxCommandEvent& event)
+void FfsTrayIcon::setProgress(double fraction)
{
- wxCommandEvent dummy(FFS_REQUEST_RESUME_TRAY_EVENT);
- ProcessEvent(dummy);
+ activeFraction = fraction;
+ trayIcon->SetIcon(generateProgressIcon(logo, activeFraction), activeToolTip);
}
-
diff --git a/ui/tray_icon.h b/ui/tray_icon.h
index 866d79d5..24c97eb0 100644
--- a/ui/tray_icon.h
+++ b/ui/tray_icon.h
@@ -4,38 +4,42 @@
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
-#ifndef TRAYICON_H_INCLUDED
-#define TRAYICON_H_INCLUDED
+#ifndef TRAYICON_H_84217830427534285
+#define TRAYICON_H_84217830427534285
-#include <wx/event.h>
+#include <functional>
#include <wx/image.h>
-//show tray icon with progress during lifetime of this instance
-//emits the following wxCommandEvent in case user double-clicks on tray icon or selects corresponding context menu item:
-extern const wxEventType FFS_REQUEST_RESUME_TRAY_EVENT;
+/*
+show tray icon with progress during lifetime of this instance
-class FfsTrayIcon : public wxEvtHandler
+ATTENTION: wxWidgets never assumes that an object indirectly destroys itself while processing an event!
+ this includes wxEvtHandler-derived objects!!!
+ it seems ProcessEvent() works (on Windows), but AddPendingEvent() will crash since it uses "this" after the event processing!
+
+=> don't derive from wxEvtHandler or any other wxWidgets object here!!!!!!
+=> use simple std::function as callback instead => instance may now be safely deleted in callback!
+*/
+
+class FfsTrayIcon
{
public:
- FfsTrayIcon();
+ FfsTrayIcon(const std::function<void()>& onRequestResume); //callback only held during lifetime of this instance
~FfsTrayIcon();
void setToolTip(const wxString& toolTip);
void setProgress(double fraction); //number between [0, 1], for small progress indicator
private:
- FfsTrayIcon(const FfsTrayIcon&);
- FfsTrayIcon& operator=(const FfsTrayIcon&);
-
- void OnContextMenuSelection(wxCommandEvent& event);
- void OnDoubleClick(wxCommandEvent& event);
+ FfsTrayIcon(const FfsTrayIcon&); //=delete
+ FfsTrayIcon& operator=(const FfsTrayIcon&); //=delete
class TaskBarImpl;
- TaskBarImpl* trayIcon; //actual tray icon (don't use inheritance to enable delayed deletion)
+ TaskBarImpl* trayIcon;
- wxString toolTipLast;
- double fractionLast;
+ wxString activeToolTip;
+ double activeFraction;
wxImage logo;
};
-#endif // TRAYICON_H_INCLUDED
+#endif //TRAYICON_H_84217830427534285
diff --git a/ui/tree_view.cpp b/ui/tree_view.cpp
index 10037380..791fa6cc 100644
--- a/ui/tree_view.cpp
+++ b/ui/tree_view.cpp
@@ -46,11 +46,11 @@ void TreeView::extractVisibleSubtree(HierarchyObject& hierObj, //in
if (fileObj.isActive())
switch (fileObj.getSyncDir())
{
- case SYNC_DIR_LEFT:
+ case SyncDirection::LEFT:
return fileObj.getFileSize<RIGHT_SIDE>();
- case SYNC_DIR_RIGHT:
+ case SyncDirection::RIGHT:
return fileObj.getFileSize<LEFT_SIDE>();
- case SYNC_DIR_NONE:
+ case SyncDirection::NONE:
break;
}
return std::max(fileObj.getFileSize<LEFT_SIDE>(), fileObj.getFileSize<RIGHT_SIDE>());
bgstack15