diff --git a/clientgui/DlgEventLog.cpp b/clientgui/DlgEventLog.cpp index 34eb3397cd..419bd5fcde 100644 --- a/clientgui/DlgEventLog.cpp +++ b/clientgui/DlgEventLog.cpp @@ -136,6 +136,9 @@ bool CDlgEventLog::Create( wxWindow* parent, wxWindowID id, const wxString& capt m_iPreviousRowCount = 0; m_iTotalDocCount = 0; m_iPreviousTotalDocCount = 0; + m_iPreviousFirstMsgSeqNum = 0; + m_iPreviousLastMsgSeqNum = 0; + if (!s_bIsFiltered) { s_strFilteredProjectName.clear(); } @@ -443,29 +446,76 @@ wxInt32 CDlgEventLog::GetFilteredMessageIndex( wxInt32 iRow) const { // Get the (possibly filtered) item count (i.e., the Row count) wxInt32 CDlgEventLog::GetDocCount() { - int i; + int i, j, numDeletedRows; + int numDeletedFilteredRows = 0; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); - m_iTotalDocCount = wxGetApp().GetDocument()->GetMessageCount(); + m_iTotalDocCount = pDoc->GetMessageCount(); if (m_iTotalDocCount < m_iPreviousTotalDocCount) { // Usually due to a disconnect from client ResetMessageFiltering(); + m_iPreviousFirstMsgSeqNum = 0; + m_iPreviousLastMsgSeqNum = 0; } - + + numDeletedRows = pDoc->GetFirstMsgSeqNum() - m_iPreviousFirstMsgSeqNum; + if (s_bIsFiltered) { - for (i = m_iPreviousTotalDocCount; i < m_iTotalDocCount; i++) { - MESSAGE* message = wxGetApp().GetDocument()->message(i); + if (numDeletedRows > 0) { + // Remove any deleted messages from our filtered list + while (m_iFilteredIndexes.GetCount() > 0) { + if (m_iFilteredIndexes[0] >= numDeletedRows) break; + m_iFilteredIndexes.RemoveAt(0); + numDeletedFilteredRows++; + } + + // Adjust the remaining indexes + for (i = m_iFilteredIndexes.GetCount()-1; i >= 0; i--) { + m_iFilteredIndexes[i] -= numDeletedRows; + } + } + + // Add indexes of new messages to filtered list as appropriate + i = m_iTotalDocCount - (pDoc->GetLastMsgSeqNum() - m_iPreviousLastMsgSeqNum); + for (; i < m_iTotalDocCount; i++) { + MESSAGE* message = pDoc->message(i); if (message->project.empty() || (message->project == s_strFilteredProjectName)) { m_iFilteredIndexes.Add(i); } } - m_iPreviousTotalDocCount = m_iTotalDocCount; m_iFilteredDocCount = (int)(m_iFilteredIndexes.GetCount()); - return m_iFilteredDocCount; + } else { + m_iFilteredDocCount = m_iTotalDocCount; + numDeletedFilteredRows = numDeletedRows; + } + + if (numDeletedRows > 0) { + // Adjust the selected row numbers + wxArrayInt arrSelRows; + + i = -1; + for (;;) { + i = m_pList->GetNextItem(i, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (i < 0) break; + arrSelRows.Add(i); + } + int count = arrSelRows.Count(); + for (i=0; iSetItemState(arrSelRows[i], 0, wxLIST_STATE_SELECTED); + } + + for (i=0; i= 0) { + m_pList->SetItemState(j, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + } + } } m_iPreviousTotalDocCount = m_iTotalDocCount; - m_iFilteredDocCount = m_iTotalDocCount; - return m_iTotalDocCount; + + return s_bIsFiltered ? m_iFilteredDocCount : m_iTotalDocCount; } @@ -485,13 +535,16 @@ void CDlgEventLog::OnRefresh() { if (!m_bProcessingRefreshEvent) { m_bProcessingRefreshEvent = true; - wxASSERT(m_pList); wxInt32 iRowCount = GetDocCount(); + long topItem = m_pList->GetTopItem(); + if (0 >= iRowCount) { m_pList->DeleteAllItems(); ResetMessageFiltering(); + m_iPreviousFirstMsgSeqNum = 0; + m_iPreviousLastMsgSeqNum = 0; } else { // If connected computer changed, reset message filtering isConnected = wxGetApp().GetDocument()->IsConnected(); @@ -501,6 +554,8 @@ void CDlgEventLog::OnRefresh() { strLastMachineName = strNewMachineName; was_connected = false; ResetMessageFiltering(); + m_iPreviousFirstMsgSeqNum = 0; + m_iPreviousLastMsgSeqNum = 0; } } @@ -516,19 +571,26 @@ void CDlgEventLog::OnRefresh() { } else { // Connection status didn't change - if (m_iPreviousRowCount != iRowCount) { + if (m_iPreviousLastMsgSeqNum != pDoc->GetLastMsgSeqNum()) { m_pList->SetItemCount(iRowCount); } } } - if ((iRowCount > 1) && (EnsureLastItemVisible()) && (m_iPreviousRowCount != iRowCount)) { - m_pList->EnsureVisible(iRowCount - 1); + if ((iRowCount > 1) && (m_iPreviousLastMsgSeqNum != pDoc->GetLastMsgSeqNum())) { + if (EnsureLastItemVisible()) { + m_pList->EnsureVisible(iRowCount - 1); + } else if (topItem > 0) { + int numDeletedRows = pDoc->GetFirstMsgSeqNum() - m_iPreviousFirstMsgSeqNum; + Freeze(); // Avoid flicker if selected rows are visible + m_pList->EnsureVisible(topItem - numDeletedRows); + Thaw(); + } } - if (m_iPreviousRowCount != iRowCount) { - m_iPreviousRowCount = iRowCount; - } + m_iPreviousRowCount = iRowCount; + m_iPreviousFirstMsgSeqNum = pDoc->GetFirstMsgSeqNum(); + m_iPreviousLastMsgSeqNum = pDoc->GetLastMsgSeqNum(); UpdateButtons(); @@ -842,6 +904,7 @@ wxListItemAttr* CDlgEventLog::OnListGetItemAttr(long item) const { if (wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) != wxColor(wxT("WHITE"))) return NULL; if (message) { + item += m_iPreviousFirstMsgSeqNum; switch(message->priority) { case MSG_USER_ALERT: pAttribute = item % 2 ? m_pMessageErrorGrayAttr : m_pMessageErrorAttr; diff --git a/clientgui/DlgEventLog.h b/clientgui/DlgEventLog.h index 4d11b39187..d3c9c6c8d0 100644 --- a/clientgui/DlgEventLog.h +++ b/clientgui/DlgEventLog.h @@ -148,6 +148,9 @@ private: wxInt32 m_iTotalDocCount; wxInt32 m_iFilteredDocCount; wxInt32 m_iPreviousTotalDocCount; + wxInt32 m_iPreviousFirstMsgSeqNum; + wxInt32 m_iPreviousLastMsgSeqNum; + wxInt32 m_iPreviousRowCount; wxButton* m_pFilterButton; wxButton* m_pCopySelectedButton; diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp index 275ad4367e..5275b6e522 100644 --- a/clientgui/MainDocument.cpp +++ b/clientgui/MainDocument.cpp @@ -45,6 +45,8 @@ #include #endif +#define MAX_DISPLAYED_MESSAGES 2000 + #define USE_CACHE_TIMEOUTS 0 // If get_results RPC takes x seconds, do it no more often than @@ -402,7 +404,8 @@ CMainDocument::CMainDocument() : rpc(this) { m_fProjectTotalResourceShare = 0.0; - m_iMessageSequenceNumber = 0; + m_iLastMessageSequenceNumber = 0; + m_iFirstMessageSequenceNumber = -1; m_iNoticeSequenceNumber = 0; m_iLastReadNoticeSequenceNumber = -1; @@ -954,9 +957,9 @@ void CMainDocument::RunPeriodicRPCs(int frameRefreshRate) { // request.clear(); request.which_rpc = RPC_GET_MESSAGES; - // m_iMessageSequenceNumber could change between request and execution + // m_iLastMessageSequenceNumber could change between request and execution // of RPC, so pass in a pointer rather than its value - request.arg1 = &m_iMessageSequenceNumber; + request.arg1 = &m_iLastMessageSequenceNumber; request.arg2 = &messages; static bool _true = true; request.arg3 = &_true; @@ -2019,21 +2022,33 @@ bool CMainDocument::LocalizeNoticeText(wxString& strMessage, bool bSanitize, boo // int CMainDocument::CachedMessageUpdate() { static bool in_this_func = false; + size_t last_ind; if (in_this_func) return 0; in_this_func = true; if (IsConnected()) { // rpc.get_messages is now called from RunPeriodicRPCs() - // retval = rpc.get_messages(m_iMessageSequenceNumber, messages); + // retval = rpc.get_messages(m_iLastMessageSequenceNumber, messages); if (m_iGet_messages_rpc_result) { wxLogTrace(wxT("Function Status"), wxT("CMainDocument::CachedMessageUpdate - Get Messages Failed '%d'"), m_iGet_messages_rpc_result); m_pNetworkConnection->SetStateDisconnected(); goto done; } if (messages.messages.size() != 0) { - size_t last_ind = messages.messages.size()-1; - m_iMessageSequenceNumber = messages.messages[last_ind]->seqno; + last_ind = messages.messages.size()-1; + m_iLastMessageSequenceNumber = messages.messages[last_ind]->seqno; + + if (last_ind >= MAX_DISPLAYED_MESSAGES) { + // Remove oldest messages if we have too many + while (messages.messages.size() > MAX_DISPLAYED_MESSAGES) { + delete messages.messages.front(); + messages.messages.pop_front(); + } + m_iFirstMessageSequenceNumber = messages.messages[0]->seqno; + } else if (m_iFirstMessageSequenceNumber < 0) { + m_iFirstMessageSequenceNumber = messages.messages[0]->seqno; + } } } @@ -2075,7 +2090,8 @@ int CMainDocument::GetMessageCount() { int CMainDocument::ResetMessageState() { messages.clear(); - m_iMessageSequenceNumber = 0; + m_iLastMessageSequenceNumber = 0; + m_iFirstMessageSequenceNumber = -1; return 0; } diff --git a/clientgui/MainDocument.h b/clientgui/MainDocument.h index edb5c4a436..58c3a4b6ef 100644 --- a/clientgui/MainDocument.h +++ b/clientgui/MainDocument.h @@ -321,8 +321,11 @@ public: int ResetMessageState(); - int m_iMessageSequenceNumber; + int m_iFirstMessageSequenceNumber; + int m_iLastMessageSequenceNumber; + int GetFirstMsgSeqNum() { return m_iFirstMessageSequenceNumber; } + int GetLastMsgSeqNum() { return m_iLastMessageSequenceNumber; } // // Transfers Tab diff --git a/lib/gui_rpc_client.h b/lib/gui_rpc_client.h index cccaf27902..2fc3015907 100644 --- a/lib/gui_rpc_client.h +++ b/lib/gui_rpc_client.h @@ -33,6 +33,8 @@ #include #endif +#include + #include "cc_config.h" #include "common_defs.h" #include "filesys.h" @@ -456,7 +458,7 @@ struct FILE_TRANSFERS { }; struct MESSAGES { - std::vector messages; + std::deque messages; MESSAGES(); ~MESSAGES();