Restore selection list after applying filter

Dani Soufi <[email protected]>
Newsgroups gmane.comp.version-control.subversion.tortoisesvn.devel
Message-ID <CAEdP+m-zHgALZUj1x=07szXRSiZxvnCgNzS6xm+7JOdB54fOrg@mail.gmail.com>
Dear devs,

I encoutered recently an annoyance while working on a large project. I
selected several commits to merge into a seperate branch, no problem there.
Then I applied a filter to select some other commits, no problems there
too. Now when I clear the filter, only the recently selected list is
restored but my previous selection is deselected. Actually, the selection
list is restored only for the current visible list and does not work for
all the previous selects if the list was reloaded/filtered. This is a huge
annoyance when you use alot of filtering, some selects will be lost and you
need to keep track of them.

That's why I submit a patch to fix this.

The patch was developed and tested against r27333.

Best Regards
Dani El-Soufi

------------------------------------------------------
http://tortoisesvn.tigris.org/ds/viewMessage.do?dsForumId=757&dsMessageId=3187747

To unsubscribe from this discussion, e-mail: [[email protected]].
restore-selection-list-after-filtering-r27333.patch (application/octet-stream, 5.7 KB)
Index: src/TortoiseProc/LogDialog/LogDlg.cpp
===================================================================
--- src/TortoiseProc/LogDialog/LogDlg.cpp	(revision 27333)
+++ src/TortoiseProc/LogDialog/LogDlg.cpp	(working copy)
@@ -435,6 +435,7 @@
     delete m_pStoreSelection;
     m_pStoreSelection = NULL;
     m_pStoreSelection = new CStoreSelection(this, revArray);
+	RestoreCheckedList(revArray);
     if (revArray.GetCount() && revArray.GetLowestRevision().IsValid() && revArray.GetLowestRevision().IsNumber() && (svn_revnum_t(revArray.GetLowestRevision()) > 0))
     {
         m_bEnsureSelection = true;
@@ -985,7 +986,7 @@
 
     // depending on how many revisions are selected, we have to do different
     // tasks.
-    int selCount = m_LogList.GetSelectedCount();
+	int selCount = m_LogList.GetSelectedCount();
     if (selCount == 0)
     {
         // if nothing is selected, we have nothing more to do
@@ -1003,8 +1004,9 @@
         size_t selIndex = m_LogList.GetNextSelectedItem(pos);
         if (selIndex >= m_logEntries.GetVisibleCount())
         {
-            return;
+			return;
         }
+
         m_nSearchIndex = (int)selIndex;
         PLOGENTRYDATA pLogEntry = m_logEntries.GetVisible (selIndex);
         if (pLogEntry == NULL)
@@ -3173,7 +3175,9 @@
                 PLOGENTRYDATA pLogEntry = m_logEntries.GetVisible(item);
                 if (pLogEntry)
                 {
-                    pLogEntry->SetChecked ((pNMLV->uNewState & LVIS_SELECTED) != 0);
+					bool selected = ((pNMLV->uNewState & LVIS_SELECTED) != 0);
+                    pLogEntry->SetChecked(selected);
+					m_logEntries.UpdateCheckList(pLogEntry->GetRevision(), selected);
                 }
             }
         }
@@ -3180,6 +3184,7 @@
     }
     else
     {
+		m_logEntries.ClearCheckedList();
         FillLogMessageCtrl();
         UpdateData(FALSE);
     }
@@ -6409,6 +6414,7 @@
         delete m_pStoreSelection;
         m_pStoreSelection = NULL;
 
+		RestoreSelectionList();
         FillLogMessageCtrl();
         UpdateLogInfoLabel();
         if (m_bSelect)
@@ -6416,6 +6422,38 @@
     }
 }
 
