summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:19:49 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:19:49 +0200
commitc8e0e909b4a8d18319fc65434a10dc446434817c (patch)
treeeee91e7d2ce229dd043811eae8f1e2bd78061916 /ui
parent5.2 (diff)
downloadFreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.tar.gz
FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.tar.bz2
FreeFileSync-c8e0e909b4a8d18319fc65434a10dc446434817c.zip
5.3
Diffstat (limited to 'ui')
-rw-r--r--ui/batch_config.cpp128
-rw-r--r--ui/batch_config.h5
-rw-r--r--ui/batch_status_handler.cpp200
-rw-r--r--ui/batch_status_handler.h12
-rw-r--r--ui/check_version.cpp22
-rw-r--r--ui/check_version.h6
-rw-r--r--ui/custom_grid.cpp34
-rw-r--r--ui/exec_finished_box.cpp3
-rw-r--r--ui/folder_history_box.cpp8
-rw-r--r--ui/folder_pair.h8
-rw-r--r--ui/grid_view.cpp15
-rw-r--r--ui/grid_view.h12
-rw-r--r--ui/gui_generated.cpp139
-rw-r--r--ui/gui_generated.h18
-rw-r--r--ui/gui_status_handler.cpp238
-rw-r--r--ui/gui_status_handler.h19
-rw-r--r--ui/main_dlg.cpp521
-rw-r--r--ui/main_dlg.h1
-rw-r--r--ui/msg_popup.cpp34
-rw-r--r--ui/msg_popup.h11
-rw-r--r--ui/progress_indicator.cpp1168
-rw-r--r--ui/progress_indicator.h43
-rw-r--r--ui/search.cpp36
-rw-r--r--ui/search.h4
-rw-r--r--ui/small_dlgs.cpp103
-rw-r--r--ui/small_dlgs.h31
-rw-r--r--ui/sorting.h17
-rw-r--r--ui/sync_cfg.cpp17
-rw-r--r--ui/sync_cfg.h7
-rw-r--r--ui/taskbar.cpp4
-rw-r--r--ui/taskbar.h2
-rw-r--r--ui/tray_icon.cpp22
-rw-r--r--ui/tray_icon.h6
-rw-r--r--ui/tree_view.cpp8
-rw-r--r--ui/tree_view.h2
35 files changed, 1316 insertions, 1588 deletions
diff --git a/ui/batch_config.cpp b/ui/batch_config.cpp
index 0ed13399..cbb667ad 100644
--- a/ui/batch_config.cpp
+++ b/ui/batch_config.cpp
@@ -33,7 +33,7 @@ class BatchDialog: public BatchDlgGenerated
friend class FolderPairCallback;
public:
- BatchDialog(wxWindow* window,
+ BatchDialog(wxWindow* parent,
const wxString& referenceFile,
const xmlAccess::XmlBatchConfig& batchCfg,
const std::shared_ptr<FolderHistory>& folderHistLeft,
@@ -42,23 +42,23 @@ public:
size_t onCompletionHistoryMax);
private:
- virtual void OnCmpSettings( wxCommandEvent& event);
- virtual void OnSyncSettings( wxCommandEvent& event);
- virtual void OnConfigureFilter( wxCommandEvent& event);
- virtual void OnHelp( wxCommandEvent& event);
+ virtual void OnCmpSettings (wxCommandEvent& event);
+ virtual void OnSyncSettings (wxCommandEvent& event);
+ virtual void OnConfigureFilter(wxCommandEvent& event);
+ virtual void OnHelp (wxCommandEvent& event);
void OnCompSettingsContext(wxCommandEvent& event);
void OnSyncSettingsContext(wxCommandEvent& event);
void OnGlobalFilterContext(wxCommandEvent& event);
- virtual void OnCheckSaveLog( wxCommandEvent& event);
+ virtual void OnCheckSaveLog (wxCommandEvent& event);
virtual void OnChangeMaxLogCountTxt(wxCommandEvent& event);
- virtual void OnClose( wxCloseEvent& event) { EndModal(0); }
- virtual void OnCancel( wxCommandEvent& event) { EndModal(0); }
- virtual void OnSaveBatchJob( wxCommandEvent& event);
- virtual void OnLoadBatchJob( wxCommandEvent& event);
- virtual void OnAddFolderPair( wxCommandEvent& event);
- virtual void OnRemoveFolderPair( wxCommandEvent& event);
- virtual void OnRemoveTopFolderPair(wxCommandEvent& event);
+ virtual void OnClose (wxCloseEvent& event) { EndModal(0); }
+ virtual void OnCancel (wxCommandEvent& event) { EndModal(0); }
+ virtual void OnSaveBatchJob (wxCommandEvent& event);
+ virtual void OnLoadBatchJob (wxCommandEvent& event);
+ virtual void OnAddFolderPair (wxCommandEvent& event);
+ virtual void OnRemoveFolderPair (wxCommandEvent& event);
+ virtual void OnRemoveTopFolderPair (wxCommandEvent& event);
void OnFilesDropped(FileDropEvent& event);
void addFolderPair(const std::vector<zen::FolderPairEnh>& newPairs, bool addFront = false);
@@ -229,14 +229,14 @@ private:
//###################################################################################################################################
-BatchDialog::BatchDialog(wxWindow* window,
+BatchDialog::BatchDialog(wxWindow* parent,
const wxString& referenceFile,
const xmlAccess::XmlBatchConfig& batchCfg,
const std::shared_ptr<FolderHistory>& folderHistLeft,
const std::shared_ptr<FolderHistory>& folderHistRight,
std::vector<std::wstring>& onCompletionHistory,
size_t onCompletionHistoryMax) :
- BatchDlgGenerated(window),
+ BatchDlgGenerated(parent),
folderHistLeft_(folderHistLeft),
folderHistRight_(folderHistRight),
onCompletionHistory_(onCompletionHistory),
@@ -317,7 +317,7 @@ void BatchDialog::OnCmpSettings(wxCommandEvent& event)
//wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition();
//windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5;
- if (zen::showCompareCfgDialog(localBatchCfg.mainCfg.cmpConfig) == ReturnSmallDlg::BUTTON_OKAY)
+ if (zen::showCompareCfgDialog(this,localBatchCfg.mainCfg.cmpConfig) == ReturnSmallDlg::BUTTON_OKAY)
{
updateGui();
}
@@ -331,7 +331,8 @@ void BatchDialog::OnSyncSettings(wxCommandEvent& event)
onCompletionHistoryMax_
};
- if (showSyncConfigDlg(localBatchCfg.mainCfg.cmpConfig.compareVar,
+ if (showSyncConfigDlg(this,
+ localBatchCfg.mainCfg.cmpConfig.compareVar,
localBatchCfg.mainCfg.syncCfg,
nullptr,
&ewfCfg) == ReturnSyncConfig::BUTTON_OKAY) //optional input parameter
@@ -343,7 +344,8 @@ void BatchDialog::OnSyncSettings(wxCommandEvent& event)
void BatchDialog::OnConfigureFilter(wxCommandEvent& event)
{
- if (showFilterDialog(true, //is main filter dialog
+ if (showFilterDialog(this,
+ true, //is main filter dialog
localBatchCfg.mainCfg.globalFilter) == ReturnSmallDlg::BUTTON_OKAY)
{
updateGui();
@@ -455,23 +457,7 @@ void BatchDialog::OnChangeMaxLogCountTxt(wxCommandEvent& event)
void BatchDialog::OnFilesDropped(FileDropEvent& event)
{
- if (event.getFiles().empty())
- return;
-
- const std::vector<wxString>& fileList = event.getFiles();
-
- switch (xmlAccess::getMergeType(fileList)) //throw ()
- {
- case xmlAccess::MERGE_BATCH:
- case xmlAccess::MERGE_GUI:
- case xmlAccess::MERGE_GUI_BATCH:
- loadBatchFile(fileList);
- break;
-
- case xmlAccess::MERGE_OTHER:
- wxMessageBox(_("Invalid FreeFileSync config file!"), _("Error"), wxOK | wxICON_ERROR);
- break;
- }
+ loadBatchFile(event.getFiles());
}
@@ -578,11 +564,11 @@ bool BatchDialog::saveBatchFile(const wxString& filename)
//write config to XML
try
{
- xmlAccess::writeConfig(batchCfg, filename);
+ xmlAccess::writeConfig(batchCfg, toZ(filename));
}
catch (const xmlAccess::FfsXmlError& error)
{
- wxMessageBox(error.toString().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
return false;
}
@@ -611,17 +597,17 @@ void BatchDialog::loadBatchFile(const std::vector<wxString>& filenames)
try
{
//open a *.ffs_gui or *.ffs_batch file!
- xmlAccess::convertConfig(filenames, batchCfg); //throw (xmlAccess::FfsXmlError)
+ xmlAccess::convertConfig(toZ(filenames), batchCfg); //throw FfsXmlError
//xmlAccess::readConfig(filename, batchCfg);
}
catch (const xmlAccess::FfsXmlError& error)
{
if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING);
+ wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
else
{
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
return;
}
}
@@ -888,70 +874,14 @@ void BatchDialog::clearAddFolderPairs()
}
-/*
-#ifdef FFS_WIN
-#include <zen/win.h> //includes "windows.h"
-#include <shlobj.h>
-#endif // FFS_WIN
-
-
-bool BatchDialog::createBatchFile(const wxString& filename)
-{
- //create shell link (instead of batch file) for full Unicode support
- HRESULT hResult = E_FAIL;
- IShellLink* pShellLink = nullptr;
-
- if (FAILED(CoCreateInstance(CLSID_ShellLink, //class identifier
- nullptr, //object isn't part of an aggregate
- CLSCTX_INPROC_SERVER, //context for running executable code
- IID_IShellLink, //interface identifier
- (void**)&pShellLink))) //pointer to storage of interface pointer
- return false;
- CleanUp<IShellLink> cleanOnExit(pShellLink);
-
- wxString freeFileSyncExe = wxStandardPaths::Get().GetExecutablePath();
- if (FAILED(pShellLink->SetPath(freeFileSyncExe.c_str())))
- return false;
-
- if (FAILED(pShellLink->SetArguments(getCommandlineArguments().c_str())))
- return false;
-
- if (FAILED(pShellLink->SetIconLocation(freeFileSyncExe.c_str(), 1))) //second icon from executable file is used
- return false;
-
- if (FAILED(pShellLink->SetDescription(_("FreeFileSync Batch Job"))))
- return false;
-
- IPersistFile* pPersistFile = nullptr;
- if (FAILED(pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile)))
- return false;
- CleanUp<IPersistFile> cleanOnExit2(pPersistFile);
-
- //pPersistFile->Save accepts unicode input only
-#ifdef _UNICODE
- hResult = pPersistFile->Save(filename.c_str(), TRUE);
-#else
- WCHAR wszTemp [MAX_PATH];
- if (MultiByteToWideChar(CP_ACP, 0, filename.c_str(), -1, wszTemp, MAX_PATH) == 0)
- return false;
-
- hResult = pPersistFile->Save(wszTemp, TRUE);
-#endif
- if (FAILED(hResult))
- return false;
-
- return true;
-}
-*/
-
-
-void zen::showSyncBatchDlg(const wxString& referenceFile,
+void zen::showSyncBatchDlg(wxWindow* parent,
+ const wxString& referenceFile,
const xmlAccess::XmlBatchConfig& batchCfg,
const std::shared_ptr<FolderHistory>& folderHistLeft,
const std::shared_ptr<FolderHistory>& folderHistRight,
std::vector<std::wstring>& execFinishedhistory,
size_t execFinishedhistoryMax)
{
- BatchDialog batchDlg(nullptr, referenceFile, batchCfg, folderHistLeft, folderHistRight, execFinishedhistory, execFinishedhistoryMax);
+ BatchDialog batchDlg(parent, referenceFile, batchCfg, folderHistLeft, folderHistRight, execFinishedhistory, execFinishedhistoryMax);
batchDlg.ShowModal();
}
diff --git a/ui/batch_config.h b/ui/batch_config.h
index 472f21bf..04f0bf04 100644
--- a/ui/batch_config.h
+++ b/ui/batch_config.h
@@ -10,9 +10,11 @@
#include "../lib/process_xml.h"
#include "folder_history_box.h"
+
namespace zen
{
-void showSyncBatchDlg(const wxString& referenceFile,
+void showSyncBatchDlg(wxWindow* parent,
+ const wxString& referenceFile,
const xmlAccess::XmlBatchConfig& batchCfg,
const std::shared_ptr<FolderHistory>& folderHistLeft,
const std::shared_ptr<FolderHistory>& folderHistRight,
@@ -20,5 +22,4 @@ void showSyncBatchDlg(const wxString& referenceFile,
size_t execFinishedhistoryMax);
}
-
#endif // BATCHCONFIG_H_INCLUDED
diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp
index 0c45db3f..7254f570 100644
--- a/ui/batch_status_handler.cpp
+++ b/ui/batch_status_handler.cpp
@@ -5,18 +5,17 @@
// **************************************************************************
#include "batch_status_handler.h"
-#include "msg_popup.h"
#include <wx/ffile.h>
-#include <wx/msgdlg.h>
-#include "../lib/ffs_paths.h"
#include <zen/file_handling.h>
-#include "../lib/resolve_path.h"
+#include <zen/file_traverser.h>
#include <wx+/string_conv.h>
#include <wx+/app_main.h>
-#include <zen/file_traverser.h>
-#include <zen/time.h>
-#include "exec_finished_box.h"
+#include <wx+/format_unit.h>
#include <wx+/shell_execute.h>
+#include "msg_popup.h"
+#include "exec_finished_box.h"
+#include "../lib/ffs_paths.h"
+#include "../lib/resolve_path.h"
#include "../lib/status_handler_impl.h"
using namespace zen;
@@ -24,7 +23,7 @@ using namespace zen;
namespace
{
-class FindLogfiles : public zen::TraverseCallback
+class FindLogfiles : public TraverseCallback
{
public:
FindLogfiles(const Zstring& prefix, std::vector<Zstring>& logfiles) : prefix_(prefix), logfiles_(logfiles) {}
@@ -57,31 +56,47 @@ public:
{
logFile.Open(toWx(logfileName), L"w");
if (!logFile.IsOpened())
- throw FileError(_("Unable to create log file!") + L"\"" + logfileName + L"\"");
+ throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtFileName(logfileName)));
//write header
- wxString headerLine = wxString(L"FreeFileSync - ") + _("Batch execution") + L" - " + formatTime<wxString>(FORMAT_DATE);
-
- logFile.Write(headerLine + wxChar('\n'));
+ const wxString& headerLine = wxString(L"FreeFileSync - ") + _("Batch execution") + L" - " + formatTime<wxString>(FORMAT_DATE);
+ logFile.Write(headerLine + L'\n');
logFile.Write(wxString().Pad(headerLine.Len(), L'=') + L'\n');
- logItemStart = formatTime<wxString>(L"[%X] ") + _("Start");
+ //logItemStart = formatTime<wxString>(L"[%X] ") + _("Start");
totalTime.Start(); //measure total time
}
- void writeLog(const ErrorLog& log, const std::wstring& finalStatus)
+ void writeLog(const ErrorLog& log, const std::wstring& finalStatus,
+ int itemsSynced, Int64 dataSynced,
+ int itemsTotal, Int64 dataTotal)
{
- const size_t sepLineLen = finalStatus.size();
+ //assemble results box
+ std::vector<wxString> results;
+ results.push_back(finalStatus);
+ results.push_back(L"");
+ if (itemsTotal != 0 || dataTotal != 0) //=: sync phase was reached and there were actual items to sync
+ {
+ results.push_back(L" " + _("Items processed:") + L" " + toStringSep(itemsSynced) + L" (" + filesizeToShortString(dataSynced) + L")");
+
+ if (itemsSynced != itemsTotal ||
+ dataSynced != dataTotal)
+ results.push_back(L" " + _("Items remaining:") + L" " + toStringSep(itemsTotal - itemsSynced) + L" (" + filesizeToShortString(dataTotal - dataSynced) + L")");
+ }
+ results.push_back(L" " + _("Total time:") + L" " + wxTimeSpan::Milliseconds(totalTime.Time()).Format());
+
+ //write results box
+ size_t sepLineLen = 0;
+ std::for_each(results.begin(), results.end(), [&](const wxString& str) { sepLineLen = std::max(sepLineLen, str.size()); });
- //result + statistics
- logFile.Write(wxString().Pad(sepLineLen, L'_') + L'\n');
- logFile.Write(L"\n" + finalStatus + L"\n");
+ logFile.Write(wxString().Pad(sepLineLen, L'_') + L"\n\n");
+ std::for_each(results.begin(), results.end(), [&](const wxString& str) { logFile.Write(str + L'\n'); });
logFile.Write(wxString().Pad(sepLineLen, L'_') + L"\n\n");
- logFile.Write(logItemStart + L"\n\n");
+ //logFile.Write(logItemStart + L"\n\n");
- //write actual logfile
+ //write log items
const auto& entries = log.getEntries();
for (auto iter = entries.begin(); iter != entries.end(); ++iter)
{
@@ -90,9 +105,9 @@ public:
logFile.Write(L'\n');
}
- //write footer
- logFile.Write(L'\n');
- logFile.Write(formatTime<wxString>(L"[%X] ") + _("Stop") + L" (" + _("Total time:") + L" " + wxTimeSpan::Milliseconds(totalTime.Time()).Format() + L")\n");
+ ////write footer
+ //logFile.Write(L'\n');
+ //logFile.Write(formatTime<wxString>(L"[%X] ") + _("Stop") + L" (" + _("Total time:") + L" " + wxTimeSpan::Milliseconds(totalTime.Time()).Format() + L")\n");
}
void limitLogfileCount(size_t maxCount) const //throw()
@@ -111,7 +126,7 @@ public:
std::nth_element(logFiles.begin(), logFiles.end() - maxCount, logFiles.end()); //take advantage of logfile naming convention to find oldest files
std::for_each(logFiles.begin(), logFiles.end() - maxCount,
- [](const Zstring& filename) { try { zen::removeFile(filename); } catch (FileError&) {} });
+ [](const Zstring& filename) { try { removeFile(filename); } catch (FileError&) {} });
}
//Zstring getLogfileName() const { return logfileName; }
@@ -121,23 +136,20 @@ private:
{
//create logfile directory
Zstring logfileDir = logfileDirectory.empty() ?
- zen::getConfigDir() + Zstr("Logs") :
- zen::getFormattedDirectoryName(logfileDirectory);
+ getConfigDir() + Zstr("Logs") :
+ getFormattedDirectoryName(logfileDirectory);
- if (!zen::dirExists(logfileDir))
- zen::createDirectory(logfileDir); //throw FileError; create recursively if necessary
+ if (!dirExists(logfileDir))
+ createDirectory(logfileDir); //throw FileError; create recursively if necessary
//assemble logfile name
- if (!endsWith(logfileDir, FILE_NAME_SEPARATOR))
- logfileDir += FILE_NAME_SEPARATOR;
-
- const Zstring logfileName = logfileDir + toZ(jobName) + Zstr(" ") + formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"));
+ const Zstring logfileName = appendSeparator(logfileDir) + toZ(jobName) + Zstr(" ") + formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"));
//ensure uniqueness
Zstring output = logfileName + Zstr(".log");
- for (int i = 1; zen::somethingExists(output); ++i)
- output = logfileName + Zstr('_') + zen::numberTo<Zstring>(i) + Zstr(".log");
+ for (int i = 1; somethingExists(output); ++i)
+ output = logfileName + Zstr('_') + numberTo<Zstring>(i) + Zstr(".log");
return output;
}
@@ -145,7 +157,6 @@ private:
const Zstring logfileName;
wxFFile logFile;
wxStopWatch totalTime;
- wxString logItemStart;
};
@@ -163,21 +174,18 @@ BatchStatusHandler::BatchStatusHandler(bool showProgress,
showFinalResults(showProgress), //=> exit immediately or wait when finished
switchToGuiRequested(false),
handleError_(handleError),
- currentProcess(StatusHandler::PROCESS_NONE),
returnValue(returnVal),
- syncStatusFrame(*this, nullptr, SyncStatus::SCANNING, showProgress, jobName, execWhenFinished, execFinishedHistory)
+ syncStatusFrame(*this, *this, nullptr, showProgress, jobName, execWhenFinished, execFinishedHistory)
{
- if (logFileCountMax > 0)
- {
+ if (logFileCountMax > 0) //init log file: starts internal timer!
if (!tryReportingError([&]
{
- logFile = std::make_shared<LogFile>(toZ(logfileDirectory), jobName); //throw FileError
+ logFile.reset(new LogFile(toZ(logfileDirectory), jobName)); //throw FileError
logFile->limitLogfileCount(logFileCountMax); //throw()
}, *this))
- {
- returnValue = -7;
- throw BatchAbortProcess();
- }
+ {
+ returnValue = -7;
+ throw BatchAbortProcess();
}
//::wxSetEnv(L"logfile", logFile->getLogfileName());
@@ -194,7 +202,7 @@ BatchStatusHandler::~BatchStatusHandler()
{
returnValue = -4;
finalStatus = _("Synchronization aborted!");
- errorLog.logMsg(finalStatus, TYPE_FATAL_ERROR);
+ errorLog.logMsg(finalStatus, TYPE_ERROR);
}
else if (totalErrors > 0)
{
@@ -204,14 +212,20 @@ BatchStatusHandler::~BatchStatusHandler()
}
else
{
- finalStatus = _("Synchronization completed successfully!");
+ if (getObjectsTotal(PHASE_SYNCHRONIZING) == 0 && //we're past "initNewPhase(PHASE_SYNCHRONIZING)" at this point!
+ getDataTotal (PHASE_SYNCHRONIZING) == 0)
+ finalStatus = _("Nothing to synchronize!"); //even if "ignored conflicts" occurred!
+ else
+ finalStatus = _("Synchronization completed successfully!");
errorLog.logMsg(finalStatus, TYPE_INFO);
}
//print the results list: logfile
if (logFile.get())
{
- logFile->writeLog(errorLog, finalStatus);
+ logFile->writeLog(errorLog, finalStatus,
+ getObjectsCurrent(PHASE_SYNCHRONIZING), getDataCurrent(PHASE_SYNCHRONIZING),
+ getObjectsTotal (PHASE_SYNCHRONIZING), getDataTotal (PHASE_SYNCHRONIZING));
logFile.reset(); //close file now: user may do something with it in "on completion"
}
@@ -240,19 +254,18 @@ BatchStatusHandler::~BatchStatusHandler()
shellExecute(finalCommand);
}
-
if (showFinalResults) //warning: wxWindow::Show() is called within processHasFinished()!
{
//notify about (logical) application main window => program won't quit, but stay on this dialog
- zen::setMainWindow(syncStatusFrame.getAsWindow());
+ setMainWindow(syncStatusFrame.getAsWindow());
//notify to syncStatusFrame that current process has ended
if (abortIsRequested())
- syncStatusFrame.processHasFinished(SyncStatus::ABORTED, errorLog); //enable okay and close events
+ syncStatusFrame.processHasFinished(SyncStatus::RESULT_ABORTED, errorLog); //enable okay and close events
else if (totalErrors > 0)
- syncStatusFrame.processHasFinished(SyncStatus::FINISHED_WITH_ERROR, errorLog);
+ syncStatusFrame.processHasFinished(SyncStatus::RESULT_FINISHED_WITH_ERROR, errorLog);
else
- syncStatusFrame.processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS, errorLog);
+ syncStatusFrame.processHasFinished(SyncStatus::RESULT_FINISHED_WITH_SUCCESS, errorLog);
}
else
syncStatusFrame.closeWindowDirectly(); //syncStatusFrame is main window => program will quit directly
@@ -260,68 +273,36 @@ BatchStatusHandler::~BatchStatusHandler()
}
-void BatchStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, StatusHandler::Process processID)
+void BatchStatusHandler::initNewPhase(int objectsTotal, Int64 dataTotal, ProcessCallback::Phase phaseID)
{
- currentProcess = processID;
-
- switch (currentProcess)
- {
- case StatusHandler::PROCESS_SCANNING:
- syncStatusFrame.initNewProcess(SyncStatus::SCANNING, 0, 0); //initialize some gui elements (remaining time, speed)
- break;
- case StatusHandler::PROCESS_COMPARING_CONTENT:
- syncStatusFrame.initNewProcess(SyncStatus::COMPARING_CONTENT, objectsTotal, dataTotal);
- break;
- case StatusHandler::PROCESS_SYNCHRONIZING:
- syncStatusFrame.initNewProcess(SyncStatus::SYNCHRONIZING, objectsTotal, dataTotal);
- break;
- case StatusHandler::PROCESS_NONE:
- assert(false);
- break;
- }
+ StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID);
+ syncStatusFrame.initNewPhase(); //call after "StatusHandler::initNewPhase"
}
void BatchStatusHandler::updateProcessedData(int objectsDelta, Int64 dataDelta)
{
- switch (currentProcess)
+ StatusHandler::updateProcessedData(objectsDelta, dataDelta);
+
+ switch (currentPhase())
{
- case StatusHandler::PROCESS_SCANNING:
- syncStatusFrame.incScannedObjects_NoUpdate(objectsDelta); //throw ()
- break;
- case StatusHandler::PROCESS_COMPARING_CONTENT:
- case StatusHandler::PROCESS_SYNCHRONIZING:
- syncStatusFrame.incProcessedData_NoUpdate(objectsDelta, dataDelta);
- break;
- case StatusHandler::PROCESS_NONE:
+ case ProcessCallback::PHASE_NONE:
assert(false);
+ case ProcessCallback::PHASE_SCANNING:
+ break;
+ case ProcessCallback::PHASE_COMPARING_CONTENT:
+ case ProcessCallback::PHASE_SYNCHRONIZING:
+ syncStatusFrame.reportCurrentBytes(getDataCurrent(currentPhase()));
break;
}
-
//note: this method should NOT throw in order to properly allow undoing setting of statistics!
}
-void BatchStatusHandler::updateTotalData(int objectsDelta, Int64 dataDelta)
-{
- assert(currentProcess != PROCESS_SCANNING);
- syncStatusFrame.incTotalData_NoUpdate(objectsDelta, dataDelta);
-}
-
-
-void BatchStatusHandler::reportStatus(const std::wstring& text)
-{
- syncStatusFrame.setStatusText_NoUpdate(text);
- requestUiRefresh(); //throw AbortThisProcess
-}
-
-
void BatchStatusHandler::reportInfo(const std::wstring& text)
{
+ StatusHandler::reportInfo(text);
errorLog.logMsg(text, TYPE_INFO);
-
- syncStatusFrame.setStatusText_NoUpdate(text);
- requestUiRefresh(); //throw AbortThisProcess
}
@@ -340,8 +321,9 @@ void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool&
forceUiRefresh();
bool dontWarnAgain = false;
- switch (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_SWITCH | ReturnWarningDlg::BUTTON_ABORT,
- warningMessage + wxT("\n\n") + _("Press \"Switch\" to open FreeFileSync GUI mode."),
+ switch (showWarningDlg(syncStatusFrame.getAsWindow(),
+ ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_SWITCH | ReturnWarningDlg::BUTTON_ABORT,
+ warningMessage + L"\n\n" + _("Press \"Switch\" to resolve issues in FreeFileSync main dialog."),
dontWarnAgain))
{
case ReturnWarningDlg::BUTTON_ABORT:
@@ -349,7 +331,7 @@ void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool&
break;
case ReturnWarningDlg::BUTTON_SWITCH:
- errorLog.logMsg(_("Switching to FreeFileSync GUI mode..."), TYPE_INFO);
+ errorLog.logMsg(_("Switching to FreeFileSync main dialog..."), TYPE_INFO);
switchToGuiRequested = true;
abortThisProcess();
break;
@@ -365,7 +347,7 @@ void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool&
abortThisProcess();
break;
- case xmlAccess::ON_ERROR_IGNORE: //no unhandled error situation!
+ case xmlAccess::ON_ERROR_IGNORE:
break;
}
}
@@ -381,9 +363,9 @@ ProcessCallback::Response BatchStatusHandler::reportError(const std::wstring& er
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
- errorMessage,
- &ignoreNextErrors))
+ switch (showErrorDlg(syncStatusFrame.getAsWindow(),
+ ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
+ errorMessage, &ignoreNextErrors))
{
case ReturnErrorDlg::BUTTON_IGNORE:
if (ignoreNextErrors) //falsify only
@@ -428,9 +410,9 @@ void BatchStatusHandler::reportFatalError(const std::wstring& errorMessage)
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_ABORT,
- errorMessage,
- &ignoreNextErrors))
+ switch (showErrorDlg(syncStatusFrame.getAsWindow(),
+ ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_ABORT,
+ errorMessage, &ignoreNextErrors))
{
case ReturnErrorDlg::BUTTON_IGNORE:
if (ignoreNextErrors) //falsify only
@@ -459,12 +441,12 @@ void BatchStatusHandler::reportFatalError(const std::wstring& errorMessage)
void BatchStatusHandler::forceUiRefresh()
{
- syncStatusFrame.updateStatusDialogNow();
+ syncStatusFrame.updateProgress();
}
void BatchStatusHandler::abortThisProcess()
{
- requestAbortion();
+ requestAbortion(); //just make sure...
throw BatchAbortProcess(); //abort can be triggered by syncStatusFrame
}
diff --git a/ui/batch_status_handler.h b/ui/batch_status_handler.h
index 0657e881..cc23019e 100644
--- a/ui/batch_status_handler.h
+++ b/ui/batch_status_handler.h
@@ -14,13 +14,12 @@
#include "switch_to_gui.h"
class LogFile;
-class SyncStatus;
//Exception class used to abort the "compare" and "sync" process
class BatchAbortProcess {};
-class BatchStatusHandler : public StatusHandler
+class BatchStatusHandler : public zen::StatusHandler
{
public:
BatchStatusHandler(bool showProgress, //defines: -start minimized and -quit immediately when finished
@@ -34,10 +33,8 @@ public:
std::vector<std::wstring>& execFinishedHistory);
~BatchStatusHandler();
- virtual void initNewProcess (int objectsTotal, zen::Int64 dataTotal, Process processID);
+ virtual void initNewPhase (int objectsTotal, zen::Int64 dataTotal, Phase phaseID);
virtual void updateProcessedData(int objectsDelta, zen::Int64 dataDelta);
- virtual void updateTotalData (int objectsDelta, zen::Int64 dataDelta);
- virtual void reportStatus(const std::wstring& text);
virtual void reportInfo(const std::wstring& text);
virtual void forceUiRefresh();
@@ -46,18 +43,17 @@ public:
virtual void reportFatalError(const std::wstring& errorMessage);
private:
- virtual void abortThisProcess();
+ virtual void abortThisProcess(); //throw BatchAbortProcess
const zen::SwitchToGui& switchBatchToGui_; //functionality to change from batch mode to GUI mode
bool showFinalResults;
bool switchToGuiRequested;
xmlAccess::OnError handleError_;
zen::ErrorLog errorLog; //list of non-resolved errors and warnings
- Process currentProcess;
int& returnValue;
SyncStatus syncStatusFrame; //the window managed by SyncStatus has longer lifetime than this handler!
- std::shared_ptr<LogFile> logFile; //optional!
+ std::unique_ptr<LogFile> logFile; //optional!
};
diff --git a/ui/check_version.cpp b/ui/check_version.cpp
index ba922f97..37fa16ff 100644
--- a/ui/check_version.cpp
+++ b/ui/check_version.cpp
@@ -82,27 +82,30 @@ bool newerVersionExists(const wxString& onlineVersion)
}
-void zen::checkForUpdateNow()
+void zen::checkForUpdateNow(wxWindow* parent)
{
wxString onlineVersion;
if (!getOnlineVersion(onlineVersion))
{
- wxMessageBox(_("Unable to connect to sourceforge.net!"), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(_("Unable to connect to sourceforge.net!"), _("Error"), wxOK | wxICON_ERROR, parent);
return;
}
if (newerVersionExists(onlineVersion))
{
- const int rv = wxMessageBox(wxString(_("A newer version of FreeFileSync is available:")) + wxT(" v") + onlineVersion + wxT(". ") + _("Download now?"), _("Information"), wxYES_NO | wxICON_QUESTION);
+ const int rv = wxMessageBox(_("A newer version of FreeFileSync is available:") + L" v" + onlineVersion + L". " + _("Download now?"),
+ _("Information"),
+ wxYES_NO | wxICON_QUESTION,
+ parent);
if (rv == wxYES)
wxLaunchDefaultBrowser(wxString(L"http://sourceforge.net/projects/freefilesync/files/freefilesync/v") + onlineVersion + L"/");
}
else
- wxMessageBox(_("FreeFileSync is up to date!"), _("Information"), wxICON_INFORMATION);
+ wxMessageBox(_("FreeFileSync is up to date!"), _("Information"), wxICON_INFORMATION, parent);
}
-void zen::checkForUpdatePeriodically(long& lastUpdateCheck)
+void zen::checkForUpdatePeriodically(wxWindow* parent, long& lastUpdateCheck)
{
#ifdef FFS_LINUX
if (!zen::isPortableVersion()) //don't check for updates in installer version -> else: handled by .deb
@@ -113,14 +116,14 @@ void zen::checkForUpdatePeriodically(long& lastUpdateCheck)
{
if (lastUpdateCheck == 0)
{
- const bool checkRegularly = showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_NO,
+ const bool checkRegularly = showQuestionDlg(parent, ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_NO,
_("Do you want FreeFileSync to automatically check for updates every week?") + L"\n" +
_("(Requires an Internet connection!)")) == ReturnQuestionDlg::BUTTON_YES;
if (checkRegularly)
{
lastUpdateCheck = 123; //some old date (few seconds after 1970)
- checkForUpdatePeriodically(lastUpdateCheck); //check for updates now
+ checkForUpdatePeriodically(parent, lastUpdateCheck); //check for updates now
}
else
lastUpdateCheck = -1; //don't check for updates anymore
@@ -135,7 +138,10 @@ void zen::checkForUpdatePeriodically(long& lastUpdateCheck)
if (newerVersionExists(onlineVersion))
{
- const int rv = wxMessageBox(wxString(_("A newer version of FreeFileSync is available:")) + wxT(" v") + onlineVersion + wxT(". ") + _("Download now?"), _("Information"), wxYES_NO | wxICON_QUESTION);
+ const int rv = wxMessageBox(_("A newer version of FreeFileSync is available:") + L" v" + onlineVersion + L". " + _("Download now?"),
+ _("Information"),
+ wxYES_NO | wxICON_QUESTION,
+ parent);
if (rv == wxYES)
wxLaunchDefaultBrowser(wxString(L"http://sourceforge.net/projects/freefilesync/files/freefilesync/v") + onlineVersion + L"/");
}
diff --git a/ui/check_version.h b/ui/check_version.h
index bbf8d7cb..5a0bbd73 100644
--- a/ui/check_version.h
+++ b/ui/check_version.h
@@ -7,12 +7,14 @@
#ifndef UPDATEVERSION_H_INCLUDED
#define UPDATEVERSION_H_INCLUDED
+#include <wx/window.h>
+
namespace zen
{
-void checkForUpdateNow();
+void checkForUpdateNow(wxWindow* parent);
-void checkForUpdatePeriodically(long& lastUpdateCheck);
+void checkForUpdatePeriodically(wxWindow* parent, long& lastUpdateCheck);
}
#endif // UPDATEVERSION_H_INCLUDED
diff --git a/ui/custom_grid.cpp b/ui/custom_grid.cpp
index 465a1b6f..fdb72161 100644
--- a/ui/custom_grid.cpp
+++ b/ui/custom_grid.cpp
@@ -91,6 +91,12 @@ std::pair<ptrdiff_t, ptrdiff_t> getVisibleRows(Grid& grid) //returns range [from
}
+Zstring getExtension(const Zstring& shortName)
+{
+ return contains(shortName, Zchar('.')) ? afterLast(shortName, Zchar('.')) : Zstring();
+};
+
+
class IconUpdater;
class GridEventManager;
@@ -121,7 +127,6 @@ private:
Grid& grid_;
};
-
//########################################################################################################
template <SelectedSide side>
@@ -254,6 +259,7 @@ private:
struct GetTextValue : public FSObjectVisitor
{
GetTextValue(ColumnTypeRim colType, const FileSystemObject& fso) : colType_(colType), fsObj_(fso) {}
+
virtual void visit(const FileMapping& fileObj)
{
switch (colType_)
@@ -279,7 +285,7 @@ private:
value = zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>());
break;
case COL_TYPE_EXTENSION: //file extension
- value = toWx(fileObj.getExtension<side>());
+ value = toWx(getExtension(fileObj.getShortName<side>()));
break;
}
}
@@ -309,7 +315,7 @@ private:
value = zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>());
break;
case COL_TYPE_EXTENSION: //file extension
- value = wxEmptyString;
+ value = toWx(getExtension(linkObj.getShortName<side>()));
break;
}
}
@@ -543,30 +549,32 @@ private:
virtual wxString getToolTip(size_t row, ColumnType colType) const
{
wxString toolTip;
+
const FileSystemObject* fsObj = getRawData(row);
if (fsObj && !fsObj->isEmpty<side>())
{
+ toolTip = toWx(gridDataView_->getFolderPairCount() > 1 ? //gridDataView_ bound in this path
+ fsObj->getFullName<side>() :
+ fsObj->getRelativeName<side>());
+
struct AssembleTooltip : public FSObjectVisitor
{
AssembleTooltip(wxString& tipMsg) : tipMsg_(tipMsg) {}
virtual void visit(const FileMapping& fileObj)
{
- tipMsg_ = copyStringTo<wxString>(std::wstring() + fileObj.getRelativeName<side>() + L"\n" +
- _("Size") + L": " + zen::filesizeToShortString(to<Int64>(fileObj.getFileSize<side>())) + L"\n" +
- _("Date") + L": " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()));
+ tipMsg_ += L"\n" +
+ _("Size") + L": " + zen::filesizeToShortString(to<Int64>(fileObj.getFileSize<side>())) + L"\n" +
+ _("Date") + L": " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>());
}
virtual void visit(const SymLinkMapping& linkObj)
{
- tipMsg_ = copyStringTo<wxString>(std::wstring() + linkObj.getRelativeName<side>() + L"\n" +
- _("Date") + L": " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()));
+ tipMsg_ += L"\n" +
+ _("Date") + L": " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>());
}
- virtual void visit(const DirMapping& dirObj)
- {
- tipMsg_ = toWx(dirObj.getRelativeName<side>());
- }
+ virtual void visit(const DirMapping& dirObj) {}
wxString& tipMsg_;
} assembler(toolTip);
@@ -700,7 +708,7 @@ public:
{
case BLOCKPOS_CHECK_BOX:
{
- const FileSystemObject* fsObj = getRawData(rowFrom);
+ const FileSystemObject* fsObj = getRawData(dragSelection->first);
const bool setIncluded = fsObj ? !fsObj->isActive() : true;
CheckRowsEvent evt(rowFrom, rowTo, setIncluded);
diff --git a/ui/exec_finished_box.cpp b/ui/exec_finished_box.cpp
index a8ee9f4a..edc57d58 100644
--- a/ui/exec_finished_box.cpp
+++ b/ui/exec_finished_box.cpp
@@ -192,7 +192,8 @@ void ExecFinishedBox::setValueAndUpdateList(const std::wstring& value)
void ExecFinishedBox::OnSelection(wxCommandEvent& event)
{
wxCommandEvent dummy2(wxEVT_REPLACE_BUILT_IN_COMMANDS); //we cannot replace built-in commands at this position in call stack, so defer to a later time!
- GetEventHandler()->AddPendingEvent(dummy2); //
+ if (auto handler = GetEventHandler())
+ handler->AddPendingEvent(dummy2);
event.Skip();
}
diff --git a/ui/folder_history_box.cpp b/ui/folder_history_box.cpp
index 76ed785e..72204c3a 100644
--- a/ui/folder_history_box.cpp
+++ b/ui/folder_history_box.cpp
@@ -146,18 +146,12 @@ void FolderHistoryBox::OnMouseWheel(wxMouseEvent& event)
//redirect to parent scrolled window!
wxWindow* wnd = this;
- for (;;)
- {
- wnd = wnd->GetParent();
- if (!wnd)
- break;
-
+ while ((wnd = wnd->GetParent()) != nullptr) //silence MSVC warning
if (dynamic_cast<wxScrolledWindow*>(wnd) != nullptr)
{
wnd->GetEventHandler()->AddPendingEvent(event);
break;
}
- }
// event.Skip();
}
diff --git a/ui/folder_pair.h b/ui/folder_pair.h
index 7b1e7643..d80d8a05 100644
--- a/ui/folder_pair.h
+++ b/ui/folder_pair.h
@@ -151,7 +151,7 @@ private:
CompConfig cmpCfg = altCompConfig.get() ? *altCompConfig : mainCfg.cmpConfig;
- if (showCompareCfgDialog(cmpCfg) == ReturnSmallDlg::BUTTON_OKAY)
+ if (showCompareCfgDialog(getParentWindow(), cmpCfg) == ReturnSmallDlg::BUTTON_OKAY)
{
altCompConfig = std::make_shared<CompConfig>(cmpCfg);
refreshButtons();
@@ -167,7 +167,8 @@ private:
CompConfig cmpCfg = altCompConfig.get() ? *altCompConfig : mainCfg.cmpConfig;
SyncConfig syncCfg = altSyncConfig.get() ? *altSyncConfig : mainCfg.syncCfg;
- if (showSyncConfigDlg(cmpCfg.compareVar,
+ if (showSyncConfigDlg(getParentWindow(),
+ cmpCfg.compareVar,
syncCfg,
nullptr,
nullptr) == ReturnSyncConfig::BUTTON_OKAY) //optional input parameter
@@ -183,7 +184,8 @@ private:
{
FilterConfig localFiltTmp = localFilter;
- if (showFilterDialog(false, //is local filter dialog
+ if (showFilterDialog(getParentWindow(),
+ false, //is local filter dialog
localFiltTmp) == ReturnSmallDlg::BUTTON_OKAY)
{
localFilter = localFiltTmp;
diff --git a/ui/grid_view.cpp b/ui/grid_view.cpp
index 2a3e84e3..80ff895c 100644
--- a/ui/grid_view.cpp
+++ b/ui/grid_view.cpp
@@ -267,10 +267,9 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //map
}
-void GridView::getAllFileRef(const std::set<size_t>& rows, std::vector<FileSystemObject*>& output)
+std::vector<FileSystemObject*> GridView::getAllFileRef(const std::set<size_t>& rows)
{
- output.clear();
- output.reserve(rows.size());
+ std::vector<FileSystemObject*> output;
auto iterLast = rows.lower_bound(rowsOnView()); //loop over valid rows only!
std::for_each(rows.begin(), iterLast,
@@ -279,6 +278,7 @@ void GridView::getAllFileRef(const std::set<size_t>& rows, std::vector<FileSyste
if (FileSystemObject* fsObj = FileSystemObject::retrieve(viewRef[pos]))
output.push_back(fsObj);
});
+ return output;
}
@@ -336,6 +336,13 @@ void GridView::setData(FolderComparison& folderCmp)
std::vector<RefIndex>().swap(sortedRef); //
currentSort.reset();
+ folderPairCount = std::count_if(begin(folderCmp), end(folderCmp),
+ [](const BaseDirMapping& baseObj) //count non-empty pairs to distinguish single/multiple folder pair cases
+ {
+ return !baseObj.getBaseDirPf<LEFT_SIDE >().empty() ||
+ !baseObj.getBaseDirPf<RIGHT_SIDE>().empty();
+ });
+
for (auto iter = begin(folderCmp); iter != end(folderCmp); ++iter)
SerializeHierarchy(sortedRef, iter - begin(folderCmp)).execute(*iter);
}
@@ -499,7 +506,7 @@ void GridView::sortView(ColumnTypeRim type, bool onLeft, bool ascending)
viewRef.clear();
rowPositions.clear();
rowPositionsFirstChild.clear();
- currentSort.reset(new SortInfo(type, onLeft, ascending));
+ currentSort = make_unique<SortInfo>(type, onLeft, ascending);
switch (type)
{
diff --git a/ui/grid_view.h b/ui/grid_view.h
index fc828f91..c830224b 100644
--- a/ui/grid_view.h
+++ b/ui/grid_view.h
@@ -18,6 +18,8 @@ namespace zen
class GridView
{
public:
+ GridView() : folderPairCount(0) {}
+
//direct data access via row number
const FileSystemObject* getObject(size_t row) const; //returns nullptr if object is not found; complexity: constant!
/**/
@@ -26,7 +28,7 @@ public:
size_t rowsTotal () const { return sortedRef.size(); } //total rows available
//get references to FileSystemObject: no nullptr-check needed! Everything's bound.
- void getAllFileRef(const std::set<size_t>& rows, std::vector<FileSystemObject*>& output);
+ std::vector<FileSystemObject*> getAllFileRef(const std::set<size_t>& rows);
struct StatusCmpResult
{
@@ -115,6 +117,8 @@ public:
ptrdiff_t findRowFirstChild(const HierarchyObject* hierObj) const; // find first child of DirMapping or BaseDirMapping *on sorted sub view*
//"hierObj" may be invalid, it is NOT dereferenced, return < 0 if not found
+ size_t getFolderPairCount() const { return folderPairCount; } //count non-empty pairs to distinguish single/multiple folder pair cases
+
private:
struct RefIndex
{
@@ -129,8 +133,8 @@ private:
zen::hash_map<FileSystemObject::ObjectIdConst, size_t> rowPositions; //find row positions on sortedRef directly
- zen::hash_map<const HierarchyObject*, size_t> rowPositionsFirstChild; //find first child on sortedRef of a hierarchy object
- //NEVER DEREFERENCE HierarchyObject*!!! lookup only!
+ zen::hash_map<const void*, size_t> rowPositionsFirstChild; //find first child on sortedRef of a hierarchy object
+ //void* instead of HierarchyObject*: these are weak pointers and should *never be dereferenced*!
std::vector<FileSystemObject::ObjectId> viewRef; //partial view on sortedRef
/* /|\
@@ -141,6 +145,8 @@ private:
| (setData...)
| */
//std::shared_ptr<FolderComparison> folderCmp; //actual comparison data: owned by GridView!
+ size_t folderPairCount; //number of non-empty folder pairs
+
class SerializeHierarchy;
diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp
index 9caa466a..4c42caf1 100644
--- a/ui/gui_generated.cpp
+++ b/ui/gui_generated.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Mar 17 2012)
+// C++ code generated with wxFormBuilder (version Apr 10 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -928,23 +928,11 @@ CompareStatusGenerated::CompareStatusGenerated( wxWindow* parent, wxWindowID id,
bSizer154->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 );
- m_staticText117 = new wxStaticText( this, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText117->Wrap( -1 );
- m_staticText117->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
-
- bSizer154->Add( m_staticText117, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextDataRemaining->Wrap( -1 );
m_staticTextDataRemaining->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
- bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticText118 = new wxStaticText( this, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText118->Wrap( -1 );
- m_staticText118->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
-
- bSizer154->Add( m_staticText118, 0, wxALIGN_BOTTOM, 5 );
+ bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
bSizerFilesRemaining->Add( bSizer154, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
@@ -1413,7 +1401,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer68->Add( m_buttonLoad, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_button6 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button6 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button6->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer68->Add( m_button6, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -1881,13 +1869,13 @@ SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer291;
bSizer291 = new wxBoxSizer( wxHORIZONTAL );
- m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonOK = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonOK->SetDefault();
m_buttonOK->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
bSizer291->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button16 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button16->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer291->Add( m_button16, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -2042,13 +2030,13 @@ CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer22;
bSizer22 = new wxBoxSizer( wxHORIZONTAL );
- m_button10 = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button10 = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button10->SetDefault();
m_button10->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
bSizer22->Add( m_button10, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_button6 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button6 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button6->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer22->Add( m_button6, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -2064,6 +2052,8 @@ CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const w
this->Layout();
bSizer136->Fit( this );
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) );
m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this );
@@ -2168,23 +2158,11 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id,
bSizerItemsProc->Add( m_staticTextProcessedObj, 0, wxALIGN_BOTTOM, 5 );
- m_staticText98 = new wxStaticText( m_panelProgress, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText98->Wrap( -1 );
- m_staticText98->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
-
- bSizerItemsProc->Add( m_staticText98, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
m_staticTextDataProcessed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextDataProcessed->Wrap( -1 );
m_staticTextDataProcessed->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
- bSizerItemsProc->Add( m_staticTextDataProcessed, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticText99 = new wxStaticText( m_panelProgress, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText99->Wrap( -1 );
- m_staticText99->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
-
- bSizerItemsProc->Add( m_staticText99, 0, wxALIGN_BOTTOM, 5 );
+ bSizerItemsProc->Add( m_staticTextDataProcessed, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
fgSizer10->Add( bSizerItemsProc, 0, wxALIGN_BOTTOM, 5 );
@@ -2203,38 +2181,26 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id,
bSizerItemsRem->Add( m_staticTextRemainingObj, 0, wxALIGN_BOTTOM, 5 );
- m_staticText96 = new wxStaticText( m_panelProgress, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText96->Wrap( -1 );
- m_staticText96->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
-
- bSizerItemsRem->Add( m_staticText96, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
m_staticTextDataRemaining = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextDataRemaining->Wrap( -1 );
m_staticTextDataRemaining->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
- bSizerItemsRem->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticText97 = new wxStaticText( m_panelProgress, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText97->Wrap( -1 );
- m_staticText97->SetFont( wxFont( 9, 70, 90, 90, false, wxEmptyString ) );
-
- bSizerItemsRem->Add( m_staticText97, 0, wxALIGN_BOTTOM, 5 );
+ bSizerItemsRem->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
fgSizer10->Add( bSizerItemsRem, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextLabelElapsedTime = new wxStaticText( m_panelProgress, wxID_ANY, _("Elapsed time:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextLabelElapsedTime->Wrap( -1 );
- m_staticTextLabelElapsedTime->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+ m_staticText84 = new wxStaticText( m_panelProgress, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText84->Wrap( -1 );
+ m_staticText84->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
- fgSizer10->Add( m_staticTextLabelElapsedTime, 0, wxALIGN_BOTTOM, 5 );
+ fgSizer10->Add( m_staticText84, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextTimeElapsed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextTimeElapsed->Wrap( -1 );
- m_staticTextTimeElapsed->SetFont( wxFont( 9, 70, 90, 92, false, wxEmptyString ) );
+ m_staticTextSpeed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextSpeed->Wrap( -1 );
+ m_staticTextSpeed->SetFont( wxFont( 9, 70, 90, 92, false, wxEmptyString ) );
- fgSizer10->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM, 5 );
+ fgSizer10->Add( m_staticTextSpeed, 0, wxALIGN_BOTTOM, 5 );
m_staticTextLabelRemTime = new wxStaticText( m_panelProgress, wxID_ANY, _("Remaining time:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextLabelRemTime->Wrap( -1 );
@@ -2248,17 +2214,17 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id,
fgSizer10->Add( m_staticTextRemTime, 0, wxALIGN_BOTTOM, 5 );
- m_staticText84 = new wxStaticText( m_panelProgress, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText84->Wrap( -1 );
- m_staticText84->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+ m_staticTextLabelElapsedTime = new wxStaticText( m_panelProgress, wxID_ANY, _("Elapsed time:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextLabelElapsedTime->Wrap( -1 );
+ m_staticTextLabelElapsedTime->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
- fgSizer10->Add( m_staticText84, 0, wxALIGN_BOTTOM, 5 );
+ fgSizer10->Add( m_staticTextLabelElapsedTime, 0, wxALIGN_BOTTOM, 5 );
- m_staticTextSpeed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextSpeed->Wrap( -1 );
- m_staticTextSpeed->SetFont( wxFont( 9, 70, 90, 92, false, wxEmptyString ) );
+ m_staticTextTimeElapsed = new wxStaticText( m_panelProgress, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextTimeElapsed->Wrap( -1 );
+ m_staticTextTimeElapsed->SetFont( wxFont( 9, 70, 90, 92, false, wxEmptyString ) );
- fgSizer10->Add( m_staticTextSpeed, 0, wxALIGN_BOTTOM, 5 );
+ fgSizer10->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM, 5 );
bSizerProgressStat->Add( fgSizer10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@@ -2320,7 +2286,7 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id,
bSizer28->Add( 0, 0, 1, 0, 5 );
- m_buttonOK = new wxButton( m_panelBackground, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,30 ), 0 );
+ m_buttonOK = new wxButton( m_panelBackground, wxID_OK, _("OK"), wxDefaultPosition, wxSize( 100,30 ), 0 );
m_buttonOK->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
m_buttonOK->Enable( false );
@@ -2331,7 +2297,7 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id,
bSizer28->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_buttonAbort = new wxButton( m_panelBackground, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( 100,30 ), 0 );
+ m_buttonAbort = new wxButton( m_panelBackground, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( 100,30 ), 0 );
m_buttonAbort->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer28->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -2675,7 +2641,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer31->Add( sbSizer14, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
- m_buttonOkay = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,30 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( 100,30 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
@@ -2744,7 +2710,7 @@ ErrorDlgGenerated::ErrorDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer25->Add( m_buttonRetry, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
- m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonAbort = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonAbort->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer25->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
@@ -2756,6 +2722,8 @@ ErrorDlgGenerated::ErrorDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
this->SetSizer( bSizer24 );
this->Layout();
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) );
m_buttonIgnore->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnIgnore ), NULL, this );
@@ -2814,7 +2782,7 @@ WarningDlgGenerated::WarningDlgGenerated( wxWindow* parent, wxWindowID id, const
bSizer25->Add( m_buttonSwitch, 0, wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonAbort = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonAbort->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer25->Add( m_buttonAbort, 0, wxTOP|wxBOTTOM|wxLEFT, 5 );
@@ -2826,6 +2794,8 @@ WarningDlgGenerated::WarningDlgGenerated( wxWindow* parent, wxWindowID id, const
this->SetSizer( bSizer24 );
this->Layout();
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarningDlgGenerated::OnClose ) );
m_buttonIgnore->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnIgnore ), NULL, this );
@@ -2884,7 +2854,7 @@ QuestionDlgGenerated::QuestionDlgGenerated( wxWindow* parent, wxWindowID id, con
bSizer25->Add( m_buttonNo, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonCancel->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer25->Add( m_buttonCancel, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
@@ -2896,6 +2866,8 @@ QuestionDlgGenerated::QuestionDlgGenerated( wxWindow* parent, wxWindowID id, con
this->SetSizer( bSizer24 );
this->Layout();
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( QuestionDlgGenerated::OnClose ) );
m_buttonYes->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnYes ), NULL, this );
@@ -2963,13 +2935,13 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer25;
bSizer25 = new wxBoxSizer( wxHORIZONTAL );
- m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonOK = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonOK->SetDefault();
m_buttonOK->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
bSizer25->Add( m_buttonOK, 0, wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonCancel->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer25->Add( m_buttonCancel, 0, wxALL, 5 );
@@ -2984,6 +2956,8 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
this->SetSizer( bSizer24 );
this->Layout();
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::OnClose ) );
m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnUseRecycler ), NULL, this );
@@ -3254,13 +3228,13 @@ FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer22->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
- m_button10 = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button10 = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button10->SetDefault();
m_button10->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
bSizer22->Add( m_button10, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
- m_button17 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button17 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button17->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer22->Add( m_button17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@@ -3441,13 +3415,13 @@ GlobalSettingsDlgGenerated::GlobalSettingsDlgGenerated( wxWindow* parent, wxWind
bSizer97->Add( 0, 0, 1, 0, 5 );
- m_buttonOkay = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
bSizer97->Add( m_buttonOkay, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
- m_button29 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button29->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer97->Add( m_button29, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -3460,6 +3434,8 @@ GlobalSettingsDlgGenerated::GlobalSettingsDlgGenerated( wxWindow* parent, wxWind
this->Layout();
bSizer95->Fit( this );
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) );
m_buttonResetDialogs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnResetDialogs ), NULL, this );
@@ -3493,7 +3469,7 @@ SyncPreviewDlgGenerated::SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID i
wxBoxSizer* bSizer158;
bSizer158 = new wxBoxSizer( wxHORIZONTAL );
- m_buttonStartSync = new zen::BitmapButton( this, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
+ m_buttonStartSync = new zen::BitmapButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
m_buttonStartSync->SetDefault();
m_buttonStartSync->SetFont( wxFont( 14, 70, 90, 92, false, wxEmptyString ) );
m_buttonStartSync->SetToolTip( _("Start synchronization") );
@@ -3659,7 +3635,7 @@ SyncPreviewDlgGenerated::SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID i
bSizer142->Add( 10, 0, 1, 0, 5 );
- m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button16 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button16->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer142->Add( m_button16, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
@@ -3672,6 +3648,8 @@ SyncPreviewDlgGenerated::SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID i
this->Layout();
bSizer134->Fit( this );
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) );
m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this );
@@ -3752,7 +3730,7 @@ SearchDialogGenerated::SearchDialogGenerated( wxWindow* parent, wxWindowID id, c
bSizer97->Add( m_buttonFindNext, 0, wxEXPAND|wxTOP|wxRIGHT, 5 );
- m_button29 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button29->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer97->Add( m_button29, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 5 );
@@ -3763,7 +3741,8 @@ SearchDialogGenerated::SearchDialogGenerated( wxWindow* parent, wxWindowID id, c
this->SetSizer( bSizer161 );
this->Layout();
- bSizer161->Fit( this );
+
+ this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SearchDialogGenerated::OnClose ) );
@@ -3807,13 +3786,13 @@ SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWind
bSizer97->Add( 0, 0, 1, wxEXPAND, 5 );
- m_buttonOkay = new wxButton( this, wxID_ANY, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
bSizer97->Add( m_buttonOkay, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
- m_button29 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button29->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
bSizer97->Add( m_button29, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@@ -3829,6 +3808,8 @@ SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWind
this->Layout();
bSizer96->Fit( this );
+ this->Centre( wxBOTH );
+
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SelectTimespanDlgGenerated::OnClose ) );
m_calendarFrom->Connect( wxEVT_CALENDAR_SEL_CHANGED, wxCalendarEventHandler( SelectTimespanDlgGenerated::OnChangeSelectionFrom ), NULL, this );
diff --git a/ui/gui_generated.h b/ui/gui_generated.h
index 8176dbf9..bd7c6be4 100644
--- a/ui/gui_generated.h
+++ b/ui/gui_generated.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Mar 17 2012)
+// C++ code generated with wxFormBuilder (version Apr 10 2012)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -262,9 +262,7 @@ protected:
wxBoxSizer* bSizerFilesRemaining;
wxStaticText* m_staticText46;
wxStaticText* m_staticTextFilesRemaining;
- wxStaticText* m_staticText117;
wxStaticText* m_staticTextDataRemaining;
- wxStaticText* m_staticText118;
wxBoxSizer* sSizerSpeed;
wxStaticText* m_staticText104;
wxStaticText* m_staticTextSpeed;
@@ -527,21 +525,17 @@ protected:
wxStaticText* m_staticTextLabelItemsProc;
wxBoxSizer* bSizerItemsProc;
wxStaticText* m_staticTextProcessedObj;
- wxStaticText* m_staticText98;
wxStaticText* m_staticTextDataProcessed;
- wxStaticText* m_staticText99;
wxStaticText* m_staticTextLabelItemsRem;
wxBoxSizer* bSizerItemsRem;
wxStaticText* m_staticTextRemainingObj;
- wxStaticText* m_staticText96;
wxStaticText* m_staticTextDataRemaining;
- wxStaticText* m_staticText97;
- wxStaticText* m_staticTextLabelElapsedTime;
- wxStaticText* m_staticTextTimeElapsed;
- wxStaticText* m_staticTextLabelRemTime;
- wxStaticText* m_staticTextRemTime;
wxStaticText* m_staticText84;
wxStaticText* m_staticTextSpeed;
+ wxStaticText* m_staticTextLabelRemTime;
+ wxStaticText* m_staticTextRemTime;
+ wxStaticText* m_staticTextLabelElapsedTime;
+ wxStaticText* m_staticTextTimeElapsed;
zen::Graph2D* m_panelGraph;
wxBoxSizer* bSizerFinalStat;
wxListbook* m_listbookResult;
@@ -948,7 +942,7 @@ protected:
public:
- SearchDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Find"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE );
+ SearchDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Find"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 384,97 ), long style = wxDEFAULT_DIALOG_STYLE );
~SearchDialogGenerated();
};
diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp
index 6e3c08a0..65e40410 100644
--- a/ui/gui_status_handler.cpp
+++ b/ui/gui_status_handler.cpp
@@ -5,13 +5,11 @@
// **************************************************************************
#include "gui_status_handler.h"
-#include "small_dlgs.h"
+#include <wx/wupdlock.h>
+#include <wx+/shell_execute.h>
#include "msg_popup.h"
#include "main_dlg.h"
-#include <wx/wupdlock.h>
-#include <wx+/string_conv.h>
#include "exec_finished_box.h"
-#include <wx+/shell_execute.h>
using namespace zen;
using namespace xmlAccess;
@@ -19,24 +17,24 @@ using namespace xmlAccess;
CompareStatusHandler::CompareStatusHandler(MainDialog& dlg) :
mainDlg(dlg),
- ignoreErrors(false),
- currentProcess(StatusHandler::PROCESS_NONE)
+ ignoreErrors(false)
{
- wxWindowUpdateLocker dummy(&mainDlg); //avoid display distortion
+ {
+ wxWindowUpdateLocker dummy(&mainDlg); //avoid display distortion
- //prevent user input during "compare", do not disable maindialog since abort-button would also be disabled
- mainDlg.disableAllElements(true);
- mainDlg.compareStatus->init(); //clear old values
+ //prevent user input during "compare", do not disable maindialog since abort-button would also be disabled
+ mainDlg.disableAllElements(true);
- //display status panel during compare
- mainDlg.auiMgr.GetPane(mainDlg.compareStatus->getAsWindow()).Show();
- mainDlg.auiMgr.Update();
- mainDlg.compareStatus->updateStatusPanelNow(); //clear gui flicker: window must be visible to make this work!
+ //display status panel during compare
+ mainDlg.compareStatus->init(*this); //clear old values before showing panel
+ mainDlg.auiMgr.GetPane(mainDlg.compareStatus->getAsWindow()).Show();
+ mainDlg.auiMgr.Update();
- //register abort button
- mainDlg.m_buttonAbort->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this);
- //register key event
- mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this);
+ //register keys
+ mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this);
+ mainDlg.m_buttonAbort->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this);
+ }
+ mainDlg.Update(); //don't wait until idle event!
}
@@ -46,17 +44,17 @@ CompareStatusHandler::~CompareStatusHandler()
//reenable complete main dialog
mainDlg.enableAllElements();
- mainDlg.compareStatus->finalize();
+ mainDlg.compareStatus->finalize();
mainDlg.auiMgr.GetPane(mainDlg.compareStatus->getAsWindow()).Hide();
mainDlg.auiMgr.Update();
- if (abortIsRequested())
- mainDlg.pushStatusInformation(_("Operation aborted!"));
-
- //de-register keys
+ //unregister keys
mainDlg.Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this);
mainDlg.m_buttonAbort->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this);
+
+ if (abortIsRequested())
+ mainDlg.pushStatusInformation(_("Operation aborted!"));
}
@@ -73,71 +71,29 @@ void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event)
}
-void CompareStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID)
+void CompareStatusHandler::initNewPhase(int objectsTotal, Int64 dataTotal, Phase phaseID)
{
- currentProcess = processID;
+ StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID);
- switch (currentProcess)
+ switch (currentPhase())
{
- case StatusHandler::PROCESS_SCANNING:
+ case PHASE_NONE:
+ case PHASE_SYNCHRONIZING:
+ assert(false);
+ case PHASE_SCANNING:
break;
- case StatusHandler::PROCESS_COMPARING_CONTENT:
+ case PHASE_COMPARING_CONTENT:
{
wxWindowUpdateLocker dummy(&mainDlg);
- mainDlg.compareStatus->switchToCompareBytewise(objectsTotal, dataTotal);
+ mainDlg.compareStatus->switchToCompareBytewise();
mainDlg.Layout(); //show progress bar...
mainDlg.Refresh(); //remove distortion...
}
break;
- case StatusHandler::PROCESS_SYNCHRONIZING:
- case StatusHandler::PROCESS_NONE:
- assert(false);
- break;
}
}
-void CompareStatusHandler::updateProcessedData(int objectsDelta, zen::Int64 dataDelta)
-{
- switch (currentProcess)
- {
- case StatusHandler::PROCESS_SCANNING:
- mainDlg.compareStatus->incScannedObjects_NoUpdate(objectsDelta); //throw ()
- break;
- case StatusHandler::PROCESS_COMPARING_CONTENT:
- mainDlg.compareStatus->incProcessedCmpData_NoUpdate(objectsDelta, dataDelta); //throw ()
- break;
- case StatusHandler::PROCESS_SYNCHRONIZING:
- case StatusHandler::PROCESS_NONE:
- assert(false);
- break;
- }
-
- //note: this method must NOT throw in order to properly allow undoing setting of statistics!
-}
-
-
-void CompareStatusHandler::updateTotalData(int objectsDelta, Int64 dataDelta)
-{
- assert(currentProcess != PROCESS_SCANNING);
- mainDlg.compareStatus->incTotalCmpData_NoUpdate(objectsDelta, dataDelta);
-}
-
-
-void CompareStatusHandler::reportStatus(const std::wstring& text)
-{
- mainDlg.compareStatus->setStatusText_NoUpdate(text);
- requestUiRefresh(); //throw AbortThisProcess
-}
-
-
-void CompareStatusHandler::reportInfo(const std::wstring& text)
-{
- mainDlg.compareStatus->setStatusText_NoUpdate(text);
- requestUiRefresh(); //throw AbortThisProcess
-}
-
-
ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring& message)
{
if (ignoreErrors)
@@ -146,7 +102,8 @@ ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring&
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
+ switch (showErrorDlg(&mainDlg,
+ ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
message, &ignoreNextErrors))
{
case ReturnErrorDlg::BUTTON_IGNORE:
@@ -169,8 +126,7 @@ void CompareStatusHandler::reportFatalError(const std::wstring& errorMessage)
{
forceUiRefresh();
- showErrorDlg(ReturnErrorDlg::BUTTON_ABORT,
- errorMessage, nullptr);
+ showErrorDlg(&mainDlg, ReturnErrorDlg::BUTTON_ABORT, errorMessage, nullptr);
}
@@ -183,9 +139,9 @@ void CompareStatusHandler::reportWarning(const std::wstring& warningMessage, boo
//show pop-up and ask user how to handle warning
bool dontWarnAgain = false;
- switch (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_ABORT,
- warningMessage,
- dontWarnAgain))
+ switch (showWarningDlg(&mainDlg,
+ ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_ABORT,
+ warningMessage, dontWarnAgain))
{
case ReturnWarningDlg::BUTTON_IGNORE:
warningActive = !dontWarnAgain;
@@ -214,7 +170,7 @@ void CompareStatusHandler::OnAbortCompare(wxCommandEvent& event)
void CompareStatusHandler::abortThisProcess()
{
- requestAbortion();
+ requestAbortion(); //just make sure...
throw GuiAbortProcess();
}
//########################################################################################################
@@ -226,7 +182,7 @@ SyncStatusHandler::SyncStatusHandler(MainDialog* parentDlg,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory) :
parentDlg_(parentDlg),
- syncStatusFrame(*this, parentDlg, SyncStatus::SYNCHRONIZING, true, jobName, execWhenFinished, execFinishedHistory),
+ syncStatusFrame(*this, *this, parentDlg, true, jobName, execWhenFinished, execFinishedHistory),
handleError_(handleError)
{
}
@@ -238,11 +194,17 @@ SyncStatusHandler::~SyncStatusHandler()
//finalize error log
if (abortIsRequested())
- errorLog.logMsg(_("Synchronization aborted!"), TYPE_FATAL_ERROR);
+ errorLog.logMsg(_("Synchronization aborted!"), TYPE_ERROR);
else if (totalErrors > 0)
errorLog.logMsg(_("Synchronization completed with errors!"), TYPE_WARNING);
else
- errorLog.logMsg(_("Synchronization completed successfully!"), TYPE_INFO);
+ {
+ if (getObjectsTotal(PHASE_SYNCHRONIZING) == 0 && //we're past "initNewPhase(PHASE_SYNCHRONIZING)" at this point!
+ getDataTotal (PHASE_SYNCHRONIZING) == 0)
+ errorLog.logMsg(_("Nothing to synchronize!"), TYPE_INFO); //even if "ignored conflicts" occurred!
+ else
+ errorLog.logMsg(_("Synchronization completed successfully!"), TYPE_INFO);
+ }
bool showFinalResults = true;
@@ -260,60 +222,37 @@ SyncStatusHandler::~SyncStatusHandler()
if (showFinalResults)
{
if (abortIsRequested())
- syncStatusFrame.processHasFinished(SyncStatus::ABORTED, errorLog); //enable okay and close events
+ syncStatusFrame.processHasFinished(SyncStatus::RESULT_ABORTED, errorLog); //enable okay and close events
else if (totalErrors > 0)
- syncStatusFrame.processHasFinished(SyncStatus::FINISHED_WITH_ERROR, errorLog);
+ syncStatusFrame.processHasFinished(SyncStatus::RESULT_FINISHED_WITH_ERROR, errorLog);
else
- syncStatusFrame.processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS, errorLog);
+ syncStatusFrame.processHasFinished(SyncStatus::RESULT_FINISHED_WITH_SUCCESS, errorLog);
}
else
syncStatusFrame.closeWindowDirectly(); //syncStatusFrame is main window => program will quit directly
}
-void SyncStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID)
+void SyncStatusHandler::initNewPhase(int objectsTotal, Int64 dataTotal, Phase phaseID)
{
- switch (processID)
- {
- case StatusHandler::PROCESS_SYNCHRONIZING:
- syncStatusFrame.initNewProcess(SyncStatus::SYNCHRONIZING, objectsTotal, dataTotal);
- break;
- case StatusHandler::PROCESS_SCANNING:
- case StatusHandler::PROCESS_COMPARING_CONTENT:
- case StatusHandler::PROCESS_NONE:
- assert(false);
- break;
- }
+ assert(phaseID == PHASE_SYNCHRONIZING);
+ StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID);
+ syncStatusFrame.initNewPhase(); //call after "StatusHandler::initNewPhase"
}
void SyncStatusHandler::updateProcessedData(int objectsDelta, Int64 dataDelta)
{
- syncStatusFrame.incProcessedData_NoUpdate(objectsDelta, dataDelta); //throw ()
-
+ StatusHandler::updateProcessedData(objectsDelta, dataDelta);
+ syncStatusFrame.reportCurrentBytes(getDataCurrent(currentPhase())); //throw ()
//note: this method should NOT throw in order to properly allow undoing setting of statistics!
}
-void SyncStatusHandler::updateTotalData(int objectsDelta, Int64 dataDelta)
-{
- syncStatusFrame.incTotalData_NoUpdate(objectsDelta, dataDelta); //throw ()
-}
-
-
-void SyncStatusHandler::reportStatus(const std::wstring& text)
-{
- syncStatusFrame.setStatusText_NoUpdate(text); //throw ()
- requestUiRefresh(); //throw AbortThisProccess
-}
-
-
void SyncStatusHandler::reportInfo(const std::wstring& text)
{
+ StatusHandler::reportInfo(text);
errorLog.logMsg(text, TYPE_INFO);
-
- syncStatusFrame.setStatusText_NoUpdate(text); //throw ()
- requestUiRefresh(); //throw AbortThisProccess
}
@@ -332,7 +271,8 @@ ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& err
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
+ switch (showErrorDlg(parentDlg_,
+ ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
errorMessage,
&ignoreNextErrors))
{
@@ -351,9 +291,8 @@ ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& err
break;
}
- assert (false);
- errorLog.logMsg(errorMessage, TYPE_ERROR);
- return ProcessCallback::IGNORE_ERROR;
+ assert(false);
+ return ProcessCallback::IGNORE_ERROR; //dummy value
}
@@ -369,9 +308,9 @@ void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage)
forceUiRefresh();
bool ignoreNextErrors = false;
- switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_ABORT,
- errorMessage,
- &ignoreNextErrors))
+ switch (showErrorDlg(parentDlg_,
+ ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_ABORT,
+ errorMessage, &ignoreNextErrors))
{
case ReturnErrorDlg::BUTTON_IGNORE:
if (ignoreNextErrors) //falsify only
@@ -398,47 +337,48 @@ void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool&
{
errorLog.logMsg(warningMessage, TYPE_WARNING);
+ if (!warningActive)
+ return;
+
switch (handleError_)
{
case ON_GUIERROR_POPUP:
- break;
- case ON_GUIERROR_IGNORE:
- return; //if errors are ignored, then warnings should also
- }
- if (!warningActive)
- return;
+ {
+ PauseTimers dummy(syncStatusFrame);
+ forceUiRefresh();
- PauseTimers dummy(syncStatusFrame);
- forceUiRefresh();
+ bool dontWarnAgain = false;
+ switch (showWarningDlg(parentDlg_,
+ ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_ABORT,
+ warningMessage, dontWarnAgain))
+ {
+ case ReturnWarningDlg::BUTTON_IGNORE: //no unhandled error situation!
+ warningActive = !dontWarnAgain;
+ break;
- bool dontWarnAgain = false;
- switch (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_ABORT,
- warningMessage,
- dontWarnAgain))
- {
- case ReturnWarningDlg::BUTTON_IGNORE: //no unhandled error situation!
- warningActive = !dontWarnAgain;
- return;
+ case ReturnWarningDlg::BUTTON_SWITCH:
+ assert(false);
+ case ReturnWarningDlg::BUTTON_ABORT:
+ abortThisProcess();
+ break;
+ }
+ }
+ break;
- case ReturnWarningDlg::BUTTON_SWITCH:
- assert(false);
- case ReturnWarningDlg::BUTTON_ABORT:
- abortThisProcess();
- return;
+ case ON_GUIERROR_IGNORE:
+ break; //if errors are ignored, then warnings should be, too
}
-
- assert(false);
}
void SyncStatusHandler::forceUiRefresh()
{
- syncStatusFrame.updateStatusDialogNow();
+ syncStatusFrame.updateProgress();
}
void SyncStatusHandler::abortThisProcess()
{
- requestAbortion();
+ requestAbortion(); //just make sure...
throw GuiAbortProcess(); //abort can be triggered by syncStatusFrame
}
diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h
index 4e289648..ebc59473 100644
--- a/ui/gui_status_handler.h
+++ b/ui/gui_status_handler.h
@@ -21,17 +21,13 @@ class wxCommandEvent;
class GuiAbortProcess {};
//classes handling sync and compare error as well as status information
-class CompareStatusHandler : private wxEvtHandler, public StatusHandler
+class CompareStatusHandler : private wxEvtHandler, public zen::StatusHandler
{
public:
CompareStatusHandler(MainDialog& dlg);
~CompareStatusHandler();
- virtual void initNewProcess (int objectsTotal, zen::Int64 dataTotal, Process processID);
- virtual void updateProcessedData(int objectsDelta, zen::Int64 dataDelta);
- virtual void updateTotalData (int objectsDelta, zen::Int64 dataDelta);
- virtual void reportStatus(const std::wstring& text);
- virtual void reportInfo(const std::wstring& text);
+ virtual void initNewPhase (int objectsTotal, zen::Int64 dataTotal, Phase phaseID);
virtual void forceUiRefresh();
virtual Response reportError(const std::wstring& text);
@@ -41,15 +37,14 @@ public:
private:
void OnKeyPressed(wxKeyEvent& event);
void OnAbortCompare(wxCommandEvent& event); //handle abort button click
- virtual void abortThisProcess();
+ virtual void abortThisProcess(); //throw GuiAbortProcess
MainDialog& mainDlg;
bool ignoreErrors;
- Process currentProcess;
};
-class SyncStatusHandler : public StatusHandler
+class SyncStatusHandler : public zen::StatusHandler
{
public:
SyncStatusHandler(MainDialog* parentDlg,
@@ -59,10 +54,8 @@ public:
std::vector<std::wstring>& execFinishedHistory);
~SyncStatusHandler();
- virtual void initNewProcess (int objectsTotal, zen::Int64 dataTotal, Process processID);
+ virtual void initNewPhase (int objectsTotal, zen::Int64 dataTotal, Phase phaseID);
virtual void updateProcessedData(int objectsDelta, zen::Int64 dataDelta);
- virtual void updateTotalData (int objectsDelta, zen::Int64 dataDelta);
- virtual void reportStatus(const std::wstring& text);
virtual void reportInfo(const std::wstring& text);
virtual void forceUiRefresh();
@@ -71,7 +64,7 @@ public:
virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive);
private:
- virtual void abortThisProcess();
+ virtual void abortThisProcess(); //throw GuiAbortProcess
MainDialog* parentDlg_;
SyncStatus syncStatusFrame; //the window managed by SyncStatus has longer lifetime than this handler!
diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp
index 85f9a580..049a1176 100644
--- a/ui/main_dlg.cpp
+++ b/ui/main_dlg.cpp
@@ -39,8 +39,8 @@
#include "../lib/resources.h"
#include <zen/file_handling.h>
#include <zen/file_id.h>
+#include <zen/recycler.h>
#include "../lib/resolve_path.h"
-#include "../lib/recycler.h"
#include "../lib/ffs_paths.h"
#include <wx+/toggle_button.h>
#include "folder_pair.h"
@@ -119,7 +119,7 @@ public:
return false;
}
- switch (xmlAccess::getMergeType(droppedFiles)) //throw ()
+ switch (xmlAccess::getMergeType(toZ(droppedFiles))) //throw()
{
case xmlAccess::MERGE_BATCH:
case xmlAccess::MERGE_GUI:
@@ -363,20 +363,20 @@ MainDialog::MainDialog(const std::vector<wxString>& cfgFileNames, xmlAccess::Xml
//------------------------------------------------------------------------------------------
//check existence of all directories in parallel!
- std::list<boost::unique_future<bool>> fileEx;
+
+ RunUntilFirstHit<NullType> findFirstMissing;
std::for_each(filenames.begin(), filenames.end(),
- [&fileEx](const wxString& filename)
+ [&](const wxString& filename)
{
const Zstring filenameFmt = toZ(filename); //convert to Zstring first: we don't want to pass wxString by value and risk MT issues!
- fileEx.push_back(zen::async2<bool>([=]() { return !filenameFmt.empty() && zen::fileExists(filenameFmt); }));
+ findFirstMissing.addJob([=] { return filenameFmt.empty() || !fileExists(filenameFmt) ? zen::make_unique<NullType>() : nullptr; });
});
//potentially slow network access: give all checks 500ms to finish
- wait_for_all_timed(fileEx.begin(), fileEx.end(), boost::posix_time::milliseconds(500));
+ const bool allFilesExist = findFirstMissing.timedWait(boost::posix_time::milliseconds(500)) && //false: time elapsed
+ !findFirstMissing.get(); //no missing
//------------------------------------------------------------------------------------------
- //check if one of the files is not existing (this shall not be an error!)
- const bool allFilesExist = std::all_of(fileEx.begin(), fileEx.end(), [](boost::unique_future<bool>& ft) { return ft.is_ready() && ft.get(); });
if (!allFilesExist)
filenames.clear();
@@ -392,16 +392,16 @@ MainDialog::MainDialog(const std::vector<wxString>& cfgFileNames, xmlAccess::Xml
try
{
//load XML
- xmlAccess::convertConfig(filenames, guiCfg); //throw (xmlAccess::FfsXmlError)
+ xmlAccess::convertConfig(toZ(filenames), guiCfg); //throw xmlAccess::FfsXmlError
loadCfgSuccess = true;
}
catch (const xmlAccess::FfsXmlError& error)
{
if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING);
+ wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
else
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
}
const bool startComparisonImmediately = !cfgFileNames.empty() && loadCfgSuccess;
@@ -437,7 +437,7 @@ MainDialog::~MainDialog()
const xmlAccess::XmlGuiConfig guiCfg = getConfig();
try
{
- xmlAccess::writeConfig(guiCfg, lastRunConfigName());
+ xmlAccess::writeConfig(guiCfg, toZ(lastRunConfigName()));
//setLastUsedConfig(lastRunConfigName(), guiCfg); -> may be removed!?
}
//don't annoy users on read-only drives: no error checking should be fine since this is not a config the user explicitly wanted to save
@@ -456,7 +456,7 @@ MainDialog::~MainDialog()
void MainDialog::onQueryEndSession()
{
writeGlobalSettings();
- try { xmlAccess::writeConfig(getConfig(), lastRunConfigName()); }
+ try { xmlAccess::writeConfig(getConfig(), toZ(lastRunConfigName())); }
catch (const xmlAccess::FfsXmlError&) {}
}
@@ -703,29 +703,31 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
//------------------------------------------------------------------------------------------
//check existence of all directories in parallel!
- std::list<boost::unique_future<bool>> dirEx;
+ RunUntilFirstHit<NullType> findFirstMissing;
- auto addDirCheck = [&dirEx](const FolderPairEnh& fp)
+ bool haveNonEmptyPair = false;
+ auto addDirCheck = [&](const FolderPairEnh& fp)
{
- const Zstring dirFmtLeft = zen::getFormattedDirectoryName(fp.leftDirectory);
- const Zstring dirFmtRight = zen::getFormattedDirectoryName(fp.rightDirectory);
+ const Zstring dirFmtLeft = getFormattedDirectoryName(fp.leftDirectory ); //should not block!?
+ const Zstring dirFmtRight = getFormattedDirectoryName(fp.rightDirectory); //
if (dirFmtLeft.empty() && dirFmtRight.empty()) //only skip check if both sides are empty!
return;
-
- dirEx.push_back(zen::async2<bool>([=] { return !dirFmtLeft .empty() && zen::dirExists(dirFmtLeft); }));
- dirEx.push_back(zen::async2<bool>([=] { return !dirFmtRight.empty() && zen::dirExists(dirFmtRight); }));
+ haveNonEmptyPair = true;
+ findFirstMissing.addJob([=] { return dirFmtLeft .empty() || !dirExists(dirFmtLeft ) ? zen::make_unique<NullType>() : nullptr; });
+ findFirstMissing.addJob([=] { return dirFmtRight.empty() || !dirExists(dirFmtRight) ? zen::make_unique<NullType>() : nullptr; });
};
+
addDirCheck(currMainCfg.firstPair);
std::for_each(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(), addDirCheck);
- if (!dirEx.empty())
+ //------------------------------------------------------------------------------------------
+
+ if (haveNonEmptyPair)
{
//potentially slow network access: give all checks 500ms to finish
- wait_for_all_timed(dirEx.begin(), dirEx.end(), boost::posix_time::milliseconds(500));
- //------------------------------------------------------------------------------------------
-
- const bool allFoldersExist = std::all_of(dirEx.begin(), dirEx.end(), [](boost::unique_future<bool>& ft) { return ft.is_ready() && ft.get(); });
- if (allFoldersExist)
+ const bool allFilesExist = findFirstMissing.timedWait(boost::posix_time::milliseconds(500)) && //true: have result
+ !findFirstMissing.get(); //no missing
+ if (allFilesExist)
{
wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED);
m_buttonCompare->GetEventHandler()->AddPendingEvent(dummy2); //simulate button click on "compare"
@@ -816,9 +818,9 @@ void MainDialog::writeGlobalSettings()
//write list of last used configuration files
std::vector<wxString> cfgFileHistory;
- for (int i = 0; i < static_cast<int>(m_listBoxHistory->GetCount()); ++i)
- if (m_listBoxHistory->GetClientObject(i))
- cfgFileHistory.push_back(static_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(i))->name_);
+ for (unsigned int i = 0; i < m_listBoxHistory->GetCount(); ++i)
+ if (auto clientString = dynamic_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(i)))
+ cfgFileHistory.push_back(clientString->name_);
globalSettings->gui.cfgFileHistory = cfgFileHistory;
globalSettings->gui.lastUsedConfigFiles = activeConfigFiles;
@@ -951,9 +953,7 @@ std::vector<FileSystemObject*> MainDialog::getGridSelection(bool fromLeft, bool
if (fromRight)
addSelection(gridview::COMP_RIGHT);
- std::vector<FileSystemObject*> selection;
- gridDataView->getAllFileRef(selectedRows, selection);
- return selection;
+ return gridDataView->getAllFileRef(selectedRows);
}
@@ -1022,7 +1022,8 @@ public:
return DeleteFilesHandler::IGNORE_ERROR;
bool ignoreNextErrors = false;
- switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
+ switch (showErrorDlg(mainDlg,
+ ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT,
errorMessage, &ignoreNextErrors))
{
case ReturnErrorDlg::BUTTON_IGNORE:
@@ -1094,7 +1095,8 @@ void MainDialog::deleteSelectedFiles(const std::vector<FileSystemObject*>& selec
wxWindow* oldFocus = wxWindow::FindFocus();
ZEN_ON_SCOPE_EXIT( if (oldFocus) oldFocus->SetFocus(); )
- if (zen::showDeleteDialog(selectionLeft,
+ if (zen::showDeleteDialog(this,
+ selectionLeft,
selectionRight,
globalSettings->gui.deleteOnBothSides,
globalSettings->gui.useRecyclerForManualDeletion) == ReturnSmallDlg::BUTTON_OKAY)
@@ -1535,7 +1537,7 @@ void MainDialog::OnGlobalKeyEvent(wxKeyEvent& event) //process key events withou
switch (keyCode)
{
case 'F': //CTRL + F
- zen::startFind(*this, *m_gridMain, gridview::COMP_LEFT, gridview::COMP_RIGHT, globalSettings->gui.textSearchRespectCase);
+ zen::startFind(this, *m_gridMain, gridview::COMP_LEFT, gridview::COMP_RIGHT, globalSettings->gui.textSearchRespectCase);
return; //-> swallow event!
}
@@ -1543,7 +1545,7 @@ void MainDialog::OnGlobalKeyEvent(wxKeyEvent& event) //process key events withou
{
case WXK_F3: //F3
case WXK_NUMPAD_F3: //
- zen::findNext(*this, *m_gridMain, gridview::COMP_LEFT, gridview::COMP_RIGHT, globalSettings->gui.textSearchRespectCase);
+ zen::findNext(this, *m_gridMain, gridview::COMP_LEFT, gridview::COMP_RIGHT, globalSettings->gui.textSearchRespectCase);
return; //-> swallow event!
case WXK_F8: //F8
@@ -1679,15 +1681,19 @@ void MainDialog::onNaviGridContext(GridClickEvent& event)
menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false);
//----------------------------------------------------------------------------------------------------
- //CONTEXT_EXCLUDE_OBJ
+ //EXCLUDE FILTER
if (selection.size() == 1)
- menu.addItem(_("Exclude via filter:") + L" " + afterLast(selection[0]->getObjRelativeName(), FILE_NAME_SEPARATOR),
- [this, &selection] { excludeItems(selection); },
- &GlobalResources::getImage(L"filterOnSmall"));
+ {
+ //by relative path
+ menu.addItem(_("Exclude via filter:") + L" " + (FILE_NAME_SEPARATOR + selection[0]->getObjRelativeName()),
+ [this, &selection] { excludeItems(selection); }, &GlobalResources::getImage(L"filterOnSmall"));
+ }
else if (selection.size() > 1)
+ {
+ //by relative path
menu.addItem(_("Exclude via filter:") + L" " + _("<multiple selection>"),
- [this, &selection] { excludeItems(selection); },
- &GlobalResources::getImage(L"filterOnSmall"));
+ [this, &selection] { excludeItems(selection); }, &GlobalResources::getImage(L"filterOnSmall"));
+ }
//----------------------------------------------------------------------------------------------------
//CONTEXT_DELETE_FILES
@@ -1743,30 +1749,40 @@ void MainDialog::onMainGridContext(GridClickEvent& event)
menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false);
//----------------------------------------------------------------------------------------------------
- //CONTEXT_EXCLUDE_EXT
- if (!selection.empty() &&
- dynamic_cast<const DirMapping*>(selection[0]) == nullptr) //non empty && no directory
+ //EXCLUDE FILTER
+ if (selection.size() == 1)
{
- const Zstring filename = afterLast(selection[0]->getObjRelativeName(), FILE_NAME_SEPARATOR);
- if (filename.find(Zchar('.')) != Zstring::npos) //be careful: AfterLast would return the whole string if '.' were not found!
+ ContextMenu submenu;
+
+ //by extension
+ if (dynamic_cast<const DirMapping*>(selection[0]) == nullptr) //non empty && no directory
{
- const Zstring extension = afterLast(filename, Zchar('.'));
+ const Zstring filename = afterLast(selection[0]->getObjRelativeName(), FILE_NAME_SEPARATOR);
+ if (contains(filename, Zchar('.'))) //be careful: AfterLast would return the whole string if '.' were not found!
+ {
+ const Zstring extension = afterLast(filename, Zchar('.'));
- menu.addItem(_("Exclude via filter:") + L" *." + extension,
- [this, extension] { excludeExtension(extension); },
- &GlobalResources::getImage(L"filterOnSmall"));
+ submenu.addItem(L"*." + utf8CvrtTo<wxString>(extension),
+ [this, extension] { excludeExtension(extension); });
+ }
}
+
+ //by short name
+ submenu.addItem(utf8CvrtTo<wxString>(Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + selection[0]->getObjShortName()),
+ [this, &selection] { excludeShortname(*selection[0]); });
+
+ //by relative path
+ submenu.addItem(utf8CvrtTo<wxString>(FILE_NAME_SEPARATOR + selection[0]->getObjRelativeName()),
+ [this, &selection] { excludeItems(selection); });
+
+ menu.addSubmenu(_("Exclude via filter:"), submenu, &GlobalResources::getImage(L"filterOnSmall"));
}
- //----------------------------------------------------------------------------------------------------
- //CONTEXT_EXCLUDE_OBJ
- if (selection.size() == 1)
- menu.addItem(_("Exclude via filter:") + L" " + afterLast(selection[0]->getObjRelativeName(), FILE_NAME_SEPARATOR),
- [this, &selection] { excludeItems(selection); },
- &GlobalResources::getImage(L"filterOnSmall"));
else if (selection.size() > 1)
+ {
+ //by relative path
menu.addItem(_("Exclude via filter:") + L" " + _("<multiple selection>"),
- [this, &selection] { excludeItems(selection); },
- &GlobalResources::getImage(L"filterOnSmall"));
+ [this, &selection] { excludeItems(selection); }, &GlobalResources::getImage(L"filterOnSmall"));
+ }
//----------------------------------------------------------------------------------------------------
//CONTEXT_EXTERNAL_APP
@@ -1836,10 +1852,28 @@ void MainDialog::excludeExtension(const Zstring& extension)
updateFilterButtons();
//do not fully apply filter, just exclude new items
- std::for_each(begin(folderCmp), end(folderCmp),
- [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); });
+ std::for_each(begin(folderCmp), end(folderCmp), [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); });
+ updateGui();
+}
- //applyFiltering(getConfig().mainCfg, gridDataView->getDataTentative());
+
+void MainDialog::excludeShortname(const FileSystemObject& fsObj)
+{
+ Zstring newExclude = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + fsObj.getObjShortName();
+ const bool isDir = dynamic_cast<const DirMapping*>(&fsObj) != nullptr;
+ if (isDir)
+ newExclude += FILE_NAME_SEPARATOR;
+
+ //add to filter config
+ Zstring& excludeFilter = currentCfg.mainCfg.globalFilter.excludeFilter;
+ if (!excludeFilter.empty() && !endsWith(excludeFilter, Zstr("\n")))
+ excludeFilter += Zstr("\n");
+ excludeFilter += newExclude;
+
+ updateFilterButtons();
+
+ //do not fully apply filter, just exclude new items
+ std::for_each(begin(folderCmp), end(folderCmp), [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); });
updateGui();
}
@@ -1856,7 +1890,7 @@ void MainDialog::excludeItems(const std::vector<FileSystemObject*>& selection)
if (iter != selection.begin())
newExclude += Zstr("\n");
- //#pragma warning(suppress: 6011) -> fsObj cannot be NULL here!
+ //#pragma warning(suppress: 6011) -> fsObj bound in this context!
newExclude += FILE_NAME_SEPARATOR + fsObj->getObjRelativeName();
const bool isDir = dynamic_cast<const DirMapping*>(fsObj) != nullptr;
@@ -1873,10 +1907,7 @@ void MainDialog::excludeItems(const std::vector<FileSystemObject*>& selection)
updateFilterButtons();
//do not fully apply filter, just exclude new items
- std::for_each(begin(folderCmp), end(folderCmp),
- [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); });
-
- //applyFiltering(getConfig().mainCfg, gridDataView->getDataTentative());
+ std::for_each(begin(folderCmp), end(folderCmp), [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); });
updateGui();
}
}
@@ -1953,7 +1984,7 @@ void MainDialog::onGridLabelContext(GridClickEvent& event)
auto selectTimeSpan = [&]
{
- if (showSelectTimespanDlg(manualTimeSpanFrom, manualTimeSpanTo) == ReturnSmallDlg::BUTTON_OKAY)
+ if (showSelectTimespanDlg(this, manualTimeSpanFrom, manualTimeSpanTo) == ReturnSmallDlg::BUTTON_OKAY)
{
applyTimeSpanFilter(folderCmp, manualTimeSpanFrom, manualTimeSpanTo); //overwrite current active/inactive settings
updateGuiAfterFilterChange(400);
@@ -2062,22 +2093,8 @@ void MainDialog::OnDirSelected(wxFileDirPickerEvent& event)
void MainDialog::onNaviPanelFilesDropped(FileDropEvent& event)
{
- const auto& droppedFiles = event.getFiles();
-
- switch (xmlAccess::getMergeType(droppedFiles)) //throw ()
- {
- case xmlAccess::MERGE_BATCH:
- case xmlAccess::MERGE_GUI:
- case xmlAccess::MERGE_GUI_BATCH:
- loadConfiguration(droppedFiles);
- return;
-
- case xmlAccess::MERGE_OTHER:
- break;
- }
-
+ loadConfiguration(event.getFiles());
event.Skip();
-
}
@@ -2180,17 +2197,17 @@ bool MainDialog::trySaveConfig(const wxString* fileName) //return true if saved
targetFilename = *fileName;
else
{
- wxString defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxT("SyncSettings.ffs_gui");
+ wxString defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : L"SyncSettings.ffs_gui";
//attention: activeConfigFiles may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config!
- if (defaultFileName.EndsWith(wxT(".ffs_batch")))
- defaultFileName.Replace(wxT(".ffs_batch"), wxT(".ffs_gui"), false);
+ if (endsWith(defaultFileName, L".ffs_batch"))
+ replace(defaultFileName, L".ffs_batch", L".ffs_gui", false);
- wxFileDialog filePicker(this,
+ wxFileDialog filePicker(this, //put modal dialog on stack: creating this on freestore leads to memleak!
wxEmptyString,
wxEmptyString,
defaultFileName,
wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"),
- wxFD_SAVE /*| wxFD_OVERWRITE_PROMPT*/); //creating this on freestore leads to memleak!
+ wxFD_SAVE /*| wxFD_OVERWRITE_PROMPT*/);
if (filePicker.ShowModal() != wxID_OK)
return false;
targetFilename = filePicker.GetPath();
@@ -2200,15 +2217,15 @@ bool MainDialog::trySaveConfig(const wxString* fileName) //return true if saved
try
{
- xmlAccess::writeConfig(guiCfg, targetFilename); //write config to XML
+ xmlAccess::writeConfig(guiCfg, toZ(targetFilename)); //write config to XML
setLastUsedConfig(targetFilename, guiCfg);
pushStatusInformation(_("Configuration saved!"));
return true;
}
- catch (const xmlAccess::FfsXmlError& error)
+ catch (const xmlAccess::FfsXmlError& e)
{
- wxMessageBox(error.toString().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
return false;
}
}
@@ -2220,7 +2237,7 @@ void MainDialog::OnLoadConfig(wxCommandEvent& event)
wxEmptyString,
beforeLast(activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxString(), utf8CvrtTo<wxString>(FILE_NAME_SEPARATOR)), //set default dir: empty string if "activeConfigFiles" is empty or has no path separator
wxEmptyString,
- wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch"),
+ _("FreeFileSync configuration") + L" (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch",
wxFD_OPEN | wxFD_MULTIPLE);
if (filePicker.ShowModal() == wxID_OK)
@@ -2255,8 +2272,7 @@ void MainDialog::OnLoadFromHistory(wxCommandEvent& event)
std::for_each(selections.begin(), selections.end(),
[&](int pos)
{
- wxClientDataString* cData = dynamic_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(pos));
- if (cData)
+ if (auto cData = dynamic_cast<wxClientDataString*>(m_listBoxHistory->GetClientObject(pos)))
filenames.push_back(cData->name_);
});
@@ -2286,7 +2302,8 @@ bool MainDialog::saveOldConfig() //return false on user abort
bool neverSave = !globalSettings->optDialogs.popupOnConfigChange;
CheckBox cb(_("Never save changes"), neverSave);
- switch (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_NO | ReturnQuestionDlg::BUTTON_CANCEL,
+ switch (showQuestionDlg(this,
+ ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_NO | ReturnQuestionDlg::BUTTON_CANCEL,
_("Save changes to current configuration?"), &cb))
{
case ReturnQuestionDlg::BUTTON_YES:
@@ -2330,7 +2347,7 @@ void MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
try
{
//allow reading batch configurations also
- xmlAccess::convertConfig(filenames, newGuiCfg); //throw (xmlAccess::FfsXmlError)
+ xmlAccess::convertConfig(toZ(filenames), newGuiCfg); //throw FfsXmlError
setLastUsedConfig(filenames, newGuiCfg);
pushStatusInformation(_("Configuration loaded!"));
@@ -2340,11 +2357,11 @@ void MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
{
setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING);
+ wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
}
else
{
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
+ wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
return;
}
}
@@ -2421,9 +2438,7 @@ void MainDialog::onCheckRows(CheckRowsEvent& event)
for (int i = rowFirst; i < rowLast; ++i)
selectedRows.insert(i);
- std::vector<FileSystemObject*> objects;
- gridDataView->getAllFileRef(selectedRows, objects);
-
+ std::vector<FileSystemObject*> objects = gridDataView->getAllFileRef(selectedRows);
setManualFilter(objects, event.setIncluded_);
}
}
@@ -2441,9 +2456,7 @@ void MainDialog::onSetSyncDirection(SyncDirectionEvent& event)
for (int i = rowFirst; i < rowLast; ++i)
selectedRows.insert(i);
- std::vector<FileSystemObject*> objects;
- gridDataView->getAllFileRef(selectedRows, objects);
-
+ std::vector<FileSystemObject*> objects = gridDataView->getAllFileRef(selectedRows);
setSyncDirManually(objects, event.direction_);
}
}
@@ -2469,7 +2482,7 @@ void MainDialog::setLastUsedConfig(const std::vector<wxString>& filenames,
if (activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName())
SetTitle(activeConfigFiles[0]);
else
- SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
+ SetTitle(L"FreeFileSync - " + _("Folder Comparison and Synchronization"));
}
@@ -2556,7 +2569,7 @@ xmlAccess::XmlGuiConfig MainDialog::getConfig() const
const wxString& MainDialog::lastRunConfigName()
{
- static wxString instance = toWx(zen::getConfigDir()) + wxT("LastRun.ffs_gui");
+ static wxString instance = toWx(zen::getConfigDir()) + L"LastRun.ffs_gui";
return instance;
}
@@ -2589,7 +2602,8 @@ void MainDialog::OnHideFilteredButton(wxCommandEvent& event)
void MainDialog::OnConfigureFilter(wxCommandEvent& event)
{
- if (showFilterDialog(true, //is main filter dialog
+ if (showFilterDialog(this,
+ true, //is main filter dialog
currentCfg.mainCfg.globalFilter) == ReturnSmallDlg::BUTTON_OKAY)
{
updateFilterButtons(); //refresh global filter icon
@@ -2718,7 +2732,7 @@ void MainDialog::OnSyncDirNone(wxCommandEvent& event)
inline
wxBitmap buttonPressed(const std::string& name)
{
- wxBitmap background = GlobalResources::getImage(wxT("buttonPressed"));
+ wxBitmap background = GlobalResources::getImage(L"buttonPressed");
return mirrorIfRtl(
layOver(
GlobalResources::getImage(utf8CvrtTo<wxString>(name)), background));
@@ -2740,74 +2754,74 @@ void MainDialog::initViewFilterButtons()
{
//compare result buttons
m_bpButtonLeftOnly->init(buttonPressed("leftOnly"),
- _("Hide files that exist on left side only"),
buttonReleased("leftOnly"),
+ _("Hide files that exist on left side only"),
_("Show files that exist on left side only"));
m_bpButtonRightOnly->init(buttonPressed("rightOnly"),
- _("Hide files that exist on right side only"),
buttonReleased("rightOnly"),
+ _("Hide files that exist on right side only"),
_("Show files that exist on right side only"));
m_bpButtonLeftNewer->init(buttonPressed("leftNewer"),
- _("Hide files that are newer on left"),
buttonReleased("leftNewer"),
+ _("Hide files that are newer on left"),
_("Show files that are newer on left"));
m_bpButtonRightNewer->init(buttonPressed("rightNewer"),
- _("Hide files that are newer on right"),
buttonReleased("rightNewer"),
+ _("Hide files that are newer on right"),
_("Show files that are newer on right"));
m_bpButtonEqual->init(buttonPressed("equal"),
- _("Hide files that are equal"),
buttonReleased("equal"),
+ _("Hide files that are equal"),
_("Show files that are equal"));
m_bpButtonDifferent->init(buttonPressed("different"),
- _("Hide files that are different"),
buttonReleased("different"),
+ _("Hide files that are different"),
_("Show files that are different"));
m_bpButtonConflict->init(buttonPressed("conflict"),
- _("Hide conflicts"),
buttonReleased("conflict"),
+ _("Hide conflicts"),
_("Show conflicts"));
//sync preview buttons
m_bpButtonSyncCreateLeft->init(buttonPressed("createLeft"),
- _("Hide files that will be created on the left side"),
buttonReleased("createLeft"),
+ _("Hide files that will be created on the left side"),
_("Show files that will be created on the left side"));
m_bpButtonSyncCreateRight->init(buttonPressed("createRight"),
- _("Hide files that will be created on the right side"),
buttonReleased("createRight"),
+ _("Hide files that will be created on the right side"),
_("Show files that will be created on the right side"));
m_bpButtonSyncDeleteLeft->init(buttonPressed("deleteLeft"),
- _("Hide files that will be deleted on the left side"),
buttonReleased("deleteLeft"),
+ _("Hide files that will be deleted on the left side"),
_("Show files that will be deleted on the left side"));
m_bpButtonSyncDeleteRight->init(buttonPressed("deleteRight"),
- _("Hide files that will be deleted on the right side"),
buttonReleased("deleteRight"),
+ _("Hide files that will be deleted on the right side"),
_("Show files that will be deleted on the right side"));
m_bpButtonSyncDirOverwLeft->init(buttonPressed("updateLeft"),
- _("Hide files that will be overwritten on left side"),
buttonReleased("updateLeft"),
+ _("Hide files that will be overwritten on left side"),
_("Show files that will be overwritten on left side"));
m_bpButtonSyncDirOverwRight->init(buttonPressed("updateRight"),
- _("Hide files that will be overwritten on right side"),
buttonReleased("updateRight"),
+ _("Hide files that will be overwritten on right side"),
_("Show files that will be overwritten on right side"));
m_bpButtonSyncDirNone->init(buttonPressed("none"),
- _("Hide files that won't be copied"),
buttonReleased("none"),
+ _("Hide files that won't be copied"),
_("Show files that won't be copied"));
//compare result buttons
@@ -2877,11 +2891,15 @@ void MainDialog::OnCompare(wxCommandEvent& event)
const std::vector<zen::FolderPairCfg> cmpConfig = zen::extractCompareCfg(getConfig().mainCfg);
//GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization
- LockHolder dummy2(true); //allow pw prompt
- for (std::vector<FolderPairCfg>::const_iterator i = cmpConfig.begin(); i != cmpConfig.end(); ++i)
+ std::unique_ptr<LockHolder> dummy2;
+ if (globalSettings->createLockFile)
{
- dummy2.addDir(i->leftDirectoryFmt, statusHandler);
- dummy2.addDir(i->rightDirectoryFmt, statusHandler);
+ dummy2.reset(new LockHolder(true)); //allow pw prompt
+ for (auto iter = cmpConfig.begin(); iter != cmpConfig.end(); ++iter)
+ {
+ dummy2->addDir(iter->leftDirectoryFmt, statusHandler);
+ dummy2->addDir(iter->rightDirectoryFmt, statusHandler);
+ }
}
//begin comparison
@@ -2975,7 +2993,8 @@ void MainDialog::OnSyncSettings(wxCommandEvent& event)
globalSettings->gui.onCompletionHistoryMax
};
- if (showSyncConfigDlg(currentCfg.mainCfg.cmpConfig.compareVar,
+ if (showSyncConfigDlg(this,
+ currentCfg.mainCfg.cmpConfig.compareVar,
currentCfg.mainCfg.syncCfg,
&currentCfg.handleError,
&ewfCfg) == ReturnSyncConfig::BUTTON_OKAY) //optional input parameter
@@ -3020,7 +3039,7 @@ void MainDialog::OnCmpSettings(wxCommandEvent& event)
CompConfig cmpConfigNew = currentCfg.mainCfg.cmpConfig;
- if (zen::showCompareCfgDialog(cmpConfigNew) == ReturnSmallDlg::BUTTON_OKAY &&
+ if (zen::showCompareCfgDialog(this, cmpConfigNew) == ReturnSmallDlg::BUTTON_OKAY &&
//check if settings were changed at all
cmpConfigNew != currentCfg.mainCfg.cmpConfig)
{
@@ -3050,10 +3069,10 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
{
bool dontShowAgain = false;
- if (zen::showSyncPreviewDlg(
- getConfig().mainCfg.getSyncVariantName(),
- zen::SyncStatistics(folderCmp),
- dontShowAgain) != ReturnSmallDlg::BUTTON_OKAY)
+ if (zen::showSyncPreviewDlg(this,
+ getConfig().mainCfg.getSyncVariantName(),
+ zen::SyncStatistics(folderCmp),
+ dontShowAgain) != ReturnSmallDlg::BUTTON_OKAY)
return;
globalSettings->optDialogs.showSummaryBeforeSync = !dontShowAgain;
@@ -3078,12 +3097,15 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
globalSettings->gui.onCompletionHistory);
//GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization
- LockHolder dummy2(true); //allow pw prompt
-
- for (auto iter = begin(folderCmp); iter != end(folderCmp); ++iter)
+ std::unique_ptr<LockHolder> dummy2;
+ if (globalSettings->createLockFile)
{
- dummy2.addDir(iter->getBaseDirPf<LEFT_SIDE >(), statusHandler);
- dummy2.addDir(iter->getBaseDirPf<RIGHT_SIDE>(), statusHandler);
+ dummy2.reset(new LockHolder(true)); //allow pw prompt
+ for (auto iter = begin(folderCmp); iter != end(folderCmp); ++iter)
+ {
+ dummy2->addDir(iter->getBaseDirPf<LEFT_SIDE >(), statusHandler);
+ dummy2->addDir(iter->getBaseDirPf<RIGHT_SIDE>(), statusHandler);
+ }
}
//start synchronization and mark all elements processed
@@ -3104,7 +3126,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
syncProc.startSynchronizationProcess(syncProcessCfg, folderCmp);
//play (optional) sound notification after sync has completed (GUI and batch mode)
- const wxString soundFile = toWx(zen::getResourceDir()) + wxT("Sync_Complete.wav");
+ const wxString soundFile = toWx(zen::getResourceDir()) + L"Sync_Complete.wav";
if (fileExists(toZ(soundFile)))
wxSound::Play(soundFile, wxSOUND_ASYNC);
}
@@ -3411,7 +3433,8 @@ void MainDialog::applySyncConfig()
if (warningActive)
{
bool dontWarnAgain = false;
- if (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE, warning, dontWarnAgain) == ReturnWarningDlg::BUTTON_IGNORE)
+ if (showWarningDlg(this,
+ ReturnWarningDlg::BUTTON_IGNORE, warning, dontWarnAgain) == ReturnWarningDlg::BUTTON_IGNORE)
warningActive = !dontWarnAgain;
}
});
@@ -3652,146 +3675,151 @@ void MainDialog::clearAddFolderPairs()
//menu events
void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event)
{
- zen::showGlobalSettingsDlg(*globalSettings);
+ zen::showGlobalSettingsDlg(this, *globalSettings);
}
void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
{
//get a filename
- const wxString defaultFileName = wxT("FileList.csv"); //proposal
+ const wxString defaultFileName = L"FileList.csv"; //proposal
wxFileDialog filePicker(this,
wxEmptyString,
wxEmptyString,
defaultFileName,
- wxString(_("Comma separated list")) + wxT(" (*.csv)|*.csv"),
+ _("Comma separated list") + L" (*.csv)|*.csv",
wxFD_SAVE /*| wxFD_OVERWRITE_PROMPT*/); //creating this on freestore leads to memleak!
- if (filePicker.ShowModal() == wxID_OK)
+ if (filePicker.ShowModal() != wxID_OK)
+ return;
+
+ const wxString newFileName = filePicker.GetPath();
+
+ typedef Zbase<char> UtfString; //perf: wxString doesn't model exponential growth and so is out, std::string doesn't give performance guarantee!
+ UtfString exportString;
+
+ //write legend
+ exportString += utf8CvrtTo<UtfString>(_("Legend")) + '\n';
+ if (syncPreviewEnabled)
{
- const wxString newFileName = filePicker.GetPath();
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_EQUAL)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_EQUAL)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_CREATE_NEW_LEFT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_CREATE_NEW_LEFT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_CREATE_NEW_RIGHT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_CREATE_NEW_RIGHT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_OVERWRITE_LEFT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_OVERWRITE_LEFT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_OVERWRITE_RIGHT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_OVERWRITE_RIGHT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_DELETE_LEFT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_DELETE_LEFT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_DELETE_RIGHT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_DELETE_RIGHT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_DO_NOTHING)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_DO_NOTHING)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getSyncOpDescription(SO_UNRESOLVED_CONFLICT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(SO_UNRESOLVED_CONFLICT)) + '\n';
+ }
+ else
+ {
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_EQUAL)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_EQUAL)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_DIFFERENT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_DIFFERENT)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_LEFT_SIDE_ONLY)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_LEFT_SIDE_ONLY)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_RIGHT_SIDE_ONLY)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_RIGHT_SIDE_ONLY)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_LEFT_NEWER)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_LEFT_NEWER)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_RIGHT_NEWER)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_RIGHT_NEWER)) + '\n';
+ exportString += "\"" + utf8CvrtTo<UtfString>(getCategoryDescription(FILE_CONFLICT)) + "\";" + utf8CvrtTo<UtfString>(getSymbol(FILE_CONFLICT)) + '\n';
+ }
+ exportString += '\n';
- zxString exportString; //perf: wxString doesn't model exponential growth and so is out
+ //base folders
+ exportString += utf8CvrtTo<UtfString>(_("Folder pairs")) + '\n' ;
+ std::for_each(begin(folderCmp), end(folderCmp),
+ [&](BaseDirMapping& baseMap)
+ {
+ exportString += utf8CvrtTo<UtfString>(baseMap.getBaseDirPf<LEFT_SIDE >()) + ';';
+ exportString += utf8CvrtTo<UtfString>(baseMap.getBaseDirPf<RIGHT_SIDE>()) + '\n';
+ });
+ exportString += '\n';
- //write legend
- exportString += copyStringTo<zxString>(_("Legend")) + wxT('\n');
- if (syncPreviewEnabled)
- {
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_EQUAL)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_CREATE_NEW_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_LEFT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_CREATE_NEW_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_RIGHT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_OVERWRITE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_LEFT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_OVERWRITE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_RIGHT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DELETE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_LEFT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DELETE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_RIGHT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DO_NOTHING)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DO_NOTHING)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_UNRESOLVED_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_UNRESOLVED_CONFLICT)) + wxT('\n');
- }
- else
- {
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_EQUAL)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_DIFFERENT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_DIFFERENT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_LEFT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_SIDE_ONLY)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_RIGHT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_SIDE_ONLY)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_LEFT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_NEWER)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_RIGHT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_NEWER)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_CONFLICT)) + wxT('\n');
- }
- exportString += wxT('\n');
+ //write header
+ auto provLeft = m_gridMain->getDataProvider(gridview::COMP_LEFT);
+ auto provMiddle = m_gridMain->getDataProvider(gridview::COMP_MIDDLE);
+ auto provRight = m_gridMain->getDataProvider(gridview::COMP_RIGHT);
- auto addCellValue = [&](const wxString& val)
- {
- if (val.find(wxT(';')) != wxString::npos)
- exportString += wxT('\"') + copyStringTo<zxString>(val) + wxT('\"');
- else
- exportString += copyStringTo<zxString>(val);
- };
+ auto colAttrLeft = m_gridMain->getColumnConfig(gridview::COMP_LEFT);
+ auto colAttrMiddle = m_gridMain->getColumnConfig(gridview::COMP_MIDDLE);
+ auto colAttrRight = m_gridMain->getColumnConfig(gridview::COMP_RIGHT);
- //write header
- auto provLeft = m_gridMain->getDataProvider(gridview::COMP_LEFT);
- auto provMiddle = m_gridMain->getDataProvider(gridview::COMP_MIDDLE);
- auto provRight = m_gridMain->getDataProvider(gridview::COMP_RIGHT);
+ vector_remove_if(colAttrLeft , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
+ vector_remove_if(colAttrMiddle, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
+ vector_remove_if(colAttrRight , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
- auto colAttrLeft = m_gridMain->getColumnConfig(gridview::COMP_LEFT);
- auto colAttrMiddle = m_gridMain->getColumnConfig(gridview::COMP_MIDDLE);
- auto colAttrRight = m_gridMain->getColumnConfig(gridview::COMP_RIGHT);
+ auto addCellValue = [&](const wxString& val)
+ {
+ if (val.find(L';') != wxString::npos)
+ exportString += '\"' + utf8CvrtTo<UtfString>(val) + '\"';
+ else
+ exportString += utf8CvrtTo<UtfString>(val);
+ };
- vector_remove_if(colAttrLeft , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
- vector_remove_if(colAttrMiddle, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
- vector_remove_if(colAttrRight , [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
+ if (provLeft && provMiddle && provRight)
+ {
+ std::for_each(colAttrLeft.begin(), colAttrLeft.end(),
+ [&](const Grid::ColumnAttribute& ca)
+ {
+ addCellValue(provLeft->getColumnLabel(ca.type_));
+ exportString += ';';
+ });
+ std::for_each(colAttrMiddle.begin(), colAttrMiddle.end(),
+ [&](const Grid::ColumnAttribute& ca)
+ {
+ addCellValue(provMiddle->getColumnLabel(ca.type_));
+ exportString += ';';
+ });
+ if (!colAttrRight.empty())
+ {
+ std::for_each(colAttrRight.begin(), colAttrRight.end() - 1,
+ [&](const Grid::ColumnAttribute& ca)
+ {
+ addCellValue(provRight->getColumnLabel(ca.type_));
+ exportString += ';';
+ });
+ addCellValue(provRight->getColumnLabel(colAttrRight.back().type_));
+ }
+ exportString += '\n';
- if (provLeft && provMiddle && provRight)
+ //main grid
+ const size_t rowCount = m_gridMain->getRowCount();
+ for (size_t row = 0; row < rowCount; ++row)
{
std::for_each(colAttrLeft.begin(), colAttrLeft.end(),
[&](const Grid::ColumnAttribute& ca)
{
- addCellValue(provLeft->getColumnLabel(ca.type_));
- exportString += L';';
+ addCellValue(provLeft->getValue(row, ca.type_));
+ exportString += ';';
});
std::for_each(colAttrMiddle.begin(), colAttrMiddle.end(),
[&](const Grid::ColumnAttribute& ca)
{
- addCellValue(provMiddle->getColumnLabel(ca.type_));
- exportString += L';';
+ addCellValue(provMiddle->getValue(row, ca.type_));
+ exportString += ';';
});
if (!colAttrRight.empty())
{
std::for_each(colAttrRight.begin(), colAttrRight.end() - 1,
[&](const Grid::ColumnAttribute& ca)
{
- addCellValue(provRight->getColumnLabel(ca.type_));
- exportString += L';';
- });
- addCellValue(provRight->getColumnLabel(colAttrRight.back().type_));
- }
- exportString += L'\n';
-
- //main grid
- const size_t rowCount = m_gridMain->getRowCount();
- for (size_t row = 0; row < rowCount; ++row)
- {
- std::for_each(colAttrLeft.begin(), colAttrLeft.end(),
- [&](const Grid::ColumnAttribute& ca)
- {
- addCellValue(provLeft->getValue(row, ca.type_));
- exportString += L';';
+ addCellValue(provRight->getValue(row, ca.type_));
+ exportString += ';';
});
- std::for_each(colAttrMiddle.begin(), colAttrMiddle.end(),
- [&](const Grid::ColumnAttribute& ca)
- {
- addCellValue(provMiddle->getValue(row, ca.type_));
- exportString += L';';
- });
- if (!colAttrRight.empty())
- {
- std::for_each(colAttrRight.begin(), colAttrRight.end() - 1,
- [&](const Grid::ColumnAttribute& ca)
- {
- addCellValue(provRight->getValue(row, ca.type_));
- exportString += L';';
- });
- addCellValue(provRight->getValue(row, colAttrRight.back().type_));
- }
- exportString += L'\n';
+ addCellValue(provRight->getValue(row, colAttrRight.back().type_));
}
+ exportString += '\n';
+ }
- //write export file
- wxFFile output(newFileName.c_str(), wxT("w")); //don't write in binary mode
- if (output.IsOpened())
- {
- //generate UTF8 representation
- size_t bufferSize = 0;
- const wxCharBuffer utf8buffer = wxConvUTF8.cWC2MB(exportString.c_str(), exportString.size(), &bufferSize);
-
- output.Write(BYTE_ORDER_MARK_UTF8, sizeof(BYTE_ORDER_MARK_UTF8) - 1);
- output.Write(utf8buffer, bufferSize);
- pushStatusInformation(_("File list exported!"));
- }
- else
- {
- wxMessageBox(wxString(_("Error writing file:")) + wxT(" \"") + newFileName + wxT("\""), _("Error"), wxOK | wxICON_ERROR);
- }
+ //write export file
+ wxFFile output(newFileName.c_str(), L"w"); //don't write in binary mode
+ if (output.IsOpened())
+ {
+ output.Write(BYTE_ORDER_MARK_UTF8, sizeof(BYTE_ORDER_MARK_UTF8) - 1);
+ output.Write(exportString.c_str(), exportString.size());
+ pushStatusInformation(_("File list exported!"));
}
+ else
+ wxMessageBox(replaceCpy(_("Cannot write file %x."), L"%x", fmtFileName(toZ(newFileName))), _("Error"), wxOK | wxICON_ERROR, this);
}
}
@@ -3803,9 +3831,10 @@ void MainDialog::OnMenuBatchJob(wxCommandEvent& event)
const wxString referenceFile = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxString();
- const xmlAccess::XmlBatchConfig batchCfg = convertGuiToBatch(currCfg, referenceFile);
+ const xmlAccess::XmlBatchConfig batchCfg = convertGuiToBatch(currCfg, toZ(referenceFile));
- showSyncBatchDlg(referenceFile, batchCfg,
+ showSyncBatchDlg(this,
+ referenceFile, batchCfg,
folderHistoryLeft,
folderHistoryRight,
globalSettings->gui.onCompletionHistory,
@@ -3815,7 +3844,7 @@ void MainDialog::OnMenuBatchJob(wxCommandEvent& event)
void MainDialog::OnMenuCheckVersion(wxCommandEvent& event)
{
- zen::checkForUpdateNow();
+ zen::checkForUpdateNow(this);
}
@@ -3824,7 +3853,7 @@ void MainDialog::OnRegularUpdateCheck(wxIdleEvent& event)
//execute just once per startup!
Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), nullptr, this);
- zen::checkForUpdatePeriodically(globalSettings->gui.lastUpdateCheck);
+ zen::checkForUpdatePeriodically(this, globalSettings->gui.lastUpdateCheck);
}
@@ -3847,7 +3876,7 @@ void MainDialog::OnLayoutWindowAsync(wxIdleEvent& event)
void MainDialog::OnMenuAbout(wxCommandEvent& event)
{
- zen::showAboutDialog();
+ zen::showAboutDialog(this);
}
diff --git a/ui/main_dlg.h b/ui/main_dlg.h
index 228cef4a..6c0c6974 100644
--- a/ui/main_dlg.h
+++ b/ui/main_dlg.h
@@ -184,6 +184,7 @@ private:
void updateGuiAfterFilterChange(int delay);
void excludeExtension(const Zstring& extension);
+ void excludeShortname(const zen::FileSystemObject& fsObj);
void excludeItems(const std::vector<zen::FileSystemObject*>& selection);
void updateStatistics();
diff --git a/ui/msg_popup.cpp b/ui/msg_popup.cpp
index 1ed892f8..b6067242 100644
--- a/ui/msg_popup.cpp
+++ b/ui/msg_popup.cpp
@@ -16,7 +16,7 @@ using namespace zen;
class ErrorDlg : public ErrorDlgGenerated
{
public:
- ErrorDlg(wxWindow* parentWindow,
+ ErrorDlg(wxWindow* parent,
int activeButtons,
const wxString& messageText,
bool* ignoreNextErrors);
@@ -31,15 +31,15 @@ private:
};
-ErrorDlg::ErrorDlg(wxWindow* parentWindow, const int activeButtons, const wxString& messageText, bool* ignoreNextErrors) :
- ErrorDlgGenerated(parentWindow),
+ErrorDlg::ErrorDlg(wxWindow* parent, const int activeButtons, const wxString& messageText, bool* ignoreNextErrors) :
+ ErrorDlgGenerated(parent),
ignoreErrors(ignoreNextErrors)
{
#ifdef FFS_WIN
new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this"
#endif
- m_bitmap10->SetBitmap(GlobalResources::getImage(wxT("error")));
+ m_bitmap10->SetBitmap(GlobalResources::getImage(L"error"));
m_textCtrl8->SetValue(messageText);
if (ignoreNextErrors)
@@ -96,9 +96,9 @@ void ErrorDlg::OnAbort(wxCommandEvent& event)
}
-ReturnErrorDlg::ButtonPressed zen::showErrorDlg(int activeButtons, const wxString& messageText, bool* ignoreNextErrors)
+ReturnErrorDlg::ButtonPressed zen::showErrorDlg(wxWindow* parent, int activeButtons, const wxString& messageText, bool* ignoreNextErrors)
{
- ErrorDlg errorDlg(nullptr, activeButtons, messageText, ignoreNextErrors);
+ ErrorDlg errorDlg(parent, activeButtons, messageText, ignoreNextErrors);
errorDlg.Raise();
return static_cast<ReturnErrorDlg::ButtonPressed>(errorDlg.ShowModal());
}
@@ -108,7 +108,7 @@ ReturnErrorDlg::ButtonPressed zen::showErrorDlg(int activeButtons, const wxStrin
class WarningDlg : public WarningDlgGenerated
{
public:
- WarningDlg(wxWindow* parentWindow, int activeButtons, const wxString& messageText, bool& dontShowAgain);
+ WarningDlg(wxWindow* parent, int activeButtons, const wxString& messageText, bool& dontShowAgain);
private:
void OnClose(wxCloseEvent& event);
@@ -119,15 +119,15 @@ private:
};
-WarningDlg::WarningDlg(wxWindow* parentWindow, int activeButtons, const wxString& messageText, bool& dontShowDlgAgain) :
- WarningDlgGenerated(parentWindow),
+WarningDlg::WarningDlg(wxWindow* parent, int activeButtons, const wxString& messageText, bool& dontShowDlgAgain) :
+ WarningDlgGenerated(parent),
dontShowAgain(dontShowDlgAgain)
{
#ifdef FFS_WIN
new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this"
#endif
- m_bitmap10->SetBitmap(GlobalResources::getImage(wxT("warning")));
+ m_bitmap10->SetBitmap(GlobalResources::getImage(L"warning"));
m_textCtrl8->SetValue(messageText);
m_checkBoxDontShowAgain->SetValue(dontShowAgain);
@@ -178,9 +178,9 @@ void WarningDlg::OnAbort(wxCommandEvent& event)
}
-ReturnWarningDlg::ButtonPressed zen::showWarningDlg(int activeButtons, const wxString& messageText, bool& dontShowAgain)
+ReturnWarningDlg::ButtonPressed zen::showWarningDlg(wxWindow* parent, int activeButtons, const wxString& messageText, bool& dontShowAgain)
{
- WarningDlg warningDlg(nullptr, activeButtons, messageText, dontShowAgain);
+ WarningDlg warningDlg(parent, activeButtons, messageText, dontShowAgain);
warningDlg.Raise();
return static_cast<ReturnWarningDlg::ButtonPressed>(warningDlg.ShowModal());
}
@@ -190,7 +190,7 @@ ReturnWarningDlg::ButtonPressed zen::showWarningDlg(int activeButtons, const wxS
class QuestionDlg : public QuestionDlgGenerated
{
public:
- QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString& messageText, CheckBox* checkbox);
+ QuestionDlg(wxWindow* parent, int activeButtons, const wxString& messageText, CheckBox* checkbox);
private:
void OnClose (wxCloseEvent& event) { EndModal(ReturnQuestionDlg::BUTTON_CANCEL); }
@@ -202,8 +202,8 @@ private:
};
-QuestionDlg::QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString& messageText, CheckBox* checkbox) :
- QuestionDlgGenerated(parentWindow),
+QuestionDlg::QuestionDlg(wxWindow* parent, int activeButtons, const wxString& messageText, CheckBox* checkbox) :
+ QuestionDlgGenerated(parent),
checkbox_(checkbox)
{
#ifdef FFS_WIN
@@ -253,9 +253,9 @@ void QuestionDlg::OnNo(wxCommandEvent& event)
EndModal(ReturnQuestionDlg::BUTTON_NO);
}
-ReturnQuestionDlg::ButtonPressed zen::showQuestionDlg(int activeButtons, const wxString& messageText, CheckBox* checkbox)
+ReturnQuestionDlg::ButtonPressed zen::showQuestionDlg(wxWindow* parent, int activeButtons, const wxString& messageText, CheckBox* checkbox)
{
- QuestionDlg qtnDlg(nullptr, activeButtons, messageText, checkbox);
+ QuestionDlg qtnDlg(parent, activeButtons, messageText, checkbox);
qtnDlg.Raise();
return static_cast<ReturnQuestionDlg::ButtonPressed>(qtnDlg.ShowModal());
}
diff --git a/ui/msg_popup.h b/ui/msg_popup.h
index ccdf09e4..19a3c84f 100644
--- a/ui/msg_popup.h
+++ b/ui/msg_popup.h
@@ -7,10 +7,14 @@
#ifndef MESSAGEPOPUP_H_INCLUDED
#define MESSAGEPOPUP_H_INCLUDED
+#include <wx/window.h>
#include <wx/string.h>
+
namespace zen
{
+//parent window, optional: support correct dialog placement above parent on multiple monitor systems
+
struct ReturnErrorDlg
{
enum ButtonPressed
@@ -20,7 +24,7 @@ struct ReturnErrorDlg
BUTTON_ABORT = 4
};
};
-ReturnErrorDlg::ButtonPressed showErrorDlg(int activeButtons, const wxString& messageText, bool* ignoreNextErrors); //ignoreNextErrors may be nullptr
+ReturnErrorDlg::ButtonPressed showErrorDlg(wxWindow* parent, int activeButtons, const wxString& messageText, bool* ignoreNextErrors); //ignoreNextErrors may be nullptr
struct ReturnWarningDlg
@@ -32,7 +36,7 @@ struct ReturnWarningDlg
BUTTON_ABORT = 4
};
};
-ReturnWarningDlg::ButtonPressed showWarningDlg(int activeButtons, const wxString& messageText, bool& dontShowAgain);
+ReturnWarningDlg::ButtonPressed showWarningDlg(wxWindow* parent, int activeButtons, const wxString& messageText, bool& dontShowAgain);
struct ReturnQuestionDlg
@@ -53,8 +57,7 @@ struct CheckBox
bool& value_; //in/out
};
-ReturnQuestionDlg::ButtonPressed showQuestionDlg(int activeButtons, const wxString& messageText, CheckBox* checkbox = nullptr);
+ReturnQuestionDlg::ButtonPressed showQuestionDlg(wxWindow* parent, int activeButtons, const wxString& messageText, CheckBox* checkbox = nullptr);
}
-
#endif // MESSAGEPOPUP_H_INCLUDED
diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp
index 1e4be39a..fba2c801 100644
--- a/ui/progress_indicator.cpp
+++ b/ui/progress_indicator.cpp
@@ -6,20 +6,19 @@
#include "progress_indicator.h"
#include <memory>
-#include <zen/basic_math.h>
#include <wx/imaglist.h>
#include <wx/stopwatch.h>
#include <wx/wupdlock.h>
+#include <zen/basic_math.h>
#include <wx+/mouse_move_dlg.h>
#include <wx+/toggle_button.h>
-#include <wx+/string_conv.h>
#include <wx+/format_unit.h>
#include <wx+/image_tools.h>
#include <wx+/graph.h>
#include <wx+/no_flicker.h>
#include "gui_generated.h"
#include "../lib/resources.h"
-#include "../lib/statistics.h"
+#include "../lib/perf_check.h"
#include "tray_icon.h"
#include "taskbar.h"
#include "exec_finished_box.h"
@@ -32,8 +31,8 @@ namespace
const int GAUGE_FULL_RANGE = 50000;
//window size used for statistics in milliseconds
-const int windowSizeRemainingTime = 60000; //some usecases have dropouts of 40 seconds -> 60 sec. window size handles them well
-const int windowSizeBytesPerSec = 5000; //
+const int WINDOW_REMAINING_TIME = 60000; //some usecases have dropouts of 40 seconds -> 60 sec. window size handles them well
+const int WINDOW_BYTES_PER_SEC = 5000; //
}
@@ -42,49 +41,24 @@ class CompareStatus::CompareStatusImpl : public CompareStatusGenerated
public:
CompareStatusImpl(wxTopLevelWindow& parentWindow);
- void init(); //constructor/destructor semantics, but underlying Window is reused
+ void init(const Statistics& syncStat); //constructor/destructor semantics, but underlying Window is reused
void finalize(); //
- void switchToCompareBytewise(int totalObjectsToProcess, Int64 totalDataToProcess);
- void incScannedObjects_NoUpdate(int number);
- void incProcessedCmpData_NoUpdate(int objectsProcessed, Int64 dataProcessed);
- void incTotalCmpData_NoUpdate (int objectsProcessed, Int64 dataProcessed);
-
- void setStatusText_NoUpdate(const wxString& text);
+ void switchToCompareBytewise();
void updateStatusPanelNow();
private:
wxTopLevelWindow& parentWindow_;
wxString titleTextBackup;
- //status variables
- size_t scannedObjects;
- wxString currentStatusText;
-
wxStopWatch timeElapsed;
- //gauge variables
- int totalObjects; //file/dir/symlink/operation count
- Int64 totalData; //unit: [bytes]
- int currentObjects;
- Int64 currentData;
-
- void showProgressExternally(const wxString& progressText, double fraction = 0); //between [0, 1]
-
- enum CurrentStatus
- {
- SCANNING,
- COMPARING_CONTENT,
- };
-
- CurrentStatus status;
+ const Statistics* syncStat_; //only bound while sync is running
std::unique_ptr<Taskbar> taskbar_;
+ std::unique_ptr<PerfCheck> perf; //estimate remaining time
- //remaining time
- std::unique_ptr<Statistics> statistics;
-
- long lastStatCallSpeed; //used for calculating intervals between statistics update
+ long lastStatCallSpeed; //used for calculating intervals between showing and collecting perf samples
long lastStatCallRemTime; //
};
@@ -92,21 +66,17 @@ private:
CompareStatus::CompareStatusImpl::CompareStatusImpl(wxTopLevelWindow& parentWindow) :
CompareStatusGenerated(&parentWindow),
parentWindow_(parentWindow),
- scannedObjects(0),
- totalObjects(0),
- totalData(0),
- currentObjects(0),
- currentData(0),
- status(SCANNING),
- lastStatCallSpeed(-1000000), //some big number
+ syncStat_(nullptr),
+ lastStatCallSpeed (-1000000), //some big number
lastStatCallRemTime(-1000000)
{
- init();
+ //init(); -> needed?
}
-void CompareStatus::CompareStatusImpl::init()
+void CompareStatus::CompareStatusImpl::init(const Statistics& syncStat)
{
+ syncStat_ = &syncStat;
titleTextBackup = parentWindow_.GetTitle();
try //try to get access to Windows 7/Ubuntu taskbar
@@ -115,65 +85,47 @@ void CompareStatus::CompareStatusImpl::init()
}
catch (const TaskbarNotAvailable&) {}
- status = SCANNING;
-
//initialize gauge
m_gauge2->SetRange(GAUGE_FULL_RANGE);
m_gauge2->SetValue(0);
+ perf.reset();
+ timeElapsed.Start(); //measure total time
+
//initially hide status that's relevant for comparing bytewise only
bSizerFilesFound ->Show(true);
bSizerFilesRemaining->Show(false);
sSizerSpeed ->Show(false);
sSizerTimeRemaining ->Show(false);
- m_gauge2->Hide();
- bSizer42->Layout();
-
- scannedObjects = 0;
- currentStatusText.clear();
-
- totalObjects = 0;
- totalData = 0;
- currentObjects = 0;
- currentData = 0;
-
- statistics.reset();
-
- timeElapsed.Start(); //measure total time
-
updateStatusPanelNow();
+ m_gauge2->Hide();
+ bSizer42->Layout();
Layout();
}
void CompareStatus::CompareStatusImpl::finalize()
{
- taskbar_.reset();
+ syncStat_ = nullptr;
parentWindow_.SetTitle(titleTextBackup);
+ taskbar_.reset();
}
-void CompareStatus::CompareStatusImpl::switchToCompareBytewise(int totalObjectsToProcess, Int64 totalDataToProcess)
+void CompareStatus::CompareStatusImpl::switchToCompareBytewise()
{
- status = COMPARING_CONTENT;
-
- currentData = 0;
- currentObjects = 0;
- totalData = totalDataToProcess;
- totalObjects = totalObjectsToProcess;
-
- //set new statistics handler: 10 seconds "window" for remaining time, 5 seconds for speed
- statistics.reset(new Statistics(totalObjectsToProcess, to<double>(totalDataToProcess), windowSizeRemainingTime, windowSizeBytesPerSec));
+ //start to measure perf
+ perf.reset(new PerfCheck(WINDOW_REMAINING_TIME, WINDOW_BYTES_PER_SEC));
lastStatCallSpeed = -1000000; //some big number
lastStatCallRemTime = -1000000;
//show status for comparing bytewise
- bSizerFilesFound->Show(false);
+ bSizerFilesFound ->Show(false);
bSizerFilesRemaining->Show(true);
- sSizerSpeed->Show(true);
- sSizerTimeRemaining->Show(true);
+ sSizerSpeed ->Show(true);
+ sSizerTimeRemaining ->Show(true);
m_gauge2->Show();
bSizer42->Layout();
@@ -181,154 +133,119 @@ void CompareStatus::CompareStatusImpl::switchToCompareBytewise(int totalObjectsT
}
-void CompareStatus::CompareStatusImpl::incScannedObjects_NoUpdate(int number)
-{
- scannedObjects += number;
-}
-
-
-void CompareStatus::CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsDelta, Int64 dataDelta)
-{
- currentData += dataDelta;
- currentObjects += objectsDelta;
-}
-
-
-void CompareStatus::CompareStatusImpl::incTotalCmpData_NoUpdate(int objectsDelta, Int64 dataDelta)
-{
- totalData += dataDelta;
- totalObjects += objectsDelta;
-
- if (statistics)
- statistics->setNewTotal(totalObjects, to<double>(totalData));
-}
-
-
-void CompareStatus::CompareStatusImpl::setStatusText_NoUpdate(const wxString& text)
+void CompareStatus::CompareStatusImpl::updateStatusPanelNow()
{
- currentStatusText = text;
-}
+ if (!syncStat_) //no comparison running!!
+ return;
+ //wxWindowUpdateLocker dummy(this) -> not needed
-void CompareStatus::CompareStatusImpl::showProgressExternally(const wxString& progressText, double fraction)
-{
- if (parentWindow_.GetTitle() != progressText)
- parentWindow_.SetTitle(progressText);
+ const wxString& scannedObjects = toStringSep(syncStat_->getObjectsCurrent(ProcessCallback::PHASE_SCANNING));
- //show progress on Windows 7 taskbar
+ auto setTitle = [&](const wxString& title)
+ {
+ if (parentWindow_.GetTitle() != title)
+ parentWindow_.SetTitle(title);
+ };
- if (taskbar_.get())
- switch (status)
- {
- case SCANNING:
- taskbar_->setStatus(Taskbar::STATUS_INDETERMINATE);
- break;
- case COMPARING_CONTENT:
- taskbar_->setProgress(fraction);
- taskbar_->setStatus(Taskbar::STATUS_NORMAL);
- break;
- }
-}
+ bool layoutChanged = false; //avoid screen flicker by calling layout() only if necessary
+ //status texts
+ setText(*m_textCtrlStatus, replaceCpy(syncStat_->currentStatusText(), L'\n', L' ')); //no layout update for status texts!
-void CompareStatus::CompareStatusImpl::updateStatusPanelNow()
-{
- //static RetrieveStatistics statistic;
- //statistic.writeEntry(currentData.ToDouble(), currentObjects);
+ //write status information to taskbar, parent title ect.
+ switch (syncStat_->currentPhase())
{
- //wxWindowUpdateLocker dummy(this) -> not needed
-
- //add both data + obj-count, to handle "deletion-only" cases
- const double fraction = totalData + totalObjects == 0 ? 0 : std::max(0.0, to<double>(currentData + currentObjects) / to<double>(totalData + totalObjects));
+ case ProcessCallback::PHASE_NONE:
+ case ProcessCallback::PHASE_SCANNING:
+ //dialog caption, taskbar
+ setTitle(scannedObjects + L" - " + _("Scanning..."));
+ if (taskbar_.get()) //support Windows 7 taskbar
+ taskbar_->setStatus(Taskbar::STATUS_INDETERMINATE);
+ break;
- //write status information to taskbar, parent title ect.
- switch (status)
+ case ProcessCallback::PHASE_COMPARING_CONTENT:
{
- case SCANNING:
- showProgressExternally(toStringSep(scannedObjects) + wxT(" - ") + _("Scanning..."));
- break;
- case COMPARING_CONTENT:
- showProgressExternally(fractionToShortString(fraction) + wxT(" - ") + _("Comparing content..."), fraction);
- break;
- }
+ auto objectsCurrent = syncStat_->getObjectsCurrent(ProcessCallback::PHASE_COMPARING_CONTENT);
+ auto objectsTotal = syncStat_->getObjectsTotal (ProcessCallback::PHASE_COMPARING_CONTENT);
+ auto dataCurrent = syncStat_->getDataCurrent (ProcessCallback::PHASE_COMPARING_CONTENT);
+ auto dataTotal = syncStat_->getDataTotal (ProcessCallback::PHASE_COMPARING_CONTENT);
- bool layoutChanged = false; //avoid screen flicker by calling layout() only if necessary
+ //add both data + obj-count, to handle "deletion-only" cases
+ const double fraction = dataTotal + objectsTotal == 0 ? 0 : std::max(0.0, to<double>(dataCurrent + objectsCurrent) / to<double>(dataTotal + objectsTotal));
- //remove linebreaks from currentStatusText
- wxString statusTextFmt = currentStatusText;
- replace(statusTextFmt, L'\n', L' ');
+ //dialog caption, taskbar
+ setTitle(fractionToShortString(fraction) + wxT(" - ") + _("Comparing content..."));
+ if (taskbar_.get())
+ {
+ taskbar_->setProgress(fraction);
+ taskbar_->setStatus(Taskbar::STATUS_NORMAL);
+ }
- //status texts
- if (m_textCtrlStatus->GetValue() != statusTextFmt) //no layout update for status texts!
- m_textCtrlStatus->ChangeValue(statusTextFmt);
+ //progress indicator, shown for binary comparison only
+ m_gauge2->SetValue(numeric::round(fraction * GAUGE_FULL_RANGE));
- //nr of scanned objects
- setText(*m_staticTextScanned, toStringSep(scannedObjects), &layoutChanged);
+ //remaining objects and bytes for file comparison
+ setText(*m_staticTextFilesRemaining, toStringSep(objectsTotal - objectsCurrent), &layoutChanged);
+ setText(*m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged);
- //progress indicator for "compare file content"
- m_gauge2->SetValue(numeric::round(fraction * GAUGE_FULL_RANGE));
+ //remaining time and speed: only visible during binary comparison
+ if (perf)
+ if (timeElapsed.Time() - lastStatCallSpeed >= 500) //-> Win 7 copy uses 1 sec update interval
+ {
+ lastStatCallSpeed = timeElapsed.Time();
- //remaining files left for file comparison
- const wxString filesToCompareTmp = toStringSep(totalObjects - currentObjects);
- setText(*m_staticTextFilesRemaining, filesToCompareTmp, &layoutChanged);
+ perf->addSample(objectsCurrent, to<double>(dataCurrent), timeElapsed.Time());
- //remaining bytes left for file comparison
- const wxString remainingBytesTmp = zen::filesizeToShortString(totalData - currentData);
- setText(*m_staticTextDataRemaining, remainingBytesTmp, &layoutChanged);
+ //current speed
+ setText(*m_staticTextSpeed, perf->getBytesPerSecond(), &layoutChanged);
- if (statistics.get())
- {
- if (timeElapsed.Time() - lastStatCallSpeed >= 500) //call method every 500 ms
- {
- lastStatCallSpeed = timeElapsed.Time();
+ if (timeElapsed.Time() - lastStatCallRemTime >= 2000) //update GUI every 2 sec
+ {
+ lastStatCallRemTime = timeElapsed.Time();
- statistics->addMeasurement(currentObjects, to<double>(currentData));
+ //remaining time
+ setText(*m_staticTextRemTime, perf->getRemainingTime(to<double>(dataTotal - dataCurrent)), &layoutChanged);
+ }
+ }
+ }
+ break;
- //current speed
- setText(*m_staticTextSpeed, statistics->getBytesPerSecond(), &layoutChanged);
+ case ProcessCallback::PHASE_SYNCHRONIZING:
+ assert(false);
+ break;
+ }
- if (timeElapsed.Time() - lastStatCallRemTime >= 2000) //call method every two seconds only
- {
- lastStatCallRemTime = timeElapsed.Time();
+ //nr of scanned objects
+ setText(*m_staticTextScanned, scannedObjects, &layoutChanged);
- //remaining time
- setText(*m_staticTextRemTime, statistics->getRemainingTime(), &layoutChanged);
- }
- }
- }
+ //time elapsed
+ const long timeElapSec = timeElapsed.Time() / 1000;
+ setText(*m_staticTextTimeElapsed,
+ timeElapSec < 3600 ?
+ wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") :
+ wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged);
- //time elapsed
- const long timeElapSec = timeElapsed.Time() / 1000;
- setText(*m_staticTextTimeElapsed,
- timeElapSec < 3600 ?
- wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") :
- wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged);
+ //do the ui update
+ if (layoutChanged)
+ bSizer42->Layout();
- //do the ui update
- if (layoutChanged)
- bSizer42->Layout();
- }
updateUiNow();
}
//########################################################################################
//redirect to implementation
CompareStatus::CompareStatus(wxTopLevelWindow& parentWindow) :
- pimpl(new CompareStatusImpl(parentWindow)) {}
-
-CompareStatus::~CompareStatus()
-{
- //DON'T delete pimpl! it relies on wxWidgets destruction (parent window destroys child windows!)
-}
+ pimpl(new CompareStatusImpl(parentWindow)) {} //owned by parentWindow
wxWindow* CompareStatus::getAsWindow()
{
return pimpl;
}
-void CompareStatus::init()
+void CompareStatus::init(const Statistics& syncStat)
{
- pimpl->init();
+ pimpl->init(syncStat);
}
void CompareStatus::finalize()
@@ -336,29 +253,9 @@ void CompareStatus::finalize()
pimpl->finalize();
}
-void CompareStatus::switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess)
-{
- pimpl->switchToCompareBytewise(totalObjectsToProcess, totalDataToProcess);
-}
-
-void CompareStatus::incScannedObjects_NoUpdate(int number)
-{
- pimpl->incScannedObjects_NoUpdate(number);
-}
-
-void CompareStatus::incProcessedCmpData_NoUpdate(int objectsDelta, Int64 dataDelta)
+void CompareStatus::switchToCompareBytewise()
{
- pimpl->incProcessedCmpData_NoUpdate(objectsDelta, dataDelta);
-}
-
-void CompareStatus::incTotalCmpData_NoUpdate(int objectsDelta, Int64 dataDelta)
-{
- pimpl->incTotalCmpData_NoUpdate(objectsDelta, dataDelta);
-}
-
-void CompareStatus::setStatusText_NoUpdate(const wxString& text)
-{
- pimpl->setStatusText_NoUpdate(text);
+ pimpl->switchToCompareBytewise();
}
void CompareStatus::updateStatusPanelNow()
@@ -399,14 +296,9 @@ public:
const int warningCount = log_.getItemCount(TYPE_WARNING);
const int infoCount = log_.getItemCount(TYPE_INFO);
- m_bpButtonErrors->init(buttonPressed ("error"), wxString(_("Error")) + wxString::Format(wxT(" (%d)"), errorCount),
- buttonReleased("error"), wxString(_("Error")) + wxString::Format(wxT(" (%d)"), errorCount));
-
- m_bpButtonWarnings->init(buttonPressed ("warning"), wxString(_("Warning")) + wxString::Format(wxT(" (%d)"), warningCount),
- buttonReleased("warning"), wxString(_("Warning")) + wxString::Format(wxT(" (%d)"), warningCount));
-
- m_bpButtonInfo->init(buttonPressed ("info"), wxString(_("Info")) + wxString::Format(wxT(" (%d)"), infoCount),
- buttonReleased("info"), wxString(_("Info")) + wxString::Format(wxT(" (%d)"), infoCount));
+ m_bpButtonErrors ->init(buttonPressed ("error" ), buttonReleased("error" ), _("Error" ) + wxString::Format(L" (%d)", errorCount ));
+ m_bpButtonWarnings->init(buttonPressed ("warning"), buttonReleased("warning"), _("Warning") + wxString::Format(L" (%d)", warningCount));
+ m_bpButtonInfo ->init(buttonPressed ("info" ), buttonReleased("info" ), _("Info" ) + wxString::Format(L" (%d)", infoCount ));
m_bpButtonErrors ->setActive(true);
m_bpButtonWarnings->setActive(true);
@@ -421,6 +313,7 @@ public:
m_textCtrlInfo->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(LogControl::onKeyEvent), nullptr, this);
}
+private:
virtual void OnErrors(wxCommandEvent& event)
{
m_bpButtonErrors->toggle();
@@ -439,7 +332,6 @@ public:
updateLogText();
}
-private:
void onKeyEvent(wxKeyEvent& event)
{
const int keyCode = event.GetKeyCode();
@@ -478,7 +370,7 @@ private:
logText += L'\n';
}
- if (logText.empty()) //if no messages match selected view filter, show final status message at least
+ if (logText.empty()) //if no messages match selected view filter, at least show final status message
if (!entries.empty())
logText = copyStringTo<zxString>(formatMessage(entries.back()));
@@ -490,7 +382,6 @@ private:
const ErrorLog log_;
};
-
//########################################################################################
namespace
@@ -498,20 +389,19 @@ namespace
class GraphDataBytes : public GraphData
{
public:
- void addCurrentValue(double dataCurrent)
+ void addRecord(double dataCurrent, long timeMs)
{
- data.insert(data.end(), std::make_pair(timer.Time(), dataCurrent));
+ data.insert(data.end(), std::make_pair(timeMs, dataCurrent));
//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) //guard against too large a buffer
+ if (data.size() > MAX_BUFFER_SIZE) //limit buffer size
data.erase(data.begin());
}
- void pauseTimer () { timer.Pause(); }
- void resumeTimer() { timer.Resume(); }
+ void clear() { data.clear(); }
- virtual double getXBegin() const { return 0; } //{ return data.empty() ? 0 : data.begin()->first / 1000.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; }
private:
@@ -526,7 +416,6 @@ private:
}
//example: two-element range is accessible within [0, 2)
- wxStopWatch timer;
std::map<long, double> data;
};
@@ -560,11 +449,7 @@ struct LabelFormatterBytes : public LabelFormatter
bytesProposed *= 1.5; //enlarge block default size
- //if (bytesProposed <= 1024 * 1024) //set 1 MB min size: reduce initial rapid changes in y-label
- // return 1024 * 1024;
-
//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))
@@ -644,132 +529,125 @@ class SyncStatus::SyncStatusImpl : public SyncStatusDlgGenerated
{
public:
SyncStatusImpl(AbortCallback& abortCb,
+ const Statistics& syncStat,
MainDialog* parentWindow,
- SyncStatusID startStatus,
const wxString& jobName,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory);
~SyncStatusImpl();
- void initNewProcess(SyncStatusID id, int totalObjectsToProcess, Int64 totalDataToProcess);
-
- void incScannedObjects_NoUpdate(int number);
- void incProcessedData_NoUpdate(int objectsDelta, Int64 dataDelta);
- void incTotalData_NoUpdate (int objectsDelta, Int64 dataDelta);
-
- void setStatusText_NoUpdate(const wxString& text);
- void updateStatusDialogNow(bool allowYield = true);
+ void initNewPhase();
+ void reportCurrentBytes(Int64 currentData);
+ void updateProgress(bool allowYield = true);
- void processHasFinished(SyncStatus::SyncStatusID id, const ErrorLog& log); //essential to call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater
+ //call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater
+ void processHasFinished(SyncResult resultId, const ErrorLog& log);
+ void closeWindowDirectly();
std::wstring getExecWhenFinishedCommand() const;
- void stopTimer(); //halt all internal counters!
- void resumeTimer(); //
+ void stopTimer() //halt all internal counters!
+ {
+ m_animationControl1->Stop();
+ timeElapsed.Pause ();
+ }
+ void resumeTimer()
+ {
+ m_animationControl1->Play();
+ timeElapsed.Resume();
+ }
void minimizeToTray();
private:
void OnKeyPressed(wxKeyEvent& event);
- virtual void OnOkay(wxCommandEvent& event);
- virtual void OnPause(wxCommandEvent& event);
- virtual void OnAbort(wxCommandEvent& event);
- virtual void OnClose(wxCloseEvent& event);
+ virtual void OnOkay (wxCommandEvent& event);
+ virtual void OnPause (wxCommandEvent& event);
+ virtual void OnAbort (wxCommandEvent& event);
+ virtual void OnClose (wxCloseEvent& event);
virtual void OnIconize(wxIconizeEvent& event);
- void setCurrentStatus(SyncStatus::SyncStatusID id);
+ void updateDialogStatus();
void resumeFromSystray();
void OnResumeFromTray(wxCommandEvent& event);
- bool currentProcessIsRunning();
- void showProgressExternally(const wxString& progressText, double fraction = 0); //between [0, 1]
+ void setExternalStatus(const wxString& status, const wxString& progress); //progress may be empty!
const wxString jobName_;
wxStopWatch timeElapsed;
- AbortCallback* abortCb_; //temporarily bound
MainDialog* mainDialog; //optional
- //gauge variables
- int totalObjects; //file/dir/symlink/operation count
- Int64 totalData; //unit: [bytes]
- int currentObjects;
- Int64 currentData;
-
//status variables
- size_t scannedObjects;
- wxString currentStatusText;
+ AbortCallback* abortCb_; //temporarily bound while sync is running
+ const Statistics* syncStat_; //
+ bool paused_; //valid only while sync is running
+ SyncResult finalResult; //set after sync
- SyncStatus::SyncStatusID currentStatus;
- SyncStatus::SyncStatusID previousStatus; //save old status if "currentStatus == SyncStatus::PAUSED"
-
- std::unique_ptr<Taskbar> taskbar_;
+ bool isZombie; //wxGTK sends iconize event *after* wxWindow::Destroy, sigh...
//remaining time
- std::unique_ptr<Statistics> statistics;
- long lastStatCallSpeed; //used for calculating intervals between statistics update
+ std::unique_ptr<PerfCheck> perf;
+ long lastStatCallSpeed; //used for calculating intervals between collecting perf samples
long lastStatCallRemTime; //
std::shared_ptr<GraphDataBytes> graphDataBytes;
- //std::shared_ptr<GraphDataConstLine> graphDataBytesCurrent;
std::shared_ptr<GraphDataConstLine> graphDataBytesTotal;
wxString titelTextBackup;
-
std::unique_ptr<FfsTrayIcon> trayIcon; //optional: if filled all other windows should be hidden and conversely
+ std::unique_ptr<Taskbar> taskbar_;
};
SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb,
+ const Statistics& syncStat,
MainDialog* parentWindow,
- SyncStatusID startStatus,
const wxString& jobName,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory) :
SyncStatusDlgGenerated(parentWindow,
wxID_ANY,
- parentWindow ? wxString(wxEmptyString) : (wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")),
+ parentWindow ? wxString() : (wxString(L"FreeFileSync - ") + _("Folder Comparison and Synchronization")),
wxDefaultPosition, wxSize(640, 350),
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),
- jobName_(jobName),
- abortCb_(&abortCb),
+ jobName_ (jobName),
mainDialog(parentWindow),
- totalObjects(0),
- totalData(0),
- currentObjects(0),
- currentData(0),
- scannedObjects(0),
- currentStatus (SyncStatus::ABORTED),
- previousStatus(SyncStatus::ABORTED),
- lastStatCallSpeed(-1000000), //some big number
+ abortCb_ (&abortCb),
+ syncStat_ (&syncStat),
+ paused_ (false),
+ finalResult(RESULT_ABORTED), //dummy value
+ isZombie(false),
+ lastStatCallSpeed (-1000000), //some big number
lastStatCallRemTime(-1000000)
{
#ifdef FFS_WIN
- new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this"
+ new MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this"
#endif
- if (mainDialog) //save old title (will be used as progress indicator)
- titelTextBackup = mainDialog->GetTitle();
+ if (mainDialog)
+ {
+ titelTextBackup = mainDialog->GetTitle(); //save old title (will be used as progress indicator)
+ mainDialog->disableAllElements(false); //disable all child elements
+ }
m_animationControl1->SetAnimation(GlobalResources::instance().animationSync);
m_animationControl1->Play();
+ SetIcon(GlobalResources::instance().programIcon);
+
//initialize gauge
m_gauge1->SetRange(GAUGE_FULL_RANGE);
m_gauge1->SetValue(0);
-
EnableCloseButton(false);
if (IsShown()) //don't steal focus when starting in sys-tray!
m_buttonAbort->SetFocus();
- if (mainDialog)
- mainDialog->disableAllElements(false); //disable all child elements
-
timeElapsed.Start(); //measure total time
try //try to get access to Windows 7/Ubuntu taskbar
@@ -780,39 +658,29 @@ SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb,
//hide "processed" statistics until end of process
bSizerFinalStat ->Show(false);
- m_buttonOK ->Show(false);
m_staticTextLabelItemsProc->Show(false);
bSizerItemsProc ->Show(false);
-
- SetIcon(GlobalResources::instance().programIcon); //set application icon
+ m_buttonOK ->Show(false);
//register key event
Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(SyncStatusImpl::OnKeyPressed), nullptr, this);
- setCurrentStatus(startStatus); //first state: will be shown while waiting for dir locks (if at all)
-
//init graph
- graphDataBytes = std::make_shared<GraphDataBytes>();
- //graphDataBytesCurrent = std::make_shared<GraphDataConstLine>();
- graphDataBytesTotal = std::make_shared<GraphDataConstLine>();
+ graphDataBytes = std::make_shared<GraphDataBytes>();
+ graphDataBytesTotal = std::make_shared<GraphDataConstLine>();
m_panelGraph->setAttributes(Graph2D::GraphAttributes().
setLabelX(Graph2D::X_LABEL_BOTTOM, 20, std::make_shared<LabelFormatterTimeElapsed>()).
setLabelY(Graph2D::Y_LABEL_RIGHT, 60, std::make_shared<LabelFormatterBytes>()));
- m_panelGraph->setData(graphDataBytesTotal, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 64, 0))); //green
- //m_panelGraph->addData(graphDataBytesCurrent, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 128, 0))); //green
- m_panelGraph->addData(graphDataBytes, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0))); //medium green
+ m_panelGraph->setData(graphDataBytesTotal, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 64, 0))); //green
+ m_panelGraph->addData(graphDataBytes, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0))); //medium green
//allow changing on completion command
- m_comboBoxExecFinished->setValue(execWhenFinished);
+ m_comboBoxExecFinished->setValue (execWhenFinished);
m_comboBoxExecFinished->setHistoryRef(execFinishedHistory);
- //Fit() height only:
- //fitHeight(*this);
-
- m_staticTextSpeed ->SetLabel(L""); //clear "dummy" values
- m_staticTextRemTime->SetLabel(L""); //
+ updateDialogStatus(); //null-status will be shown while waiting for dir locks (if at all)
}
@@ -838,12 +706,14 @@ void SyncStatus::SyncStatusImpl::OnKeyPressed(wxKeyEvent& event)
//simulate click on abort button
if (m_buttonAbort->IsShown()) //delegate to "abort" button if available
{
- m_buttonAbort->GetEventHandler()->ProcessEvent(dummy);
+ if (wxEvtHandler* handler = m_buttonAbort->GetEventHandler())
+ handler->ProcessEvent(dummy);
return;
}
- else if (m_buttonOK->IsShown()) //delegate to "abort" button if available
+ else if (m_buttonOK->IsShown())
{
- m_buttonOK->GetEventHandler()->ProcessEvent(dummy);
+ if (wxEvtHandler* handler = m_buttonOK->GetEventHandler())
+ handler->ProcessEvent(dummy);
return;
}
}
@@ -852,119 +722,37 @@ void SyncStatus::SyncStatusImpl::OnKeyPressed(wxKeyEvent& event)
}
-void SyncStatus::SyncStatusImpl::initNewProcess(SyncStatusID id, int totalObjectsToProcess, Int64 totalDataToProcess)
+void SyncStatus::SyncStatusImpl::initNewPhase()
{
- setCurrentStatus(id);
+ updateDialogStatus(); //evaluates "syncStat_->currentPhase()"
- currentData = 0;
- currentObjects = 0;
- totalData = totalDataToProcess;
- totalObjects = totalObjectsToProcess;
-
- incProcessedData_NoUpdate(0, 0); //update graph
- incTotalData_NoUpdate (0, 0); //
-
- //set new statistics handler: 10 seconds "window" for remaining time, 5 seconds for speed
- statistics.reset(new Statistics(totalObjectsToProcess, to<double>(totalDataToProcess), windowSizeRemainingTime, windowSizeBytesPerSec));
+ //reset graph (e.g. after binary comparison)
+ graphDataBytes->clear();
+ reportCurrentBytes(0);
+ //start new measurement
+ perf.reset(new PerfCheck(WINDOW_REMAINING_TIME, WINDOW_BYTES_PER_SEC));
lastStatCallSpeed = -1000000; //some big number
lastStatCallRemTime = -1000000;
//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 updateStatusDialogNow() a chance to set a different value
+ //so give updateProgress() a chance to set a different value
m_gauge1->SetValue(0);
- updateStatusDialogNow(false); //get rid of "dummy" texts!
-}
-
-
-void SyncStatus::SyncStatusImpl::incProcessedData_NoUpdate(int objectsDelta, Int64 dataDelta)
-{
- currentData += dataDelta;
- currentObjects += objectsDelta;
-
- //update graph data
- graphDataBytes->addCurrentValue(to<double>(currentData));
+ updateProgress(false);
}
-void SyncStatus::SyncStatusImpl::incTotalData_NoUpdate(int objectsDelta, Int64 dataDelta)
+void SyncStatus::SyncStatusImpl::reportCurrentBytes(Int64 currentData)
{
- totalData += dataDelta;
- totalObjects += objectsDelta;
-
- if (statistics)
- statistics->setNewTotal(totalObjects, to<double>(totalData));
-
- graphDataBytesTotal->setValue(to<double>(totalData));
- //m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMaxY(to<double>(totalDataToProcess)));
+ //add sample for perf measurements + calc. of remaining time
+ graphDataBytes->addRecord(to<double>(currentData), timeElapsed.Time());
}
-void SyncStatus::SyncStatusImpl::incScannedObjects_NoUpdate(int number)
-{
- scannedObjects += number;
-}
-
-
-void SyncStatus::SyncStatusImpl::setStatusText_NoUpdate(const wxString& text)
-{
- currentStatusText = text;
-}
-
-
-void SyncStatus::SyncStatusImpl::showProgressExternally(const wxString& progressText, double fraction)
-{
- //write status information to systray, if window is minimized
- if (trayIcon.get())
- trayIcon->setToolTip(progressText, fraction);
-
- wxString progressTextFmt = progressText;
- progressTextFmt.Replace(wxT("\n"), wxT(" - "));
-
- if (mainDialog) //show percentage in maindialog title (and thereby in taskbar)
- {
- if (mainDialog->GetTitle() != progressTextFmt)
- mainDialog->SetTitle(progressTextFmt);
- }
- else //show percentage in this dialog's title (and thereby in taskbar)
- {
- if (this->GetTitle() != progressTextFmt)
- this->SetTitle(progressTextFmt);
- }
-
-
- //show progress on Windows 7 taskbar
- if (taskbar_.get())
- {
- switch (currentStatus)
- {
- case SyncStatus::SCANNING:
- taskbar_->setStatus(Taskbar::STATUS_INDETERMINATE);
- break;
- case SyncStatus::FINISHED_WITH_SUCCESS:
- case SyncStatus::COMPARING_CONTENT:
- case SyncStatus::SYNCHRONIZING:
- taskbar_->setProgress(fraction);
- taskbar_->setStatus(Taskbar::STATUS_NORMAL);
- break;
- case SyncStatus::PAUSE:
- taskbar_->setProgress(fraction);
- taskbar_->setStatus(Taskbar::STATUS_PAUSED);
- break;
- case SyncStatus::ABORTED:
- case SyncStatus::FINISHED_WITH_ERROR:
- taskbar_->setProgress(fraction);
- taskbar_->setStatus(Taskbar::STATUS_ERROR);
- break;
- }
- }
-}
-
-
-#ifdef FFS_WIN
namespace
{
+#ifdef FFS_WIN
enum Zorder
{
ZORDER_CORRECT,
@@ -988,131 +776,183 @@ Zorder evaluateZorder(const wxWindow& top, const wxWindow& bottom)
return ZORDER_INDEFINITE;
}
-}
#endif
-void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield)
+std::wstring getDialogStatusText(const Statistics* syncStat, bool paused, SyncStatus::SyncResult finalResult)
+{
+ if (syncStat) //sync running
+ {
+ if (paused)
+ return _("Paused");
+ else
+ switch (syncStat->currentPhase())
+ {
+ case ProcessCallback::PHASE_NONE:
+ return _("Initializing..."); //dialog is shown *before* sync starts, so this text may be visible!
+ case ProcessCallback::PHASE_SCANNING:
+ return _("Scanning...");
+ case ProcessCallback::PHASE_COMPARING_CONTENT:
+ return _("Comparing content...");
+ case ProcessCallback::PHASE_SYNCHRONIZING:
+ return _("Synchronizing...");
+ }
+ }
+ else //sync finished
+ switch (finalResult)
+ {
+ case SyncStatus::RESULT_ABORTED:
+ return _("Aborted");
+ case SyncStatus::RESULT_FINISHED_WITH_ERROR:
+ case SyncStatus::RESULT_FINISHED_WITH_SUCCESS:
+ return _("Completed");
+ }
+ return std::wstring();
+}
+}
+
+
+void SyncStatus::SyncStatusImpl::setExternalStatus(const wxString& status, const wxString& progress) //progress may be empty!
{
- //static RetrieveStatistics statistic;
- //statistic.writeEntry(currentData.ToDouble(), currentObjects);
+ //sys tray: order "top-down": jobname, status, progress
+ wxString newTrayInfo = jobName_.empty() ? status : L"\"" + jobName_ + L"\"\n" + status;
+ if (!progress.empty())
+ newTrayInfo += L" " + progress;
- //add both data + obj-count, to handle "deletion-only" cases
- const double fraction = totalData + totalObjects == 0 ? 1 : std::max(0.0, to<double>(currentData + currentObjects) / to<double>(totalData + totalObjects));
- //yes, this may legitimately become < 0: failed rename operation falls-back to copy + delete, reducing "currentData" to potentially < 0!
+ //window caption/taskbar; inverse order: progress, status, jobname
+ wxString newCaption = progress.empty() ? status : progress + L" - " + status;
+ if (!jobName_.empty())
+ newCaption += L" - \"" + jobName_ + L"\"";
- //write status information to systray, taskbar, parent title ect.
+ //systray tooltip, if window is minimized
+ if (trayIcon.get())
+ trayIcon->setToolTip(newTrayInfo);
- const wxString postFix = jobName_.empty() ? wxString() : (wxT("\n\"") + jobName_ + wxT("\""));
- switch (currentStatus)
+ //show text in dialog title (and at the same time in taskbar)
+ if (mainDialog)
{
- case SyncStatus::SCANNING:
- showProgressExternally(wxString() + toStringSep(scannedObjects) + wxT(" - ") + _("Scanning...") + postFix);
- break;
- case SyncStatus::COMPARING_CONTENT:
- showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Comparing content...") + postFix, fraction);
- break;
- case SyncStatus::SYNCHRONIZING:
- showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Synchronizing...") + postFix, fraction);
- break;
- case SyncStatus::PAUSE:
- showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Paused") + postFix, fraction);
- break;
- case SyncStatus::ABORTED:
- showProgressExternally(_("Aborted") + postFix, fraction);
- break;
- case SyncStatus::FINISHED_WITH_SUCCESS:
- case SyncStatus::FINISHED_WITH_ERROR:
- showProgressExternally(_("Completed") + postFix, fraction);
- break;
+ if (mainDialog->GetTitle() != newCaption)
+ mainDialog->SetTitle(newCaption);
}
-
- //write regular status information (whether dialog is visible or not)
+ else
{
- //wxWindowUpdateLocker dummy(this); -> not needed
+ if (this->GetTitle() != newCaption)
+ this->SetTitle(newCaption);
+ }
+}
- bool layoutChanged = false; //avoid screen flicker by calling layout() only if necessary
- //progress indicator
- switch (currentStatus)
- {
- case SyncStatus::SCANNING:
- m_gauge1->Pulse();
- break;
- case SyncStatus::COMPARING_CONTENT:
- case SyncStatus::SYNCHRONIZING:
- case SyncStatus::FINISHED_WITH_SUCCESS:
- case SyncStatus::FINISHED_WITH_ERROR:
- case SyncStatus::ABORTED:
- m_gauge1->SetValue(numeric::round(fraction * GAUGE_FULL_RANGE));
- break;
- case SyncStatus::PAUSE: //no change to gauge: don't switch between indeterminate/determinate modus
- break;
- }
+void SyncStatus::SyncStatusImpl::updateProgress(bool allowYield)
+{
+ assert(syncStat_);
+ if (!syncStat_) //no sync running!!
+ return;
+ //wxWindowUpdateLocker dummy(this); -> not needed
- wxString statusTextFmt = currentStatusText; //remove linebreaks
- replace(statusTextFmt, L'\n', L' '); //
+ bool layoutChanged = false; //avoid screen flicker by calling layout() only if necessary
- //status text
- if (m_textCtrlInfo->GetValue() != statusTextFmt) //no layout update for status texts!
- m_textCtrlInfo->ChangeValue(statusTextFmt);
+ //sync status text
+ setText(*m_textCtrlInfo, replaceCpy(syncStat_->currentStatusText(), L'\n', L' ')); //no layout update for status texts!
- //remaining objects
- const wxString remainingObjTmp = toStringSep(totalObjects - currentObjects);
- setText(*m_staticTextRemainingObj, remainingObjTmp, &layoutChanged);
+ switch (syncStat_->currentPhase()) //no matter if paused or not
+ {
+ case ProcessCallback::PHASE_NONE:
+ case ProcessCallback::PHASE_SCANNING:
+ //dialog caption, taskbar, systray tooltip
+ setExternalStatus(getDialogStatusText(syncStat_, paused_, finalResult), toStringSep(syncStat_->getObjectsCurrent(ProcessCallback::PHASE_SCANNING))); //status text may be "paused"!
- //remaining bytes left for copy
- const wxString remainingBytesTmp = zen::filesizeToShortString(totalData - currentData);
- setText(*m_staticTextDataRemaining, remainingBytesTmp, &layoutChanged);
+ //progress indicators
+ m_gauge1->Pulse();
+ if (trayIcon.get()) trayIcon->setProgress(1); //1 = regular FFS logo
- //statistics
- if (statistics.get())
- {
- if (timeElapsed.Time() - lastStatCallSpeed >= 500) //call method every 500 ms
- {
- lastStatCallSpeed = timeElapsed.Time();
+ //taskbar_ status is Taskbar::STATUS_INDETERMINATE
+
+ //constant line graph
+ graphDataBytesTotal->setValue(0);
- statistics->addMeasurement(currentObjects, to<double>(currentData));
+ //remaining objects and data
+ setText(*m_staticTextRemainingObj , L"-", &layoutChanged);
+ setText(*m_staticTextDataRemaining, L"", &layoutChanged);
- //current speed
- setText(*m_staticTextSpeed, statistics->getBytesPerSecond(), &layoutChanged);
+ //remaining time and speed
+ setText(*m_staticTextSpeed, L"-", &layoutChanged);
+ setText(*m_staticTextRemTime, L"-", &layoutChanged);
+ break;
- if (timeElapsed.Time() - lastStatCallRemTime >= 2000) //call method every two seconds only
+ 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());
+
+ //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));
+ //yes, this may legitimately become < 0: failed rename operation falls-back to copy + delete, reducing "dataCurrent" to potentially < 0!
+ //----------------------------------------------------------------------------------------------------
+
+ //dialog caption, taskbar, systray tooltip
+ setExternalStatus(getDialogStatusText(syncStat_, paused_, finalResult), fractionToShortString(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));
+
+ //remaining objects and data
+ setText(*m_staticTextRemainingObj, toStringSep(objectsTotal - objectsCurrent), &layoutChanged);
+ setText(*m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged);
+
+ //remaining time and speed
+ assert(perf);
+ if (perf)
+ if (timeElapsed.Time() - lastStatCallSpeed >= 500) //-> Win 7 copy uses 1 sec update interval
{
- lastStatCallRemTime = timeElapsed.Time();
+ lastStatCallSpeed = timeElapsed.Time();
- //remaining time
- setText(*m_staticTextRemTime, statistics->getRemainingTime(), &layoutChanged);
- }
- }
- }
+ perf->addSample(objectsCurrent, to<double>(dataCurrent), timeElapsed.Time());
- {
- m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMinX(graphDataBytes->getXBegin()));
- m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMaxX(graphDataBytes->getXEnd()));
+ //current speed
+ setText(*m_staticTextSpeed, perf->getBytesPerSecond(), &layoutChanged);
- m_panelGraph->Refresh();
+ if (timeElapsed.Time() - lastStatCallRemTime >= 2000) //update GUI every 2 sec
+ {
+ lastStatCallRemTime = timeElapsed.Time();
+
+ //remaining time
+ setText(*m_staticTextRemTime, perf->getRemainingTime(to<double>(dataTotal - dataCurrent)), &layoutChanged);
+ }
+ }
}
+ break;
+ }
- //time elapsed
- const long timeElapSec = timeElapsed.Time() / 1000;
- setText(*m_staticTextTimeElapsed,
- timeElapSec < 3600 ?
- wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") :
- wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged);
+ m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMinX(graphDataBytes->getXBegin()));
+ m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMaxX(graphDataBytes->getXEnd()));
+ m_panelGraph->Refresh();
- //do the ui update
- 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!
- }
+ //time elapsed
+ const long timeElapSec = timeElapsed.Time() / 1000;
+ setText(*m_staticTextTimeElapsed,
+ timeElapSec < 3600 ?
+ wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") :
+ wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged);
+
+ //do the ui update
+ 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!
}
#ifdef FFS_WIN
@@ -1132,92 +972,195 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield)
if (allowYield)
{
//support for pause button
- while (currentStatus == SyncStatus::PAUSE && currentProcessIsRunning())
+ if (paused_)
{
- wxMilliSleep(UI_UPDATE_INTERVAL);
- updateUiNow();
+ stopTimer();
+ while (paused_)
+ {
+ wxMilliSleep(UI_UPDATE_INTERVAL);
+ updateUiNow(); //receive UI message that ends pause
+ }
+ resumeTimer();
}
-
/*
/|\
- | keep this order to ensure one full statistics update before entering pause mode
+ | keep this sequence to ensure one full progress update before entering pause mode!
\|/
*/
- updateUiNow();
+ updateUiNow(); //receive UI message that sets pause status
}
else
Update(); //don't wait until next idle event (who knows what blocking process comes next?)
}
-bool SyncStatus::SyncStatusImpl::currentProcessIsRunning()
-{
- return abortCb_ != nullptr;
-}
-
-
std::wstring SyncStatus::SyncStatusImpl::getExecWhenFinishedCommand() const
{
return m_comboBoxExecFinished->getValue();
}
-void SyncStatus::SyncStatusImpl::setCurrentStatus(SyncStatus::SyncStatusID id)
+void SyncStatus::SyncStatusImpl::updateDialogStatus() //depends on "syncStat_, paused_, finalResult"
{
- switch (id)
+ m_staticTextStatus->SetLabel(getDialogStatusText(syncStat_, paused_, finalResult));
+
+ if (syncStat_) //sync running
{
- case SyncStatus::ABORTED:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusError")));
- m_staticTextStatus->SetLabel(_("Aborted"));
- break;
+ if (paused_)
+ m_buttonPause->SetLabel(_("Continue"));
+ else
+ m_buttonPause->SetLabel(_("Pause"));
+
+ if (paused_)
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusPause"));
+ else
+ switch (syncStat_->currentPhase())
+ {
+ case ProcessCallback::PHASE_NONE:
+ break;
- case SyncStatus::FINISHED_WITH_SUCCESS:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusSuccess")));
- m_staticTextStatus->SetLabel(_("Completed"));
- break;
+ case ProcessCallback::PHASE_SCANNING:
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusScanning"));
+ break;
- case SyncStatus::FINISHED_WITH_ERROR:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusWarning")));
- m_staticTextStatus->SetLabel(_("Completed"));
- break;
+ case ProcessCallback::PHASE_COMPARING_CONTENT:
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusBinaryCompare"));
+ break;
- case SyncStatus::PAUSE:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusPause")));
- m_staticTextStatus->SetLabel(_("Paused"));
- break;
+ case ProcessCallback::PHASE_SYNCHRONIZING:
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusSyncing"));
+ break;
+ }
+ }
+ else //sync finished
+ switch (finalResult)
+ {
+ case RESULT_ABORTED:
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusError"));
+ break;
- case SyncStatus::SCANNING:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusScanning")));
- m_staticTextStatus->SetLabel(_("Scanning..."));
- break;
+ case RESULT_FINISHED_WITH_ERROR:
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusWarning"));
+ break;
- case SyncStatus::COMPARING_CONTENT:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusBinaryCompare")));
- m_staticTextStatus->SetLabel(_("Comparing content..."));
- break;
+ case RESULT_FINISHED_WITH_SUCCESS:
+ m_bitmapStatus->SetBitmap(GlobalResources::getImage(L"statusSuccess"));
+ break;
+ }
- case SyncStatus::SYNCHRONIZING:
- m_bitmapStatus->SetBitmap(GlobalResources::getImage(wxT("statusSyncing")));
- m_staticTextStatus->SetLabel(_("Synchronizing..."));
- break;
+ //show status on Windows 7 taskbar
+ if (taskbar_.get())
+ {
+ if (syncStat_) //sync running
+ {
+ if (paused_)
+ taskbar_->setStatus(Taskbar::STATUS_PAUSED);
+ else
+ switch (syncStat_->currentPhase())
+ {
+ case ProcessCallback::PHASE_NONE:
+ case ProcessCallback::PHASE_SCANNING:
+ taskbar_->setStatus(Taskbar::STATUS_INDETERMINATE);
+ break;
+
+ case ProcessCallback::PHASE_COMPARING_CONTENT:
+ case ProcessCallback::PHASE_SYNCHRONIZING:
+ taskbar_->setStatus(Taskbar::STATUS_NORMAL);
+ break;
+ }
+ }
+ else //sync finished
+ switch (finalResult)
+ {
+ case RESULT_ABORTED:
+ case RESULT_FINISHED_WITH_ERROR:
+ taskbar_->setStatus(Taskbar::STATUS_ERROR);
+ break;
+
+ case RESULT_FINISHED_WITH_SUCCESS:
+ taskbar_->setStatus(Taskbar::STATUS_NORMAL);
+ break;
+ }
}
- currentStatus = id;
-
m_panelBackground->Layout(); //we use a dummy panel as actual background: replaces simple "Layout()" call
}
-void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, const ErrorLog& log) //essential to call this in StatusHandler derived class destructor
+void SyncStatus::SyncStatusImpl::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 cut callbacks!
+ //e.g. wxGTK calls OnIconize after wxWindow::Close() (better not ask why) and before physical destruction! => indirectly calls updateDialogStatus(), which reads syncStat_!!!
+
+ //------- change class state -------
+ abortCb_ = nullptr; //avoid callback to (maybe) deleted parent process
+ syncStat_ = nullptr; //set *after* last call to "updateProgress"
+ //----------------------------------
+
+ Close();
+}
+
+
+void SyncStatus::SyncStatusImpl::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
wxWindowUpdateLocker dummy(this); //badly needed
- abortCb_ = nullptr; //avoid callback to (maybe) deleted parent process
+ paused_ = false; //you never know?
- setCurrentStatus(id);
+ //update numbers one last time (as if sync were still running)
+ updateProgress(false);
+
+ switch (syncStat_->currentPhase()) //no matter if paused or not
+ {
+ case ProcessCallback::PHASE_NONE:
+ case ProcessCallback::PHASE_SCANNING:
+ //set overall speed -> not needed
+ //items processed -> not needed
+ break;
+
+ case ProcessCallback::PHASE_COMPARING_CONTENT:
+ case ProcessCallback::PHASE_SYNCHRONIZING:
+ {
+ auto objectsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase());
+ auto objectsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase());
+ auto dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase());
+ auto dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase());
+
+ //set overall speed (instead of current speed)
+ assert(perf);
+ if (perf)
+ m_staticTextSpeed->SetLabel(perf->getOverallBytesPerSecond()); //note: we can't simply divide "sync total bytes" by "timeElapsed"
+
+ //show new element "items processed"
+ m_staticTextLabelItemsProc->Show(true);
+ bSizerItemsProc ->Show(true);
+ m_staticTextProcessedObj ->SetLabel(toStringSep(objectsCurrent));
+ 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);
+ }
+ }
+ break;
+ }
+
+ //------- change class state -------
+ abortCb_ = nullptr; //avoid callback to (maybe) deleted parent process
+ syncStat_ = nullptr; //set *after* last call to "updateProgress"
+ finalResult = resultId;
+ //----------------------------------
+
+ updateDialogStatus();
+ setExternalStatus(getDialogStatusText(syncStat_, paused_, finalResult), wxString());
resumeFromSystray(); //if in tray mode...
@@ -1244,45 +1187,30 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id,
//show and prepare final statistics
bSizerFinalStat->Show(true);
- if (totalObjects == currentObjects && //if everything was processed successfully
- totalData == currentData)
- {
- m_staticTextLabelItemsRem->Show(false);
- bSizerItemsRem ->Show(false);
- }
-
- m_staticTextLabelItemsProc->Show(true);
- bSizerItemsProc ->Show(true);
- m_staticTextProcessedObj ->SetLabel(toStringSep(currentObjects));
- m_staticTextDataProcessed->SetLabel(zen::filesizeToShortString(currentData));
-
+ //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);
- updateStatusDialogNow(false); //keep this sequence to avoid display distortion, if e.g. only 1 item is sync'ed
-
- //changed meaning: from current to overall speed: -> make sure to call after "updateStatusDialogNow"
- const long timeElapMs = timeElapsed.Time();
- m_staticTextSpeed->SetLabel(timeElapMs <= 0 ? L"-" : zen::filesizeToShortString(currentData * 1000 / timeElapMs) + _("/sec"));
-
- //fill result listbox:
-
//workaround wxListBox bug on Windows XP: labels are drawn on top of each other
assert(m_listbookResult->GetImageList()); //make sure listbook keeps *any* image list
//due to some crazy reasons that aren't worth debugging, this needs to be done directly in wxFormBuilder,
- //the following call is *not* sufficient: m_listbookResult->AssignImageList(new wxImageList(0, 0));
+ //the following call is *not* sufficient: m_listbookResult->AssignImageList(new wxImageList(180, 1));
//note: alternative solutions involving wxLC_LIST, wxLC_REPORT and SetWindowStyleFlag() do not work portably! wxListBook using wxLC_ICON is obviously a class invariant!
//1. re-arrange graph into results listbook
bSizerTop->Detach(m_panelProgress);
m_panelProgress->Reparent(m_listbookResult);
+#ifdef FFS_LINUX
+ wxYield(); //wxGTK 2.9.3 fails miserably at "reparent" whithout this
+#endif
m_listbookResult->AddPage(m_panelProgress, _("Statistics"), true); //AddPage() takes ownership!
//2. log file
const size_t posLog = 1;
- LogControl* logControl = new LogControl(m_listbookResult, log);
+ LogControl* logControl = new LogControl(m_listbookResult, log); //owned by m_listbookResult
m_listbookResult->AddPage(logControl, _("Logging"), false);
//bSizerHoldStretch->Insert(0, logControl, 1, wxEXPAND);
@@ -1304,62 +1232,19 @@ void SyncStatus::SyncStatusImpl::OnOkay(wxCommandEvent& event)
void SyncStatus::SyncStatusImpl::OnAbort(wxCommandEvent& event)
{
- if (currentStatus == SyncStatus::PAUSE)
- {
- wxCommandEvent dummy;
- OnPause(dummy);
- }
-
- if (currentProcessIsRunning())
- {
- m_buttonAbort->Disable();
- m_buttonAbort->Hide();
- m_buttonPause->Disable();
- m_buttonPause->Hide();
-
- setStatusText_NoUpdate(_("Abort requested: Waiting for current operation to finish..."));
- //no Layout() or UI-update here to avoid cascaded Yield()-call
+ paused_ = false;
+ updateDialogStatus(); //update status + pause button
+ //no Layout() or UI-update here to avoid cascaded Yield()-call
+ if (abortCb_)
abortCb_->requestAbortion();
- }
-}
-
-
-void SyncStatus::SyncStatusImpl::stopTimer()
-{
- timeElapsed.Pause();
- if (statistics.get()) statistics->pauseTimer();
- graphDataBytes->pauseTimer();
-}
-
-
-void SyncStatus::SyncStatusImpl::resumeTimer()
-{
- timeElapsed.Resume();
- if (statistics.get()) statistics->resumeTimer();
- graphDataBytes->resumeTimer();
}
void SyncStatus::SyncStatusImpl::OnPause(wxCommandEvent& event)
{
- if (currentStatus == SyncStatus::PAUSE)
- {
- resumeTimer();
- setCurrentStatus(previousStatus);
-
- m_buttonPause->SetLabel(_("Pause"));
- m_animationControl1->Play();
- }
- else
- {
- stopTimer();
- previousStatus = currentStatus; //save current status
- setCurrentStatus(SyncStatus::PAUSE);
-
- m_buttonPause->SetLabel(_("Continue"));
- m_animationControl1->Stop();
- }
+ paused_ = !paused_;
+ updateDialogStatus(); //update status + pause button
}
@@ -1367,16 +1252,19 @@ void SyncStatus::SyncStatusImpl::OnClose(wxCloseEvent& event)
{
//this event handler may be called due to a system shutdown DURING synchronization!
//try to stop sync gracefully and cross fingers:
- if (currentProcessIsRunning())
+ if (abortCb_)
abortCb_->requestAbortion();
- //Note: we must NOT veto dialog destruction, else we will cancel system shutdown if this dialog is application main window (like in batch mode)
+ //Note: we must NOT veto dialog destruction, else we will cancel system shutdown if this dialog is application main window (as in batch mode)
+ isZombie = true; //it "lives" until cleanup in next idle event
Destroy();
}
void SyncStatus::SyncStatusImpl::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
@@ -1399,7 +1287,8 @@ void SyncStatus::SyncStatusImpl::minimizeToTray()
//tray icon has shorter lifetime than this => no need to disconnect event later
}
- updateStatusDialogNow(false); //set tooltip: e.g. in pause mode there was no GUI update, so this is the last chance
+ if (syncStat_)
+ updateProgress(false); //set tray tooltip + progress: e.g. no updates while paused
Hide();
if (mainDialog)
@@ -1425,7 +1314,9 @@ void SyncStatus::SyncStatusImpl::resumeFromSystray()
Raise();
SetFocus();
- updateStatusDialogNow(false); //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)
+ if (syncStat_)
+ updateProgress(false); //restore Windows 7 task bar progress (e.g. required in pause mode)
}
@@ -1434,18 +1325,18 @@ void SyncStatus::SyncStatusImpl::resumeFromSystray()
//redirect to implementation
SyncStatus::SyncStatus(AbortCallback& abortCb,
+ const Statistics& syncStat,
MainDialog* parentWindow,
- SyncStatusID startStatus,
bool showProgress,
const wxString& jobName,
const std::wstring& execWhenFinished,
std::vector<std::wstring>& execFinishedHistory) :
- pimpl(new SyncStatusImpl(abortCb, parentWindow, startStatus, jobName, execWhenFinished, execFinishedHistory))
+ pimpl(new SyncStatusImpl(abortCb, syncStat, parentWindow, jobName, execWhenFinished, execFinishedHistory))
{
if (showProgress)
{
pimpl->Show();
- pimpl->updateStatusDialogNow(false); //clear gui flicker: window must be visible to make this work!
+ pimpl->updateProgress(false); //clear gui flicker, remove dummy texts: window must be visible to make this work!
}
else
pimpl->minimizeToTray();
@@ -1461,34 +1352,19 @@ wxWindow* SyncStatus::getAsWindow()
return pimpl;
}
-void SyncStatus::initNewProcess(SyncStatusID id, int totalObjectsToProcess, Int64 totalDataToProcess)
-{
- pimpl->initNewProcess(id, totalObjectsToProcess, totalDataToProcess);
-}
-
-void SyncStatus::incScannedObjects_NoUpdate(int number)
-{
- pimpl->incScannedObjects_NoUpdate(number);
-}
-
-void SyncStatus::incProcessedData_NoUpdate(int objectsDelta, Int64 dataDelta)
-{
- pimpl->incProcessedData_NoUpdate(objectsDelta, dataDelta);
-}
-
-void SyncStatus::incTotalData_NoUpdate(int objectsDelta, Int64 dataDelta)
+void SyncStatus::initNewPhase()
{
- pimpl->incTotalData_NoUpdate(objectsDelta, dataDelta);
+ pimpl->initNewPhase();
}
-void SyncStatus::setStatusText_NoUpdate(const wxString& text)
+void SyncStatus::reportCurrentBytes(Int64 currentData)
{
- pimpl->setStatusText_NoUpdate(text);
+ pimpl->reportCurrentBytes(currentData);
}
-void SyncStatus::updateStatusDialogNow()
+void SyncStatus::updateProgress()
{
- pimpl->updateStatusDialogNow();
+ pimpl->updateProgress();
}
std::wstring SyncStatus::getExecWhenFinishedCommand() const
@@ -1506,12 +1382,12 @@ void SyncStatus::resumeTimer()
return pimpl->resumeTimer();
}
-void SyncStatus::processHasFinished(SyncStatusID id, const ErrorLog& log)
+void SyncStatus::processHasFinished(SyncResult resultId, const ErrorLog& log)
{
- pimpl->processHasFinished(id, log);
+ pimpl->processHasFinished(resultId, log);
}
void SyncStatus::closeWindowDirectly() //don't wait for user (silent mode)
{
- pimpl->Destroy();
+ pimpl->closeWindowDirectly();
}
diff --git a/ui/progress_indicator.h b/ui/progress_indicator.h
index 858f6ce9..cd974408 100644
--- a/ui/progress_indicator.h
+++ b/ui/progress_indicator.h
@@ -18,18 +18,13 @@ class CompareStatus
{
public:
CompareStatus(wxTopLevelWindow& parentWindow); //CompareStatus will be owned by parentWindow!
- ~CompareStatus();
wxWindow* getAsWindow(); //convenience! don't abuse!
- void init(); //make visible, initialize all status values
- void finalize(); //hide again
+ void init(const zen::Statistics& syncStat); //begin of sync: make visible, set pointer to "syncStat", initialize all status values
+ void finalize(); //end of sync: hide again, clear pointer to "syncStat"
- void switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess);
- void incScannedObjects_NoUpdate(int number);
- void incProcessedCmpData_NoUpdate(int objectsDelta, zen::Int64 dataDelta);
- void incTotalCmpData_NoUpdate (int objectsDelta, zen::Int64 dataDelta);
- void setStatusText_NoUpdate(const wxString& text);
+ void switchToCompareBytewise();
void updateStatusPanelNow();
private:
@@ -41,20 +36,9 @@ private:
class SyncStatus
{
public:
- enum SyncStatusID
- {
- ABORTED,
- FINISHED_WITH_SUCCESS,
- FINISHED_WITH_ERROR,
- PAUSE,
- SCANNING,
- COMPARING_CONTENT,
- SYNCHRONIZING
- };
-
- SyncStatus(AbortCallback& abortCb,
+ SyncStatus(zen::AbortCallback& abortCb,
+ const zen::Statistics& syncStat,
MainDialog* parentWindow, //may be nullptr
- SyncStatusID startStatus,
bool showProgress,
const wxString& jobName,
const std::wstring& execWhenFinished,
@@ -63,22 +47,25 @@ public:
wxWindow* getAsWindow(); //convenience! don't abuse!
- void initNewProcess(SyncStatusID id, int totalObjectsToProcess, zen::Int64 totalDataToProcess);
+ void initNewPhase(); //call after "StatusHandler::initNewPhase"
- void incScannedObjects_NoUpdate(int number);
- void incProcessedData_NoUpdate(int objectsDelta, zen::Int64 dataDelta);
- void incTotalData_NoUpdate (int objectsDelta, zen::Int64 dataDelta);
- void setStatusText_NoUpdate(const wxString& text);
- void updateStatusDialogNow();
+ void reportCurrentBytes(zen::Int64 currentData); //throw (), required by graph!
+ void updateProgress();
std::wstring getExecWhenFinishedCommand() const; //final value (after possible user modification)
void stopTimer(); //halt all internal counters!
void resumeTimer(); //
+ enum SyncResult
+ {
+ RESULT_ABORTED,
+ RESULT_FINISHED_WITH_ERROR,
+ RESULT_FINISHED_WITH_SUCCESS
+ };
//essential to call one of these two methods in StatusUpdater derived class destructor at the LATEST(!)
//to prevent access to callback to updater (e.g. request abort)
- void processHasFinished(SyncStatusID id, const zen::ErrorLog& log);
+ void processHasFinished(SyncResult resultId, const zen::ErrorLog& log); //sync finished, still dialog may live on
void closeWindowDirectly(); //don't wait for user
private:
diff --git a/ui/search.cpp b/ui/search.cpp
index af62686b..80e4aa26 100644
--- a/ui/search.cpp
+++ b/ui/search.cpp
@@ -17,16 +17,17 @@ using namespace zen;
class SearchDlg : public SearchDialogGenerated
{
public:
- SearchDlg(wxWindow& parentWindow, wxString& searchText, bool& respectCase);
+ SearchDlg(wxWindow* parent, wxString& searchText, bool& respectCase);
enum ReturnCodes
{
- BUTTON_OKAY = 1 //mustn't be 0
+ BUTTON_CANCEL,
+ BUTTON_OKAY
};
private:
- void OnClose (wxCloseEvent& event) { EndModal(0); }
- void OnCancel(wxCommandEvent& event) { EndModal(0); }
+ void OnClose (wxCloseEvent& event) { EndModal(BUTTON_CANCEL); }
+ void OnCancel(wxCommandEvent& event) { EndModal(BUTTON_CANCEL); }
void OnFindNext(wxCommandEvent& event);
void OnText(wxCommandEvent& event);
@@ -35,8 +36,8 @@ private:
};
-SearchDlg::SearchDlg(wxWindow& parentWindow, wxString& searchText, bool& respectCase) :
- SearchDialogGenerated(&parentWindow),
+SearchDlg::SearchDlg(wxWindow* parent, wxString& searchText, bool& respectCase) :
+ SearchDialogGenerated(parent),
searchText_(searchText),
respectCase_(respectCase)
{
@@ -47,7 +48,6 @@ SearchDlg::SearchDlg(wxWindow& parentWindow, wxString& searchText, bool& respect
m_checkBoxMatchCase->SetValue(respectCase_);
m_textCtrlSearchTxt->SetValue(searchText_);
- CentreOnParent(); //this requires a parent window!
m_textCtrlSearchTxt->SetFocus();
}
@@ -79,7 +79,7 @@ class FindInText
{
public:
FindInText(const wxString& textToFind) : textToFind_(textToFind) {}
- bool found(const wxString& phrase) const { return phrase.Find(textToFind_) != wxNOT_FOUND; }
+ bool found(const wxString& phrase) const { return contains(phrase, textToFind_); }
private:
wxString textToFind_;
@@ -95,7 +95,7 @@ public:
{
//wxWidgets::MakeUpper() is inefficient! But performance is not THAT important for this high-level search functionality
phrase.MakeUpper();
- return phrase.Find(textToFind_) != wxNOT_FOUND;
+ return contains(phrase, textToFind_);
}
private:
@@ -147,7 +147,7 @@ wxString lastSearchString; //this variable really is conceptionally global...
void executeSearch(bool forceShowDialog,
bool& respectCase,
- wxWindow& parentWindow,
+ wxWindow* parent,
Grid& grid,
size_t compPosLeft, size_t compPosRight)
{
@@ -155,7 +155,7 @@ void executeSearch(bool forceShowDialog,
if (forceShowDialog || lastSearchString.IsEmpty())
{
- SearchDlg searchDlg(parentWindow, lastSearchString, respectCase); //wxWidgets deletion handling -> deleted by parentWindow
+ SearchDlg searchDlg(parent, lastSearchString, respectCase); //wxWidgets deletion handling -> deleted by parentWindow
if (static_cast<SearchDlg::ReturnCodes>(searchDlg.ShowModal()) != SearchDlg::BUTTON_OKAY)
return;
@@ -195,24 +195,22 @@ void executeSearch(bool forceShowDialog,
return;
}
- wxString messageNotFound = _("Cannot find %x");
- messageNotFound.Replace(wxT("%x"), wxString(wxT("\"")) + lastSearchString + wxT("\""), false);
- wxMessageBox(messageNotFound, _("Find"), wxOK);
+ wxMessageBox(replaceCpy(_("Cannot find %x"), L"%x", L"\"" + lastSearchString + L"\"", false), _("Find"), wxOK, parent);
//show search dialog again
if (searchDialogWasShown)
- executeSearch(true, respectCase, parentWindow, grid, compPosLeft, compPosRight);
+ executeSearch(true, respectCase, parent, grid, compPosLeft, compPosRight);
}
//###########################################################################################
-void zen::startFind(wxWindow& parentWindow, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase) //Strg + F
+void zen::startFind(wxWindow* parent, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase) //Strg + F
{
- executeSearch(true, respectCase, parentWindow, grid, compPosLeft, compPosRight);
+ executeSearch(true, respectCase, parent, grid, compPosLeft, compPosRight);
}
-void zen::findNext(wxWindow& parentWindow, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase) //F3
+void zen::findNext(wxWindow* parent, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase) //F3
{
- executeSearch(false, respectCase, parentWindow, grid, compPosLeft, compPosRight);
+ executeSearch(false, respectCase, parent, grid, compPosLeft, compPosRight);
}
diff --git a/ui/search.h b/ui/search.h
index 1c26ea78..6120562e 100644
--- a/ui/search.h
+++ b/ui/search.h
@@ -11,8 +11,8 @@
namespace zen
{
-void startFind(wxWindow& parentWindow, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase); //Strg + F
-void findNext( wxWindow& parentWindow, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase); //F3
+void startFind(wxWindow* parent, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase); //Strg + F
+void findNext( wxWindow* parent, Grid& grid, size_t compPosLeft, size_t compPosRight, bool& respectCase); //F3
}
#endif // SEARCH_H_INCLUDED
diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp
index 20e5da4e..c8c88de0 100644
--- a/ui/small_dlgs.cpp
+++ b/ui/small_dlgs.cpp
@@ -34,8 +34,8 @@ public:
AboutDlg(wxWindow* parent);
private:
- void OnClose(wxCloseEvent& event) { EndModal(0); }
- void OnOK (wxCommandEvent& event) { EndModal(0); }
+ void OnClose(wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
+ void OnOK (wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_OKAY); }
};
@@ -72,22 +72,19 @@ AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent)
//build information
wxString build = __TDATE__;
#if wxUSE_UNICODE
- build += wxT(" - Unicode");
+ build += L" - Unicode";
#else
- build += wxT(" - ANSI");
+ build += L" - ANSI";
#endif //wxUSE_UNICODE
//compile time info about 32/64-bit build
if (zen::is64BitBuild)
- build += wxT(" x64");
+ build += L" x64";
else
- build += wxT(" x86");
+ build += L" x86";
assert_static(zen::is32BitBuild || zen::is64BitBuild);
- wxString buildFormatted = _("(Build: %x)");
- buildFormatted.Replace(wxT("%x"), build);
-
- m_build->SetLabel(buildFormatted);
+ m_build->SetLabel(replaceCpy(_("(Build: %x)"), L"%x", build));
//m_animationControl1->SetAnimation(GlobalResources::instance().animationMoney);
//m_animationControl1->Play();
@@ -101,9 +98,9 @@ AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent)
}
-void zen::showAboutDialog()
+void zen::showAboutDialog(wxWindow* parent)
{
- AboutDlg aboutDlg(nullptr);
+ AboutDlg aboutDlg(parent);
aboutDlg.ShowModal();
}
//########################################################################################
@@ -118,8 +115,8 @@ public:
~FilterDlg() {}
private:
- void OnClose ( wxCloseEvent& event) { EndModal(0); }
- void OnCancel (wxCommandEvent& event) { EndModal(0); }
+ void OnClose ( wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
+ void OnCancel (wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
void OnHelp (wxCommandEvent& event);
void OnDefault (wxCommandEvent& event);
void OnApply (wxCommandEvent& event);
@@ -302,9 +299,9 @@ void FilterDlg::OnApply(wxCommandEvent& event)
}
-ReturnSmallDlg::ButtonPressed zen::showFilterDialog(bool isGlobalFilter, FilterConfig& filter)
+ReturnSmallDlg::ButtonPressed zen::showFilterDialog(wxWindow* parent, bool isGlobalFilter, FilterConfig& filter)
{
- FilterDlg filterDlg(nullptr,
+ FilterDlg filterDlg(parent,
isGlobalFilter, //is main filter dialog
filter);
return static_cast<ReturnSmallDlg::ButtonPressed>(filterDlg.ShowModal());
@@ -417,12 +414,13 @@ void DeleteDialog::OnUseRecycler(wxCommandEvent& event)
}
-ReturnSmallDlg::ButtonPressed zen::showDeleteDialog(const std::vector<zen::FileSystemObject*>& rowsOnLeft,
+ReturnSmallDlg::ButtonPressed zen::showDeleteDialog(wxWindow* parent,
+ const std::vector<zen::FileSystemObject*>& rowsOnLeft,
const std::vector<zen::FileSystemObject*>& rowsOnRight,
bool& deleteOnBothSides,
bool& useRecycleBin)
{
- DeleteDialog confirmDeletion(nullptr,
+ DeleteDialog confirmDeletion(parent,
rowsOnLeft,
rowsOnRight,
deleteOnBothSides,
@@ -440,15 +438,14 @@ public:
const zen::SyncStatistics& statistics,
bool& dontShowAgain);
private:
- void OnClose(wxCloseEvent& event);
- void OnCancel(wxCommandEvent& event);
+ void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
+ void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
void OnStartSync(wxCommandEvent& event);
bool& m_dontShowAgain;
};
-
SyncPreviewDlg::SyncPreviewDlg(wxWindow* parent,
const wxString& variantName,
const zen::SyncStatistics& statistics,
@@ -487,18 +484,6 @@ SyncPreviewDlg::SyncPreviewDlg(wxWindow* parent,
}
-void SyncPreviewDlg::OnClose(wxCloseEvent& event)
-{
- EndModal(ReturnSmallDlg::BUTTON_CANCEL);
-}
-
-
-void SyncPreviewDlg::OnCancel(wxCommandEvent& event)
-{
- EndModal(ReturnSmallDlg::BUTTON_CANCEL);
-}
-
-
void SyncPreviewDlg::OnStartSync(wxCommandEvent& event)
{
m_dontShowAgain = m_checkBoxDontShowAgain->GetValue();
@@ -506,12 +491,12 @@ void SyncPreviewDlg::OnStartSync(wxCommandEvent& event)
}
-ReturnSmallDlg::ButtonPressed zen::showSyncPreviewDlg(
- const wxString& variantName,
- const zen::SyncStatistics& statistics,
- bool& dontShowAgain)
+ReturnSmallDlg::ButtonPressed zen::showSyncPreviewDlg(wxWindow* parent,
+ const wxString& variantName,
+ const zen::SyncStatistics& statistics,
+ bool& dontShowAgain)
{
- SyncPreviewDlg preview(nullptr,
+ SyncPreviewDlg preview(parent,
variantName,
statistics,
dontShowAgain);
@@ -524,13 +509,12 @@ ReturnSmallDlg::ButtonPressed zen::showSyncPreviewDlg(
class CompareCfgDialog : public CmpCfgDlgGenerated
{
public:
- CompareCfgDialog(wxWindow* parent,
- CompConfig& cmpConfig);
+ CompareCfgDialog(wxWindow* parent, CompConfig& cmpConfig);
private:
void OnOkay(wxCommandEvent& event);
- void OnClose(wxCloseEvent& event) { EndModal(0); }
- void OnCancel(wxCommandEvent& event) { EndModal(0); }
+ void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
+ void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
void OnShowHelp(wxCommandEvent& event);
void OnTimeSize(wxCommandEvent& event) { m_radioBtnSizeDate->SetValue(true); }
@@ -632,10 +616,9 @@ void CompareCfgDialog::OnShowHelp(wxCommandEvent& event)
}
-ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog(CompConfig& cmpConfig)
+ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog(wxWindow* parent, CompConfig& cmpConfig)
{
- CompareCfgDialog syncDlg(nullptr, cmpConfig);
-
+ CompareCfgDialog syncDlg(parent, cmpConfig);
return static_cast<ReturnSmallDlg::ButtonPressed>(syncDlg.ShowModal());
}
//########################################################################################
@@ -650,8 +633,8 @@ private:
void OnOkay(wxCommandEvent& event);
void OnResetDialogs(wxCommandEvent& event);
void OnDefault(wxCommandEvent& event);
- void OnCancel(wxCommandEvent& event);
- void OnClose(wxCloseEvent& event);
+ void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
+ void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
void OnAddRow(wxCommandEvent& event);
void OnRemoveRow(wxCommandEvent& event);
void OnResize(wxSizeEvent& event);
@@ -741,7 +724,7 @@ void GlobalSettingsDlg::OnOkay(wxCommandEvent& event)
void GlobalSettingsDlg::OnResetDialogs(wxCommandEvent& event)
{
- if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL,
+ if (showQuestionDlg(this, ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL,
_("Make hidden dialogs and warning messages visible again?")) == ReturnQuestionDlg::BUTTON_YES)
settings.optDialogs.resetDialogs();
}
@@ -758,18 +741,6 @@ void GlobalSettingsDlg::OnDefault(wxCommandEvent& event)
}
-void GlobalSettingsDlg::OnCancel(wxCommandEvent& event)
-{
- EndModal(0);
-}
-
-
-void GlobalSettingsDlg::OnClose(wxCloseEvent& event)
-{
- EndModal(0);
-}
-
-
void GlobalSettingsDlg::set(const xmlAccess::ExternalApps& extApp)
{
auto extAppTmp = extApp;
@@ -835,9 +806,9 @@ void GlobalSettingsDlg::OnRemoveRow(wxCommandEvent& event)
}
-ReturnSmallDlg::ButtonPressed zen::showGlobalSettingsDlg(xmlAccess::XmlGlobalSettings& globalSettings)
+ReturnSmallDlg::ButtonPressed zen::showGlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings)
{
- GlobalSettingsDlg settingsDlg(nullptr, globalSettings);
+ GlobalSettingsDlg settingsDlg(parent, globalSettings);
return static_cast<ReturnSmallDlg::ButtonPressed>(settingsDlg.ShowModal());
}
//########################################################################################
@@ -850,8 +821,8 @@ public:
private:
void OnOkay(wxCommandEvent& event);
- void OnCancel(wxCommandEvent& event) { EndModal(0); }
- void OnClose(wxCloseEvent& event) { EndModal(0); }
+ void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
+ void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
virtual void OnChangeSelectionFrom(wxCalendarEvent& event)
{
@@ -960,8 +931,8 @@ void SelectTimespanDlg::OnOkay(wxCommandEvent& event)
}
-ReturnSmallDlg::ButtonPressed zen::showSelectTimespanDlg(Int64& timeFrom, Int64& timeTo)
+ReturnSmallDlg::ButtonPressed zen::showSelectTimespanDlg(wxWindow* parent, Int64& timeFrom, Int64& timeTo)
{
- SelectTimespanDlg timeSpanDlg(nullptr, timeFrom, timeTo);
+ SelectTimespanDlg timeSpanDlg(parent, timeFrom, timeTo);
return static_cast<ReturnSmallDlg::ButtonPressed>(timeSpanDlg.ShowModal());
}
diff --git a/ui/small_dlgs.h b/ui/small_dlgs.h
index b42f56eb..98a072cf 100644
--- a/ui/small_dlgs.h
+++ b/ui/small_dlgs.h
@@ -13,6 +13,8 @@
namespace zen
{
+//parent window, optional: support correct dialog placement above parent on multiple monitor systems
+
struct ReturnSmallDlg
{
enum ButtonPressed
@@ -22,27 +24,26 @@ struct ReturnSmallDlg
};
};
+void showAboutDialog(wxWindow* parent);
-void showAboutDialog();
-
-ReturnSmallDlg::ButtonPressed showFilterDialog(bool isGlobalFilter, FilterConfig& filter);
+ReturnSmallDlg::ButtonPressed showFilterDialog(wxWindow* parent, bool isGlobalFilter, FilterConfig& filter);
-ReturnSmallDlg::ButtonPressed showDeleteDialog(
- const std::vector<FileSystemObject*>& rowsOnLeft,
- const std::vector<FileSystemObject*>& rowsOnRight,
- bool& deleteOnBothSides,
- bool& useRecycleBin);
+ReturnSmallDlg::ButtonPressed showDeleteDialog(wxWindow* parent,
+ const std::vector<FileSystemObject*>& rowsOnLeft,
+ const std::vector<FileSystemObject*>& rowsOnRight,
+ bool& deleteOnBothSides,
+ bool& useRecycleBin);
-ReturnSmallDlg::ButtonPressed showSyncPreviewDlg(
- const wxString& variantName,
- const SyncStatistics& statistics,
- bool& dontShowAgain);
+ReturnSmallDlg::ButtonPressed showSyncPreviewDlg(wxWindow* parent,
+ const wxString& variantName,
+ const SyncStatistics& statistics,
+ bool& dontShowAgain);
-ReturnSmallDlg::ButtonPressed showCompareCfgDialog(CompConfig& cmpConfig);
+ReturnSmallDlg::ButtonPressed showCompareCfgDialog(wxWindow* parent, CompConfig& cmpConfig);
-ReturnSmallDlg::ButtonPressed showGlobalSettingsDlg(xmlAccess::XmlGlobalSettings& globalSettings);
+ReturnSmallDlg::ButtonPressed showGlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings);
-ReturnSmallDlg::ButtonPressed showSelectTimespanDlg(Int64& timeFrom, Int64& timeTo);
+ReturnSmallDlg::ButtonPressed showSelectTimespanDlg(wxWindow* parent, Int64& timeFrom, Int64& timeTo);
}
#endif // SMALLDIALOGS_H_INCLUDED
diff --git a/ui/sorting.h b/ui/sorting.h
index 807a9ce3..ad54bfbe 100644
--- a/ui/sorting.h
+++ b/ui/sorting.h
@@ -156,16 +156,19 @@ bool lessExtension(const FileSystemObject& a, const FileSystemObject& b)
else if (b.isEmpty<side>())
return true; //empty rows always last
-
- const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
- const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
-
- if (!fileObjA)
+ if (dynamic_cast<const DirMapping*>(&a))
return false; //directories last
- else if (!fileObjB)
+ else if (dynamic_cast<const DirMapping*>(&b))
return true; //directories last
- return makeSortDirection(LessFilename(), Int2Type<ascending>())(fileObjA->getExtension<side>(), fileObjB->getExtension<side>());
+ auto getExtension = [&](const FileSystemObject& fsObj) -> Zstring
+ {
+ const Zstring& shortName = fsObj.getShortName<side>();
+ const size_t pos = shortName.rfind(Zchar('.'));
+ return pos == Zstring::npos ? Zstring() : Zstring(shortName.c_str() + pos + 1);
+ };
+
+ return makeSortDirection(LessFilename(), Int2Type<ascending>())(getExtension(a), getExtension(b));
}
diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp
index 4f6df013..87e1b44d 100644
--- a/ui/sync_cfg.cpp
+++ b/ui/sync_cfg.cpp
@@ -26,7 +26,7 @@ using namespace xmlAccess;
class SyncCfgDialog : public SyncCfgDlgGenerated
{
public:
- SyncCfgDialog(wxWindow* window,
+ SyncCfgDialog(wxWindow* parent,
CompareVariant compareVar,
SyncConfig& syncCfg,
xmlAccess::OnGuiError* handleError, //
@@ -50,9 +50,9 @@ private:
virtual void OnDifferent( wxCommandEvent& event);
virtual void OnConflict( wxCommandEvent& event);
- virtual void OnClose( wxCloseEvent& event) { EndModal(0); }
- virtual void OnCancel( wxCommandEvent& event) { EndModal(0); }
- virtual void OnApply( wxCommandEvent& event);
+ virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSyncConfig::BUTTON_CANCEL); }
+ virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSyncConfig::BUTTON_CANCEL); }
+ virtual void OnApply (wxCommandEvent& event);
void updateGui();
@@ -194,12 +194,12 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
}
-SyncCfgDialog::SyncCfgDialog(wxWindow* window,
+SyncCfgDialog::SyncCfgDialog(wxWindow* parent,
CompareVariant compareVar,
SyncConfig& syncCfg,
xmlAccess::OnGuiError* handleError,
ExecWhenFinishedCfg* execWhenFinished) :
- SyncCfgDlgGenerated(window),
+ SyncCfgDlgGenerated(parent),
cmpVariant(compareVar),
currentDirectionCfg(syncCfg.directionCfg), //make working copy
syncCfgOut(syncCfg),
@@ -529,12 +529,13 @@ void SyncCfgDialog::OnConflict(wxCommandEvent& event)
}
-ReturnSyncConfig::ButtonPressed zen::showSyncConfigDlg(CompareVariant compareVar,
+ReturnSyncConfig::ButtonPressed zen::showSyncConfigDlg(wxWindow* parent,
+ CompareVariant compareVar,
SyncConfig& syncCfg,
xmlAccess::OnGuiError* handleError, //
ExecWhenFinishedCfg* execWhenFinished) //optional input parameter
{
- SyncCfgDialog syncDlg(nullptr,
+ SyncCfgDialog syncDlg(parent,
compareVar,
syncCfg,
handleError,
diff --git a/ui/sync_cfg.h b/ui/sync_cfg.h
index dae79d1d..3d5eb88c 100644
--- a/ui/sync_cfg.h
+++ b/ui/sync_cfg.h
@@ -7,8 +7,10 @@
#ifndef SYNCCONFIG_H_INCLUDED
#define SYNCCONFIG_H_INCLUDED
+#include <wx/window.h>
#include "../lib/process_xml.h"
+
namespace zen
{
struct ReturnSyncConfig
@@ -16,7 +18,7 @@ struct ReturnSyncConfig
enum ButtonPressed
{
BUTTON_CANCEL,
- BUTTON_OKAY = 1
+ BUTTON_OKAY
};
};
@@ -28,7 +30,8 @@ struct ExecWhenFinishedCfg
};
-ReturnSyncConfig::ButtonPressed showSyncConfigDlg(CompareVariant compareVar,
+ReturnSyncConfig::ButtonPressed showSyncConfigDlg(wxWindow* parent,
+ CompareVariant compareVar,
SyncConfig& syncCfg,
xmlAccess::OnGuiError* handleError, //
ExecWhenFinishedCfg* execWhenFinished); //optional input parameter
diff --git a/ui/taskbar.cpp b/ui/taskbar.cpp
index 7219be14..0611d739 100644
--- a/ui/taskbar.cpp
+++ b/ui/taskbar.cpp
@@ -24,7 +24,7 @@ using namespace zen;
using namespace tbseven;
-class Taskbar::Pimpl //throw (TaskbarNotAvailable)
+class Taskbar::Pimpl //throw TaskbarNotAvailable
{
public:
Pimpl(const wxTopLevelWindow& window) :
@@ -145,7 +145,7 @@ public:
//########################################################################################################
Taskbar::Taskbar(const wxTopLevelWindow& window) : pimpl_(new Pimpl(window)) {} //throw TaskbarNotAvailable
-Taskbar::~Taskbar() {} //std::unique_ptr ...
+Taskbar::~Taskbar() {}
void Taskbar::setStatus(Status status) { pimpl_->setStatus(status); }
void Taskbar::setProgress(double fraction) { pimpl_->setProgress(fraction); }
diff --git a/ui/taskbar.h b/ui/taskbar.h
index bf40adde..048bf9e8 100644
--- a/ui/taskbar.h
+++ b/ui/taskbar.h
@@ -11,7 +11,7 @@
#include <wx/toplevel.h>
/*
-Windows 7; show progress in windows superbar via ITaskbarList3 Interface (http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx)
+Windows 7; show progress in windows superbar via ITaskbarList3 Interface: http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx
Ubuntu: use Unity interface (optional)
diff --git a/ui/tray_icon.cpp b/ui/tray_icon.cpp
index 51441e36..2fc76f15 100644
--- a/ui/tray_icon.cpp
+++ b/ui/tray_icon.cpp
@@ -185,9 +185,10 @@ private:
FfsTrayIcon::FfsTrayIcon() :
- trayIcon(new TaskBarImpl(*this))
+ trayIcon(new TaskBarImpl(*this)),
+ fractionLast(1) //show FFS logo by default
{
- trayIcon->SetIcon(generateIcon(0), wxT("FreeFileSync"));
+ trayIcon->SetIcon(generateIcon(fractionLast), L"FreeFileSync");
trayIcon->Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(FfsTrayIcon::OnDoubleClick), nullptr, this); //register double-click
}
@@ -204,23 +205,30 @@ FfsTrayIcon::~FfsTrayIcon()
}
-void FfsTrayIcon::setToolTip(const wxString& toolTipText, double fraction)
+void FfsTrayIcon::setToolTip(const wxString& toolTip)
{
- trayIcon->SetIcon(generateIcon(fraction), toolTipText);
+ toolTipLast = toolTip;
+ trayIcon->SetIcon(generateIcon(fractionLast), toolTip); //another wxWidgets design bug: non-orthogonal method!
+}
+
+
+void FfsTrayIcon::setProgress(double fraction)
+{
+ fractionLast = fraction;
+ trayIcon->SetIcon(generateIcon(fraction), toolTipLast);
}
void FfsTrayIcon::OnContextMenuSelection(wxCommandEvent& event)
{
- const Selection eventId = static_cast<Selection>(event.GetId());
- switch (eventId)
+ 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();
+ zen::showAboutDialog(nullptr);
trayIcon->SetEvtHandlerEnabled(true);
}
break;
diff --git a/ui/tray_icon.h b/ui/tray_icon.h
index d1522602..50480b54 100644
--- a/ui/tray_icon.h
+++ b/ui/tray_icon.h
@@ -19,7 +19,8 @@ public:
FfsTrayIcon();
~FfsTrayIcon();
- void setToolTip(const wxString& toolTipText, double fraction = 0); //number between [0, 1], for small progress indicator
+ void setToolTip(const wxString& toolTip);
+ void setProgress(double fraction); //number between [0, 1], for small progress indicator
private:
FfsTrayIcon(const FfsTrayIcon&);
@@ -30,6 +31,9 @@ private:
class TaskBarImpl;
TaskBarImpl* trayIcon; //actual tray icon (don't use inheritance to enable delayed deletion)
+
+ wxString toolTipLast;
+ double fractionLast;
};
#endif // TRAYICON_H_INCLUDED
diff --git a/ui/tree_view.cpp b/ui/tree_view.cpp
index 49548142..b3a9595a 100644
--- a/ui/tree_view.cpp
+++ b/ui/tree_view.cpp
@@ -23,10 +23,10 @@ inline
void TreeView::compressNode(Container& cont) //remove single-element sub-trees -> gain clarity + usability (call *after* inclusion check!!!)
{
if (cont.subDirs.empty() || //single files node or...
- (cont.firstFile == nullptr && //single dir node...
- cont.subDirs.size() == 1 && //
+ (cont.firstFile == nullptr && //single dir node...
+ cont.subDirs.size() == 1 && //
cont.subDirs[0].firstFile == nullptr && //...that is empty
- cont.subDirs[0].subDirs.empty())) //
+ cont.subDirs[0].subDirs.empty())) //
{
cont.subDirs.clear();
cont.firstFile = nullptr;
@@ -624,7 +624,7 @@ public:
fileIcon(IconBuffer(IconBuffer::SIZE_SMALL).genericFileIcon()),
dirIcon (IconBuffer(IconBuffer::SIZE_SMALL).genericDirIcon ()),
rootBmp(GlobalResources::getImage(L"rootFolder").ConvertToImage().Scale(fileIcon.GetWidth(), fileIcon.GetHeight(), wxIMAGE_QUALITY_HIGH)),
- widthNodeIcon(fileIcon.GetWidth()),
+ widthNodeIcon(dirIcon.GetWidth()),
widthLevelStep(widthNodeIcon),
widthNodeStatus(GlobalResources::getImage(L"nodeExpanded").GetWidth()),
grid_(grid),
diff --git a/ui/tree_view.h b/ui/tree_view.h
index 3bb741e6..01c737bc 100644
--- a/ui/tree_view.h
+++ b/ui/tree_view.h
@@ -151,7 +151,7 @@ private:
/* /|\
| (update...)
| */
- std::vector<RootNodeImpl> folderCmpView; //partial view on folderCmp -> unsorted(cannot be, because of files!)
+ std::vector<RootNodeImpl> folderCmpView; //partial view on folderCmp -> unsorted (cannot be, because files are not a separate entity)
/* /|\
| (update...)
| */
bgstack15