summaryrefslogtreecommitdiff
path: root/ui/grid_view.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/grid_view.cpp')
-rw-r--r--ui/grid_view.cpp387
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;
bgstack15