diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/CustomGrid.cpp | 80 | ||||
-rw-r--r-- | library/CustomGrid.h | 11 | ||||
-rw-r--r-- | library/fileHandling.cpp | 218 | ||||
-rw-r--r-- | library/fileHandling.h | 37 | ||||
-rw-r--r-- | library/globalFunctions.cpp | 4 | ||||
-rw-r--r-- | library/globalFunctions.h | 30 | ||||
-rw-r--r-- | library/misc.cpp | 4 | ||||
-rw-r--r-- | library/processXml.cpp | 40 | ||||
-rw-r--r-- | library/processXml.h | 14 | ||||
-rw-r--r-- | library/resources.cpp | 15 | ||||
-rw-r--r-- | library/resources.h | 13 | ||||
-rw-r--r-- | library/sorting.h | 30 | ||||
-rw-r--r-- | library/statusHandler.h | 14 |
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; }; |