diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:18:53 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:18:53 +0200 |
commit | 32cb97237e7691d31977ab503c6ea4511e8eb3a8 (patch) | |
tree | 4e97b53e9f7b74e8cc5d7548507d9e82ae38e36f /ui/grid_view.cpp | |
parent | 4.6 (diff) | |
download | FreeFileSync-32cb97237e7691d31977ab503c6ea4511e8eb3a8.tar.gz FreeFileSync-32cb97237e7691d31977ab503c6ea4511e8eb3a8.tar.bz2 FreeFileSync-32cb97237e7691d31977ab503c6ea4511e8eb3a8.zip |
5.0
Diffstat (limited to 'ui/grid_view.cpp')
-rw-r--r-- | ui/grid_view.cpp | 387 |
1 files changed, 207 insertions, 180 deletions
diff --git a/ui/grid_view.cpp b/ui/grid_view.cpp index 7ed2bde1..8460b238 100644 --- a/ui/grid_view.cpp +++ b/ui/grid_view.cpp @@ -1,32 +1,18 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "grid_view.h" #include "sorting.h" #include "../synchronization.h" #include <zen/stl_tools.h> +//#include <zen/perf.h> using namespace zen; -GridView::StatusCmpResult::StatusCmpResult() : - existsLeftOnly(false), - existsRightOnly(false), - existsLeftNewer(false), - existsRightNewer(false), - existsDifferent(false), - existsEqual(false), - existsConflict(false), - - filesOnLeftView(0), - foldersOnLeftView(0), - filesOnRightView(0), - foldersOnRightView(0) {} - - template <class StatusResult> void getNumbers(const FileSystemObject& fsObj, StatusResult& result) { @@ -71,6 +57,70 @@ void getNumbers(const FileSystemObject& fsObj, StatusResult& result) } +template <class Predicate> +void GridView::updateView(Predicate pred) +{ + viewRef.clear(); + rowPositions.clear(); + rowPositionsFirstChild.clear(); + + std::for_each(sortedRef.begin(), sortedRef.end(), + [&](const RefIndex& ref) + { + if (const FileSystemObject* fsObj = FileSystemObject::retrieve(ref.objId)) + if (pred(*fsObj)) + { + //save row position for direct random access to FileMapping or DirMapping + rowPositions.insert(std::make_pair(ref.objId, viewRef.size())); //costs: 0.28 µs per call - MSVC based on std::set + + //save row position to identify first child *on sorted subview* of DirMapping or BaseDirMapping in case latter are filtered out + const HierarchyObject* parent = &(fsObj->parent()); + for (;;) //map all yet unassociated parents to this row + { + const auto rv = rowPositionsFirstChild.insert(std::make_pair(parent, viewRef.size())); + if (!rv.second) + break; + + if (auto dirObj = dynamic_cast<const DirMapping*>(parent)) + parent = &(dirObj->parent()); + else + break; + } + + //build subview + viewRef.push_back(ref.objId); + } + }); +} + + +int GridView::findRowDirect(FileSystemObject::ObjectIdConst objId) const +{ + auto iter = rowPositions.find(objId); + return iter != rowPositions.end() ? iter->second : -1; +} + +int GridView::findRowFirstChild(const HierarchyObject* hierObj) const +{ + auto iter = rowPositionsFirstChild.find(hierObj); + return iter != rowPositionsFirstChild.end() ? iter->second : -1; +} + + +GridView::StatusCmpResult::StatusCmpResult() : + existsLeftOnly (false), + existsRightOnly (false), + existsLeftNewer (false), + existsRightNewer(false), + existsDifferent (false), + existsEqual (false), + existsConflict (false), + filesOnLeftView (0), + foldersOnLeftView (0), + filesOnRightView (0), + foldersOnRightView(0) {} + + GridView::StatusCmpResult GridView::updateCmpResult(bool hideFiltered, //maps sortedRef to viewRef bool leftOnlyFilesActive, bool rightOnlyFilesActive, @@ -82,75 +132,65 @@ GridView::StatusCmpResult GridView::updateCmpResult(bool hideFiltered, //maps so { StatusCmpResult output; - viewRef.clear(); - - for (std::vector<RefIndex>::const_iterator j = sortedRef.begin(); j != sortedRef.end(); ++j) + updateView([&](const FileSystemObject& fsObj) -> bool { - const FileSystemObject* fsObj = FileSystemObject::retrieve(j->objId); - if (fsObj) - { - //hide filtered row, if corresponding option is set - if (hideFiltered && !fsObj->isActive()) - continue; - - switch (fsObj->getCategory()) - { - case FILE_LEFT_SIDE_ONLY: - output.existsLeftOnly = true; - if (!leftOnlyFilesActive) continue; - break; - case FILE_RIGHT_SIDE_ONLY: - output.existsRightOnly = true; - if (!rightOnlyFilesActive) continue; - break; - case FILE_LEFT_NEWER: - output.existsLeftNewer = true; - if (!leftNewerFilesActive) continue; - break; - case FILE_RIGHT_NEWER: - output.existsRightNewer = true; - if (!rightNewerFilesActive) continue; - break; - case FILE_DIFFERENT: - output.existsDifferent = true; - if (!differentFilesActive) continue; - break; - case FILE_EQUAL: - output.existsEqual = true; - if (!equalFilesActive) continue; - break; - case FILE_CONFLICT: - case FILE_DIFFERENT_METADATA: //no extra button on screen - output.existsConflict = true; - if (!conflictFilesActive) continue; - break; - } - - //calculate total number of bytes for each side - getNumbers(*fsObj, output); + if (hideFiltered && !fsObj.isActive()) + return false; - viewRef.push_back(j->objId); + switch (fsObj.getCategory()) + { + case FILE_LEFT_SIDE_ONLY: + output.existsLeftOnly = true; + if (!leftOnlyFilesActive) return false; + break; + case FILE_RIGHT_SIDE_ONLY: + output.existsRightOnly = true; + if (!rightOnlyFilesActive) return false; + break; + case FILE_LEFT_NEWER: + output.existsLeftNewer = true; + if (!leftNewerFilesActive) return false; + break; + case FILE_RIGHT_NEWER: + output.existsRightNewer = true; + if (!rightNewerFilesActive) return false; + break; + case FILE_DIFFERENT: + output.existsDifferent = true; + if (!differentFilesActive) return false; + break; + case FILE_EQUAL: + output.existsEqual = true; + if (!equalFilesActive) return false; + break; + case FILE_CONFLICT: + case FILE_DIFFERENT_METADATA: //no extra button on screen + output.existsConflict = true; + if (!conflictFilesActive) return false; + break; } - } + //calculate total number of bytes for each side + getNumbers(fsObj, output); + return true; + }); return output; } GridView::StatusSyncPreview::StatusSyncPreview() : - existsSyncCreateLeft(false), + existsSyncCreateLeft (false), existsSyncCreateRight(false), - existsSyncDeleteLeft(false), + existsSyncDeleteLeft (false), existsSyncDeleteRight(false), - existsSyncDirLeft(false), - existsSyncDirRight(false), - existsSyncDirNone(false), - existsSyncEqual(false), - existsConflict(false), - - filesOnLeftView(0), - foldersOnLeftView(0), - filesOnRightView(0), + existsSyncDirLeft (false), + existsSyncDirRight (false), + existsSyncDirNone (false), + existsSyncEqual (false), + existsConflict (false), + filesOnLeftView (0), + foldersOnLeftView (0), + filesOnRightView (0), foldersOnRightView(0) {} @@ -167,86 +207,76 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //map { StatusSyncPreview output; - viewRef.clear(); - - for (std::vector<RefIndex>::const_iterator j = sortedRef.begin(); j != sortedRef.end(); ++j) + updateView([&](const FileSystemObject& fsObj) -> bool { - const FileSystemObject* fsObj = FileSystemObject::retrieve(j->objId); - if (fsObj) - { - //hide filtered row, if corresponding option is set - if (hideFiltered && !fsObj->isActive()) - continue; - - switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - case SO_MOVE_LEFT_TARGET: - output.existsSyncCreateLeft = true; - if (!syncCreateLeftActive) continue; - break; - case SO_CREATE_NEW_RIGHT: - case SO_MOVE_RIGHT_TARGET: - output.existsSyncCreateRight = true; - if (!syncCreateRightActive) continue; - break; - case SO_DELETE_LEFT: - case SO_MOVE_LEFT_SOURCE: - output.existsSyncDeleteLeft = true; - if (!syncDeleteLeftActive) continue; - break; - case SO_DELETE_RIGHT: - case SO_MOVE_RIGHT_SOURCE: - output.existsSyncDeleteRight = true; - if (!syncDeleteRightActive) continue; - break; - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: //no extra button on screen - output.existsSyncDirRight = true; - if (!syncDirOverwRightActive) continue; - break; - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: //no extra button on screen - output.existsSyncDirLeft = true; - if (!syncDirOverwLeftActive) continue; - break; - case SO_DO_NOTHING: - output.existsSyncDirNone = true; - if (!syncDirNoneActive) continue; - break; - case SO_EQUAL: - output.existsSyncEqual = true; - if (!syncEqualActive) continue; - break; - case SO_UNRESOLVED_CONFLICT: - output.existsConflict = true; - if (!conflictFilesActive) continue; - break; - } - - //calculate total number of bytes for each side - getNumbers(*fsObj, output); + if (hideFiltered && !fsObj.isActive()) + return false; - viewRef.push_back(j->objId); + switch (fsObj.getSyncOperation()) //evaluate comparison result and sync direction + { + case SO_CREATE_NEW_LEFT: + case SO_MOVE_LEFT_TARGET: + output.existsSyncCreateLeft = true; + if (!syncCreateLeftActive) return false; + break; + case SO_CREATE_NEW_RIGHT: + case SO_MOVE_RIGHT_TARGET: + output.existsSyncCreateRight = true; + if (!syncCreateRightActive) return false; + break; + case SO_DELETE_LEFT: + case SO_MOVE_LEFT_SOURCE: + output.existsSyncDeleteLeft = true; + if (!syncDeleteLeftActive) return false; + break; + case SO_DELETE_RIGHT: + case SO_MOVE_RIGHT_SOURCE: + output.existsSyncDeleteRight = true; + if (!syncDeleteRightActive) return false; + break; + case SO_OVERWRITE_RIGHT: + case SO_COPY_METADATA_TO_RIGHT: //no extra button on screen + output.existsSyncDirRight = true; + if (!syncDirOverwRightActive) return false; + break; + case SO_OVERWRITE_LEFT: + case SO_COPY_METADATA_TO_LEFT: //no extra button on screen + output.existsSyncDirLeft = true; + if (!syncDirOverwLeftActive) return false; + break; + case SO_DO_NOTHING: + output.existsSyncDirNone = true; + if (!syncDirNoneActive) return false; + break; + case SO_EQUAL: + output.existsSyncEqual = true; + if (!syncEqualActive) return false; + break; + case SO_UNRESOLVED_CONFLICT: + output.existsConflict = true; + if (!conflictFilesActive) return false; + break; } - } + + //calculate total number of bytes for each side + getNumbers(fsObj, output); + return true; + }); return output; } -void GridView::getAllFileRef(const std::set<size_t>& guiRows, std::vector<FileSystemObject*>& output) +void GridView::getAllFileRef(const std::set<size_t>& rows, std::vector<FileSystemObject*>& output) { - std::set<size_t>::const_iterator upperEnd = guiRows.lower_bound(rowsOnView()); //loop over valid rows only! - output.clear(); - output.reserve(guiRows.size()); + output.reserve(rows.size()); - std::for_each(guiRows.begin(), upperEnd, + auto iterLast = rows.lower_bound(rowsOnView()); //loop over valid rows only! + std::for_each(rows.begin(), iterLast, [&](size_t pos) { - FileSystemObject* fsObj = FileSystemObject::retrieve(viewRef[pos]); - if (fsObj) + if (FileSystemObject* fsObj = FileSystemObject::retrieve(viewRef[pos])) output.push_back(fsObj); }); } @@ -255,20 +285,14 @@ void GridView::getAllFileRef(const std::set<size_t>& guiRows, std::vector<FileSy void GridView::removeInvalidRows() { viewRef.clear(); + rowPositions.clear(); + rowPositionsFirstChild.clear(); //remove rows that have been deleted meanwhile vector_remove_if(sortedRef, [&](const RefIndex& refIdx) { return FileSystemObject::retrieve(refIdx.objId) == NULL; }); } -void GridView::clearAllRows() -{ - std::vector<FileSystemObject::ObjectID>().swap(viewRef); //free mem - std::vector<RefIndex>().swap(sortedRef); // - folderCmp.clear(); -} - - class GridView::SerializeHierarchy { public: @@ -305,15 +329,15 @@ private: }; -void GridView::setData(FolderComparison& newData) +void GridView::setData(FolderComparison& folderCmp) { - clearAllRows(); + //clear everything + std::vector<FileSystemObject::ObjectId>().swap(viewRef); //free mem + std::vector<RefIndex>().swap(sortedRef); // + currentSort.reset(); - folderCmp.swap(newData); - - //fill sortedRef - for (auto j = begin(folderCmp); j != end(folderCmp); ++j) - SerializeHierarchy(sortedRef, j - folderCmp.begin()).execute(*j); + for (auto iter = begin(folderCmp); iter != end(folderCmp); ++iter) + SerializeHierarchy(sortedRef, iter - begin(folderCmp)).execute(*iter); } @@ -450,20 +474,19 @@ public: }; //------------------------------------------------------------------------------------------------------- -bool GridView::getDefaultDirection(SortType type) //true: ascending; false: descending +bool GridView::getDefaultSortDirection(ColumnTypeRim type) //true: ascending; false: descending { switch (type) { - case SORT_BY_FILESIZE: - case SORT_BY_DATE: + case COL_TYPE_SIZE: + case COL_TYPE_DATE: return false; - case SORT_BY_REL_NAME: - case SORT_BY_FILENAME: - case SORT_BY_EXTENSION: - case SORT_BY_CMP_RESULT: - case SORT_BY_DIRECTORY: - case SORT_BY_SYNC_DIRECTION: + case COL_TYPE_DIRECTORY: + case COL_TYPE_FULL_PATH: + case COL_TYPE_REL_PATH: + case COL_TYPE_FILENAME: + case COL_TYPE_EXTENSION: return true; } assert(false); @@ -471,49 +494,53 @@ bool GridView::getDefaultDirection(SortType type) //true: ascending; false: desc } -void GridView::sortView(SortType type, bool onLeft, bool ascending) +void GridView::sortView(ColumnTypeRim type, bool onLeft, bool ascending) { viewRef.clear(); + rowPositions.clear(); + rowPositionsFirstChild.clear(); + currentSort.reset(new SortInfo(type, onLeft, ascending)); switch (type) { - case SORT_BY_REL_NAME: + case COL_TYPE_FULL_PATH: + case COL_TYPE_REL_PATH: if ( ascending) std::sort(sortedRef.begin(), sortedRef.end(), LessRelativeName<true>()); else if (!ascending) std::sort(sortedRef.begin(), sortedRef.end(), LessRelativeName<false>()); break; - case SORT_BY_FILENAME: + case COL_TYPE_FILENAME: if ( ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<true, LEFT_SIDE >()); else if ( ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<true, RIGHT_SIDE>()); else if (!ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<false, LEFT_SIDE >()); else if (!ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessShortFileName<false, RIGHT_SIDE>()); break; - case SORT_BY_FILESIZE: + case COL_TYPE_SIZE: if ( ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<true, LEFT_SIDE >()); else if ( ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<true, RIGHT_SIDE>()); else if (!ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<false, LEFT_SIDE >()); else if (!ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFilesize<false, RIGHT_SIDE>()); break; - case SORT_BY_DATE: + case COL_TYPE_DATE: if ( ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<true, LEFT_SIDE >()); else if ( ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<true, RIGHT_SIDE>()); else if (!ascending && onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<false, LEFT_SIDE >()); else if (!ascending && !onLeft) std::sort(sortedRef.begin(), sortedRef.end(), LessFiletime<false, RIGHT_SIDE>()); break; - case SORT_BY_EXTENSION: + case COL_TYPE_EXTENSION: if ( ascending && onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<true, LEFT_SIDE >()); else if ( ascending && !onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<true, RIGHT_SIDE>()); else if (!ascending && onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<false, LEFT_SIDE >()); else if (!ascending && !onLeft) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessExtension<false, RIGHT_SIDE>()); break; - case SORT_BY_CMP_RESULT: - if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessCmpResult<true >()); - else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessCmpResult<false>()); - break; - case SORT_BY_SYNC_DIRECTION: - if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessSyncDirection<true >()); - else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessSyncDirection<false>()); - break; - case SORT_BY_DIRECTORY: + //case SORT_BY_CMP_RESULT: + // if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessCmpResult<true >()); + // else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessCmpResult<false>()); + // break; + //case SORT_BY_SYNC_DIRECTION: + // if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessSyncDirection<true >()); + // else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), LessSyncDirection<false>()); + // break; + case COL_TYPE_DIRECTORY: if ( ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), [](const RefIndex a, const RefIndex b) { return a.folderIndex < b.folderIndex; }); else if (!ascending) std::stable_sort(sortedRef.begin(), sortedRef.end(), [](const RefIndex a, const RefIndex b) { return a.folderIndex > b.folderIndex; }); break; |