summaryrefslogtreecommitdiff
path: root/algorithm.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:00:17 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:00:17 +0200
commitfd0853d2623dd278b08288331ed42e3be59252fb (patch)
treea7645daeaef8bdbed064faf4eb88e72cee58726c /algorithm.cpp
parent2.1 (diff)
downloadFreeFileSync-fd0853d2623dd278b08288331ed42e3be59252fb.tar.gz
FreeFileSync-fd0853d2623dd278b08288331ed42e3be59252fb.tar.bz2
FreeFileSync-fd0853d2623dd278b08288331ed42e3be59252fb.zip
2.2
Diffstat (limited to 'algorithm.cpp')
-rw-r--r--algorithm.cpp219
1 files changed, 98 insertions, 121 deletions
diff --git a/algorithm.cpp b/algorithm.cpp
index 4ce2c911..40636e83 100644
--- a/algorithm.cpp
+++ b/algorithm.cpp
@@ -1,21 +1,21 @@
#include "algorithm.h"
#include <wx/intl.h>
-#include <cmath>
#include <wx/log.h>
#include "library/resources.h"
-#include "library/globalFunctions.h"
-#include "library/statusHandler.h"
-#include "library/fileHandling.h"
+#include "shared/globalFunctions.h"
+#include "shared/systemFunctions.h"
+#include "shared/fileHandling.h"
#include <wx/msgdlg.h>
+#include <wx/textctrl.h>
+#include <wx/combobox.h>
+#include <wx/filepicker.h>
+#include "shared/localization.h"
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
-
-#elif defined FFS_LINUX
-#include <string.h>
-#include <errno.h>
#endif
+
using namespace FreeFileSync;
@@ -36,96 +36,89 @@ wxString FreeFileSync::formatFilesizeToShortString(const double filesize)
if (filesize < 0)
return _("Error");
+ if (filesize <= 999)
+ return wxString::Format(wxT("%i"), static_cast<int>(filesize)) + _(" Byte"); //no decimal places in case of bytes
+
double nrOfBytes = filesize;
- bool unitByte = true;
- wxString unit = _(" Byte");
+ nrOfBytes /= 1024;
+ wxString unit = _(" kB");
if (nrOfBytes > 999)
{
- unitByte = false;
nrOfBytes /= 1024;
- unit = _(" kB");
+ unit = _(" MB");
if (nrOfBytes > 999)
{
nrOfBytes /= 1024;
- unit = _(" MB");
+ unit = _(" GB");
if (nrOfBytes > 999)
{
nrOfBytes /= 1024;
- unit = _(" GB");
+ unit = _(" TB");
if (nrOfBytes > 999)
{
nrOfBytes /= 1024;
- unit = _(" TB");
- if (nrOfBytes > 999)
- {
- nrOfBytes /= 1024;
- unit = _(" PB");
- }
+ unit = _(" PB");
}
}
}
}
- wxString temp;
- if (unitByte) //no decimal places in case of bytes
+ //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111
+
+ const unsigned int leadDigitCount = globalFunctions::getDigitCount(static_cast<unsigned int>(nrOfBytes)); //number of digits before decimal point
+ if (leadDigitCount == 0 || leadDigitCount > 3)
+ return _("Error");
+
+ if (leadDigitCount == 3)
+ return wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes)) + unit;
+ else if (leadDigitCount == 2)
{
- double integer = 0;
- modf(nrOfBytes, &integer); //get integer part of nrOfBytes
- temp = globalFunctions::numberToWxString(int(integer));
+ wxString output = wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes * 10));
+ output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT);
+ return output + unit;
}
- else
+ else //leadDigitCount == 1
{
- nrOfBytes*= 100; //we want up to two decimal places
- double integer = 0;
- modf(nrOfBytes, &integer); //get integer part of nrOfBytes
+ wxString output = wxString::Format(wxT("%03i"), static_cast<int>(nrOfBytes * 100));
+ output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT);
+ return output + unit;
+ }
- temp = globalFunctions::numberToWxString(int(integer));
+ //return wxString::Format(wxT("%.*f"), 3 - leadDigitCount, nrOfBytes) + unit;
+}
- switch (temp.length())
- {
- case 0:
- return _("Error");
- case 1:
- temp = wxString(wxT("0")) + FreeFileSync::DECIMAL_POINT + wxT("0") + temp;
- break; //0,01
- case 2:
- temp = wxString(wxT("0")) + FreeFileSync::DECIMAL_POINT + temp;
- break; //0,11
- case 3:
- temp.insert(1, FreeFileSync::DECIMAL_POINT);
- break; //1,11
- case 4:
- temp = temp.substr(0, 3);
- temp.insert(2, FreeFileSync::DECIMAL_POINT);
- break; //11,1
- case 5:
- temp = temp.substr(0, 3);
- break; //111
- default:
- return _("Error");
- }
- }
- return (temp + unit);
+
+wxString FreeFileSync::includeNumberSeparator(const wxString& number)
+{
+ wxString output(number);
+ for (int i = output.size() - 3; i > 0; i -= 3)
+ output.insert(i, FreeFileSync::THOUSANDS_SEPARATOR);
+
+ return output;
}
-Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname)
-{ //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names.
- //Also improves usability.
+template <class T>
+void setDirectoryNameImpl(const wxString& dirname, T* txtCtrl, wxDirPickerCtrl* dirPicker)
+{
+ txtCtrl->SetValue(dirname);
+ const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(dirname.c_str());
+ if (wxDirExists(leftDirFormatted.c_str()))
+ dirPicker->SetPath(leftDirFormatted.c_str());
+}
- Zstring dirnameTmp = dirname;
- dirnameTmp.Trim(true); //remove whitespace characters from right
- dirnameTmp.Trim(false); //remove whitespace characters from left
- if (dirnameTmp.empty()) //an empty string is interpreted as "\"; this is not desired
- return Zstring();
+void FreeFileSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker)
+{
+ setDirectoryNameImpl(dirname, txtCtrl, dirPicker);
+}
- if (!endsWithPathSeparator(dirnameTmp))
- dirnameTmp += FreeFileSync::FILE_NAME_SEPARATOR;
- //don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix
- return dirnameTmp;
+void FreeFileSync::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker)
+{
+ txtCtrl->SetSelection(wxNOT_FOUND);
+ setDirectoryNameImpl(dirname, txtCtrl, dirPicker);
}
@@ -162,7 +155,6 @@ void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, Fol
{
//do not handle i->selectedForSynchronization in this method! handled in synchronizeFile(), synchronizeFolder()!
-
for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
{
FileComparison& fileCmp = j->fileCmp;
@@ -171,31 +163,31 @@ void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, Fol
switch (i->cmpResult)
{
case FILE_LEFT_SIDE_ONLY:
- i->direction = config.exLeftSideOnly;
+ i->syncDir = convertToSyncDirection(config.exLeftSideOnly);
break;
case FILE_RIGHT_SIDE_ONLY:
- i->direction = config.exRightSideOnly;
+ i->syncDir = convertToSyncDirection(config.exRightSideOnly);
break;
case FILE_RIGHT_NEWER:
- i->direction = config.rightNewer;
+ i->syncDir = convertToSyncDirection(config.rightNewer);
break;
case FILE_LEFT_NEWER:
- i->direction = config.leftNewer;
+ i->syncDir = convertToSyncDirection(config.leftNewer);
break;
case FILE_DIFFERENT:
- i->direction = config.different;
+ i->syncDir = convertToSyncDirection(config.different);
break;
case FILE_CONFLICT:
- i->direction = SYNC_UNRESOLVED_CONFLICT;
+ i->syncDir = SYNC_UNRESOLVED_CONFLICT;
break;
case FILE_EQUAL:
- i->direction = SYNC_DIR_NONE;
+ i->syncDir = SYNC_DIR_NONE;
}
}
}
@@ -216,7 +208,7 @@ void FreeFileSync::addSubElements(const FileComparison& fileCmp, const FileCompa
else
return;
- relevantDirectory += FreeFileSync::FILE_NAME_SEPARATOR; //FILE_NAME_SEPARATOR needed to exclude subfile/dirs only
+ relevantDirectory += globalFunctions::FILE_NAME_SEPARATOR; //FILE_NAME_SEPARATOR needed to exclude subfile/dirs only
for (FileComparison::const_iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
{
@@ -249,11 +241,14 @@ struct SortedFileName
//assemble message containing all files to be deleted
-wxString FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
+std::pair<wxString, int> FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
const std::set<int>& rowsToDeleteOnLeft,
const std::set<int>& rowsToDeleteOnRight,
const bool deleteOnBothSides)
{
+ wxString filesToDelete;
+ int totalDelCount = 0;
+
if (deleteOnBothSides)
{
//mix selected rows from left and right
@@ -261,21 +256,26 @@ wxString FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
for (std::set<int>::const_iterator i = rowsToDeleteOnRight.begin(); i != rowsToDeleteOnRight.end(); ++i)
rowsToDelete.insert(*i);
- wxString filesToDelete;
for (std::set<int>::const_iterator i = rowsToDelete.begin(); i != rowsToDelete.end(); ++i)
{
const FileCompareLine& currentCmpLine = fileCmp[*i];
if (currentCmpLine.fileDescrLeft.objType != FileDescrLine::TYPE_NOTHING)
+ {
filesToDelete += (currentCmpLine.fileDescrLeft.fullName + wxT("\n")).c_str();
+ ++totalDelCount;
+ }
if (currentCmpLine.fileDescrRight.objType != FileDescrLine::TYPE_NOTHING)
+ {
filesToDelete += (currentCmpLine.fileDescrRight.fullName + wxT("\n")).c_str();
+ ++totalDelCount;
+ }
filesToDelete+= wxT("\n");
}
- return filesToDelete;
+ return std::pair<wxString, int>(filesToDelete, totalDelCount);
}
else //delete selected files only
{
@@ -291,6 +291,7 @@ wxString FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
newEntry.position = *i * 10;
newEntry.name = currentCmpLine.fileDescrLeft.fullName;
outputTable.insert(newEntry);
+ ++totalDelCount;
}
}
@@ -303,14 +304,14 @@ wxString FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
newEntry.position = *i * 10 + 1; //ensure files on left are before files on right for the same row number
newEntry.name = currentCmpLine.fileDescrRight.fullName;
outputTable.insert(newEntry);
+ ++totalDelCount;
}
}
- wxString filesToDelete;
for (std::set<SortedFileName>::const_iterator i = outputTable.begin(); i != outputTable.end(); ++i)
filesToDelete += (i->name + wxT("\n")).c_str();
- return filesToDelete;
+ return std::pair<wxString, int>(filesToDelete, totalDelCount);
}
}
@@ -318,7 +319,7 @@ wxString FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
class RemoveAtExit //this class ensures, that the result of the method below is ALWAYS written on exit, even if exceptions are thrown!
{
public:
- RemoveAtExit(FileComparison& fileCmp) :
+ RemoveAtExit(FreeFileSync::FileComparison& fileCmp) :
gridToWrite(fileCmp) {}
~RemoveAtExit()
@@ -332,7 +333,7 @@ public:
}
private:
- FileComparison& gridToWrite;
+ FreeFileSync::FileComparison& gridToWrite;
std::set<int> rowsProcessed;
};
@@ -369,12 +370,12 @@ void updateCmpLineAfterDeletion(const int rowNr, const SyncConfiguration& syncCo
if (leftSide) //again evaluated at compile time
{
currentLine.cmpResult = FILE_RIGHT_SIDE_ONLY;
- currentLine.direction = syncConfig.exRightSideOnly;
+ currentLine.syncDir = convertToSyncDirection(syncConfig.exRightSideOnly);
}
else
{
currentLine.cmpResult = FILE_LEFT_SIDE_ONLY;
- currentLine.direction = syncConfig.exLeftSideOnly;
+ currentLine.syncDir = convertToSyncDirection(syncConfig.exLeftSideOnly);
}
}
}
@@ -387,7 +388,7 @@ void deleteFromGridAndHDOneSide(FileComparison& fileCmp,
const bool useRecycleBin,
RemoveAtExit& markForRemoval,
const SyncConfiguration& syncConfig,
- ErrorHandler* errorHandler)
+ DeleteFilesHandler* statusHandler)
{
for (std::set<int>::const_iterator i = rowsToDeleteOneSide.begin(); i != rowsToDeleteOneSide.end(); ++i)
{
@@ -403,10 +404,12 @@ void deleteFromGridAndHDOneSide(FileComparison& fileCmp,
case FileDescrLine::TYPE_FILE:
FreeFileSync::removeFile(fileDescr->fullName, useRecycleBin);
updateCmpLineAfterDeletion<leftSide>(*i, syncConfig, fileCmp, markForRemoval); //remove entries from fileCmp
+ statusHandler->deletionSuccessful(); //notify successful file/folder deletion
break;
case FileDescrLine::TYPE_DIRECTORY:
FreeFileSync::removeDirectory(fileDescr->fullName, useRecycleBin);
updateCmpLineAfterDeletion<leftSide>(*i, syncConfig, fileCmp, markForRemoval); //remove entries from fileCmp
+ statusHandler->deletionSuccessful(); //notify successful file/folder deletion
break;
case FileDescrLine::TYPE_NOTHING:
break;
@@ -416,12 +419,12 @@ void deleteFromGridAndHDOneSide(FileComparison& fileCmp,
}
catch (const FileError& error)
{
- ErrorHandler::Response rv = errorHandler->reportError(error.show());
+ DeleteFilesHandler::Response rv = statusHandler->reportError(error.show());
- if (rv == ErrorHandler::IGNORE_ERROR)
+ if (rv == DeleteFilesHandler::IGNORE_ERROR)
break;
- else if (rv == ErrorHandler::RETRY)
+ else if (rv == DeleteFilesHandler::RETRY)
; //continue in loop
else
assert (false);
@@ -437,7 +440,7 @@ void FreeFileSync::deleteFromGridAndHD(FileComparison& fileCmp,
const bool deleteOnBothSides,
const bool useRecycleBin,
const SyncConfiguration& syncConfig,
- ErrorHandler* errorHandler)
+ DeleteFilesHandler* statusHandler)
{
//remove deleted rows from fileCmp (AFTER all rows to be deleted are known: consider row references!
RemoveAtExit markForRemoval(fileCmp); //ensure that fileCmp is always written to, even if method is exitted via exceptions
@@ -454,14 +457,14 @@ void FreeFileSync::deleteFromGridAndHD(FileComparison& fileCmp,
useRecycleBin,
markForRemoval,
syncConfig,
- errorHandler);
+ statusHandler);
deleteFromGridAndHDOneSide<false>(fileCmp,
rowsToDeleteBothSides,
useRecycleBin,
markForRemoval,
syncConfig,
- errorHandler);
+ statusHandler);
}
else
{
@@ -470,14 +473,14 @@ void FreeFileSync::deleteFromGridAndHD(FileComparison& fileCmp,
useRecycleBin,
markForRemoval,
syncConfig,
- errorHandler);
+ statusHandler);
deleteFromGridAndHDOneSide<false>(fileCmp,
rowsToDeleteOnRight,
useRecycleBin,
markForRemoval,
syncConfig,
- errorHandler);
+ statusHandler);
}
}
//############################################################################################################
@@ -527,7 +530,7 @@ wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zst
FILETIME localFileTime;
- if (::FileTimeToLocalFileTime( //convert to local time
+ if (::FileTimeToLocalFileTime( //convert to local time
&lastWriteTimeUtc, //pointer to UTC file time to convert
&localFileTime //pointer to converted file time
) == 0)
@@ -581,32 +584,6 @@ wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zst
}
-#ifdef FFS_WIN
-Zstring FreeFileSync::getLastErrorFormatted(const unsigned long lastError) //try to get additional Windows error information
-{
- //determine error code if none was specified
- const unsigned long lastErrorCode = lastError == 0 ? GetLastError() : lastError;
-
- Zstring output = Zstring(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastErrorCode).c_str();
-
- WCHAR buffer[1001];
- if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, lastErrorCode, 0, buffer, 1001, NULL) != 0)
- output += Zstring(wxT(": ")) + buffer;
- return output;
-}
-
-#elif defined FFS_LINUX
-Zstring FreeFileSync::getLastErrorFormatted(const int lastError) //try to get additional Linux error information
-{
- //determine error code if none was specified
- const int lastErrorCode = lastError == 0 ? errno : lastError;
-
- Zstring output = Zstring(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastErrorCode).c_str();
- output += Zstring(wxT(": ")) + strerror(lastErrorCode);
- return output;
-}
-#endif
-
/*Statistical theory: detect daylight saving time (DST) switch by comparing files that exist on both sides (and have same filesizes). If there are "enough"
that have a shift by +-1h then assert that DST switch occured.
What is "enough" =: N? N should be large enough AND small enough that the following two errors remain small:
bgstack15