summaryrefslogtreecommitdiff
path: root/ui/MainDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/MainDialog.cpp')
-rw-r--r--ui/MainDialog.cpp3804
1 files changed, 0 insertions, 3804 deletions
diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp
deleted file mode 100644
index ce7129aa..00000000
--- a/ui/MainDialog.cpp
+++ /dev/null
@@ -1,3804 +0,0 @@
-// **************************************************************************
-// * 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) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-//
-#include "mainDialog.h"
-#include <wx/filename.h>
-#include <stdexcept>
-#include "../shared/systemConstants.h"
-#include <wx/clipbrd.h>
-#include <wx/dataobj.h>
-#include <iterator>
-#include <wx/ffile.h>
-#include "../library/customGrid.h"
-#include "../shared/customButton.h"
-#include "../shared/customComboBox.h"
-#include <wx/msgdlg.h>
-#include "../comparison.h"
-#include "../synchronization.h"
-#include "../algorithm.h"
-#include "../shared/appMain.h"
-#include "../shared/util.h"
-#include "checkVersion.h"
-#include "guiStatusHandler.h"
-#include "syncConfig.h"
-#include "../shared/localization.h"
-#include "../shared/stringConv.h"
-#include "smallDialogs.h"
-#include "mouseMoveWindow.h"
-#include "progressIndicator.h"
-#include "messagePopup.h"
-#include "../shared/dragAndDrop.h"
-#include "../library/filter.h"
-#include "../structures.h"
-#include <wx/imaglist.h>
-#include <wx/wupdlock.h>
-#include "gridView.h"
-#include "../library/resources.h"
-#include "../shared/fileHandling.h"
-#include "../shared/recycler.h"
-#include "../shared/xmlBase.h"
-#include "../shared/standardPaths.h"
-#include "../shared/toggleButton.h"
-#include "folderPair.h"
-#include "../shared/globalFunctions.h"
-#include <wx/sound.h>
-#include "search.h"
-#include "../shared/helpProvider.h"
-#include "isNullFilter.h"
-#include "batchConfig.h"
-#include "../shared/checkExist.h"
-
-using namespace FreeFileSync;
-using FreeFileSync::CustomLocale;
-
-
-class MainFolderDragDrop : public DragDropOnMainDlg
-{
-public:
- MainFolderDragDrop(MainDialog& mainDlg,
- wxWindow* dropWindow1,
- wxWindow* dropWindow2,
- wxDirPickerCtrl* dirPicker,
- wxComboBox* dirName) :
-
- DragDropOnMainDlg(dropWindow1, dropWindow2, dirPicker, dirName),
- mainDlg_(mainDlg) {}
-
- virtual bool AcceptDrop(const wxString& dropName)
- {
- const xmlAccess::XmlType fileType = xmlAccess::getXmlType(dropName);
-
- //test if ffs config file has been dropped
- if (fileType == xmlAccess::XML_GUI_CONFIG)
- {
- mainDlg_.loadConfiguration(dropName);
- return false;
- }
- //...or a ffs batch file
- else if (fileType == xmlAccess::XML_BATCH_CONFIG)
- {
- BatchDialog* batchDlg = new BatchDialog(&mainDlg_, dropName);
- if (batchDlg->ShowModal() == BatchDialog::BATCH_FILE_SAVED)
- mainDlg_.pushStatusInformation(_("Batch file created successfully!"));
- return false;
- }
-
- //disable the sync button
- mainDlg_.syncPreview->enableSynchronization(false);
-
- //clear grids
- mainDlg_.gridDataView->clearAllRows();
- mainDlg_.updateGuiGrid();
-
- return true;
- }
-
-private:
- MainFolderDragDrop(const MainFolderDragDrop&);
-
- MainDialog& mainDlg_;
-};
-
-//------------------------------------------------------------------
-/* class hierarchy:
-
- template<>
- FolderPairPanelBasic
- /|\
- |
- template<>
- FolderPairCallback FolderPairGenerated
- /|\ /|\
- _________|________ ________|
- | | |
- FirstFolderPairCfg FolderPairPanel
-*/
-
-template <class GuiPanel>
-class FolderPairCallback : public FolderPairPanelBasic<GuiPanel> //implements callback functionality to MainDialog as imposed by FolderPairPanelBasic
-{
-public:
- FolderPairCallback(GuiPanel& basicPanel, MainDialog& mainDialog) :
- FolderPairPanelBasic<GuiPanel>(basicPanel), //pass FolderPairGenerated part...
- mainDlg(mainDialog) {}
-
-private:
- virtual void OnLocalFilterCfgRemoveConfirm(wxCommandEvent& event)
- {
- FolderPairPanelBasic<GuiPanel>::OnLocalFilterCfgRemoveConfirm(event);
- mainDlg.updateFilterConfig(); //update filter
- }
-
- virtual void OnAltSyncCfgRemoveConfirm(wxCommandEvent& event)
- {
- FolderPairPanelBasic<GuiPanel>::OnAltSyncCfgRemoveConfirm(event);
- mainDlg.updateSyncConfig();
- }
-
- virtual wxWindow* getParentWindow()
- {
- return &mainDlg;
- }
-
- virtual MainConfiguration getMainConfig() const
- {
- return mainDlg.getCurrentConfiguration().mainCfg;
- }
-
- virtual void OnAltSyncCfgChange()
- {
- mainDlg.updateSyncConfig();
- }
-
- virtual void OnLocalFilterCfgChange()
- {
- mainDlg.updateFilterConfig(); //re-apply filter
- }
-
- MainDialog& mainDlg;
-};
-
-
-class FolderPairPanel :
- public FolderPairGenerated, //FolderPairPanel "owns" FolderPairGenerated!
- public FolderPairCallback<FolderPairGenerated>
-{
-public:
- FolderPairPanel(wxWindow* parent, MainDialog& mainDialog) :
- FolderPairGenerated(parent),
- FolderPairCallback<FolderPairGenerated>(static_cast<FolderPairGenerated&>(*this), mainDialog), //pass FolderPairGenerated part...
- dragDropOnLeft( m_panelLeft, m_dirPickerLeft, m_directoryLeft),
- dragDropOnRight(m_panelRight, m_dirPickerRight, m_directoryRight) {}
-
-private:
- //support for drag and drop
- DragDropOnDlg dragDropOnLeft;
- DragDropOnDlg dragDropOnRight;
-};
-
-
-class FirstFolderPairCfg : public FolderPairCallback<MainDialogGenerated>
-{
-public:
- FirstFolderPairCfg(MainDialog& mainDialog) :
- FolderPairCallback<MainDialogGenerated>(mainDialog, mainDialog),
-
- //prepare drag & drop
- dragDropOnLeft(mainDialog,
- mainDialog.m_panelLeft,
- mainDialog.m_panelTopLeft,
- mainDialog.m_dirPickerLeft,
- mainDialog.m_directoryLeft),
- dragDropOnRight(mainDialog,
- mainDialog.m_panelRight,
- mainDialog.m_panelTopRight,
- mainDialog.m_dirPickerRight,
- mainDialog.m_directoryRight) {}
-
-private:
- //support for drag and drop
- MainFolderDragDrop dragDropOnLeft;
- MainFolderDragDrop dragDropOnRight;
-};
-
-
-//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()
- {
- //start updating menu icons
- const wxMenuItemList& allItems = menuToUpdate_->GetMenuItems();
-
- //retrieve menu item positions: unfortunately wxMenu doesn't offer a better way
- MenuItemMap::iterator j;
- int index = 0;
- for (wxMenuItemList::const_iterator i = allItems.begin(); i != allItems.end(); ++i, ++index)
- if ((j = menuItems.find(*i)) != menuItems.end())
- j->second = index;
-
- //finally update items
- for (MenuItemMap::const_iterator i = menuItems.begin(); i != menuItems.end(); ++i)
- if (i->second >= 0)
- {
- menuToUpdate_->Remove(i->first); //actual workaround
- menuToUpdate_->Insert(i->second, i->first); //
- }
- }
-
- void addForUpdate(wxMenuItem* newEntry, const wxBitmap& newBitmap)
- {
- newEntry->SetBitmap(newBitmap);
- menuItems.insert(std::pair<wxMenuItem*, int>(newEntry, -1));
- }
-
-private:
- typedef std::map<wxMenuItem*, int> MenuItemMap;
- wxMenu* menuToUpdate_;
- MenuItemMap menuItems;
-};
-
-
-struct DirNotFound
-{
- bool operator()(const FolderPairEnh& fp) const
- {
- return !dirExists(FreeFileSync::getFormattedDirectoryName(fp.leftDirectory)) ||
- !dirExists(FreeFileSync::getFormattedDirectoryName(fp.rightDirectory));
- }
-};
-
-
-//##################################################################################################################################
-MainDialog::MainDialog(const wxString& cfgFileName, xmlAccess::XmlGlobalSettings& settings) :
- MainDialogGenerated(NULL)
-{
- xmlAccess::XmlGuiConfig guiCfg; //structure to receive gui settings, already defaulted!!
-
- const wxString actualConfigFile = cfgFileName.empty() ? lastConfigFileName() : cfgFileName;
-
- bool loadCfgSuccess = false;
- if (!cfgFileName.empty() || fileExists(wxToZ(lastConfigFileName())))
- {
- //load XML
- try
- {
- xmlAccess::readGuiOrBatchConfig(actualConfigFile, guiCfg); //allow reading batch configurations also
- loadCfgSuccess = true;
- }
- catch (const xmlAccess::XmlError& error)
- {
- if (error.getSeverity() == xmlAccess::XmlError::WARNING)
- wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
- else
- wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
- }
- }
-
- init(guiCfg,
- settings,
- !cfgFileName.empty() && loadCfgSuccess);
-
- setLastUsedConfig(actualConfigFile, loadCfgSuccess ? guiCfg : xmlAccess::XmlGuiConfig()); //simulate changed config on parsing errors
-}
-
-
-MainDialog::MainDialog(const xmlAccess::XmlGuiConfig& guiCfg,
- xmlAccess::XmlGlobalSettings& settings,
- bool startComparison) :
- MainDialogGenerated(NULL)
-{
- init(guiCfg,
- settings,
- startComparison);
-}
-
-
-MainDialog::~MainDialog()
-{
- //keep non-inline destructor for std::auto_ptr to work with forward declaration
-
- cleanUp(true); //do NOT include any other code here! cleanUp() is re-used when switching languages
-}
-
-
-void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg,
- xmlAccess::XmlGlobalSettings& settings,
- bool startComparison)
-{
- wxWindowUpdateLocker dummy(this); //avoid display distortion
-
- //--------- avoid mirroring this dialog in RTL languages like Hebrew or Arabic --------------------
- m_panelViewFilter->SetLayoutDirection(wxLayout_LeftToRight);
- m_panelStatusBar->SetLayoutDirection(wxLayout_LeftToRight);
-// if (GetLayoutDirection() == wxLayout_RightToLeft)
-//{
-// bSizerGridHolder->Detach(m_panelRight);
-// bSizerGridHolder->Detach(m_panelLeft);
-// bSizerGridHolder->Add(m_panelLeft);
-// bSizerGridHolder->Prepend(m_panelRight);
-//bSizerGridHolder->Fit(this);
-//
-// bSizerGridHolder->Layout();
-//}
-//------------------------------------------------------------------------------------------------------
-
- globalSettings = &settings;
- gridDataView.reset(new FreeFileSync::GridView);
- contextMenu.reset(new wxMenu); //initialize right-click context menu; will be dynamically re-created on each R-mouse-click
-
- compareStatus.reset(new CompareStatus(*this));
- cleanedUp = false;
- lastSortColumn = -1;
- lastSortGrid = NULL;
-
- updateFileIcons.reset(new IconUpdater(m_gridLeft, m_gridRight));
-
-#ifdef FFS_WIN
- moveWholeWindow.reset(new MouseMoveWindow(this));
-#endif
- syncPreview.reset(new SyncPreview(this));
-
- SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
-
- SetIcon(*GlobalResources::getInstance().programIcon); //set application icon
-
-
- //notify about (logical) application main window => program won't quit, but stay on this dialog
- FreeFileSync::AppMainWindow::setMainWindow(this);
-
- //init handling of first folder pair
- firstFolderPair.reset(new FirstFolderPairCfg(*this));
-
- initViewFilterButtons();
-
- //initialize and load configuration
- readGlobalSettings();
- setCurrentConfiguration(guiCfg);
-
- //set icons for this dialog
- m_bpButton10->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("exit")));
- m_buttonCompare->setBitmapFront(GlobalResources::getInstance().getImageByName(wxT("compare")));
- m_bpButtonSyncConfig->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("syncConfig")));
- m_bpButtonCmpConfig->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("cmpConfig")));
- m_bpButtonSave->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("save")));
- m_bpButtonLoad->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("load")));
- m_bpButtonAddPair->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("addFolderPair")));
- m_bitmap15->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("statusEdge")));
-
- m_bitmapCreate->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("create")));
- m_bitmapUpdate->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("update")));
- m_bitmapDelete->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("delete")));
- m_bitmapData->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("data")));
-
- bSizer6->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);
- updateMenuFile.addForUpdate(m_menuItem10, GlobalResources::getInstance().getImageByName(wxT("compareSmall")));
- updateMenuFile.addForUpdate(m_menuItem11, GlobalResources::getInstance().getImageByName(wxT("syncSmall")));
- updateMenuFile.addForUpdate(m_menuItemNew, GlobalResources::getInstance().getImageByName(wxT("newSmall")));
- updateMenuFile.addForUpdate(m_menuItemSave, GlobalResources::getInstance().getImageByName(wxT("saveSmall")));
- updateMenuFile.addForUpdate(m_menuItemLoad, GlobalResources::getInstance().getImageByName(wxT("loadSmall")));
-
- MenuItemUpdater updateMenuAdv(m_menuAdvanced);
- updateMenuAdv.addForUpdate(m_menuItemGlobSett, GlobalResources::getInstance().getImageByName(wxT("settingsSmall")));
- updateMenuAdv.addForUpdate(m_menuItem7, GlobalResources::getInstance().getImageByName(wxT("batchSmall")));
-
- MenuItemUpdater updateMenuHelp(m_menuHelp);
- updateMenuHelp.addForUpdate(m_menuItemAbout, GlobalResources::getInstance().getImageByName(wxT("aboutSmall")));
-
-#ifdef FFS_WIN
- //allow moving main dialog by clicking (nearly) anywhere...
- moveWholeWindow->connectSourceWindow(m_panel71);
- moveWholeWindow->connectSourceWindow(m_panelBottom);
- moveWholeWindow->connectSourceWindow(m_panelStatusBar);
-#endif
-
-#ifdef FFS_LINUX
- if (!FreeFileSync::isPortableVersion()) //disable update check for Linux installer-based version -> handled by .deb
- m_menuItemCheckVer->Enable(false);
-#endif
-
- //create language selection menu
- for (std::vector<LocInfoLine>::const_iterator i = LocalizationInfo::getMapping().begin(); i != LocalizationInfo::getMapping().end(); ++i)
- {
- wxMenuItem* newItem = new wxMenuItem(m_menuLanguages, wxID_ANY, i->languageName, wxEmptyString, wxITEM_NORMAL );
- newItem->SetBitmap(GlobalResources::getInstance().getImageByName(i->languageFlag));
-
- //map menu item IDs with language IDs: evaluated when processing event handler
- languageMenuItemMap.insert(std::map<MenuItemID, LanguageID>::value_type(newItem->GetId(), i->languageID));
-
- //connect event
- Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnMenuLanguageSwitch));
- m_menuLanguages->Append(newItem);
- }
-
- //support for CTRL + C and DEL on grids
- m_gridLeft->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGridLeftButtonEvent), NULL, this);
- m_gridRight->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGridRightButtonEvent), NULL, this);
- m_gridMiddle->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainDialog::onGridMiddleButtonEvent), NULL, this);
-
- Connect(wxEVT_IDLE, wxEventHandler(MainDialog::OnIdleEvent), NULL, this);
- Connect(wxEVT_SIZE, wxSizeEventHandler(MainDialog::OnResize), NULL, this);
- Connect(wxEVT_MOVE, wxSizeEventHandler(MainDialog::OnResize), NULL, this);
-
- m_bpButtonFilter->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(MainDialog::OnGlobalFilterOpenContext), NULL, this);
-
- //calculate witdh of folder pair manually (if scrollbars are visible)
- m_scrolledWindowFolderPairs->Connect(wxEVT_SIZE, wxSizeEventHandler(MainDialog::OnResizeFolderPairs), NULL, this);
-
- //event handler for manual (un-)checking of rows and setting of sync direction
- m_gridMiddle->Connect(FFS_CHECK_ROWS_EVENT, FFSCheckRowsEventHandler(MainDialog::OnCheckRows), NULL, this);
- m_gridMiddle->Connect(FFS_SYNC_DIRECTION_EVENT, FFSSyncDirectionEventHandler(MainDialog::OnSetSyncDirection), NULL, this);
-
- //init grid settings
- m_gridLeft ->initSettings(m_gridLeft, m_gridMiddle, m_gridRight, gridDataView.get());
- m_gridMiddle->initSettings(m_gridLeft, m_gridMiddle, m_gridRight, gridDataView.get());
- m_gridRight ->initSettings(m_gridLeft, m_gridMiddle, m_gridRight, gridDataView.get());
-
- //disable sync button as long as "compare" hasn't been triggered.
- syncPreview->enableSynchronization(false);
-
- //mainly to update row label sizes...
- updateGuiGrid();
-
- //integrate the compare status panel (in hidden state)
- bSizer1->Insert(1, compareStatus->getAsWindow(), 0, wxEXPAND | wxBOTTOM, 5 );
- Layout(); //avoid screen flicker when panel is shown later
- compareStatus->getAsWindow()->Hide();
-
- //correct width of swap button above middle grid
- const wxSize source = m_gridMiddle->GetSize();
- const wxSize target = m_bpButtonSwapSides->GetSize();
- const int spaceToAdd = source.GetX() - target.GetX();
- bSizerMiddle->Insert(1, spaceToAdd / 2, 0, 0);
- bSizerMiddle->Insert(0, spaceToAdd - (spaceToAdd / 2), 0, 0);
-
- //register regular check for update on next idle event
- Connect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), NULL, this);
-
- //asynchronous call to wxWindow::Layout(): fix superfluous frame on right and bottom when FFS is started in fullscreen mode
- Connect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnLayoutWindowAsync), NULL, this);
-
-//----------------------------------------------------------------------------------------------------------------------------------------------------------------
- //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 FreeFileSync::MainConfiguration currMainCfg = getCurrentConfiguration().mainCfg;
- const bool allFoldersExist = !DirNotFound()(currMainCfg.firstPair) &&
- std::find_if(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(),
- DirNotFound()) == currMainCfg.additionalPairs.end();
- if (allFoldersExist)
- {
- wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED);
- m_buttonCompare->AddPendingEvent(dummy2); //simulate button click on "compare"
- }
- }
-//----------------------------------------------------------------------------------------------------------------------------------------------------------------
-}
-
-
-void MainDialog::cleanUp(bool saveLastUsedConfig)
-{
- if (!cleanedUp)
- {
- cleanedUp = true;
-
- //no need for wxEventHandler::Disconnect() here; done automatically when window is destoyed!
-
- m_gridLeft ->release(); //handle wxGrid-related callback on grid data after MainDialog has died... (Linux only)
- m_gridMiddle->release();
- m_gridRight ->release();
-
- //save configuration
- if (saveLastUsedConfig)
- writeConfigurationToXml(lastConfigFileName()); //don't throw exceptions in destructors
- writeGlobalSettings();
- }
-}
-
-
-void MainDialog::readGlobalSettings()
-{
- //apply window size and position at program startup ONLY
- widthNotMaximized = globalSettings->gui.widthNotMaximized;
- heightNotMaximized = globalSettings->gui.heightNotMaximized;
- posXNotMaximized = globalSettings->gui.posXNotMaximized;
- posYNotMaximized = globalSettings->gui.posYNotMaximized;
-
- //apply window size and position
- if ( widthNotMaximized != wxDefaultCoord &&
- heightNotMaximized != wxDefaultCoord &&
- posXNotMaximized != wxDefaultCoord &&
- posYNotMaximized != wxDefaultCoord)
- SetSize(posXNotMaximized, posYNotMaximized, widthNotMaximized, heightNotMaximized);
- else
- Centre();
-
- Maximize(globalSettings->gui.isMaximized);
-
- //set column attributes
- m_gridLeft->setColumnAttributes(globalSettings->gui.columnAttribLeft);
- m_gridRight->setColumnAttributes(globalSettings->gui.columnAttribRight);
-
- //load list of last used configuration files (in reverse order)
- for (std::vector<wxString>::reverse_iterator i = globalSettings->gui.cfgFileHistory.rbegin();
- i != globalSettings->gui.cfgFileHistory.rend();
- ++i)
- addFileToCfgHistory(*i);
-
- //load list of last used folders
- for (std::vector<wxString>::reverse_iterator i = globalSettings->gui.folderHistoryLeft.rbegin();
- i != globalSettings->gui.folderHistoryLeft.rend();
- ++i)
- addLeftFolderToHistory(*i);
- for (std::vector<wxString>::reverse_iterator i = globalSettings->gui.folderHistoryRight.rbegin();
- i != globalSettings->gui.folderHistoryRight.rend();
- ++i)
- addRightFolderToHistory(*i);
-
- //show/hide file icons
- m_gridLeft->enableFileIcons(globalSettings->gui.showFileIconsLeft);
- m_gridRight->enableFileIcons(globalSettings->gui.showFileIconsRight);
-
- //set selected tab
- m_notebookBottomLeft->ChangeSelection(globalSettings->gui.selectedTabBottomLeft);
-}
-
-
-void MainDialog::writeGlobalSettings()
-{
- //write global settings to (global) variable stored in application instance
- globalSettings->gui.widthNotMaximized = widthNotMaximized;
- globalSettings->gui.heightNotMaximized = heightNotMaximized;
- globalSettings->gui.posXNotMaximized = posXNotMaximized;
- globalSettings->gui.posYNotMaximized = posYNotMaximized;
- globalSettings->gui.isMaximized = IsMaximized();
-
- //retrieve column attributes
- globalSettings->gui.columnAttribLeft = m_gridLeft->getColumnAttributes();
- globalSettings->gui.columnAttribRight = m_gridRight->getColumnAttributes();
-
- //write list of last used configuration files
- globalSettings->gui.cfgFileHistory = cfgFileNames;
-
- //write list of last used folders
- globalSettings->gui.folderHistoryLeft.clear();
- const wxArrayString leftFolderHistory = m_directoryLeft->GetStrings();
- for (unsigned i = 0; i < leftFolderHistory.GetCount(); ++i)
- globalSettings->gui.folderHistoryLeft.push_back(leftFolderHistory[i]);
-
- globalSettings->gui.folderHistoryRight.clear();
- const wxArrayString rightFolderHistory = m_directoryRight->GetStrings();
- for (unsigned i = 0; i < rightFolderHistory.GetCount(); ++i)
- globalSettings->gui.folderHistoryRight.push_back(rightFolderHistory[i]);
-
- //get selected tab
- globalSettings->gui.selectedTabBottomLeft = m_notebookBottomLeft->GetSelection();
-}
-
-
-void MainDialog::setSyncDirManually(const std::set<size_t>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir)
-{
- if (rowsToSetOnUiTable.size() > 0)
- {
- for (std::set<size_t>::const_iterator i = rowsToSetOnUiTable.begin(); i != rowsToSetOnUiTable.end(); ++i)
- {
- FileSystemObject* fsObj = gridDataView->getObject(*i);
- if (fsObj)
- {
- setSyncDirectionRec(dir, *fsObj); //set new direction (recursively)
- FreeFileSync::setActiveStatus(true, *fsObj); //works recursively for directories
- }
- }
-
- updateGuiGrid();
- }
-}
-
-
-void MainDialog::filterRangeManually(const std::set<size_t>& rowsToFilterOnUiTable, int leadingRow)
-{
- if (rowsToFilterOnUiTable.size() > 0)
- {
- bool newSelection = false; //default: deselect range
-
- //leadingRow determines de-/selection of all other rows
- const FileSystemObject* fsObj = gridDataView->getObject(leadingRow);
- if (fsObj)
- newSelection = !fsObj->isActive();
-
- //if hidefiltered is active, there should be no filtered elements on screen => current element was filtered out
- assert(!currentCfg.hideFilteredElements || !newSelection);
-
- //get all lines that need to be filtered
- std::vector<FileSystemObject*> compRef;
- gridDataView->getAllFileRef(rowsToFilterOnUiTable, compRef); //everything in compRef is bound
-
- for (std::vector<FileSystemObject*>::iterator i = compRef.begin(); i != compRef.end(); ++i)
- FreeFileSync::setActiveStatus(newSelection, **i); //works recursively for directories
-
- refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
- }
-}
-
-
-void MainDialog::OnIdleEvent(wxEvent& event)
-{
- //small routine to restore status information after some time
- if (stackObjects.size() > 0 ) //check if there is some work to do
- {
- wxLongLong currentTime = wxGetLocalTimeMillis();
- if (currentTime - lastStatusChange > 2500) //restore stackObject after two seconds
- {
- lastStatusChange = currentTime;
-
- m_staticTextStatusMiddle->SetLabel(stackObjects.top());
- stackObjects.pop();
-
- if (stackObjects.empty())
- m_staticTextStatusMiddle->SetForegroundColour(*wxBLACK); //reset color
-
- m_panelStatusBar->Layout();
- }
- }
-
- event.Skip();
-}
-
-
-void MainDialog::copySelectionToClipboard(const CustomGrid* selectedGrid)
-{
- const std::set<size_t> selectedRows = getSelectedRows(selectedGrid);
- if (selectedRows.size() > 0)
- {
- wxString clipboardString;
-
- for (std::set<size_t>::const_iterator i = selectedRows.begin(); i != selectedRows.end(); ++i)
- {
- for (int k = 0; k < const_cast<CustomGrid*>(selectedGrid)->GetNumberCols(); ++k)
- {
- clipboardString+= const_cast<CustomGrid*>(selectedGrid)->GetCellValue(static_cast<int>(*i), k);
- if (k != const_cast<CustomGrid*>(selectedGrid)->GetNumberCols() - 1)
- clipboardString+= '\t';
- }
- clipboardString+= '\n';
- }
-
- if (!clipboardString.IsEmpty())
- // Write text to the clipboard
- if (wxTheClipboard->Open())
- {
- // these data objects are held by the clipboard,
- // so do not delete them in the app.
- wxTheClipboard->SetData( new wxTextDataObject(clipboardString) );
- wxTheClipboard->Close();
- }
- }
-}
-
-
-std::set<size_t> MainDialog::getSelectedRows(const CustomGrid* grid) const
-{
- std::set<size_t> output = grid->getAllSelectedRows();
-
- //remove invalid rows
- output.erase(output.lower_bound(gridDataView->rowsOnView()), output.end());
-
- return output;
-}
-
-
-std::set<size_t> MainDialog::getSelectedRows() const
-{
- //merge selections from left and right grid
- std::set<size_t> selection = getSelectedRows(m_gridLeft);
- std::set<size_t> additional = getSelectedRows(m_gridRight);
- selection.insert(additional.begin(), additional.end());
- return selection;
-}
-
-
-class ManualDeletionHandler : private wxEvtHandler, public DeleteFilesHandler
-{
-public:
- ManualDeletionHandler(MainDialog* main, size_t totalObjToDel) :
- mainDlg(main),
- totalObjToDelete(totalObjToDel),
- abortRequested(false),
- ignoreErrors(false),
- deletionCount(0)
- {
- mainDlg->disableAllElements(); //disable everything except abort button
- mainDlg->clearStatusBar();
-
- //register abort button
- mainDlg->m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortCompare ), NULL, this );
- }
-
- ~ManualDeletionHandler()
- {
- //de-register abort button
- mainDlg->m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortCompare ), NULL, this );
-
- mainDlg->enableAllElements();
- }
-
- virtual Response reportError(const wxString& errorMessage)
- {
- if (abortRequested)
- throw FreeFileSync::AbortThisProcess();
-
- if (ignoreErrors)
- return DeleteFilesHandler::IGNORE_ERROR;
-
- bool ignoreNextErrors = false;
- ErrorDlg* errorDlg = new ErrorDlg(NULL,
- ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT,
- errorMessage, ignoreNextErrors);
- const int rv = errorDlg->ShowModal();
- errorDlg->Destroy();
- switch (static_cast<ErrorDlg::ReturnCodes>(rv))
- {
- case ErrorDlg::BUTTON_IGNORE:
- ignoreErrors = ignoreNextErrors;
- return DeleteFilesHandler::IGNORE_ERROR;
- case ErrorDlg::BUTTON_RETRY:
- return DeleteFilesHandler::RETRY;
- case ErrorDlg::BUTTON_ABORT:
- throw FreeFileSync::AbortThisProcess();
- }
-
- assert (false);
- return DeleteFilesHandler::IGNORE_ERROR; //dummy return value
- }
-
- virtual void deletionSuccessful() //called for each file/folder that has been deleted
- {
- ++deletionCount;
-
- if (updateUiIsAllowed()) //test if specific time span between ui updates is over
- {
- wxString statusMessage = _("%x / %y objects deleted successfully");
- statusMessage.Replace(wxT("%x"), FreeFileSync::numberToStringSep(deletionCount), false);
- statusMessage.Replace(wxT("%y"), FreeFileSync::numberToStringSep(totalObjToDelete), false);
-
- mainDlg->m_staticTextStatusMiddle->SetLabel(statusMessage);
- mainDlg->m_panelStatusBar->Layout();
-
- updateUiNow();
- }
-
- if (abortRequested) //test after (implicit) call to wxApp::Yield()
- throw FreeFileSync::AbortThisProcess();
- }
-
-private:
- void OnAbortCompare(wxCommandEvent& event) //handle abort button click
- {
- abortRequested = true; //don't throw exceptions in a GUI-Callback!!! (throw FreeFileSync::AbortThisProcess())
- }
-
- MainDialog* const mainDlg;
- const size_t totalObjToDelete;
-
- bool abortRequested;
- bool ignoreErrors;
- size_t deletionCount;
-};
-
-
-void MainDialog::deleteSelectedFiles()
-{
- //get set of selected rows on view
- const std::set<size_t> viewSelectionLeft = getSelectedRows(m_gridLeft);
- const std::set<size_t> viewSelectionRight = getSelectedRows(m_gridRight);
-
- if (viewSelectionLeft.size() + viewSelectionRight.size())
- {
- //map lines from GUI view to grid line references
- std::vector<FileSystemObject*> compRefLeft;
- gridDataView->getAllFileRef(viewSelectionLeft, compRefLeft);
-
- std::vector<FileSystemObject*> compRefRight;
- gridDataView->getAllFileRef(viewSelectionRight, compRefRight);
-
-
- int totalDeleteCount = 0;
-
- if (FreeFileSync::showDeleteDialog(compRefLeft,
- compRefRight,
- globalSettings->gui.deleteOnBothSides,
- globalSettings->gui.useRecyclerForManualDeletion,
- totalDeleteCount) == DefaultReturnCode::BUTTON_OKAY)
- {
- if (globalSettings->gui.useRecyclerForManualDeletion && !FreeFileSync::recycleBinExists())
- {
- wxMessageBox(_("Recycle Bin not yet supported for this system!"));
- return;
- }
-
- try
- {
- //handle errors when deleting files/folders
- ManualDeletionHandler statusHandler(this, totalDeleteCount);
-
- FreeFileSync::deleteFromGridAndHD(gridDataView->getDataTentative(),
- compRefLeft,
- compRefRight,
- globalSettings->gui.deleteOnBothSides,
- globalSettings->gui.useRecyclerForManualDeletion,
- getCurrentConfiguration().mainCfg,
- &statusHandler);
- }
- catch (FreeFileSync::AbortThisProcess&) {}
-
- //remove rows that empty: just a beautification, invalid rows shouldn't cause issues
- gridDataView->removeInvalidRows();
-
- //redraw grid neccessary to update new dimensions and for UI-Backend data linkage
- updateGuiGrid(); //call immediately after deleteFromGridAndHD!!!
-
- m_gridLeft-> ClearSelection();
- m_gridMiddle->ClearSelection();
- m_gridRight-> ClearSelection();
- }
- }
-}
-
-
-template <SelectedSide side>
-void exstractNames(const FileSystemObject& fsObj, wxString& name, wxString& dir)
-{
- if (!fsObj.isEmpty<side>())
- {
- struct GetNames : public FSObjectVisitor
- {
- GetNames(wxString& nameIn, wxString& dirIn) : name_(nameIn), dir_(dirIn) {}
- virtual void visit(const FileMapping& fileObj)
- {
- name_ = zToWx(fileObj.getFullName<side>());
- dir_ = zToWx(fileObj.getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR));
- }
- virtual void visit(const SymLinkMapping& linkObj)
- {
- name_ = zToWx(linkObj.getFullName<side>());
- dir_ = zToWx(linkObj.getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR));
- }
- virtual void visit(const DirMapping& dirObj)
- {
- dir_ = name_ = zToWx(dirObj.getFullName<side>());
- }
-
- wxString& name_;
- wxString& dir_;
- ;
- } getNames(name, dir);
- fsObj.accept(getNames);
- }
- else
- {
- name.clear();
- dir.clear();
- }
-}
-
-
-void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const wxString& commandline)
-{
- if (commandline.empty())
- return;
-
- wxString command = commandline;
-
- wxString name;
- wxString dir;
- wxString nameCo;
- wxString dirCo;
-
- const FileSystemObject* fsObj = gridDataView->getObject(rowNumber);
- if (fsObj)
- {
- if (leftSide)
- {
- exstractNames<LEFT_SIDE>( *fsObj, name, dir);
- exstractNames<RIGHT_SIDE>(*fsObj, nameCo, dirCo);
- }
- else
- {
- exstractNames<RIGHT_SIDE>(*fsObj, name, dir);
- exstractNames<LEFT_SIDE>( *fsObj, nameCo, dirCo);
- }
-#ifdef FFS_WIN
- if (name.empty())
- {
- if (leftSide)
- wxExecute(wxString(wxT("explorer ")) + zToWx(fsObj->getBaseDirPf<LEFT_SIDE>()));
- else
- wxExecute(wxString(wxT("explorer ")) + zToWx(fsObj->getBaseDirPf<RIGHT_SIDE>()));
- return;
- }
-#endif
- }
- else
- {
- //fallback
- dir = zToWx(FreeFileSync::getFormattedDirectoryName(firstFolderPair->getLeftDir()));
- dirCo = zToWx(FreeFileSync::getFormattedDirectoryName(firstFolderPair->getRightDir()));
-
- if (!leftSide)
- std::swap(dir, dirCo);
-
-#ifdef FFS_WIN
- wxExecute(wxString(wxT("explorer ")) + dir); //default
- return;
-#endif
- }
-
- command.Replace(wxT("%nameCo"), nameCo, true); //attention: replace %nameCo, %dirCo BEFORE %name, %dir to handle dependency
- command.Replace(wxT("%dirCo"), dirCo, true);
- command.Replace(wxT("%name"), name, true);
- command.Replace(wxT("%dir"), dir, true);
-
- wxExecute(command);
-}
-
-
-void MainDialog::pushStatusInformation(const wxString& text)
-{
- lastStatusChange = wxGetLocalTimeMillis();
- stackObjects.push(m_staticTextStatusMiddle->GetLabel());
- m_staticTextStatusMiddle->SetLabel(text);
- m_staticTextStatusMiddle->SetForegroundColour(wxColour(31, 57, 226)); //highlight color: blue
- m_panelStatusBar->Layout();
-}
-
-
-void MainDialog::clearStatusBar()
-{
- while (stackObjects.size() > 0)
- stackObjects.pop();
-
- m_staticTextStatusMiddle->SetForegroundColour(*wxBLACK); //reset color
- m_staticTextStatusLeft->SetLabel(wxEmptyString);
- m_staticTextStatusMiddle->SetLabel(wxEmptyString);
- m_staticTextStatusRight->SetLabel(wxEmptyString);
-}
-
-
-void MainDialog::disableAllElements()
-{
- //disenables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion
- m_bpButtonCmpConfig-> Disable();
- m_notebookBottomLeft->Disable();
- m_checkBoxHideFilt-> Disable();
- m_bpButtonSyncConfig->Disable();
- m_buttonStartSync-> Disable();
- m_dirPickerLeft-> Disable();
- m_dirPickerRight-> Disable();
- m_bpButtonSwapSides-> Disable();
- m_bpButtonLeftOnly-> Disable();
- m_bpButtonLeftNewer-> Disable();
- m_bpButtonEqual-> Disable();
- m_bpButtonDifferent-> Disable();
- m_bpButtonRightNewer->Disable();
- m_bpButtonRightOnly-> Disable();
- m_panelLeft-> Disable();
- m_panelMiddle-> Disable();
- m_panelRight-> Disable();
- m_panelTopLeft-> Disable();
- m_panelTopMiddle-> Disable();
- m_panelTopRight-> Disable();
- m_bpButton10-> Disable();
- m_scrolledWindowFolderPairs->Disable();
- m_menubar1->EnableTop(0, false);
- m_menubar1->EnableTop(1, false);
- m_menubar1->EnableTop(2, false);
- EnableCloseButton(false);
-
- //show abort button
- m_buttonAbort->Enable();
- m_buttonAbort->Show();
- m_buttonCompare->Disable();
- m_buttonCompare->Hide();
- m_buttonAbort->SetFocus();
-}
-
-
-void MainDialog::enableAllElements()
-{
- m_bpButtonCmpConfig-> Enable();
- m_notebookBottomLeft->Enable();
- m_checkBoxHideFilt-> Enable();
- m_bpButtonSyncConfig->Enable();
- m_buttonStartSync-> Enable();
- m_dirPickerLeft-> Enable();
- m_dirPickerRight-> Enable();
- m_bpButtonSwapSides-> Enable();
- m_bpButtonLeftOnly-> Enable();
- m_bpButtonLeftNewer-> Enable();
- m_bpButtonEqual-> Enable();
- m_bpButtonDifferent-> Enable();
- m_bpButtonRightNewer->Enable();
- m_bpButtonRightOnly-> Enable();
- m_panelLeft-> Enable();
- m_panelMiddle-> Enable();
- m_panelRight-> Enable();
- m_panelTopLeft-> Enable();
- m_panelTopMiddle-> Enable();
- m_panelTopRight-> Enable();
- m_bpButton10-> Enable();
- m_scrolledWindowFolderPairs->Enable();
- m_menubar1->EnableTop(0, true);
- m_menubar1->EnableTop(1, true);
- m_menubar1->EnableTop(2, true);
- EnableCloseButton(true);
-
- //show compare button
- m_buttonAbort->Disable();
- m_buttonAbort->Hide();
- m_buttonCompare->Enable();
- m_buttonCompare->Show();
-}
-
-
-void MainDialog::OnResize(wxSizeEvent& event)
-{
- if (!IsMaximized())
- {
- int width = 0;
- int height = 0;
- int x = 0;
- int y = 0;
-
- GetSize(&width, &height);
- GetPosition(&x, &y);
-
- if (width > 0 && height > 0 && x >= 0 && y >= 0) //test ALL parameters at once, since width/height are invalid if
- {
- //the window is minimized (eg x,y == -32000; height = 28, width = 160)
- widthNotMaximized = width;
- heightNotMaximized = height;
-
- posXNotMaximized = x;
- posYNotMaximized = y;
- }
- }
-
- event.Skip();
-}
-
-
-void MainDialog::OnResizeFolderPairs(wxSizeEvent& event)
-{
- //adapt left-shift display distortion caused by scrollbars for multiple folder pairs
- if (additionalFolderPairs.size() > 0)
- {
- const int width = m_panelTopLeft->GetSize().GetWidth();
-
- for (std::vector<FolderPairPanel*>::iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
- (*i)->m_panelLeft->SetMinSize(wxSize(width, -1));
- }
-
- event.Skip();
-}
-
-
-void MainDialog::onGridLeftButtonEvent(wxKeyEvent& event)
-{
- const int keyCode = event.GetKeyCode();
-
- if (event.ControlDown())
- switch (keyCode)
- {
- case 'C':
- case WXK_INSERT: //CTRL + C || CTRL + INS
- copySelectionToClipboard(m_gridLeft);
- break;
-
- case 'A': //CTRL + A
- m_gridLeft->SelectAll();
- break;
-
- case 'F': //CTRL + F
- FreeFileSync::startFind(*this, *m_gridLeft, *m_gridRight, globalSettings->gui.textSearchRespectCase);
- break;
-
- case WXK_NUMPAD_ADD: //CTRL + '+'
- m_gridLeft->autoSizeColumns();
- break;
- }
-
- else if (event.AltDown())
- switch (keyCode)
- {
- case WXK_LEFT: //ALT + <-
- {
- wxCommandEvent dummy;
- OnContextSyncDirLeft(dummy);
- }
- break;
-
- case WXK_RIGHT: //ALT + ->
- {
- wxCommandEvent dummy;
- OnContextSyncDirRight(dummy);
- }
- break;
-
- case WXK_UP: /* ALT + /|\ */
- case WXK_DOWN: /* ALT + \|/ */
- {
- wxCommandEvent dummy;
- OnContextSyncDirNone(dummy);
- }
- break;
- }
-
- else
- switch (keyCode)
- {
- case WXK_DELETE:
- case WXK_NUMPAD_DELETE:
- deleteSelectedFiles();
- break;
-
- case WXK_SPACE:
- {
- wxCommandEvent dummy;
- OnContextFilterTemp(dummy);
- }
- break;
-
- case WXK_RETURN:
- case WXK_NUMPAD_ENTER:
- {
- wxCommandEvent dummy(wxEVT_NULL, externalAppIDFirst); //open with first external application
- OnContextOpenWith(dummy);
- }
- break;
-
- case WXK_F3: //F3
- case WXK_NUMPAD_F3: //
- FreeFileSync::findNext(*this, *m_gridLeft, *m_gridRight, globalSettings->gui.textSearchRespectCase);
- break;
- }
-
- //event.Skip(); -> swallow event! don't allow default grid commands!
-}
-
-
-void MainDialog::onGridMiddleButtonEvent(wxKeyEvent& event)
-{
- const int keyCode = event.GetKeyCode();
-
- if (event.ControlDown())
- {
- if (keyCode == 67 || keyCode == WXK_INSERT) //CTRL + C || CTRL + INS
- copySelectionToClipboard(m_gridMiddle);
- }
-
- //event.Skip(); -> swallow event! don't allow default grid commands!
-}
-
-
-void MainDialog::onGridRightButtonEvent(wxKeyEvent& event)
-{
- const int keyCode = event.GetKeyCode();
-
- if (event.ControlDown())
- switch (keyCode)
- {
- case 'C':
- case WXK_INSERT: //CTRL + C || CTRL + INS
- copySelectionToClipboard(m_gridRight);
- break;
-
- case 'A': //CTRL + A
- m_gridRight->SelectAll();
- break;
-
- case 'F': //CTRL + F
- FreeFileSync::startFind(*this, *m_gridLeft, *m_gridRight, globalSettings->gui.textSearchRespectCase);
- break;
-
- case WXK_NUMPAD_ADD: //CTRL + '+'
- m_gridRight->autoSizeColumns();
- break;
- }
-
- else if (event.AltDown())
- switch (keyCode)
- {
- case WXK_LEFT: //ALT + <-
- {
- wxCommandEvent dummy;
- OnContextSyncDirLeft(dummy);
- }
- break;
-
- case WXK_RIGHT: //ALT + ->
- {
- wxCommandEvent dummy;
- OnContextSyncDirRight(dummy);
- }
- break;
-
- case WXK_UP: /* ALT + /|\ */
- case WXK_DOWN: /* ALT + \|/ */
- {
- wxCommandEvent dummy;
- OnContextSyncDirNone(dummy);
- }
- break;
- }
-
- else
- switch (keyCode)
- {
- case WXK_DELETE:
- case WXK_NUMPAD_DELETE:
- deleteSelectedFiles();
- break;
-
- case WXK_SPACE:
- {
- wxCommandEvent dummy;
- OnContextFilterTemp(dummy);
- }
- break;
-
- case WXK_RETURN:
- case WXK_NUMPAD_ENTER:
- {
- wxCommandEvent dummy(wxEVT_NULL, externalAppIDFirst); //open with first external application
- OnContextOpenWith(dummy);
- }
- break;
-
- case WXK_F3: //F3
- case WXK_NUMPAD_F3: //
- FreeFileSync::findNext(*this, *m_gridLeft, *m_gridRight, globalSettings->gui.textSearchRespectCase);
- break;
- }
-
- //event.Skip(); -> swallow event! don't allow default grid commands!
-}
-
-
-
-//------------------------------------------------------------
-//temporal variables used by exclude via context menu
-struct SelectedExtension : public wxObject
-{
- SelectedExtension(const Zstring& ext) : extension(ext) {}
-
- Zstring extension;
-};
-
-struct FilterObject
-{
- FilterObject(const Zstring& relName, bool isDirectory) :
- relativeName(relName),
- isDir(isDirectory) {}
- Zstring relativeName;
- bool isDir;
-};
-
-typedef std::vector<FilterObject> FilterObjList;
-
-struct FilterObjContainer : public wxObject
-{
- FilterObjContainer(const FilterObjList& objList) : selectedObjects(objList) {}
-
- FilterObjList selectedObjects;
-};
-//------------------------------------------------------------
-
-
-
-void MainDialog::OnContextRim(wxGridEvent& event)
-{
- //usability: select row unter right-click if not already selected
- wxGrid* sourceGrid = dynamic_cast<wxGrid*>(event.GetEventObject());
- if (sourceGrid != NULL)
- {
- const int clickedRow = event.GetRow();
- const int clickedCol = event.GetCol();
- if (clickedRow >= 0 && clickedCol >= 0 && !sourceGrid->IsInSelection(clickedRow, 0))
- {
- sourceGrid->SelectRow(clickedRow);
- sourceGrid->SetGridCursor(clickedRow, clickedCol);
-
- if (sourceGrid == m_gridLeft)
- m_gridRight->ClearSelection();
- else if (sourceGrid == m_gridRight)
- m_gridLeft->ClearSelection();
- }
- }
- //------------------------------------------------------------------------------
-
-
- const std::set<size_t> selectionLeft = getSelectedRows(m_gridLeft);
- const std::set<size_t> selectionRight = getSelectedRows(m_gridRight);
-
- const size_t selectionBegin = selectionLeft.size() + selectionRight.size() == 0 ? 0 :
- selectionLeft.size() == 0 ? *selectionRight.begin() :
- selectionRight.size() == 0 ? *selectionLeft.begin() :
- std::min(*selectionLeft.begin(), *selectionRight.begin());
-
- const FileSystemObject* fsObj = gridDataView->getObject(selectionBegin);
-
-
- //#######################################################
- //re-create context menu
- contextMenu.reset(new wxMenu);
-
- if (syncPreview->previewIsEnabled() &&
- fsObj && fsObj->getSyncOperation() != SO_EQUAL)
- {
- if (selectionLeft.size() + selectionRight.size() > 0)
- {
- //CONTEXT_SYNC_DIR_LEFT
- wxMenuItem* menuItemSyncDirLeft = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_LEFT, wxString(_("Set direction:")) +
- wxT(" ") + getSymbol(fsObj->testSyncOperation(true, SYNC_DIR_LEFT)) +
- wxT("\tALT + LEFT")); //Linux needs a direction, "<-", because it has no context menu icons!
- menuItemSyncDirLeft->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_LEFT)));
- contextMenu->Append(menuItemSyncDirLeft);
-
- //CONTEXT_SYNC_DIR_NONE
- wxMenuItem* menuItemSyncDirNone = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_NONE, wxString(_("Set direction:")) +
- wxT(" ") + getSymbol(fsObj->testSyncOperation(true, SYNC_DIR_NONE)) +
- wxT("\tALT + UP"));
- menuItemSyncDirNone->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_NONE)));
- contextMenu->Append(menuItemSyncDirNone);
-
- //CONTEXT_SYNC_DIR_RIGHT
- wxMenuItem* menuItemSyncDirRight = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_RIGHT, wxString(_("Set direction:")) +
- wxT(" ") + getSymbol(fsObj->testSyncOperation(true, SYNC_DIR_RIGHT)) +
- wxT("\tALT + RIGHT"));
- menuItemSyncDirRight->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_RIGHT)));
- contextMenu->Append(menuItemSyncDirRight);
-
- contextMenu->AppendSeparator();
- }
- }
-
-
- //CONTEXT_FILTER_TEMP
- if (fsObj && (selectionLeft.size() + selectionRight.size() > 0))
- {
- if (fsObj->isActive())
- {
- wxMenuItem* menuItemExclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, wxString(_("Exclude temporarily")) + wxT("\tSPACE"));
- menuItemExclTemp->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("checkboxFalse")));
- contextMenu->Append(menuItemExclTemp);
- }
- else
- {
- wxMenuItem* menuItemInclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, wxString(_("Include temporarily")) + wxT("\tSPACE"));
- menuItemInclTemp->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("checkboxTrue")));
- contextMenu->Append(menuItemInclTemp);
- }
- }
- else
- {
- contextMenu->Append(CONTEXT_FILTER_TEMP, wxString(_("Exclude temporarily")) + wxT("\tSPACE")); //this element should always be visible
- contextMenu->Enable(CONTEXT_FILTER_TEMP, false);
- }
-
- //###############################################################################################
- //get list of relative file/dir-names for filtering
- FilterObjList exFilterCandidateObj;
-
- class AddFilter : public FSObjectVisitor
- {
- public:
- AddFilter(FilterObjList& fl) : filterList_(fl) {}
- virtual void visit(const FileMapping& fileObj)
- {
- filterList_.push_back(FilterObject(fileObj.getObjRelativeName(), false));
- }
- virtual void visit(const SymLinkMapping& linkObj)
- {
- filterList_.push_back(FilterObject(linkObj.getObjRelativeName(), false));
- }
- virtual void visit(const DirMapping& dirObj)
- {
- filterList_.push_back(FilterObject(dirObj.getObjRelativeName(), true));
- }
-
- private:
- FilterObjList& filterList_;
- } newFilterEntry(exFilterCandidateObj);
-
-
- for (std::set<size_t>::const_iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i)
- {
- const FileSystemObject* currObj = gridDataView->getObject(*i);
- if (currObj && !currObj->isEmpty<LEFT_SIDE>())
- currObj->accept(newFilterEntry);
- }
- for (std::set<size_t>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i)
- {
- const FileSystemObject* currObj = gridDataView->getObject(*i);
- if (currObj && !currObj->isEmpty<RIGHT_SIDE>())
- currObj->accept(newFilterEntry);
- }
- //###############################################################################################
-
- //CONTEXT_EXCLUDE_EXT
- if (exFilterCandidateObj.size() > 0 && !exFilterCandidateObj[0].isDir)
- {
- const Zstring filename = exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR);
- if (filename.Find(wxChar('.'), false) != Zstring::npos) //be careful: AfterLast would return the whole string if '.' were not found!
- {
- const Zstring extension = filename.AfterLast(DefaultChar('.'));
-
- //add context menu item
- wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + zToWx(extension));
- menuItemExclExt->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("filterSmall")));
- contextMenu->Append(menuItemExclExt);
-
- //connect event
- contextMenu->Connect(CONTEXT_EXCLUDE_EXT,
- wxEVT_COMMAND_MENU_SELECTED,
- wxCommandEventHandler(MainDialog::OnContextExcludeExtension),
- new SelectedExtension(extension), //ownership passed!
- this);
- }
- }
-
-
- //CONTEXT_EXCLUDE_OBJ
- wxMenuItem* menuItemExclObj = NULL;
- if (exFilterCandidateObj.size() == 1)
- menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + zToWx(exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR)));
- else if (exFilterCandidateObj.size() > 1)
- menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + _("<multiple selection>"));
-
- if (menuItemExclObj != NULL)
- {
- menuItemExclObj->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("filterSmall")));
- contextMenu->Append(menuItemExclObj);
-
- //connect event
- contextMenu->Connect(CONTEXT_EXCLUDE_OBJ,
- wxEVT_COMMAND_MENU_SELECTED,
- wxCommandEventHandler(MainDialog::OnContextExcludeObject),
- new FilterObjContainer(exFilterCandidateObj), //ownership passed!
- this);
- }
-
-
-
- //CONTEXT_EXTERNAL_APP
- if (!globalSettings->gui.externelApplications.empty())
- {
- contextMenu->AppendSeparator();
-
- const bool externalAppEnabled = (m_gridLeft->isLeadGrid() || m_gridRight->isLeadGrid()) &&
- (selectionLeft.size() + selectionRight.size() == 1);
-
- int newID = externalAppIDFirst;
- for (xmlAccess::ExternalApps::iterator i = globalSettings->gui.externelApplications.begin();
- i != globalSettings->gui.externelApplications.end();
- ++i, ++newID)
- {
- //some trick to translate default external apps on the fly: 1. "open in explorer" 2. "start directly"
- wxString description = wxGetTranslation(i->first);
- if (description.empty())
- description = wxT(" "); //wxWidgets doesn't like empty items
-
- if (i == globalSettings->gui.externelApplications.begin())
- contextMenu->Append(newID, description + wxT("\t") + wxString(_("D-Click")) + wxT("; ENTER"));
- else
- contextMenu->Append(newID, description);
-
- contextMenu->Enable(newID, externalAppEnabled);
-
- //register event
- contextMenu->Connect(newID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextOpenWith), NULL, this);
- }
- }
-
-
- contextMenu->AppendSeparator();
-
-
- //CONTEXT_CLIPBOARD
- contextMenu->Append(CONTEXT_CLIPBOARD, _("Copy to clipboard\tCTRL+C"));
-
- if ( (m_gridLeft->isLeadGrid() && selectionLeft.size()) ||
- (m_gridRight->isLeadGrid() && selectionRight.size()))
- contextMenu->Enable(CONTEXT_CLIPBOARD, true);
- else
- contextMenu->Enable(CONTEXT_CLIPBOARD, false);
-
-
- //CONTEXT_DELETE_FILES
- contextMenu->Append(CONTEXT_DELETE_FILES, _("Delete files\tDEL"));
-
- if (selectionLeft.size() + selectionRight.size() == 0)
- contextMenu->Enable(CONTEXT_DELETE_FILES, false);
-
-
- //###############################################################################################
- //connect events
- contextMenu->Connect(CONTEXT_FILTER_TEMP, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextFilterTemp), NULL, this);
- contextMenu->Connect(CONTEXT_CLIPBOARD, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCopyClipboard), NULL, this);
- contextMenu->Connect(CONTEXT_DELETE_FILES, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextDeleteFiles), NULL, this);
- contextMenu->Connect(CONTEXT_SYNC_DIR_LEFT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncDirLeft), NULL, this);
- contextMenu->Connect(CONTEXT_SYNC_DIR_NONE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncDirNone), NULL, this);
- contextMenu->Connect(CONTEXT_SYNC_DIR_RIGHT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncDirRight), NULL, this);
-
- //show context menu
- PopupMenu(contextMenu.get());
-}
-
-
-void MainDialog::OnContextFilterTemp(wxCommandEvent& event)
-{
- //merge selections from left and right grid
- std::set<size_t> selection = getSelectedRows();
- if (!selection.empty())
- filterRangeManually(selection, static_cast<int>(*selection.begin()));
-}
-
-
-void MainDialog::OnContextExcludeExtension(wxCommandEvent& event)
-{
- SelectedExtension* selExtension = dynamic_cast<SelectedExtension*>(event.m_callbackUserData);
- if (selExtension)
- {
- const Zstring newExclude = Zstring(DefaultStr("*.")) + selExtension->extension;
-
- //add to filter config
- Zstring& excludeFilter = currentCfg.mainCfg.globalFilter.excludeFilter;
- if (!excludeFilter.empty() && !excludeFilter.EndsWith(DefaultStr(";")))
- excludeFilter += DefaultStr("\n");
- excludeFilter += newExclude + DefaultStr(";"); //';' is appended to 'mark' that next exclude extension entry won't write to new line
-
- updateFilterButtons();
-
- //do not fully apply filter, just exclude new items
- addExcludeFiltering(newExclude, gridDataView->getDataTentative());
- //applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
- updateGuiGrid();
-
- if (currentCfg.hideFilteredElements)
- {
- m_gridLeft-> ClearSelection();
- m_gridRight-> ClearSelection();
- m_gridMiddle->ClearSelection();
- }
- }
-}
-
-
-void MainDialog::OnContextExcludeObject(wxCommandEvent& event)
-{
- FilterObjContainer* objCont = dynamic_cast<FilterObjContainer*>(event.m_callbackUserData);
- if (objCont)
- {
- if (objCont->selectedObjects.size() > 0) //check needed to determine if filtering is needed
- {
- Zstring newExclude;
- for (std::vector<FilterObject>::const_iterator i = objCont->selectedObjects.begin(); i != objCont->selectedObjects.end(); ++i)
- {
- if (i != objCont->selectedObjects.begin())
- newExclude += DefaultStr("\n");
-
- newExclude += globalFunctions::FILE_NAME_SEPARATOR + i->relativeName;
- if (i->isDir)
- newExclude += globalFunctions::FILE_NAME_SEPARATOR;
- }
-
- //add to filter config
- Zstring& excludeFilter = currentCfg.mainCfg.globalFilter.excludeFilter;
- if (!excludeFilter.empty() && !excludeFilter.EndsWith(DefaultStr("\n")))
- excludeFilter += DefaultStr("\n");
- excludeFilter += newExclude;
-
- updateFilterButtons();
-
- //do not fully apply filter, just exclude new items
- addExcludeFiltering(newExclude, gridDataView->getDataTentative());
- //applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
- updateGuiGrid();
-
- if (currentCfg.hideFilteredElements)
- {
- m_gridLeft->ClearSelection();
- m_gridRight->ClearSelection();
- m_gridMiddle->ClearSelection();
- }
- }
- }
-}
-
-
-void MainDialog::OnContextCopyClipboard(wxCommandEvent& event)
-{
- if (m_gridLeft->isLeadGrid())
- copySelectionToClipboard(m_gridLeft);
- else if (m_gridRight->isLeadGrid())
- copySelectionToClipboard(m_gridRight);
-}
-
-
-void MainDialog::OnContextOpenWith(wxCommandEvent& event)
-{
- if (m_gridLeft->isLeadGrid() || m_gridRight->isLeadGrid())
- {
- const CustomGrid* leadGrid = m_gridLeft->isLeadGrid() ?
- static_cast<CustomGrid*>(m_gridLeft) :
- static_cast<CustomGrid*>(m_gridRight);
- std::set<size_t> selection = getSelectedRows(leadGrid);
-
- const int index = event.GetId() - externalAppIDFirst;
-
- if ( selection.size() == 1 &&
- 0 <= index && static_cast<size_t>(index) < globalSettings->gui.externelApplications.size())
- openExternalApplication(*selection.begin(), m_gridLeft->isLeadGrid(), globalSettings->gui.externelApplications[index].second);
- }
-}
-
-
-void MainDialog::OnContextDeleteFiles(wxCommandEvent& event)
-{
- deleteSelectedFiles();
-}
-
-
-void MainDialog::OnContextSyncDirLeft(wxCommandEvent& event)
-{
- //merge selections from left and right grid
- const std::set<size_t> selection = getSelectedRows();
- setSyncDirManually(selection, FreeFileSync::SYNC_DIR_LEFT);
-}
-
-
-void MainDialog::OnContextSyncDirNone(wxCommandEvent& event)
-{
- //merge selections from left and right grid
- const std::set<size_t> selection = getSelectedRows();
- setSyncDirManually(selection, FreeFileSync::SYNC_DIR_NONE);
-}
-
-
-void MainDialog::OnContextSyncDirRight(wxCommandEvent& event)
-{
- //merge selections from left and right grid
- const std::set<size_t> selection = getSelectedRows();
- setSyncDirManually(selection, FreeFileSync::SYNC_DIR_RIGHT);
-}
-
-
-void MainDialog::OnContextRimLabelLeft(wxGridEvent& event)
-{
- contextMenu.reset(new wxMenu); //re-create context menu
- contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_LEFT, _("Customize..."));
-
- contextMenu->AppendSeparator();
-
- wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), CONTEXT_AUTO_ADJUST_COLUMN_LEFT, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK);
- contextMenu->Append(itemAutoAdjust);
- itemAutoAdjust->Check(globalSettings->gui.autoAdjustColumnsLeft);
-
- contextMenu->Connect(CONTEXT_CUSTOMIZE_COLUMN_LEFT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnLeft), NULL, this);
- contextMenu->Connect(CONTEXT_AUTO_ADJUST_COLUMN_LEFT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustLeft), NULL, this);
-
- PopupMenu(contextMenu.get()); //show context menu
-}
-
-
-void MainDialog::OnContextRimLabelRight(wxGridEvent& event)
-{
- contextMenu.reset(new wxMenu); //re-create context menu
- contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_RIGHT, _("Customize..."));
-
- contextMenu->AppendSeparator();
-
- wxMenuItem* itemAutoAdjust = new wxMenuItem(contextMenu.get(), CONTEXT_AUTO_ADJUST_COLUMN_RIGHT, _("Auto-adjust columns"), wxEmptyString, wxITEM_CHECK);
- contextMenu->Append(itemAutoAdjust);
- itemAutoAdjust->Check(globalSettings->gui.autoAdjustColumnsRight);
-
- contextMenu->Connect(CONTEXT_CUSTOMIZE_COLUMN_RIGHT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextCustColumnRight), NULL, this);
- contextMenu->Connect(CONTEXT_AUTO_ADJUST_COLUMN_RIGHT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextAutoAdjustRight), NULL, this);
-
- PopupMenu(contextMenu.get()); //show context menu
-}
-
-
-void MainDialog::OnContextCustColumnLeft(wxCommandEvent& event)
-{
- xmlAccess::ColumnAttributes colAttr = m_gridLeft->getColumnAttributes();
-
- if (FreeFileSync::showCustomizeColsDlg(colAttr) == DefaultReturnCode::BUTTON_OKAY)
- {
- m_gridLeft->setColumnAttributes(colAttr);
-
- m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING)); //hide sort direction indicator on GUI grids
- m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- }
-}
-
-
-void MainDialog::OnContextCustColumnRight(wxCommandEvent& event)
-{
- xmlAccess::ColumnAttributes colAttr = m_gridRight->getColumnAttributes();
-
- if (FreeFileSync::showCustomizeColsDlg(colAttr) == DefaultReturnCode::BUTTON_OKAY)
- {
- m_gridRight->setColumnAttributes(colAttr);
-
- m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING)); //hide sort direction indicator on GUI grids
- m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- }
-}
-
-
-void MainDialog::OnContextAutoAdjustLeft(wxCommandEvent& event)
-{
- globalSettings->gui.autoAdjustColumnsLeft = !globalSettings->gui.autoAdjustColumnsLeft;
- updateGuiGrid();
-}
-
-
-void MainDialog::OnContextAutoAdjustRight(wxCommandEvent& event)
-{
- globalSettings->gui.autoAdjustColumnsRight = !globalSettings->gui.autoAdjustColumnsRight;
- updateGuiGrid();
-}
-
-
-void MainDialog::OnContextMiddle(wxGridEvent& event)
-{
- contextMenu.reset(new wxMenu); //re-create context menu
-
- contextMenu->Append(CONTEXT_CHECK_ALL, _("Include all rows"));
- contextMenu->Append(CONTEXT_UNCHECK_ALL, _("Exclude all rows"));
-
- if (gridDataView->rowsTotal() == 0)
- {
- contextMenu->Enable(CONTEXT_CHECK_ALL, false);
- contextMenu->Enable(CONTEXT_UNCHECK_ALL, false);
- }
-
- contextMenu->Connect(CONTEXT_CHECK_ALL, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextIncludeAll), NULL, this);
- contextMenu->Connect(CONTEXT_UNCHECK_ALL, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextExcludeAll), NULL, this);
-
- PopupMenu(contextMenu.get()); //show context menu
-}
-
-
-void MainDialog::OnContextMiddleLabel(wxGridEvent& event)
-{
- contextMenu.reset(new wxMenu); //re-create context menu
-
- wxMenuItem* itemSyncPreview = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_PREVIEW, _("Synchronization Preview"));
- wxMenuItem* itemCmpResult = new wxMenuItem(contextMenu.get(), CONTEXT_COMPARISON_RESULT, _("Comparison Result"));
-
- if (syncPreview->previewIsEnabled())
- itemSyncPreview->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("syncViewSmall")));
- else
- itemCmpResult->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("cmpViewSmall")));
-
- contextMenu->Append(itemCmpResult);
- contextMenu->Append(itemSyncPreview);
-
- contextMenu->Connect(CONTEXT_SYNC_PREVIEW, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncView), NULL, this);
- contextMenu->Connect(CONTEXT_COMPARISON_RESULT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextComparisonView), NULL, this);
-
- PopupMenu(contextMenu.get()); //show context menu
-}
-
-
-void MainDialog::OnContextIncludeAll(wxCommandEvent& event)
-{
- FreeFileSync::setActiveStatus(true, gridDataView->getDataTentative());
- refreshGridAfterFilterChange(0); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts break;
-}
-
-
-void MainDialog::OnContextExcludeAll(wxCommandEvent& event)
-{
- FreeFileSync::setActiveStatus(false, gridDataView->getDataTentative());
- refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
-}
-
-
-void MainDialog::OnContextComparisonView(wxCommandEvent& event)
-{
- syncPreview->enablePreview(false); //change view
-}
-
-
-void MainDialog::OnContextSyncView(wxCommandEvent& event)
-{
- syncPreview->enablePreview(true); //change view
-}
-
-
-void MainDialog::OnDirSelected(wxFileDirPickerEvent& event)
-{
- //left and right directory text-control and dirpicker are synchronized by MainFolderDragDrop automatically
-
- //disable the sync button
- syncPreview->enableSynchronization(false);
-
- //clear grids
- gridDataView->clearAllRows();
- updateGuiGrid();
-
- event.Skip();
-}
-
-
-wxString getFormattedHistoryElement(const wxString& filename)
-{
- wxString output = wxFileName(filename).GetFullName();
- if (output.EndsWith(wxT(".ffs_gui")))
- output = output.BeforeLast('.');
- return output;
-}
-
-
-//tests if the same filenames are specified, even if they are relative to the current working directory/include symlinks or \\?\ prefix
-class FindDuplicates
-{
-public:
- FindDuplicates(const Zstring& name) : m_name(name) {}
-
- bool operator()(const wxString& other) const
- {
- return Utility::sameFileSpecified(m_name, wxToZ(other));
- }
-
-private:
- const Zstring& m_name;
-};
-
-
-void MainDialog::addFileToCfgHistory(const wxString& filename)
-{
- //only (still) existing files should be included in the list
- if (Utility::fileExists(wxToZ(filename), 200) == Utility::EXISTING_FALSE) //potentially slow network access: wait 200ms
- return;
-
- std::vector<wxString>::const_iterator i = find_if(cfgFileNames.begin(), cfgFileNames.end(), FindDuplicates(wxToZ(filename)));
- if (i != cfgFileNames.end())
- {
- //if entry is in the list, then jump to element
- m_choiceHistory->SetSelection(i - cfgFileNames.begin());
- }
- else
- {
- cfgFileNames.insert(cfgFileNames.begin(), filename);
-
- //the default config file should receive another name on GUI
- if (Utility::sameFileSpecified(wxToZ(lastConfigFileName()), wxToZ(filename)))
- m_choiceHistory->Insert(_("<Last session>"), 0); //insert at beginning of list
- else
- m_choiceHistory->Insert(getFormattedHistoryElement(filename), 0); //insert at beginning of list
-
- m_choiceHistory->SetSelection(0);
- }
-
- //keep maximal size of history list
- if (cfgFileNames.size() > globalSettings->gui.cfgHistoryMax)
- {
- //delete last rows
- cfgFileNames.pop_back();
- m_choiceHistory->Delete(globalSettings->gui.cfgHistoryMax);
- }
-}
-
-
-void MainDialog::addLeftFolderToHistory(const wxString& leftFolder)
-{
- m_directoryLeft->addPairToFolderHistory(leftFolder, globalSettings->gui.folderHistLeftMax);
-}
-
-
-void MainDialog::addRightFolderToHistory(const wxString& rightFolder)
-{
- m_directoryRight->addPairToFolderHistory(rightFolder, globalSettings->gui.folderHistRightMax);
-}
-
-
-void MainDialog::OnSaveConfig(wxCommandEvent& event)
-{
- trySaveConfig();
-}
-
-
-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!
- if (defaultFileName.EndsWith(wxT(".ffs_batch")))
- defaultFileName.Replace(wxT(".ffs_batch"), wxT(".ffs_gui"), false);
-
-
- wxFileDialog* filePicker = new wxFileDialog(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"), wxFD_SAVE);
- if (filePicker->ShowModal() == wxID_OK)
- {
- const wxString newFileName = filePicker->GetPath();
-
- if (FreeFileSync::fileExists(wxToZ(newFileName)))
- {
- QuestionDlg* messageDlg = new QuestionDlg(this,
- QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_CANCEL,
- wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""));
-
- if (messageDlg->ShowModal() != QuestionDlg::BUTTON_YES)
- return trySaveConfig(); //retry
- }
-
- if (writeConfigurationToXml(newFileName))
- {
- pushStatusInformation(_("Configuration saved!"));
- return true;
- }
- }
-
- return false;
-}
-
-
-void MainDialog::OnLoadConfig(wxCommandEvent& event)
-{
- wxFileDialog* filePicker = new wxFileDialog(this,
- wxEmptyString,
- wxEmptyString,
- wxEmptyString,
- wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui;*.ffs_batch)|*.ffs_gui;*.ffs_batch"), wxFD_OPEN);
-
- if (filePicker->ShowModal() == wxID_OK)
- loadConfiguration(filePicker->GetPath());
-}
-
-
-void MainDialog::OnNewConfig(wxCommandEvent& event)
-{
- if (!saveOldConfig()) //notify user about changed settings
- return;
-
- setCurrentConfiguration(xmlAccess::XmlGuiConfig());
-
- SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
- currentConfigFileName.clear();
-}
-
-
-void MainDialog::OnLoadFromHistory(wxCommandEvent& event)
-{
- const int selectedItem = m_choiceHistory->GetSelection();
- if (0 <= selectedItem && unsigned(selectedItem) < cfgFileNames.size())
- loadConfiguration(cfgFileNames[selectedItem]);
-}
-
-
-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 (lastConfigurationSaved != getCurrentConfiguration())
- {
- bool dontShowAgain = !globalSettings->optDialogs.popupOnConfigChange;
-
- QuestionDlg* notifyChangeDlg = new QuestionDlg(this,
- QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_NO | QuestionDlg::BUTTON_CANCEL,
- _("Save changes to current configuration?"),
- &dontShowAgain);
-
- switch (notifyChangeDlg->ShowModal())
- {
- case QuestionDlg::BUTTON_YES:
- if (!trySaveConfig())
- return false;
- break;
- case QuestionDlg::BUTTON_NO:
- globalSettings->optDialogs.popupOnConfigChange = !dontShowAgain;
- break;
- case QuestionDlg::BUTTON_CANCEL:
- return false;
- }
- }
- }
- return true;
-}
-
-
-void MainDialog::loadConfiguration(const wxString& filename)
-{
- if (!filename.IsEmpty())
- {
- if (!saveOldConfig())
- return;
-
- if (readConfigurationFromXml(filename))
- pushStatusInformation(_("Configuration loaded!"));
- }
-}
-
-
-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_choiceHistory->GetCurrentSelection();
- if ( 0 <= selectedItem &&
- selectedItem < int(m_choiceHistory->GetCount()) &&
- selectedItem < int(cfgFileNames.size()))
- {
- //delete selected row
- cfgFileNames.erase(cfgFileNames.begin() + selectedItem);
- m_choiceHistory->Delete(selectedItem);
- }
- }
- event.Skip();
-}
-
-
-void MainDialog::OnClose(wxCloseEvent &event)
-{
- if (!saveOldConfig()) //notify user about changed settings
- return;
-
- Destroy();
-}
-
-
-void MainDialog::OnQuit(wxCommandEvent &event)
-{
- if (!saveOldConfig()) //notify user about changed settings
- return;
-
- Destroy();
-}
-
-
-void MainDialog::OnCheckRows(FFSCheckRowsEvent& event)
-{
- const int lowerBound = std::min(event.rowFrom, event.rowTo);
- const int upperBound = std::max(event.rowFrom, event.rowTo);
-
- if (0 <= lowerBound)
- {
- std::set<size_t> selectedRowsOnView;
-
- for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->rowsOnView()) - 1); ++i)
- selectedRowsOnView.insert(i);
-
- filterRangeManually(selectedRowsOnView, event.rowFrom);
- }
-}
-
-
-void MainDialog::OnSetSyncDirection(FFSSyncDirectionEvent& event)
-{
- const int lowerBound = std::min(event.rowFrom, event.rowTo);
- const int upperBound = std::max(event.rowFrom, event.rowTo);
-
- if (0 <= lowerBound)
- {
- for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->rowsOnView()) - 1); ++i)
- {
- FileSystemObject* fsObj = gridDataView->getObject(i);
- if (fsObj)
- {
- setSyncDirectionRec(event.direction, *fsObj); //set new direction (recursively)
- FreeFileSync::setActiveStatus(true, *fsObj); //works recursively for directories
- }
- }
-
- updateGuiGrid();
- }
-}
-
-
-bool MainDialog::readConfigurationFromXml(const wxString& filename)
-{
- //load XML
- xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!!
- bool parsingError = true;
- try
- {
- xmlAccess::readGuiOrBatchConfig(filename, newGuiCfg); //allow reading batch configurations also
- parsingError = false;
- }
- catch (const xmlAccess::XmlError& error)
- {
- if (error.getSeverity() == xmlAccess::XmlError::WARNING)
- wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
- else
- {
- wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
- return false;
- }
- }
-
- setCurrentConfiguration(newGuiCfg);
-
- setLastUsedConfig(filename, parsingError ? xmlAccess::XmlGuiConfig() : newGuiCfg); //simulate changed config on parsing errors
-
- return !parsingError;
-}
-
-
-void MainDialog::setLastUsedConfig(const wxString& filename, const xmlAccess::XmlGuiConfig& guiConfig)
-{
- addFileToCfgHistory(filename); //put filename on list of last used config files
-
- //set title
- if (filename == lastConfigFileName())
- {
- SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
- currentConfigFileName.clear();
- }
- else
- {
- SetTitle(wxString(wxT("FreeFileSync - ")) + filename);
- currentConfigFileName = filename;
- }
-
- lastConfigurationSaved = guiConfig;
-}
-
-
-bool MainDialog::writeConfigurationToXml(const wxString& filename)
-{
- const xmlAccess::XmlGuiConfig guiCfg = getCurrentConfiguration();
-
- //write config to XML
- try
- {
- xmlAccess::writeGuiConfig(guiCfg, filename);
- }
- catch (const xmlAccess::XmlError& error)
- {
- wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR);
- return false;
- }
-
- setLastUsedConfig(filename, guiCfg);
-
- return true;
-}
-
-
-void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCfg)
-{
- currentCfg = newGuiCfg;
-
- //evaluate new settings...
-
- //disable the sync button
- syncPreview->enableSynchronization(false);
-
- //clear grids
- gridDataView->clearAllRows();
- updateGuiGrid();
-
- //(re-)set view filter buttons
- initViewFilterButtons();
-
- updateFilterButtons();
-
- //set first folder pair
- firstFolderPair->setValues(currentCfg.mainCfg.firstPair.leftDirectory,
- 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()!!! :(
-
- //clear existing additional folder pairs
- clearAddFolderPairs();
-
- //set additional pairs
- addFolderPair(currentCfg.mainCfg.additionalPairs);
-
-
- //read GUI layout
- m_checkBoxHideFilt->SetValue(currentCfg.hideFilteredElements);
-
- syncPreview->enablePreview(currentCfg.syncPreviewEnabled);
-
- //###########################################################
- //update compare variant name
- m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(currentCfg.mainCfg.compareVar) + wxT(")"));
-
- //update sync variant name
- m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + currentCfg.mainCfg.getSyncVariantName() + wxT(")"));
- bSizer6->Layout(); //adapt layout for variant text
-}
-
-
-inline
-FolderPairEnh getEnahncedPair(const FolderPairPanel* panel)
-{
- return FolderPairEnh(panel->getLeftDir(),
- panel->getRightDir(),
- panel->getAltSyncConfig(),
- panel->getAltFilterConfig());
-}
-
-
-xmlAccess::XmlGuiConfig MainDialog::getCurrentConfiguration() const
-{
- xmlAccess::XmlGuiConfig guiCfg = currentCfg;
-
- //load settings whose ownership lies not in currentCfg:
-
- //first folder pair
- guiCfg.mainCfg.firstPair = FolderPairEnh(firstFolderPair->getLeftDir(),
- firstFolderPair->getRightDir(),
- firstFolderPair->getAltSyncConfig(),
- firstFolderPair->getAltFilterConfig());
-
- //add additional pairs
- guiCfg.mainCfg.additionalPairs.clear();
- std::transform(additionalFolderPairs.begin(), additionalFolderPairs.end(),
- std::back_inserter(guiCfg.mainCfg.additionalPairs), getEnahncedPair);
-
- //sync preview
- guiCfg.syncPreviewEnabled = syncPreview->previewIsEnabled();
-
- return guiCfg;
-}
-
-
-const wxString& MainDialog::lastConfigFileName()
-{
- static wxString instance = FreeFileSync::getConfigDir() + wxT("LastRun.ffs_gui");
- return instance;
-}
-
-
-void MainDialog::refreshGridAfterFilterChange(const int delay)
-{
- //signal UI that grids need to be refreshed on next Update()
- m_gridLeft->ForceRefresh();
- m_gridMiddle->ForceRefresh();
- m_gridRight->ForceRefresh();
- Update(); //show changes resulting from ForceRefresh()
-
- if (currentCfg.hideFilteredElements)
- {
- wxMilliSleep(delay); //some delay to show user the rows he has filtered out before they are removed
- updateGuiGrid(); //redraw grid to remove excluded elements (keeping sort sequence)
-
- m_gridLeft->ClearSelection();
- m_gridRight->ClearSelection();
- }
- else
- updateGuiGrid();
-}
-
-
-void MainDialog::OnHideFilteredButton(wxCommandEvent &event)
-{
- //toggle showing filtered rows
- currentCfg.hideFilteredElements = !currentCfg.hideFilteredElements;
- //make sure, checkbox and "hideFiltered" are in sync
- m_checkBoxHideFilt->SetValue(currentCfg.hideFilteredElements);
-
- m_gridLeft->ClearSelection();
- m_gridRight->ClearSelection();
- updateGuiGrid();
-
-// event.Skip();
-}
-
-
-void MainDialog::OnConfigureFilter(wxCommandEvent &event)
-{
- if (showFilterDialog(true, //is main filter dialog
- currentCfg.mainCfg.globalFilter.includeFilter,
- currentCfg.mainCfg.globalFilter.excludeFilter) == DefaultReturnCode::BUTTON_OKAY)
- {
- updateFilterButtons(); //refresh global filter icon
- updateFilterConfig(); //re-apply filter
- }
-
- //event.Skip()
-}
-
-
-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);
-
- if (isNullFilter(currentCfg.mainCfg.globalFilter))
- contextMenu->Enable(menuId, false); //disable menu item, if clicking wouldn't make sense anyway
-
- PopupMenu(contextMenu.get()); //show context menu
-}
-
-
-void MainDialog::OnGlobalFilterRemConfirm(wxCommandEvent& event)
-{
- currentCfg.mainCfg.globalFilter = FilterConfig();
-
- updateFilterButtons(); //refresh global filter icon
- updateFilterConfig(); //re-apply filter
-}
-
-
-void MainDialog::OnLeftOnlyFiles(wxCommandEvent& event)
-{
- m_bpButtonLeftOnly->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnLeftNewerFiles(wxCommandEvent& event)
-{
- m_bpButtonLeftNewer->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnDifferentFiles(wxCommandEvent& event)
-{
- m_bpButtonDifferent->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnRightNewerFiles(wxCommandEvent& event)
-{
- m_bpButtonRightNewer->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnRightOnlyFiles(wxCommandEvent& event)
-{
- m_bpButtonRightOnly->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnEqualFiles(wxCommandEvent& event)
-{
- m_bpButtonEqual->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnConflictFiles(wxCommandEvent& event)
-{
- m_bpButtonConflict->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncCreateLeft(wxCommandEvent& event)
-{
- m_bpButtonSyncCreateLeft->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncCreateRight(wxCommandEvent& event)
-{
- m_bpButtonSyncCreateRight->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncDeleteLeft(wxCommandEvent& event)
-{
- m_bpButtonSyncDeleteLeft->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncDeleteRight(wxCommandEvent& event)
-{
- m_bpButtonSyncDeleteRight->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncDirLeft(wxCommandEvent& event)
-{
- m_bpButtonSyncDirOverwLeft->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncDirRight(wxCommandEvent& event)
-{
- m_bpButtonSyncDirOverwRight->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::OnSyncDirNone(wxCommandEvent& event)
-{
- m_bpButtonSyncDirNone->toggle();
- updateGuiGrid();
-}
-
-
-void MainDialog::initViewFilterButtons()
-{
- //compare result buttons
- m_bpButtonLeftOnly->init(GlobalResources::getInstance().getImageByName(wxT("leftOnlyAct")),
- _("Hide files that exist on left side only"),
- GlobalResources::getInstance().getImageByName(wxT("leftOnlyDeact")),
- _("Show files that exist on left side only"));
-
- m_bpButtonRightOnly->init(GlobalResources::getInstance().getImageByName(wxT("rightOnlyAct")),
- _("Hide files that exist on right side only"),
- GlobalResources::getInstance().getImageByName(wxT("rightOnlyDeact")),
- _("Show files that exist on right side only"));
-
- m_bpButtonLeftNewer->init(GlobalResources::getInstance().getImageByName(wxT("leftNewerAct")),
- _("Hide files that are newer on left"),
- GlobalResources::getInstance().getImageByName(wxT("leftNewerDeact")),
- _("Show files that are newer on left"));
-
- m_bpButtonRightNewer->init(GlobalResources::getInstance().getImageByName(wxT("rightNewerAct")),
- _("Hide files that are newer on right"),
- GlobalResources::getInstance().getImageByName(wxT("rightNewerDeact")),
- _("Show files that are newer on right"));
-
- m_bpButtonEqual->init(GlobalResources::getInstance().getImageByName(wxT("equalAct")),
- _("Hide files that are equal"),
- GlobalResources::getInstance().getImageByName(wxT("equalDeact")),
- _("Show files that are equal"));
-
- m_bpButtonDifferent->init(GlobalResources::getInstance().getImageByName(wxT("differentAct")),
- _("Hide files that are different"),
- GlobalResources::getInstance().getImageByName(wxT("differentDeact")),
- _("Show files that are different"));
-
- m_bpButtonConflict->init(GlobalResources::getInstance().getImageByName(wxT("conflictAct")),
- _("Hide conflicts"),
- GlobalResources::getInstance().getImageByName(wxT("conflictDeact")),
- _("Show conflicts"));
-
- //sync preview buttons
- m_bpButtonSyncCreateLeft->init(GlobalResources::getInstance().getImageByName(wxT("syncCreateLeftAct")),
- _("Hide files that will be created on the left side"),
- GlobalResources::getInstance().getImageByName(wxT("syncCreateLeftDeact")),
- _("Show files that will be created on the left side"));
-
- m_bpButtonSyncCreateRight->init(GlobalResources::getInstance().getImageByName(wxT("syncCreateRightAct")),
- _("Hide files that will be created on the right side"),
- GlobalResources::getInstance().getImageByName(wxT("syncCreateRightDeact")),
- _("Show files that will be created on the right side"));
-
- m_bpButtonSyncDeleteLeft->init(GlobalResources::getInstance().getImageByName(wxT("syncDeleteLeftAct")),
- _("Hide files that will be deleted on the left side"),
- GlobalResources::getInstance().getImageByName(wxT("syncDeleteLeftDeact")),
- _("Show files that will be deleted on the left side"));
-
- m_bpButtonSyncDeleteRight->init(GlobalResources::getInstance().getImageByName(wxT("syncDeleteRightAct")),
- _("Hide files that will be deleted on the right side"),
- GlobalResources::getInstance().getImageByName(wxT("syncDeleteRightDeact")),
- _("Show files that will be deleted on the right side"));
-
- m_bpButtonSyncDirOverwLeft->init(GlobalResources::getInstance().getImageByName(wxT("syncDirLeftAct")),
- _("Hide files that will be overwritten on left side"),
- GlobalResources::getInstance().getImageByName(wxT("syncDirLeftDeact")),
- _("Show files that will be overwritten on left side"));
-
- m_bpButtonSyncDirOverwRight->init(GlobalResources::getInstance().getImageByName(wxT("syncDirRightAct")),
- _("Hide files that will be overwritten on right side"),
- GlobalResources::getInstance().getImageByName(wxT("syncDirRightDeact")),
- _("Show files that will be overwritten on right side"));
-
- m_bpButtonSyncDirNone->init(GlobalResources::getInstance().getImageByName(wxT("syncDirNoneAct")),
- _("Hide files that won't be copied"),
- GlobalResources::getInstance().getImageByName(wxT("syncDirNoneDeact")),
- _("Show files that won't be copied"));
-
- //compare result buttons
- m_bpButtonLeftOnly-> setActive(true);
- m_bpButtonRightOnly-> setActive(true);
- m_bpButtonLeftNewer-> setActive(true);
- m_bpButtonRightNewer->setActive(true);
- m_bpButtonEqual-> setActive(false);
- m_bpButtonDifferent-> setActive(true);
- m_bpButtonConflict-> setActive(true);
-
- //sync preview buttons
- m_bpButtonSyncCreateLeft-> setActive(true);
- m_bpButtonSyncCreateRight-> setActive(true);
- m_bpButtonSyncDeleteLeft-> setActive(true);
- m_bpButtonSyncDeleteRight-> setActive(true);
- m_bpButtonSyncDirOverwLeft-> setActive(true);
- m_bpButtonSyncDirOverwRight->setActive(true);
- m_bpButtonSyncDirNone-> setActive(true);
-}
-
-
-void MainDialog::updateFilterButtons()
-{
- //prepare filter icon
- if (m_notebookBottomLeft->GetImageList() == NULL)
- {
- wxImageList* panelIcons = new wxImageList(16, 16);
- panelIcons->Add(wxBitmap(GlobalResources::getInstance().getImageByName(wxT("filterSmall"))));
- panelIcons->Add(wxBitmap(GlobalResources::getInstance().getImageByName(wxT("filterSmallGrey"))));
- m_notebookBottomLeft->AssignImageList(panelIcons); //pass ownership
- }
-
- //global filter: test for Null-filter
- if (isNullFilter(currentCfg.mainCfg.globalFilter))
- {
- m_bpButtonFilter->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("filterOff")));
- m_bpButtonFilter->SetToolTip(_("No filter selected"));
-
- //additional filter icon
- m_notebookBottomLeft->SetPageImage(1, 1);
- }
- else
- {
- m_bpButtonFilter->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("filterOn")));
- m_bpButtonFilter->SetToolTip(_("Filter is active"));
-
- //show filter icon
- m_notebookBottomLeft->SetPageImage(1, 0);
- }
-
- //update main local filter
- firstFolderPair->refreshButtons();
-
- //update folder pairs
- for (std::vector<FolderPairPanel*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
- {
- FolderPairPanel* dirPair = *i;
- dirPair->refreshButtons();
- }
-}
-
-
-void MainDialog::OnCompare(wxCommandEvent &event)
-{
- //PERF_START;
- clearStatusBar();
-
- wxBusyCursor dummy; //show hourglass cursor
-
- //prevent temporary memory peak by clearing old result list
- gridDataView->clearAllRows();
- updateGuiGrid(); //refresh GUI grid
-
- bool aborted = false;
- try
- {
- //class handling status display and error messages
- CompareStatusHandler statusHandler(this);
-
- //begin comparison
- FreeFileSync::CompareProcess comparison(currentCfg.mainCfg.handleSymlinks,
- currentCfg.mainCfg.hidden.fileTimeTolerance,
- globalSettings->ignoreOneHourDiff,
- globalSettings->optDialogs,
- &statusHandler);
-
- //technical representation of comparison data
- FreeFileSync::FolderComparison newCompareData;
-
- comparison.startCompareProcess(
- FreeFileSync::extractCompareCfg(getCurrentConfiguration().mainCfg), //call getCurrentCfg() to get current values for directory pairs!
- currentCfg.mainCfg.compareVar,
- newCompareData);
-
- gridDataView->setData(newCompareData); //newCompareData is invalidated after this call
-
- //play (optional) sound notification after sync has completed (GUI and batch mode)
- const wxString soundFile = FreeFileSync::getResourceDir() + wxT("Compare_Complete.wav");
- if (fileExists(wxToZ(soundFile)))
- wxSound::Play(soundFile, wxSOUND_ASYNC);
- }
- catch (AbortThisProcess&)
- {
- aborted = true;
- }
-
- if (aborted)
- {
- //disable the sync button
- syncPreview->enableSynchronization(false);
- m_buttonCompare->SetFocus();
- updateGuiGrid(); //refresh grid in ANY case! (also on abort)
- }
- else
- {
- //once compare is finished enable the sync button
- syncPreview->enableSynchronization(true);
- m_buttonStartSync->SetFocus();
-
- //hide sort direction indicator on GUI grids
- m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
-
- //reset last sort selection: used for determining sort direction
- lastSortColumn = -1;
- lastSortGrid = NULL;
-
- m_gridLeft-> ClearSelection();
- m_gridMiddle->ClearSelection();
- m_gridRight-> ClearSelection();
-
- //add to folder history after successful comparison only
- addLeftFolderToHistory( m_directoryLeft->GetValue());
- addRightFolderToHistory(m_directoryRight->GetValue());
-
- //refresh grid in ANY case! (also on abort)
- updateGuiGrid();
-
- //prepare status information
- wxString statusInfo;
- if (allElementsEqual(gridDataView->getDataTentative()))
- statusInfo += _("All directories in sync!");
- pushStatusInformation(statusInfo);
- }
-}
-
-
-void MainDialog::updateGuiGrid()
-{
- updateGridViewData(); //update gridDataView and write status information
-
- //all three grids retrieve their data directly via gridDataView
- //the only thing left to do is notify the grids to updafte their sizes (nr of rows), since this has to be communicated by the grids via messages
- m_gridLeft ->updateGridSizes();
- m_gridMiddle->updateGridSizes();
- m_gridRight ->updateGridSizes();
-
- //enlarge label width to display row numbers correctly
- const int nrOfRows = m_gridLeft->GetNumberRows();
- if (nrOfRows >= 0)
- {
-#ifdef FFS_WIN
- const size_t digitWidth = 8;
-#elif defined FFS_LINUX
- const size_t digitWidth = 10;
-#endif
- const size_t nrOfDigits = globalFunctions::getDigitCount(static_cast<size_t>(nrOfRows));
- m_gridLeft ->SetRowLabelSize(static_cast<int>(nrOfDigits * digitWidth + 4));
- m_gridRight->SetRowLabelSize(static_cast<int>(nrOfDigits * digitWidth + 4));
- }
-
- //support for column auto adjustment
- if (globalSettings->gui.autoAdjustColumnsLeft)
- m_gridLeft->autoSizeColumns();
- if (globalSettings->gui.autoAdjustColumnsRight)
- m_gridRight->autoSizeColumns();
-
- //update sync preview statistics
- calculatePreview();
-
- m_gridLeft ->Refresh();
- m_gridMiddle->Refresh();
- m_gridRight ->Refresh();
-}
-
-
-void MainDialog::calculatePreview()
-{
- //update preview of bytes to be transferred:
- const SyncStatistics st(gridDataView->getDataTentative());
- const wxString toCreate = FreeFileSync::numberToStringSep(st.getCreate());
- const wxString toUpdate = FreeFileSync::numberToStringSep(st.getOverwrite());
- const wxString toDelete = FreeFileSync::numberToStringSep(st.getDelete());
- const wxString data = FreeFileSync::formatFilesizeToShortString(st.getDataToProcess());
-
- m_textCtrlCreate->SetValue(toCreate);
- m_textCtrlUpdate->SetValue(toUpdate);
- m_textCtrlDelete->SetValue(toDelete);
- m_textCtrlData->SetValue(data);
-}
-
-
-void MainDialog::OnSwitchView(wxCommandEvent& event)
-{
- //toggle view
- syncPreview->enablePreview(!syncPreview->previewIsEnabled());
-}
-
-
-void MainDialog::OnSyncSettings(wxCommandEvent& event)
-{
- SyncCfgDialog* syncDlg = new SyncCfgDialog(this,
- currentCfg.mainCfg.compareVar,
- currentCfg.mainCfg.syncConfiguration,
- currentCfg.mainCfg.handleDeletion,
- currentCfg.mainCfg.customDeletionDirectory,
- &currentCfg.ignoreErrors);
- if (syncDlg->ShowModal() == SyncCfgDialog::BUTTON_APPLY)
- {
- updateSyncConfig();
- }
-}
-
-
-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;
-
- if (FreeFileSync::showCompareCfgDialog(windowPos,
- currentCfg.mainCfg.compareVar,
- currentCfg.mainCfg.handleSymlinks) == DefaultReturnCode::BUTTON_OKAY)
- {
- //update compare variant name
- m_staticTextCmpVariant->SetLabel(wxString(wxT("(")) + getVariantName(currentCfg.mainCfg.compareVar) + wxT(")"));
- bSizer6->Layout(); //adapt layout for variant text
-
- //disable the sync button
- syncPreview->enableSynchronization(false);
-
- //clear grids
- gridDataView->clearAllRows();
- updateGuiGrid();
-
- m_buttonCompare->SetFocus();
- }
-}
-
-
-void MainDialog::OnStartSync(wxCommandEvent& event)
-{
- if (!syncPreview->synchronizationIsEnabled())
- {
- pushStatusInformation(_("Please run a Compare first before synchronizing!"));
- return;
- }
-
- //show sync preview screen
- if (globalSettings->optDialogs.showSummaryBeforeSync)
- {
- bool dontShowAgain = false;
-
- if (FreeFileSync::showSyncPreviewDlg(
- getCurrentConfiguration().mainCfg.getSyncVariantName(),
- FreeFileSync::SyncStatistics(gridDataView->getDataTentative()),
- dontShowAgain) != DefaultReturnCode::BUTTON_OKAY)
- return;
-
- globalSettings->optDialogs.showSummaryBeforeSync = !dontShowAgain;
- }
-
- wxBusyCursor dummy; //show hourglass cursor
-
- clearStatusBar();
- try
- {
- //PERF_START;
-
- //class handling status updates and error messages
- SyncStatusHandler statusHandler(this, currentCfg.ignoreErrors);
-
- //check if there are files/folders to be sync'ed at all
- if (!synchronizationNeeded(gridDataView->getDataTentative()))
- statusHandler.reportInfo(_("Nothing to synchronize according to configuration!")); //inform about this special case
-
- //start synchronization and mark all elements processed
- FreeFileSync::SyncProcess synchronization(
- globalSettings->optDialogs,
- currentCfg.mainCfg.hidden.verifyFileCopy,
- globalSettings->copyLockedFiles,
- statusHandler);
-
- const std::vector<FreeFileSync::FolderPairSyncCfg> syncProcessCfg = FreeFileSync::extractSyncCfg(getCurrentConfiguration().mainCfg);
- FolderComparison& dataToSync = gridDataView->getDataTentative();
-
- //make sure syncProcessCfg and dataToSync have same size and correspond!
- if (syncProcessCfg.size() != dataToSync.size())
- throw std::logic_error("Programming Error: Contract violation!"); //should never happen: sync button is deactivated if they are not in sync
-
- synchronization.startSynchronizationProcess(syncProcessCfg, dataToSync);
-
- //play (optional) sound notification after sync has completed (GUI and batch mode)
- const wxString soundFile = FreeFileSync::getResourceDir() + wxT("Sync_Complete.wav");
- if (fileExists(wxToZ(soundFile)))
- wxSound::Play(soundFile, wxSOUND_ASYNC);
- }
- catch (AbortThisProcess&)
- {
- //do NOT disable the sync button: user might want to try to sync the REMAINING rows
- } //enableSynchronization(false);
-
- //remove rows that empty: just a beautification, invalid rows shouldn't cause issues
- gridDataView->removeInvalidRows();
-
- updateGuiGrid();
-
- m_gridLeft-> ClearSelection();
- m_gridMiddle->ClearSelection();
- m_gridRight-> ClearSelection();
-}
-
-
-void MainDialog::OnLeftGridDoubleClick(wxGridEvent& event)
-{
- if (!globalSettings->gui.externelApplications.empty())
- openExternalApplication(event.GetRow(), true, globalSettings->gui.externelApplications[0].second);
- // event.Skip();
-}
-
-
-void MainDialog::OnRightGridDoubleClick(wxGridEvent& event)
-{
- if (!globalSettings->gui.externelApplications.empty())
- openExternalApplication(event.GetRow(), false, globalSettings->gui.externelApplications[0].second);
-// event.Skip();
-}
-
-
-void MainDialog::OnSortLeftGrid(wxGridEvent& event)
-{
- //determine direction for std::sort()
- const int currentSortColumn = event.GetCol();
- if (0 <= currentSortColumn && currentSortColumn < int(xmlAccess::COLUMN_TYPE_COUNT))
- {
- static bool sortDefault = true;
- if (lastSortColumn != currentSortColumn || lastSortGrid != m_gridLeft)
- sortDefault = true;
- else
- sortDefault = !sortDefault;
-
- lastSortColumn = currentSortColumn;
- lastSortGrid = m_gridLeft;
-
- GridView::SortType st = GridView::SORT_BY_REL_NAME;
-
- const xmlAccess::ColumnTypes columnType = m_gridLeft->getTypeAtPos(currentSortColumn);
- switch (columnType)
- {
- case xmlAccess::FULL_PATH:
- st = GridView::SORT_BY_REL_NAME;
- break;
- case xmlAccess::FILENAME:
- st = GridView::SORT_BY_FILENAME;
- break;
- case xmlAccess::REL_PATH:
- st = GridView::SORT_BY_REL_NAME;
- break;
- case xmlAccess::DIRECTORY:
- st = GridView::SORT_BY_DIRECTORY;
- break;
- case xmlAccess::SIZE:
- st = GridView::SORT_BY_FILESIZE;
- break;
- case xmlAccess::DATE:
- st = GridView::SORT_BY_DATE;
- break;
- case xmlAccess::EXTENSION:
- st = GridView::SORT_BY_EXTENSION;
- break;
- }
-
- const bool sortAscending = sortDefault ?
- GridView::getDefaultDirection(st) :
- !GridView::getDefaultDirection(st);
-
- gridDataView->sortView(st, true, sortAscending);
-
- updateGuiGrid(); //refresh gridDataView
-
- //set sort direction indicator on UI
- m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridLeft->setSortMarker(CustomGrid::SortMarker(currentSortColumn, sortAscending ? CustomGrid::ASCENDING : CustomGrid::DESCENDING));
- }
-}
-
-
-void MainDialog::OnSortMiddleGrid(wxGridEvent& event)
-{
- //determine direction for std::sort()
- static bool sortDefault = true;
- if (lastSortColumn != 0 || lastSortGrid != m_gridMiddle)
- sortDefault = true;
- else
- sortDefault = !sortDefault;
- lastSortColumn = 0;
- lastSortGrid = m_gridMiddle;
-
- //start sort
- if (syncPreview->previewIsEnabled())
- gridDataView->sortView(GridView::SORT_BY_SYNC_DIRECTION, true, sortDefault);
- else
- gridDataView->sortView(GridView::SORT_BY_CMP_RESULT, true, sortDefault);
-
- updateGuiGrid(); //refresh gridDataView
-
- //set sort direction indicator on UI
- m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridMiddle->setSortMarker(CustomGrid::SortMarker(0, sortDefault ? CustomGrid::ASCENDING : CustomGrid::DESCENDING));
-}
-
-
-void MainDialog::OnSortRightGrid(wxGridEvent& event)
-{
- //determine direction for std::sort()
- const int currentSortColumn = event.GetCol();
- if (0 <= currentSortColumn && currentSortColumn < int(xmlAccess::COLUMN_TYPE_COUNT))
- {
- static bool sortDefault = true;
- if (lastSortColumn != currentSortColumn || lastSortGrid != m_gridRight)
- sortDefault = true;
- else
- sortDefault = !sortDefault;
-
- lastSortColumn = currentSortColumn;
- lastSortGrid = m_gridRight;
-
- GridView::SortType st = GridView::SORT_BY_REL_NAME;
-
- const xmlAccess::ColumnTypes columnType = m_gridRight->getTypeAtPos(currentSortColumn);
- switch (columnType)
- {
- case xmlAccess::FULL_PATH:
- st = GridView::SORT_BY_REL_NAME;
- break;
- case xmlAccess::FILENAME:
- st = GridView::SORT_BY_FILENAME;
- break;
- case xmlAccess::REL_PATH:
- st = GridView::SORT_BY_REL_NAME;
- break;
- case xmlAccess::DIRECTORY:
- st = GridView::SORT_BY_DIRECTORY;
- break;
- case xmlAccess::SIZE:
- st = GridView::SORT_BY_FILESIZE;
- break;
- case xmlAccess::DATE:
- st = GridView::SORT_BY_DATE;
- break;
- case xmlAccess::EXTENSION:
- st = GridView::SORT_BY_EXTENSION;
- break;
- }
-
- const bool sortAscending = sortDefault ?
- GridView::getDefaultDirection(st) :
- !GridView::getDefaultDirection(st);
-
- gridDataView->sortView(st, false, sortAscending);
-
- updateGuiGrid(); //refresh gridDataView
-
- //set sort direction indicator on UI
- m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
- m_gridRight->setSortMarker(CustomGrid::SortMarker(currentSortColumn, sortAscending ? CustomGrid::ASCENDING : CustomGrid::DESCENDING));
- }
-}
-
-
-void MainDialog::OnSwapSides(wxCommandEvent& event)
-{
- //swap directory names: first pair
- firstFolderPair->setValues(firstFolderPair->getRightDir(), // swap directories
- firstFolderPair->getLeftDir(), //
- firstFolderPair->getAltSyncConfig(),
- firstFolderPair->getAltFilterConfig());
-
- //additional pairs
- for (std::vector<FolderPairPanel*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
- {
- FolderPairPanel* dirPair = *i;
- dirPair->setValues(dirPair->getRightDir(), // swap directories
- dirPair->getLeftDir(), //
- dirPair->getAltSyncConfig(),
- dirPair->getAltFilterConfig());
- }
-
- //swap view filter
- bool tmp = m_bpButtonLeftOnly->isActive();
- m_bpButtonLeftOnly->setActive(m_bpButtonRightOnly->isActive());
- m_bpButtonRightOnly->setActive(tmp);
-
- tmp = m_bpButtonLeftNewer->isActive();
- m_bpButtonLeftNewer->setActive(m_bpButtonRightNewer->isActive());
- m_bpButtonRightNewer->setActive(tmp);
-
-
- tmp = m_bpButtonSyncCreateLeft->isActive();
- m_bpButtonSyncCreateLeft->setActive(m_bpButtonSyncCreateRight->isActive());
- m_bpButtonSyncCreateRight->setActive(tmp);
-
- tmp = m_bpButtonSyncDeleteLeft->isActive();
- m_bpButtonSyncDeleteLeft->setActive(m_bpButtonSyncDeleteRight->isActive());
- m_bpButtonSyncDeleteRight->setActive(tmp);
-
- tmp = m_bpButtonSyncDirOverwLeft->isActive();
- m_bpButtonSyncDirOverwLeft->setActive(m_bpButtonSyncDirOverwRight->isActive());
- m_bpButtonSyncDirOverwRight->setActive(tmp);
-
- //swap grid information
- FreeFileSync::swapGrids(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
- updateGuiGrid();
-}
-
-
-void MainDialog::updateGridViewData()
-{
- size_t filesOnLeftView = 0;
- size_t foldersOnLeftView = 0;
- size_t filesOnRightView = 0;
- size_t foldersOnRightView = 0;
- wxULongLong filesizeLeftView;
- wxULongLong filesizeRightView;
-
- //disable all buttons per default
- m_bpButtonLeftOnly-> Show(false);
- m_bpButtonRightOnly-> Show(false);
- m_bpButtonLeftNewer-> Show(false);
- m_bpButtonRightNewer->Show(false);
- m_bpButtonDifferent-> Show(false);
- m_bpButtonEqual-> Show(false);
- m_bpButtonConflict-> Show(false);
-
- m_bpButtonSyncCreateLeft-> Show(false);
- m_bpButtonSyncCreateRight-> Show(false);
- m_bpButtonSyncDeleteLeft-> Show(false);
- m_bpButtonSyncDeleteRight-> Show(false);
- m_bpButtonSyncDirOverwLeft-> Show(false);
- m_bpButtonSyncDirOverwRight->Show(false);
- m_bpButtonSyncDirNone-> Show(false);
-
-
- if (syncPreview->previewIsEnabled())
- {
- const GridView::StatusSyncPreview result = gridDataView->updateSyncPreview(currentCfg.hideFilteredElements,
- m_bpButtonSyncCreateLeft-> isActive(),
- m_bpButtonSyncCreateRight-> isActive(),
- m_bpButtonSyncDeleteLeft-> isActive(),
- m_bpButtonSyncDeleteRight-> isActive(),
- m_bpButtonSyncDirOverwLeft-> isActive(),
- m_bpButtonSyncDirOverwRight->isActive(),
- m_bpButtonSyncDirNone-> isActive(),
- m_bpButtonEqual-> isActive(),
- m_bpButtonConflict-> isActive());
-
- filesOnLeftView = result.filesOnLeftView;
- foldersOnLeftView = result.foldersOnLeftView;
- filesOnRightView = result.filesOnRightView;
- foldersOnRightView = result.foldersOnRightView;
- filesizeLeftView = result.filesizeLeftView;
- filesizeRightView = result.filesizeRightView;
-
-
- //sync preview buttons
- m_bpButtonSyncCreateLeft-> Show(result.existsSyncCreateLeft);
- m_bpButtonSyncCreateRight-> Show(result.existsSyncCreateRight);
- m_bpButtonSyncDeleteLeft-> Show(result.existsSyncDeleteLeft);
- m_bpButtonSyncDeleteRight-> Show(result.existsSyncDeleteRight);
- m_bpButtonSyncDirOverwLeft-> Show(result.existsSyncDirLeft);
- m_bpButtonSyncDirOverwRight->Show(result.existsSyncDirRight);
- m_bpButtonSyncDirNone-> Show(result.existsSyncDirNone);
- m_bpButtonEqual-> Show(result.existsSyncEqual);
- m_bpButtonConflict-> Show(result.existsConflict);
-
- if ( m_bpButtonSyncCreateLeft-> IsShown() ||
- m_bpButtonSyncCreateRight-> IsShown() ||
- m_bpButtonSyncDeleteLeft-> IsShown() ||
- m_bpButtonSyncDeleteRight-> IsShown() ||
- m_bpButtonSyncDirOverwLeft-> IsShown() ||
- m_bpButtonSyncDirOverwRight->IsShown() ||
- m_bpButtonSyncDirNone-> IsShown() ||
- m_bpButtonEqual-> IsShown() ||
- m_bpButtonConflict-> IsShown())
- {
- m_panelViewFilter->Show();
- m_panelViewFilter->Layout();
- }
- else
- m_panelViewFilter->Hide();
-
- }
- else
- {
- const GridView::StatusCmpResult result = gridDataView->updateCmpResult(currentCfg.hideFilteredElements,
- m_bpButtonLeftOnly-> isActive(),
- m_bpButtonRightOnly-> isActive(),
- m_bpButtonLeftNewer-> isActive(),
- m_bpButtonRightNewer->isActive(),
- m_bpButtonDifferent-> isActive(),
- m_bpButtonEqual-> isActive(),
- m_bpButtonConflict-> isActive());
-
- filesOnLeftView = result.filesOnLeftView;
- foldersOnLeftView = result.foldersOnLeftView;
- filesOnRightView = result.filesOnRightView;
- foldersOnRightView = result.foldersOnRightView;
- filesizeLeftView = result.filesizeLeftView;
- filesizeRightView = result.filesizeRightView;
-
- //comparison result view buttons
- m_bpButtonLeftOnly-> Show(result.existsLeftOnly);
- m_bpButtonRightOnly-> Show(result.existsRightOnly);
- m_bpButtonLeftNewer-> Show(result.existsLeftNewer);
- m_bpButtonRightNewer->Show(result.existsRightNewer);
- m_bpButtonDifferent-> Show(result.existsDifferent);
- m_bpButtonEqual-> Show(result.existsEqual);
- m_bpButtonConflict-> Show(result.existsConflict);
-
- if ( m_bpButtonLeftOnly-> IsShown() ||
- m_bpButtonRightOnly-> IsShown() ||
- m_bpButtonLeftNewer-> IsShown() ||
- m_bpButtonRightNewer->IsShown() ||
- m_bpButtonDifferent-> IsShown() ||
- m_bpButtonEqual-> IsShown() ||
- m_bpButtonConflict-> IsShown())
- {
- m_panelViewFilter->Show();
- m_panelViewFilter->Layout();
- }
- else
- m_panelViewFilter->Hide();
- }
-
-
- bSizer3->Layout();
-
- //update status information
- clearStatusBar();
-
-
- wxString statusLeftNew;
- wxString statusMiddleNew;
- wxString statusRightNew;
-
-//#################################################
-//format numbers to text:
-
-//show status information on "root" level.
- if (foldersOnLeftView)
- {
- if (foldersOnLeftView == 1)
- statusLeftNew += _("1 directory");
- else
- {
- wxString folderCount = FreeFileSync::numberToStringSep(foldersOnLeftView);
-
- wxString outputString = _("%x directories");
- outputString.Replace(wxT("%x"), folderCount, false);
- statusLeftNew += outputString;
- }
-
- if (filesOnLeftView)
- statusLeftNew += wxT(" - ");
- }
-
- if (filesOnLeftView)
- {
- if (filesOnLeftView == 1)
- statusLeftNew += _("1 file");
- else
- {
- wxString fileCount = FreeFileSync::numberToStringSep(filesOnLeftView);
-
- wxString outputString = _("%x files");
- outputString.Replace(wxT("%x"), fileCount, false);
- statusLeftNew += outputString;
- }
- statusLeftNew += wxT(" - ");
- statusLeftNew += FreeFileSync::formatFilesizeToShortString(filesizeLeftView);
- }
-
- const wxString objectsView = FreeFileSync::numberToStringSep(gridDataView->rowsOnView());
- if (gridDataView->rowsTotal() == 1)
- {
- wxString outputString = _("%x of 1 row in view");
- outputString.Replace(wxT("%x"), objectsView, false);
- statusMiddleNew = outputString;
- }
- else
- {
- const wxString objectsTotal = FreeFileSync::numberToStringSep(gridDataView->rowsTotal());
-
- wxString outputString = _("%x of %y rows in view");
- outputString.Replace(wxT("%x"), objectsView, false);
- outputString.Replace(wxT("%y"), objectsTotal, false);
- statusMiddleNew = outputString;
- }
-
- if (foldersOnRightView)
- {
- if (foldersOnRightView == 1)
- statusRightNew += _("1 directory");
- else
- {
- wxString folderCount = FreeFileSync::numberToStringSep(foldersOnRightView);
-
- wxString outputString = _("%x directories");
- outputString.Replace(wxT("%x"), folderCount, false);
- statusRightNew += outputString;
- }
-
- if (filesOnRightView)
- statusRightNew += wxT(" - ");
- }
-
- if (filesOnRightView)
- {
- if (filesOnRightView == 1)
- statusRightNew += _("1 file");
- else
- {
- wxString fileCount = FreeFileSync::numberToStringSep(filesOnRightView);
-
- wxString outputString = _("%x files");
- outputString.Replace(wxT("%x"), fileCount, false);
- statusRightNew += outputString;
- }
-
- statusRightNew += wxT(" - ");
- statusRightNew += FreeFileSync::formatFilesizeToShortString(filesizeRightView);
- }
-
-
- //avoid screen flicker
- if (m_staticTextStatusLeft->GetLabel() != statusLeftNew)
- m_staticTextStatusLeft->SetLabel(statusLeftNew);
- if (m_staticTextStatusMiddle->GetLabel() != statusMiddleNew)
- m_staticTextStatusMiddle->SetLabel(statusMiddleNew);
- if (m_staticTextStatusRight->GetLabel() != statusRightNew)
- m_staticTextStatusRight->SetLabel(statusRightNew);
-
- m_panelStatusBar->Layout();
-}
-
-
-void MainDialog::OnAddFolderPair(wxCommandEvent& event)
-{
- wxWindowUpdateLocker dummy(this); //avoid display distortion
-
- std::vector<FolderPairEnh> newPairs;
- newPairs.push_back(getCurrentConfiguration().mainCfg.firstPair);
-
- addFolderPair(newPairs, true); //add pair in front of additonal pairs
-
- //clear first pair
- const FolderPairEnh cfgEmpty;
- firstFolderPair->setValues(cfgEmpty.leftDirectory,
- cfgEmpty.rightDirectory,
- cfgEmpty.altSyncConfig,
- cfgEmpty.localFilter);
-
- //disable the sync button
- syncPreview->enableSynchronization(false);
-
- //clear grids
- gridDataView->clearAllRows();
- updateSyncConfig(); //mainly to update sync dir description text
-}
-
-
-void MainDialog::updateFilterConfig()
-{
- applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
- refreshGridAfterFilterChange(400);
-}
-
-
-void MainDialog::updateSyncConfig()
-{
- //update sync variant name
- m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getCurrentConfiguration().mainCfg.getSyncVariantName() + wxT(")"));
- bSizer6->Layout(); //adapt layout for variant text
-
-
- class RedetermineCallback : public DeterminationProblem
- {
- public:
- RedetermineCallback(bool& warningSyncDatabase, wxWindow* parent) :
- warningSyncDatabase_(warningSyncDatabase),
- parent_(parent) {}
-
- virtual void reportWarning(const wxString& text)
- {
- if (warningSyncDatabase_)
- {
- bool dontWarnAgain = false;
- WarningDlg* warningDlg = new WarningDlg(parent_, //show popup and ask user how to handle warning
- WarningDlg::BUTTON_IGNORE,
- text,
- dontWarnAgain);
- if (warningDlg->ShowModal() == WarningDlg::BUTTON_IGNORE)
- warningSyncDatabase_ = !dontWarnAgain;
- }
- }
- private:
- bool& warningSyncDatabase_;
- wxWindow* parent_;
- } redetCallback(globalSettings->optDialogs.warningSyncDatabase, this);
-
- FreeFileSync::redetermineSyncDirection(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative(), &redetCallback);
- updateGuiGrid();
-}
-
-
-void MainDialog::OnRemoveTopFolderPair(wxCommandEvent& event)
-{
- if (additionalFolderPairs.size() > 0)
- {
- //get settings from second folder pair
- const FolderPairEnh cfgSecond = getEnahncedPair(additionalFolderPairs[0]);
-
- //reset first pair
- firstFolderPair->setValues(cfgSecond.leftDirectory,
- cfgSecond.rightDirectory,
- cfgSecond.altSyncConfig,
- cfgSecond.localFilter);
-
- removeAddFolderPair(0); //remove second folder pair (first of additional folder pairs)
-
-//------------------------------------------------------------------
- //disable the sync button
- syncPreview->enableSynchronization(false);
-
- //clear grids
- gridDataView->clearAllRows();
- updateSyncConfig(); //mainly to update sync dir description text
- }
-}
-
-
-void MainDialog::OnRemoveFolderPair(wxCommandEvent& event)
-{
- const wxObject* const eventObj = event.GetEventObject(); //find folder pair originating the event
- for (std::vector<FolderPairPanel*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
- if (eventObj == (*i)->m_bpButtonRemovePair)
- {
- removeAddFolderPair(i - additionalFolderPairs.begin());
-
-//------------------------------------------------------------------
- //disable the sync button
- syncPreview->enableSynchronization(false);
-
- //clear grids
- gridDataView->clearAllRows();
- updateSyncConfig(); //mainly to update sync dir description text
- return;
- }
-}
-
-
-const size_t MAX_ADD_FOLDER_PAIRS = 5;
-
-
-void MainDialog::updateGuiForFolderPair()
-{
- //adapt delete top folder pair button
- if (additionalFolderPairs.size() == 0)
- m_bpButtonRemovePair->Hide();
- else
- m_bpButtonRemovePair->Show();
-
- m_panelTopRight->Layout();
-
- //adapt local filter and sync cfg for first folder pair
- if ( additionalFolderPairs.size() == 0 &&
- firstFolderPair->getAltSyncConfig().get() == NULL &&
- NameFilter(firstFolderPair->getAltFilterConfig().includeFilter,
- firstFolderPair->getAltFilterConfig().excludeFilter).isNull())
- {
- m_bpButtonLocalFilter->Hide();
- m_bpButtonAltSyncCfg->Hide();
-
- m_bpButtonSwapSides->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("swap")));
- }
- else
- {
- m_bpButtonLocalFilter->Show();
- m_bpButtonAltSyncCfg->Show();
-
- m_bpButtonSwapSides->SetBitmapLabel(GlobalResources::getInstance().getImageByName(wxT("swapSlim")));
- }
-
- m_panelTopMiddle->Layout();
-}
-
-
-void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool addFront)
-{
- wxWindowUpdateLocker dummy(this); //avoid display distortion
-
- if (!newPairs.empty())
- {
- int pairHeight = 0;
- for (std::vector<FolderPairEnh>::const_iterator i = newPairs.begin(); i != newPairs.end(); ++i)
- {
- //add new folder pair
- FolderPairPanel* newPair = new FolderPairPanel(m_scrolledWindowFolderPairs, *this);
-
- //correct width of middle block
- newPair->m_panel21->SetMinSize(wxSize(m_gridMiddle->GetSize().GetWidth(), -1));
-
- //set width of left folder panel
- const int width = m_panelTopLeft->GetSize().GetWidth();
- newPair->m_panelLeft->SetMinSize(wxSize(width, -1));
-
-
- if (addFront)
- {
- bSizerAddFolderPairs->Insert(0, newPair, 0, wxEXPAND, 5);
- additionalFolderPairs.insert(additionalFolderPairs.begin(), newPair);
- }
- else
- {
- bSizerAddFolderPairs->Add(newPair, 0, wxEXPAND, 5);
- additionalFolderPairs.push_back(newPair);
- }
-
- //get size of scrolled window
- pairHeight = newPair->GetSize().GetHeight();
-
- //register events
- newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), NULL, this);
-
- //set alternate configuration
- newPair->setValues(i->leftDirectory,
- i->rightDirectory,
- i->altSyncConfig,
- i->localFilter);
- }
-
- //set size of scrolled window
- const size_t visiblePairs = std::min(additionalFolderPairs.size(), MAX_ADD_FOLDER_PAIRS); //up to MAX_ADD_FOLDER_PAIRS additional pairs shall be shown
- m_scrolledWindowFolderPairs->SetMinSize(wxSize( -1, pairHeight * static_cast<int>(visiblePairs)));
-
- //update controls
- m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size
- m_scrolledWindowFolderPairs->Layout(); //adjust stuff inside scrolled window
- bSizer1->Layout();
- }
-
- updateGuiForFolderPair();
-}
-
-
-void MainDialog::removeAddFolderPair(size_t pos)
-{
- wxWindowUpdateLocker dummy(this); //avoid display distortion
-
- if (pos < additionalFolderPairs.size())
- {
- //remove folder pairs from window
- FolderPairPanel* pairToDelete = additionalFolderPairs[pos];
- const int pairHeight = pairToDelete->GetSize().GetHeight();
-
- bSizerAddFolderPairs->Detach(pairToDelete); //Remove() does not work on Window*, so do it manually
- pairToDelete->Destroy(); //
- additionalFolderPairs.erase(additionalFolderPairs.begin() + pos); //remove element from vector
-
- //set size of scrolled window
- const size_t additionalRows = additionalFolderPairs.size();
- if (additionalRows <= MAX_ADD_FOLDER_PAIRS) //up to MAX_ADD_FOLDER_PAIRS additional pairs shall be shown
- m_scrolledWindowFolderPairs->SetMinSize(wxSize(-1, pairHeight * static_cast<int>(additionalRows)));
-
- //update controls
- m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size
- m_scrolledWindowFolderPairs->Layout(); //adjust stuff inside scrolled window
- bSizer1->Layout();
- }
-
- updateGuiForFolderPair();
-}
-
-
-void MainDialog::clearAddFolderPairs()
-{
- wxWindowUpdateLocker dummy(this); //avoid display distortion
-
- additionalFolderPairs.clear();
- bSizerAddFolderPairs->Clear(true);
-
- m_scrolledWindowFolderPairs->SetMinSize(wxSize(-1, 0));
- bSizer1->Layout();
-}
-//########################################################################################################
-
-
-//menu events
-void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event)
-{
- FreeFileSync::showGlobalSettingsDlg(*globalSettings);
-
- //event.Skip();
-}
-
-
-void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
-{
- //get a filename
- const wxString defaultFileName = wxT("FileList.csv"); //proposal
- wxFileDialog* filePicker = new wxFileDialog(this, wxEmptyString, wxEmptyString, defaultFileName, wxString(_("Comma separated list")) + wxT(" (*.csv)|*.csv"), wxFD_SAVE);
-
- if (filePicker->ShowModal() == wxID_OK)
- {
- const wxString newFileName = filePicker->GetPath();
- if (FreeFileSync::fileExists(wxToZ(newFileName)))
- {
- QuestionDlg* messageDlg = new QuestionDlg(this,
- QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_CANCEL,
- wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""));
-
- if (messageDlg->ShowModal() != QuestionDlg::BUTTON_YES)
- {
- OnMenuExportFileList(event); //retry
- return;
- }
- }
-
- wxString exportString;
- //write legend
- exportString += wxString(_("Legend")) + wxT('\n');
- if (syncPreview->previewIsEnabled())
- {
- exportString += wxString(wxT("\"")) + getDescription(SO_CREATE_NEW_LEFT) + wxT("\";") + getSymbol(SO_CREATE_NEW_LEFT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_CREATE_NEW_RIGHT) + wxT("\";") + getSymbol(SO_CREATE_NEW_RIGHT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_DELETE_LEFT) + wxT("\";") + getSymbol(SO_DELETE_LEFT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_DELETE_RIGHT) + wxT("\";") + getSymbol(SO_DELETE_RIGHT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_OVERWRITE_LEFT) + wxT("\";") + getSymbol(SO_OVERWRITE_LEFT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_OVERWRITE_RIGHT) + wxT("\";") + getSymbol(SO_OVERWRITE_RIGHT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_DO_NOTHING) + wxT("\";") + getSymbol(SO_DO_NOTHING) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_EQUAL) + wxT("\";") + getSymbol(SO_EQUAL) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(SO_UNRESOLVED_CONFLICT) + wxT("\";") + getSymbol(SO_UNRESOLVED_CONFLICT) + wxT('\n');
- }
- else
- {
- exportString += wxString(wxT("\"")) + getDescription(FILE_LEFT_SIDE_ONLY) + wxT("\";") + getSymbol(FILE_LEFT_SIDE_ONLY) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(FILE_RIGHT_SIDE_ONLY) + wxT("\";") + getSymbol(FILE_RIGHT_SIDE_ONLY) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(FILE_LEFT_NEWER) + wxT("\";") + getSymbol(FILE_LEFT_NEWER) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(FILE_RIGHT_NEWER) + wxT("\";") + getSymbol(FILE_RIGHT_NEWER) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(FILE_DIFFERENT) + wxT("\";") + getSymbol(FILE_DIFFERENT) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(FILE_EQUAL) + wxT("\";") + getSymbol(FILE_EQUAL) + wxT('\n');
- exportString += wxString(wxT("\"")) + getDescription(FILE_CONFLICT) + wxT("\";") + getSymbol(FILE_CONFLICT) + wxT('\n');
- }
- exportString += '\n';
-
- //write header
- for (int k = 0; k < m_gridLeft->GetNumberCols(); ++k)
- {
- exportString += m_gridLeft->GetColLabelValue(k);
- exportString += ';';
- }
-
- for (int k = 0; k < m_gridMiddle->GetNumberCols(); ++k)
- {
- exportString += m_gridMiddle->GetColLabelValue(k);
- exportString += ';';
- }
-
- for (int k = 0; k < m_gridRight->GetNumberCols(); ++k)
- {
- exportString += m_gridRight->GetColLabelValue(k);
- if (k != m_gridRight->GetNumberCols() - 1)
- exportString += ';';
- }
- exportString += '\n';
-
- //begin work
- for (int i = 0; i < m_gridLeft->GetNumberRows(); ++i)
- {
- for (int k = 0; k < m_gridLeft->GetNumberCols(); ++k)
- {
- exportString += m_gridLeft->GetCellValue(i, k);
- exportString += ';';
- }
-
- for (int k = 0; k < m_gridMiddle->GetNumberCols(); ++k)
- {
- exportString += m_gridMiddle->GetCellValue(i, k);
- exportString += ';';
- }
-
- for (int k = 0; k < m_gridRight->GetNumberCols(); ++k)
- {
- exportString += m_gridRight->GetCellValue(i, k);
- if (k != m_gridRight->GetNumberCols() - 1)
- exportString+= ';';
- }
- exportString+= '\n';
- }
-
- //write export file
- wxFFile output(newFileName.c_str(), wxT("w")); //don't write in binary mode
- if (output.IsOpened())
- {
- output.Write(exportString);
- pushStatusInformation(_("File list exported!"));
- }
- else
- {
- wxMessageBox(wxString(_("Error writing file:")) + wxT(" \"") + newFileName + wxT("\""), _("Error"), wxOK | wxICON_ERROR);
- }
- }
-}
-
-
-void MainDialog::OnMenuBatchJob(wxCommandEvent& event)
-{
- //fill batch config structure
- xmlAccess::XmlGuiConfig currCfg = getCurrentConfiguration(); //get UP TO DATE config, with updated values for main and additional folders!
-
- xmlAccess::XmlBatchConfig batchCfg;
- batchCfg.mainCfg = currCfg.mainCfg;
-
- if (currentCfg.ignoreErrors)
- batchCfg.handleError = xmlAccess::ON_ERROR_IGNORE;
- else
- batchCfg.handleError = xmlAccess::ON_ERROR_POPUP;
-
- BatchDialog* batchDlg = new BatchDialog(this, batchCfg);
- if (batchDlg->ShowModal() == BatchDialog::BATCH_FILE_SAVED)
- pushStatusInformation(_("Batch file created successfully!"));
-}
-
-
-void MainDialog::OnMenuCheckVersion(wxCommandEvent& event)
-{
- FreeFileSync::checkForUpdateNow();
-}
-
-
-void MainDialog::OnRegularUpdateCheck(wxIdleEvent& event)
-{
- //execute just once per startup!
- Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), NULL, this);
-
- FreeFileSync::checkForUpdatePeriodically(globalSettings->gui.lastUpdateCheck);
-}
-
-
-void MainDialog::OnLayoutWindowAsync(wxIdleEvent& event)
-{
- //execute just once per startup!
- Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnLayoutWindowAsync), NULL, this);
-
- wxWindowUpdateLocker dummy(this); //avoid display distortion
-
- //adjust folder pair distortion on startup
- m_scrolledWindowFolderPairs->Fit();
-
- Layout(); //strangely this layout call works if called in next idle event only
- Refresh();
-}
-
-
-void MainDialog::OnMenuAbout(wxCommandEvent& event)
-{
- FreeFileSync::showAboutDialog();
-}
-
-
-void MainDialog::OnShowHelp(wxCommandEvent& event)
-{
- FreeFileSync::displayHelpEntry();
-}
-
-
-void MainDialog::OnMenuQuit(wxCommandEvent& event)
-{
- if (!saveOldConfig()) //notify user about changed settings
- return;
-
- Destroy();
-}
-
-//#########################################################################################################
-
-//language selection
-void MainDialog::switchProgramLanguage(const int langID)
-{
- //create new dialog with respect to new language
- CustomLocale::getInstance().setLanguage(langID); //language is a global attribute
-
- const xmlAccess::XmlGuiConfig currentGuiCfg = getCurrentConfiguration();
-
- cleanUp(false); //destructor's code: includes updating global settings
-
- //create new main window and delete old one
- MainDialog* frame = new MainDialog(currentGuiCfg, *globalSettings, false);
- frame->Show();
-
- Destroy();
-}
-
-
-void MainDialog::OnMenuLanguageSwitch(wxCommandEvent& event)
-{
- std::map<MenuItemID, LanguageID>::const_iterator it = languageMenuItemMap.find(event.GetId());
-
- if (it != languageMenuItemMap.end())
- switchProgramLanguage(it->second);
-}
-
-//#########################################################################################################
-
-MainDialog::SyncPreview::SyncPreview(MainDialog* mainDlg) :
- mainDlg_(mainDlg),
- syncPreviewEnabled(false),
- synchronizationEnabled(false) {}
-
-
-bool MainDialog::SyncPreview::previewIsEnabled() const
-{
- return syncPreviewEnabled;
-}
-
-
-void MainDialog::SyncPreview::enablePreview(bool value)
-{
- if (value)
- {
- syncPreviewEnabled = true;
-
- //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();
- }
-
- mainDlg_->updateGuiGrid();
-}
-
-
-void MainDialog::SyncPreview::enableSynchronization(bool value)
-{
- if (value)
- {
- synchronizationEnabled = true;
- mainDlg_->m_buttonStartSync->SetForegroundColour(*wxBLACK);
- mainDlg_->m_buttonStartSync->setBitmapFront(GlobalResources::getInstance().getImageByName(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::getInstance().getImageByName(wxT("syncDisabled")));
- }
-}
-
-
-bool MainDialog::SyncPreview::synchronizationIsEnabled() const
-{
- return synchronizationEnabled;
-}
bgstack15