From b338e29fd3eaf700f8c8360aa0310048ba941d54 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:12:46 +0200 Subject: 3.19 --- ui/batch_config.cpp | 241 ++++++------ ui/batch_status_handler.cpp | 74 ++-- ui/batch_status_handler.h | 8 +- ui/folder_pair.h | 29 +- ui/gui_generated.cpp | 177 +++++---- ui/gui_generated.h | 144 +------ ui/gui_status_handler.cpp | 86 +++-- ui/gui_status_handler.h | 8 +- ui/main_dlg.cpp | 907 ++++++++++++++++++++++++++------------------ ui/main_dlg.h | 35 +- ui/progress_indicator.cpp | 72 ++-- ui/progress_indicator.h | 4 +- ui/small_dlgs.cpp | 106 ++---- ui/small_dlgs.h | 1 - ui/sorting.h | 1 - ui/sync_cfg.cpp | 50 ++- 16 files changed, 1002 insertions(+), 941 deletions(-) (limited to 'ui') diff --git a/ui/batch_config.cpp b/ui/batch_config.cpp index 557cb229..c6aa4df7 100644 --- a/ui/batch_config.cpp +++ b/ui/batch_config.cpp @@ -15,7 +15,7 @@ #include "gui_generated.h" #include #include -//#include "../shared/util.h" +#include "../shared/custom_button.h" #include "../shared/wx_choice_enum.h" #include "../shared/mouse_move_dlg.h" @@ -47,7 +47,7 @@ private: void OnGlobalFilterOpenContext(wxCommandEvent& event); void OnGlobalFilterRemConfirm(wxCommandEvent& event); - virtual void OnCheckSilent( wxCommandEvent& event); + virtual void OnCheckSaveLog( wxCommandEvent& event); virtual void OnChangeMaxLogCountTxt(wxCommandEvent& event); virtual void OnClose( wxCloseEvent& event); virtual void OnCancel( wxCommandEvent& event); @@ -70,14 +70,15 @@ private: //error handling //xmlAccess::OnError getSelectionHandleError() const; -> obsolete, use getEnumVal() - void setSelectionHandleError(const xmlAccess::OnError value); + void setSelectionHandleError(xmlAccess::OnError value); void OnChangeErrorHandling(wxCommandEvent& event); bool saveBatchFile(const wxString& filename); void loadBatchFile(const wxString& filename); - void loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg); + void loadBatchFile(const std::vector& filenames); - xmlAccess::XmlBatchConfig getCurrentConfiguration() const; + void setConfig(const xmlAccess::XmlBatchConfig& batchCfg); + xmlAccess::XmlBatchConfig getConfig() const; std::shared_ptr firstFolderPair; //always bound!!! std::vector additionalFolderPairs; @@ -127,7 +128,7 @@ private: virtual MainConfiguration getMainConfig() const { - return batchDlg.getCurrentConfiguration().mainCfg; + return batchDlg.getConfig().mainCfg; } virtual void OnAltSyncCfgChange() @@ -210,7 +211,7 @@ BatchDialog::BatchDialog(wxWindow* window, const xmlAccess::XmlBatchConfig& batc BatchDlgGenerated(window) { init(); - loadBatchCfg(batchCfg); + setConfig(batchCfg); } @@ -253,7 +254,7 @@ void BatchDialog::init() setupFileDrop(*this); Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(BatchDialog::OnFilesDropped), NULL, this); - logfileDir.reset(new DirectoryName(*m_panelLogging, *m_dirPickerLogfileDir, *m_textCtrlLogfileDir, sbSizerLogfileDir)); + logfileDir.reset(new DirectoryName(*m_panelBatchSettings, *m_dirPickerLogfileDir, *m_textCtrlLogfileDir)); //set icons for this dialog m_bpButtonAddPair->SetBitmapLabel(GlobalResources::instance().getImage(wxT("addFolderPair"))); @@ -264,16 +265,17 @@ void BatchDialog::init() //------------------- error handling -------------------------- -void BatchDialog::setSelectionHandleError(const xmlAccess::OnError value) +void BatchDialog::setSelectionHandleError(xmlAccess::OnError value) { - if (m_checkBoxSilent->GetValue()) - setEnumVal(enumDescrMap, *m_choiceHandleError, value); - else - { - EnumDescrList tmp(enumDescrMap); - tmp.descrList.pop_back(); //remove "Exit instantly" -> this option shall be available for silent mode only! - setEnumVal(tmp, *m_choiceHandleError, value); - } + // if (m_checkBoxSilent->GetValue()) + setEnumVal(enumDescrMap, *m_choiceHandleError, value); + /* else + { + EnumDescrList tmp(enumDescrMap); + tmp.descrList.pop_back(); //remove "Exit instantly" -> this option shall be available for silent mode only! + setEnumVal(tmp, *m_choiceHandleError, value); + } + */ } void BatchDialog::OnChangeErrorHandling(wxCommandEvent& event) @@ -284,13 +286,11 @@ void BatchDialog::OnChangeErrorHandling(wxCommandEvent& event) void BatchDialog::OnCmpSettings(wxCommandEvent& event) { - //show window right next to the compare-config button - wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); - windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; + //wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); + //windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; - if (zen::showCompareCfgDialog(windowPos, - localBatchCfg.mainCfg.compareVar, + if (zen::showCompareCfgDialog(localBatchCfg.mainCfg.compareVar, localBatchCfg.mainCfg.handleSymlinks) == ReturnSmallDlg::BUTTON_OKAY) { updateGui(); @@ -323,12 +323,11 @@ void BatchDialog::OnConfigureFilter(wxCommandEvent& event) void BatchDialog::updateGui() //re-evaluate gui after config changes { - xmlAccess::XmlBatchConfig cfg = getCurrentConfiguration(); + xmlAccess::XmlBatchConfig cfg = getConfig(); - showNotebookpage(m_panelLogging, _("Logging"), cfg.silent); + //showNotebookpage(m_panelLogging, _("Logging"), cfg.silent); - m_textCtrlLogfileDir ->Enable(cfg.logFileCountMax > 0); - m_dirPickerLogfileDir->Enable(cfg.logFileCountMax > 0); + m_panelLogfile->Enable(cfg.logFileCountMax > 0); //update compare variant name m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(cfg.mainCfg.compareVar) + wxT(")")); @@ -339,12 +338,12 @@ void BatchDialog::updateGui() //re-evaluate gui after config changes //set filter icon if (isNullFilter(cfg.mainCfg.globalFilter)) { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOff"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOff"))); m_bpButtonFilter->SetToolTip(_("No filter selected")); } else { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOn"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOn"))); m_bpButtonFilter->SetToolTip(_("Filter is active")); } @@ -354,13 +353,14 @@ void BatchDialog::updateGui() //re-evaluate gui after config changes void BatchDialog::OnGlobalFilterOpenContext(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Clear filter settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BatchDialog::OnGlobalFilterRemConfirm), NULL, this); + + wxMenuItem* itemClear = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Clear filter settings")); + contextMenu->Append(itemClear); + contextMenu->Connect(itemClear->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(BatchDialog::OnGlobalFilterRemConfirm), NULL, this); if (isNullFilter(localBatchCfg.mainCfg.globalFilter)) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemClear->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway PopupMenu(contextMenu.get()); //show context menu } @@ -373,12 +373,12 @@ void BatchDialog::OnGlobalFilterRemConfirm(wxCommandEvent& event) } -void BatchDialog::OnCheckSilent(wxCommandEvent& event) +void BatchDialog::OnCheckSaveLog(wxCommandEvent& event) { updateGui(); //reset error handling depending on "m_checkBoxSilent" - setSelectionHandleError(getEnumVal(enumDescrMap, *m_choiceHandleError)); + //setSelectionHandleError(getEnumVal(enumDescrMap, *m_choiceHandleError)); } @@ -393,37 +393,14 @@ void BatchDialog::OnFilesDropped(FFSFileDropEvent& event) if (event.getFiles().empty()) return; - std::vector fileList = event.getFiles(); + const std::vector& fileList = event.getFiles(); switch (xmlAccess::getMergeType(fileList)) //throw () { case xmlAccess::MERGE_BATCH: case xmlAccess::MERGE_GUI: case xmlAccess::MERGE_GUI_BATCH: - if (fileList.size() == 1) - { - loadBatchFile(fileList[0]); - return; - } - else - { - xmlAccess::XmlBatchConfig batchCfg; - try - { - convertConfig(fileList, batchCfg); //throw (xmlAccess::FfsXmlError) - } - catch (const xmlAccess::FfsXmlError& error) - { - if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) - wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); - else - { - wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); - return; - } - } - loadBatchCfg(batchCfg); - } + loadBatchFile(fileList); break; case xmlAccess::MERGE_OTHER: @@ -494,19 +471,15 @@ void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) defaultFileName.Replace(wxT(".ffs_gui"), wxT(".ffs_batch"), false); - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("FreeFileSync batch file")) + wxT(" (*.ffs_batch)|*.ffs_batch"), wxFD_SAVE); //creating this on freestore leads to memleak! + wxFileDialog filePicker(this, + wxEmptyString, + wxEmptyString, + defaultFileName, + wxString(_("FreeFileSync batch file")) + wxT(" (*.ffs_batch)|*.ffs_batch"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) { const wxString newFileName = filePicker.GetPath(); - if (zen::fileExists(wxToZ(newFileName))) - { - if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL, - wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")) != ReturnQuestionDlg::BUTTON_YES) - { - OnSaveBatchJob(event); //retry - return; - } - } //create batch file if (saveBatchFile(newFileName)) @@ -517,9 +490,20 @@ void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) void BatchDialog::OnLoadBatchJob(wxCommandEvent& event) { - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, wxEmptyString, wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_batch;*.ffs_gui)|*.ffs_batch;*.ffs_gui"), wxFD_OPEN); //creating this on freestore leads to memleak! + wxFileDialog filePicker(this, + wxEmptyString, + beforeLast(proposedBatchFileName, FILE_NAME_SEPARATOR), //set default dir: empty string if "currentConfigFileName" is empty or has no path separator + wxEmptyString, + wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_batch;*.ffs_gui)|*.ffs_batch;*.ffs_gui"), + wxFD_OPEN | wxFD_MULTIPLE); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) - loadBatchFile(filePicker.GetPath()); + { + wxArrayString tmp; + filePicker.GetPaths(tmp); + std::vector fileNames(tmp.begin(), tmp.end()); + + loadBatchFile(fileNames); + } } @@ -527,44 +511,16 @@ void BatchDialog::OnLoadBatchJob(wxCommandEvent& event) inline FolderPairEnh getEnhancedPair(const DirectoryPairBatch* panel) { - return FolderPairEnh(wxToZ(panel->getLeftDir()), - wxToZ(panel->getRightDir()), + return FolderPairEnh(toZ(panel->getLeftDir()), + toZ(panel->getRightDir()), panel->getAltSyncConfig(), panel->getAltFilterConfig()); } -xmlAccess::XmlBatchConfig BatchDialog::getCurrentConfiguration() const -{ - xmlAccess::XmlBatchConfig batchCfg = localBatchCfg; - - //load parameter with ownership within wxWidgets controls... - - //first folder pair - batchCfg.mainCfg.firstPair = FolderPairEnh(wxToZ(firstFolderPair->getLeftDir()), - wxToZ(firstFolderPair->getRightDir()), - firstFolderPair->getAltSyncConfig(), - firstFolderPair->getAltFilterConfig()); - - //add additional pairs - batchCfg.mainCfg.additionalPairs.clear(); - std::transform(additionalFolderPairs.begin(), additionalFolderPairs.end(), - std::back_inserter(batchCfg.mainCfg.additionalPairs), getEnhancedPair); - - - //load structure with batch settings "batchCfg" - batchCfg.silent = m_checkBoxSilent->GetValue(); - batchCfg.logFileDirectory = logfileDir->getName(); - batchCfg.logFileCountMax = m_spinCtrlLogCountMax->GetValue(); - batchCfg.handleError = getEnumVal(enumDescrMap, *m_choiceHandleError); - - return batchCfg; -} - - bool BatchDialog::saveBatchFile(const wxString& filename) { - const xmlAccess::XmlBatchConfig batchCfg = getCurrentConfiguration(); + const xmlAccess::XmlBatchConfig batchCfg = getConfig(); //write config to XML try @@ -577,7 +533,7 @@ bool BatchDialog::saveBatchFile(const wxString& filename) return false; } - SetTitle(wxString(_("Create a batch job")) + wxT(" - ") + filename); + SetTitle(filename); proposedBatchFileName = filename; //may be used on next save return true; @@ -586,14 +542,22 @@ bool BatchDialog::saveBatchFile(const wxString& filename) void BatchDialog::loadBatchFile(const wxString& filename) { + std::vector filenames; + filenames.push_back(filename); + loadBatchFile(filenames); +} + + +void BatchDialog::loadBatchFile(const std::vector& filenames) +{ + if (filenames.empty()) + return; + //load XML settings xmlAccess::XmlBatchConfig batchCfg; //structure to receive gui settings try { //open a *.ffs_gui or *.ffs_batch file! - std::vector filenames; - filenames.push_back(filename); - xmlAccess::convertConfig(filenames, batchCfg); //throw (xmlAccess::FfsXmlError) //xmlAccess::readConfig(filename, batchCfg); @@ -609,13 +573,20 @@ void BatchDialog::loadBatchFile(const wxString& filename) } } - SetTitle(wxString(_("Create a batch job")) + wxT(" - ") + filename); - proposedBatchFileName = filename; //may be used on next save - this->loadBatchCfg(batchCfg); + const wxString activeFile = filenames.size() == 1 ? filenames[0] : wxString(); + + if (activeFile.empty()) + SetTitle(_("Create a batch job")); + else + SetTitle(activeFile); + + proposedBatchFileName = activeFile; //may be used on next save + + setConfig(batchCfg); } -void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) +void BatchDialog::setConfig(const xmlAccess::XmlBatchConfig& batchCfg) { wxWindowUpdateLocker dummy(this); //avoid display distortion @@ -623,6 +594,7 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) localBatchCfg = batchCfg; m_checkBoxSilent->SetValue(batchCfg.silent); + //error handling is dependent from m_checkBoxSilent! /|\ \|/ setSelectionHandleError(batchCfg.handleError); @@ -630,8 +602,8 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) m_spinCtrlLogCountMax->SetValue(static_cast(batchCfg.logFileCountMax)); //attention: this one emits a "change value" event!! => updateGui() called implicitly! //set first folder pair - firstFolderPair->setValues(zToWx(batchCfg.mainCfg.firstPair.leftDirectory), - zToWx(batchCfg.mainCfg.firstPair.rightDirectory), + firstFolderPair->setValues(toWx(batchCfg.mainCfg.firstPair.leftDirectory), + toWx(batchCfg.mainCfg.firstPair.rightDirectory), batchCfg.mainCfg.firstPair.altSyncConfig, batchCfg.mainCfg.firstPair.localFilter); @@ -649,19 +621,47 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) } +xmlAccess::XmlBatchConfig BatchDialog::getConfig() const +{ + xmlAccess::XmlBatchConfig batchCfg = localBatchCfg; + + //load parameter with ownership within wxWidgets controls... + + //first folder pair + batchCfg.mainCfg.firstPair = FolderPairEnh(toZ(firstFolderPair->getLeftDir()), + toZ(firstFolderPair->getRightDir()), + firstFolderPair->getAltSyncConfig(), + firstFolderPair->getAltFilterConfig()); + + //add additional pairs + batchCfg.mainCfg.additionalPairs.clear(); + std::transform(additionalFolderPairs.begin(), additionalFolderPairs.end(), + std::back_inserter(batchCfg.mainCfg.additionalPairs), getEnhancedPair); + + + //load structure with batch settings "batchCfg" + batchCfg.silent = m_checkBoxSilent->GetValue(); + batchCfg.logFileDirectory = logfileDir->getName(); + batchCfg.logFileCountMax = m_spinCtrlLogCountMax->GetValue(); + batchCfg.handleError = getEnumVal(enumDescrMap, *m_choiceHandleError); + + return batchCfg; +} + + void BatchDialog::OnAddFolderPair(wxCommandEvent& event) { wxWindowUpdateLocker dummy(this); //avoid display distortion std::vector newPairs; - newPairs.push_back(getCurrentConfiguration().mainCfg.firstPair); + newPairs.push_back(getConfig().mainCfg.firstPair); addFolderPair(newPairs, true); //add pair in front of additonal pairs //clear first pair const FolderPairEnh cfgEmpty; - firstFolderPair->setValues(zToWx(cfgEmpty.leftDirectory), - zToWx(cfgEmpty.rightDirectory), + firstFolderPair->setValues(toWx(cfgEmpty.leftDirectory), + toWx(cfgEmpty.rightDirectory), cfgEmpty.altSyncConfig, cfgEmpty.localFilter); } @@ -690,8 +690,8 @@ void BatchDialog::OnRemoveTopFolderPair(wxCommandEvent& event) const FolderPairEnh cfgSecond = getEnhancedPair(additionalFolderPairs[0]); //reset first pair - firstFolderPair->setValues(zToWx(cfgSecond.leftDirectory), - zToWx(cfgSecond.rightDirectory), + firstFolderPair->setValues(toWx(cfgSecond.leftDirectory), + toWx(cfgSecond.rightDirectory), cfgSecond.altSyncConfig, cfgSecond.localFilter); @@ -723,10 +723,11 @@ void BatchDialog::updateGuiForFolderPair() } //update controls + const int maxAddFolderPairsVisible = 2; int pairHeight = sbSizerMainPair->GetSize().GetHeight(); //respect height of main pair if (additionalFolderPairs.size() > 0) - pairHeight += std::min(1.5, additionalFolderPairs.size()) * //have 0.5 * height indicate that more folders are there + pairHeight += std::min(maxAddFolderPairsVisible + 0.5, additionalFolderPairs.size()) * //have 0.5 * height indicate that more folders are there additionalFolderPairs[0]->GetSize().GetHeight(); m_scrolledWindow6->SetMinSize(wxSize( -1, pairHeight)); @@ -771,8 +772,8 @@ void BatchDialog::addFolderPair(const std::vector& newPairs, newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BatchDialog::OnRemoveFolderPair), NULL, this ); //set alternate configuration - newPair->setValues(zToWx(i->leftDirectory), - zToWx(i->rightDirectory), + newPair->setValues(toWx(i->leftDirectory), + toWx(i->rightDirectory), i->altSyncConfig, i->localFilter); } diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp index 4b4740f9..2cfd43cb 100644 --- a/ui/batch_status_handler.cpp +++ b/ui/batch_status_handler.cpp @@ -41,7 +41,7 @@ public: return Loki::Int2Type(); //DON'T traverse into subdirs } - virtual void onError(const wxString& errorText) {} //errors are not really critical in this context + virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } //errors are not really critical in this context private: const Zstring prefix_; @@ -68,11 +68,11 @@ public: logFile.Open(logfileName, wxT("w")); if (!logFile.IsOpened()) - throw FileError(wxString(_("Unable to create logfile!")) + wxT("\"") + logfileName + wxT("\"")); + throw FileError(_("Unable to create logfile!") + "\"" + logfileName.c_str() + "\""); //write header - wxString headerLine = wxString(wxT("FreeFileSync - ")) + _("Batch execution") + - wxT(" (") + _("Date") + wxT(": ") + wxDateTime::Now().FormatDate() + wxT(")"); //"Date" is used at other places, too + wxString headerLine = L"FreeFileSync - " + _("Batch execution") + + " (" + _("Date") + ": " + wxDateTime::Now().FormatDate() + ")"; //"Date" is used at other places, too logFile.Write(headerLine + wxChar('\n')); logFile.Write(wxString().Pad(headerLine.Len(), wxChar('-')) + wxChar('\n') + wxChar('\n')); @@ -110,9 +110,9 @@ public: void limitLogfileCount(size_t maxCount) const { std::vector logFiles; - FindLogfiles traverseCallback(wxToZ(jobName_), logFiles); + FindLogfiles traverseCallback(toZ(jobName_), logFiles); - traverseFolder(wxToZ(logfileName).BeforeLast(common::FILE_NAME_SEPARATOR), //throw(); + traverseFolder(beforeLast(toZ(logfileName), FILE_NAME_SEPARATOR), //throw(); false, //don't follow symlinks traverseCallback); @@ -131,8 +131,8 @@ private: //create logfile directory Zstring logfileDir = logfileDirectory.empty() ? - wxToZ(zen::getConfigDir() + wxT("Logs")) : - zen::getFormattedDirectoryName(wxToZ(logfileDirectory)); + toZ(zen::getConfigDir() + wxT("Logs")) : + zen::getFormattedDirectoryName(toZ(logfileDirectory)); if (!zen::dirExists(logfileDir)) zen::createDirectory(logfileDir); //create recursively if necessary: may throw (FileError&) @@ -141,7 +141,7 @@ private: if (!logfileDir.EndsWith(FILE_NAME_SEPARATOR)) logfileDir += FILE_NAME_SEPARATOR; - wxString logfileName = zToWx(logfileDir); + wxString logfileName = toWx(logfileDir); //add prefix logfileName += jobName + wxT(" "); @@ -154,7 +154,7 @@ private: wxString output = logfileName + wxT(".log"); //ensure uniqueness - for (int i = 1; zen::somethingExists(wxToZ(output)); ++i) + for (int i = 1; zen::somethingExists(toZ(output)); ++i) output = logfileName + wxChar('_') + zen::toString(i) + wxT(".log"); return output; @@ -171,8 +171,8 @@ private: //############################################################################################################################## BatchStatusHandler::BatchStatusHandler(bool runSilent, const wxString& jobName, - const wxString* logfileDirectory, - size_t logFileMaxCount, + const wxString& logfileDirectory, + size_t logFileCountMax, const xmlAccess::OnError handleError, const SwitchToGui& switchBatchToGui, //functionality to change from batch mode to GUI mode int& returnVal) : @@ -184,12 +184,12 @@ BatchStatusHandler::BatchStatusHandler(bool runSilent, returnValue(returnVal), syncStatusFrame(*this, NULL, SyncStatus::SCANNING, runSilent, jobName) { - if (logfileDirectory && logFileMaxCount > 0) + if (logFileCountMax > 0) { try { - logFile.reset(new LogFile(*logfileDirectory, jobName)); - logFile->limitLogfileCount(logFileMaxCount); + logFile = std::make_shared(logfileDirectory, jobName); //throw FileError + logFile->limitLogfileCount(logFileCountMax); //throw FileError } catch (zen::FileError& error) { @@ -198,8 +198,6 @@ BatchStatusHandler::BatchStatusHandler(bool runSilent, throw BatchAbortProcess(); } } - - assert(runSilent || handleError != xmlAccess::ON_ERROR_EXIT); //shouldn't be selectable from GUI settings } @@ -255,16 +253,6 @@ BatchStatusHandler::~BatchStatusHandler() } -inline -void BatchStatusHandler::reportInfo(const Zstring& text) -{ - if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) //write file transfer information to log - errorLog.logMsg(zToWx(text), TYPE_INFO); //avoid spamming with file copy info: visually identifying warning messages has priority! however when saving to a log file wee need this info - - syncStatusFrame.setStatusText_NoUpdate(text); -} - - void BatchStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, StatusHandler::Process processID) { currentProcess = processID; @@ -290,13 +278,12 @@ void BatchStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, } -inline void BatchStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) { switch (currentProcess) { case StatusHandler::PROCESS_SCANNING: - syncStatusFrame.incScannedObjects_NoUpdate(objectsProcessed); + syncStatusFrame.incScannedObjects_NoUpdate(objectsProcessed); //throw () break; case StatusHandler::PROCESS_COMPARING_CONTENT: case StatusHandler::PROCESS_SYNCHRONIZING: @@ -306,6 +293,18 @@ void BatchStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 da assert(false); break; } + + //note: this method should NOT throw in order to properly allow undoing setting of statistics! +} + + +void BatchStatusHandler::reportInfo(const wxString& text) +{ + if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) //write file transfer information to log + errorLog.logMsg(text, TYPE_INFO); //avoid spamming with file copy info: visually identifying warning messages has priority! however when saving to a log file wee need this info + + syncStatusFrame.setStatusText_NoUpdate(text); + requestUiRefresh(); //throw AbortThisProcess } @@ -320,7 +319,8 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war { case xmlAccess::ON_ERROR_POPUP: { - //show popup and ask user how to handle warning + 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."), @@ -353,14 +353,15 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war } -ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMessage) +ProcessCallback::Response BatchStatusHandler::reportError(const wxString& errorMessage) { switch (handleError_) { case xmlAccess::ON_ERROR_POPUP: { - bool ignoreNextErrors = false; + forceUiRefresh(); + bool ignoreNextErrors = false; switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT, errorMessage, ignoreNextErrors)) @@ -369,10 +370,10 @@ ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMess if (ignoreNextErrors) //falsify only handleError_ = xmlAccess::ON_ERROR_IGNORE; errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; case ReturnErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; + return ProcessCallback::RETRY; case ReturnErrorDlg::BUTTON_ABORT: errorLog.logMsg(errorMessage, TYPE_ERROR); @@ -387,11 +388,11 @@ ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMess case xmlAccess::ON_ERROR_IGNORE: errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; } assert(false); - return ErrorHandler::IGNORE_ERROR; //dummy value + return ProcessCallback::IGNORE_ERROR; //dummy value } @@ -405,7 +406,6 @@ void BatchStatusHandler::reportFatalError(const wxString& errorMessage) } -inline void BatchStatusHandler::forceUiRefresh() { syncStatusFrame.updateStatusDialogNow(); diff --git a/ui/batch_status_handler.h b/ui/batch_status_handler.h index a7c16488..1803019e 100644 --- a/ui/batch_status_handler.h +++ b/ui/batch_status_handler.h @@ -25,8 +25,8 @@ class BatchStatusHandler : public StatusHandler public: BatchStatusHandler(bool runSilent, //defines: -start minimized and -quit immediately when finished const wxString& jobName, - const wxString* logfileDirectory, //non-empty if logging shall be active - size_t logFileMaxCount, + const wxString& logfileDirectory, + size_t logFileCountMax, //0 if logging shall be inactive const xmlAccess::OnError handleError, const zen::SwitchToGui& switchBatchToGui, //functionality to change from batch mode to GUI mode int& returnVal); @@ -34,11 +34,11 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportInfo(const Zstring& text); + virtual void reportInfo(const wxString& text); virtual void forceUiRefresh(); virtual void reportWarning(const wxString& warningMessage, bool& warningActive); - virtual ErrorHandler::Response reportError(const wxString& errorMessage); + virtual Response reportError(const wxString& errorMessage); virtual void reportFatalError(const wxString& errorMessage); private: diff --git a/ui/folder_pair.h b/ui/folder_pair.h index 770aceb3..893acdc7 100644 --- a/ui/folder_pair.h +++ b/ui/folder_pair.h @@ -17,6 +17,7 @@ #include "../shared/util.h" #include "../shared/string_conv.h" #include "../library/norm_filter.h" +#include "../shared/custom_button.h" namespace zen { @@ -50,25 +51,25 @@ public: { if (altSyncConfig.get()) { - basicPanel_.m_bpButtonAltSyncCfg->SetBitmapLabel(GlobalResources::instance().getImage(wxT("syncConfigSmall"))); - basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(wxString(_("Select alternate synchronization settings")) + wxT(" ") + common::LINE_BREAK + + setBitmapLabel(*basicPanel_.m_bpButtonAltSyncCfg, GlobalResources::instance().getImage(wxT("syncConfigSmall"))); + basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(wxString(_("Select alternate synchronization settings")) + wxT(" \n") + wxT("(") + getVariantName(altSyncConfig->syncConfiguration.var) + wxT(")")); } else { - basicPanel_.m_bpButtonAltSyncCfg->SetBitmapLabel(GlobalResources::instance().getImage(wxT("syncConfigSmallGrey"))); + setBitmapLabel(*basicPanel_.m_bpButtonAltSyncCfg, GlobalResources::instance().getImage(wxT("syncConfigSmallGrey"))); basicPanel_.m_bpButtonAltSyncCfg->SetToolTip(_("Select alternate synchronization settings")); } //test for Null-filter if (isNullFilter(localFilter)) { - basicPanel_.m_bpButtonLocalFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterSmallGrey"))); + setBitmapLabel(*basicPanel_.m_bpButtonLocalFilter, GlobalResources::instance().getImage(wxT("filterSmallGrey"))); basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("No filter selected")); } else { - basicPanel_.m_bpButtonLocalFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterSmall"))); + setBitmapLabel(*basicPanel_.m_bpButtonLocalFilter, GlobalResources::instance().getImage(wxT("filterSmall"))); basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("Filter is active")); } } @@ -103,26 +104,28 @@ protected: private: void OnLocalFilterCfgRemove(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Clear filter settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnLocalFilterCfgRemoveConfirm), NULL, this); + + wxMenuItem* itemClear = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Clear filter settings")); + contextMenu->Append(itemClear); + contextMenu->Connect(itemClear->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnLocalFilterCfgRemoveConfirm), NULL, this); if (isNullFilter(localFilter)) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemClear->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway basicPanel_.PopupMenu(contextMenu.get()); //show context menu } void OnAltSyncCfgRemove(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Remove alternate settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemoveConfirm), NULL, this); + + wxMenuItem* itemRemove = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Remove alternate settings")); + contextMenu->Append(itemRemove); + contextMenu->Connect(itemRemove->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemoveConfirm), NULL, this); if (!altSyncConfig.get()) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemRemove->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway basicPanel_.PopupMenu(contextMenu.get()); //show context menu } diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp index c268957e..d3c0bb8e 100644 --- a/ui/gui_generated.cpp +++ b/ui/gui_generated.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Mar 22 2011) +// C++ code generated with wxFormBuilder (version Jun 30 2011) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -439,7 +439,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const bSizerConfig->Add( bSizer151, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_NEEDED_SB|wxLB_SINGLE|wxLB_SORT ); + m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_NEEDED_SB|wxLB_SORT ); m_listBoxHistory->SetToolTip( _("Last used configurations (press DEL to remove from list)") ); m_listBoxHistory->SetMinSize( wxSize( -1,40 ) ); @@ -990,7 +990,7 @@ BatchFolderPairGenerated::~BatchFolderPairGenerated() BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( 460,420 ), wxDefaultSize ); + this->SetSizeHints( wxSize( 560,320 ), wxDefaultSize ); wxBoxSizer* bSizer54; bSizer54 = new wxBoxSizer( wxVERTICAL ); @@ -1021,18 +1021,13 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer87->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer87->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer69->Add( bSizer87, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer69->Add( 0, 5, 0, 0, 5 ); + bSizer87->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); wxBoxSizer* bSizer70; bSizer70 = new wxBoxSizer( wxHORIZONTAL ); m_staticText44 = new wxStaticText( this, wxID_ANY, _("Create a batch file for automated synchronization. To start in batch mode simply double-click the file or execute via command line: FreeFileSync.exe . This can also be scheduled in your operating system's task planner."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText44->Wrap( 500 ); + m_staticText44->Wrap( 460 ); bSizer70->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); m_bpButtonHelp = new wxBitmapButton( this, wxID_HELP, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); @@ -1040,19 +1035,9 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer70->Add( m_bpButtonHelp, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - bSizer69->Add( bSizer70, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer69->Add( 0, 5, 0, 0, 5 ); - - m_staticline10 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer69->Add( m_staticline10, 0, wxEXPAND|wxTOP, 5 ); - - m_staticText531 = new wxStaticText( this, wxID_ANY, _("Configuration overview:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText531->Wrap( -1 ); - m_staticText531->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) ); + bSizer87->Add( bSizer70, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer69->Add( m_staticText531, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer69->Add( bSizer87, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); m_notebookSettings = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); m_panelOverview = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); @@ -1241,26 +1226,10 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer120->Add( 0, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - wxFlexGridSizer* fgSizer15; - fgSizer15 = new wxFlexGridSizer( 1, 2, 10, 10 ); - fgSizer15->SetFlexibleDirection( wxBOTH ); - fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticBoxSizer* sbSizer24; - sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Status feedback") ), wxVERTICAL ); - - - sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_checkBoxSilent = new wxCheckBox( m_panelOverview, wxID_ANY, _("Silent mode"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxSilent->SetToolTip( _("Start minimized and write status information to a logfile") ); - - sbSizer24->Add( m_checkBoxSilent, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 14 ); - - - sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer67->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 10 ); - fgSizer15->Add( sbSizer24, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + wxBoxSizer* bSizer171; + bSizer171 = new wxBoxSizer( wxVERTICAL ); wxStaticBoxSizer* sbSizer25; sbSizer25 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Error handling") ), wxHORIZONTAL ); @@ -1270,60 +1239,83 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_choiceHandleError->SetSelection( 0 ); sbSizer25->Add( m_choiceHandleError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - fgSizer15->Add( sbSizer25, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer171->Add( sbSizer25, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - bSizer120->Add( fgSizer15, 0, 0, 5 ); - - bSizer67->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 10 ); + bSizer67->Add( bSizer171, 0, wxTOP|wxBOTTOM|wxRIGHT, 10 ); m_panelOverview->SetSizer( bSizer67 ); m_panelOverview->Layout(); bSizer67->Fit( m_panelOverview ); m_notebookSettings->AddPage( m_panelOverview, _("Overview"), true ); - m_panelLogging = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panelBatchSettings = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* bSizer117; bSizer117 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer119; - bSizer119 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer172; + bSizer172 = new wxBoxSizer( wxVERTICAL ); - m_staticText120 = new wxStaticText( m_panelLogging, wxID_ANY, _("Select logfile directory:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText120->Wrap( -1 ); - bSizer119->Add( m_staticText120, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + wxStaticBoxSizer* sbSizer24; + sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( m_panelBatchSettings, wxID_ANY, _("Status feedback") ), wxVERTICAL ); - sbSizerLogfileDir = new wxStaticBoxSizer( new wxStaticBox( m_panelLogging, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + m_checkBoxSilent = new wxCheckBox( m_panelBatchSettings, wxID_ANY, _("Run minimized"), wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer24->Add( m_checkBoxSilent, 0, wxALL|wxEXPAND, 5 ); - m_textCtrlLogfileDir = new wxTextCtrl( m_panelLogging, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizerLogfileDir->Add( m_textCtrlLogfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( sbSizer24, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_dirPickerLogfileDir = new FfsDirPickerCtrl( m_panelLogging, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLogfileDir->SetToolTip( _("Select a folder") ); - sbSizerLogfileDir->Add( m_dirPickerLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( 0, 5, 0, 0, 5 ); - bSizer119->Add( sbSizerLogfileDir, 1, wxEXPAND, 5 ); + sbSizerLogfileDir = new wxStaticBoxSizer( new wxStaticBox( m_panelBatchSettings, wxID_ANY, _("Logging") ), wxVERTICAL ); wxBoxSizer* bSizer152; bSizer152 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText96 = new wxStaticText( m_panelLogging, wxID_ANY, _("Maximum number of logfiles:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText96 = new wxStaticText( m_panelBatchSettings, wxID_ANY, _("Maximum number of logfiles:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText96->Wrap( -1 ); - bSizer152->Add( m_staticText96, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer152->Add( m_staticText96, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); bSizer152->Add( 0, 0, 1, wxEXPAND, 5 ); - m_spinCtrlLogCountMax = new wxSpinCtrl( m_panelLogging, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); - bSizer152->Add( m_spinCtrlLogCountMax, 0, wxALL, 5 ); + m_spinCtrlLogCountMax = new wxSpinCtrl( m_panelBatchSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); + bSizer152->Add( m_spinCtrlLogCountMax, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizerLogfileDir->Add( bSizer152, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_panelLogfile = new wxPanel( m_panelBatchSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1721; + bSizer1721 = new wxBoxSizer( wxVERTICAL ); + + m_staticText94 = new wxStaticText( m_panelLogfile, wxID_ANY, _("Select logfile directory:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText94->Wrap( -1 ); + bSizer1721->Add( m_staticText94, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + wxBoxSizer* bSizer170; + bSizer170 = new wxBoxSizer( wxHORIZONTAL ); + + m_textCtrlLogfileDir = new wxTextCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer170->Add( m_textCtrlLogfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerLogfileDir = new FfsDirPickerCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLogfileDir->SetToolTip( _("Select a folder") ); + + bSizer170->Add( m_dirPickerLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer1721->Add( bSizer170, 0, wxEXPAND, 5 ); - bSizer119->Add( bSizer152, 0, wxEXPAND, 5 ); + m_panelLogfile->SetSizer( bSizer1721 ); + m_panelLogfile->Layout(); + bSizer1721->Fit( m_panelLogfile ); + sbSizerLogfileDir->Add( m_panelLogfile, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizer117->Add( bSizer119, 0, wxEXPAND|wxALL, 10 ); + bSizer172->Add( sbSizerLogfileDir, 0, wxEXPAND, 5 ); - m_panelLogging->SetSizer( bSizer117 ); - m_panelLogging->Layout(); - bSizer117->Fit( m_panelLogging ); - m_notebookSettings->AddPage( m_panelLogging, _("Logging"), false ); + bSizer117->Add( bSizer172, 1, wxEXPAND|wxALL, 10 ); + + m_panelBatchSettings->SetSizer( bSizer117 ); + m_panelBatchSettings->Layout(); + bSizer117->Fit( m_panelBatchSettings ); + m_notebookSettings->AddPage( m_panelBatchSettings, _("Batch settings"), false ); bSizer69->Add( m_notebookSettings, 1, wxEXPAND, 5 ); @@ -1364,7 +1356,6 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSyncSettings ), NULL, this ); m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); m_bpButtonRemovePair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRemoveTopFolderPair ), NULL, this ); - m_checkBoxSilent->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckSilent ), NULL, this ); m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_spinCtrlLogCountMax->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BatchDlgGenerated::OnChangeMaxLogCountTxt ), NULL, this ); m_buttonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); @@ -1382,7 +1373,6 @@ BatchDlgGenerated::~BatchDlgGenerated() m_bpButtonSyncConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSyncSettings ), NULL, this ); m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); m_bpButtonRemovePair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRemoveTopFolderPair ), NULL, this ); - m_checkBoxSilent->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckSilent ), NULL, this ); m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_spinCtrlLogCountMax->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BatchDlgGenerated::OnChangeMaxLogCountTxt ), NULL, this ); m_buttonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); @@ -1851,12 +1841,16 @@ SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); m_radioBtnAutomatic->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); m_buttonAutomatic->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_buttonAutomatic->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncAutomaticDouble ), NULL, this ); m_radioBtnMirror->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); m_buttonOneWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); + m_buttonOneWay->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncMirrorDouble ), NULL, this ); m_radioBtnUpdate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); m_buttonUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_buttonUpdate->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncUpdateDouble ), NULL, this ); m_radioBtnCustom->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); m_buttonUpdate1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); + m_buttonUpdate1->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncCustomDouble ), NULL, this ); m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_choiceHandleDeletion->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); @@ -1875,12 +1869,16 @@ SyncCfgDlgGenerated::~SyncCfgDlgGenerated() this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); m_radioBtnAutomatic->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); m_buttonAutomatic->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_buttonAutomatic->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncAutomaticDouble ), NULL, this ); m_radioBtnMirror->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); m_buttonOneWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncMirror ), NULL, this ); + m_buttonOneWay->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncMirrorDouble ), NULL, this ); m_radioBtnUpdate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); m_buttonUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_buttonUpdate->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncUpdateDouble ), NULL, this ); m_radioBtnCustom->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); m_buttonUpdate1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCustom ), NULL, this ); + m_buttonUpdate1->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( SyncCfgDlgGenerated::OnSyncCustomDouble ), NULL, this ); m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_choiceHandleDeletion->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); @@ -1996,8 +1994,10 @@ CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const w this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); m_buttonTimeSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_buttonTimeSize->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnTimeSizeDouble ), NULL, this ); m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); m_buttonContent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_buttonContent->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnContentDouble ), NULL, this ); m_bpButtonHelp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); m_choiceHandleSymlinks->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_button10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnOkay ), NULL, this ); @@ -2010,8 +2010,10 @@ CmpCfgDlgGenerated::~CmpCfgDlgGenerated() this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); m_buttonTimeSize->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_buttonTimeSize->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnTimeSizeDouble ), NULL, this ); m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); m_buttonContent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_buttonContent->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( CmpCfgDlgGenerated::OnContentDouble ), NULL, this ); m_bpButtonHelp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); m_choiceHandleSymlinks->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); m_button10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnOkay ), NULL, this ); @@ -2540,25 +2542,25 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer171->Add( m_hyperlink10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink7 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxWidgets"), wxT("http://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink7->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer171->Add( m_hyperlink7, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink13 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Boost"), wxT("http://www.boost.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink13->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer171->Add( m_hyperlink13, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink14 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxFormBuilder"), wxT("http://wxformbuilder.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink14->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + m_hyperlink7 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxWidgets"), wxT("http://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink7->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - bSizer171->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer171->Add( m_hyperlink7, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hyperlink11 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("MS Visual C++"), wxT("http://msdn.microsoft.com/library/60k1461a.aspx"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink11->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + + bSizer171->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); m_hyperlink16 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Artistic Style"), wxT("http://astyle.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink16->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - bSizer171->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer171->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); bSizer167->Add( bSizer171, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM, 5 ); @@ -2575,26 +2577,21 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer172->Add( m_hyperlink15, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink11 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("MS Visual C++"), wxT("http://msdn.microsoft.com/library/60k1461a.aspx"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink11->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer172->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink12 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Google Test"), wxT("http://code.google.com/p/googletest"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink12->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer172->Add( m_hyperlink12, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink17 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("inotify"), wxT("http://inotify.aiken.cz"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink17->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer172->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink18 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("Unicode NSIS"), wxT("http://www.scratchpaper.com"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink18->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer172->Add( m_hyperlink18, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_hyperlink14 = new wxHyperlinkCtrl( m_panel33, wxID_ANY, _("wxFormBuilder"), wxT("http://wxformbuilder.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink14->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + + bSizer172->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer167->Add( bSizer172, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); bSizerCodeInfo->Add( bSizer167, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); @@ -3026,7 +3023,7 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w bSizer24->Add( bSizer99, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); - m_textCtrlMessage = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrlMessage = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY ); m_textCtrlMessage->SetBackgroundColour( wxColour( 208, 208, 208 ) ); bSizer24->Add( m_textCtrlMessage, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); diff --git a/ui/gui_generated.h b/ui/gui_generated.h index 13a4ea00..1659503c 100644 --- a/ui/gui_generated.h +++ b/ui/gui_generated.h @@ -1,15 +1,16 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Mar 22 2011) +// C++ code generated with wxFormBuilder (version Jun 30 2011) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// -#ifndef __gui_generated__ -#define __gui_generated__ +#ifndef __GUI_GENERATED_H__ +#define __GUI_GENERATED_H__ +#include +#include #include - class CustomComboBox; class CustomGridLeft; class CustomGridMiddle; @@ -85,26 +86,17 @@ protected: wxBoxSizer* bSizerPanelHolder; wxPanel* m_panelTopButtons; wxBoxSizer* bSizerTopButtons; - wxStaticText* m_staticTextCmpVariant; - wxButtonWithImage* m_buttonCompare; wxButton* m_buttonAbort; wxBitmapButton* m_bpButtonCmpConfig; - - wxStaticText* m_staticTextSyncVariant; wxBitmapButton* m_bpButtonSyncConfig; wxButtonWithImage* m_buttonStartSync; - wxPanel* m_panelDirectoryPairs; wxStaticBoxSizer* sbSizerDirLeft; wxPanel* m_panelTopMiddle; - wxBitmapButton* m_bpButtonSwapSides; - - - wxStaticBoxSizer* sbSizerDirRight; wxBitmapButton* m_bpButtonAddPair; wxScrolledWindow* m_scrolledWindowFolderPairs; @@ -117,17 +109,14 @@ protected: CustomGridRight* m_gridRight; wxPanel* m_panelConfig; wxBoxSizer* bSizerConfig; - wxBitmapButton* m_bpButtonSave; wxBitmapButton* m_bpButtonLoad; wxListBox* m_listBoxHistory; wxPanel* m_panelFilter; - wxBitmapButton* m_bpButtonFilter; wxCheckBox* m_checkBoxHideFilt; wxPanel* m_panelStatistics; wxBoxSizer* bSizerStatistics; - wxStaticBitmap* m_bitmapCreate; wxTextCtrl* m_textCtrlCreate; wxStaticBitmap* m_bitmapUpdate; @@ -136,10 +125,8 @@ protected: wxTextCtrl* m_textCtrlDelete; wxStaticBitmap* m_bitmapData; wxTextCtrl* m_textCtrlData; - wxPanel* m_panelViewFilter; wxBoxSizer* bSizerViewFilter; - ToggleButton* m_bpButtonSyncCreateLeft; ToggleButton* m_bpButtonSyncDirOverwLeft; ToggleButton* m_bpButtonSyncDeleteLeft; @@ -154,19 +141,12 @@ protected: ToggleButton* m_bpButtonSyncDirOverwRight; ToggleButton* m_bpButtonSyncCreateRight; ToggleButton* m_bpButtonConflict; - wxPanel* m_panelStatusBar; - wxStaticText* m_staticTextStatusLeft; - wxStaticLine* m_staticline9; - wxStaticText* m_staticTextStatusMiddle; - wxStaticLine* m_staticline10; - wxStaticText* m_staticTextStatusRight; - wxStaticBitmap* m_bitmap15; // Virtual event handlers, overide them in your derived class @@ -248,9 +228,6 @@ private: protected: - - - public: wxPanel* m_panelLeft; wxTextCtrl* m_directoryLeft; @@ -282,7 +259,6 @@ protected: wxPanel* m_panelLeft; wxPanel* m_panelRight; - public: wxBitmapButton* m_bpButtonRemovePair; wxTextCtrl* m_directoryLeft; @@ -309,43 +285,30 @@ protected: wxStaticBitmap* m_bitmap27; wxPanel* m_panel8; wxStaticText* m_staticText56; - - wxStaticText* m_staticText44; wxBitmapButton* m_bpButtonHelp; - - wxStaticLine* m_staticline10; - wxStaticText* m_staticText531; wxNotebook* m_notebookSettings; wxPanel* m_panelOverview; wxBitmapButton* m_bpButtonCmpConfig; - wxStaticText* m_staticTextCmpVariant; - wxBitmapButton* m_bpButtonFilter; - wxStaticText* m_staticTextSyncVariant; - wxBitmapButton* m_bpButtonSyncConfig; - wxBoxSizer* sbSizerMainPair; wxPanel* m_panelMainPair; wxStaticText* m_staticText532; wxStaticText* m_staticText5411; wxBoxSizer* bSizerAddFolderPairs; - - - wxCheckBox* m_checkBoxSilent; - wxChoice* m_choiceHandleError; - wxPanel* m_panelLogging; - wxStaticText* m_staticText120; + wxPanel* m_panelBatchSettings; + wxCheckBox* m_checkBoxSilent; wxStaticBoxSizer* sbSizerLogfileDir; - wxTextCtrl* m_textCtrlLogfileDir; - FfsDirPickerCtrl* m_dirPickerLogfileDir; wxStaticText* m_staticText96; - wxSpinCtrl* m_spinCtrlLogCountMax; + wxPanel* m_panelLogfile; + wxStaticText* m_staticText94; + wxTextCtrl* m_textCtrlLogfileDir; + FfsDirPickerCtrl* m_dirPickerLogfileDir; wxButton* m_buttonSave; wxButton* m_buttonLoad; wxButton* m_button6; @@ -358,7 +321,6 @@ protected: virtual void OnSyncSettings( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddFolderPair( wxCommandEvent& event ) { event.Skip(); } virtual void OnRemoveTopFolderPair( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCheckSilent( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeMaxLogCountTxt( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveBatchJob( wxCommandEvent& event ) { event.Skip(); } @@ -392,7 +354,6 @@ class CompareStatusGenerated : public wxPanel private: protected: - wxBoxSizer* bSizer42; wxBoxSizer* bSizerFilesFound; wxStaticText* m_staticText321; @@ -403,22 +364,18 @@ protected: wxStaticText* m_staticText117; wxStaticText* m_staticTextDataRemaining; wxStaticText* m_staticText118; - wxBoxSizer* sSizerSpeed; wxStaticText* m_staticText104; wxStaticText* m_staticTextSpeed; - wxBoxSizer* sSizerTimeRemaining; wxStaticText* m_staticTextTimeRemFixed; wxStaticText* m_staticTextTimeRemaining; - wxBoxSizer* sSizerTimeElapsed; wxStaticText* m_staticTextTimeElapsed; wxStaticText* m_staticText30; wxTextCtrl* m_textCtrlStatus; wxGauge* m_gauge2; - public: CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER|wxTAB_TRAVERSAL ); @@ -447,7 +404,6 @@ protected: wxRadioButton* m_radioBtnCustom; wxButton* m_buttonUpdate1; wxStaticText* m_staticText9; - wxBoxSizer* bSizer201; wxStaticBoxSizer* sbSizerErrorHandling; wxChoice* m_choiceHandleError; @@ -458,9 +414,6 @@ protected: FfsDirPickerCtrl* m_dirPickerCustomDelFolder; wxButton* m_buttonOK; wxButton* m_button16; - - - wxStaticBitmap* m_bitmapDatabase; wxBoxSizer* sbSizerSyncDirections; wxStaticText* m_staticText21; @@ -468,36 +421,33 @@ protected: wxStaticLine* m_staticline3; wxBoxSizer* bSizerLeftOnly; wxStaticBitmap* m_bitmapLeftOnly; - wxBitmapButton* m_bpButtonLeftOnly; wxBoxSizer* bSizerRightOnly; wxStaticBitmap* m_bitmapRightOnly; - wxBitmapButton* m_bpButtonRightOnly; wxBoxSizer* bSizerLeftNewer; wxStaticBitmap* m_bitmapLeftNewer; - wxBitmapButton* m_bpButtonLeftNewer; wxBoxSizer* bSizerRightNewer; wxStaticBitmap* m_bitmapRightNewer; - wxBitmapButton* m_bpButtonRightNewer; wxBoxSizer* bSizerDifferent; wxStaticBitmap* m_bitmapDifferent; - wxBitmapButton* m_bpButtonDifferent; wxBoxSizer* bSizerConflict; wxStaticBitmap* m_bitmapConflict; - wxBitmapButton* m_bpButtonConflict; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnSyncAutomatic( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncAutomaticDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnSyncMirror( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncMirrorDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnSyncUpdate( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncUpdateDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnSyncCustom( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSyncCustomDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeDeletionHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnApply( wxCommandEvent& event ) { event.Skip(); } @@ -533,7 +483,6 @@ protected: wxButton* m_buttonContent; wxStaticLine* m_staticline14; wxBitmapButton* m_bpButtonHelp; - wxChoice* m_choiceHandleSymlinks; wxButton* m_button10; wxButton* m_button6; @@ -541,7 +490,9 @@ protected: // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnTimeSize( wxCommandEvent& event ) { event.Skip(); } + virtual void OnTimeSizeDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnContent( wxCommandEvent& event ) { event.Skip(); } + virtual void OnContentDouble( wxMouseEvent& event ) { event.Skip(); } virtual void OnShowHelp( wxCommandEvent& event ) { event.Skip(); } virtual void OnChangeErrorHandling( wxCommandEvent& event ) { event.Skip(); } virtual void OnOkay( wxCommandEvent& event ) { event.Skip(); } @@ -563,12 +514,9 @@ class SyncStatusDlgGenerated : public wxFrame private: protected: - - wxStaticBitmap* m_bitmapStatus; wxStaticText* m_staticTextStatus; wxAnimationCtrl* m_animationControl1; - wxBoxSizer* bSizer31; wxBoxSizer* bSizerObjectsRemaining; wxStaticText* m_staticText25; @@ -582,7 +530,6 @@ protected: wxStaticText* m_staticText98; wxStaticText* m_staticTextDataProcessed; wxStaticText* m_staticText99; - wxStaticText* m_staticText55; wxStaticText* m_staticTextTimeElapsed; wxBoxSizer* bSizerProgressText; @@ -591,18 +538,13 @@ protected: wxBoxSizer* bSizerSpeed; wxStaticText* m_staticText108; wxStaticText* m_staticTextSpeed; - - wxButton* m_buttonOK; wxButton* m_buttonPause; wxButton* m_buttonAbort; - wxBoxSizer* bSizerRemTime; - wxStaticText* m_staticText21; wxStaticText* m_staticTextTimeRemaining; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnIconize( wxIconizeEvent& event ) { event.Skip(); } @@ -654,13 +596,9 @@ class HelpDlgGenerated : public wxDialog private: protected: - wxStaticBitmap* m_bitmap25; wxPanel* m_panel8; - wxStaticText* m_staticText56; - - wxNotebook* m_notebook1; wxScrolledWindow* m_scrolledWindow1; wxStaticText* m_staticText59; @@ -705,50 +643,42 @@ class AboutDlgGenerated : public wxDialog private: protected: - wxPanel* m_panel5; wxStaticBitmap* m_bitmap11; wxStaticText* m_build; - wxPanel* m_panel33; wxBoxSizer* bSizerCodeInfo; wxStaticText* m_staticText72; wxHyperlinkCtrl* m_hyperlink9; wxHyperlinkCtrl* m_hyperlink10; - wxHyperlinkCtrl* m_hyperlink7; wxHyperlinkCtrl* m_hyperlink13; - wxHyperlinkCtrl* m_hyperlink14; + wxHyperlinkCtrl* m_hyperlink7; + wxHyperlinkCtrl* m_hyperlink11; wxHyperlinkCtrl* m_hyperlink16; wxHyperlinkCtrl* m_hyperlink8; wxHyperlinkCtrl* m_hyperlink15; - wxHyperlinkCtrl* m_hyperlink11; wxHyperlinkCtrl* m_hyperlink12; - wxHyperlinkCtrl* m_hyperlink17; wxHyperlinkCtrl* m_hyperlink18; + wxHyperlinkCtrl* m_hyperlink14; wxHyperlinkCtrl* m_hyperlink21; wxScrolledWindow* m_scrolledWindowTranslators; wxBoxSizer* bSizerTranslators; wxStaticText* m_staticText54; - wxFlexGridSizer* fgSizerTranslators; wxStaticLine* m_staticline3; wxStaticText* m_staticText131; wxStaticLine* m_staticline12; wxStaticBitmap* m_bitmap9; wxHyperlinkCtrl* m_hyperlink1; - wxHyperlinkCtrl* m_hyperlink3; wxAnimationCtrl* m_animationControl1; wxStaticBitmap* m_bitmap10; wxHyperlinkCtrl* m_hyperlink2; - wxHyperlinkCtrl* m_hyperlink6; wxStaticBitmap* m_bitmapTransl; wxStaticLine* m_staticline2; - wxStaticBitmap* m_bitmap13; wxHyperlinkCtrl* m_hyperlink5; - wxButton* m_buttonOkay; // Virtual event handlers, overide them in your derived class @@ -771,16 +701,13 @@ class ErrorDlgGenerated : public wxDialog private: protected: - wxStaticBitmap* m_bitmap10; wxTextCtrl* m_textCtrl8; wxCheckBox* m_checkBoxIgnoreErrors; - wxButton* m_buttonIgnore; wxButton* m_buttonRetry; wxButton* m_buttonAbort; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnIgnore( wxCommandEvent& event ) { event.Skip(); } @@ -803,15 +730,12 @@ class WarningDlgGenerated : public wxDialog private: protected: - wxTextCtrl* m_textCtrl8; wxCheckBox* m_checkBoxDontShowAgain; - wxButton* m_buttonIgnore; wxButton* m_buttonSwitch; wxButton* m_buttonAbort; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnIgnore( wxCommandEvent& event ) { event.Skip(); } @@ -835,16 +759,13 @@ class QuestionDlgGenerated : public wxDialog private: protected: - wxStaticBitmap* m_bitmap10; wxTextCtrl* m_textCtrl8; wxCheckBox* m_checkBoxDontAskAgain; - wxButton* m_buttonYes; wxButton* m_buttonNo; wxButton* m_buttonCancel; - // Virtual event handlers, overide them in your derived class virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } virtual void OnYes( wxCommandEvent& event ) { event.Skip(); } @@ -867,13 +788,9 @@ class DeleteDlgGenerated : public wxDialog private: protected: - - wxStaticBitmap* m_bitmap12; wxStaticText* m_staticTextHeader; - wxCheckBox* m_checkBoxDeleteBothSides; - wxCheckBox* m_checkBoxUseRecycler; wxTextCtrl* m_textCtrlMessage; wxButton* m_buttonOK; @@ -905,10 +822,8 @@ protected: wxStaticBitmap* m_bitmap26; wxPanel* m_panel8; wxStaticText* m_staticTexHeader; - wxStaticText* m_staticText44; wxBitmapButton* m_bpButtonHelp; - wxPanel* m_panel13; wxStaticLine* m_staticline10; wxStaticText* m_staticText45; @@ -917,12 +832,10 @@ protected: wxStaticText* m_staticText85; wxStaticText* m_staticText181; wxStaticText* m_staticText1811; - wxStaticBitmap* m_bitmapInclude; wxTextCtrl* m_textCtrlInclude; wxStaticBitmap* m_bitmapExclude; wxTextCtrl* m_textCtrlExclude; - wxStaticBitmap* m_bitmapFilterDate; wxStaticText* m_staticText103; wxSpinCtrl* m_spinCtrlTimespan; @@ -935,7 +848,6 @@ protected: wxSpinCtrl* m_spinCtrlMaxSize; wxChoice* m_choiceUnitMaxSize; wxButton* m_button9; - wxButton* m_button10; wxButton* m_button17; @@ -968,7 +880,6 @@ protected: wxBitmapButton* m_bpButton29; wxBitmapButton* m_bpButton30; wxButton* m_button9; - wxButton* m_button28; wxButton* m_button29; @@ -997,24 +908,17 @@ private: protected: wxStaticBitmap* m_bitmapSettings; - wxPanel* m_panel8; wxStaticText* m_staticText56; - wxCheckBox* m_checkBoxCopyLocked; wxCheckBox* m_checkBoxCopyPermissions; wxStaticLine* m_staticline10; wxStaticText* m_staticText100; - wxButtonWithImage* m_buttonResetDialogs; - - wxGrid* m_gridCustomCommand; wxBitmapButton* m_bpButtonAddRow; wxBitmapButton* m_bpButtonRemoveRow; - wxButton* m_button9; - wxButton* m_buttonOkay; wxButton* m_button29; @@ -1047,7 +951,6 @@ protected: wxStaticLine* m_staticline16; wxStaticText* m_staticTextVariant; wxStaticLine* m_staticline14; - wxStaticText* m_staticText94; wxStaticBitmap* m_bitmapCreate; wxTextCtrl* m_textCtrlCreateL; @@ -1059,14 +962,10 @@ protected: wxTextCtrl* m_textCtrlCreateR; wxTextCtrl* m_textCtrlUpdateR; wxTextCtrl* m_textCtrlDeleteR; - wxStaticBitmap* m_bitmapData; - wxTextCtrl* m_textCtrlData; - wxStaticLine* m_staticline12; wxCheckBox* m_checkBoxDontShowAgain; - wxButton* m_button16; // Virtual event handlers, overide them in your derived class @@ -1111,7 +1010,6 @@ private: protected: wxStaticText* m_staticText101; wxTextCtrl* m_textCtrlSearchTxt; - wxCheckBox* m_checkBoxMatchCase; wxButton* m_buttonFindNext; wxButton* m_button29; @@ -1130,4 +1028,4 @@ public: }; -#endif //__gui_generated__ +#endif //__GUI_GENERATED_H__ diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp index 3319d07a..43293829 100644 --- a/ui/gui_status_handler.cpp +++ b/ui/gui_status_handler.cpp @@ -7,7 +7,6 @@ #include "gui_status_handler.h" #include "small_dlgs.h" #include "msg_popup.h" -#include "../shared/system_constants.h" #include "main_dlg.h" #include #include "../shared/global_func.h" @@ -73,12 +72,6 @@ void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event) } -void CompareStatusHandler::reportInfo(const Zstring& text) -{ - mainDlg.compareStatus->setStatusText_NoUpdate(text); -} - - void CompareStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID) { currentProcess = processID; @@ -103,31 +96,39 @@ void CompareStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal } -inline void CompareStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) { switch (currentProcess) { case StatusHandler::PROCESS_SCANNING: - mainDlg.compareStatus->incScannedObjects_NoUpdate(objectsProcessed); + mainDlg.compareStatus->incScannedObjects_NoUpdate(objectsProcessed); //throw () break; case StatusHandler::PROCESS_COMPARING_CONTENT: - mainDlg.compareStatus->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); + mainDlg.compareStatus->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); //throw () break; case StatusHandler::PROCESS_SYNCHRONIZING: case StatusHandler::PROCESS_NONE: assert(false); break; } + + //note: this method should NOT throw in order to properly allow undoing setting of statistics! +} + + +void CompareStatusHandler::reportInfo(const wxString& text) +{ + mainDlg.compareStatus->setStatusText_NoUpdate(text); + requestUiRefresh(); //throw AbortThisProcess } -ErrorHandler::Response CompareStatusHandler::reportError(const wxString& message) +ProcessCallback::Response CompareStatusHandler::reportError(const wxString& message) { if (ignoreErrors) - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; - mainDlg.compareStatus->updateStatusPanelNow(); + forceUiRefresh(); bool ignoreNextErrors = false; switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT, @@ -135,23 +136,23 @@ ErrorHandler::Response CompareStatusHandler::reportError(const wxString& message { case ReturnErrorDlg::BUTTON_IGNORE: ignoreErrors = ignoreNextErrors; - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; case ReturnErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; + return ProcessCallback::RETRY; case ReturnErrorDlg::BUTTON_ABORT: abortThisProcess(); } assert(false); - return ErrorHandler::IGNORE_ERROR; //dummy return value + return ProcessCallback::IGNORE_ERROR; //dummy return value } void CompareStatusHandler::reportFatalError(const wxString& errorMessage) { - mainDlg.compareStatus->updateStatusPanelNow(); + forceUiRefresh(); //show message and abort: currently there are no fatal errors during comparison that can be ignored bool dummy = false; @@ -167,7 +168,7 @@ void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& w if (!warningActive || ignoreErrors) //if errors are ignored, then warnings should also return; - mainDlg.compareStatus->updateStatusPanelNow(); + forceUiRefresh(); //show popup and ask user how to handle warning bool dontWarnAgain = false; @@ -188,7 +189,6 @@ void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& w } -inline void CompareStatusHandler::forceUiRefresh() { mainDlg.compareStatus->updateStatusPanelNow(); @@ -223,9 +223,9 @@ SyncStatusHandler::~SyncStatusHandler() //finalize error log if (abortIsRequested()) - errorLog.logMsg(wxString(_("Synchronization aborted!")) + wxT(" \n") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_ERROR); + errorLog.logMsg(_("Synchronization aborted!") + " \n" + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_ERROR); else if (totalErrors > 0) - errorLog.logMsg(wxString(_("Synchronization completed with errors!")) + wxT(" \n") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_WARNING); + errorLog.logMsg(_("Synchronization completed with errors!") + " \n" + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"), TYPE_WARNING); else errorLog.logMsg(_("Synchronization completed successfully!"), TYPE_INFO); @@ -239,16 +239,6 @@ SyncStatusHandler::~SyncStatusHandler() } -inline -void SyncStatusHandler::reportInfo(const Zstring& text) -{ - //if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) - errorLog.logMsg(zToWx(text), TYPE_INFO); - - syncStatusFrame.setStatusText_NoUpdate(text); -} - - void SyncStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID) { switch (processID) @@ -266,14 +256,26 @@ void SyncStatusHandler::initNewProcess(int objectsTotal, zen::Int64 dataTotal, P } -inline void SyncStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) { - syncStatusFrame.incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); + syncStatusFrame.incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); //throw () + + //note: this method should NOT throw in order to properly allow undoing setting of statistics! +} + + +void SyncStatusHandler::reportInfo(const wxString& text) +{ + //if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) + errorLog.logMsg(text, TYPE_INFO); + + syncStatusFrame.setStatusText_NoUpdate(text); //throw () + + requestUiRefresh(); //throw AbortThisProccess } -ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessage) +ProcessCallback::Response SyncStatusHandler::reportError(const wxString& errorMessage) { switch (handleError_) { @@ -281,10 +283,10 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa break; case ON_GUIERROR_IGNORE: errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; } - syncStatusFrame.updateStatusDialogNow(); + forceUiRefresh(); bool ignoreNextErrors = false; switch (showErrorDlg(ReturnErrorDlg::BUTTON_IGNORE | ReturnErrorDlg::BUTTON_RETRY | ReturnErrorDlg::BUTTON_ABORT, @@ -294,10 +296,10 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa case ReturnErrorDlg::BUTTON_IGNORE: handleError_ = ignoreNextErrors ? ON_GUIERROR_IGNORE : ON_GUIERROR_POPUP; errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; case ReturnErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; + return ProcessCallback::RETRY; case ReturnErrorDlg::BUTTON_ABORT: errorLog.logMsg(errorMessage, TYPE_ERROR); @@ -306,7 +308,7 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa assert (false); errorLog.logMsg(errorMessage, TYPE_ERROR); - return ErrorHandler::IGNORE_ERROR; + return ProcessCallback::IGNORE_ERROR; } @@ -327,11 +329,11 @@ void SyncStatusHandler::reportWarning(const wxString& warningMessage, bool& warn case ON_GUIERROR_IGNORE: return; //if errors are ignored, then warnings should also } - if (!warningActive) return; + if (!warningActive) + return; - syncStatusFrame.updateStatusDialogNow(); + forceUiRefresh(); - //show popup and ask user how to handle warning bool dontWarnAgain = false; switch (showWarningDlg(ReturnWarningDlg::BUTTON_IGNORE | ReturnWarningDlg::BUTTON_ABORT, warningMessage, diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h index 7f41e649..45d429b1 100644 --- a/ui/gui_status_handler.h +++ b/ui/gui_status_handler.h @@ -29,10 +29,10 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportInfo(const Zstring& text); + virtual void reportInfo(const wxString& text); virtual void forceUiRefresh(); - virtual ErrorHandler::Response reportError(const wxString& text); + virtual Response reportError(const wxString& text); virtual void reportFatalError(const wxString& errorMessage); virtual void reportWarning(const wxString& warningMessage, bool& warningActive); @@ -55,10 +55,10 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportInfo(const Zstring& text); + virtual void reportInfo(const wxString& text); virtual void forceUiRefresh(); - virtual ErrorHandler::Response reportError(const wxString& text); + virtual Response reportError(const wxString& text); virtual void reportFatalError(const wxString& errorMessage); virtual void reportWarning(const wxString& warningMessage, bool& warningActive); diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp index c5e8ef72..2256329a 100644 --- a/ui/main_dlg.cpp +++ b/ui/main_dlg.cpp @@ -17,7 +17,6 @@ #include #include #include -#include "../shared/system_constants.h" #include "../library/custom_grid.h" #include "../shared/custom_button.h" #include "../shared/custom_combo_box.h" @@ -97,31 +96,8 @@ public: case xmlAccess::MERGE_GUI: case xmlAccess::MERGE_GUI_BATCH: - if (droppedFiles.size() == 1) - { - mainDlg_.loadConfiguration(droppedFiles[0]); - return false; - } - else - { - xmlAccess::XmlGuiConfig guiCfg; - try - { - convertConfig(droppedFiles, guiCfg); //throw (xmlAccess::FfsXmlError) - } - catch (const xmlAccess::FfsXmlError& error) - { - if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) - wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); - else - { - wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); - return false; - } - } - mainDlg_.setCurrentConfiguration(guiCfg); - return false; - } + mainDlg_.loadConfiguration(droppedFiles); + return false; case xmlAccess::MERGE_OTHER: //=> return true: change directory selection via drag and drop @@ -177,7 +153,7 @@ private: virtual MainConfiguration getMainConfig() const { - return mainDlg.getCurrentConfiguration().mainCfg; + return mainDlg.getConfig().mainCfg; } virtual void OnAltSyncCfgChange() @@ -356,18 +332,30 @@ MainDialog::MainDialog(const wxString& cfgFileName, xmlAccess::XmlGlobalSettings { xmlAccess::XmlGuiConfig guiCfg; //structure to receive gui settings, already defaulted!! - wxString currentConfigFile = cfgFileName; //this one has priority - if (currentConfigFile.empty()) currentConfigFile = settings.gui.lastUsedConfigFile; //next: suggest name of last used selection - if (currentConfigFile.empty() || !fileExists(wxToZ(currentConfigFile))) currentConfigFile = lastRunConfigName(); //if above fails... + std::vector filenames; + if (!cfgFileName.empty()) //1. this one has priority + filenames.push_back(cfgFileName); + else //next: use last used selection + { + filenames = settings.gui.lastUsedConfigFiles; //2. now try last used files + + //check if one of the files is not existing (this shall not be an error!) + if (std::find_if(filenames.begin(), filenames.end(), + [](const wxString& filename) { return !fileExists(toZ(filename)); }) != filenames.end()) + filenames.clear(); + + if (filenames.empty()) + { + if (fileExists(toZ(lastRunConfigName()))) //3. try to load auto-save config + filenames.push_back(lastRunConfigName()); + } + } bool loadCfgSuccess = false; - if (!cfgFileName.empty() || fileExists(wxToZ(currentConfigFile))) + if (!filenames.empty()) try { //load XML - std::vector filenames; - filenames.push_back(currentConfigFile); - xmlAccess::convertConfig(filenames, guiCfg); //throw (xmlAccess::FfsXmlError) loadCfgSuccess = true; @@ -385,7 +373,7 @@ MainDialog::MainDialog(const wxString& cfgFileName, xmlAccess::XmlGlobalSettings settings, startComparisonImmediately); - setLastUsedConfig(currentConfigFile, loadCfgSuccess ? guiCfg : xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors + setLastUsedConfig(filenames, loadCfgSuccess ? guiCfg : xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors } @@ -397,6 +385,8 @@ MainDialog::MainDialog(const xmlAccess::XmlGuiConfig& guiCfg, init(guiCfg, settings, startComparison); + + setLastUsedConfig(std::vector(), guiCfg); } @@ -479,6 +469,11 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, m_panelStatusBar ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSetLayout), NULL, this); //---------------------------------------------------------------------------------- + //register context: quick variant selection + m_bpButtonCmpConfig ->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSelectCompVariant), NULL, this); + m_bpButtonSyncConfig->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(MainDialog::OnContextSelectSyncVariant), NULL, this); + + globalSettings = &settings; gridDataView.reset(new zen::GridView); contextMenu.reset(new wxMenu); //initialize right-click context menu; will be dynamically re-created on each R-mouse-click @@ -496,8 +491,6 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, syncPreview.reset(new SyncPreview(this)); - SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); - SetIcon(*GlobalResources::instance().programIcon); //set application icon //notify about (logical) application main window => program won't quit, but stay on this dialog @@ -510,7 +503,7 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, //initialize and load configuration readGlobalSettings(); - setCurrentConfiguration(guiCfg); + setConfig(guiCfg); //set icons for this dialog m_buttonCompare->setBitmapFront(GlobalResources::instance().getImage(wxT("compare"))); @@ -618,7 +611,7 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, //some convenience: if FFS is started with a *.ffs_gui file as commandline parameter AND all directories contained exist, comparison shall be started right off if (startComparison) { - const zen::MainConfiguration currMainCfg = getCurrentConfiguration().mainCfg; + const zen::MainConfiguration currMainCfg = getConfig().mainCfg; const bool allFoldersExist = !DirNotFound()(currMainCfg.firstPair) && std::find_if(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(), DirNotFound()) == currMainCfg.additionalPairs.end(); @@ -629,8 +622,6 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, } } //---------------------------------------------------------------------------------------------------------------------------------------------------------------- - - addFileToCfgHistory(lastRunConfigName()); //make sure is always part of history list } @@ -651,12 +642,12 @@ void MainDialog::cleanUp(bool saveLastUsedConfig) m_gridMiddle->release(); m_gridRight ->release(); - writeGlobalSettings(); //set before saving last used config since this will reset "currentConfigFileName" + writeGlobalSettings(); //set before saving last used config since "activeConfigFiles" will be replaced //save configuration if (saveLastUsedConfig) { - const xmlAccess::XmlGuiConfig guiCfg = getCurrentConfiguration(); + const xmlAccess::XmlGuiConfig guiCfg = getConfig(); try { xmlAccess::writeConfig(guiCfg, lastRunConfigName()); @@ -689,9 +680,10 @@ void MainDialog::readGlobalSettings() m_gridLeft->setColumnAttributes(globalSettings->gui.columnAttribLeft); m_gridRight->setColumnAttributes(globalSettings->gui.columnAttribRight); - //load list of last used configuration files (in reverse order) - std::for_each(globalSettings->gui.cfgFileHistory.rbegin(), globalSettings->gui.cfgFileHistory.rend(), - boost::bind(&MainDialog::addFileToCfgHistory, this, _1)); + //load list of last used configuration files + std::vector cfgFileNames = globalSettings->gui.cfgFileHistory; + cfgFileNames.push_back(lastRunConfigName()); //make sure is always part of history list + addFileToCfgHistory(cfgFileNames); //load list of last used folders std::for_each(globalSettings->gui.folderHistoryLeft.rbegin(), @@ -738,8 +730,8 @@ void MainDialog::writeGlobalSettings() if (m_listBoxHistory->GetClientObject(i)) cfgFileHistory.push_back(static_cast(m_listBoxHistory->GetClientObject(i))->name_); - globalSettings->gui.cfgFileHistory = cfgFileHistory; - globalSettings->gui.lastUsedConfigFile = currentConfigFileName; + globalSettings->gui.cfgFileHistory = cfgFileHistory; + globalSettings->gui.lastUsedConfigFiles = activeConfigFiles; //write list of last used folders globalSettings->gui.folderHistoryLeft.clear(); @@ -825,15 +817,18 @@ void MainDialog::OnIdleEvent(wxEvent& event) event.Skip(); } +namespace +{ +//fast replacement for wxString modelling exponential growth +typedef Zbase zxString; //for use with UI texts +} + void MainDialog::copySelectionToClipboard(CustomGrid& selectedGrid) { const std::set selectedRows = getSelectedRows(&selectedGrid); if (selectedRows.size() > 0) { - //fast replacement for wxString modelling exponential growth - typedef Zbase zxString; - zxString clipboardString; //perf: wxString doesn't model exponential growth and so is out const int colCount = selectedGrid.GetNumberCols(); @@ -899,7 +894,7 @@ public: mainDlg->clearStatusBar(); //register abort button - mainDlg->m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortCompare ), NULL, this ); + mainDlg->m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion), NULL, this ); mainDlg->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), NULL, this); } @@ -907,7 +902,7 @@ public: { //de-register abort button mainDlg->Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), NULL, this); - mainDlg->m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortCompare ), NULL, this ); + mainDlg->m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion ), NULL, this ); mainDlg->enableAllElements(); } @@ -959,7 +954,7 @@ public: } private: - void OnAbortCompare(wxCommandEvent& event) //handle abort button click + void OnAbortDeletion(wxCommandEvent& event) //handle abort button click { abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw zen::AbortThisProcess()) } @@ -968,7 +963,10 @@ private: { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_ESCAPE) + { abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw zen::AbortThisProcess()) + return; + } event.Skip(); } @@ -1001,12 +999,6 @@ void MainDialog::deleteSelectedFiles(const std::set& viewSelectionLeft, globalSettings->gui.deleteOnBothSides, globalSettings->gui.useRecyclerForManualDeletion) == ReturnSmallDlg::BUTTON_OKAY) { - if (globalSettings->gui.useRecyclerForManualDeletion && !zen::recycleBinExists()) - { - wxMessageBox(_("Recycle Bin not yet supported for this system!")); - return; - } - try { //handle errors when deleting files/folders @@ -1048,17 +1040,17 @@ void exstractNames(const FileSystemObject& fsObj, wxString& name, wxString& dir) GetNames(wxString& nameIn, wxString& dirIn) : name_(nameIn), dir_(dirIn) {} virtual void visit(const FileMapping& fileObj) { - name_ = zToWx(fileObj.getFullName()); - dir_ = zToWx(fileObj.getFullName().BeforeLast(common::FILE_NAME_SEPARATOR)); + name_ = toWx(fileObj.getFullName()); + dir_ = toWx(fileObj.getFullName().BeforeLast(FILE_NAME_SEPARATOR)); } virtual void visit(const SymLinkMapping& linkObj) { - name_ = zToWx(linkObj.getFullName()); - dir_ = zToWx(linkObj.getFullName().BeforeLast(common::FILE_NAME_SEPARATOR)); + name_ = toWx(linkObj.getFullName()); + dir_ = toWx(linkObj.getFullName().BeforeLast(FILE_NAME_SEPARATOR)); } virtual void visit(const DirMapping& dirObj) { - dir_ = name_ = zToWx(dirObj.getFullName()); + dir_ = name_ = toWx(dirObj.getFullName()); } wxString& name_; @@ -1119,10 +1111,10 @@ void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const if (name.empty()) { if (leftSide) - zen::shellExecute(wxString(L"\"") + zToWx(fsObj->getBaseDirPf()) + L"\""); + zen::shellExecute(wxString(L"\"") + fsObj->getBaseDirPf() + "\""); //zen::shellExecute(wxString(wxT("explorer ")) + L"\"" + zToWx(fsObj->getBaseDirPf()) + L"\""); else - zen::shellExecute(wxString(L"\"") + zToWx(fsObj->getBaseDirPf()) + L"\""); + zen::shellExecute(wxString(L"\"") + fsObj->getBaseDirPf() + "\""); //zen::shellExecute(wxString(wxT("explorer ")) + L"\"" + zToWx(fsObj->getBaseDirPf()) + L"\""); return; } @@ -1131,8 +1123,8 @@ void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const else { //fallback - dir = zToWx(zen::getFormattedDirectoryName(wxToZ(firstFolderPair->getLeftDir()))); - dirCo = zToWx(zen::getFormattedDirectoryName(wxToZ(firstFolderPair->getRightDir()))); + dir = toWx(zen::getFormattedDirectoryName(toZ(firstFolderPair->getLeftDir()))); + dirCo = toWx(zen::getFormattedDirectoryName(toZ(firstFolderPair->getRightDir()))); if (!leftSide) std::swap(dir, dirCo); @@ -1177,6 +1169,10 @@ void MainDialog::clearStatusBar() void MainDialog::disableAllElements(bool enableAbort) { + //when changing consider: comparison, synchronization, manual deletion + + EnableCloseButton(false); //not allowed for synchronization! progress indicator is top window! + //disables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion m_panelViewFilter ->Disable(); m_bpButtonCmpConfig ->Disable(); @@ -1211,6 +1207,8 @@ void MainDialog::disableAllElements(bool enableAbort) void MainDialog::enableAllElements() { + EnableCloseButton(true); + m_panelViewFilter ->Enable(); m_bpButtonCmpConfig ->Enable(); m_panelFilter ->Enable(); @@ -1798,13 +1796,13 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_EXCLUDE_EXT if (exFilterCandidateObj.size() > 0 && !exFilterCandidateObj.begin()->second) //non empty && no directory { - const Zstring filename = exFilterCandidateObj.begin()->first.AfterLast(common::FILE_NAME_SEPARATOR); + const Zstring filename = exFilterCandidateObj.begin()->first.AfterLast(FILE_NAME_SEPARATOR); if (filename.find(Zchar('.')) != Zstring::npos) //be careful: AfterLast would return the whole string if '.' were not found! { const Zstring extension = filename.AfterLast(Zchar('.')); //add context menu item - wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + zToWx(extension)); + wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + " " + "*." + extension); menuItemExclExt->SetBitmap(GlobalResources::instance().getImage(wxT("filterSmall"))); contextMenu->Append(menuItemExclExt); @@ -1821,9 +1819,9 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_EXCLUDE_OBJ wxMenuItem* menuItemExclObj = NULL; if (exFilterCandidateObj.size() == 1) - menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + wxT(" ") + zToWx(exFilterCandidateObj.begin()->first.AfterLast(common::FILE_NAME_SEPARATOR))); + menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + " " + exFilterCandidateObj.begin()->first.AfterLast(FILE_NAME_SEPARATOR)); else if (exFilterCandidateObj.size() > 1) - menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + wxT(" ") + _("")); + menuItemExclObj = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Exclude via filter:")) + " " + _("")); if (menuItemExclObj != NULL) { @@ -1853,7 +1851,7 @@ void MainDialog::OnContextRim(wxGridEvent& event) { //some trick to translate default external apps on the fly: 1. "open in explorer" 2. "start directly" //wxString description = wxGetTranslation(i->first); - wxString description = zen::translate(i->first); + wxString description = zen::translate(i->first.c_str()); if (description.empty()) description = wxT(" "); //wxWidgets doesn't like empty items @@ -1909,8 +1907,10 @@ void MainDialog::OnContextExcludeExtension(wxCommandEvent& event) updateFilterButtons(); //do not fully apply filter, just exclude new items - addExcludeFiltering(gridDataView->getDataTentative(), newExclude); - //applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + std::for_each(gridDataView->getDataTentative().begin(), gridDataView->getDataTentative().end(), + [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); }); + + //applyFiltering(getConfig().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); if (currentCfg.hideFilteredElements) @@ -1936,9 +1936,9 @@ void MainDialog::OnContextExcludeObject(wxCommandEvent& event) if (i != objCont->selectedObjects.begin()) newExclude += Zstr("\n"); - newExclude += common::FILE_NAME_SEPARATOR + i->first; + newExclude += FILE_NAME_SEPARATOR + i->first; if (i->second) //is directory - newExclude += common::FILE_NAME_SEPARATOR; + newExclude += FILE_NAME_SEPARATOR; } //add to filter config @@ -1950,8 +1950,10 @@ void MainDialog::OnContextExcludeObject(wxCommandEvent& event) updateFilterButtons(); //do not fully apply filter, just exclude new items - addExcludeFiltering(gridDataView->getDataTentative(), newExclude); - //applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + std::for_each(gridDataView->getDataTentative().begin(), gridDataView->getDataTentative().end(), + [&](BaseDirMapping& baseMap) { addHardFiltering(baseMap, newExclude); }); + + //applyFiltering(getConfig().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); if (currentCfg.hideFilteredElements) @@ -2009,18 +2011,18 @@ void MainDialog::OnContextSyncDirRight(wxCommandEvent& event) void MainDialog::OnContextRimLabelLeft(wxGridEvent& event) { - int ctxtElementId = 1000; - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(++ctxtElementId, _("Customize...")); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnLeft), NULL, this); + + wxMenuItem* menuItemCustomize = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Customize...")); + contextMenu->Append(menuItemCustomize); + contextMenu->Connect(menuItemCustomize->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnLeft), NULL, this); contextMenu->AppendSeparator(); - wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), ++ctxtElementId, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); + wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); contextMenu->Append(itemAutoAdjust); itemAutoAdjust->Check(globalSettings->gui.autoAdjustColumnsLeft); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustLeft), NULL, this); + contextMenu->Connect(itemAutoAdjust->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustLeft), NULL, this); PopupMenu(contextMenu.get()); //show context menu } @@ -2028,19 +2030,18 @@ void MainDialog::OnContextRimLabelLeft(wxGridEvent& event) void MainDialog::OnContextRimLabelRight(wxGridEvent& event) { - int ctxtElementId = 1000; - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(++ctxtElementId, _("Customize...")); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnRight), NULL, this); + wxMenuItem* menuItemCustomize = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Customize...")); + contextMenu->Append(menuItemCustomize); + contextMenu->Connect(menuItemCustomize->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnRight), NULL, this); contextMenu->AppendSeparator(); - wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), ++ctxtElementId, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); + wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK); contextMenu->Append(itemAutoAdjust); itemAutoAdjust->Check(globalSettings->gui.autoAdjustColumnsRight); - contextMenu->Connect(ctxtElementId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustRight), NULL, this); + contextMenu->Connect(itemAutoAdjust->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustRight), NULL, this); PopupMenu(contextMenu.get()); //show context menu } @@ -2092,20 +2093,19 @@ void MainDialog::OnContextAutoAdjustRight(wxCommandEvent& event) void MainDialog::OnContextMiddle(wxGridEvent& event) { - int contextItemID = 2000; - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(++contextItemID, _("Include all rows")); + wxMenuItem* menuItemInclude = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Include all rows")); + contextMenu->Append(menuItemInclude); if (gridDataView->rowsTotal() == 0) - contextMenu->Enable(contextItemID, false); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextIncludeAll), NULL, this); - + menuItemInclude->Enable(false); + contextMenu->Connect(menuItemInclude->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextIncludeAll), NULL, this); - contextMenu->Append(++contextItemID, _("Exclude all rows")); + wxMenuItem* menuItemExclude = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Exclude all rows")); + contextMenu->Append(menuItemExclude); if (gridDataView->rowsTotal() == 0) - contextMenu->Enable(contextItemID, false); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextExcludeAll), NULL, this); + menuItemExclude->Enable(false); + contextMenu->Connect(menuItemExclude->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextExcludeAll), NULL, this); PopupMenu(contextMenu.get()); //show context menu } @@ -2113,15 +2113,13 @@ void MainDialog::OnContextMiddle(wxGridEvent& event) void MainDialog::OnContextMiddleLabel(wxGridEvent& event) { - int contextItemID = 2000; - contextMenu.reset(new wxMenu); //re-create context menu - wxMenuItem* itemSyncPreview = new wxMenuItem(contextMenu.get(), ++contextItemID, _("Synchronization Preview")); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncView), NULL, this); + wxMenuItem* itemSyncPreview = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Synchronization Preview")); + contextMenu->Connect(itemSyncPreview->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncView), NULL, this); - wxMenuItem* itemCmpResult = new wxMenuItem(contextMenu.get(), ++contextItemID, _("Comparison Result")); - contextMenu->Connect(contextItemID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextComparisonView), NULL, this); + wxMenuItem* itemCmpResult = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Comparison Result")); + contextMenu->Connect(itemCmpResult->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextComparisonView), NULL, this); if (syncPreview->previewIsEnabled()) itemSyncPreview->SetBitmap(GlobalResources::instance().getImage(wxT("syncViewSmall"))); @@ -2215,6 +2213,138 @@ void MainDialog::OnContextSyncView(wxCommandEvent& event) } +struct CtxtSelectionCmpVar : public wxObject +{ + CtxtSelectionCmpVar(CompareVariant var) : compareVar(var) {} + CompareVariant compareVar; +}; + + +void MainDialog::OnContextSelectCompVariant(wxMouseEvent& event) +{ + contextMenu.reset(new wxMenu); //re-create context menu + + wxMenuItem* itemSizeDate = new wxMenuItem(contextMenu.get(), wxID_ANY, _("File size and date"), L"", wxITEM_RADIO); + contextMenu->Append(itemSizeDate); + contextMenu->Connect(itemSizeDate->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetCompVariant), + new CtxtSelectionCmpVar(CMP_BY_TIME_SIZE), //ownership passed! + this); + + wxMenuItem* itemContent = new wxMenuItem(contextMenu.get(), wxID_ANY, _("File content"), L"", wxITEM_RADIO); + contextMenu->Append(itemContent); + contextMenu->Connect(itemContent->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetCompVariant), + new CtxtSelectionCmpVar(CMP_BY_CONTENT), //ownership passed! + this); + + //--------------------------------------------------------------- + xmlAccess::XmlGuiConfig cfg = getConfig(); + + switch (cfg.mainCfg.compareVar) + { + case CMP_BY_TIME_SIZE: + itemSizeDate->Check(); + break; + case CMP_BY_CONTENT: + itemContent->Check(); + break; + } + + PopupMenu(contextMenu.get()); //show context menu +} + + +struct CtxtSelectionSyncVar : public wxObject +{ + CtxtSelectionSyncVar(SyncConfig::Variant var) : syncVar(var) {} + SyncConfig::Variant syncVar; +}; + + +void MainDialog::OnContextSelectSyncVariant(wxMouseEvent& event) +{ + contextMenu.reset(new wxMenu); //re-create context menu + + wxMenuItem* itemAuto = new wxMenuItem(contextMenu.get(), wxID_ANY, _(""), L"", wxITEM_RADIO); + contextMenu->Append(itemAuto); + contextMenu->Connect(itemAuto->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::AUTOMATIC), //ownership passed! + this); + + wxMenuItem* itemMirror = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Mirror ->>"), L"", wxITEM_RADIO); + contextMenu->Append(itemMirror); + contextMenu->Connect(itemMirror->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::MIRROR), //ownership passed! + this); + + wxMenuItem* itemUpdate = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Update ->"), L"", wxITEM_RADIO); + contextMenu->Append(itemUpdate); + contextMenu->Connect(itemUpdate->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::UPDATE), //ownership passed! + this); + + wxMenuItem* itemCustom = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Custom"), L"", wxITEM_RADIO); + contextMenu->Append(itemCustom); + contextMenu->Connect(itemCustom->GetId(), + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MainDialog::OnSetSyncVariant), + new CtxtSelectionSyncVar(SyncConfig::CUSTOM), //ownership passed! + this); + + //--------------------------------------------------------------- + xmlAccess::XmlGuiConfig cfg = getConfig(); + + switch (cfg.mainCfg.syncConfiguration.var) + { + case SyncConfig::AUTOMATIC: + itemAuto->Check(); + break; + case SyncConfig::MIRROR: + itemMirror->Check(); + break; + case SyncConfig::UPDATE: + itemUpdate->Check(); + break; + case SyncConfig::CUSTOM: + itemCustom->Check(); + break; + } + + PopupMenu(contextMenu.get()); //show context menu +} + + +void MainDialog::OnSetCompVariant(wxCommandEvent& event) +{ + CtxtSelectionCmpVar* selection = dynamic_cast(event.m_callbackUserData); + if (selection) + { + currentCfg.mainCfg.compareVar = selection->compareVar; + applyCompareConfig(); + } +} + + +void MainDialog::OnSetSyncVariant(wxCommandEvent& event) +{ + CtxtSelectionSyncVar* selection = dynamic_cast(event.m_callbackUserData); + if (selection) + { + currentCfg.mainCfg.syncConfiguration.var = selection->syncVar; + applySyncConfig(); + } +} + + void MainDialog::OnDirSelected(wxFileDirPickerEvent& event) { //left and right directory text-control and dirpicker are synchronized by MainFolderDragDrop automatically @@ -2232,58 +2362,69 @@ void MainDialog::OnDirSelected(wxFileDirPickerEvent& event) wxString getFormattedHistoryElement(const wxString& filename) { - Zstring output = wxToZ(filename).AfterLast(common::FILE_NAME_SEPARATOR); - if (output.EndsWith(Zstr(".ffs_gui"))) - output = output.BeforeLast(Zstr('.')); - return zToWx(output); + wxString output = afterLast(filename, FILE_NAME_SEPARATOR); + if (endsWith(output, ".ffs_gui")) + output = beforeLast(output, '.'); + return output; } -void MainDialog::addFileToCfgHistory(const wxString& cfgFile) +void MainDialog::addFileToCfgHistory(const std::vector& filenames) { - wxString filename = cfgFile; - if (filename.empty()) - filename = lastRunConfigName(); + std::deque selections(m_listBoxHistory->GetCount()); - //only (still) existing files should be included in the list - if (util::fileExists(wxToZ(filename), 200) == util::EXISTING_FALSE) //potentially slow network access: wait 200ms - return; + std::for_each(filenames.begin(), filenames.end(), + [&](wxString filename) + { + //only (still) existing files should be included in the list + if (util::fileExists(toZ(filename), 200) == util::EXISTING_FALSE) //potentially slow network access: wait 200ms + return; - int posFound = -1; + int posFound = -1; - for (int i = 0; i < static_cast(m_listBoxHistory->GetCount()); ++i) - if (m_listBoxHistory->GetClientObject(i)) + for (int i = 0; i < static_cast(m_listBoxHistory->GetCount()); ++i) { - const wxString& filenameTmp = static_cast(m_listBoxHistory->GetClientObject(i))->name_; - - //tests if the same filenames are specified, even if they are relative to the current working directory/include symlinks or \\?\ prefix - if (util::sameFileSpecified(wxToZ(filename), wxToZ(filenameTmp))) + wxClientDataString* cData = dynamic_cast(m_listBoxHistory->GetClientObject(i)); + if (cData) { - posFound = i; - break; + const wxString& filenameTmp = cData->name_; + + //tests if the same filenames are specified, even if they are relative to the current working directory/include symlinks or \\?\ prefix + if (util::sameFileSpecified(toZ(filename), toZ(filenameTmp))) + { + posFound = i; + break; + } } } - if (posFound != -1) - { - //if entry is in the list, then jump to element - m_listBoxHistory->SetSelection(posFound); - } - else - { - int newPos = -1; - //the default config file should receive another name on GUI - if (util::sameFileSpecified(wxToZ(lastRunConfigName()), wxToZ(filename))) - newPos = m_listBoxHistory->Append(_(""), new wxClientDataString(filename)); //insert at beginning of list + if (posFound != -1) + selections[posFound] = true; else - newPos = m_listBoxHistory->Append(getFormattedHistoryElement(filename), new wxClientDataString(filename)); //insert at beginning of list + { + int newPos = -1; + //the default config file should receive a different name on GUI + if (util::sameFileSpecified(toZ(lastRunConfigName()), toZ(filename))) + newPos = m_listBoxHistory->Append(_(""), new wxClientDataString(filename)); + else + newPos = m_listBoxHistory->Append(getFormattedHistoryElement(filename), new wxClientDataString(filename)); - m_listBoxHistory->SetSelection(newPos); - } + selections.insert(selections.begin() + newPos, true); + } + }); + + assert(selections.size() == m_listBoxHistory->GetCount()); - //keep maximal size of history list - //if (m_comboHistory->GetCount() > globalSettings->gui.cfgHistoryMax) - // m_comboHistory->Delete(globalSettings->gui.cfgHistoryMax); + //do not apply selections immediately but only when needed! + //this prevents problems with m_listBoxHistory losing keyboard selection focus if identical selection is redundantly reapplied + for (int pos = 0; pos < static_cast(selections.size()); ++pos) + if (m_listBoxHistory->IsSelected(pos) != selections[pos]) + { + if (selections[pos]) + m_listBoxHistory->SetSelection(pos); + else + m_listBoxHistory->Deselect(pos); + } } @@ -2307,33 +2448,35 @@ void MainDialog::OnSaveConfig(wxCommandEvent& event) bool MainDialog::trySaveConfig() //return true if saved successfully { - wxString defaultFileName = currentConfigFileName.empty() ? wxT("SyncSettings.ffs_gui") : currentConfigFileName; - //attention: currentConfigFileName may be an imported *.ffs_batch file! We don't want to overwrite it with a GUI config! + wxString defaultFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxT("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); - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName, - wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"), wxFD_SAVE); //creating this on freestore leads to memleak! + wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) { - const wxString newFileName = filePicker.GetPath(); + const wxString filename = filePicker.GetPath(); + const xmlAccess::XmlGuiConfig guiCfg = getConfig(); - if (zen::fileExists(wxToZ(newFileName))) + //write config to XML + try { - if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL, - wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")) != ReturnQuestionDlg::BUTTON_YES) - return trySaveConfig(); //retry - } + xmlAccess::writeConfig(guiCfg, filename); + setLastUsedConfig(filename, guiCfg); - if (writeConfigurationToXml(newFileName)) - { pushStatusInformation(_("Configuration saved!")); return true; } + catch (const xmlAccess::FfsXmlError& error) + { + wxMessageBox(error.msg().c_str(), _("Error"), wxOK | wxICON_ERROR); + } } return false; @@ -2344,12 +2487,19 @@ void MainDialog::OnLoadConfig(wxCommandEvent& event) { wxFileDialog filePicker(this, wxEmptyString, - beforeLast(currentConfigFileName, common::FILE_NAME_SEPARATOR), //set default dir: empty string if "currentConfigFileName" is empty or has no path separator + beforeLast(activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : 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"), wxFD_OPEN); + wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch"), + wxFD_OPEN | wxFD_MULTIPLE); if (filePicker.ShowModal() == wxID_OK) - loadConfiguration(filePicker.GetPath()); + { + wxArrayString tmp; + filePicker.GetPaths(tmp); + std::vector fileNames(tmp.begin(), tmp.end()); + + loadConfiguration(fileNames); + } } @@ -2358,21 +2508,33 @@ void MainDialog::OnNewConfig(wxCommandEvent& event) if (!saveOldConfig()) //notify user about changed settings return; - setCurrentConfiguration(xmlAccess::XmlGuiConfig()); + xmlAccess::XmlGuiConfig emptyCfg; + setConfig(emptyCfg); - SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); - currentConfigFileName.clear(); + setLastUsedConfig(std::vector(), emptyCfg); } void MainDialog::OnLoadFromHistory(wxCommandEvent& event) { - if (event.GetClientObject()) + wxArrayInt selections; + m_listBoxHistory->GetSelections(selections); + + std::vector filenames; + std::for_each(selections.begin(), selections.end(), + [&](int pos) { - const wxString filename = static_cast(event.GetClientObject())->name_; - loadConfiguration(filename); + wxClientDataString* cData = dynamic_cast(m_listBoxHistory->GetClientObject(pos)); + if (cData) + filenames.push_back(cData->name_); + }); - addFileToCfgHistory(currentConfigFileName); //in case user cancelled saving old config: restore selection to currently active config file + if (!filenames.empty()) + { + loadConfiguration(filenames); + + //in case user cancelled saving old config, selection is wrong: so reapply it! + addFileToCfgHistory(activeConfigFiles); } } @@ -2380,9 +2542,11 @@ void MainDialog::OnLoadFromHistory(wxCommandEvent& event) bool MainDialog::saveOldConfig() //return false on user abort { //notify user about changed settings - if (globalSettings->optDialogs.popupOnConfigChange && !currentConfigFileName.empty()) //only if check is active and non-default config file loaded + if (globalSettings->optDialogs.popupOnConfigChange && + //only if check is active and non-default config file loaded + (activeConfigFiles.size() != 1 || activeConfigFiles[0] != lastRunConfigName())) { - if (lastConfigurationSaved != getCurrentConfiguration()) + if (lastConfigurationSaved != getConfig()) { bool dontShowAgain = !globalSettings->optDialogs.popupOnConfigChange; @@ -2408,14 +2572,46 @@ bool MainDialog::saveOldConfig() //return false on user abort void MainDialog::loadConfiguration(const wxString& filename) { - if (!filename.IsEmpty()) + std::vector filenames; + filenames.push_back(filename); + + loadConfiguration(filenames); +} + + +void MainDialog::loadConfiguration(const std::vector& filenames) +{ + if (filenames.empty()) + return; + + if (!saveOldConfig()) + return; + + //load XML + xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!! + try { - if (!saveOldConfig()) - return; + //allow reading batch configurations also + xmlAccess::convertConfig(filenames, newGuiCfg); //throw (xmlAccess::FfsXmlError) - if (readConfigurationFromXml(filename)) - pushStatusInformation(_("Configuration loaded!")); + setLastUsedConfig(filenames, newGuiCfg); + pushStatusInformation(_("Configuration loaded!")); } + catch (const xmlAccess::FfsXmlError& error) + { + if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) + { + setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors + wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); + } + else + { + wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); + return; + } + } + + setConfig(newGuiCfg); } @@ -2424,21 +2620,27 @@ void MainDialog::OnCfgHistoryKeyEvent(wxKeyEvent& event) const int keyCode = event.GetKeyCode(); if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE) { - //try to delete the currently selected config history item - //const int selectedItem = m_listBoxHistory->GetCurrentSelection(); - const int selectedItem = m_listBoxHistory->GetSelection(); - if (selectedItem != wxNOT_FOUND) + //delete currently selected config history items + wxArrayInt tmp; + m_listBoxHistory->GetSelections(tmp); + + std::set selections(tmp.begin(), tmp.end()); //sort ascending! + + int shift = 0; + std::for_each(selections.begin(), selections.end(), + [&](int pos) { - m_listBoxHistory->Delete(selectedItem); + m_listBoxHistory->Delete(pos + shift); + --shift; + }); - //set selection on next element - if (m_listBoxHistory->GetCount() > 0) - { - int newSelection = selectedItem; - if (newSelection >= static_cast(m_listBoxHistory->GetCount())) - newSelection = m_listBoxHistory->GetCount() - 1; - m_listBoxHistory->SetSelection(newSelection); - } + //set active selection on next element to allow "batch-deletion" by holding down DEL key + if (!selections.empty() && m_listBoxHistory->GetCount() > 0) + { + int newSelection = *selections.begin(); + if (newSelection >= static_cast(m_listBoxHistory->GetCount())) + newSelection = m_listBoxHistory->GetCount() - 1; + m_listBoxHistory->SetSelection(newSelection); } return; //"swallow" event @@ -2450,6 +2652,7 @@ void MainDialog::OnCfgHistoryKeyEvent(wxKeyEvent& event) void MainDialog::OnClose(wxCloseEvent& event) { + /* if (m_buttonAbort->IsShown()) //delegate to "abort" button if available { wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); //simulate button click @@ -2461,18 +2664,21 @@ void MainDialog::OnClose(wxCloseEvent& event) return; } } - else //regular destruction handling + */ + + //regular destruction handling + if (event.CanVeto()) { - if (event.CanVeto()) + const bool cancelled = !saveOldConfig(); //notify user about changed settings + if (cancelled) { - const bool cancelled = !saveOldConfig(); //notify user about changed settings - if (cancelled) - { - event.Veto(); - return; - } + //attention: this Veto() does NOT cancel system shutdown: application will block + //in saveOldConfig() within a modal dialog, so system will just kill the app + event.Veto(); + return; } } + Destroy(); } @@ -2516,80 +2722,30 @@ void MainDialog::OnSetSyncDirection(FFSSyncDirectionEvent& event) } -bool MainDialog::readConfigurationFromXml(const wxString& filename) +void MainDialog::setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig) { - //load XML - xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!! - bool parsingError = true; - try - { - //allow reading batch configurations also - std::vector filenames; - filenames.push_back(filename); - - xmlAccess::convertConfig(filenames, newGuiCfg); //throw (xmlAccess::FfsXmlError) - - parsingError = false; - } - catch (const xmlAccess::FfsXmlError& error) - { - if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING) - wxMessageBox(error.msg(), _("Warning"), wxOK | wxICON_WARNING); - else - { - wxMessageBox(error.msg(), _("Error"), wxOK | wxICON_ERROR); - return false; - } - } - - setCurrentConfiguration(newGuiCfg); - - setLastUsedConfig(filename, parsingError ? xmlAccess::XmlGuiConfig() : newGuiCfg); //simulate changed config on parsing errors - - return !parsingError; + std::vector filenames; + filenames.push_back(filename); + setLastUsedConfig(filenames, guiConfig); } -void MainDialog::setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig) +void MainDialog::setLastUsedConfig(const std::vector& filenames, const xmlAccess::XmlGuiConfig& guiConfig) { - addFileToCfgHistory(filename); //put filename on list of last used config files - - //set title - if (filename.empty() || filename == lastRunConfigName()) - { - SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); - currentConfigFileName.clear(); - } - else - { - SetTitle(filename); - currentConfigFileName = filename; - } - + activeConfigFiles = filenames; lastConfigurationSaved = guiConfig; -} + addFileToCfgHistory(activeConfigFiles); //put filename on list of last used config files -bool MainDialog::writeConfigurationToXml(const wxString& filename) -{ - const xmlAccess::XmlGuiConfig guiCfg = getCurrentConfiguration(); - - //write config to XML - try - { - xmlAccess::writeConfig(guiCfg, filename); - setLastUsedConfig(filename, guiCfg); - return true; - } - catch (const xmlAccess::FfsXmlError& error) - { - wxMessageBox(error.msg().c_str(), _("Error"), wxOK | wxICON_ERROR); - return false; - } + //set title + if (activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName()) + SetTitle(activeConfigFiles[0]); + else + SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")); } -void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCfg) +void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg) { currentCfg = newGuiCfg; @@ -2608,13 +2764,13 @@ void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCf updateFilterButtons(); //set first folder pair - firstFolderPair->setValues(zToWx(currentCfg.mainCfg.firstPair.leftDirectory), - zToWx(currentCfg.mainCfg.firstPair.rightDirectory), + firstFolderPair->setValues(toWx(currentCfg.mainCfg.firstPair.leftDirectory), + toWx(currentCfg.mainCfg.firstPair.rightDirectory), currentCfg.mainCfg.firstPair.altSyncConfig, currentCfg.mainCfg.firstPair.localFilter); - addLeftFolderToHistory( zToWx(currentCfg.mainCfg.firstPair.leftDirectory)); //another hack: wxCombobox::Insert() asynchronously sends message - addRightFolderToHistory(zToWx(currentCfg.mainCfg.firstPair.rightDirectory)); //overwriting a later wxCombobox::SetValue()!!! :( + addLeftFolderToHistory( toWx(currentCfg.mainCfg.firstPair.leftDirectory)); //another hack: wxCombobox::Insert() asynchronously sends message + addRightFolderToHistory(toWx(currentCfg.mainCfg.firstPair.rightDirectory)); //overwriting a later wxCombobox::SetValue()!!! :( //clear existing additional folder pairs clearAddFolderPairs(); @@ -2641,22 +2797,22 @@ void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCf inline FolderPairEnh getEnhancedPair(const DirectoryPair* panel) { - return FolderPairEnh(wxToZ(panel->getLeftDir()), - wxToZ(panel->getRightDir()), + return FolderPairEnh(toZ(panel->getLeftDir()), + toZ(panel->getRightDir()), panel->getAltSyncConfig(), panel->getAltFilterConfig()); } -xmlAccess::XmlGuiConfig MainDialog::getCurrentConfiguration() const +xmlAccess::XmlGuiConfig MainDialog::getConfig() const { xmlAccess::XmlGuiConfig guiCfg = currentCfg; //load settings whose ownership lies not in currentCfg: //first folder pair - guiCfg.mainCfg.firstPair = FolderPairEnh(wxToZ(firstFolderPair->getLeftDir()), - wxToZ(firstFolderPair->getRightDir()), + guiCfg.mainCfg.firstPair = FolderPairEnh(toZ(firstFolderPair->getLeftDir()), + toZ(firstFolderPair->getRightDir()), firstFolderPair->getAltSyncConfig(), firstFolderPair->getAltFilterConfig()); @@ -2679,15 +2835,15 @@ const wxString& MainDialog::lastRunConfigName() } -void MainDialog::refreshGridAfterFilterChange(const int delay) +void MainDialog::refreshGridAfterFilterChange(int delay) { //signal UI that grids need to be refreshed on next Update() m_gridLeft ->ForceRefresh(); m_gridMiddle->ForceRefresh(); m_gridRight ->ForceRefresh(); - m_gridLeft ->Update(); // - m_gridMiddle->Update(); //show changes resulting from ForceRefresh() - m_gridRight ->Update(); // + //m_gridLeft ->Update(); // + //m_gridMiddle->Update(); //show changes resulting from ForceRefresh() + //m_gridRight ->Update(); // if (currentCfg.hideFilteredElements) { @@ -2732,13 +2888,14 @@ void MainDialog::OnConfigureFilter(wxCommandEvent& event) void MainDialog::OnGlobalFilterOpenContext(wxCommandEvent& event) { - const int menuId = 1234; contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(menuId, _("Clear filter settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnGlobalFilterRemConfirm), NULL, this); + + wxMenuItem* itemClear = new wxMenuItem(contextMenu.get(), wxID_ANY, _("Clear filter settings")); + contextMenu->Append(itemClear); + contextMenu->Connect(itemClear->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnGlobalFilterRemConfirm), NULL, this); if (isNullFilter(currentCfg.mainCfg.globalFilter)) - contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway + contextMenu->Enable(itemClear->GetId(), false); //disable menu item, if clicking wouldn't make sense anyway PopupMenu(contextMenu.get()); //show context menu } @@ -2950,12 +3107,12 @@ void MainDialog::updateFilterButtons() //global filter: test for Null-filter if (isNullFilter(currentCfg.mainCfg.globalFilter)) { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOff"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOff"))); m_bpButtonFilter->SetToolTip(_("No filter selected")); } else { - m_bpButtonFilter->SetBitmapLabel(GlobalResources::instance().getImage(wxT("filterOn"))); + setBitmapLabel(*m_bpButtonFilter, GlobalResources::instance().getImage(wxT("filterOn"))); m_bpButtonFilter->SetToolTip(_("Filter is active")); } @@ -2987,7 +3144,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) //class handling status display and error messages CompareStatusHandler statusHandler(*this); - const std::vector cmpConfig = zen::extractCompareCfg(getCurrentConfiguration().mainCfg); + const std::vector cmpConfig = zen::extractCompareCfg(getConfig().mainCfg); //GUI mode: place directory locks on directories isolated(!) during both comparison and synchronization LockHolder dummy2; @@ -2998,8 +3155,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) } //begin comparison - zen::CompareProcess comparison(currentCfg.mainCfg.handleSymlinks, - globalSettings->fileTimeTolerance, + zen::CompareProcess comparison(globalSettings->fileTimeTolerance, globalSettings->optDialogs, statusHandler); @@ -3013,7 +3169,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) //play (optional) sound notification after sync has completed (GUI and batch mode) const wxString soundFile = zen::getResourceDir() + wxT("Compare_Complete.wav"); - if (fileExists(wxToZ(soundFile))) + if (fileExists(toZ(soundFile))) wxSound::Play(soundFile, wxSOUND_ASYNC); } catch (GuiAbortProcess&) @@ -3120,45 +3276,53 @@ void MainDialog::OnSyncSettings(wxCommandEvent& event) } -void MainDialog::OnCmpSettings(wxCommandEvent& event) +void MainDialog::applyCompareConfig() { - //show window right next to the compare-config button - wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); - windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; + //update compare variant name + m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(currentCfg.mainCfg.compareVar) + wxT(")")); + m_panelTopButtons->Layout(); //adapt layout for variant text - const CompareVariant compareVarOld = currentCfg.mainCfg.compareVar; - const SymLinkHandling handleSymlinksOld = currentCfg.mainCfg.handleSymlinks; + //disable the sync button + syncPreview->enableSynchronization(false); - if (zen::showCompareCfgDialog(windowPos, - currentCfg.mainCfg.compareVar, - currentCfg.mainCfg.handleSymlinks) == ReturnSmallDlg::BUTTON_OKAY && - //check if settings were changed at all - (compareVarOld != currentCfg.mainCfg.compareVar || - handleSymlinksOld != currentCfg.mainCfg.handleSymlinks)) + //clear grids + gridDataView->clearAllRows(); + updateGuiGrid(); + + //convenience: change sync view + switch (currentCfg.mainCfg.compareVar) { - //update compare variant name - m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(currentCfg.mainCfg.compareVar) + wxT(")")); - m_panelTopButtons->Layout(); //adapt layout for variant text + case CMP_BY_TIME_SIZE: + syncPreview->enablePreview(true); + break; + case CMP_BY_CONTENT: + syncPreview->enablePreview(false); + break; + } - //disable the sync button - syncPreview->enableSynchronization(false); + m_buttonCompare->SetFocus(); +} - //clear grids - gridDataView->clearAllRows(); - updateGuiGrid(); - //convenience: change sync view - switch (currentCfg.mainCfg.compareVar) - { - case CMP_BY_TIME_SIZE: - syncPreview->enablePreview(true); - break; - case CMP_BY_CONTENT: - syncPreview->enablePreview(false); - break; - } +void MainDialog::OnCmpSettings(wxCommandEvent& event) +{ + //show window right next to the compare-config button + //wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition(); + //windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5; - m_buttonCompare->SetFocus(); + CompareVariant compareVarNew = currentCfg.mainCfg.compareVar; + SymLinkHandling handleSymlinkNew = currentCfg.mainCfg.handleSymlinks; + + if (zen::showCompareCfgDialog(compareVarNew, + handleSymlinkNew) == ReturnSmallDlg::BUTTON_OKAY && + //check if settings were changed at all + (compareVarNew != currentCfg.mainCfg.compareVar || + handleSymlinkNew != currentCfg.mainCfg.handleSymlinks)) + { + currentCfg.mainCfg.compareVar = compareVarNew; + currentCfg.mainCfg.handleSymlinks = handleSymlinkNew; + + applyCompareConfig(); } } @@ -3183,7 +3347,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) bool dontShowAgain = false; if (zen::showSyncPreviewDlg( - getCurrentConfiguration().mainCfg.getSyncVariantName(), + getConfig().mainCfg.getSyncVariantName(), zen::SyncStatistics(gridDataView->getDataTentative()), dontShowAgain) != ReturnSmallDlg::BUTTON_OKAY) return; @@ -3198,8 +3362,10 @@ void MainDialog::OnStartSync(wxCommandEvent& event) { //PERF_START; + wxString activeFileName = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName() ? activeConfigFiles[0] : wxString(); + //class handling status updates and error messages - SyncStatusHandler statusHandler(this, currentCfg.handleError, zen::extractJobName(currentConfigFileName)); + SyncStatusHandler statusHandler(this, currentCfg.handleError, zen::extractJobName(activeFileName)); FolderComparison& dataToSync = gridDataView->getDataTentative(); @@ -3219,7 +3385,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) globalSettings->copyFilePermissions, statusHandler); - const std::vector syncProcessCfg = zen::extractSyncCfg(getCurrentConfiguration().mainCfg); + const std::vector syncProcessCfg = zen::extractSyncCfg(getConfig().mainCfg); //make sure syncProcessCfg and dataToSync have same size and correspond! if (syncProcessCfg.size() != dataToSync.size()) @@ -3229,7 +3395,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) //play (optional) sound notification after sync has completed (GUI and batch mode) const wxString soundFile = zen::getResourceDir() + wxT("Sync_Complete.wav"); - if (fileExists(wxToZ(soundFile))) + if (fileExists(toZ(soundFile))) wxSound::Play(soundFile, wxSOUND_ASYNC); } catch (GuiAbortProcess&) @@ -3452,7 +3618,7 @@ void MainDialog::OnSwapSides(wxCommandEvent& event) m_bpButtonSyncDirOverwRight->setActive(tmp); //swap grid information - zen::swapGrids(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + zen::swapGrids(getConfig().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); } @@ -3651,14 +3817,14 @@ void MainDialog::OnAddFolderPair(wxCommandEvent& event) wxWindowUpdateLocker dummy(this); //avoid display distortion std::vector newPairs; - newPairs.push_back(getCurrentConfiguration().mainCfg.firstPair); + newPairs.push_back(getConfig().mainCfg.firstPair); addFolderPair(newPairs, true); //add pair in front of additonal pairs //clear first pair const FolderPairEnh cfgEmpty; - firstFolderPair->setValues(zToWx(cfgEmpty.leftDirectory), - zToWx(cfgEmpty.rightDirectory), + firstFolderPair->setValues(toWx(cfgEmpty.leftDirectory), + toWx(cfgEmpty.rightDirectory), cfgEmpty.altSyncConfig, cfgEmpty.localFilter); @@ -3673,7 +3839,7 @@ void MainDialog::OnAddFolderPair(wxCommandEvent& event) void MainDialog::updateFilterConfig() { - applyFiltering(gridDataView->getDataTentative(), getCurrentConfiguration().mainCfg); + applyFiltering(gridDataView->getDataTentative(), getConfig().mainCfg); refreshGridAfterFilterChange(400); } @@ -3681,7 +3847,7 @@ void MainDialog::updateFilterConfig() void MainDialog::applySyncConfig() { //update sync variant name - m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getCurrentConfiguration().mainCfg.getSyncVariantName() + wxT(")")); + m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getConfig().mainCfg.getSyncVariantName() + wxT(")")); m_panelTopButtons->Layout(); //adapt layout for variant text @@ -3708,7 +3874,7 @@ void MainDialog::applySyncConfig() wxWindow* parent_; } redetCallback(globalSettings->optDialogs.warningSyncDatabase, this); - zen::redetermineSyncDirection(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative(), &redetCallback); + zen::redetermineSyncDirection(getConfig().mainCfg, gridDataView->getDataTentative(), &redetCallback); updateGuiGrid(); } @@ -3723,8 +3889,8 @@ void MainDialog::OnRemoveTopFolderPair(wxCommandEvent& event) const FolderPairEnh cfgSecond = getEnhancedPair(additionalFolderPairs[0]); //reset first pair - firstFolderPair->setValues(zToWx(cfgSecond.leftDirectory), - zToWx(cfgSecond.rightDirectory), + firstFolderPair->setValues(toWx(cfgSecond.leftDirectory), + toWx(cfgSecond.rightDirectory), cfgSecond.altSyncConfig, cfgSecond.localFilter); @@ -3780,43 +3946,55 @@ void MainDialog::updateGuiForFolderPair() m_bpButtonLocalFilter->Hide(); m_bpButtonAltSyncCfg->Hide(); - m_bpButtonSwapSides->SetBitmapLabel(GlobalResources::instance().getImage(wxT("swap"))); + setBitmapLabel(*m_bpButtonSwapSides, GlobalResources::instance().getImage(wxT("swap"))); } else { m_bpButtonLocalFilter->Show(); m_bpButtonAltSyncCfg->Show(); - m_bpButtonSwapSides->SetBitmapLabel(GlobalResources::instance().getImage(wxT("swapSlim"))); + setBitmapLabel(*m_bpButtonSwapSides, GlobalResources::instance().getImage(wxT("swapSlim"))); } m_panelTopMiddle->Layout(); - - int addPairHeight = 0; + int addPairMinimalHeight = 0; + int addPairOptimalHeight = 0; if (additionalFolderPairs.size() > 0) - addPairHeight = std::min(1.5, additionalFolderPairs.size()) * //have 0.5 * height indicate that more folders are there - additionalFolderPairs[0]->GetSize().GetHeight(); + { + int pairHeight = additionalFolderPairs[0]->GetSize().GetHeight(); + addPairMinimalHeight = std::min(1.5, additionalFolderPairs.size()) * pairHeight; //have 0.5 * height indicate that more folders are there + addPairOptimalHeight = std::min(globalSettings->gui.maxFolderPairsVisible - 1 + 0.5, //subtract first/main folder pair and add 0.5 to indicate additional folders + additionalFolderPairs.size()) * pairHeight; + + addPairOptimalHeight = std::max(addPairOptimalHeight, addPairMinimalHeight); //implicitly handle corrupted values for "maxFolderPairsVisible" + } + + //######################################################################################################################## + //wxAUI hack: set minimum height to desired value, then call wxAuiPaneInfo::Fixed() to apply it + auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, m_panelTopLeft->GetSize().GetHeight() + addPairOptimalHeight); + auiMgr.GetPane(m_panelDirectoryPairs).Fixed(); + auiMgr.Update(); + + //now make resizable again + auiMgr.GetPane(m_panelDirectoryPairs).Resizable(); + auiMgr.Update(); + //######################################################################################################################## //ensure additional folder pairs are at least partially visible - auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, m_panelTopLeft->GetSize().GetHeight() + addPairHeight); + auiMgr.GetPane(m_panelDirectoryPairs).MinSize(-1, m_panelTopLeft->GetSize().GetHeight() + addPairMinimalHeight); auiMgr.Update(); m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size //m_scrolledWindowFolderPairs->Layout(); //adjust stuff inside scrolled window m_panelDirectoryPairs->Layout(); - - /* - #warning test - auiMgr.GetPane(m_panelDirectoryPairs).MaxSize(20, 20); - auiMgr.Update(); - */ } void MainDialog::addFolderPair(const std::vector& newPairs, bool addFront) { wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelGrids); // if (!newPairs.empty()) { @@ -3845,8 +4023,8 @@ void MainDialog::addFolderPair(const std::vector& newPairs, bool newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), NULL, this); //set alternate configuration - newPair->setValues(zToWx(i->leftDirectory), - zToWx(i->rightDirectory), + newPair->setValues(toWx(i->leftDirectory), + toWx(i->rightDirectory), i->altSyncConfig, i->localFilter); } @@ -3867,6 +4045,7 @@ void MainDialog::addFolderPair(const std::vector& newPairs, bool void MainDialog::removeAddFolderPair(size_t pos) { wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelGrids); // if (pos < additionalFolderPairs.size()) { @@ -3896,6 +4075,7 @@ void MainDialog::removeAddFolderPair(size_t pos) void MainDialog::clearAddFolderPairs() { wxWindowUpdateLocker dummy(m_panelDirectoryPairs); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelGrids); // additionalFolderPairs.clear(); bSizerAddFolderPairs->Clear(true); @@ -3917,8 +4097,6 @@ void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event) namespace { -typedef Zbase zxString; - inline void addCellValue(zxString& exportString, const wxString& cellVal) { @@ -3934,20 +4112,16 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) { //get a filename const wxString defaultFileName = wxT("FileList.csv"); //proposal - wxFileDialog filePicker(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("Comma separated list")) + wxT(" (*.csv)|*.csv"), wxFD_SAVE); //creating this on freestore leads to memleak! + wxFileDialog filePicker(this, + wxEmptyString, + wxEmptyString, + defaultFileName, + wxString(_("Comma separated list")) + wxT(" (*.csv)|*.csv"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //creating this on freestore leads to memleak! if (filePicker.ShowModal() == wxID_OK) { const wxString newFileName = filePicker.GetPath(); - if (zen::fileExists(wxToZ(newFileName))) - { - if (showQuestionDlg(ReturnQuestionDlg::BUTTON_YES | ReturnQuestionDlg::BUTTON_CANCEL, - wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")) != ReturnQuestionDlg::BUTTON_YES) - { - OnMenuExportFileList(event); //retry - return; - } - } zxString exportString; //perf: wxString doesn't model exponential growth and so is out @@ -4034,7 +4208,7 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) size_t bufferSize = 0; const wxCharBuffer utf8buffer = wxConvUTF8.cWC2MB(exportString.c_str(), exportString.size(), &bufferSize); - output.Write(common::BYTE_ORDER_MARK_UTF8, sizeof(common::BYTE_ORDER_MARK_UTF8) - 1); + output.Write(BYTE_ORDER_MARK_UTF8, sizeof(BYTE_ORDER_MARK_UTF8) - 1); output.Write(utf8buffer, bufferSize); pushStatusInformation(_("File list exported!")); } @@ -4049,7 +4223,7 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) void MainDialog::OnMenuBatchJob(wxCommandEvent& event) { //fill batch config structure - const xmlAccess::XmlGuiConfig currCfg = getCurrentConfiguration(); //get UP TO DATE config, with updated values for main and additional folders! + const xmlAccess::XmlGuiConfig currCfg = getConfig(); //get UP TO DATE config, with updated values for main and additional folders! const xmlAccess::XmlBatchConfig batchCfg = convertGuiToBatch(currCfg); @@ -4115,7 +4289,7 @@ void MainDialog::switchProgramLanguage(const int langID) //create new dialog with respect to new language zen::setLanguage(langID); //language is a global attribute - const xmlAccess::XmlGuiConfig currentGuiCfg = getCurrentConfiguration(); + const xmlAccess::XmlGuiConfig currentGuiCfg = getConfig(); cleanUp(false); //destructor's code: includes updating global settings @@ -4151,24 +4325,11 @@ bool MainDialog::SyncPreview::previewIsEnabled() const void MainDialog::SyncPreview::enablePreview(bool value) { - if (value) - { - syncPreviewEnabled = true; + syncPreviewEnabled = value; - //toggle display of sync preview in middle grid - mainDlg_->m_gridMiddle->enableSyncPreview(true); - - mainDlg_->Refresh(); - } - else - { - syncPreviewEnabled = false; - - //toggle display of sync preview in middle grid - mainDlg_->m_gridMiddle->enableSyncPreview(false); - - mainDlg_->Refresh(); - } + //toggle display of sync preview in middle grid + mainDlg_->m_gridMiddle->enableSyncPreview(value); + // mainDlg_->Refresh(); mainDlg_->updateGuiGrid(); } @@ -4176,15 +4337,15 @@ void MainDialog::SyncPreview::enablePreview(bool value) void MainDialog::SyncPreview::enableSynchronization(bool value) { + synchronizationEnabled = value; + if (value) { - synchronizationEnabled = true; mainDlg_->m_buttonStartSync->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT)); mainDlg_->m_buttonStartSync->setBitmapFront(GlobalResources::instance().getImage(wxT("sync"))); } else { - synchronizationEnabled = false; mainDlg_->m_buttonStartSync->SetForegroundColour(wxColor(128, 128, 128)); //Some colors seem to have problems with 16Bit color depth, well this one hasn't! mainDlg_->m_buttonStartSync->setBitmapFront(GlobalResources::instance().getImage(wxT("syncDisabled"))); } diff --git a/ui/main_dlg.h b/ui/main_dlg.h index 4d00ff2a..47adf4a9 100644 --- a/ui/main_dlg.h +++ b/ui/main_dlg.h @@ -46,8 +46,8 @@ public: ~MainDialog(); - void disableAllElements(bool enableAbort); //dis-/enables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion - void enableAllElements(); // + void disableAllElements(bool enableAbort); //dis-/enables all elements (except abort button) that might receive user input + void enableAllElements(); //during long-running processes: comparison, deletion private: friend class CompareStatusHandler; @@ -68,18 +68,23 @@ private: void cleanUp(bool saveLastUsedConfig); //configuration load/save - bool readConfigurationFromXml(const wxString& filename); - bool writeConfigurationToXml(const wxString& filename); void setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig); + void setLastUsedConfig(const std::vector& filenames, const xmlAccess::XmlGuiConfig& guiConfig); - xmlAccess::XmlGuiConfig getCurrentConfiguration() const; - void setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCfg); + xmlAccess::XmlGuiConfig getConfig() const; + void setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg); + + void loadConfiguration(const wxString& filename); + void loadConfiguration(const std::vector& filenames); + + bool trySaveConfig(); //return true if saved successfully + bool saveOldConfig(); //return false on user abort static const wxString& lastRunConfigName(); xmlAccess::XmlGuiConfig lastConfigurationSaved; //support for: "Save changed configuration?" dialog //used when saving configuration - wxString currentConfigFileName; + std::vector activeConfigFiles; //name of currently loaded config file (may be more than 1) void readGlobalSettings(); void writeGlobalSettings(); @@ -87,7 +92,8 @@ private: void initViewFilterButtons(); void updateFilterButtons(); - void addFileToCfgHistory(const wxString& filename); + void addFileToCfgHistory(const std::vector& filenames); + void addLeftFolderToHistory(const wxString& leftFolder); void addRightFolderToHistory(const wxString& rightFolder); @@ -131,6 +137,14 @@ private: void OnContextSetLayout( wxMouseEvent& event); void OnGlobalKeyEvent( wxKeyEvent& event); + void OnContextSelectCompVariant( wxMouseEvent& event); + void OnContextSelectSyncVariant( wxMouseEvent& event); + + void applyCompareConfig(); + + void OnSetCompVariant(wxCommandEvent& event); + void OnSetSyncVariant(wxCommandEvent& event); + //context menu handler methods void OnContextFilterTemp (wxCommandEvent& event); void OnContextExcludeExtension (wxCommandEvent& event); @@ -182,15 +196,12 @@ private: void OnSaveConfig( wxCommandEvent& event); void OnLoadConfig( wxCommandEvent& event); void OnLoadFromHistory( wxCommandEvent& event); - bool trySaveConfig(); //return true if saved successfully - bool saveOldConfig(); //return false on user abort - void loadConfiguration(const wxString& filename); void OnCfgHistoryKeyEvent( wxKeyEvent& event); void OnRegularUpdateCheck( wxIdleEvent& event); void OnLayoutWindowAsync( wxIdleEvent& event); - void refreshGridAfterFilterChange(const int delay); + void refreshGridAfterFilterChange(int delay); void OnResize( wxSizeEvent& event); //void OnResizeTopButtons( wxEvent& event); diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp index 949384b9..e244877a 100644 --- a/ui/progress_indicator.cpp +++ b/ui/progress_indicator.cpp @@ -67,7 +67,7 @@ public: void switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); void incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusPanelNow(); private: @@ -76,7 +76,7 @@ private: //status variables size_t scannedObjects; - Zstring currentStatusText; + wxString currentStatusText; wxStopWatch timeElapsed; @@ -146,7 +146,7 @@ void CompareStatus::incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int6 pimpl->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); } -void CompareStatus::setStatusText_NoUpdate(const Zstring& text) +void CompareStatus::setStatusText_NoUpdate(const wxString& text) { pimpl->setStatusText_NoUpdate(text); } @@ -276,7 +276,7 @@ void CompareStatus::CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsP } -void CompareStatus::CompareStatusImpl::setStatusText_NoUpdate(const Zstring& text) +void CompareStatus::CompareStatusImpl::setStatusText_NoUpdate(const wxString& text) { currentStatusText = text; } @@ -334,10 +334,8 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() bool updateLayout = false; //avoid screen flicker by calling layout() only if necessary //remove linebreaks from currentStatusText - wxString formattedStatusText = zToWx(currentStatusText); - for (wxString::iterator i = formattedStatusText.begin(); i != formattedStatusText.end(); ++i) - if (*i == wxChar('\n')) - *i = wxChar(' '); + wxString formattedStatusText = currentStatusText; + replace(formattedStatusText, L'\n', L' '); //status texts if (m_textCtrlStatus->GetValue() != formattedStatusText) //no layout update for status texts! @@ -490,7 +488,7 @@ public: void resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); void incScannedObjects_NoUpdate(int number); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusDialogNow(); void setCurrentStatus(SyncStatus::SyncStatusID id); @@ -525,7 +523,7 @@ private: //status variables size_t scannedObjects; - Zstring currentStatusText; + wxString currentStatusText; bool processPaused; SyncStatus::SyncStatusID currentStatus; @@ -596,7 +594,7 @@ void SyncStatus::incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 pimpl->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); } -void SyncStatus::setStatusText_NoUpdate(const Zstring& text) +void SyncStatus::setStatusText_NoUpdate(const wxString& text) { pimpl->setStatusText_NoUpdate(text); } @@ -661,14 +659,14 @@ SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb, 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->EnableCloseButton(false); mainDialog->disableAllElements(false); //disable all child elements - } timeElapsed.Start(); //measure total time @@ -697,7 +695,6 @@ SyncStatus::SyncStatusImpl::~SyncStatusImpl() { if (mainDialog) { - mainDialog->EnableCloseButton(true); mainDialog->enableAllElements(); //restore title text @@ -716,7 +713,21 @@ void SyncStatus::SyncStatusImpl::OnKeyPressed(wxKeyEvent& event) { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_ESCAPE) - Close(); //generate close event: do NOT destroy window unconditionally! + { + wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); + + //simulate click on abort button + if (m_buttonAbort->IsShown()) //delegate to "abort" button if available + { + m_buttonAbort->GetEventHandler()->ProcessEvent(dummy); + return; + } + else if (m_buttonOK->IsShown()) //delegate to "abort" button if available + { + m_buttonOK->GetEventHandler()->ProcessEvent(dummy); + return; + } + } event.Skip(); } @@ -762,7 +773,7 @@ void SyncStatus::SyncStatusImpl::incScannedObjects_NoUpdate(int number) } -void SyncStatus::SyncStatusImpl::setStatusText_NoUpdate(const Zstring& text) +void SyncStatus::SyncStatusImpl::setStatusText_NoUpdate(const wxString& text) { currentStatusText = text; } @@ -833,7 +844,7 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow() //static RetrieveStatistics statistic; //statistic.writeEntry(currentData.ToDouble(), currentObjects); - const float percent = totalData == 0 ? 0 : to(currentData) * 100.0 / to(totalData); + const float percent = totalData == 0 ? 100.0 : to(currentData) * 100.0 / to(totalData); //write status information to systray, taskbar, parent title ect. @@ -886,9 +897,8 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow() } //status text - const wxString statusTxt = zToWx(currentStatusText); - if (m_textCtrlInfo->GetValue() != statusTxt) //no layout update for status texts! - m_textCtrlInfo->ChangeValue(statusTxt); + if (m_textCtrlInfo->GetValue() != currentStatusText) //no layout update for status texts! + m_textCtrlInfo->ChangeValue(currentStatusText); //remaining objects const wxString remainingObjTmp = toStringSep(totalObjects - currentObjects); @@ -1016,6 +1026,8 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, resumeFromSystray(); //if in tray mode... + EnableCloseButton(true); + m_buttonAbort->Disable(); m_buttonAbort->Hide(); m_buttonPause->Disable(); @@ -1074,7 +1086,7 @@ void SyncStatus::SyncStatusImpl::OnAbort(wxCommandEvent& event) m_buttonPause->Disable(); m_buttonPause->Hide(); - setStatusText_NoUpdate(wxToZ(_("Abort requested: Waiting for current operation to finish..."))); + setStatusText_NoUpdate(_("Abort requested: Waiting for current operation to finish...")); //no Layout() or UI-update here to avoid cascaded Yield()-call abortCb_->requestAbortion(); @@ -1114,17 +1126,11 @@ void SyncStatus::SyncStatusImpl::OnPause(wxCommandEvent& event) void SyncStatus::SyncStatusImpl::OnClose(wxCloseEvent& event) { - if (m_buttonAbort->IsShown()) //delegate to "abort" button if available - { - wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); - m_buttonAbort->GetEventHandler()->ProcessEvent(dummy); - - if (event.CanVeto()) - { - event.Veto(); //that's what we want here - return; - } - } + //this event handler may be called due to a system shutdown DURING synchronization! + //try to stop sync gracefully and cross fingers: + if (currentProcessIsRunning()) + 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) Destroy(); } diff --git a/ui/progress_indicator.h b/ui/progress_indicator.h index 528ec562..9bb0eed0 100644 --- a/ui/progress_indicator.h +++ b/ui/progress_indicator.h @@ -32,7 +32,7 @@ public: void switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); void incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusPanelNow(); private: @@ -67,7 +67,7 @@ public: void resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); void incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); - void setStatusText_NoUpdate(const Zstring& text); + void setStatusText_NoUpdate(const wxString& text); void updateStatusDialogNow(); void setCurrentStatus(SyncStatusID id); diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp index f6694586..ed28a166 100644 --- a/ui/small_dlgs.cpp +++ b/ui/small_dlgs.cpp @@ -296,8 +296,8 @@ void FilterDlg::updateGui() void FilterDlg::setFilter(const FilterConfig& filter) { - m_textCtrlInclude->ChangeValue(zToWx(filter.includeFilter)); - m_textCtrlExclude->ChangeValue(zToWx(filter.excludeFilter)); + m_textCtrlInclude->ChangeValue(toWx(filter.includeFilter)); + m_textCtrlExclude->ChangeValue(toWx(filter.excludeFilter)); setEnumVal(enumTimeDescr, *m_choiceUnitTimespan, filter.unitTimeSpan); setEnumVal(enumSizeDescr, *m_choiceUnitMinSize, filter.unitSizeMin); @@ -313,8 +313,8 @@ void FilterDlg::setFilter(const FilterConfig& filter) FilterConfig FilterDlg::getFilter() const { - return FilterConfig(wxToZ(m_textCtrlInclude->GetValue()), - wxToZ(m_textCtrlExclude->GetValue()), + return FilterConfig(toZ(m_textCtrlInclude->GetValue()), + toZ(m_textCtrlExclude->GetValue()), m_spinCtrlTimespan->GetValue(), getEnumVal(enumTimeDescr, *m_choiceUnitTimespan), m_spinCtrlMinSize->GetValue(), @@ -458,7 +458,7 @@ void DeleteDialog::updateGui() header.Replace(wxT("%x"), toStringSep(delInfo.second)); m_staticTextHeader->SetLabel(header); - const wxString filesToDelete = delInfo.first; + const wxString& filesToDelete = delInfo.first; m_textCtrlMessage->SetValue(filesToDelete); Layout(); @@ -733,71 +733,29 @@ class CompareCfgDialog : public CmpCfgDlgGenerated { public: CompareCfgDialog(wxWindow* parent, - const wxPoint& position, zen::CompareVariant& cmpVar, SymLinkHandling& handleSymlinks); private: void OnOkay(wxCommandEvent& event); - void OnClose(wxCloseEvent& event); - void OnCancel(wxCommandEvent& event); + void OnClose(wxCloseEvent& event) { EndModal(0); } + void OnCancel(wxCommandEvent& event) { EndModal(0); } void OnTimeSize(wxCommandEvent& event); + void OnTimeSizeDouble(wxMouseEvent& event); void OnContent(wxCommandEvent& event); + void OnContentDouble(wxMouseEvent& event); void OnShowHelp(wxCommandEvent& event); void updateView(); zen::CompareVariant& cmpVarOut; SymLinkHandling& handleSymlinksOut; -}; - -namespace -{ -void setValue(wxChoice& choiceCtrl, zen::SymLinkHandling value) -{ - choiceCtrl.Clear(); - choiceCtrl.Append(_("Ignore")); - choiceCtrl.Append(_("Direct")); - choiceCtrl.Append(_("Follow")); - - //default - choiceCtrl.SetSelection(0); - - switch (value) - { - case zen::SYMLINK_IGNORE: - choiceCtrl.SetSelection(0); - break; - case zen::SYMLINK_USE_DIRECTLY: - choiceCtrl.SetSelection(1); - break; - case zen::SYMLINK_FOLLOW_LINK: - choiceCtrl.SetSelection(2); - break; - } -} + zen::EnumDescrList enumDescrHandleSyml; +}; -zen::SymLinkHandling getValue(const wxChoice& choiceCtrl) -{ - switch (choiceCtrl.GetSelection()) - { - case 0: - return zen::SYMLINK_IGNORE; - case 1: - return zen::SYMLINK_USE_DIRECTLY; - case 2: - return zen::SYMLINK_FOLLOW_LINK; - default: - assert(false); - return zen::SYMLINK_IGNORE; - } -} -} - CompareCfgDialog::CompareCfgDialog(wxWindow* parent, - const wxPoint& position, CompareVariant& cmpVar, SymLinkHandling& handleSymlinks) : CmpCfgDlgGenerated(parent), @@ -808,8 +766,13 @@ CompareCfgDialog::CompareCfgDialog(wxWindow* parent, new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" #endif + enumDescrHandleSyml. + add(SYMLINK_IGNORE, _("Ignore")). + add(SYMLINK_USE_DIRECTLY, _("Direct")). + add(SYMLINK_FOLLOW_LINK, _("Follow")); + //move dialog up so that compare-config button and first config-variant are on same level - Move(wxPoint(position.x, std::max(0, position.y - (m_buttonTimeSize->GetScreenPosition() - GetScreenPosition()).y))); + // Move(wxPoint(position.x, std::max(0, position.y - (m_buttonTimeSize->GetScreenPosition() - GetScreenPosition()).y))); m_bpButtonHelp ->SetBitmapLabel(GlobalResources::instance().getImage(wxT("help"))); m_bitmapByTime ->SetBitmap (GlobalResources::instance().getImage(wxT("clock"))); @@ -827,8 +790,7 @@ CompareCfgDialog::CompareCfgDialog(wxWindow* parent, break; } - - setValue(*m_choiceHandleSymlinks, handleSymlinks); + setEnumVal(enumDescrHandleSyml, *m_choiceHandleSymlinks, handleSymlinks); updateView(); } @@ -845,35 +807,37 @@ void CompareCfgDialog::OnOkay(wxCommandEvent& event) else cmpVarOut = CMP_BY_TIME_SIZE; - handleSymlinksOut = getValue(*m_choiceHandleSymlinks);; + handleSymlinksOut = getEnumVal(enumDescrHandleSyml, *m_choiceHandleSymlinks); EndModal(ReturnSmallDlg::BUTTON_OKAY); } -void CompareCfgDialog::OnClose(wxCloseEvent& event) +void CompareCfgDialog::OnTimeSize(wxCommandEvent& event) { - EndModal(0); + m_radioBtnSizeDate->SetValue(true); } -void CompareCfgDialog::OnCancel(wxCommandEvent& event) +void CompareCfgDialog::OnContent(wxCommandEvent& event) { - EndModal(0); + m_radioBtnContent->SetValue(true); } -void CompareCfgDialog::OnTimeSize(wxCommandEvent& event) +void CompareCfgDialog::OnTimeSizeDouble(wxMouseEvent& event) { - m_radioBtnSizeDate->SetValue(true); - OnOkay(event); + wxCommandEvent dummy; + OnTimeSize(dummy); + OnOkay(dummy); } -void CompareCfgDialog::OnContent(wxCommandEvent& event) +void CompareCfgDialog::OnContentDouble(wxMouseEvent& event) { - m_radioBtnContent->SetValue(true); - OnOkay(event); + wxCommandEvent dummy; + OnContent(dummy); + OnOkay(dummy); } @@ -884,12 +848,10 @@ void CompareCfgDialog::OnShowHelp(wxCommandEvent& event) } -ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog( - const wxPoint& position, - CompareVariant& cmpVar, - SymLinkHandling& handleSymlinks) +ReturnSmallDlg::ButtonPressed zen::showCompareCfgDialog(CompareVariant& cmpVar, + SymLinkHandling& handleSymlinks) { - CompareCfgDialog syncDlg(NULL, position, cmpVar, handleSymlinks); + CompareCfgDialog syncDlg(NULL, cmpVar, handleSymlinks); return static_cast(syncDlg.ShowModal()); } diff --git a/ui/small_dlgs.h b/ui/small_dlgs.h index 06fb9964..31fd4548 100644 --- a/ui/small_dlgs.h +++ b/ui/small_dlgs.h @@ -43,7 +43,6 @@ ReturnSmallDlg::ButtonPressed showSyncPreviewDlg( bool& dontShowAgain); ReturnSmallDlg::ButtonPressed showCompareCfgDialog( - const wxPoint& position, CompareVariant& cmpVar, SymLinkHandling& handleSymlinks); diff --git a/ui/sorting.h b/ui/sorting.h index 28f0b8e4..d2bafd1d 100644 --- a/ui/sorting.h +++ b/ui/sorting.h @@ -8,7 +8,6 @@ #define SORTING_H_INCLUDED #include "../file_hierarchy.h" -#include "../shared/system_constants.h" #include "../synchronization.h" #include "../shared/assert_static.h" diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp index 0bbe8809..59d4d689 100644 --- a/ui/sync_cfg.cpp +++ b/ui/sync_cfg.cpp @@ -40,6 +40,11 @@ private: virtual void OnSyncUpdate( wxCommandEvent& event); virtual void OnSyncCustom( wxCommandEvent& event); + virtual void OnSyncAutomaticDouble( wxMouseEvent& event); + virtual void OnSyncMirrorDouble( wxMouseEvent& event); + virtual void OnSyncUpdateDouble( wxMouseEvent& event); + virtual void OnSyncCustomDouble( wxMouseEvent& event); + virtual void OnExLeftSideOnly( wxCommandEvent& event); virtual void OnExRightSideOnly( wxCommandEvent& event); virtual void OnLeftNewer( wxCommandEvent& event); @@ -47,8 +52,8 @@ private: virtual void OnDifferent( wxCommandEvent& event); virtual void OnConflict( wxCommandEvent& event); - virtual void OnClose( wxCloseEvent& event); - virtual void OnCancel( wxCommandEvent& event); + virtual void OnClose( wxCloseEvent& event) { EndModal(0); } + virtual void OnCancel( wxCommandEvent& event) { EndModal(0); } virtual void OnApply( wxCommandEvent& event); void updateGui(); @@ -332,18 +337,6 @@ void SyncCfgDialog::updateGui() } -void SyncCfgDialog::OnClose(wxCloseEvent& event) -{ - EndModal(0); -} - - -void SyncCfgDialog::OnCancel(wxCommandEvent& event) -{ - EndModal(0); -} - - void SyncCfgDialog::OnApply(wxCommandEvent& event) { //write configuration to main dialog @@ -399,6 +392,35 @@ void SyncCfgDialog::OnSyncCustom(wxCommandEvent& event) } +void SyncCfgDialog::OnSyncAutomaticDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncAutomatic(dummy); + OnApply(dummy); +} + +void SyncCfgDialog::OnSyncMirrorDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncMirror(dummy); + OnApply(dummy); +} + +void SyncCfgDialog::OnSyncUpdateDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncUpdate(dummy); + OnApply(dummy); +} + +void SyncCfgDialog::OnSyncCustomDouble(wxMouseEvent& event) +{ + wxCommandEvent dummy; + OnSyncCustom(dummy); + OnApply(dummy); +} + + void toggleSyncDirection(SyncDirection& current) { switch (current) -- cgit