summaryrefslogtreecommitdiff
path: root/ui/main_dlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/main_dlg.cpp')
-rw-r--r--ui/main_dlg.cpp522
1 files changed, 283 insertions, 239 deletions
diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp
index 894b0b11..2d52d45e 100644
--- a/ui/main_dlg.cpp
+++ b/ui/main_dlg.cpp
@@ -1,7 +1,7 @@
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) ZenJu (zenju AT gmx DOT de) - All Rights Reserved *
+// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
#include "main_dlg.h"
@@ -17,6 +17,7 @@
#include <wx/app.h>
#include <wx/dcmemory.h>
#include <wx/filedlg.h>
+#include <zen/format_unit.h>
#include <wx+/context_menu.h>
#include "folder_history_box.h"
#include <wx+/button.h>
@@ -24,7 +25,6 @@
#include "../synchronization.h"
#include "../algorithm.h"
#include <wx+/app_main.h>
-#include <wx+/format_unit.h>
#include "check_version.h"
#include "gui_status_handler.h"
#include "sync_cfg.h"
@@ -158,13 +158,13 @@ private:
}
virtual MainConfiguration getMainConfig() const { return mainDlg.getConfig().mainCfg; }
- virtual void OnAltCompCfgChange() { mainDlg.applyCompareConfig(false); } //false: do not change preview status
- virtual void OnAltSyncCfgChange() { mainDlg.applySyncConfig(); }
+ virtual void OnAltCompCfgChange() { mainDlg.applyCompareConfig(); }
+ virtual void OnAltSyncCfgChange() { mainDlg.applySyncConfig (); }
virtual void removeAltCompCfg()
{
FolderPairPanelBasic<GuiPanel>::removeAltCompCfg();
- mainDlg.applyCompareConfig(false); //false: do not change preview status
+ mainDlg.applyCompareConfig();
}
virtual void removeAltSyncCfg()
@@ -196,8 +196,11 @@ public:
dirNameLeft (*m_panelLeft, *m_buttonSelectDirLeft, *m_directoryLeft),
dirNameRight(*m_panelRight, *m_buttonSelectDirRight, *m_directoryRight)
{
- dirNameLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::OnDirSelected), nullptr, &mainDialog);
- dirNameRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::OnDirSelected), nullptr, &mainDialog);
+ dirNameLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog);
+ dirNameRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog);
+
+ dirNameLeft .Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog);
+ dirNameRight.Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog);
}
void setValues(const wxString& leftDir,
@@ -240,8 +243,11 @@ public:
*mainDialog.m_directoryRight,
*mainDialog.m_staticTextFinalPathRight)
{
- dirNameLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::OnDirSelected), nullptr, &mainDialog);
- dirNameRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::OnDirSelected), nullptr, &mainDialog);
+ dirNameLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog);
+ dirNameRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog);
+
+ dirNameLeft .Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog);
+ dirNameRight.Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog);
}
void setValues(const wxString& leftDir,
@@ -264,53 +270,6 @@ private:
};
-//workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build)
-class MenuItemUpdater
-{
-public:
- MenuItemUpdater(wxMenu& menuToUpdate) : menuToUpdate_(menuToUpdate) {}
-
- ~MenuItemUpdater()
- {
- wxMenuItemList allItems = menuToUpdate_.GetMenuItems();
-
- //retrieve menu item positions: unfortunately wxMenu doesn't offer a better way
- int index = 0;
- for (auto itemIter = allItems.begin(); itemIter != allItems.end(); ++itemIter, ++index) //wxMenuItemList + std::for_each screws up with VS2010!
- {
- wxMenuItem* item = *itemIter;
-
- auto iter = menuItems.find(item);
- if (iter != menuItems.end())
- {
- /*
- menuToUpdate_.Remove(item); ->this simple sequence crashes on Kubuntu x64, wxWidgets 2.9.2
- menuToUpdate_.Insert(index, item);
- */
-
- const wxBitmap& bmp = iter->second;
-
- wxMenuItem* newItem = new wxMenuItem(&menuToUpdate_, item->GetId(), item->GetItemLabel());
- newItem->SetBitmap(bmp);
-
- menuToUpdate_.Destroy(item); //actual workaround
- menuToUpdate_.Insert(index, newItem); //
- }
- }
- }
-
- void markForUpdate(wxMenuItem* newEntry, const wxBitmap& bmp)
- {
- menuItems.insert(std::make_pair(newEntry, bmp));
- }
-
-private:
- wxMenu& menuToUpdate_;
- std::map<wxMenuItem*, wxBitmap> menuItems;
-};
-
-
-
#ifdef FFS_WIN
class PanelMoveWindow : public MouseMoveWindow
{
@@ -337,11 +296,65 @@ private:
#endif
+namespace
+{
+//workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build)
+void setMenuItemImage(wxMenuItem*& menuItem, const wxBitmap& bmp)
+{
+ assert(menuItem->GetKind() == wxITEM_NORMAL);
+
+ //support polling
+ if (isEqual(bmp, menuItem->GetBitmap()))
+ return;
+
+ if (wxMenu* menu = menuItem->GetMenu())
+ {
+ int pos = menu->GetMenuItems().IndexOf(menuItem);
+ if (pos != wxNOT_FOUND)
+ {
+ /*
+ menu->Remove(item); ->this simple sequence crashes on Kubuntu x64, wxWidgets 2.9.2
+ menu->Insert(index, item);
+ */
+ const bool enabled = menuItem->IsEnabled();
+ wxMenuItem* newItem = new wxMenuItem(menu, menuItem->GetId(), menuItem->GetItemLabel());
+ newItem->SetBitmap(bmp);
+
+ menu->Destroy(menuItem); //actual workaround
+ menuItem = menu->Insert(pos, newItem); //don't forget to update input item pointer!
+
+ if (!enabled)
+ menuItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason
+ }
+ }
+}
+
//##################################################################################################################################
-MainDialog::MainDialog(const std::vector<wxString>& cfgFileNames, const xmlAccess::XmlGlobalSettings& globalSettings) :
- MainDialogGenerated(nullptr)
+
+xmlAccess::XmlGlobalSettings retrieveGlobalCfgFromDisk() //blocks on GUI on errors!
+{
+ using namespace xmlAccess;
+ XmlGlobalSettings globalCfg;
+ try
+ {
+ if (fileExists(toZ(getGlobalConfigFile())))
+ readConfig(globalCfg); //throw FfsXmlError
+ //else: globalCfg already has default values
+ }
+ catch (const FfsXmlError& e)
+ {
+ if (e.getSeverity() != FfsXmlError::WARNING) //ignore parsing errors: should be migration problems only *cross-fingers*
+ wxMessageBox(e.toString(), _("Error"), wxOK | wxICON_ERROR);
+ }
+ return globalCfg;
+}
+}
+
+
+void MainDialog::create(const std::vector<wxString>& cfgFileNames)
{
- xmlAccess::XmlGuiConfig guiCfg; //structure to receive gui settings, already defaulted!!
+ using namespace xmlAccess;
+ const XmlGlobalSettings globalSettings = retrieveGlobalCfgFromDisk();
std::vector<wxString> filenames;
if (!cfgFileNames.empty()) //1. this one has priority
@@ -375,93 +388,77 @@ MainDialog::MainDialog(const std::vector<wxString>& cfgFileNames, const xmlAcces
}
}
+ XmlGuiConfig guiCfg; //structure to receive gui settings with default values
+
bool loadCfgSuccess = false;
if (!filenames.empty())
try
{
- //load XML
- xmlAccess::convertConfig(toZ(filenames), guiCfg); //throw xmlAccess::FfsXmlError
-
+ mergeConfigs(toZ(filenames), guiCfg); //throw FfsXmlError
loadCfgSuccess = true;
}
- catch (const xmlAccess::FfsXmlError& error)
+ catch (const FfsXmlError& error)
{
- if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
- wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
+ if (error.getSeverity() == FfsXmlError::WARNING)
+ wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING);
+ //what about simulating changed config on parsing errors????
else
- wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
+ wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR);
}
const bool startComparisonImmediately = !cfgFileNames.empty() && loadCfgSuccess;
- init(guiCfg,
- globalSettings,
- startComparisonImmediately);
+ //------------------------------------------------------------------------------------------
- setLastUsedConfig(filenames, loadCfgSuccess ? guiCfg : xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors
+ create_impl(guiCfg, filenames, globalSettings, startComparisonImmediately);
}
-MainDialog::MainDialog(const std::vector<wxString>& referenceFiles,
- const xmlAccess::XmlGuiConfig& guiCfg,
- const xmlAccess::XmlGlobalSettings& globalSettings,
- bool startComparison) :
- MainDialogGenerated(nullptr)
+void MainDialog::create(const xmlAccess::XmlGuiConfig& guiCfg,
+ bool startComparison)
{
- init(guiCfg,
- globalSettings,
- startComparison);
+ create_impl(guiCfg, std::vector<wxString>(), retrieveGlobalCfgFromDisk(), startComparison);
+}
+
- setLastUsedConfig(referenceFiles, guiCfg);
+void MainDialog::create(const xmlAccess::XmlGuiConfig& guiCfg,
+ const std::vector<wxString>& referenceFiles,
+ const xmlAccess::XmlGlobalSettings& globalSettings,
+ bool startComparison)
+{
+ create_impl(guiCfg, referenceFiles, globalSettings, startComparison);
}
-MainDialog::~MainDialog()
+void MainDialog::create_impl(const xmlAccess::XmlGuiConfig& guiCfg,
+ const std::vector<wxString>& referenceFiles,
+ const xmlAccess::XmlGlobalSettings& globalSettings,
+ bool startComparison)
{
- try //save "GlobalSettings.xml"
- {
- xmlAccess::writeConfig(getGlobalCfgBeforeExit()); //throw FfsXmlError
- }
- catch (const xmlAccess::FfsXmlError& e)
+ try
{
- wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
+ //we need to set language *before* creating MainDialog!
+ setLanguage(globalSettings.programLanguage); //throw FileError
}
-
- try //save "LastRun.ffs_gui"
+ catch (const FileError& e)
{
- xmlAccess::writeConfig(getConfig(), toZ(lastRunConfigName())); //throw FfsXmlError
+ wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR);
+ //continue!
}
- //don't annoy users on read-only drives: it's enough to show a single error message when saving global config
- catch (const xmlAccess::FfsXmlError&) {}
-
- //important! event source wxTheApp is NOT dependent on this instance -> disconnect!
- wxTheApp->Disconnect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this);
- wxTheApp->Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this);
-
- auiMgr.UnInit();
-
- //no need for wxEventHandler::Disconnect() here; event sources are components of this window and are destroyed, too
-}
-
-
-void MainDialog::onQueryEndSession()
-{
- try { xmlAccess::writeConfig(getGlobalCfgBeforeExit()); }
- catch (const xmlAccess::FfsXmlError&) {} //we try our best do to something useful in this extreme situation - no reason to notify or even log errors here!
- try { xmlAccess::writeConfig(getConfig(), toZ(lastRunConfigName())); }
- catch (const xmlAccess::FfsXmlError&) {}
+ MainDialog* frame = new MainDialog(guiCfg, referenceFiles, globalSettings, startComparison);
+ frame->Show();
}
-void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
- const xmlAccess::XmlGlobalSettings& globalSettings,
- bool startComparison)
+MainDialog::MainDialog(const xmlAccess::XmlGuiConfig& guiCfg,
+ const std::vector<wxString>& referenceFiles,
+ const xmlAccess::XmlGlobalSettings& globalSettings,
+ bool startComparison) :
+ MainDialogGenerated(nullptr),
+ showSyncAction_(false),
+ folderHistoryLeft (std::make_shared<FolderHistory>()), //make sure it is always bound
+ folderHistoryRight(std::make_shared<FolderHistory>()) //
{
- showSyncAction_ = false;
-
- folderHistoryLeft = std::make_shared<FolderHistory>(); //make sure it is always bound
- folderHistoryRight = std::make_shared<FolderHistory>(); //
-
m_directoryLeft ->init(folderHistoryLeft);
m_directoryRight->init(folderHistoryRight);
@@ -516,6 +513,14 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
auiMgr.Update();
+ //give panel captions bold typeface
+ if (wxAuiDockArt* artProvider = auiMgr.GetArtProvider())
+ {
+ wxFont font = artProvider->GetFont(wxAUI_DOCKART_CAPTION_FONT);
+ font.SetWeight(wxFONTWEIGHT_BOLD);
+ artProvider->SetFont(wxAUI_DOCKART_CAPTION_FONT, font);
+ }
+
auiMgr.GetPane(m_gridNavi).MinSize(-1, -1); //we successfully tricked wxAuiManager into setting an initial Window size :> incomplete API anyone??
auiMgr.Update(); //
@@ -581,16 +586,14 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
//initialize and load configuration
setGlobalCfgOnInit(globalSettings);
- setConfig(guiCfg);
+ setConfig(guiCfg, referenceFiles);
//set icons for this dialog
- m_buttonCompare ->setBitmapFront(GlobalResources::getImage(L"compare"));
+ m_buttonCompare ->setBitmapFront(GlobalResources::getImage(L"compare"), 5);
m_bpButtonSyncConfig->SetBitmapLabel(GlobalResources::getImage(L"syncConfig"));
m_bpButtonCmpConfig ->SetBitmapLabel(GlobalResources::getImage(L"cmpConfig"));
- m_bpButtonSave ->SetBitmapLabel(GlobalResources::getImage(L"save"));
m_bpButtonLoad ->SetBitmapLabel(GlobalResources::getImage(L"load"));
- m_bpButtonAddPair ->SetBitmapLabel(GlobalResources::getImage(L"addFolderPair"));
- //m_bitmapResizeCorner->SetBitmap(mirrorIfRtl(GlobalResources::getImage(L"statusEdge")));
+ m_bpButtonAddPair ->SetBitmapLabel(GlobalResources::getImage(L"item_add"));
{
IconBuffer tmp(IconBuffer::SIZE_SMALL);
const wxBitmap bmpFile = tmp.genericFileIcon();
@@ -604,32 +607,26 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
m_panelTopButtons->Layout(); //wxButtonWithImage size might have changed
- //menu icons: workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build)
- MenuItemUpdater updateMenuFile(*m_menuFile);
-
const int dummySize = 5;
wxImage dummyImg(dummySize, dummySize);
if (!dummyImg.HasAlpha())
dummyImg.InitAlpha();
std::fill(dummyImg.GetAlpha(), dummyImg.GetAlpha() + dummySize * dummySize, wxIMAGE_ALPHA_TRANSPARENT);
- updateMenuFile.markForUpdate(m_menuItem10, GlobalResources::getImage(L"compareSmall"));
- updateMenuFile.markForUpdate(m_menuItem11, GlobalResources::getImage(L"syncSmall"));
-
- updateMenuFile.markForUpdate(m_menuItemNew, dummyImg); //it's ridiculous, but wxWidgets screws up aligning short-cut label texts if we don't set an image!
- //updateMenuFile.markForUpdate(m_menuItemSave, dummyImg); //
- updateMenuFile.markForUpdate(m_menuItemSave, GlobalResources::getImage(L"saveSmall"));
+ //menu icons: workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build)
+ setMenuItemImage(m_menuItem10, GlobalResources::getImage(L"compareSmall"));
+ setMenuItemImage(m_menuItem11, GlobalResources::getImage(L"syncSmall"));
- //updateMenuFile.markForUpdate(m_menuItemSaveAs, GlobalResources::getImage(L"saveSmall"));
- updateMenuFile.markForUpdate(m_menuItemLoad, GlobalResources::getImage(L"loadSmall"));
+ setMenuItemImage(m_menuItemNew, dummyImg); //it's ridiculous, but wxWidgets screws up aligning short-cut label texts if we don't set an image!
+ setMenuItemImage(m_menuItemSaveAs, dummyImg);
+ setMenuItemImage(m_menuItemLoad, GlobalResources::getImage(L"loadSmall"));
+ setMenuItemImage(m_menuItemSave, GlobalResources::getImage(L"saveSmall"));
- MenuItemUpdater updateMenuAdv(*m_menuAdvanced);
- updateMenuAdv.markForUpdate(m_menuItemGlobSett, GlobalResources::getImage(L"settingsSmall"));
- updateMenuAdv.markForUpdate(m_menuItem7, GlobalResources::getImage(L"batchSmall"));
+ setMenuItemImage(m_menuItemGlobSett, GlobalResources::getImage(L"settingsSmall"));
+ setMenuItemImage(m_menuItem7, GlobalResources::getImage(L"batchSmall"));
- MenuItemUpdater updateMenuHelp(*m_menuHelp);
- updateMenuHelp.markForUpdate(m_menuItemManual, GlobalResources::getImage(L"helpSmall"));
- updateMenuHelp.markForUpdate(m_menuItemAbout, GlobalResources::getImage(L"aboutSmall"));
+ setMenuItemImage(m_menuItemManual, GlobalResources::getImage(L"helpSmall"));
+ setMenuItemImage(m_menuItemAbout, GlobalResources::getImage(L"aboutSmall"));
#ifdef FFS_LINUX
m_menuItemCheckVer->Enable(zen::isPortableVersion()); //disable update check for Linux installer-based version -> handled by .deb
@@ -639,7 +636,7 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
std::for_each(zen::ExistingTranslations::get().begin(), ExistingTranslations::get().end(),
[&](const ExistingTranslations::Entry& entry)
{
- wxMenuItem* newItem = new wxMenuItem(m_menuLanguages, wxID_ANY, entry.languageName, wxEmptyString, wxITEM_NORMAL );
+ wxMenuItem* newItem = new wxMenuItem(m_menuLanguages, wxID_ANY, entry.languageName);
newItem->SetBitmap(GlobalResources::getImage(entry.languageFlag));
//map menu item IDs with language IDs: evaluated when processing event handler
@@ -745,15 +742,53 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig& guiCfg,
}
}
}
- //----------------------------------------------------------------------------------------------------------------------------------------------------------------
}
+MainDialog::~MainDialog()
+{
+ try //save "GlobalSettings.xml"
+ {
+ xmlAccess::writeConfig(getGlobalCfgBeforeExit()); //throw FfsXmlError
+ }
+ catch (const xmlAccess::FfsXmlError& e)
+ {
+ wxMessageBox(e.toString().c_str(), _("Error"), wxOK | wxICON_ERROR, this);
+ }
+
+ try //save "LastRun.ffs_gui"
+ {
+ xmlAccess::writeConfig(getConfig(), toZ(lastRunConfigName())); //throw FfsXmlError
+ }
+ //don't annoy users on read-only drives: it's enough to show a single error message when saving global config
+ catch (const xmlAccess::FfsXmlError&) {}
+
+ //important! event source wxTheApp is NOT dependent on this instance -> disconnect!
+ wxTheApp->Disconnect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this);
+ wxTheApp->Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnGlobalKeyEvent), nullptr, this);
+
+ auiMgr.UnInit();
+
+ //no need for wxEventHandler::Disconnect() here; event sources are components of this window and are destroyed, too
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------
+
+void MainDialog::onQueryEndSession()
+{
+ try { xmlAccess::writeConfig(getGlobalCfgBeforeExit()); }
+ catch (const xmlAccess::FfsXmlError&) {} //we try our best do to something useful in this extreme situation - no reason to notify or even log errors here!
+
+ try { xmlAccess::writeConfig(getConfig(), toZ(lastRunConfigName())); }
+ catch (const xmlAccess::FfsXmlError&) {}
+}
+
void MainDialog::setGlobalCfgOnInit(const xmlAccess::XmlGlobalSettings& globalSettings)
{
globalCfg = globalSettings;
- setLanguage(globalSettings.programLanguage);
+ //caveat set/get language asymmmetry! setLanguage(globalSettings.programLanguage); //throw FileError
+ //we need to set langugabe before creating this class!
//set dialog size and position: test ALL parameters at once, since width/height are invalid if the window is minimized (eg x,y == -32000; height = 28, width = 160)
//note: negative values for x and y are possible when using multiple monitors!
@@ -912,14 +947,13 @@ void MainDialog::setManualFilter(const std::vector<FileSystemObject*>& selection
namespace
{
-//fast replacement for wxString modelling exponential growth
-typedef Zbase<wchar_t> zxString; //for use with UI texts
+//perf: wxString doesn't model exponential growth and so is unusable for large data sets
+typedef Zbase<wchar_t> zxString; //guaranteed exponential growth
}
-
void MainDialog::copySelectionToClipboard()
{
- zxString clipboardString; //perf: wxString doesn't model exponential growth and so is out
+ zxString clipboardString;
auto addSelection = [&](const Grid& grid)
{
@@ -2145,9 +2179,8 @@ void MainDialog::OnContextSetLayout(wxMouseEvent& event)
menu.addItem(_("Default view"), [&]
{
- auiMgr.LoadPerspective(defaultPerspective);
-
m_splitterMain->setSashOffset(0);
+ auiMgr.LoadPerspective(defaultPerspective);
updateGuiForFolderPair();
});
//----------------------------------------------------------------------------------------
@@ -2186,7 +2219,7 @@ void MainDialog::OnCompSettingsContext(wxMouseEvent& event)
auto setVariant = [&](CompareVariant var)
{
currentCfg.mainCfg.cmpConfig.compareVar = var;
- applyCompareConfig();
+ applyCompareConfig(true); //true: switchMiddleGrid
};
auto currentVar = getConfig().mainCfg.cmpConfig.compareVar;
@@ -2226,7 +2259,7 @@ void MainDialog::onNaviPanelFilesDropped(FileDropEvent& event)
}
-void MainDialog::OnDirSelected(wxCommandEvent& event)
+void MainDialog::onDirSelected(wxCommandEvent& event)
{
//left and right directory text-control and dirpicker are synchronized by MainFolderDragDrop automatically
clearGrid(); //disable the sync button
@@ -2234,6 +2267,13 @@ void MainDialog::OnDirSelected(wxCommandEvent& event)
}
+void MainDialog::onDirManualCorrection(wxCommandEvent& event)
+{
+ updateUnsavedCfgStatus();
+ event.Skip();
+}
+
+
wxString getFormattedHistoryElement(const wxString& filename)
{
wxString output = afterLast(filename, utfCvrtTo<wxString>(FILE_NAME_SEPARATOR));
@@ -2317,6 +2357,41 @@ void MainDialog::addFileToCfgHistory(const std::vector<wxString>& filenames)
}
+void MainDialog::updateUnsavedCfgStatus()
+{
+ const bool haveUnsavedCfg = lastConfigurationSaved != getConfig();
+ const bool singleCfgLoaded = activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName();
+
+ //update save config button
+ const bool allowSave = !singleCfgLoaded || haveUnsavedCfg;
+
+ auto makeBrightGrey = [](const wxBitmap& bmp) -> wxBitmap
+ {
+ wxImage img = bmp.ConvertToImage().ConvertToGreyscale(1.0/3, 1.0/3, 1.0/3); //treat all channels equally!
+ brighten(img, 80);
+ return img;
+ };
+ //setImage(*m_bpButtonSave, greyScale(GlobalResources::getImage(L"save")));
+
+ setImage(*m_bpButtonSave, allowSave ? GlobalResources::getImage(L"save") : makeBrightGrey(GlobalResources::getImage(L"save")));
+ m_bpButtonSave->Enable(allowSave);
+
+ m_menuItemSave->Enable(allowSave); //bitmap is automatically greyscaled on Win7 (introducing a crappy looking shift), but not on XP
+
+ //set main dialog title
+ wxString title;
+ if (haveUnsavedCfg)
+ title += L'*';
+
+ if (singleCfgLoaded)
+ title += activeConfigFiles[0];
+ else
+ title += L"FreeFileSync - " + _("Folder Comparison and Synchronization");
+
+ SetTitle(title);
+}
+
+
void MainDialog::OnConfigSave(wxCommandEvent& event)
{
//if we work on a single named configuration document: save directly if changed
@@ -2424,8 +2499,10 @@ bool MainDialog::saveOldConfig() //return false on user abort
}
}
- //discard current config selection, this ensures next app start will load <last session> instead of the original non-modified config selection
- setLastUsedConfig(std::vector<wxString>(), getConfig());
+ //discard current reference file(s), this ensures next app start will load <last session> instead of the original non-modified config selection
+ setLastUsedConfig(std::vector<wxString>(), lastConfigurationSaved);
+ //this seems to make theoretical sense also: the job of this function is to make sure current (volatile) config and reference file name are in sync
+ // => if user does not save cfg, it is not attached to a physical file names anymore!
}
return true;
}
@@ -2456,10 +2533,7 @@ void MainDialog::OnConfigNew(wxCommandEvent& event)
if (!saveOldConfig()) //notify user about changed settings
return;
- xmlAccess::XmlGuiConfig emptyCfg;
- setConfig(emptyCfg);
-
- setLastUsedConfig(std::vector<wxString>(), emptyCfg);
+ setConfig(xmlAccess::XmlGuiConfig(), std::vector<wxString>());
}
@@ -2508,26 +2582,22 @@ void MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
try
{
//allow reading batch configurations also
- xmlAccess::convertConfig(toZ(filenames), newGuiCfg); //throw FfsXmlError
+ xmlAccess::mergeConfigs(toZ(filenames), newGuiCfg); //throw FfsXmlError
- setLastUsedConfig(filenames, newGuiCfg);
+ setConfig(newGuiCfg, filenames);
//flashStatusInformation(_("Configuration loaded!")); -> irrelvant!?
}
catch (const xmlAccess::FfsXmlError& error)
{
if (error.getSeverity() == xmlAccess::FfsXmlError::WARNING)
{
- setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors
wxMessageBox(error.toString(), _("Warning"), wxOK | wxICON_WARNING, this);
+ setConfig(newGuiCfg, filenames);
+ setLastUsedConfig(filenames, xmlAccess::XmlGuiConfig()); //simulate changed config due to parsing errors
}
else
- {
wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
- return;
- }
}
-
- setConfig(newGuiCfg);
}
@@ -2639,18 +2709,12 @@ void MainDialog::setLastUsedConfig(const std::vector<wxString>& filenames,
addFileToCfgHistory(activeConfigFiles); //put filename on list of last used config files
- //set title
- if (activeConfigFiles.size() == 1 && activeConfigFiles[0] != lastRunConfigName())
- SetTitle(activeConfigFiles[0]);
- else
- SetTitle(L"FreeFileSync - " + _("Folder Comparison and Synchronization"));
+ updateUnsavedCfgStatus();
}
-void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg)
+void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg, const std::vector<wxString>& referenceFiles)
{
- clearGrid();
-
currentCfg = newGuiCfg;
//evaluate new settings...
@@ -2689,6 +2753,10 @@ void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg)
//update sync variant name
m_staticTextSyncVariant->SetLabel(currentCfg.mainCfg.getSyncVariantName());
m_panelTopButtons->Layout(); //adapt layout for variant text
+
+ clearGrid(); //+ update GUI
+
+ setLastUsedConfig(referenceFiles, newGuiCfg);
}
@@ -3022,15 +3090,11 @@ void MainDialog::updateFilterButtons()
m_bpButtonFilter->SetToolTip(_("No filter selected"));
}
- //update main local filter
+ //update local filter buttons
firstFolderPair->refreshButtons();
- //update folder pairs
std::for_each(additionalFolderPairs.begin(), additionalFolderPairs.end(),
- [&](DirectoryPair* dirPair)
- {
- dirPair->refreshButtons();
- });
+ [&](DirectoryPair* dirPair) { dirPair->refreshButtons(); });
}
@@ -3051,7 +3115,7 @@ void MainDialog::OnCompare(wxCommandEvent& event)
m_gridMainR->Scroll(scrollPosX, scrollPosY); //restore
m_gridMainC->Scroll(-1, scrollPosY); ) //
- clearGrid(false); //avoid memory peak by clearing old data
+ clearGrid(); //avoid memory peak by clearing old data
try
{
@@ -3092,8 +3156,6 @@ void MainDialog::OnCompare(wxCommandEvent& event)
treeDataView->setData(folderCmp); //
updateGui();
- updateSyncEnabledStatus(); //enable the sync button
-
// if (m_buttonStartSync->IsShownOnScreen()) m_buttonStartSync->SetFocus();
gridview::clearSelection(*m_gridMainL, *m_gridMainC, *m_gridMainR);
@@ -3121,20 +3183,36 @@ void MainDialog::updateGui()
//update sync preview statistics
updateStatistics();
+ updateUnsavedCfgStatus();
+
+ //update sync and comparison variant names
+ m_staticTextSyncVariant->SetLabel(getConfig().mainCfg.getSyncVariantName());
+ m_staticTextCmpVariant ->SetLabel(getConfig().mainCfg.getCompVariantName());
+ m_panelTopButtons->Layout();
+
+ //update sync button enabled/disabled status
+ if (!folderCmp.empty())
+ {
+ m_buttonStartSync->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
+ m_buttonStartSync->setBitmapFront(GlobalResources::getImage(L"sync"), 5);
+ }
+ else
+ {
+ m_buttonStartSync->SetForegroundColour(wxColor(128, 128, 128)); //Some colors seem to have problems with 16-bit desktop color, well this one hasn't!
+ m_buttonStartSync->setBitmapFront(greyScale(GlobalResources::getImage(L"sync")), 5);
+ }
+
auiMgr.Update(); //fix small display distortion, if view filter panel is empty
}
-void MainDialog::clearGrid(bool refreshGrid)
+void MainDialog::clearGrid()
{
folderCmp.clear();
gridDataView->setData(folderCmp);
treeDataView->setData(folderCmp);
- updateSyncEnabledStatus();
-
- if (refreshGrid)
- updateGui();
+ updateGui();
}
@@ -3189,17 +3267,12 @@ void MainDialog::OnSyncSettings(wxCommandEvent& event)
}
-void MainDialog::applyCompareConfig(bool changePreviewStatus)
+void MainDialog::applyCompareConfig(bool switchMiddleGrid)
{
- //update compare variant name
- m_staticTextCmpVariant->SetLabel(getConfig().mainCfg.getCompVariantName());
- m_panelTopButtons->Layout(); //adapt layout for variant text
-
- if (changePreviewStatus)
- {
- clearGrid();
+ clearGrid(); //+ GUI update
- //convenience: change sync view
+ //convenience: change sync view
+ if (switchMiddleGrid)
switch (currentCfg.mainCfg.cmpConfig.compareVar)
{
case CMP_BY_TIME_SIZE:
@@ -3209,10 +3282,6 @@ void MainDialog::applyCompareConfig(bool changePreviewStatus)
showSyncAction(false);
break;
}
-
- if (m_buttonCompare->IsShownOnScreen())
- m_buttonCompare->SetFocus();
- }
}
@@ -3230,7 +3299,7 @@ void MainDialog::OnCmpSettings(wxCommandEvent& event)
{
currentCfg.mainCfg.cmpConfig = cmpConfigNew;
- applyCompareConfig();
+ applyCompareConfig(true); //true: switchMiddleGrid
}
}
@@ -3248,8 +3317,8 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
return;
}
- //show sync preview screen
- if (globalCfg.optDialogs.showSummaryBeforeSync)
+ //show sync preview/confirmation dialog
+ if (globalCfg.optDialogs.confirmSyncStart)
{
bool dontShowAgain = false;
@@ -3259,7 +3328,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
dontShowAgain) != ReturnSmallDlg::BUTTON_OKAY)
return;
- globalCfg.optDialogs.showSummaryBeforeSync = !dontShowAgain;
+ globalCfg.optDialogs.confirmSyncStart = !dontShowAgain;
}
wxBusyCursor dummy; //show hourglass cursor
@@ -3275,7 +3344,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
const auto& guiCfg = getConfig();
//class handling status updates and error messages
- SyncStatusHandler statusHandler(this,
+ SyncStatusHandler statusHandler(this, //throw GuiAbortProcess
currentCfg.handleError,
xmlAccess::extractJobName(activeFileName),
guiCfg.mainCfg.onCompletion,
@@ -3296,7 +3365,8 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
//START SYNCHRONIZATION
const std::vector<zen::FolderPairSyncCfg> syncProcessCfg = zen::extractSyncCfg(guiCfg.mainCfg);
if (syncProcessCfg.size() != folderCmp.size())
- throw std::logic_error("Programming Error: Contract violation!"); //should never happen: sync button is deactivated if they are not in sync
+ throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ //should never happen: sync button is deactivated if they are not in sync
synchronize(localTime(),
globalCfg.optDialogs,
@@ -3610,14 +3680,10 @@ void MainDialog::applyFilterConfig()
void MainDialog::applySyncConfig()
{
- //update sync variant name
- m_staticTextSyncVariant->SetLabel(getConfig().mainCfg.getSyncVariantName());
- m_panelTopButtons->Layout(); //adapt layout for variant text
-
zen::redetermineSyncDirection(getConfig().mainCfg, folderCmp,
[&](const std::wstring& warning)
{
- bool& warningActive = globalCfg.optDialogs.warningSyncDatabase;
+ bool& warningActive = globalCfg.optDialogs.warningDatabaseError;
if (warningActive)
{
bool dontWarnAgain = false;
@@ -3704,7 +3770,8 @@ void MainDialog::updateGuiForFolderPair()
m_bpButtonAltSyncCfg ->Show(showLocalCfgFirstPair);
m_bpButtonLocalFilter->Show(showLocalCfgFirstPair);
setImage(*m_bpButtonSwapSides, GlobalResources::getImage(showLocalCfgFirstPair ? L"swapSlim" : L"swap"));
- m_panelTopMiddle->Layout();
+ m_panelTopMiddle->Layout(); //both required to update button size for calculations below!!!
+ m_panelDirectoryPairs->Layout(); // -> updates size of stretched m_panelTopLeft!
int addPairMinimalHeight = 0;
int addPairOptimalHeight = 0;
@@ -3789,10 +3856,7 @@ void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool
iter->altCmpConfig,
iter->altSyncConfig,
iter->localFilter);
-
- clearGrid();
- applySyncConfig(); //mainly to update sync dir description text
- applyCompareConfig(false); //false: do not change preview status
+ clearGrid(); //+ GUI update
}
@@ -3824,11 +3888,7 @@ void MainDialog::removeAddFolderPair(size_t pos)
updateGuiForFolderPair();
- //------------------------------------------------------------------
- //disable the sync button
- clearGrid();
- applySyncConfig(); //mainly to update sync dir description text
- applyCompareConfig(false); //false: do not change preview status
+ clearGrid(); //+ GUI update
}
@@ -4075,12 +4135,11 @@ void MainDialog::OnMenuQuit(wxCommandEvent& event)
void MainDialog::switchProgramLanguage(int langID)
{
//create new dialog with respect to new language
- zen::setLanguage(langID); //language is a global attribute
-
- //create new main window and delete old one
- MainDialog* frame = new MainDialog(activeConfigFiles, getConfig(), getGlobalCfgBeforeExit(), false);
- frame->Show();
+ xmlAccess::XmlGlobalSettings newGlobalCfg = getGlobalCfgBeforeExit();
+ newGlobalCfg.programLanguage = langID;
+ //show new dialog, then delete old one
+ MainDialog::create(getConfig(), activeConfigFiles, newGlobalCfg, false);
Destroy();
}
@@ -4105,18 +4164,3 @@ void MainDialog::showSyncAction(bool value)
updateGui();
}
-
-void MainDialog::updateSyncEnabledStatus()
-{
- if (!folderCmp.empty())
- {
- m_buttonStartSync->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
- m_buttonStartSync->setBitmapFront(GlobalResources::getImage(L"sync"));
- }
- else
- {
- m_buttonStartSync->SetForegroundColour(wxColor(128, 128, 128)); //Some colors seem to have problems with 16-bit desktop color, well this one hasn't!
- m_buttonStartSync->setBitmapFront(GlobalResources::getImage(L"syncDisabled")); //looks better than greyscaling "sync" bmp
- }
-}
-
bgstack15