summaryrefslogtreecommitdiff
path: root/ui/sorting.h
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/sorting.h
parent2.2 (diff)
downloadFreeFileSync-4ecfd41e36533d858c98d051ef70cab80e69e972.tar.gz
FreeFileSync-4ecfd41e36533d858c98d051ef70cab80e69e972.tar.bz2
FreeFileSync-4ecfd41e36533d858c98d051ef70cab80e69e972.zip
2.3
Diffstat (limited to 'ui/sorting.h')
-rw-r--r--ui/sorting.h275
1 files changed, 81 insertions, 194 deletions
diff --git a/ui/sorting.h b/ui/sorting.h
index c3cf8f97..33a6404f 100644
--- a/ui/sorting.h
+++ b/ui/sorting.h
@@ -1,282 +1,169 @@
#ifndef SORTING_H_INCLUDED
#define SORTING_H_INCLUDED
-#include "../structures.h"
-#include "../shared/globalFunctions.h"
+#include "../fileHierarchy.h"
+#include "../shared/systemConstants.h"
+#include "../synchronization.h"
namespace FreeFileSync
{
- enum SideToSort
- {
- SORT_ON_LEFT,
- SORT_ON_RIGHT,
- };
-
-
inline
- bool stringSmallerThan(const DefaultChar* stringA, const DefaultChar* stringB)
+ int compareString(const Zstring& stringA, const Zstring& stringB)
{
-#ifdef FFS_WIN
- //case-insensitive comparison!
- return FreeFileSync::compareStringsWin32(stringA, stringB) < 0; //way faster than wxString::CmpNoCase() in windows build!!!
-#else
- return defaultCompare(stringA, stringB) < 0;
+#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case
+ return stringA.CmpNoCase(stringB);
+#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case
+ return stringA.Cmp(stringB);
#endif
}
inline
- int compareString(const wxChar* stringA, const wxChar* stringB, const int lengthA, const int lengthB)
+ bool stringSmallerThan(const Zstring& stringA, const Zstring& stringB)
{
-#ifdef FFS_WIN
- //case-insensitive comparison!
- return FreeFileSync::compareStringsWin32(stringA, stringB, lengthA, lengthB); //way faster than wxString::CmpNoCase() in the windows build!!!
-#else
- for (int i = 0; i < std::min(lengthA, lengthB); ++i)
- {
- if (stringA[i] != stringB[i])
- return stringA[i] - stringB[i];
- }
- return lengthA - lengthB;
-
- //equivalent:
- //const int rv = strncmp(stringA, stringB, std::min(lengthA, lengthB));
- //return rv != 0 ? rv : lengthA - lengthB;
-#endif
+ return compareString(stringA, stringB) < 0;
}
- template <SideToSort side>
+ template <bool ascending, SelectedSide side>
inline
- bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b)
+ bool sortByFileName(const FileSystemObject& a, const FileSystemObject& b)
{
- const FileDescrLine* const descrLineA = side == SORT_ON_LEFT ? &a.fileDescrLeft : &a.fileDescrRight;
- const FileDescrLine* const descrLineB = side == SORT_ON_LEFT ? &b.fileDescrLeft : &b.fileDescrRight;
-
//presort types: first files, then directories then empty rows
- if (descrLineA->objType == FileDescrLine::TYPE_NOTHING)
+ if (a.isEmpty<side>())
return false; //empty rows always last
- else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING)
+ else if (b.isEmpty<side>())
return true; //empty rows always last
- if (descrLineA->objType == FileDescrLine::TYPE_DIRECTORY) //sort directories by relative name
+ if (dynamic_cast<const DirMapping*>(&a)) //sort directories by relative name
{
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
- return stringSmallerThan(descrLineA->relativeName.c_str(), descrLineB->relativeName.c_str());
+ if (dynamic_cast<const DirMapping*>(&b))
+ return stringSmallerThan(a.getRelativeName<side>(), b.getRelativeName<side>());
else
return false;
}
else
{
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
+ if (dynamic_cast<const DirMapping*>(&b))
return true;
else
{
- const wxChar* stringA = descrLineA->relativeName.c_str();
- const wxChar* stringB = descrLineB->relativeName.c_str();
-
- size_t pos = descrLineA->relativeName.findFromEnd(globalFunctions::FILE_NAME_SEPARATOR); //start search beginning from end
- if (pos != std::string::npos)
- stringA += pos + 1;
-
- pos = descrLineB->relativeName.findFromEnd(globalFunctions::FILE_NAME_SEPARATOR); //start search beginning from end
- if (pos != std::string::npos)
- stringB += pos + 1;
-
- return stringSmallerThan(stringA, stringB);
+ return ascending ?
+ stringSmallerThan(a.getShortName<side>(), b.getShortName<side>()) :
+ stringSmallerThan(b.getShortName<side>(), a.getShortName<side>());
}
}
}
- template <SideToSort side>
- bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b)
+ template <bool ascending, SelectedSide side>
+ bool sortByRelativeName(const FileSystemObject& a, const FileSystemObject& b)
{
- const FileDescrLine* const descrLineA = side == SORT_ON_LEFT ? &a.fileDescrLeft : &a.fileDescrRight;
- const FileDescrLine* const descrLineB = side == SORT_ON_LEFT ? &b.fileDescrLeft : &b.fileDescrRight;
-
- //extract relative name and filename
- const wxChar* const relStringA = descrLineA->relativeName.c_str(); //mustn't be NULL for CompareString() API to work correctly
- const wxChar* fileStringA = relStringA;
- int relLengthA = 0;
- int fileLengthA = 0;
-
- if (descrLineA->objType == FileDescrLine::TYPE_DIRECTORY)
- relLengthA = descrLineA->relativeName.length();
- else if (descrLineA->objType == FileDescrLine::TYPE_FILE)
- {
- relLengthA = descrLineA->relativeName.findFromEnd(globalFunctions::FILE_NAME_SEPARATOR); //start search beginning from end
- if (relLengthA == wxNOT_FOUND)
- {
- relLengthA = 0;
- fileLengthA = descrLineA->relativeName.length();
- }
- else
- {
- fileStringA += relLengthA + 1;
- fileLengthA = descrLineA->relativeName.length() - (relLengthA + 1);
- }
- }
- else
- return false; //empty rows should be on end of list
+ if (a.isEmpty<side>())
+ return false; //empty rows always last
+ else if (b.isEmpty<side>())
+ return true; //empty rows always last
- const wxChar* const relStringB = descrLineB->relativeName.c_str(); //mustn't be NULL for CompareString() API to work correctly
- const wxChar* fileStringB = relStringB;
- int relLengthB = 0;
- int fileLengthB = 0;
+ const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
+ const Zstring relDirNameA = fileObjA != NULL ?
+ a.getParentRelativeName<side>() : //file
+ a.getRelativeName<side>(); //directory
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
- relLengthB = descrLineB->relativeName.length();
- else if (descrLineB->objType == FileDescrLine::TYPE_FILE)
- {
- relLengthB = descrLineB->relativeName.findFromEnd(globalFunctions::FILE_NAME_SEPARATOR); //start search beginning from end
- if (relLengthB == wxNOT_FOUND)
- {
- relLengthB = 0;
- fileLengthB = descrLineB->relativeName.length();
- }
- else
- {
- fileStringB += relLengthB + 1;
- fileLengthB = descrLineB->relativeName.length() - (relLengthB + 1);
- }
- }
- else
- return true; //empty rows should be on end of list
+ const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
+ const Zstring relDirNameB = fileObjB != NULL ?
+ b.getParentRelativeName<side>() : //file
+ b.getRelativeName<side>(); //directory
//compare relative names without filenames first
- const int rv = compareString(relStringA, relStringB, relLengthA, relLengthB);
+ const int rv = compareString(relDirNameA, relDirNameB);
if (rv != 0)
- return rv < 0;
+ return ascending ? rv < 0 : rv > 0;
else //compare the filenames
{
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY) //directories shall appear before files
+ if (fileObjB == NULL) //directories shall appear before files
return false;
- else if (descrLineA->objType == FileDescrLine::TYPE_DIRECTORY)
+ else if (fileObjA == NULL)
return true;
- return compareString(fileStringA, fileStringB, fileLengthA, fileLengthB) < 0;
+ return stringSmallerThan(a.getShortName<side>(), b.getShortName<side>());
}
}
- template <SideToSort side>
+ template <bool ascending, SelectedSide side>
inline
- bool sortByFullName(const FileCompareLine& a, const FileCompareLine& b)
+ bool sortByFileSize(const FileSystemObject& a, const FileSystemObject& b)
{
- const FileDescrLine* const descrLineA = side == SORT_ON_LEFT ? &a.fileDescrLeft : &a.fileDescrRight;
- const FileDescrLine* const descrLineB = side == SORT_ON_LEFT ? &b.fileDescrLeft : &b.fileDescrRight;
-
- //presort types: first files, then directories then empty rows
- if (descrLineA->objType == FileDescrLine::TYPE_NOTHING)
+ if (a.isEmpty<side>())
return false; //empty rows always last
- else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING)
+ else if (b.isEmpty<side>())
return true; //empty rows always last
- else
-#ifdef FFS_WIN //case-insensitive comparison!
- return FreeFileSync::compareStringsWin32(descrLineA->fullName.c_str(), descrLineB->fullName.c_str()) < 0; //way faster than wxString::CmpNoCase() in windows build!!!
-#else
- return descrLineA->fullName.Cmp(descrLineB->fullName) < 0;
-#endif
- }
-
- template <SideToSort side>
- inline
- bool sortByFileSize(const FileCompareLine& a, const FileCompareLine& b)
- {
- const FileDescrLine* const descrLineA = side == SORT_ON_LEFT ? &a.fileDescrLeft : &a.fileDescrRight;
- const FileDescrLine* const descrLineB = side == SORT_ON_LEFT ? &b.fileDescrLeft : &b.fileDescrRight;
- //presort types: first files, then directories then empty rows
- if (descrLineA->objType == FileDescrLine::TYPE_NOTHING)
- return false; //empty rows always last
- else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING)
- return true; //empty rows always last
+ const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
+ const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
+ if (fileObjA == NULL)
+ return false; //directories last
+ else if (fileObjB == NULL)
+ return true; //directories last
- if (descrLineA->objType == FileDescrLine::TYPE_DIRECTORY) //sort directories by relative name
- {
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
- return stringSmallerThan(descrLineA->relativeName.c_str(), descrLineB->relativeName.c_str());
- else
- return false;
- }
- else
- {
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
- return true;
- else
- return descrLineA->fileSize > descrLineB->fileSize; //sortAscending shall result in list beginning with largest files first
- }
+ return ascending ?
+ fileObjA->getFileSize<side>() > fileObjB->getFileSize<side>() : //sortAscending shall result in list beginning with largest files first
+ fileObjA->getFileSize<side>() < fileObjB->getFileSize<side>();
}
- template <SideToSort side>
+ template <bool ascending, SelectedSide side>
inline
- bool sortByDate(const FileCompareLine& a, const FileCompareLine& b)
+ bool sortByDate(const FileSystemObject& a, const FileSystemObject& b)
{
- const FileDescrLine* const descrLineA = side == SORT_ON_LEFT ? &a.fileDescrLeft : &a.fileDescrRight;
- const FileDescrLine* const descrLineB = side == SORT_ON_LEFT ? &b.fileDescrLeft : &b.fileDescrRight;
-
- //presort types: first files, then directories then empty rows
- if (descrLineA->objType == FileDescrLine::TYPE_NOTHING)
+ if (a.isEmpty<side>())
return false; //empty rows always last
- else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING)
+ else if (b.isEmpty<side>())
return true; //empty rows always last
- if (descrLineA->objType == FileDescrLine::TYPE_DIRECTORY) //sort directories by relative name
- {
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
- return stringSmallerThan(descrLineA->relativeName.c_str(), descrLineB->relativeName.c_str());
- else
- return false;
- }
- else
- {
- if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY)
- return true;
- else
- return descrLineA->lastWriteTimeRaw > descrLineB->lastWriteTimeRaw;
- }
+
+ const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
+ const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
+
+ if (fileObjA == NULL)
+ return false; //directories last
+ else if (fileObjB == NULL)
+ return true; //directories last
+
+ return ascending ?
+ fileObjA->getLastWriteTime<side>() > fileObjB->getLastWriteTime<side>() :
+ fileObjA->getLastWriteTime<side>() < fileObjB->getLastWriteTime<side>();
}
+ template <bool ascending>
inline
- bool sortByCmpResult(const FileCompareLine& a, const FileCompareLine& b)
+ bool sortByCmpResult(const FileSystemObject& a, const FileSystemObject& b)
{
//presort result: equal shall appear at end of list
- if (a.cmpResult == FILE_EQUAL)
+ if (a.getCategory() == FILE_EQUAL)
return false;
- if (b.cmpResult == FILE_EQUAL)
+ if (b.getCategory() == FILE_EQUAL)
return true;
- return a.cmpResult < b.cmpResult;
- }
-
-
- inline
- bool sortBySyncDirection(const FileCompareLine& a, const FileCompareLine& b)
- {
- return a.syncDir < b.syncDir;
+ return ascending ?
+ a.getCategory() < b.getCategory() :
+ a.getCategory() > b.getCategory();
}
- template <SideToSort side>
+ template <bool ascending>
inline
- bool sortByDirectory(const FolderCompareLine& a, const FolderCompareLine& b)
+ bool sortBySyncDirection(const FileSystemObject& a, const FileSystemObject& b)
{
- const Zstring& dirNameA = side == SORT_ON_LEFT ? a.syncPair.leftDirectory : a.syncPair.rightDirectory;
- const Zstring& dirNameB = side == SORT_ON_LEFT ? b.syncPair.leftDirectory : b.syncPair.rightDirectory;
-
-#ifdef FFS_WIN //case-insensitive comparison!
- return FreeFileSync::compareStringsWin32(dirNameA.c_str(), dirNameB.c_str()) < 0; //way faster than wxString::CmpNoCase() in windows build!!!
-#elif defined FFS_LINUX
- return dirNameA.Cmp(dirNameB) < 0;
-#endif
+ return ascending ?
+ getSyncOperation(a) < getSyncOperation(b) :
+ getSyncOperation(a) > getSyncOperation(b);
}
}
bgstack15