summaryrefslogtreecommitdiff
path: root/ui/MainDialog.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:00:50 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:00:50 +0200
commit4ecfd41e36533d858c98d051ef70cab80e69e972 (patch)
treeca07d8745967d2c6a7123a5d32269cfbfaa7bd6c /ui/MainDialog.cpp
parent2.2 (diff)
downloadFreeFileSync-4ecfd41e36533d858c98d051ef70cab80e69e972.tar.gz
FreeFileSync-4ecfd41e36533d858c98d051ef70cab80e69e972.tar.bz2
FreeFileSync-4ecfd41e36533d858c98d051ef70cab80e69e972.zip
2.3
Diffstat (limited to 'ui/MainDialog.cpp')
-rw-r--r--ui/MainDialog.cpp1997
1 files changed, 1032 insertions, 965 deletions
diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp
index 5f078cda..d053bed5 100644
--- a/ui/MainDialog.cpp
+++ b/ui/MainDialog.cpp
@@ -1,6 +1,7 @@
#include "mainDialog.h"
#include <wx/filename.h>
-#include "../shared/globalFunctions.h"
+#include <stdexcept>
+#include "../shared/systemConstants.h"
#include <wx/clipbrd.h>
#include <wx/dataobj.h>
#include <wx/ffile.h>
@@ -25,23 +26,61 @@
#include "../shared/fileHandling.h"
#include "../shared/xmlBase.h"
#include "../shared/standardPaths.h"
+#include "../shared/toggleButton.h"
+#include "folderPair.h"
+#include "../shared/globalFunctions.h"
using namespace FreeFileSync;
using FreeFileSync::CustomLocale;
-class FolderPairPanel : public FolderPairGenerated
+typedef FreeFileSync::FolderPairPanelBasic<FolderPairGenerated> FolderPairParent;
+
+class FolderPairPanel : public FolderPairParent
{
public:
- FolderPairPanel(wxWindow* parent) :
- FolderPairGenerated(parent),
- dragDropOnLeft(new DragDropOnDlg(m_panelLeft, m_dirPickerLeft, m_directoryLeft)),
- dragDropOnRight(new DragDropOnDlg(m_panelRight, m_dirPickerRight, m_directoryRight)) {}
+ FolderPairPanel(wxWindow* parent, MainDialog* mainDialog) :
+ FolderPairParent(parent),
+ mainDlg(mainDialog)
+ {}
private:
- //support for drag and drop
- std::auto_ptr<DragDropOnDlg> dragDropOnLeft;
- std::auto_ptr<DragDropOnDlg> dragDropOnRight;
+ virtual void OnAltFilterCfgRemoveConfirm(wxCommandEvent& event)
+ {
+ FolderPairParent::OnAltFilterCfgRemoveConfirm(event);
+ mainDlg->updateFilterConfig(false); //update filter, leave activation status as it is
+ }
+
+ virtual void OnAltSyncCfgRemoveConfirm(wxCommandEvent& event)
+ {
+ FolderPairParent::OnAltSyncCfgRemoveConfirm(event);
+ mainDlg->updateSyncConfig();
+ }
+
+ virtual wxWindow* getParentWindow()
+ {
+ return mainDlg;
+ }
+
+ virtual MainConfiguration getMainConfig() const
+ {
+ return mainDlg->getCurrentConfiguration().mainCfg;
+ }
+
+ virtual void OnAltSyncCfgChange()
+ {
+ mainDlg->updateSyncConfig();
+ }
+
+ virtual void OnAltFilterCfgChange(bool defaultValueSet)
+ {
+ if (defaultValueSet) //default
+ mainDlg->updateFilterConfig(false); //re-apply filter (without changing active-status)
+ else
+ mainDlg->updateFilterConfig(true); //activate(and apply) filter
+ }
+
+ MainDialog* mainDlg;
};
@@ -80,7 +119,7 @@ public:
mainDlg_->syncPreview.enableSynchronization(false);
//clear grids
- mainDlg_->currentGridData.clear();
+ mainDlg_->gridDataView->clearAllRows();
mainDlg_->updateGuiGrid();
return true;
@@ -130,12 +169,12 @@ private:
MenuItemMap menuItems;
};
-//##################################################################################################################################
-
+//##################################################################################################################################
MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::XmlGlobalSettings& settings) :
MainDialogGenerated(frame),
globalSettings(settings),
+ gridDataView(new FreeFileSync::GridView()),
contextMenu(new wxMenu), //initialize right-click context menu; will be dynamically re-created on each R-mouse-click
cleanedUp(false),
lastSortColumn(-1),
@@ -147,9 +186,7 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::X
{
wxWindowUpdateLocker dummy(this); //avoid display distortion
- gridDataView.reset(new FreeFileSync::GridView(currentGridData));
-
- m_bpButtonRemoveTopPair->Hide();
+ initViewFilterButtons();
//initialize and load configuration
readGlobalSettings();
@@ -168,7 +205,6 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::X
m_bpButtonSave->SetBitmapLabel(*GlobalResources::getInstance().bitmapSave);
m_bpButtonLoad->SetBitmapLabel(*GlobalResources::getInstance().bitmapLoad);
m_bpButtonAddPair->SetBitmapLabel(*GlobalResources::getInstance().bitmapAddFolderPair);
- m_bpButtonRemoveTopPair->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
m_bitmap15->SetBitmap(*GlobalResources::getInstance().bitmapStatusEdge);
m_bitmapCreate->SetBitmap(*GlobalResources::getInstance().bitmapCreate);
@@ -180,8 +216,11 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::X
//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().bitmapCompareSmall);
- updateMenuFile.addForUpdate(m_menuItem11, *GlobalResources::getInstance().bitmapSyncSmall);
+ updateMenuFile.addForUpdate(m_menuItem10, *GlobalResources::getInstance().bitmapCompareSmall);
+ updateMenuFile.addForUpdate(m_menuItem11, *GlobalResources::getInstance().bitmapSyncSmall);
+ updateMenuFile.addForUpdate(m_menuItemNew, *GlobalResources::getInstance().bitmapNewSmall);
+ updateMenuFile.addForUpdate(m_menuItemSave, *GlobalResources::getInstance().bitmapSaveSmall);
+ updateMenuFile.addForUpdate(m_menuItemLoad, *GlobalResources::getInstance().bitmapLoadSmall);
MenuItemUpdater updateMenuAdv(m_menuAdvanced);
updateMenuAdv.addForUpdate(m_menuItemGlobSett, *GlobalResources::getInstance().bitmapSettingsSmall);
@@ -195,7 +234,6 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::X
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
@@ -203,7 +241,6 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::X
//connect event
Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnMenuLanguageSwitch));
-
m_menuLanguages->Append(newItem);
}
@@ -372,14 +409,18 @@ void MainDialog::writeGlobalSettings()
}
-void MainDialog::setSyncDirManually(const std::set<int>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir)
+void MainDialog::setSyncDirManually(const std::set<unsigned int>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir)
{
if (rowsToSetOnUiTable.size() > 0)
{
- for (std::set<int>::const_iterator i = rowsToSetOnUiTable.begin(); i != rowsToSetOnUiTable.end(); ++i)
+ for (std::set<unsigned int>::const_iterator i = rowsToSetOnUiTable.begin(); i != rowsToSetOnUiTable.end(); ++i)
{
- (*gridDataView)[*i].syncDir = dir;
- (*gridDataView)[*i].selectedForSynchronization = true;
+ FileSystemObject* fsObj = gridDataView->getObject(*i);
+ if (fsObj)
+ {
+ setSyncDirection(dir, *fsObj); //set new direction (recursively)
+ FilterProcess::setActiveStatus(true, *fsObj); //works recursively for directories
+ }
}
updateGuiGrid();
@@ -387,41 +428,26 @@ void MainDialog::setSyncDirManually(const std::set<int>& rowsToSetOnUiTable, con
}
-void MainDialog::filterRangeManually(const std::set<int>& rowsToFilterOnUiTable, const int leadingRow)
+void MainDialog::filterRangeManually(const std::set<unsigned int>& rowsToFilterOnUiTable, const int leadingRow)
{
if (rowsToFilterOnUiTable.size() > 0)
{
bool newSelection = false; //default: deselect range
//leadingRow determines de-/selection of all other rows
- if (0 <= leadingRow && leadingRow < int(gridDataView->elementsOnView()))
- newSelection = !(*gridDataView)[leadingRow].selectedForSynchronization;
+ const FileSystemObject* fsObj = gridDataView->getObject(leadingRow);
+ if (fsObj)
+ newSelection = !fsObj->selectedForSynchronization;
//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 (e.g. if a folder is marked, then its subelements should be marked as well)
- FolderCompRef compRef;
- gridDataView->viewRefToFolderRef(rowsToFilterOnUiTable, compRef);
-
- assert(compRef.size() == currentGridData.size()); //GridView::viewRefToFolderRef() should ensure this!
+ //get all lines that need to be filtered
+ std::vector<FileSystemObject*> compRef;
+ gridDataView->getAllFileRef(rowsToFilterOnUiTable, compRef); //everything in compRef is bound
- for (FolderComparison::iterator i = currentGridData.begin(); i != currentGridData.end(); ++i)
- {
- FileComparison& fileCmp = i->fileCmp;
- const std::set<int>& markedRows = compRef[i - currentGridData.begin()];
-
- std::set<int> markedRowsTotal; //retrieve additional rows that need to be filtered, too
- for (std::set<int>::const_iterator j = markedRows.begin(); j != markedRows.end(); ++j)
- {
- markedRowsTotal.insert(*j);
- FreeFileSync::addSubElements(fileCmp, fileCmp[*j], markedRowsTotal);
- }
-
- //toggle selection of filtered rows
- for (std::set<int>::iterator k = markedRowsTotal.begin(); k != markedRowsTotal.end(); ++k)
- fileCmp[*k].selectedForSynchronization = newSelection;
- }
+ for (std::vector<FileSystemObject*>::iterator i = compRef.begin(); i != compRef.end(); ++i)
+ FilterProcess::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
}
@@ -450,12 +476,12 @@ void MainDialog::OnIdleEvent(wxEvent& event)
void MainDialog::copySelectionToClipboard(const CustomGrid* selectedGrid)
{
- const std::set<int> selectedRows = getSelectedRows(selectedGrid);
+ const std::set<unsigned int> selectedRows = getSelectedRows(selectedGrid);
if (selectedRows.size() > 0)
{
wxString clipboardString;
- for (std::set<int>::const_iterator i = selectedRows.begin(); i != selectedRows.end(); ++i)
+ for (std::set<unsigned int>::const_iterator i = selectedRows.begin(); i != selectedRows.end(); ++i)
{
for (int k = 0; k < const_cast<CustomGrid*>(selectedGrid)->GetNumberCols(); ++k)
{
@@ -479,38 +505,23 @@ void MainDialog::copySelectionToClipboard(const CustomGrid* selectedGrid)
}
-void removeInvalidRows(std::set<int>& rows, const int currentUiTableSize)
+std::set<unsigned int> MainDialog::getSelectedRows(const CustomGrid* grid) const
{
- std::set<int> validRows; //temporal table IS needed here
- for (std::set<int>::iterator i = rows.begin(); i != rows.end(); ++i)
- if (0 <= *i)
- {
- if (*i >= currentUiTableSize) //set is sorted, so no need to continue here
- break;
- validRows.insert(*i);
- }
- rows.swap(validRows);
-}
+ std::set<unsigned int> output = grid->getAllSelectedRows();
-
-std::set<int> MainDialog::getSelectedRows(const CustomGrid* grid) const
-{
- std::set<int> output = grid->getAllSelectedRows();
-
- removeInvalidRows(output, gridDataView->elementsOnView());
+ //remove invalid rows
+ output.erase(output.lower_bound(gridDataView->rowsOnView()), output.end());
return output;
}
-std::set<int> MainDialog::getSelectedRows() const
+std::set<unsigned int> MainDialog::getSelectedRows() const
{
//merge selections from left and right grid
- std::set<int> selection = getSelectedRows(m_gridLeft);
- std::set<int> additional = getSelectedRows(m_gridRight);
- for (std::set<int>::const_iterator i = additional.begin(); i != additional.end(); ++i)
- selection.insert(*i);
-
+ std::set<unsigned int> selection = getSelectedRows(m_gridLeft);
+ std::set<unsigned int> additional = getSelectedRows(m_gridRight);
+ selection.insert(additional.begin(), additional.end());
return selection;
}
@@ -607,22 +618,22 @@ private:
void MainDialog::deleteSelectedFiles()
{
//get set of selected rows on view
- const std::set<int> viewSelectionLeft = getSelectedRows(m_gridLeft);
- const std::set<int> viewSelectionRight = getSelectedRows(m_gridRight);
+ const std::set<unsigned int> viewSelectionLeft = getSelectedRows(m_gridLeft);
+ const std::set<unsigned int> viewSelectionRight = getSelectedRows(m_gridRight);
if (viewSelectionLeft.size() + viewSelectionRight.size())
{
- //map lines from GUI view to grid line references for "currentGridData"
- FolderCompRef compRefLeft;
- gridDataView->viewRefToFolderRef(viewSelectionLeft, compRefLeft);
+ //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);
- FolderCompRef compRefRight;
- gridDataView->viewRefToFolderRef(viewSelectionRight, compRefRight);
int totalDeleteCount = 0;
DeleteDialog* confirmDeletion = new DeleteDialog(this, //no destruction needed; attached to main window
- currentGridData,
compRefLeft,
compRefRight,
globalSettings.gui.deleteOnBothSides,
@@ -636,98 +647,95 @@ void MainDialog::deleteSelectedFiles()
return;
}
- //Attention! Modifying the grid is highly critical! There MUST NOT BE any accesses to gridDataView until this reference table is updated
- //by updateGuiGrid()!! This is easily missed, e.g. when ClearSelection() or ShowModal() or possibly any other wxWidgets function is called
- //that might want to redraw the UI (which implicitly uses the information in gridDataView (see CustomGrid)
- gridDataView->clearView(); //no superfluous precaution: e.g. consider grid update when error message is shown in multiple folder pair scenario!
-
try
{ //handle errors when deleting files/folders
ManualDeletionHandler statusHandler(this, totalDeleteCount);
- assert(compRefLeft.size() == currentGridData.size()); //GridView::viewRefToFolderRef() should ensure this!
- assert(compRefRight.size() == currentGridData.size());
-
- for (FolderComparison::iterator i = currentGridData.begin(); i != currentGridData.end(); ++i)
- {
- const int folderPairNr = i - currentGridData.begin();
-
- const std::set<int>& rowsToDeleteOnLeft = compRefLeft[folderPairNr];
- const std::set<int>& rowsToDeleteOnRight = compRefRight[folderPairNr];
-
- FreeFileSync::deleteFromGridAndHD(i->fileCmp,
- rowsToDeleteOnLeft,
- rowsToDeleteOnRight,
- globalSettings.gui.deleteOnBothSides,
- globalSettings.gui.useRecyclerForManualDeletion,
- currentCfg.mainCfg.syncConfiguration,
- &statusHandler);
- }
-
+ 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_gridLeft-> ClearSelection();
m_gridMiddle->ClearSelection();
- m_gridRight->ClearSelection();
+ m_gridRight-> ClearSelection();
}
}
}
-void exstractNames(const FileDescrLine& fileDescr, wxString& name, wxString& dir)
+template <SelectedSide side>
+void exstractNames(const FileSystemObject& fsObj, wxString& name, wxString& dir)
{
- switch (fileDescr.objType)
+ if (!fsObj.isEmpty<side>())
+ {
+ const FileMapping* fileObj = dynamic_cast<const FileMapping*>(&fsObj);
+ if (fileObj != NULL)
+ {
+ name = fsObj.getFullName<side>().c_str();
+ dir = name.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR);
+ }
+ else
+ {
+ const DirMapping* dirObj = dynamic_cast<const DirMapping*>(&fsObj);
+ if (dirObj != NULL)
+ {
+ name = fsObj.getFullName<side>().c_str();
+ dir = name;
+ }
+ }
+ }
+ else
{
- case FileDescrLine::TYPE_FILE:
- name = fileDescr.fullName.c_str();
- dir = wxString(fileDescr.fullName.c_str()).BeforeLast(globalFunctions::FILE_NAME_SEPARATOR);
- break;
-
- case FileDescrLine::TYPE_DIRECTORY:
- name = fileDescr.fullName.c_str();
- dir = fileDescr.fullName.c_str();
- break;
-
- case FileDescrLine::TYPE_NOTHING:
name.clear();
dir.clear();
- break;
}
}
-void MainDialog::openWithFileManager(const int rowNumber, const bool leftSide)
+void MainDialog::openExternalApplication(unsigned int rowNumber, bool leftSide, const wxString& commandline)
{
- wxString command = globalSettings.gui.commandLineFileManager;
+ if (commandline.empty())
+ return;
+
+ wxString command = commandline;
wxString name;
wxString dir;
wxString nameCo;
wxString dirCo;
- if (0 <= rowNumber && rowNumber < int(gridDataView->elementsOnView()))
+ const FileSystemObject* fsObj = gridDataView->getObject(rowNumber);
+ if (fsObj)
{
if (leftSide)
{
- exstractNames((*gridDataView)[rowNumber].fileDescrLeft, name, dir);
- exstractNames((*gridDataView)[rowNumber].fileDescrRight, nameCo, dirCo);
+ exstractNames<LEFT_SIDE>( *fsObj, name, dir);
+ exstractNames<RIGHT_SIDE>(*fsObj, nameCo, dirCo);
}
else
{
- exstractNames((*gridDataView)[rowNumber].fileDescrRight, name, dir);
- exstractNames((*gridDataView)[rowNumber].fileDescrLeft, nameCo, dirCo);
+ exstractNames<RIGHT_SIDE>(*fsObj, name, dir);
+ exstractNames<LEFT_SIDE>( *fsObj, nameCo, dirCo);
}
#ifdef FFS_WIN
if (name.empty())
{
if (leftSide)
- wxExecute(wxString(wxT("explorer ")) + gridDataView->getFolderPair(rowNumber).leftDirectory);
+ wxExecute(wxString(wxT("explorer ")) + fsObj->getBaseDirPf<LEFT_SIDE>());
else
- wxExecute(wxString(wxT("explorer ")) + gridDataView->getFolderPair(rowNumber).rightDirectory);
+ wxExecute(wxString(wxT("explorer ")) + fsObj->getBaseDirPf<RIGHT_SIDE>());
return;
}
#endif
@@ -746,10 +754,10 @@ void MainDialog::openWithFileManager(const int rowNumber, const bool leftSide)
#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);
- command.Replace(wxT("%nameCo"), nameCo, true);
- command.Replace(wxT("%dirCo"), dirCo, true);
wxExecute(command);
}
@@ -902,10 +910,31 @@ void MainDialog::onGridLeftButtonEvent(wxKeyEvent& event)
else if (keyCode == WXK_NUMPAD_ADD) //CTRL + '+'
m_gridLeft->AutoSizeColumns(false);
}
- else if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE)
- deleteSelectedFiles();
+ else
+ switch (keyCode)
+ {
+ case WXK_DELETE:
+ case WXK_NUMPAD_DELETE:
+ deleteSelectedFiles();
+ break;
- event.Skip();
+ 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;
+ }
+
+ //event.Skip(); -> swallow event! don't allow default grid commands!
}
@@ -919,7 +948,7 @@ void MainDialog::onGridMiddleButtonEvent(wxKeyEvent& event)
copySelectionToClipboard(m_gridMiddle);
}
- event.Skip();
+ //event.Skip(); -> swallow event! don't allow default grid commands!
}
@@ -936,13 +965,64 @@ void MainDialog::onGridRightButtonEvent(wxKeyEvent& event)
else if (keyCode == WXK_NUMPAD_ADD) //CTRL + '+'
m_gridRight->AutoSizeColumns(false);
}
- else if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE)
- deleteSelectedFiles();
+ else
+ switch (keyCode)
+ {
+ case WXK_DELETE:
+ case WXK_NUMPAD_DELETE:
+ deleteSelectedFiles();
+ break;
- event.Skip();
+ 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;
+ }
+ //event.Skip(); -> swallow event! don't allow default grid commands!
}
+
+//------------------------------------------------------------
+//temporal variables used by exclude via context menu
+struct SelectedExtension : public wxObject
+{
+ SelectedExtension(const wxString& ext) : extension(ext) {}
+
+ wxString extension;
+};
+
+struct FilterObject
+{
+ FilterObject(const wxString& relName, bool isDirectory) :
+ relativeName(relName),
+ isDir(isDirectory) {}
+ wxString 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
@@ -962,38 +1042,41 @@ void MainDialog::OnContextRim(wxGridEvent& event)
m_gridLeft->ClearSelection();
}
}
-//------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------
- const std::set<int> selectionLeft = getSelectedRows(m_gridLeft);
- const std::set<int> selectionRight = getSelectedRows(m_gridRight);
+ const std::set<unsigned int> selectionLeft = getSelectedRows(m_gridLeft);
+ const std::set<unsigned int> selectionRight = getSelectedRows(m_gridRight);
- const int selectionBegin = selectionLeft.size() + selectionRight.size() == 0 ? 0 :
- selectionLeft.size() == 0 ? *selectionRight.begin() :
- selectionRight.size() == 0 ? *selectionLeft.begin() :
- std::min(*selectionLeft.begin(), *selectionRight.begin());
+ const unsigned int 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())
{
- if (selectionLeft.size() + selectionRight.size() > 0)
+ if (fsObj && (selectionLeft.size() + selectionRight.size() > 0))
{
//CONTEXT_SYNC_DIR_LEFT
wxMenuItem* menuItemSyncDirLeft = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_LEFT, _("Change direction"));
- menuItemSyncDirLeft->SetBitmap(getSyncOpImage((*gridDataView)[selectionBegin].cmpResult, true, SYNC_DIR_LEFT));
+ menuItemSyncDirLeft->SetBitmap(getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_LEFT));
contextMenu->Append(menuItemSyncDirLeft);
//CONTEXT_SYNC_DIR_NONE
wxMenuItem* menuItemSyncDirNone = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_NONE, _("Change direction"));
- menuItemSyncDirNone->SetBitmap(getSyncOpImage((*gridDataView)[selectionBegin].cmpResult, true, SYNC_DIR_NONE));
+ menuItemSyncDirNone->SetBitmap(getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_NONE));
contextMenu->Append(menuItemSyncDirNone);
//CONTEXT_SYNC_DIR_RIGHT
wxMenuItem* menuItemSyncDirRight = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_RIGHT, _("Change direction"));
- menuItemSyncDirRight->SetBitmap(getSyncOpImage((*gridDataView)[selectionBegin].cmpResult, true, SYNC_DIR_RIGHT));
+ menuItemSyncDirRight->SetBitmap(getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_RIGHT));
contextMenu->Append(menuItemSyncDirRight);
contextMenu->AppendSeparator();
@@ -1002,62 +1085,67 @@ void MainDialog::OnContextRim(wxGridEvent& event)
//CONTEXT_FILTER_TEMP
- if (selectionLeft.size() + selectionRight.size() > 0)
+ if (fsObj && (selectionLeft.size() + selectionRight.size() > 0))
{
- if ((*gridDataView)[selectionBegin].selectedForSynchronization) //valid access, as getSelectedRows returns valid references only
+ if (fsObj->selectedForSynchronization)
{
- wxMenuItem* menuItemExclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, _("Exclude temporarily"));
+ wxMenuItem* menuItemExclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, wxString(_("Exclude temporarily")) + wxT("\tSPACE"));
menuItemExclTemp->SetBitmap(*GlobalResources::getInstance().bitmapCheckBoxFalse);
contextMenu->Append(menuItemExclTemp);
}
else
{
- wxMenuItem* menuItemInclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, _("Include temporarily"));
+ wxMenuItem* menuItemInclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, wxString(_("Include temporarily")) + wxT("\tSPACE"));
menuItemInclTemp->SetBitmap(*GlobalResources::getInstance().bitmapCheckBoxTrue);
contextMenu->Append(menuItemInclTemp);
}
}
else
{
- contextMenu->Append(CONTEXT_FILTER_TEMP, _("Exclude temporarily")); //this element should always be visible
+ 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
- exFilterCandidateObj.clear();
- FilterObject newFilterEntry;
- for (std::set<int>::const_iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i)
+ FilterObjList exFilterCandidateObj;
+ for (std::set<unsigned int>::const_iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i)
{
- const FileCompareLine& line = (*gridDataView)[*i];
- newFilterEntry.relativeName = line.fileDescrLeft.relativeName.c_str();
- newFilterEntry.type = line.fileDescrLeft.objType;
- if (!newFilterEntry.relativeName.IsEmpty())
- exFilterCandidateObj.push_back(newFilterEntry);
+ const FileSystemObject* currObj = gridDataView->getObject(*i);
+ if (currObj && !currObj->isEmpty<LEFT_SIDE>())
+ exFilterCandidateObj.push_back(
+ FilterObject(currObj->getRelativeName<LEFT_SIDE>().c_str(),
+ dynamic_cast<const DirMapping*>(currObj) != NULL));
}
- for (std::set<int>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i)
+ for (std::set<unsigned int>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i)
{
- const FileCompareLine& line = (*gridDataView)[*i];
- newFilterEntry.relativeName = line.fileDescrRight.relativeName.c_str();
- newFilterEntry.type = line.fileDescrRight.objType;
- if (!newFilterEntry.relativeName.IsEmpty())
- exFilterCandidateObj.push_back(newFilterEntry);
+ const FileSystemObject* currObj = gridDataView->getObject(*i);
+ if (currObj && !currObj->isEmpty<RIGHT_SIDE>())
+ exFilterCandidateObj.push_back(
+ FilterObject(currObj->getRelativeName<RIGHT_SIDE>().c_str(),
+ dynamic_cast<const DirMapping*>(currObj) != NULL));
}
-//###############################################################################################
+ //###############################################################################################
//CONTEXT_EXCLUDE_EXT
- exFilterCandidateExtension.clear();
- if (exFilterCandidateObj.size() > 0 && exFilterCandidateObj[0].type == FileDescrLine::TYPE_FILE)
+ if (exFilterCandidateObj.size() > 0 && !exFilterCandidateObj[0].isDir)
{
const wxString filename = exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR);
if (filename.Find(wxChar('.')) != wxNOT_FOUND) //be careful: AfterLast will return the whole string if '.' is not found!
{
- exFilterCandidateExtension = filename.AfterLast(wxChar('.'));
+ const wxString extension = filename.AfterLast(wxChar('.'));
//add context menu item
- wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + exFilterCandidateExtension);
+ wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + extension);
menuItemExclExt->SetBitmap(*GlobalResources::getInstance().bitmapFilterSmall);
contextMenu->Append(menuItemExclExt);
+
+ //connect event
+ contextMenu->Connect(CONTEXT_EXCLUDE_EXT,
+ wxEVT_COMMAND_MENU_SELECTED,
+ wxCommandEventHandler(MainDialog::OnContextExcludeExtension),
+ new SelectedExtension(extension), //ownership passed!
+ this);
}
}
@@ -1073,6 +1161,40 @@ void MainDialog::OnContextRim(wxGridEvent& event)
{
menuItemExclObj->SetBitmap(*GlobalResources::getInstance().bitmapFilterSmall);
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)
+ {
+ if (i == globalSettings.gui.externelApplications.begin())
+ contextMenu->Append(newID, i->first + wxT("\t") + wxString(_("D-Click")) + wxT("; ENTER"));
+ else
+ contextMenu->Append(newID, i->first.empty() ? wxT(" ") : i->first); //wxWidgets doesn't like empty items
+
+ contextMenu->Enable(newID, externalAppEnabled);
+
+ //register event
+ contextMenu->Connect(newID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextOpenWith), NULL, this);
+ }
}
@@ -1089,18 +1211,6 @@ void MainDialog::OnContextRim(wxGridEvent& event)
contextMenu->Enable(CONTEXT_CLIPBOARD, false);
- //CONTEXT_EXPLORER
- contextMenu->Append(CONTEXT_EXPLORER, _("Open with File Manager\tD-Click"));
-
- if ( (m_gridLeft->isLeadGrid() && selectionLeft.size() <= 1) ||
- (m_gridRight->isLeadGrid() && selectionRight.size() <= 1))
- contextMenu->Enable(CONTEXT_EXPLORER, true);
- else
- contextMenu->Enable(CONTEXT_EXPLORER, false);
-
- contextMenu->AppendSeparator();
-
-
//CONTEXT_DELETE_FILES
contextMenu->Append(CONTEXT_DELETE_FILES, _("Delete files\tDEL"));
@@ -1108,98 +1218,78 @@ void MainDialog::OnContextRim(wxGridEvent& event)
contextMenu->Enable(CONTEXT_DELETE_FILES, false);
-//###############################################################################################
-
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextRimSelection), NULL, this);
+ //###############################################################################################
+ //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::OnContextRimSelection(wxCommandEvent& event)
+void MainDialog::OnContextFilterTemp(wxCommandEvent& event)
{
- const ContextIDRim eventId = static_cast<ContextIDRim>(event.GetId());
- switch (eventId)
- {
- case CONTEXT_SYNC_DIR_LEFT:
- {
- //merge selections from left and right grid
- const std::set<int> selection = getSelectedRows();
- setSyncDirManually(selection, FreeFileSync::SYNC_DIR_LEFT);
- }
- break;
-
- case CONTEXT_SYNC_DIR_NONE:
- {
- //merge selections from left and right grid
- const std::set<int> selection = getSelectedRows();
- setSyncDirManually(selection, FreeFileSync::SYNC_DIR_NONE);
- }
- break;
+ //merge selections from left and right grid
+ std::set<unsigned int> selection = getSelectedRows();
+ filterRangeManually(selection, *selection.begin());
+}
- case CONTEXT_SYNC_DIR_RIGHT:
- {
- //merge selections from left and right grid
- const std::set<int> selection = getSelectedRows();
- setSyncDirManually(selection, FreeFileSync::SYNC_DIR_RIGHT);
- }
- break;
- case CONTEXT_FILTER_TEMP:
+void MainDialog::OnContextExcludeExtension(wxCommandEvent& event)
+{
+ SelectedExtension* selExtension = dynamic_cast<SelectedExtension*>(event.m_callbackUserData);
+ if (selExtension)
{
- //merge selections from left and right grid
- std::set<int> selection = getSelectedRows();
- filterRangeManually(selection, *selection.begin());
- }
- break;
-
- case CONTEXT_EXCLUDE_EXT:
- if (!exFilterCandidateExtension.IsEmpty())
- {
- if (!currentCfg.mainCfg.excludeFilter.IsEmpty() && !currentCfg.mainCfg.excludeFilter.EndsWith(wxT(";")))
- currentCfg.mainCfg.excludeFilter+= wxT("\n");
+ if (!currentCfg.mainCfg.excludeFilter.IsEmpty() && !currentCfg.mainCfg.excludeFilter.EndsWith(wxT(";")))
+ currentCfg.mainCfg.excludeFilter += wxT("\n");
- currentCfg.mainCfg.excludeFilter+= wxString(wxT("*.")) + exFilterCandidateExtension + wxT(";"); //';' is appended to 'mark' that next exclude extension entry won't write to new line
+ currentCfg.mainCfg.excludeFilter += wxString(wxT("*.")) + selExtension->extension + wxT(";"); //';' is appended to 'mark' that next exclude extension entry won't write to new line
- currentCfg.mainCfg.filterIsActive = true;
- updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
+ currentCfg.mainCfg.filterIsActive = true;
+ updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
- FreeFileSync::FilterProcess filterInstance(currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter);
- filterInstance.filterGridData(currentGridData);
+ applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
+ updateGuiGrid();
- updateGuiGrid();
- if (currentCfg.hideFilteredElements)
- {
- m_gridLeft->ClearSelection();
- m_gridRight->ClearSelection();
- m_gridMiddle->ClearSelection();
- }
+ if (currentCfg.hideFilteredElements)
+ {
+ m_gridLeft-> ClearSelection();
+ m_gridRight-> ClearSelection();
+ m_gridMiddle->ClearSelection();
}
- break;
+ }
+}
- case CONTEXT_EXCLUDE_OBJ:
- if (exFilterCandidateObj.size() > 0) //check needed to determine if filtering is needed
+
+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
{
- for (std::vector<FilterObject>::const_iterator i = exFilterCandidateObj.begin(); i != exFilterCandidateObj.end(); ++i)
+ for (std::vector<FilterObject>::const_iterator i = objCont->selectedObjects.begin(); i != objCont->selectedObjects.end(); ++i)
{
if (!currentCfg.mainCfg.excludeFilter.IsEmpty() && !currentCfg.mainCfg.excludeFilter.EndsWith(wxT("\n")))
currentCfg.mainCfg.excludeFilter+= wxT("\n");
- if (i->type == FileDescrLine::TYPE_FILE)
+ if (!i->isDir)
currentCfg.mainCfg.excludeFilter+= wxString(globalFunctions::FILE_NAME_SEPARATOR) + i->relativeName;
- else if (i->type == FileDescrLine::TYPE_DIRECTORY)
+ else
currentCfg.mainCfg.excludeFilter+= wxString(globalFunctions::FILE_NAME_SEPARATOR) + i->relativeName + globalFunctions::FILE_NAME_SEPARATOR + wxT("*");
- else assert(false);
}
currentCfg.mainCfg.filterIsActive = true;
updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
- FreeFileSync::FilterProcess filterInstance(currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter);
- filterInstance.filterGridData(currentGridData);
-
+ applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
updateGuiGrid();
+
if (currentCfg.hideFilteredElements)
{
m_gridLeft->ClearSelection();
@@ -1207,40 +1297,67 @@ void MainDialog::OnContextRimSelection(wxCommandEvent& event)
m_gridMiddle->ClearSelection();
}
}
- break;
+ }
+}
- case CONTEXT_CLIPBOARD:
- if (m_gridLeft->isLeadGrid())
- copySelectionToClipboard(m_gridLeft);
- else if (m_gridRight->isLeadGrid())
- copySelectionToClipboard(m_gridRight);
- break;
- case CONTEXT_EXPLORER:
- if (m_gridLeft->isLeadGrid() || m_gridRight->isLeadGrid())
- {
- const CustomGrid* leadGrid = NULL;
- if (m_gridLeft->isLeadGrid())
- leadGrid = m_gridLeft;
- else
- leadGrid = m_gridRight;
+void MainDialog::OnContextCopyClipboard(wxCommandEvent& event)
+{
+ if (m_gridLeft->isLeadGrid())
+ copySelectionToClipboard(m_gridLeft);
+ else if (m_gridRight->isLeadGrid())
+ copySelectionToClipboard(m_gridRight);
+}
- std::set<int> selection = getSelectedRows(leadGrid);
- if (selection.size() == 1)
- openWithFileManager(*selection.begin(), m_gridLeft->isLeadGrid());
- else if (selection.size() == 0)
- openWithFileManager(-1, m_gridLeft->isLeadGrid());
- }
- break;
+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<unsigned int> selection = getSelectedRows(leadGrid);
- case CONTEXT_DELETE_FILES:
- deleteSelectedFiles();
- break;
+ const int index = event.GetId() - externalAppIDFirst;
+
+ if ( selection.size() == 1 &&
+ 0 <= index && static_cast<unsigned>(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<unsigned int> selection = getSelectedRows();
+ setSyncDirManually(selection, FreeFileSync::SYNC_DIR_LEFT);
+}
+
+
+void MainDialog::OnContextSyncDirNone(wxCommandEvent& event)
+{
+ //merge selections from left and right grid
+ const std::set<unsigned int> selection = getSelectedRows();
+ setSyncDirManually(selection, FreeFileSync::SYNC_DIR_NONE);
+}
+
+
+void MainDialog::OnContextSyncDirRight(wxCommandEvent& event)
+{
+ //merge selections from left and right grid
+ const std::set<unsigned int> selection = getSelectedRows();
+ setSyncDirManually(selection, FreeFileSync::SYNC_DIR_RIGHT);
+}
+
+
void MainDialog::OnContextRimLabelLeft(wxGridEvent& event)
{
contextMenu.reset(new wxMenu); //re-create context menu
@@ -1252,7 +1369,9 @@ void MainDialog::OnContextRimLabelLeft(wxGridEvent& event)
contextMenu->Append(itemAutoAdjust);
itemAutoAdjust->Check(globalSettings.gui.autoAdjustColumnsLeft);
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextRimLabelSelection), NULL, this);
+ 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
}
@@ -1268,62 +1387,60 @@ void MainDialog::OnContextRimLabelRight(wxGridEvent& event)
contextMenu->Append(itemAutoAdjust);
itemAutoAdjust->Check(globalSettings.gui.autoAdjustColumnsRight);
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextRimLabelSelection), NULL, this);
+ 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::OnContextRimLabelSelection(wxCommandEvent& event)
+void MainDialog::OnContextCustColumnLeft(wxCommandEvent& event)
{
- const ContextIDRimLabel eventId = static_cast<ContextIDRimLabel>(event.GetId());
- switch (eventId)
- {
- case CONTEXT_CUSTOMIZE_COLUMN_LEFT:
+ xmlAccess::ColumnAttributes colAttr = m_gridLeft->getColumnAttributes();
+ CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIconsLeft);
+ if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
{
- xmlAccess::ColumnAttributes colAttr = m_gridLeft->getColumnAttributes();
- CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIconsLeft);
- if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
- {
- m_gridLeft->setColumnAttributes(colAttr);
+ m_gridLeft->setColumnAttributes(colAttr);
#ifdef FFS_WIN
- m_gridLeft->enableFileIcons(globalSettings.gui.showFileIconsLeft);
+ m_gridLeft->enableFileIcons(globalSettings.gui.showFileIconsLeft);
#endif
- 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));
- }
+ 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));
}
- break;
+}
- case CONTEXT_CUSTOMIZE_COLUMN_RIGHT:
+
+void MainDialog::OnContextCustColumnRight(wxCommandEvent& event)
+{
+ xmlAccess::ColumnAttributes colAttr = m_gridRight->getColumnAttributes();
+ CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIconsRight);
+ if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
{
- xmlAccess::ColumnAttributes colAttr = m_gridRight->getColumnAttributes();
- CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIconsRight);
- if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
- {
- m_gridRight->setColumnAttributes(colAttr);
+ m_gridRight->setColumnAttributes(colAttr);
#ifdef FFS_WIN
- m_gridRight->enableFileIcons(globalSettings.gui.showFileIconsRight);
+ m_gridRight->enableFileIcons(globalSettings.gui.showFileIconsRight);
#endif
- 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));
- }
+ 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));
}
- break;
+}
- case CONTEXT_AUTO_ADJUST_COLUMN_LEFT:
- globalSettings.gui.autoAdjustColumnsLeft = !globalSettings.gui.autoAdjustColumnsLeft;
- updateGuiGrid();
- break;
- case CONTEXT_AUTO_ADJUST_COLUMN_RIGHT:
- globalSettings.gui.autoAdjustColumnsRight = !globalSettings.gui.autoAdjustColumnsRight;
- updateGuiGrid();
- break;
- }
+void MainDialog::OnContextAutoAdjustLeft(wxCommandEvent& event)
+{
+ globalSettings.gui.autoAdjustColumnsLeft = !globalSettings.gui.autoAdjustColumnsLeft;
+ updateGuiGrid();
+}
+
+
+void MainDialog::OnContextAutoAdjustRight(wxCommandEvent& event)
+{
+ globalSettings.gui.autoAdjustColumnsRight = !globalSettings.gui.autoAdjustColumnsRight;
+ updateGuiGrid();
}
@@ -1334,31 +1451,16 @@ void MainDialog::OnContextMiddle(wxGridEvent& event)
contextMenu->Append(CONTEXT_CHECK_ALL, _("Check all"));
contextMenu->Append(CONTEXT_UNCHECK_ALL, _("Uncheck all"));
- if (gridDataView->refGridIsEmpty())
+ if (gridDataView->rowsTotal() == 0)
{
contextMenu->Enable(CONTEXT_CHECK_ALL, false);
contextMenu->Enable(CONTEXT_UNCHECK_ALL, false);
}
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextMiddleSelection), NULL, this);
- PopupMenu(contextMenu.get()); //show context menu
-}
-
+ 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);
-void MainDialog::OnContextMiddleSelection(wxCommandEvent& event)
-{
- const ContextIDMiddle eventId = static_cast<ContextIDMiddle>(event.GetId());
- switch (eventId)
- {
- case CONTEXT_CHECK_ALL:
- FreeFileSync::FilterProcess::includeAllRowsOnGrid(currentGridData);
- refreshGridAfterFilterChange(0); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts break;
- break;
- case CONTEXT_UNCHECK_ALL:
- FreeFileSync::FilterProcess::excludeAllRowsOnGrid(currentGridData);
- refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
- break;
- }
+ PopupMenu(contextMenu.get()); //show context menu
}
@@ -1377,25 +1479,36 @@ void MainDialog::OnContextMiddleLabel(wxGridEvent& event)
contextMenu->Append(itemCmpResult);
contextMenu->Append(itemSyncPreview);
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextMiddleLabelSelection), NULL, this);
+ 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::OnContextMiddleLabelSelection(wxCommandEvent& event)
+void MainDialog::OnContextIncludeAll(wxCommandEvent& event)
{
- const ContextIDMiddleLabel eventId = static_cast<ContextIDMiddleLabel>(event.GetId());
- switch (eventId)
- {
- case CONTEXT_COMPARISON_RESULT:
- //change view
- syncPreview.enablePreview(false);
- break;
- case CONTEXT_SYNC_PREVIEW:
- //change view
- syncPreview.enablePreview(true);
- break;
- }
+ FilterProcess::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)
+{
+ FilterProcess::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
}
@@ -1407,7 +1520,7 @@ void MainDialog::OnDirSelected(wxFileDirPickerEvent& event)
syncPreview.enableSynchronization(false);
//clear grids
- currentGridData.clear();
+ gridDataView->clearAllRows();
updateGuiGrid();
event.Skip();
@@ -1442,7 +1555,7 @@ bool sameFileSpecified(const wxString& file1, const wxString& file2)
const wxString file2Full = getFullFilename(file2);
#ifdef FFS_WIN //don't respect case in windows build
- return FreeFileSync::compareStringsWin32(file1Full.c_str(), file2Full.c_str()) == 0;
+ return file1Full.CmpNoCase(file2Full) == 0;
#elif defined FFS_LINUX
return file1Full == file2Full;
#endif
@@ -1502,7 +1615,7 @@ int findTextPos(const wxArrayString& array, const wxString& text)
{
for (unsigned int i = 0; i < array.GetCount(); ++i)
#ifdef FFS_WIN //don't respect case in windows build
- if (FreeFileSync::compareStringsWin32(array[i].c_str(), text.c_str()) == 0)
+ if (array[i].CmpNoCase(text) == 0)
#elif defined FFS_LINUX
if (array[i] == text)
#endif
@@ -1579,12 +1692,29 @@ bool MainDialog::trySaveConfig() //return true if saved successfully
void MainDialog::OnLoadConfig(wxCommandEvent& event)
{
- wxFileDialog* filePicker = new wxFileDialog(this, wxEmptyString, wxEmptyString, wxEmptyString, wxString(_("FreeFileSync configuration")) + wxT(" (*.ffs_gui)|*.ffs_gui"), wxFD_OPEN);
+ 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();
@@ -1593,14 +1723,14 @@ void MainDialog::OnLoadFromHistory(wxCommandEvent& event)
}
-void MainDialog::loadConfiguration(const wxString& filename)
+bool MainDialog::saveOldConfig() //return false on user abort
{
//notify user about changed settings
- if (globalSettings.gui.popupOnConfigChange && !currentConfigFileName.empty()) //only if check is active and non-default config file loaded
+ if (globalSettings.optDialogs.popupOnConfigChange && !currentConfigFileName.empty()) //only if check is active and non-default config file loaded
{
if (lastConfigurationSaved != getCurrentConfiguration())
{
- bool dontShowAgain = !globalSettings.gui.popupOnConfigChange;
+ bool dontShowAgain = !globalSettings.optDialogs.popupOnConfigChange;
QuestionDlg* notifyChangeDlg = new QuestionDlg(this,
QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_NO | QuestionDlg::BUTTON_CANCEL,
@@ -1611,22 +1741,26 @@ void MainDialog::loadConfiguration(const wxString& filename)
{
case QuestionDlg::BUTTON_YES:
if (!trySaveConfig())
- return;
+ return false;
break;
case QuestionDlg::BUTTON_NO:
- globalSettings.gui.popupOnConfigChange = !dontShowAgain;
+ globalSettings.optDialogs.popupOnConfigChange = !dontShowAgain;
break;
case QuestionDlg::BUTTON_CANCEL:
- return;
+ return false;
}
}
}
- //------------------------------------------------------------------------------------
+ return true;
+}
+
+void MainDialog::loadConfiguration(const wxString& filename)
+{
if (!filename.IsEmpty())
- { //clear grids
- currentGridData.clear();
- updateGuiGrid();
+ {
+ if (!saveOldConfig())
+ return;
if (readConfigurationFromXml(filename))
pushStatusInformation(_("Configuration loaded!"));
@@ -1692,44 +1826,17 @@ void MainDialog::OnFolderHistoryKeyEvent(wxKeyEvent& event)
void MainDialog::OnClose(wxCloseEvent &event)
{
- requestShutdown();
-}
-
+ if (!saveOldConfig()) //notify user about changed settings
+ return;
-void MainDialog::OnQuit(wxCommandEvent &event)
-{
- requestShutdown();
+ Destroy();
}
-void MainDialog::requestShutdown()
+void MainDialog::OnQuit(wxCommandEvent &event)
{
- //notify user about changed settings
- if (globalSettings.gui.popupOnConfigChange && !currentConfigFileName.empty()) //only if check is active and non-default config file loaded
- {
- if (lastConfigurationSaved != getCurrentConfiguration())
- {
- bool dontShowAgain = !globalSettings.gui.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;
- break;
- case QuestionDlg::BUTTON_NO:
- globalSettings.gui.popupOnConfigChange = !dontShowAgain;
- break;
- case QuestionDlg::BUTTON_CANCEL:
- return;
- }
- }
- }
+ if (!saveOldConfig()) //notify user about changed settings
+ return;
Destroy();
}
@@ -1742,9 +1849,9 @@ void MainDialog::OnCheckRows(FFSCheckRowsEvent& event)
if (0 <= lowerBound)
{
- std::set<int> selectedRowsOnView;
+ std::set<unsigned int> selectedRowsOnView;
- for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->elementsOnView()) - 1); ++i)
+ for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->rowsOnView()) - 1); ++i)
selectedRowsOnView.insert(i);
filterRangeManually(selectedRowsOnView, event.rowFrom);
@@ -1759,10 +1866,14 @@ void MainDialog::OnSetSyncDirection(FFSSyncDirectionEvent& event)
if (0 <= lowerBound)
{
- for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->elementsOnView()) - 1); ++i)
+ for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->rowsOnView()) - 1); ++i)
{
- (*gridDataView)[i].syncDir = event.direction;
- (*gridDataView)[i].selectedForSynchronization = true;
+ FileSystemObject* fsObj = gridDataView->getObject(i);
+ if (fsObj)
+ {
+ setSyncDirection(event.direction, *fsObj); //set new direction (recursively)
+ FilterProcess::setActiveStatus(true, *fsObj); //works recursively for directories
+ }
}
updateGuiGrid();
@@ -1774,9 +1885,10 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
{
//load XML
xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!!
+ bool parsingError = false;
try
{
- xmlAccess::readGuiConfig(filename, newGuiCfg);
+ xmlAccess::readGuiOrBatchConfig(filename, newGuiCfg); //allow reading batch configurations also
}
catch (const xmlAccess::XmlError& error)
{
@@ -1785,7 +1897,10 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
else
{
if (error.getSeverity() == xmlAccess::XmlError::WARNING)
+ {
wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING);
+ parsingError = true;
+ }
else
{
wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR);
@@ -1794,60 +1909,15 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
}
}
- currentCfg = newGuiCfg;
-
- //evaluate new settings...
-
- //disable the sync button
- syncPreview.enableSynchronization(false);
-
- //clear grids
- currentGridData.clear();
- updateGuiGrid();
-
- //(re-)set view filter buttons
- gridDataView->resetSettings();
- updateViewFilterButtons();
-
- updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
-
- //read folder pairs:
-
- //clear existing pairs first
- FreeFileSync::setDirectoryName(wxEmptyString, m_directoryLeft, m_dirPickerLeft);
- FreeFileSync::setDirectoryName(wxEmptyString, m_directoryRight, m_dirPickerRight);
-
- clearAddFolderPairs();
-
- if (currentCfg.directoryPairs.size() > 0)
- {
- //set main folder pair
- std::vector<FolderPair>::const_iterator main = currentCfg.directoryPairs.begin();
-
- FreeFileSync::setDirectoryName(main->leftDirectory.c_str(), m_directoryLeft, m_dirPickerLeft);
- FreeFileSync::setDirectoryName(main->rightDirectory.c_str(), m_directoryRight, m_dirPickerRight);
-
- addLeftFolderToHistory( main->leftDirectory.c_str()); //another hack: wxCombobox::Insert() asynchronously sends message
- addRightFolderToHistory(main->rightDirectory.c_str()); //overwriting a later wxCombobox::SetValue()!!! :(
-
- //set additional pairs
- addFolderPair(std::vector<FolderPair>(currentCfg.directoryPairs.begin() + 1, currentCfg.directoryPairs.end()));
- }
-
- //read GUI layout
- currentCfg.hideFilteredElements = currentCfg.hideFilteredElements;
- m_checkBoxHideFilt->SetValue(currentCfg.hideFilteredElements);
-
- currentCfg.ignoreErrors = currentCfg.ignoreErrors;
-
- syncPreview.enablePreview(currentCfg.syncPreviewEnabled);
+ setCurrentConfiguration(newGuiCfg);
//###########################################################
addFileToCfgHistory(filename); //put filename on list of last used config files
- lastConfigurationSaved = currentCfg;
+ lastConfigurationSaved = parsingError ? xmlAccess::XmlGuiConfig() : currentCfg; //simulate changed config on parsing errors
- if (filename == lastConfigFileName()) //set title
+ //set title
+ if (filename == lastConfigFileName())
{
SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
currentConfigFileName.clear();
@@ -1858,13 +1928,6 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
currentConfigFileName = filename;
}
- //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.syncConfiguration.getVariantName() + wxT(")"));
- bSizer6->Layout(); //adapt layout for variant text
-
return true;
}
@@ -1904,12 +1967,83 @@ bool MainDialog::writeConfigurationToXml(const wxString& filename)
}
+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();
+
+ updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
+
+
+ //read main folder pair
+ const wxString mainFolderLeft = currentCfg.mainCfg.mainFolderPair.leftDirectory.c_str();
+ const wxString mainFolderRight = currentCfg.mainCfg.mainFolderPair.rightDirectory.c_str();
+ FreeFileSync::setDirectoryName(mainFolderLeft, m_directoryLeft, m_dirPickerLeft);
+ FreeFileSync::setDirectoryName(mainFolderRight, m_directoryRight, m_dirPickerRight);
+
+ addLeftFolderToHistory( mainFolderLeft); //another hack: wxCombobox::Insert() asynchronously sends message
+ addRightFolderToHistory(mainFolderRight); //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->m_directoryLeft->GetValue().c_str(),
+ panel->m_directoryRight->GetValue().c_str(),
+ panel->altSyncConfig,
+ panel->altFilter);
+}
+
+
xmlAccess::XmlGuiConfig MainDialog::getCurrentConfiguration() const
{
xmlAccess::XmlGuiConfig guiCfg = currentCfg;
- //load settings whose ownership lies not in currentCfg
- guiCfg.directoryPairs = getFolderPairs();
+ //load settings whose ownership lies not in currentCfg:
+
+ //main folder pair
+ guiCfg.mainCfg.mainFolderPair.leftDirectory = m_directoryLeft->GetValue().c_str();
+ guiCfg.mainCfg.mainFolderPair.rightDirectory = m_directoryRight->GetValue().c_str();
+
+ //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;
@@ -1936,7 +2070,7 @@ void MainDialog::refreshGridAfterFilterChange(const int delay)
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)
+ updateGuiGrid(); //redraw grid to remove excluded elements (keeping sort sequence)
m_gridLeft->ClearSelection();
m_gridRight->ClearSelection();
@@ -1952,17 +2086,7 @@ void MainDialog::OnFilterButton(wxCommandEvent &event)
//make sure, button-appearance and "filterIsActive" are in sync.
updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
- if (currentCfg.mainCfg.filterIsActive)
- {
- FreeFileSync::FilterProcess filterInstance(currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter);
- filterInstance.filterGridData(currentGridData);
- refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
- }
- else
- {
- FreeFileSync::FilterProcess::includeAllRowsOnGrid(currentGridData);
- refreshGridAfterFilterChange(0); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts }
- }
+ updateFilterConfig(false); //refresh filtering (without changing active-status)
}
@@ -1974,41 +2098,21 @@ void MainDialog::OnHideFilteredButton(wxCommandEvent &event)
m_gridLeft->ClearSelection();
m_gridRight->ClearSelection();
+ updateGuiGrid();
- refreshGridAfterFilterChange(0);
-
- event.Skip();
+// event.Skip();
}
void MainDialog::OnConfigureFilter(wxHyperlinkEvent &event)
{
- const wxString beforeImage = currentCfg.mainCfg.includeFilter + wxChar(1) + currentCfg.mainCfg.excludeFilter;
-
FilterDlg* filterDlg = new FilterDlg(this, currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter);
- if (filterDlg->ShowModal() == FilterDlg::BUTTON_OKAY)
+ if (filterDlg->ShowModal() == FilterDlg::BUTTON_APPLY)
{
- const wxString afterImage = currentCfg.mainCfg.includeFilter + wxChar(1) + currentCfg.mainCfg.excludeFilter;
-
- if (beforeImage != afterImage) //if filter settings are changed: set filtering to "on"
- {
- if (afterImage == (wxString(wxT("*")) + wxChar(1))) //default
- {
- currentCfg.mainCfg.filterIsActive = false;
- FreeFileSync::FilterProcess::includeAllRowsOnGrid(currentGridData);
- }
- else
- {
- currentCfg.mainCfg.filterIsActive = true;
-
- FreeFileSync::FilterProcess filterInstance(currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter);
- filterInstance.filterGridData(currentGridData);
- }
-
- updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
-
- updateGuiGrid();
- }
+ if (currentCfg.mainCfg.includeFilter == wxT("*") && currentCfg.mainCfg.excludeFilter.empty()) //default
+ updateFilterConfig(false); //re-apply filter (without changing active-status)
+ else
+ updateFilterConfig(true); //activate(and apply) filter
}
//no event.Skip() here, to not start browser
@@ -2017,269 +2121,193 @@ void MainDialog::OnConfigureFilter(wxHyperlinkEvent &event)
void MainDialog::OnLeftOnlyFiles(wxCommandEvent& event)
{
- gridDataView->leftOnlyFilesActive = !gridDataView->leftOnlyFilesActive;
- updateViewFilterButtons();
+ m_bpButtonLeftOnly->toggle();
updateGuiGrid();
};
+
void MainDialog::OnLeftNewerFiles(wxCommandEvent& event)
{
- gridDataView->leftNewerFilesActive = !gridDataView->leftNewerFilesActive;
- updateViewFilterButtons();
+ m_bpButtonLeftNewer->toggle();
updateGuiGrid();
};
+
void MainDialog::OnDifferentFiles(wxCommandEvent& event)
{
- gridDataView->differentFilesActive = !gridDataView->differentFilesActive;
- updateViewFilterButtons();
+ m_bpButtonDifferent->toggle();
updateGuiGrid();
};
+
void MainDialog::OnRightNewerFiles(wxCommandEvent& event)
{
- gridDataView->rightNewerFilesActive = !gridDataView->rightNewerFilesActive;
- updateViewFilterButtons();
+ m_bpButtonRightNewer->toggle();
updateGuiGrid();
};
+
void MainDialog::OnRightOnlyFiles(wxCommandEvent& event)
{
- gridDataView->rightOnlyFilesActive = !gridDataView->rightOnlyFilesActive;
- updateViewFilterButtons();
+ m_bpButtonRightOnly->toggle();
updateGuiGrid();
};
void MainDialog::OnEqualFiles(wxCommandEvent& event)
{
- gridDataView->equalFilesActive = !gridDataView->equalFilesActive;
- updateViewFilterButtons();
+ m_bpButtonEqual->toggle();
updateGuiGrid();
};
void MainDialog::OnConflictFiles(wxCommandEvent& event)
{
- gridDataView->conflictFilesActive = !gridDataView->conflictFilesActive;
- updateViewFilterButtons();
+ m_bpButtonConflict->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncCreateLeft(wxCommandEvent& event)
{
- gridDataView->syncCreateLeftActive = !gridDataView->syncCreateLeftActive;
- updateViewFilterButtons();
+ m_bpButtonSyncCreateLeft->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncCreateRight(wxCommandEvent& event)
{
- gridDataView->syncCreateRightActive = !gridDataView->syncCreateRightActive;
- updateViewFilterButtons();
+ m_bpButtonSyncCreateRight->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncDeleteLeft(wxCommandEvent& event)
{
- gridDataView->syncDeleteLeftActive = !gridDataView->syncDeleteLeftActive;
- updateViewFilterButtons();
+ m_bpButtonSyncDeleteLeft->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncDeleteRight(wxCommandEvent& event)
{
- gridDataView->syncDeleteRightActive = !gridDataView->syncDeleteRightActive;
- updateViewFilterButtons();
+ m_bpButtonSyncDeleteRight->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncDirLeft(wxCommandEvent& event)
{
- gridDataView->syncDirLeftActive = !gridDataView->syncDirLeftActive;
- updateViewFilterButtons();
+ m_bpButtonSyncDirOverwLeft->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncDirRight(wxCommandEvent& event)
{
- gridDataView->syncDirRightActive = !gridDataView->syncDirRightActive;
- updateViewFilterButtons();
+ m_bpButtonSyncDirOverwRight->toggle();
updateGuiGrid();
};
void MainDialog::OnSyncDirNone(wxCommandEvent& event)
{
- gridDataView->syncDirNoneActive = !gridDataView->syncDirNoneActive;
- updateViewFilterButtons();
+ m_bpButtonSyncDirNone->toggle();
updateGuiGrid();
};
-void MainDialog::updateViewFilterButtons()
+void MainDialog::initViewFilterButtons()
{
//compare result buttons
- if (gridDataView->leftOnlyFilesActive)
- {
- m_bpButtonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftOnlyAct);
- m_bpButtonLeftOnly->SetToolTip(_("Hide files that exist on left side only"));
- }
- else
- {
- m_bpButtonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftOnlyDeact);
- m_bpButtonLeftOnly->SetToolTip(_("Show files that exist on left side only"));
- }
-
- if (gridDataView->rightOnlyFilesActive)
- {
- m_bpButtonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightOnlyAct);
- m_bpButtonRightOnly->SetToolTip(_("Hide files that exist on right side only"));
- }
- else
- {
- m_bpButtonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightOnlyDeact);
- m_bpButtonRightOnly->SetToolTip(_("Show files that exist on right side only"));
- }
-
- if (gridDataView->leftNewerFilesActive)
- {
- m_bpButtonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftNewerAct);
- m_bpButtonLeftNewer->SetToolTip(_("Hide files that are newer on left"));
- }
- else
- {
- m_bpButtonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftNewerDeact);
- m_bpButtonLeftNewer->SetToolTip(_("Show files that are newer on left"));
- }
-
- if (gridDataView->rightNewerFilesActive)
- {
- m_bpButtonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightNewerAct);
- m_bpButtonRightNewer->SetToolTip(_("Hide files that are newer on right"));
- }
- else
- {
- m_bpButtonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightNewerDeact);
- m_bpButtonRightNewer->SetToolTip(_("Show files that are newer on right"));
- }
-
- if (gridDataView->equalFilesActive)
- {
- m_bpButtonEqual->SetBitmapLabel(*GlobalResources::getInstance().bitmapEqualAct);
- m_bpButtonEqual->SetToolTip(_("Hide files that are equal"));
- }
- else
- {
- m_bpButtonEqual->SetBitmapLabel(*GlobalResources::getInstance().bitmapEqualDeact);
- m_bpButtonEqual->SetToolTip(_("Show files that are equal"));
- }
-
- if (gridDataView->differentFilesActive)
- {
- m_bpButtonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapDifferentAct);
- m_bpButtonDifferent->SetToolTip(_("Hide files that are different"));
- }
- else
- {
- m_bpButtonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapDifferentDeact);
- m_bpButtonDifferent->SetToolTip(_("Show files that are different"));
- }
-
- if (gridDataView->conflictFilesActive)
- {
- m_bpButtonConflict->SetBitmapLabel(*GlobalResources::getInstance().bitmapConflictAct);
- m_bpButtonConflict->SetToolTip(_("Hide conflicts"));
- }
- else
- {
- m_bpButtonConflict->SetBitmapLabel(*GlobalResources::getInstance().bitmapConflictDeact);
- m_bpButtonConflict->SetToolTip(_("Show conflicts"));
- }
+ m_bpButtonLeftOnly->init(*GlobalResources::getInstance().bitmapLeftOnlyAct,
+ _("Hide files that exist on left side only"),
+ *GlobalResources::getInstance().bitmapLeftOnlyDeact,
+ _("Show files that exist on left side only"));
+
+ m_bpButtonRightOnly->init(*GlobalResources::getInstance().bitmapRightOnlyAct,
+ _("Hide files that exist on right side only"),
+ *GlobalResources::getInstance().bitmapRightOnlyDeact,
+ _("Show files that exist on right side only"));
+
+ m_bpButtonLeftNewer->init(*GlobalResources::getInstance().bitmapLeftNewerAct,
+ _("Hide files that are newer on left"),
+ *GlobalResources::getInstance().bitmapLeftNewerDeact,
+ _("Show files that are newer on left"));
+
+ m_bpButtonRightNewer->init(*GlobalResources::getInstance().bitmapRightNewerAct,
+ _("Hide files that are newer on right"),
+ *GlobalResources::getInstance().bitmapRightNewerDeact,
+ _("Show files that are newer on right"));
+
+ m_bpButtonEqual->init(*GlobalResources::getInstance().bitmapEqualAct,
+ _("Hide files that are equal"),
+ *GlobalResources::getInstance().bitmapEqualDeact,
+ _("Show files that are equal"));
+
+ m_bpButtonDifferent->init(*GlobalResources::getInstance().bitmapDifferentAct,
+ _("Hide files that are different"),
+ *GlobalResources::getInstance().bitmapDifferentDeact,
+ _("Show files that are different"));
+
+ m_bpButtonConflict->init(*GlobalResources::getInstance().bitmapConflictAct,
+ _("Hide conflicts"),
+ *GlobalResources::getInstance().bitmapConflictDeact,
+ _("Show conflicts"));
//sync preview buttons
- if (gridDataView->syncCreateLeftActive)
- {
- m_bpButtonSyncCreateLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCreateLeftAct);
- m_bpButtonSyncCreateLeft->SetToolTip(_("Hide files that will be created on the left side"));
- }
- else
- {
- m_bpButtonSyncCreateLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCreateLeftDeact);
- m_bpButtonSyncCreateLeft->SetToolTip(_("Show files that will be created on the left side"));
- }
-
- if (gridDataView->syncCreateRightActive)
- {
- m_bpButtonSyncCreateRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCreateRightAct);
- m_bpButtonSyncCreateRight->SetToolTip(_("Hide files that will be created on the right side"));
- }
- else
- {
- m_bpButtonSyncCreateRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCreateRightDeact);
- m_bpButtonSyncCreateRight->SetToolTip(_("Show files that will be created on the right side"));
- }
-
- if (gridDataView->syncDeleteLeftActive)
- {
- m_bpButtonSyncDeleteLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDeleteLeftAct);
- m_bpButtonSyncDeleteLeft->SetToolTip(_("Hide files that will be deleted on the left side"));
- }
- else
- {
- m_bpButtonSyncDeleteLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDeleteLeftDeact);
- m_bpButtonSyncDeleteLeft->SetToolTip(_("Show files that will be deleted on the left side"));
- }
-
- if (gridDataView->syncDeleteRightActive)
- {
- m_bpButtonSyncDeleteRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDeleteRightAct);
- m_bpButtonSyncDeleteRight->SetToolTip(_("Hide files that will be deleted on the right side"));
- }
- else
- {
- m_bpButtonSyncDeleteRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDeleteRightDeact);
- m_bpButtonSyncDeleteRight->SetToolTip(_("Show files that will be deleted on the right side"));
- }
+ m_bpButtonSyncCreateLeft->init(*GlobalResources::getInstance().bitmapSyncCreateLeftAct,
+ _("Hide files that will be created on the left side"),
+ *GlobalResources::getInstance().bitmapSyncCreateLeftDeact,
+ _("Show files that will be created on the left side"));
+
+ m_bpButtonSyncCreateRight->init(*GlobalResources::getInstance().bitmapSyncCreateRightAct,
+ _("Hide files that will be created on the right side"),
+ *GlobalResources::getInstance().bitmapSyncCreateRightDeact,
+ _("Show files that will be created on the right side"));
+
+ m_bpButtonSyncDeleteLeft->init(*GlobalResources::getInstance().bitmapSyncDeleteLeftAct,
+ _("Hide files that will be deleted on the left side"),
+ *GlobalResources::getInstance().bitmapSyncDeleteLeftDeact,
+ _("Show files that will be deleted on the left side"));
+
+ m_bpButtonSyncDeleteRight->init(*GlobalResources::getInstance().bitmapSyncDeleteRightAct,
+ _("Hide files that will be deleted on the right side"),
+ *GlobalResources::getInstance().bitmapSyncDeleteRightDeact,
+ _("Show files that will be deleted on the right side"));
+
+ m_bpButtonSyncDirOverwLeft->init(*GlobalResources::getInstance().bitmapSyncDirLeftAct,
+ _("Hide files that will be overwritten on left side"),
+ *GlobalResources::getInstance().bitmapSyncDirLeftDeact,
+ _("Show files that will be overwritten on left side"));
+
+ m_bpButtonSyncDirOverwRight->init(*GlobalResources::getInstance().bitmapSyncDirRightAct,
+ _("Hide files that will be overwritten on right side"),
+ *GlobalResources::getInstance().bitmapSyncDirRightDeact,
+ _("Show files that will be overwritten on right side"));
+
+ m_bpButtonSyncDirNone->init(*GlobalResources::getInstance().bitmapSyncDirNoneAct,
+ _("Hide files that won't be copied"),
+ *GlobalResources::getInstance().bitmapSyncDirNoneDeact,
+ _("Show files that won't be copied"));
- if (gridDataView->syncDirLeftActive)
- {
- m_bpButtonSyncDirLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirLeftAct);
- m_bpButtonSyncDirLeft->SetToolTip(_("Hide files that will be copied to the left side"));
- }
- else
- {
- m_bpButtonSyncDirLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirLeftDeact);
- m_bpButtonSyncDirLeft->SetToolTip(_("Show files that will be copied to the left side"));
- }
-
- if (gridDataView->syncDirRightActive)
- {
- m_bpButtonSyncDirRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirRightAct);
- m_bpButtonSyncDirRight->SetToolTip(_("Hide files that will be copied to the right side"));
- }
- else
- {
- m_bpButtonSyncDirRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirRightDeact);
- m_bpButtonSyncDirRight->SetToolTip(_("Show files that will be copied to the right side"));
- }
+ //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);
- if (gridDataView->syncDirNoneActive)
- {
- m_bpButtonSyncDirNone->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirNoneAct);
- m_bpButtonSyncDirNone->SetToolTip(_("Hide files that won't be copied"));
- }
- else
- {
- m_bpButtonSyncDirNone->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirNoneDeact);
- m_bpButtonSyncDirNone->SetToolTip(_("Show files that won't be copied"));
- }
+ //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);
}
@@ -2311,34 +2339,15 @@ void MainDialog::updateFilterButton(wxBitmapButton* filterButton, bool isActive)
}
-std::vector<FolderPair> MainDialog::getFolderPairs() const
-{
- std::vector<FolderPair> output;
-
- //add main pair
- output.push_back(FolderPair(m_directoryLeft->GetValue().c_str(),
- m_directoryRight->GetValue().c_str()));
-
- //add additional pairs
- for (std::vector<FolderPairPanel*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
- output.push_back(FolderPair((*i)->m_directoryLeft->GetValue().c_str(),
- (*i)->m_directoryRight->GetValue().c_str()));
- return output;
-}
-
-
void MainDialog::OnCompare(wxCommandEvent &event)
{
//PERF_START;
-
clearStatusBar();
wxBusyCursor dummy; //show hourglass cursor
- //1. prevent temporary memory peak by clearing old result list
- //2. ATTENTION: wxAPP->Yield() will be called in the following!
- // when comparing there will be a mismatch "gridDataView <-> currentGridData": make sure gridDataView does NOT access currentGridData!!!
- currentGridData.clear();
+ //prevent temporary memory peak by clearing old result list
+ gridDataView->clearAllRows();
updateGuiGrid(); //refresh GUI grid
bool aborted = false;
@@ -2346,29 +2355,22 @@ void MainDialog::OnCompare(wxCommandEvent &event)
{ //class handling status display and error messages
CompareStatusHandler statusHandler(this);
- //prepare filter
- std::auto_ptr<FreeFileSync::FilterProcess> filterInstance(NULL);
- if (currentCfg.mainCfg.filterIsActive)
- filterInstance.reset(new FreeFileSync::FilterProcess(currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter));
-
//begin comparison
- FreeFileSync::CompareProcess comparison(globalSettings.traverseDirectorySymlinks,
- globalSettings.fileTimeTolerance,
+ FreeFileSync::CompareProcess comparison(currentCfg.mainCfg.hidden.traverseDirectorySymlinks,
+ currentCfg.mainCfg.hidden.fileTimeTolerance,
globalSettings.ignoreOneHourDiff,
- globalSettings.warnings,
- filterInstance.get(),
+ globalSettings.optDialogs,
&statusHandler);
- comparison.startCompareProcess(getFolderPairs(),
- currentCfg.mainCfg.compareVar,
- currentCfg.mainCfg.syncConfiguration,
- currentGridData);
+ //technical representation of comparison data
+ FreeFileSync::FolderComparison newCompareData;
- //if (output.size < 50000)
- statusHandler.updateStatusText(_("Sorting file list..."));
- statusHandler.forceUiRefresh(); //keep total number of scanned files up to date
+ comparison.startCompareProcess(
+ FreeFileSync::extractCompareCfg(getCurrentConfiguration().mainCfg), //call getCurrentCfg() to get current values for directory pairs!
+ currentCfg.mainCfg.compareVar,
+ newCompareData);
- gridDataView->sortView(GridView::SORT_BY_DIRECTORY, true, true);
+ gridDataView->setData(newCompareData); //newCompareData is invalidated after this call
}
catch (AbortThisProcess&)
{
@@ -2394,9 +2396,9 @@ void MainDialog::OnCompare(wxCommandEvent &event)
lastSortColumn = -1;
lastSortGrid = NULL;
- m_gridLeft->ClearSelection();
+ m_gridLeft-> ClearSelection();
m_gridMiddle->ClearSelection();
- m_gridRight->ClearSelection();
+ m_gridRight-> ClearSelection();
//add to folder history after successful comparison only
addLeftFolderToHistory(m_directoryLeft->GetValue());
@@ -2416,8 +2418,8 @@ void MainDialog::updateGuiGrid()
updateGridViewData(); //update gridDataView and write status information
- //all three grids retrieve their data directly via gridDataView(which knows currentGridData)!!!
- //the only thing left to do is notify the grids to update their sizes (nr of rows), since this has to be communicated by the grids via messages
+ //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();
@@ -2454,7 +2456,7 @@ void MainDialog::updateGuiGrid()
void MainDialog::calculatePreview()
{
//update preview of bytes to be transferred:
- const SyncStatistics st(currentGridData);
+ const SyncStatistics st(gridDataView->getDataTentative());
const wxString toCreate = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(st.getCreate()));
const wxString toUpdate = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(st.getOverwrite()));
const wxString toDelete = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(st.getDelete()));
@@ -2476,16 +2478,15 @@ void MainDialog::OnSwitchView(wxCommandEvent& event)
void MainDialog::OnSyncSettings(wxCommandEvent& event)
{
- SyncCfgDialog* syncDlg = new SyncCfgDialog(this, currentGridData, currentCfg.mainCfg, currentCfg.ignoreErrors);
- if (syncDlg->ShowModal() == SyncCfgDialog::BUTTON_OKAY)
+ 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)
{
- //update sync variant name
- m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + currentCfg.mainCfg.syncConfiguration.getVariantName() + wxT(")"));
- bSizer6->Layout(); //adapt layout for variant text
-
- redetermineSyncDirection(currentCfg.mainCfg.syncConfiguration, currentGridData);
-
- updateGuiGrid();
+ updateSyncConfig();
}
}
@@ -2494,7 +2495,11 @@ void MainDialog::OnCmpSettings(wxCommandEvent& event)
{
CompareVariant newCmpVariant = currentCfg.mainCfg.compareVar;
- CompareCfgDialog* syncDlg = new CompareCfgDialog(this, newCmpVariant);
+ //show window right next to the compare-config button
+ wxPoint windowPos = m_bpButtonCmpConfig->GetScreenPosition();
+ windowPos.x += m_bpButtonCmpConfig->GetSize().GetWidth() + 5;
+
+ CompareCfgDialog* syncDlg = new CompareCfgDialog(this, windowPos, newCmpVariant);
if (syncDlg->ShowModal() == CompareCfgDialog::BUTTON_OKAY)
{
if (currentCfg.mainCfg.compareVar != newCmpVariant)
@@ -2509,7 +2514,7 @@ void MainDialog::OnCmpSettings(wxCommandEvent& event)
syncPreview.enableSynchronization(false);
//clear grids
- currentGridData.clear();
+ gridDataView->clearAllRows();
updateGuiGrid();
m_buttonCompare->SetFocus();
@@ -2523,24 +2528,24 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
if (syncPreview.synchronizationIsEnabled())
{
//show sync preview screen
- if (globalSettings.gui.showSummaryBeforeSync)
+ if (globalSettings.optDialogs.showSummaryBeforeSync)
{
bool dontShowAgain = false;
SyncPreviewDlg* preview = new SyncPreviewDlg(
this,
- currentCfg.mainCfg.syncConfiguration.getVariantName(),
- FreeFileSync::SyncStatistics(currentGridData),
+ getCurrentConfiguration().mainCfg.getSyncVariantName(),
+ FreeFileSync::SyncStatistics(gridDataView->getDataTentative()),
dontShowAgain);
if (preview->ShowModal() != SyncPreviewDlg::BUTTON_START)
return;
- globalSettings.gui.showSummaryBeforeSync = !dontShowAgain;
+ globalSettings.optDialogs.showSummaryBeforeSync = !dontShowAgain;
}
//check if there are files/folders to be sync'ed at all
- if (!synchronizationNeeded(currentGridData))
+ if (!synchronizationNeeded(gridDataView->getDataTentative()))
{
wxMessageBox(_("Nothing to synchronize according to configuration!"), _("Information"), wxICON_WARNING);
return;
@@ -2548,62 +2553,60 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
wxBusyCursor dummy; //show hourglass cursor
- //ATTENTION: wxAPP->Yield() will be called in the following!
- //when sync'ing there will be a mismatch "gridDataView <-> currentGridData": make sure gridDataView does NOT access currentGridData!!!
- gridDataView->clearView();
-
clearStatusBar();
try
{
+ //PERF_START;
+
//class handling status updates and error messages
SyncStatusHandler statusHandler(this, currentCfg.ignoreErrors);
- //start synchronization and return elements that were not sync'ed in currentGridData
+ //start synchronization and mark all elements processed
FreeFileSync::SyncProcess synchronization(
- currentCfg.mainCfg.handleDeletion,
- currentCfg.mainCfg.customDeletionDirectory,
- globalSettings.copyFileSymlinks,
- globalSettings.traverseDirectorySymlinks,
- globalSettings.warnings,
+ currentCfg.mainCfg.hidden.copyFileSymlinks,
+ currentCfg.mainCfg.hidden.traverseDirectorySymlinks,
+ globalSettings.optDialogs,
+ currentCfg.mainCfg.hidden.verifyFileCopy,
&statusHandler);
- synchronization.startSynchronizationProcess(currentGridData);
+ 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);
}
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();
- //show remaining files that have not been processed: put DIRECTLY after startSynchronizationProcess() and DON'T call any wxWidgets functions
- //in between! Else CustomGrid might access obsolete data entries in currentGridData!
updateGuiGrid();
- m_gridLeft->ClearSelection();
+ m_gridLeft-> ClearSelection();
m_gridMiddle->ClearSelection();
- m_gridRight->ClearSelection();
-
- if (!gridDataView->refGridIsEmpty())
- pushStatusInformation(_("Not all items have been synchronized! Have a look at the list."));
- else
- {
- pushStatusInformation(_("All items have been synchronized!"));
- syncPreview.enableSynchronization(false);
- }
+ m_gridRight-> ClearSelection();
}
}
void MainDialog::OnLeftGridDoubleClick(wxGridEvent& event)
{
- openWithFileManager(event.GetRow(), true);
- event.Skip();
+ if (!globalSettings.gui.externelApplications.empty())
+ openExternalApplication(event.GetRow(), true, globalSettings.gui.externelApplications[0].second);
+ // event.Skip();
}
void MainDialog::OnRightGridDoubleClick(wxGridEvent& event)
{
- openWithFileManager(event.GetRow(), false);
- event.Skip();
+ if (!globalSettings.gui.externelApplications.empty())
+ openExternalApplication(event.GetRow(), false, globalSettings.gui.externelApplications[0].second);
+// event.Skip();
}
@@ -2743,27 +2746,38 @@ void MainDialog::OnSwapSides(wxCommandEvent& event)
m_directoryRight->SetValue(leftDir);
//additional pairs
- wxString tmp;
for (std::vector<FolderPairPanel*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
{
FolderPairPanel* dirPair = *i;
- tmp = dirPair->m_directoryLeft->GetValue();
+ wxString tmp = dirPair->m_directoryLeft->GetValue();
dirPair->m_directoryLeft->SetValue(dirPair->m_directoryRight->GetValue());
dirPair->m_directoryRight->SetValue(tmp);
}
//swap view filter
- std::swap(gridDataView->leftOnlyFilesActive, gridDataView->rightOnlyFilesActive);
- std::swap(gridDataView->leftNewerFilesActive, gridDataView->rightNewerFilesActive);
+ 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);
+
- std::swap(gridDataView->syncCreateLeftActive, gridDataView->syncCreateRightActive);
- std::swap(gridDataView->syncDirLeftActive, gridDataView->syncDirRightActive);
- std::swap(gridDataView->syncDeleteLeftActive, gridDataView->syncDeleteRightActive);
+ tmp = m_bpButtonSyncCreateLeft->isActive();
+ m_bpButtonSyncCreateLeft->setActive(m_bpButtonSyncCreateRight->isActive());
+ m_bpButtonSyncCreateRight->setActive(tmp);
- updateViewFilterButtons();
+ 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(currentCfg.mainCfg.syncConfiguration, currentGridData);
+ FreeFileSync::swapGrids2(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
updateGuiGrid();
event.Skip();
}
@@ -2771,103 +2785,120 @@ void MainDialog::OnSwapSides(wxCommandEvent& event)
void MainDialog::updateGridViewData()
{
- const GridView::StatusInfo result = gridDataView->update(currentCfg.hideFilteredElements, syncPreview.previewIsEnabled());
-
- //hide or enable view filter buttons
-
- //comparison result view buttons
- if (result.existsLeftOnly)
- m_bpButtonLeftOnly->Show();
- else
- m_bpButtonLeftOnly->Hide();
-
- if (result.existsRightOnly)
- m_bpButtonRightOnly->Show();
- else
- m_bpButtonRightOnly->Hide();
-
- if (result.existsLeftNewer)
- m_bpButtonLeftNewer->Show();
- else
- m_bpButtonLeftNewer->Hide();
-
- if (result.existsRightNewer)
- m_bpButtonRightNewer->Show();
- else
- m_bpButtonRightNewer->Hide();
+ unsigned int filesOnLeftView = 0;
+ unsigned int foldersOnLeftView = 0;
+ unsigned int filesOnRightView = 0;
+ unsigned int foldersOnRightView = 0;
+ wxULongLong filesizeLeftView;
+ wxULongLong filesizeRightView;
- if (result.existsDifferent)
- m_bpButtonDifferent->Show();
- else
- m_bpButtonDifferent->Hide();
-
- if (result.existsEqual)
- m_bpButtonEqual->Show();
- else
- m_bpButtonEqual->Hide();
-
- if (result.existsConflict)
- m_bpButtonConflict->Show();
- else
- m_bpButtonConflict->Hide();
-
- //sync preview buttons
- if (result.existsSyncCreateLeft)
- m_bpButtonSyncCreateLeft->Show();
- else
- m_bpButtonSyncCreateLeft->Hide();
-
- if (result.existsSyncCreateRight)
- m_bpButtonSyncCreateRight->Show();
- else
- m_bpButtonSyncCreateRight->Hide();
+ //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);
- if (result.existsSyncDeleteLeft)
- m_bpButtonSyncDeleteLeft->Show();
- else
- m_bpButtonSyncDeleteLeft->Hide();
+ 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 (result.existsSyncDeleteRight)
- m_bpButtonSyncDeleteRight->Show();
- else
- m_bpButtonSyncDeleteRight->Hide();
- if (result.existsSyncDirLeft)
- m_bpButtonSyncDirLeft->Show();
- else
- m_bpButtonSyncDirLeft->Hide();
- if (result.existsSyncDirRight)
- m_bpButtonSyncDirRight->Show();
- else
- m_bpButtonSyncDirRight->Hide();
+ 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_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_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_bpButtonConflict-> IsShown())
+ {
+ m_panel112->Show();
+ m_panel112->Layout();
+ }
+ else
+ m_panel112->Hide();
- if (result.existsSyncDirNone)
- m_bpButtonSyncDirNone->Show();
- else
- m_bpButtonSyncDirNone->Hide();
-
-
- if ( result.existsLeftOnly ||
- result.existsRightOnly ||
- result.existsLeftNewer ||
- result.existsRightNewer ||
- result.existsDifferent ||
- result.existsEqual ||
- result.existsConflict ||
- result.existsSyncCreateLeft ||
- result.existsSyncCreateRight ||
- result.existsSyncDeleteLeft ||
- result.existsSyncDeleteRight ||
- result.existsSyncDirLeft ||
- result.existsSyncDirRight ||
- result.existsSyncDirNone)
- {
- m_panel112->Show();
- m_panel112->Layout();
}
else
- m_panel112->Hide();
+ {
+ 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_panel112->Show();
+ m_panel112->Layout();
+ }
+ else
+ m_panel112->Hide();
+ }
+
bSizer3->Layout();
@@ -2884,41 +2915,41 @@ void MainDialog::updateGridViewData()
//format numbers to text:
//show status information on "root" level.
- if (result.foldersOnLeftView)
+ if (foldersOnLeftView)
{
- if (result.foldersOnLeftView == 1)
+ if (foldersOnLeftView == 1)
statusLeftNew += _("1 directory");
else
{
- wxString folderCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(result.foldersOnLeftView));
+ wxString folderCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(foldersOnLeftView));
wxString outputString = _("%x directories");
outputString.Replace(wxT("%x"), folderCount, false);
statusLeftNew += outputString;
}
- if (result.filesOnLeftView)
+ if (filesOnLeftView)
statusLeftNew += wxT(", ");
}
- if (result.filesOnLeftView)
+ if (filesOnLeftView)
{
- if (result.filesOnLeftView == 1)
+ if (filesOnLeftView == 1)
statusLeftNew += _("1 file,");
else
{
- wxString fileCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(result.filesOnLeftView));
+ wxString fileCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(filesOnLeftView));
wxString outputString = _("%x files,");
outputString.Replace(wxT("%x"), fileCount, false);
statusLeftNew += outputString;
}
statusLeftNew += wxT(" ");
- statusLeftNew += FreeFileSync::formatFilesizeToShortString(result.filesizeLeftView);
+ statusLeftNew += FreeFileSync::formatFilesizeToShortString(filesizeLeftView);
}
- const wxString objectsView = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(gridDataView->elementsOnView()));
- if (result.objectsTotal == 1)
+ const wxString objectsView = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(gridDataView->rowsOnView()));
+ if (gridDataView->rowsTotal() == 1)
{
wxString outputString = _("%x of 1 row in view");
outputString.Replace(wxT("%x"), objectsView, false);
@@ -2926,7 +2957,7 @@ void MainDialog::updateGridViewData()
}
else
{
- const wxString objectsTotal = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(result.objectsTotal));
+ const wxString objectsTotal = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(gridDataView->rowsTotal()));
wxString outputString = _("%x of %y rows in view");
outputString.Replace(wxT("%x"), objectsView, false);
@@ -2934,30 +2965,30 @@ void MainDialog::updateGridViewData()
statusMiddleNew = outputString;
}
- if (result.foldersOnRightView)
+ if (foldersOnRightView)
{
- if (result.foldersOnRightView == 1)
+ if (foldersOnRightView == 1)
statusRightNew += _("1 directory");
else
{
- wxString folderCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(result.foldersOnRightView));
+ wxString folderCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(foldersOnRightView));
wxString outputString = _("%x directories");
outputString.Replace(wxT("%x"), folderCount, false);
statusRightNew += outputString;
}
- if (result.filesOnRightView)
+ if (filesOnRightView)
statusRightNew += wxT(", ");
}
- if (result.filesOnRightView)
+ if (filesOnRightView)
{
- if (result.filesOnRightView == 1)
+ if (filesOnRightView == 1)
statusRightNew += _("1 file,");
else
{
- wxString fileCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(result.filesOnRightView));
+ wxString fileCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(filesOnRightView));
wxString outputString = _("%x files,");
outputString.Replace(wxT("%x"), fileCount, false);
@@ -2965,7 +2996,7 @@ void MainDialog::updateGridViewData()
}
statusRightNew += wxT(" ");
- statusRightNew += FreeFileSync::formatFilesizeToShortString(result.filesizeRightView);
+ statusRightNew += FreeFileSync::formatFilesizeToShortString(filesizeRightView);
}
@@ -2983,93 +3014,88 @@ void MainDialog::updateGridViewData()
void MainDialog::OnAddFolderPair(wxCommandEvent& event)
{
- std::vector<FolderPair> newPairs;
- newPairs.push_back(FolderPair(m_directoryLeft ->GetValue().c_str(),
- m_directoryRight->GetValue().c_str()));
+ wxWindowUpdateLocker dummy(this); //avoid display distortion
+
+ std::vector<FolderPairEnh> newPairs;
+ newPairs.push_back(
+ FolderPairEnh(Zstring(),
+ Zstring(),
+ boost::shared_ptr<AlternateSyncConfig>(),
+ boost::shared_ptr<AlternateFilter>()));
- addFolderPair(newPairs, true); //add pair in front of additonal pairs
+ addFolderPair(newPairs, false); //add pair at the end of additional pairs
- //clear existing pairs
- FreeFileSync::setDirectoryName(wxEmptyString, m_directoryLeft, m_dirPickerLeft);
- FreeFileSync::setDirectoryName(wxEmptyString, m_directoryRight, m_dirPickerRight);
+ FreeFileSync::scrollToBottom(m_scrolledWindowFolderPairs);
//disable the sync button
syncPreview.enableSynchronization(false);
//clear grids
- currentGridData.clear();
+ gridDataView->clearAllRows();
updateGuiGrid();
}
-void MainDialog::OnRemoveFolderPair(wxCommandEvent& event)
+void MainDialog::updateFilterConfig(bool activateFilter) //true: activate filter false: stay as it is
{
- //find folder pair originating the event
- const wxObject* const eventObj = event.GetEventObject();
- for (std::vector<FolderPairPanel*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i)
+ if (activateFilter)
{
- if (eventObj == static_cast<wxObject*>((*i)->m_bpButtonRemovePair))
+ //activate filter (if not yet active)
+ if (!currentCfg.mainCfg.filterIsActive)
{
- removeAddFolderPair(i - additionalFolderPairs.begin());
-
- //disable the sync button
- syncPreview.enableSynchronization(false);
-
- //clear grids
- currentGridData.clear();
- updateGuiGrid();
- return;
+ currentCfg.mainCfg.filterIsActive = true;
+ updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive);
}
}
-}
-
-void MainDialog::OnRemoveTopFolderPair(wxCommandEvent& event)
-{
- if (additionalFolderPairs.size() > 0)
+ if (currentCfg.mainCfg.filterIsActive)
{
- const wxString leftDir = (*additionalFolderPairs.begin())->m_directoryLeft->GetValue().c_str();
- const wxString rightDir = (*additionalFolderPairs.begin())->m_directoryRight->GetValue().c_str();
-
- FreeFileSync::setDirectoryName(leftDir, m_directoryLeft, m_dirPickerLeft);
- FreeFileSync::setDirectoryName(rightDir, m_directoryRight, m_dirPickerRight);
+ applyFiltering(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
+ refreshGridAfterFilterChange(400);
+ }
+ else
+ {
+ FilterProcess::setActiveStatus(true, gridDataView->getDataTentative());
+ refreshGridAfterFilterChange(0);
+ }
+}
- removeAddFolderPair(0); //remove first of additional folder pairs
- //disable the sync button
- syncPreview.enableSynchronization(false);
+void MainDialog::updateSyncConfig()
+{
+ //update sync variant name
+ m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getCurrentConfiguration().mainCfg.getSyncVariantName() + wxT(")"));
+ bSizer6->Layout(); //adapt layout for variant text
- //clear grids
- currentGridData.clear();
- updateGuiGrid();
- }
+ FreeFileSync::redetermineSyncDirection(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative());
+ updateGuiGrid();
}
-void scrollToBottom(wxScrolledWindow* scrWindow)
+void MainDialog::OnRemoveFolderPair(wxCommandEvent& event)
{
- int height = 0;
- scrWindow->GetClientSize(NULL, &height);
+ 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 == static_cast<wxObject*>((*i)->m_bpButtonRemovePair))
+ {
+ removeAddFolderPair(i - additionalFolderPairs.begin());
- int pixelPerLine = 0;
- scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine);
+ //disable the sync button
+ syncPreview.enableSynchronization(false);
- if (height > 0 && pixelPerLine > 0)
- {
- const int scrollLinesTotal = scrWindow->GetScrollLines(wxVERTICAL);
- const int scrollLinesOnScreen = height / pixelPerLine;
- const int scrollPosBottom = scrollLinesTotal - scrollLinesOnScreen;
+ //clear grids
+ gridDataView->clearAllRows();
- if (0 <= scrollPosBottom)
- scrWindow->Scroll(0, scrollPosBottom);
- }
+ updateSyncConfig();
+ return;
+ }
}
const size_t MAX_ADD_FOLDER_PAIRS = 5;
-void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs, bool addFront)
+void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool addFront)
{
if (newPairs.size() == 0)
return;
@@ -3077,12 +3103,13 @@ void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs, bool add
wxWindowUpdateLocker dummy(this); //avoid display distortion
int pairHeight = 0;
- for (std::vector<FolderPair>::const_iterator i = newPairs.begin(); i != newPairs.end(); ++i)
+ for (std::vector<FolderPairEnh>::const_iterator i = newPairs.begin(); i != newPairs.end(); ++i)
{
//add new folder pair
- FolderPairPanel* newPair = new FolderPairPanel(m_scrolledWindowFolderPairs);
- newPair->m_bitmap23->SetBitmap(*GlobalResources::getInstance().bitmapLink);
- newPair->m_bpButtonRemovePair->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
+ 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();
@@ -3104,21 +3131,22 @@ void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs, bool add
pairHeight = newPair->GetSize().GetHeight();
//register events
- newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), NULL, this );
+ newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), NULL, this);
//insert directory names
FreeFileSync::setDirectoryName(i->leftDirectory.c_str(), newPair->m_directoryLeft, newPair->m_dirPickerLeft);
FreeFileSync::setDirectoryName(i->rightDirectory.c_str(), newPair->m_directoryRight, newPair->m_dirPickerRight);
+
+ //set alternate configuration
+ newPair->altSyncConfig = i->altSyncConfig;
+ newPair->altFilter = i->altFilter;
+ newPair->updateAltButtonColor();
}
//set size of scrolled window
const int 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 * visiblePairs));
- //adapt delete top folder pair button
- m_bpButtonRemoveTopPair->Show();
- m_panelTopRight->Layout();
-
//update controls
m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size
m_scrolledWindowFolderPairs->Layout(); //adjust stuff inside scrolled window
@@ -3129,11 +3157,11 @@ void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs, bool add
}
-void MainDialog::removeAddFolderPair(const int pos)
+void MainDialog::removeAddFolderPair(const unsigned int pos)
{
wxWindowUpdateLocker dummy(this); //avoid display distortion
- if (0 <= pos && pos < int(additionalFolderPairs.size()))
+ if (pos < additionalFolderPairs.size())
{
//remove folder pairs from window
FolderPairPanel* pairToDelete = additionalFolderPairs[pos];
@@ -3148,13 +3176,6 @@ void MainDialog::removeAddFolderPair(const int pos)
if (additionalRows <= MAX_ADD_FOLDER_PAIRS) //up to MAX_ADD_FOLDER_PAIRS additional pairs shall be shown
m_scrolledWindowFolderPairs->SetMinSize(wxSize(-1, pairHeight * additionalRows));
- //adapt delete top folder pair button
- if (additionalFolderPairs.size() == 0)
- {
- m_bpButtonRemoveTopPair->Hide();
- m_panelTopRight->Layout();
- }
-
//update controls
m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size
m_scrolledWindowFolderPairs->Layout(); //adjust stuff inside scrolled window
@@ -3170,9 +3191,6 @@ void MainDialog::clearAddFolderPairs()
additionalFolderPairs.clear();
bSizerAddFolderPairs->Clear(true);
- m_bpButtonRemoveTopPair->Hide();
- m_panelTopRight->Layout();
-
m_scrolledWindowFolderPairs->SetMinSize(wxSize(-1, 0));
bSizer1->Layout();
}
@@ -3209,25 +3227,71 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
}
}
- //begin work
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_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+= ';';
+ exportString += m_gridLeft->GetCellValue(i, k);
+ exportString += ';';
}
for (int k = 0; k < m_gridMiddle->GetNumberCols(); ++k)
{
- exportString+= m_gridMiddle->GetCellValue(i, k);
- exportString+= ';';
+ exportString += m_gridMiddle->GetCellValue(i, k);
+ exportString += ';';
}
for (int k = 0; k < m_gridRight->GetNumberCols(); ++k)
{
- exportString+= m_gridRight->GetCellValue(i, k);
+ exportString += m_gridRight->GetCellValue(i, k);
if (k != m_gridRight->GetNumberCols() - 1)
exportString+= ';';
}
@@ -3252,10 +3316,10 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
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 = currentCfg.mainCfg;
- batchCfg.directoryPairs = getFolderPairs();
- batchCfg.silent = false;
+ batchCfg.mainCfg = currCfg.mainCfg;
if (currentCfg.ignoreErrors)
batchCfg.handleError = xmlAccess::ON_ERROR_IGNORE;
@@ -3307,7 +3371,10 @@ void MainDialog::OnMenuAbout(wxCommandEvent& event)
void MainDialog::OnMenuQuit(wxCommandEvent& event)
{
- requestShutdown();
+ if (!saveOldConfig()) //notify user about changed settings
+ return;
+
+ Destroy();
}
//#########################################################################################################
@@ -3387,7 +3454,7 @@ void MainDialog::SyncPreview::enableSynchronization(bool value)
else
{
synchronizationEnabled = false;
- mainDlg_->m_buttonStartSync->SetForegroundColour(wxColor(94, 94, 94)); //grey
+ 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().bitmapSyncDisabled);
}
}
bgstack15