From 4ecfd41e36533d858c98d051ef70cab80e69e972 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:00:50 +0200 Subject: 2.3 --- ui/sorting.h | 275 ++++++++++++++++++----------------------------------------- 1 file changed, 81 insertions(+), 194 deletions(-) (limited to 'ui/sorting.h') 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 + template 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()) return false; //empty rows always last - else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING) + else if (b.isEmpty()) return true; //empty rows always last - if (descrLineA->objType == FileDescrLine::TYPE_DIRECTORY) //sort directories by relative name + if (dynamic_cast(&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(&b)) + return stringSmallerThan(a.getRelativeName(), b.getRelativeName()); else return false; } else { - if (descrLineB->objType == FileDescrLine::TYPE_DIRECTORY) + if (dynamic_cast(&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(), b.getShortName()) : + stringSmallerThan(b.getShortName(), a.getShortName()); } } } - template - bool sortByRelativeName(const FileCompareLine& a, const FileCompareLine& b) + template + 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()) + return false; //empty rows always last + else if (b.isEmpty()) + 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(&a); + const Zstring relDirNameA = fileObjA != NULL ? + a.getParentRelativeName() : //file + a.getRelativeName(); //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(&b); + const Zstring relDirNameB = fileObjB != NULL ? + b.getParentRelativeName() : //file + b.getRelativeName(); //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(), b.getShortName()); } } - template + template 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()) return false; //empty rows always last - else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING) + else if (b.isEmpty()) 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 - 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(&a); + const FileMapping* fileObjB = dynamic_cast(&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() > fileObjB->getFileSize() : //sortAscending shall result in list beginning with largest files first + fileObjA->getFileSize() < fileObjB->getFileSize(); } - template + template 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()) return false; //empty rows always last - else if (descrLineB->objType == FileDescrLine::TYPE_NOTHING) + else if (b.isEmpty()) 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(&a); + const FileMapping* fileObjB = dynamic_cast(&b); + + if (fileObjA == NULL) + return false; //directories last + else if (fileObjB == NULL) + return true; //directories last + + return ascending ? + fileObjA->getLastWriteTime() > fileObjB->getLastWriteTime() : + fileObjA->getLastWriteTime() < fileObjB->getLastWriteTime(); } + template 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 + template 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); } } -- cgit