summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/CustomGrid.cpp80
-rw-r--r--library/CustomGrid.h11
-rw-r--r--library/fileHandling.cpp218
-rw-r--r--library/fileHandling.h37
-rw-r--r--library/globalFunctions.cpp4
-rw-r--r--library/globalFunctions.h30
-rw-r--r--library/misc.cpp4
-rw-r--r--library/processXml.cpp40
-rw-r--r--library/processXml.h14
-rw-r--r--library/resources.cpp15
-rw-r--r--library/resources.h13
-rw-r--r--library/sorting.h30
-rw-r--r--library/statusHandler.h14
13 files changed, 418 insertions, 92 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp
index 3fdc5967..1abf73a7 100644
--- a/library/CustomGrid.cpp
+++ b/library/CustomGrid.cpp
@@ -114,9 +114,9 @@ public:
switch (col)
{
case 0: //filename
- return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::fileNameSeparator);
+ return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
case 1: //relative path
- return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::fileNameSeparator);
+ return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
case 2: //file size
return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrLeft.fileSize.ToString());
case 3: //date
@@ -148,9 +148,9 @@ public:
switch (col)
{
case 0: //filename
- return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::fileNameSeparator);
+ return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
case 1: //relative path
- return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::fileNameSeparator);
+ return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
case 2: //file size
return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrRight.fileSize.ToString());
case 3: //date
@@ -319,7 +319,7 @@ CustomGrid::CustomGrid(wxWindow *parent,
const wxString& name) :
wxGrid(parent, id, pos, size, style, name),
scrollbarsEnabled(true),
- m_grid1(0), m_grid2(0), m_grid3(0),
+ m_gridLeft(0), m_gridRight(0), m_gridMiddle(0),
gridDataTable(0),
currentSortColumn(-1),
sortMarker(0)
@@ -357,39 +357,39 @@ void CustomGrid::SetScrollbar(int orientation, int position, int thumbSize, int
//ensure that all grids are properly aligned: add some extra window space to grids that have no horizontal scrollbar
-void CustomGrid::adjustGridHeights() //m_grid1, m_grid2, m_grid3 are not NULL in this context
+void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are not NULL in this context
{
int y1 = 0;
int y2 = 0;
int y3 = 0;
int dummy = 0;
- m_grid1->GetViewStart(&dummy, &y1);
- m_grid2->GetViewStart(&dummy, &y2);
- m_grid3->GetViewStart(&dummy, &y3);
+ m_gridLeft->GetViewStart(&dummy, &y1);
+ m_gridRight->GetViewStart(&dummy, &y2);
+ m_gridMiddle->GetViewStart(&dummy, &y3);
if (y1 != y2 || y2 != y3)
{
int yMax = max(y1, max(y2, y3));
if (leadingPanel == 1) //do not handle case (y1 == yMax) here!!! Avoid back coupling!
- m_grid1->SetMargins(0, 0);
+ m_gridLeft->SetMargins(0, 0);
else if (y1 < yMax)
- m_grid1->SetMargins(0, 50);
+ m_gridLeft->SetMargins(0, 50);
if (leadingPanel == 2)
- m_grid2->SetMargins(0, 0);
+ m_gridRight->SetMargins(0, 0);
else if (y2 < yMax)
- m_grid2->SetMargins(0, 50);
+ m_gridRight->SetMargins(0, 50);
if (leadingPanel == 3)
- m_grid3->SetMargins(0, 0);
+ m_gridMiddle->SetMargins(0, 0);
else if (y3 < yMax)
- m_grid3->SetMargins(0, 50);
+ m_gridMiddle->SetMargins(0, 50);
- m_grid1->ForceRefresh();
- m_grid2->ForceRefresh();
- m_grid3->ForceRefresh();
+ m_gridLeft->ForceRefresh();
+ m_gridRight->ForceRefresh();
+ m_gridMiddle->ForceRefresh();
}
}
@@ -400,47 +400,47 @@ void CustomGrid::DoPrepareDC(wxDC& dc)
wxScrollHelper::DoPrepareDC(dc);
int x, y = 0;
- if (leadingPanel == 1 && this == m_grid1) //avoid back coupling
+ if (leadingPanel == 1 && this == m_gridLeft) //avoid back coupling
{
GetViewStart(&x, &y);
- m_grid2->Scroll(x, y);
- m_grid3->Scroll(-1, y); //scroll in y-direction only
- adjustGridHeights(); //keep here to ensure m_grid1, m_grid2, m_grid3 != NULL
+ m_gridRight->Scroll(x, y);
+ m_gridMiddle->Scroll(-1, y); //scroll in y-direction only
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
}
- else if (leadingPanel == 2 && this == m_grid2) //avoid back coupling
+ else if (leadingPanel == 2 && this == m_gridRight) //avoid back coupling
{
GetViewStart(&x, &y);
- m_grid1->Scroll(x, y);
- m_grid3->Scroll(-1, y);
- adjustGridHeights(); //keep here to ensure m_grid1, m_grid2, m_grid3 != NULL
+ m_gridLeft->Scroll(x, y);
+ m_gridMiddle->Scroll(-1, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
}
- else if (leadingPanel == 3 && this == m_grid3) //avoid back coupling
+ else if (leadingPanel == 3 && this == m_gridMiddle) //avoid back coupling
{
GetViewStart(&x, &y);
- m_grid1->Scroll(-1, y);
- m_grid2->Scroll(-1, y);
- adjustGridHeights(); //keep here to ensure m_grid1, m_grid2, m_grid3 != NULL
+ m_gridLeft->Scroll(-1, y);
+ m_gridRight->Scroll(-1, y);
+ adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL
}
}
//these classes will scroll together, hence the name ;)
-void CustomGrid::setScrollFriends(CustomGrid* grid1, CustomGrid* grid2, CustomGrid* grid3)
+void CustomGrid::setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle)
{
- assert(grid1);
- assert(grid2);
- assert(grid3);
+ assert(gridLeft);
+ assert(gridRight);
+ assert(gridMiddle);
- m_grid1 = grid1;
- m_grid2 = grid2;
- m_grid3 = grid3;
+ m_gridLeft = gridLeft;
+ m_gridRight = gridRight;
+ m_gridMiddle = gridMiddle;
assert(gridDataTable);
- if (this == m_grid1)
+ if (this == m_gridLeft)
gridDataTable->SetGridIdentifier(1);
- else if (this == m_grid2)
+ else if (this == m_gridRight)
gridDataTable->SetGridIdentifier(2);
- else if (this == m_grid3)
+ else if (this == m_gridMiddle)
gridDataTable->SetGridIdentifier(3);
else
assert (false);
diff --git a/library/CustomGrid.h b/library/CustomGrid.h
index 8f22275b..3547b090 100644
--- a/library/CustomGrid.h
+++ b/library/CustomGrid.h
@@ -5,7 +5,8 @@
#include <wx/grid.h>
#include "../FreeFileSync.h"
-using namespace std;
+using namespace FreeFileSync;
+
class CustomGridTableBase;
@@ -35,7 +36,7 @@ public:
//this method is called when grid view changes: useful for parallel updating of multiple grids
void DoPrepareDC(wxDC& dc);
- void setScrollFriends(CustomGrid* grid1, CustomGrid* grid2, CustomGrid* grid3);
+ void setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle);
void setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData);
@@ -51,9 +52,9 @@ private:
bool scrollbarsEnabled;
- CustomGrid* m_grid1;
- CustomGrid* m_grid2;
- CustomGrid* m_grid3;
+ CustomGrid* m_gridLeft;
+ CustomGrid* m_gridRight;
+ CustomGrid* m_gridMiddle;
CustomGridTableBase* gridDataTable;
diff --git a/library/fileHandling.cpp b/library/fileHandling.cpp
new file mode 100644
index 00000000..e46a2b69
--- /dev/null
+++ b/library/fileHandling.cpp
@@ -0,0 +1,218 @@
+#include "fileHandling.h"
+#include <wx/intl.h>
+#include <wx/msgdlg.h>
+#include "resources.h"
+
+#ifdef FFS_WIN
+#include <windows.h>
+#endif // FFS_WIN
+
+
+class RecycleBin
+{
+public:
+ RecycleBin() :
+ recycleBinAvailable(false)
+ {
+#ifdef FFS_WIN
+ recycleBinAvailable = true;
+#endif // FFS_WIN
+ }
+
+ ~RecycleBin() {}
+
+ bool recycleBinExists()
+ {
+ return recycleBinAvailable;
+ }
+
+ bool moveToRecycleBin(const wxString& filename)
+ {
+ if (!recycleBinAvailable) //this method should ONLY be called if recycle bin is available
+ throw RuntimeException(_("Initialization of Recycle Bin failed! It cannot be used!"));
+
+#ifdef FFS_WIN
+ wxString filenameDoubleNull = filename + wxChar(0);
+
+ SHFILEOPSTRUCT fileOp;
+ fileOp.hwnd = NULL;
+ fileOp.wFunc = FO_DELETE;
+ fileOp.pFrom = filenameDoubleNull.c_str();
+ fileOp.pTo = NULL;
+ fileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT;
+ fileOp.fAnyOperationsAborted = false;
+ fileOp.hNameMappings = NULL;
+ fileOp.lpszProgressTitle = NULL;
+
+ if (SHFileOperation(&fileOp //pointer to an SHFILEOPSTRUCT structure that contains information the function needs to carry out
+ ) != 0 || fileOp.fAnyOperationsAborted) return false;
+#else
+ assert(false);
+#endif
+
+ return true;
+ }
+
+private:
+ bool recycleBinAvailable;
+};
+
+//global instance of recycle bin
+RecycleBin recyclerInstance;
+
+
+bool FreeFileSync::recycleBinExists()
+{
+ return recyclerInstance.recycleBinExists();
+}
+
+
+inline
+bool moveToRecycleBin(const wxString& filename) throw(RuntimeException)
+{
+ return recyclerInstance.moveToRecycleBin(filename);
+}
+
+
+inline
+void FreeFileSync::removeFile(const wxString& filename, const bool useRecycleBin)
+{
+ if (!wxFileExists(filename)) return; //this is NOT an error situation: the manual deletion relies on it!
+
+ if (useRecycleBin)
+ {
+ if (!moveToRecycleBin(filename))
+ throw FileError(wxString(_("Error moving to recycle bin: ")) + wxT("\"") + filename + wxT("\""));
+ return;
+ }
+
+#ifdef FFS_WIN
+ if (!SetFileAttributes(
+ filename.c_str(), //address of filename
+ FILE_ATTRIBUTE_NORMAL //attributes to set
+ )) throw FileError(wxString(_("Error deleting file: ")) + wxT("\"") + filename + wxT("\""));
+#endif //FFS_WIN
+
+ if (!wxRemoveFile(filename))
+ throw FileError(wxString(_("Error deleting file: ")) + wxT("\"") + filename + wxT("\""));
+}
+
+
+void FreeFileSync::removeDirectory(const wxString& directory, const bool useRecycleBin)
+{
+ if (!wxDirExists(directory)) return; //this is NOT an error situation: the manual deletion relies on it!
+
+ if (useRecycleBin)
+ {
+ if (!moveToRecycleBin(directory))
+ throw FileError(wxString(_("Error moving to recycle bin: ")) + wxT("\"") + directory + wxT("\""));
+ return;
+ }
+
+ wxArrayString fileList;
+ wxArrayString dirList;
+
+ try
+ {
+ //should be executed in own scope so that directory access does not disturb deletion!
+ getAllFilesAndDirs(directory, fileList, dirList);
+ }
+ catch (const FileError& e)
+ {
+ throw FileError(wxString(_("Error deleting directory: ")) + wxT("\"") + directory + wxT("\""));
+ }
+
+ for (unsigned int j = 0; j < fileList.GetCount(); ++j)
+ removeFile(fileList[j], useRecycleBin);
+
+ dirList.Insert(directory, 0); //this directory will be deleted last
+
+ for (int j = int(dirList.GetCount()) - 1; j >= 0 ; --j)
+ {
+#ifdef FFS_WIN
+ if (!SetFileAttributes(
+ dirList[j].c_str(), // address of directory name
+ FILE_ATTRIBUTE_NORMAL // attributes to set
+ )) throw FileError(wxString(_("Error deleting directory: ")) + wxT("\"") + dirList[j] + wxT("\""));
+#endif // FFS_WIN
+
+ if (!wxRmdir(dirList[j]))
+ throw FileError(wxString(_("Error deleting directory: ")) + wxT("\"") + dirList[j] + wxT("\""));
+ }
+}
+
+
+void FreeFileSync::createDirectory(const wxString& directory, int level)
+{
+ if (wxDirExists(directory))
+ return;
+
+ if (level == 50) //catch endless loop
+ return;
+
+ //try to create directory
+ if (wxMkdir(directory))
+ return;
+
+ //if not successfull try to create containing folders first
+ wxString createFirstDir = wxDir(directory).GetName().BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+
+ //call function recursively
+ if (createFirstDir.IsEmpty()) return;
+ createDirectory(createFirstDir, level + 1);
+
+ //now creation should be possible
+ if (!wxMkdir(directory))
+ {
+ if (level == 0)
+ throw FileError(wxString(_("Error creating directory ")) + wxT("\"") + directory + wxT("\""));
+ }
+}
+
+
+class GetAllFilesSimple : public wxDirTraverser
+{
+public:
+ GetAllFilesSimple(wxArrayString& files, wxArrayString& subDirectories) :
+ m_files(files),
+ m_dirs(subDirectories) {}
+
+
+ wxDirTraverseResult OnDir(const wxString& dirname)
+ {
+ m_dirs.Add(dirname);
+ return wxDIR_CONTINUE;
+ }
+
+ wxDirTraverseResult OnFile(const wxString& filename)
+ {
+ m_files.Add(filename);
+ return wxDIR_CONTINUE;
+ }
+
+ wxDirTraverseResult OnOpenError(const wxString& openerrorname)
+ {
+ wxMessageBox(openerrorname, _("Error"));
+ return wxDIR_IGNORE;
+ }
+
+private:
+ wxArrayString& m_files;
+ wxArrayString& m_dirs;
+};
+
+
+void FreeFileSync::getAllFilesAndDirs(const wxString& sourceDir, wxArrayString& files, wxArrayString& directories) throw(FileError)
+{
+ files.Clear();
+ directories.Clear();
+
+ //get all files and directories from current directory (and subdirectories)
+ wxDir dir(sourceDir);
+ GetAllFilesSimple traverser(files, directories);
+
+ if (dir.Traverse(traverser) == (size_t)-1)
+ throw FileError(wxString(_("Error traversing directory ")) + wxT("\"") + sourceDir + wxT("\""));
+}
+
+
diff --git a/library/fileHandling.h b/library/fileHandling.h
new file mode 100644
index 00000000..a4f43391
--- /dev/null
+++ b/library/fileHandling.h
@@ -0,0 +1,37 @@
+#ifndef RECYCLER_H_INCLUDED
+#define RECYCLER_H_INCLUDED
+
+#include "globalFunctions.h"
+#include <wx/dir.h>
+
+
+class FileError //Exception class used to notify file/directory copy/delete errors
+{
+public:
+ FileError(const wxString& txt) : errorMessage(txt) {}
+
+ wxString show() const
+ {
+ return errorMessage;
+ }
+
+private:
+ wxString errorMessage;
+};
+
+
+namespace FreeFileSync
+{
+ void getAllFilesAndDirs(const wxString& sourceDir, wxArrayString& files, wxArrayString& directories) throw(FileError);
+
+ //recycler
+ bool recycleBinExists(); //test existence of Recycle Bin API on current system
+
+ //file handling
+ void removeDirectory(const wxString& directory, const bool useRecycleBin);
+ void removeFile(const wxString& filename, const bool useRecycleBin);
+ void createDirectory(const wxString& directory, int level = 0); //level is used internally only
+}
+
+
+#endif // RECYCLER_H_INCLUDED
diff --git a/library/globalFunctions.cpp b/library/globalFunctions.cpp
index 07c34af0..7e99e036 100644
--- a/library/globalFunctions.cpp
+++ b/library/globalFunctions.cpp
@@ -91,7 +91,7 @@ double globalFunctions::wxStringToDouble(const wxString& number)
wxString& globalFunctions::includeNumberSeparator(wxString& number)
{
for (int i = number.size() - 3; i > 0; i-= 3)
- number.insert(i, GlobalResources::thousandsSeparator);
+ number.insert(i, GlobalResources::THOUSANDS_SEPARATOR);
return number;
}
@@ -197,5 +197,5 @@ void DebugLog::write(const wxString& logText)
wxString getCodeLocation(const wxString file, const int line)
{
- return wxString(file).AfterLast(GlobalResources::fileNameSeparator) + wxT(", LINE ") + globalFunctions::numberToWxString(line) + wxT(" | ");
+ return wxString(file).AfterLast(GlobalResources::FILE_NAME_SEPARATOR) + wxT(", LINE ") + globalFunctions::numberToWxString(line) + wxT(" | ");
}
diff --git a/library/globalFunctions.h b/library/globalFunctions.h
index efbc42c7..add3c79d 100644
--- a/library/globalFunctions.h
+++ b/library/globalFunctions.h
@@ -4,6 +4,7 @@
#include <string>
#include <algorithm>
#include <vector>
+#include <set>
#include <wx/string.h>
#include <fstream>
#include <wx/stream.h>
@@ -106,4 +107,33 @@ private:
wxString errorMessage;
};
+
+//Note: the following lines are a performance optimization for deleting elements from a vector. It is incredibly faster to create a new
+//vector and leave specific elements out than to delete row by row and force recopying of most elements for each single deletion (linear vs quadratic runtime)
+template <class T>
+void removeRowsFromVector(vector<T>& grid, const set<int>& rowsToRemove)
+{
+ vector<T> temp;
+ int rowToSkip = -1; //keep it an INT!
+
+ set<int>::iterator rowToSkipIndex = rowsToRemove.begin();
+
+ if (rowToSkipIndex != rowsToRemove.end())
+ rowToSkip = *rowToSkipIndex;
+
+ for (int i = 0; i < int(grid.size()); ++i)
+ {
+ if (i != rowToSkip)
+ temp.push_back(grid[i]);
+ else
+ {
+ ++rowToSkipIndex;
+ if (rowToSkipIndex != rowsToRemove.end())
+ rowToSkip = *rowToSkipIndex;
+ }
+ }
+ grid.swap(temp);
+}
+
+
#endif // GLOBALFUNCTIONS_H_INCLUDED
diff --git a/library/misc.cpp b/library/misc.cpp
index 0a850805..f7aea8bd 100644
--- a/library/misc.cpp
+++ b/library/misc.cpp
@@ -129,8 +129,8 @@ void CustomLocale::setLanguage(const int language)
; //if languageFile is empty texts will be english per default
//these global variables need to be redetermined on language selection
- GlobalResources::decimalPoint = _(".");
- GlobalResources::thousandsSeparator = _(",");
+ GlobalResources::DECIMAL_POINT = _(".");
+ GlobalResources::THOUSANDS_SEPARATOR = _(",");
}
diff --git a/library/processXml.cpp b/library/processXml.cpp
index e87ae9de..2ce22b3e 100644
--- a/library/processXml.cpp
+++ b/library/processXml.cpp
@@ -144,15 +144,15 @@ XmlBatchConfig xmlAccess::readBatchConfig(const wxString& filename)
XmlGlobalSettings xmlAccess::readGlobalSettings()
{
//load XML
- XmlConfigInput inputFile(FreeFileSync::FfsGlobalSettingsFile, XML_GLOBAL_SETTINGS);
+ XmlConfigInput inputFile(FreeFileSync::GLOBAL_CONFIG_FILE, XML_GLOBAL_SETTINGS);
XmlGlobalSettings outputCfg;
if (!inputFile.loadedSuccessfully())
- throw FileError(wxString(_("Could not open configuration file ")) + wxT("\"") + FreeFileSync::FfsGlobalSettingsFile + wxT("\""));
+ throw FileError(wxString(_("Could not open configuration file ")) + wxT("\"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\""));
if (!inputFile.readXmlGlobalSettings(outputCfg))
- throw FileError(wxString(_("Error parsing configuration file ")) + wxT("\"") + FreeFileSync::FfsGlobalSettingsFile + wxT("\""));
+ throw FileError(wxString(_("Error parsing configuration file ")) + wxT("\"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\""));
return outputCfg;
}
@@ -184,12 +184,12 @@ void xmlAccess::writeBatchConfig(const wxString& filename, const XmlBatchConfig&
void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& inputCfg)
{
- XmlConfigOutput outputFile(FreeFileSync::FfsGlobalSettingsFile, XML_GLOBAL_SETTINGS);
+ XmlConfigOutput outputFile(FreeFileSync::GLOBAL_CONFIG_FILE, XML_GLOBAL_SETTINGS);
//populate and write XML tree
if ( !outputFile.writeXmlGlobalSettings(inputCfg) || //add GUI layout configuration settings
!outputFile.writeToFile()) //save XML
- throw FileError(wxString(_("Could not write configuration file ")) + wxT("\"") + FreeFileSync::FfsGlobalSettingsFile + wxT("\""));
+ throw FileError(wxString(_("Could not write configuration file ")) + wxT("\"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\""));
return;
}
@@ -365,8 +365,8 @@ bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, vector<Folder
mainCfg.excludeFilter = wxString::FromUTF8(tempString.c_str());
//###########################################################
//other
- if (!readXmlElementValue(mainCfg.useRecycleBin, miscSettings, "Recycler")) return false;
- if (!readXmlElementValue(mainCfg.continueOnError, miscSettings, "Continue")) return false;
+ readXmlElementValue(mainCfg.useRecycleBin, miscSettings, "UseRecycler");
+ readXmlElementValue(mainCfg.ignoreErrors, miscSettings, "IgnoreErrors");
return true;
}
@@ -388,8 +388,7 @@ bool XmlConfigInput::readXmlGuiConfig(XmlGuiConfig& outputCfg)
TiXmlElement* mainWindow = hRoot.FirstChild("GuiConfig").FirstChild("Windows").FirstChild("Main").ToElement();
if (mainWindow)
{
- if (!readXmlElementValue(outputCfg.hideFilteredElements, mainWindow, "HideFiltered"))
- outputCfg.hideFilteredElements = false;
+ readXmlElementValue(outputCfg.hideFilteredElements, mainWindow, "HideFiltered");
}
return true;
@@ -413,8 +412,7 @@ bool XmlConfigInput::readXmlBatchConfig(XmlBatchConfig& outputCfg)
if (batchConfig)
{
//read application window size and position
- if (!readXmlElementValue(outputCfg.silent, batchConfig, "Silent"))
- outputCfg.silent = false;
+ readXmlElementValue(outputCfg.silent, batchConfig, "Silent");
}
return true;
@@ -435,6 +433,14 @@ bool XmlConfigInput::readXmlGlobalSettings(XmlGlobalSettings& outputCfg)
//program language
readXmlElementValue(outputCfg.global.programLanguage, global, "Language");
+#ifdef FFS_WIN
+ //daylight saving time check
+ readXmlElementValue(outputCfg.global.dstCheckActive, global, "DaylightSavingTimeCheckActive");
+#endif
+
+ //folder dependency check
+ readXmlElementValue(outputCfg.global.folderDependCheckActive, global, "FolderDependencyCheckActive");
+
//gui specific global settings (optional)
TiXmlElement* mainWindow = hRoot.FirstChild("Gui").FirstChild("Windows").FirstChild("Main").ToElement();
if (mainWindow)
@@ -614,8 +620,8 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const
addXmlElement(filter, "Exclude", string((mainCfg.excludeFilter).ToUTF8()));
//other
- addXmlElement(miscSettings, "Recycler", mainCfg.useRecycleBin);
- addXmlElement(miscSettings, "Continue", mainCfg.continueOnError);
+ addXmlElement(miscSettings, "UseRecycler", mainCfg.useRecycleBin);
+ addXmlElement(miscSettings, "IgnoreErrors", mainCfg.ignoreErrors);
//###########################################################
return true;
@@ -679,6 +685,14 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg)
//program language
addXmlElement(global, "Language", inputCfg.global.programLanguage);
+#ifdef FFS_WIN
+ //daylight saving time check
+ addXmlElement(global, "DaylightSavingTimeCheckActive", inputCfg.global.dstCheckActive);
+#endif
+
+ //folder dependency check
+ addXmlElement(global, "FolderDependencyCheckActive", inputCfg.global.folderDependCheckActive);
+
//###################################################################
//write gui settings
TiXmlElement* guiLayout = new TiXmlElement("Gui");
diff --git a/library/processXml.h b/library/processXml.h
index abf5bfc6..e359e7b0 100644
--- a/library/processXml.h
+++ b/library/processXml.h
@@ -5,6 +5,8 @@
#include "tinyxml/tinyxml.h"
#include <wx/intl.h>
+using namespace FreeFileSync;
+
namespace xmlAccess
{
@@ -45,8 +47,18 @@ namespace xmlAccess
{
struct _Global
{
- _Global() : programLanguage(wxLocale::GetSystemLanguage()) {}
+ _Global() :
+ programLanguage(wxLocale::GetSystemLanguage()),
+#ifdef FFS_WIN
+ dstCheckActive(true),
+#endif
+ folderDependCheckActive(true) {}
+
int programLanguage;
+#ifdef FFS_WIN
+ bool dstCheckActive;
+#endif
+ bool folderDependCheckActive;
} global;
struct _Gui
diff --git a/library/resources.cpp b/library/resources.cpp
index 2156fd50..68eeb4d6 100644
--- a/library/resources.cpp
+++ b/library/resources.cpp
@@ -6,16 +6,16 @@
#include "globalFunctions.h"
#ifdef FFS_WIN
-const wxChar GlobalResources::fileNameSeparator = '\\';
+const wxChar GlobalResources::FILE_NAME_SEPARATOR = '\\';
#elif defined FFS_LINUX
-const wxChar GlobalResources::fileNameSeparator = '/';
+const wxChar GlobalResources::FILE_NAME_SEPARATOR = '/';
#else
assert(false);
#endif
//these two global variables are language-dependent => cannot be set statically! See CustomLocale
-const wxChar* GlobalResources::decimalPoint = wxEmptyString;
-const wxChar* GlobalResources::thousandsSeparator = wxEmptyString;
+const wxChar* GlobalResources::DECIMAL_POINT = wxEmptyString;
+const wxChar* GlobalResources::THOUSANDS_SEPARATOR = wxEmptyString;
GlobalResources globalResource; //init resources on program startup
@@ -84,6 +84,13 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("remove pair disabl.png")] = (bitmapRemoveFolderPairD = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("link.png")] = (bitmapLink = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("background.png")] = (bitmapBackground = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("compare_small.png")] = (bitmapCompareSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("sync_small.png")] = (bitmapSyncSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("clock_small.png")] = (bitmapClockSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("clock.png")] = (bitmapClock = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("filter.png")] = (bitmapFilter = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("batch.png")] = (bitmapBatch = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("batch_small.png")] = (bitmapBatchSmall = new wxBitmap(wxNullBitmap));
//init all the other resource files
animationMoney = new wxAnimation(wxNullAnimation);
diff --git a/library/resources.h b/library/resources.h
index c91b5cb7..d08ce0ce 100644
--- a/library/resources.h
+++ b/library/resources.h
@@ -16,11 +16,11 @@ public:
void load();
- static const wxChar fileNameSeparator;
+ static const wxChar FILE_NAME_SEPARATOR;
//language dependent global variables: need to be initialized by CustomLocale on program startup and language switch
- static const wxChar* decimalPoint;
- static const wxChar* thousandsSeparator;
+ static const wxChar* DECIMAL_POINT;
+ static const wxChar* THOUSANDS_SEPARATOR;
//image resource objects
wxBitmap* bitmapArrowLeft;
@@ -85,6 +85,13 @@ public:
wxBitmap* bitmapRemoveFolderPairD;
wxBitmap* bitmapLink;
wxBitmap* bitmapBackground;
+ wxBitmap* bitmapCompareSmall;
+ wxBitmap* bitmapSyncSmall;
+ wxBitmap* bitmapClockSmall;
+ wxBitmap* bitmapClock;
+ wxBitmap* bitmapFilter;
+ wxBitmap* bitmapBatch;
+ wxBitmap* bitmapBatchSmall;
wxAnimation* animationMoney;
wxAnimation* animationSync;
diff --git a/library/sorting.h b/library/sorting.h
index 0faa1bfd..bf643176 100644
--- a/library/sorting.h
+++ b/library/sorting.h
@@ -104,8 +104,8 @@ template <bool sortAscending, SideToSort side>
inline
bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b)
{
- const FileDescrLine* descrLineA;
- const FileDescrLine* descrLineB;
+ const FileDescrLine* descrLineA = NULL;
+ const FileDescrLine* descrLineB = NULL;
getDescrLine<side>(a, b, descrLineA, descrLineB);
//presort types: first files, then directories then empty rows
@@ -124,7 +124,7 @@ bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b)
int lenghtA = 0;
int lenghtB = 0;
- int pos = descrLineA->relativeName.Find(GlobalResources::fileNameSeparator, true); //start search beginning from end
+ int pos = descrLineA->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end
if (pos == wxNOT_FOUND)
{
stringA = descrLineA->relativeName.c_str();
@@ -136,7 +136,7 @@ bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b)
lenghtA = descrLineA->relativeName.Len() - (pos + 1);
}
- pos = descrLineB->relativeName.Find(GlobalResources::fileNameSeparator, true); //start search beginning from end
+ pos = descrLineB->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end
if (pos == wxNOT_FOUND)
{
stringB = descrLineB->relativeName.c_str();
@@ -149,7 +149,7 @@ bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b)
}
int rv = compareString(stringA, stringB, lenghtA, lenghtB);
- return sortAscending ? (rv == -1) : (rv != -1);
+ return sortAscending ? (rv == -1) : (rv == 1);
}
}
@@ -158,8 +158,8 @@ template <bool sortAscending, SideToSort side>
inline
bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b)
{
- const FileDescrLine* descrLineA;
- const FileDescrLine* descrLineB;
+ const FileDescrLine* descrLineA = NULL;
+ const FileDescrLine* descrLineB = NULL;
getDescrLine<side>(a, b, descrLineA, descrLineB);
//extract relative name and filename
@@ -174,7 +174,7 @@ bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b)
}
else if (descrLineA->objType == FileDescrLine::TYPE_FILE)
{
- relLenghtA = descrLineA->relativeName.Find(GlobalResources::fileNameSeparator, true); //start search beginning from end
+ relLenghtA = descrLineA->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end
if (relLenghtA == wxNOT_FOUND)
{
relLenghtA = 0;
@@ -203,7 +203,7 @@ bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b)
}
else if (descrLineB->objType == FileDescrLine::TYPE_FILE)
{
- relLenghtB = descrLineB->relativeName.Find(GlobalResources::fileNameSeparator, true); //start search beginning from end
+ relLenghtB = descrLineB->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end
if (relLenghtB == wxNOT_FOUND)
{
relLenghtB = 0;
@@ -223,7 +223,7 @@ bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b)
//compare relative names without filenames first
int rv = compareString(relStringA, relStringB, relLenghtA, relLenghtB);
if (rv != 0)
- return sortAscending ? (rv == -1) : (rv != -1);
+ return sortAscending ? (rv == -1) : (rv == 1);
else //compare the filenames
{
if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY) //directories shall appear before files
@@ -232,7 +232,7 @@ bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b)
return true;
rv = compareString(fileStringA, fileStringB, fileLengthA, fileLengthB);
- return sortAscending ? (rv == -1) : (rv != -1);
+ return sortAscending ? (rv == -1) : (rv == 1);
}
}
@@ -241,8 +241,8 @@ template <bool sortAscending, SideToSort side>
inline
bool sortByFileSize(const FileCompareLine& a, const FileCompareLine& b)
{
- const FileDescrLine* descrLineA;
- const FileDescrLine* descrLineB;
+ const FileDescrLine* descrLineA = NULL;
+ const FileDescrLine* descrLineB = NULL;
getDescrLine<side>(a, b, descrLineA, descrLineB);
//presort types: first files, then directories then empty rows
@@ -263,8 +263,8 @@ template <bool sortAscending, SideToSort side>
inline
bool sortByDate(const FileCompareLine& a, const FileCompareLine& b)
{
- const FileDescrLine* descrLineA;
- const FileDescrLine* descrLineB;
+ const FileDescrLine* descrLineA = NULL;
+ const FileDescrLine* descrLineB = NULL;
getDescrLine<side>(a, b, descrLineA, descrLineB);
return cmpString<sortAscending>(descrLineA->lastWriteTime, descrLineB->lastWriteTime);
diff --git a/library/statusHandler.h b/library/statusHandler.h
index ad4cb3a0..70f8c2d8 100644
--- a/library/statusHandler.h
+++ b/library/statusHandler.h
@@ -21,8 +21,8 @@ public:
enum Response
{
- CONTINUE_NEXT = -1,
- RETRY = -2
+ CONTINUE_NEXT = 10,
+ RETRY
};
virtual Response reportError(const wxString& text) = 0;
};
@@ -32,7 +32,7 @@ class StatusHandler
{
public:
StatusHandler() :
- abortionRequested(false) {}
+ abortRequested(false) {}
virtual ~StatusHandler() {}
//identifiers of different processes
@@ -47,7 +47,7 @@ public:
//these methods have to be implemented in the derived classes to handle error and status information
virtual void updateStatusText(const wxString& text) = 0;
virtual void initNewProcess(int objectsTotal, double dataTotal, Process processID) = 0; //informs about the total amount of data that will be processed from now on
- virtual void updateProcessedData(int objectsProcessed, double dataProcessed) = 0; //called periodically after data was processed
+ virtual void updateProcessedData(int objectsProcessed, double dataProcessed) = 0; //called periodically after data was processed
virtual ErrorHandler::Response reportError(const wxString& text) = 0;
//this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events
@@ -57,19 +57,19 @@ public:
if (updateUiIsAllowed()) //test if specific time span between ui updates is over
forceUiRefresh();
- if (abortionRequested && !asyncProcessActive)
+ if (abortRequested && !asyncProcessActive)
abortThisProcess(); //abort can be triggered by requestAbortion()
}
void requestAbortion() //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh()
{ //currently used by the UI status information screen, when button "Abort is pressed"
- abortionRequested = true;
+ abortRequested = true;
}
protected:
virtual void abortThisProcess() = 0;
- bool abortionRequested;
+ bool abortRequested;
};
bgstack15