From 1dcc71e0356b3205bf783d0956c1575a38d647e9 Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Wed, 5 Mar 2008 07:13:53 +0000 Subject: [PATCH] MGR: Grid views: When order of rows changes, reselect same data in new rows; update buttons when selected row is deleted. svn path=/trunk/boinc/; revision=14844 --- checkin_notes | 17 +++++++++- clientgui/BOINCGridCtrl.cpp | 59 +++++++++++++++++++++------------ clientgui/BOINCGridCtrl.h | 13 +++++--- clientgui/ViewMessagesGrid.cpp | 2 +- clientgui/ViewProjectsGrid.cpp | 12 ++++--- clientgui/ViewTransfersGrid.cpp | 8 +++-- clientgui/ViewWorkGrid.cpp | 13 +++++--- 7 files changed, 84 insertions(+), 40 deletions(-) diff --git a/checkin_notes b/checkin_notes index 989d978906..3c96d82cc8 100644 --- a/checkin_notes +++ b/checkin_notes @@ -1873,6 +1873,21 @@ Charlie Mar 4 2008 The other tabs disabled all buttons when multiple items were selected, so allowing multiple selections was confusing to users. + - MGR: When order of rows in grid views changes (due to sorting or + changes in data), reselect the same data in the rearranged rows + using: + Projects tab: project name only + Tasks tab: project name and work unit (task) name + Transfers tab: project name and file name + Messages tab: sequence number only. + - MGR: set m_bForceUpdateSelection=true when deleting rows from grid + views. Fixes bug: if the last row was selected and is deleted, + the new last row is automatically selected but the buttons were + not updated to reflect the new selection. clientgui/ - ViewTransfersGrid.cpp,h + BOINCGridGtrl.cpp,h + ViewMessagesGrid.cpp + ViewProjectsGrid.cpp + ViewTransfersGrid.cpp + ViewWorkGrid.cpp diff --git a/clientgui/BOINCGridCtrl.cpp b/clientgui/BOINCGridCtrl.cpp index 2cd2d196ef..1980dcb0ab 100644 --- a/clientgui/BOINCGridCtrl.cpp +++ b/clientgui/BOINCGridCtrl.cpp @@ -130,9 +130,13 @@ CBOINCGridCtrl::CBOINCGridCtrl(wxWindow* parent, wxWindowID iGridWindowID) : wxG sortColumn=-1; sortAscending=true; sortNeededByLabelClick=false; - m_pkColumnIndex=-1; + m_pkColumnIndex1=-1; + m_pkColumnIndex2=-1; m_cursorcol=-1; - m_cursorrow=-1; + m_cursorrow=-1; + m_arrSelectedKeys1.Clear(); + m_arrSelectedKeys2.Clear(); + //load sorting bitmaps ascBitmap = wxBitmap(sortascending_xpm); descBitmap = wxBitmap(sortdescending_xpm); @@ -185,8 +189,9 @@ wxArrayInt CBOINCGridCtrl::GetSelectedRows2() { } /* sets the column with unique values */ -void CBOINCGridCtrl::SetPrimaryKeyColumn(int col) { - m_pkColumnIndex = col; +void CBOINCGridCtrl::SetPrimaryKeyColumns(int col1,int col2) { + m_pkColumnIndex1 = col1; + m_pkColumnIndex2 = col2; } /* If the user clicked inside the grid, the former selected cells must be deselected. @@ -195,16 +200,22 @@ void CBOINCGridCtrl::SetPrimaryKeyColumn(int col) { */ void CBOINCGridCtrl::ClearSavedSelection() { if(this->GetBatchCount()<=0) { - m_arrSelectedKeys.Empty(); + m_arrSelectedKeys1.Empty(); + m_arrSelectedKeys2.Empty(); } } /* save the key values of the currently selected rows for later restore */ void CBOINCGridCtrl::SaveSelection() { - if(m_pkColumnIndex>=0) { + if(m_pkColumnIndex1>=0) { wxArrayInt arrSelRows = GetSelectedRows2(); + m_arrSelectedKeys1.Empty(); + m_arrSelectedKeys2.Empty(); for(unsigned int i=0; i< arrSelRows.GetCount();i++) { - m_arrSelectedKeys.Add(GetCellValue(arrSelRows[i],m_pkColumnIndex)); + m_arrSelectedKeys1.Add(GetCellValue(arrSelRows[i],m_pkColumnIndex1)); + if (m_pkColumnIndex2 >= 0) { + m_arrSelectedKeys2.Add(GetCellValue(arrSelRows[i],m_pkColumnIndex2)); + } } } } @@ -212,9 +223,11 @@ void CBOINCGridCtrl::SaveSelection() { /* select all rows, that were formerly selected this raises selection events without user interaction */ void CBOINCGridCtrl::RestoreSelection() { - ClearSelection(); - for(unsigned int i=0;i < m_arrSelectedKeys.size();i++) { - int index = GetTable()->FindRowIndexByColValue(m_pkColumnIndex,m_arrSelectedKeys[i]); +// ClearSelection(); + for(unsigned int i=0;i < m_arrSelectedKeys1.size();i++) { + int index = GetTable()->FindRowIndexByColValue( + m_pkColumnIndex1,m_arrSelectedKeys1[i],m_pkColumnIndex2,m_arrSelectedKeys2[i] + ); if(index >=0) { SelectRow(index,true); } @@ -225,12 +238,15 @@ void CBOINCGridCtrl::SaveGridCursorPosition() { m_cursorcol = GetGridCursorCol(); m_cursorrow = GetGridCursorRow(); if(m_cursorrow>=0 && m_cursorcol >=0) { - m_szCursorKey = GetCellValue(m_cursorrow,m_pkColumnIndex); + m_szCursorKey1 = GetCellValue(m_cursorrow,m_pkColumnIndex1); + if (m_pkColumnIndex2 >= 0) { + m_szCursorKey2 = GetCellValue(m_cursorrow,m_pkColumnIndex2); + } } } void CBOINCGridCtrl::RestoreGridCursorPosition() { - int index = GetTable()->FindRowIndexByColValue(m_pkColumnIndex,m_szCursorKey); + int index = GetTable()->FindRowIndexByColValue(m_pkColumnIndex1,m_szCursorKey1,m_pkColumnIndex2,m_szCursorKey2); if(index >=0) { SetGridCursor(index,m_cursorcol); } @@ -571,8 +587,7 @@ void CBOINCGridCtrl::OnLabelLClick(wxGridEvent& ev) { wxTimerEvent tEvent; wxDynamicCast(GetParent(),CBOINCBaseView)->FireOnListRender(tEvent); } - - ev.Skip(); + // The base class calls ClearSelection(), so do NOT call ev.Skip(); } void CBOINCGridCtrl::SortData() { @@ -869,7 +884,7 @@ void CBOINCGridTable::SortData(int col,bool ascending) { wxGridStringArray newArray; for(unsigned int i=0; i< arColValues.GetCount();i++) { //find the original row index - int indexold = FindRowIndexByColValue(col,arColValues[i]); + int indexold = FindRowIndexByColValue(col,arColValues[i],-1,arColValues[i]); wxArrayString rowArray; for(int j=0; j < this->GetNumberCols(); j++) { rowArray.Add(this->GetValue(indexold,j)); @@ -888,16 +903,16 @@ void CBOINCGridTable::SortData(int col,bool ascending) { } } -/* finds the first row index for the cell value value in column col - !! only use this (outside sorting method) with a column, that has unique values !! +/* finds the first row index for the cell with value value1 in column col1 and value2 in col2 + ignores col2 and value2 if col2 < 0 + !! only use this (outside sorting method) with a pair of columns, that have unique value pairs !! */ -int CBOINCGridTable::FindRowIndexByColValue(int col,wxString& value) { +int CBOINCGridTable::FindRowIndexByColValue(int col1,wxString& value1,int col2,wxString& value2) { for(int i=0; i < this->GetNumberRows(); i++) { - wxString curr = GetValue(i,col); - if(this->GetValue(i,col).IsSameAs(value)) { - return i; - } + if(! this->GetValue(i,col1).IsSameAs(value1)) continue; + if (col2 < 0) return i; + if(this->GetValue(i,col2).IsSameAs(value2)) return i; } return -1; } diff --git a/clientgui/BOINCGridCtrl.h b/clientgui/BOINCGridCtrl.h index 5ccaf3b1c4..672dbf5ab1 100644 --- a/clientgui/BOINCGridCtrl.h +++ b/clientgui/BOINCGridCtrl.h @@ -67,7 +67,7 @@ public: CBOINCGridTable(int rows,int cols); virtual ~CBOINCGridTable(); void SortData(int col,bool ascending); - int FindRowIndexByColValue(int col,wxString& value); + int FindRowIndexByColValue(int col1,wxString& value1,int col2,wxString& value2); void SetColumnSortType(int col,int sortType=CST_STRING); private: wxArrayInt arrColumnSortTypes; @@ -98,7 +98,7 @@ public: wxArrayInt GetSelectedRows2(); CBOINCGridTable* GetTable(); //methods to handle selection and grid cursor positions correct with sorting - void SetPrimaryKeyColumn(int col); + void SetPrimaryKeyColumns(int col1,int col2); void SaveSelection(); void RestoreSelection(); void SaveGridCursorPosition(); @@ -117,11 +117,14 @@ private: int ccollast,crowlast; wxBitmap ascBitmap; wxBitmap descBitmap; - int m_pkColumnIndex;//col index act as a primary key - wxArrayString m_arrSelectedKeys;//array for remembering the current selected rows by primary key column value + int m_pkColumnIndex1; //col index to use as a primary key + int m_pkColumnIndex2; //col index to use as secondary key + wxArrayString m_arrSelectedKeys1;//array for remembering the current selected rows by primary key column value + wxArrayString m_arrSelectedKeys2;//array for remembering the current selected rows by secondary key column value int m_cursorcol; //saved grid cursor column index int m_cursorrow; //saved grid cursor row index - wxString m_szCursorKey;//key value for grid cursor cell + wxString m_szCursorKey1;//primary key value for grid cursor cell + wxString m_szCursorKey2;//secondary key value for grid cursor cell }; #endif //_BOINCGRIDCTRL_H_ diff --git a/clientgui/ViewMessagesGrid.cpp b/clientgui/ViewMessagesGrid.cpp index f66ae36380..e4da7f37a7 100644 --- a/clientgui/ViewMessagesGrid.cpp +++ b/clientgui/ViewMessagesGrid.cpp @@ -142,7 +142,7 @@ CViewMessagesGrid::CViewMessagesGrid(wxNotebook* pNotebook) : m_pGridPane->SetColumnSortType(COLUMN_TIME,CST_TIME); m_pGridPane->SetColumnSortType(COLUMN_SEQNO,CST_LONG); //set primary key column index - m_pGridPane->SetPrimaryKeyColumn(COLUMN_SEQNO); + m_pGridPane->SetPrimaryKeyColumns(COLUMN_SEQNO,-1); UpdateSelection(); } diff --git a/clientgui/ViewProjectsGrid.cpp b/clientgui/ViewProjectsGrid.cpp index 919b344539..7e55e50e44 100644 --- a/clientgui/ViewProjectsGrid.cpp +++ b/clientgui/ViewProjectsGrid.cpp @@ -176,7 +176,7 @@ CViewProjectsGrid::CViewProjectsGrid(wxNotebook* pNotebook) : m_pGridPane->SetColumnSortType(COLUMN_RESOURCESHARE,CST_FLOAT); m_pGridPane->SetColumnSortType(COLUMN_AVGCREDIT,CST_FLOAT); // - m_pGridPane->SetPrimaryKeyColumn(COLUMN_PROJECT); + m_pGridPane->SetPrimaryKeyColumns(COLUMN_PROJECT,-1); UpdateSelection(); } @@ -771,12 +771,15 @@ void CViewProjectsGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { if(docCount != m_pGridPane->GetNumberRows()) { if (docCount > m_pGridPane->GetNumberRows()) { m_pGridPane->AppendRows(docCount - m_pGridPane->GetNumberRows()); - } else { - m_pGridPane->DeleteRows(0, m_pGridPane->GetNumberRows() - docCount); + } else { + m_pGridPane->DeleteRows(0, m_pGridPane->GetNumberRows() - docCount); + m_bForceUpdateSelection = true; } wxASSERT(docCount == m_pGridPane->GetNumberRows()); } + m_pGridPane->SaveSelection(); + wxString strBuffer; int iMax = m_pGridPane->GetNumberRows(); for(int iRow = 0; iRow < iMax; iRow++) { @@ -821,7 +824,8 @@ void CViewProjectsGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { m_pGridPane->SortData(); - UpdateSelection(); + m_pGridPane->RestoreSelection(); + UpdateSelection(); wxLogTrace(wxT("Function Start/End"), wxT("CViewProjectsGrid::OnListRender - Function End")); } diff --git a/clientgui/ViewTransfersGrid.cpp b/clientgui/ViewTransfersGrid.cpp index 29f5042186..50e7cbef26 100644 --- a/clientgui/ViewTransfersGrid.cpp +++ b/clientgui/ViewTransfersGrid.cpp @@ -140,7 +140,7 @@ CViewTransfersGrid::CViewTransfersGrid(wxNotebook* pNotebook) : //m_pGridPane->SetColumnSortType(COLUMN_SIZE,CST_FLOAT); m_pGridPane->SetColumnSortType(COLUMN_SPEED,CST_FLOAT); //set primary key column index - m_pGridPane->SetPrimaryKeyColumn(COLUMN_FILE); + m_pGridPane->SetPrimaryKeyColumns(COLUMN_FILE,COLUMN_PROJECT); UpdateSelection(); } @@ -485,11 +485,14 @@ void CViewTransfersGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { if (docCount > m_pGridPane->GetNumberRows()) { m_pGridPane->AppendRows(docCount - m_pGridPane->GetNumberRows()); } else { - m_pGridPane->DeleteRows(0, m_pGridPane->GetNumberRows() - docCount); + m_pGridPane->DeleteRows(0, m_pGridPane->GetNumberRows() - docCount); + m_bForceUpdateSelection = true; } wxASSERT(docCount == m_pGridPane->GetNumberRows()); } + m_pGridPane->SaveSelection(); + //update cell values wxString strBuffer; int iMax = m_pGridPane->GetNumberRows(); @@ -535,6 +538,7 @@ void CViewTransfersGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { m_pGridPane->SortData(); + m_pGridPane->RestoreSelection(); UpdateSelection(); } diff --git a/clientgui/ViewWorkGrid.cpp b/clientgui/ViewWorkGrid.cpp index e3638e63b1..e3b6a7d846 100644 --- a/clientgui/ViewWorkGrid.cpp +++ b/clientgui/ViewWorkGrid.cpp @@ -160,7 +160,7 @@ CViewWorkGrid::CViewWorkGrid(wxNotebook* pNotebook) : m_pGridPane->SetColumnSortType(COLUMN_REPORTDEADLINE,CST_DATETIME); m_pGridPane->SetColumnSortType(COLUMN_RESULTS_INDEX,CST_LONG); //set primary key column index - m_pGridPane->SetPrimaryKeyColumn(COLUMN_NAME); + m_pGridPane->SetPrimaryKeyColumns(COLUMN_NAME,COLUMN_PROJECT); // Hide the Index column int min_width = m_pGridPane->GetColMinimalAcceptableWidth(); m_pGridPane->SetColMinimalAcceptableWidth(0); @@ -845,8 +845,8 @@ void CViewWorkGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { return; } - // flag for row count changes - bool rowCountChanged=false; + // flag for row count changes + bool rowCountChanged=false; // Right-size the grid so that the number of rows matches // the document state. if(docCount != m_pGridPane->GetNumberRows()) { @@ -854,8 +854,9 @@ void CViewWorkGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { m_pGridPane->AppendRows(docCount - m_pGridPane->GetNumberRows()); rowCountChanged=true; } else { - m_pGridPane->DeleteRows(0, m_pGridPane->GetNumberRows() - docCount); + m_pGridPane->DeleteRows(0, m_pGridPane->GetNumberRows() - docCount); rowCountChanged=true; + m_bForceUpdateSelection = true; } wxASSERT(docCount == m_pGridPane->GetNumberRows()); } @@ -938,7 +939,8 @@ void CViewWorkGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { m_pGridPane->sortNeededByLabelClick) { wxArrayString ordered_indexes; - for(int iRow = 0; iRow < iMax; iRow++) { + m_pGridPane->SaveSelection(); + for(int iRow = 0; iRow < iMax; iRow++) { ordered_indexes.Add(m_pGridPane->GetCellValue(iRow, COLUMN_RESULTS_INDEX)); } @@ -947,6 +949,7 @@ void CViewWorkGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { for(int iRow = 0; iRow < iMax; iRow++) { if (ordered_indexes[iRow] != m_pGridPane->GetCellValue(iRow, COLUMN_RESULTS_INDEX)) { // Refresh entire grid if sort order has changed + m_pGridPane->RestoreSelection(); m_pGridPane->ForceRefresh(); break; }