+void CLogDlg::RestoreSelectionList()
+{
+	for (size_t i = 0; i < m_logEntries.GetCheckedCount(); i++)
+	{
+		PLOGENTRYDATA selectedEntry = m_logEntries.GetChecked(i);
+		if (selectedEntry != NULL)
+		{
+			for (size_t j = 0; j < m_logEntries.GetVisibleCount(); j++)
+			{
+				PLOGENTRYDATA visibleEntry = m_logEntries.GetVisible(j);
+				if (visibleEntry != NULL && selectedEntry->GetRevision() == visibleEntry->GetRevision())
+				{
+					m_LogList.SetSelectionMark(j); // restore selection
+					m_LogList.SetItemState(j, LVIS_SELECTED, LVIS_SELECTED);
+				}
+			}
+		}
+	}
+}
+
+void CLogDlg::RestoreCheckedList(const SVNRevRangeArray& revRange)
+{
+	for (int i = 0; i < revRange.GetCount(); ++i)
+	{
+		const SVNRevRange range = revRange[i];
+		for (svn_revnum_t rev = range.GetStartRevision(); rev <= range.GetEndRevision(); ++rev)
+		{
+			m_logEntries.UpdateCheckList(rev, true);
+		}
+	}
+}
+
 CString CLogDlg::GetListviewHelpString(HWND hControl, int index)
 {
     CString sHelpText;
Index: src/TortoiseProc/LogDialog/LogDlg.h
===================================================================
--- src/TortoiseProc/LogDialog/LogDlg.h	(revision 27333)
+++ src/TortoiseProc/LogDialog/LogDlg.h	(working copy)
@@ -395,6 +395,9 @@
     void AutoStoreSelection();
     void AutoRestoreSelection();
 
+	void RestoreSelectionList();
+	void RestoreCheckedList(const SVNRevRangeArray& revRange);
+
     // ListViewAccProvider
     virtual CString GetListviewHelpString(HWND hControl, int index) override;
     void DetectVisualStudioRunningThread();
Index: src/TortoiseProc/LogDialog/LogDlgDataModel.cpp
===================================================================
--- src/TortoiseProc/LogDialog/LogDlgDataModel.cpp	(revision 27333)
+++ src/TortoiseProc/LogDialog/LogDlgDataModel.cpp	(working copy)
@@ -636,6 +636,11 @@
     return visible.size();
 }
 
+size_t CLogDataVector::GetCheckedCount() const
+{
+	return checked.size();
+}
+
 PLOGENTRYDATA CLogDataVector::GetVisible (size_t index) const
 {
     if (index < visible.size())
@@ -647,6 +652,44 @@
     return NULL;
 }
 
+PLOGENTRYDATA CLogDataVector::GetChecked(size_t index) const
+{
+	if (index < checked.size())
+	{
+		for (size_t i = 0; i < size(); i++)
+		{
+			PLOGENTRYDATA entry = at(i);
+			if (checked.at(index) == entry->GetRevision()) {
+				return entry;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+void CLogDataVector::UpdateCheckList(size_t rev, bool isChecked)
+{
+	std::vector<size_t>::iterator it = std::find(checked.begin(), checked.end(), rev);
+	if (it != checked.end()) {
+		if (!isChecked) {
+			auto index = it - checked.begin();
+			checked.erase(checked.begin() + index);
+		}
+	}
+	else
+	{
+		if (isChecked) {
+			checked.push_back(rev);
+		}
+	}
+}
+
+void CLogDataVector::ClearCheckedList()
+{
+	checked.clear();
+}
+
 namespace
 {
 
Index: src/TortoiseProc/LogDialog/LogDlgDataModel.h
===================================================================
--- src/TortoiseProc/LogDialog/LogDlgDataModel.h	(revision 27333)
+++ src/TortoiseProc/LogDialog/LogDlgDataModel.h	(working copy)
@@ -258,6 +258,10 @@
 
     std::vector<size_t> visible;
 
+	// revision numbers of checked entries
+
+	std::vector<size_t> checked;
+
     /// max of LogEntryData::GetDepth
 
     DWORD maxDepth;
@@ -333,8 +337,14 @@
     /// access to the filtered info
 
     size_t GetVisibleCount() const;
+	size_t GetCheckedCount() const;
     PLOGENTRYDATA GetVisible (size_t index) const;
+	PLOGENTRYDATA GetChecked(size_t rev) const;
 
+	void UpdateCheckList(size_t rev, bool isChecked);
+
+	void ClearCheckedList();
+
     /// encapsulate sorting
 
     enum SortColumn
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.