// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . #if defined(__GNUG__) && !defined(__APPLE__) #pragma implementation "DlgEventLog.h" #endif #include "stdwx.h" #include "common_defs.h" #include "diagnostics.h" #include "str_util.h" #include "mfile.h" #include "miofile.h" #include "parse.h" #include "error_numbers.h" #include "Events.h" #include "BOINCGUIApp.h" #include "SkinManager.h" #include "MainDocument.h" #include "BOINCBaseFrame.h" #include "version.h" #include "DlgEventLogListCtrl.h" #include "DlgEventLog.h" #include "AdvancedFrame.h" ////@begin includes ////@end includes ////@begin XPM images ////@end XPM images #define COLUMN_PROJECT 0 #define COLUMN_TIME 1 #define COLUMN_MESSAGE 2 /*! * CDlgEventLog type definition */ IMPLEMENT_DYNAMIC_CLASS( CDlgEventLog, wxDialog ) /*! * CDlgEventLog event table definition */ BEGIN_EVENT_TABLE( CDlgEventLog, wxDialog ) ////@begin CDlgEventLog event table entries EVT_SHOW(CDlgEventLog::OnShow) EVT_HELP(wxID_ANY, CDlgEventLog::OnHelp) EVT_BUTTON(wxID_OK, CDlgEventLog::OnOK) EVT_BUTTON(ID_COPYAll, CDlgEventLog::OnMessagesCopyAll) EVT_BUTTON(ID_COPYSELECTED, CDlgEventLog::OnMessagesCopySelected) EVT_BUTTON(ID_TASK_MESSAGES_FILTERBYPROJECT, CDlgEventLog::OnMessagesFilter) EVT_BUTTON(ID_SIMPLE_HELP, CDlgEventLog::OnButtonHelp) EVT_CLOSE(CDlgEventLog::OnClose) ////@end CDlgEventLog event table entries END_EVENT_TABLE() /*! * CDlgEventLog constructors */ CDlgEventLog::CDlgEventLog( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::CDlgEventLog - Constructor Function Begin")); Create(parent, id, caption, pos, size, style); wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::CDlgEventLog - Constructor Function End")); } CDlgEventLog::~CDlgEventLog() { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::CDlgEventLog - Destructor Function Begin")); SaveState(); // Save state if close box on window frame clicked if (m_pMessageInfoAttr) { delete m_pMessageInfoAttr; m_pMessageInfoAttr = NULL; } if (m_pMessageErrorAttr) { delete m_pMessageErrorAttr; m_pMessageErrorAttr = NULL; } if (m_pMessageInfoGrayAttr) { delete m_pMessageInfoGrayAttr; m_pMessageInfoGrayAttr = NULL; } if (m_pMessageErrorGrayAttr) { delete m_pMessageErrorGrayAttr; m_pMessageErrorGrayAttr = NULL; } m_strFilteredProjectName.clear(); m_iFilteredIndexes.Clear(); wxGetApp().OnEventLogClose(); wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::CDlgEventLog - Destructor Function End")); } /*! * CDlgEventLog creator */ bool CDlgEventLog::Create( wxWindow* WXUNUSED(parent), wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) { ////@begin CDlgEventLog member initialisation m_iPreviousRowCount = 0; m_iTotalDocCount = 0; m_iPreviousTotalDocCount = 0; m_bIsFiltered = false; m_strFilteredProjectName.clear(); m_iFilteredIndexes.Clear(); m_bProcessingRefreshEvent = false; ////@end CDlgEventLog member initialisation CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced(); wxASSERT(pSkinAdvanced); wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced)); SetExtraStyle(GetExtraStyle()|wxDIALOG_EX_CONTEXTHELP|wxWS_EX_BLOCK_EVENTS); wxDialog::Create( NULL, id, caption, pos, size, style ); // Initialize Application Title wxString strCaption = caption; if (strCaption.IsEmpty()) { strCaption.Printf(_("%s - Event Log"), pSkinAdvanced->GetApplicationName().c_str()); } SetTitle(strCaption); // Initialize Application Icon wxIconBundle icons; icons.AddIcon(*pSkinAdvanced->GetApplicationIcon()); icons.AddIcon(*pSkinAdvanced->GetApplicationIcon32()); SetIcons(icons); CreateControls(); // Create List Pane Items m_pList->InsertColumn(COLUMN_PROJECT, _("Project"), wxLIST_FORMAT_LEFT, 109); m_pList->InsertColumn(COLUMN_TIME, _("Time"), wxLIST_FORMAT_LEFT, 130); m_pList->InsertColumn(COLUMN_MESSAGE, _("Message"), wxLIST_FORMAT_LEFT, 378); m_pMessageInfoAttr = new wxListItemAttr( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW), wxNullFont ); m_pMessageErrorAttr = new wxListItemAttr( *wxRED, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW), wxNullFont ); #if EVENT_LOG_STRIPES m_pMessageInfoGrayAttr = new wxListItemAttr(*wxBLACK, wxColour(240, 240, 240), wxNullFont); m_pMessageErrorGrayAttr = new wxListItemAttr(*wxRED, wxColour(240, 240, 240), wxNullFont); m_pMessageErrorGrayAttr = new wxListItemAttr(*wxRED, wxColour(0, 0, 0, 15), wxNullFont); #else m_pMessageInfoGrayAttr = new wxListItemAttr(*m_pMessageInfoAttr); m_pMessageErrorGrayAttr = new wxListItemAttr(*m_pMessageErrorAttr); #endif GetSizer()->Fit(this); GetSizer()->SetSizeHints(this); Center(); // To work properly on Mac, RestoreState() must be called _after_ // calling GetSizer()->Fit(), GetSizer()->SetSizeHints() and Center() RestoreState(); return true; } /*! * Control creation for CDlgEventLog */ void CDlgEventLog::CreateControls() { wxFlexGridSizer* itemFlexGridSizer2 = new wxFlexGridSizer(2, 1, 0, 0); itemFlexGridSizer2->AddGrowableRow(0); itemFlexGridSizer2->AddGrowableCol(0); SetSizer(itemFlexGridSizer2); m_pList = new CDlgEventLogListCtrl(this, ID_SIMPLE_MESSAGESVIEW, EVENT_LOG_DEFAULT_LIST_MULTI_SEL_FLAGS); itemFlexGridSizer2->Add(m_pList, 0, wxGROW|wxALL, 5); wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL); itemFlexGridSizer2->Add(itemBoxSizer4, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 12); m_pFilterButton = new wxButton(this, ID_TASK_MESSAGES_FILTERBYPROJECT, _("Show only this project"), wxDefaultPosition, wxDefaultSize); itemBoxSizer4->Add(m_pFilterButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); #ifdef wxUSE_TOOLTIPS m_pFilterButton->SetToolTip(_("Show only the messages for the selected project")); #endif #ifdef wxUSE_CLIPBOARD wxButton* itemButton1 = new wxButton(this, ID_COPYAll, _("Copy All"), wxDefaultPosition, wxDefaultSize ); itemButton1->SetHelpText( _("Copy all the messages to the clipboard.") ); #if wxUSE_TOOLTIPS itemButton1->SetToolTip( _("Copy all the messages to the clipboard.") ); #endif itemBoxSizer4->Add(itemButton1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); m_pCopySelectedButton = new wxButton(this, ID_COPYSELECTED, _("Copy Selected"), wxDefaultPosition, wxDefaultSize ); m_pCopySelectedButton->SetHelpText( #ifdef __WXMAC__ _("Copy the selected messages to the clipboard. You can select multiple messages by holding down the shift or command key while clicking on messages.") #else _("Copy the selected messages to the clipboard. You can select multiple messages by holding down the shift or control key while clicking on messages.") #endif ); #if wxUSE_TOOLTIPS m_pCopySelectedButton->SetToolTip( #ifdef __WXMAC__ _("Copy the selected messages to the clipboard. You can select multiple messages by holding down the shift or command key while clicking on messages.") #else _("Copy the selected messages to the clipboard. You can select multiple messages by holding down the shift or control key while clicking on messages.") #endif ); #endif itemBoxSizer4->Add(m_pCopySelectedButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); #endif wxButton* itemButton44 = new wxButton(this, wxID_OK, _("Close"), wxDefaultPosition, wxDefaultSize); itemBoxSizer4->Add(itemButton44, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); #ifndef __WXMSW__ #ifdef __WXMAC__ wxButton* itemButton45 = new wxButton(this, ID_SIMPLE_HELP, _("Help"), wxDefaultPosition, wxDefaultSize); itemButton45->SetHelpText( _("Get help with BOINC") ); #ifdef wxUSE_TOOLTIPS itemButton45->SetToolTip(_("Get help with BOINC")); #endif itemBoxSizer4->Add(itemButton45, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); #else wxContextHelpButton* itemButton45 = new wxContextHelpButton(this); itemBoxSizer4->Add(itemButton45, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); #endif #endif } /*! * wxEVT_SHOW event handler for ID_DLGMESSAGES */ void CDlgEventLog::OnShow(wxShowEvent& event) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnShow - Function Begin")); static bool bAlreadyRunning = false; if ((event.GetEventObject() == this) && !bAlreadyRunning) { bAlreadyRunning = true; wxLogTrace(wxT("Function Status"), wxT("CDlgEventLog::OnShow - Show/Hide Event for CAdvancedFrame detected")); if (event.GetShow()) { RestoreWindowDimensions(); } else { SaveWindowDimensions(); } bAlreadyRunning = false; } else { event.Skip(); } wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnShow - Function End")); } /*! * wxEVT_HELP event handler for ID_DLGMESSAGES */ void CDlgEventLog::OnHelp(wxHelpEvent& event) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnHelp - Function Begin")); if (IsShown()) { wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl(); wxString wxurl; wxurl.Printf( wxT("%s?target=simple_messages&version=%s&controlid=%d"), strURL.c_str(), wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(), event.GetId() ); wxLaunchDefaultBrowser(wxurl); } wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnHelp - Function End")); } /*! * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK */ void CDlgEventLog::OnOK( wxCommandEvent& WXUNUSED(event) ) { Destroy(); } /*! * wxEVT_CLOSE event handler for CDlgEventLog (window close control clicked) */ void CDlgEventLog::OnClose(wxCloseEvent& WXUNUSED(event)) { Destroy(); } void CDlgEventLog::OnMessagesFilter( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnMessagesFilter - Function Begin")); wxInt32 iIndex = -1; MESSAGE* message; wxASSERT(m_pList); m_iFilteredIndexes.Clear(); m_strFilteredProjectName.clear(); if (m_bIsFiltered) { m_bIsFiltered = false; m_pFilterButton->SetLabel( _("Show only this project") ); m_pFilterButton->SetHelpText( _("Show only the messages for the selected project") ); #ifdef wxUSE_TOOLTIPS m_pFilterButton->SetToolTip(_("Show only the messages for the selected project")); #endif m_iFilteredDocCount = m_iTotalDocCount; } else { iIndex = m_pList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if (iIndex >= 0) { message = wxGetApp().GetDocument()->message(iIndex); if ((message->project).size() > 0) { m_strFilteredProjectName = message->project; m_bIsFiltered = true; m_pFilterButton->SetLabel( _("Show all messages") ); m_pFilterButton->SetHelpText( _("Show messages for all projects") ); #ifdef wxUSE_TOOLTIPS m_pFilterButton->SetToolTip(_("Show messages for all projects")); #endif for (iIndex = 0; iIndex < m_iTotalDocCount; iIndex++) { message = wxGetApp().GetDocument()->message(iIndex); if (message->project.empty() || (message->project == m_strFilteredProjectName)) { m_iFilteredIndexes.Add(iIndex); } } m_iFilteredDocCount = (int)(m_iFilteredIndexes.GetCount()); } } } // Force a complete update m_iPreviousRowCount = 0; m_pList->DeleteAllItems(); m_pList->SetItemCount(m_iFilteredDocCount); OnRefresh(); wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnMessagesFilter - Function End")); } wxInt32 CDlgEventLog::GetFilteredMessageIndex( wxInt32 iRow) const { if (m_bIsFiltered) return m_iFilteredIndexes[iRow]; return iRow; } // Get the (possibly filtered) item count (i.e., the Row count) wxInt32 CDlgEventLog::GetDocCount() { int i; m_iTotalDocCount = wxGetApp().GetDocument()->GetMessageCount(); if (m_iTotalDocCount < m_iPreviousTotalDocCount) { // Usually due to a disconnect from client m_bIsFiltered = false; m_strFilteredProjectName.clear(); m_iFilteredIndexes.Clear(); } if (m_bIsFiltered) { for (i = m_iPreviousTotalDocCount; i < m_iTotalDocCount; i++) { MESSAGE* message = wxGetApp().GetDocument()->message(i); if (message->project.empty() || (message->project == m_strFilteredProjectName)) { m_iFilteredIndexes.Add(i); } } m_iPreviousTotalDocCount = m_iTotalDocCount; m_iFilteredDocCount = (int)(m_iFilteredIndexes.GetCount()); return m_iFilteredDocCount; } m_iPreviousTotalDocCount = m_iTotalDocCount; m_iFilteredDocCount = m_iTotalDocCount; return m_iTotalDocCount; } /*! * called from CMainDocument::HandleCompletedRPC() after wxEVT_RPC_FINISHED event */ void CDlgEventLog::OnRefresh() { bool isConnected; static bool was_connected = false; if (!m_bProcessingRefreshEvent) { m_bProcessingRefreshEvent = true; wxASSERT(m_pList); wxInt32 iRowCount = GetDocCount(); if (0 >= iRowCount) { m_pList->DeleteAllItems(); } else { // If connection status changed, adjust color of messages display isConnected = wxGetApp().GetDocument()->IsConnected(); if (was_connected != isConnected) { was_connected = isConnected; if (isConnected) { m_pMessageInfoAttr->SetTextColour(*wxBLACK); m_pMessageErrorAttr->SetTextColour(*wxRED); m_pMessageInfoGrayAttr->SetTextColour(*wxBLACK); m_pMessageErrorGrayAttr->SetTextColour(*wxRED); } else { wxColourDatabase colorBase; m_pMessageInfoAttr->SetTextColour(wxColour(128, 128, 128)); m_pMessageErrorAttr->SetTextColour(wxColour(255, 128, 128)); m_pMessageInfoGrayAttr->SetTextColour(wxColour(128, 128, 128)); m_pMessageErrorGrayAttr->SetTextColour(wxColour(255, 128, 128)); } // Force a complete update m_pList->DeleteAllItems(); m_pList->SetItemCount(iRowCount); m_iPreviousRowCount = 0; // Force scrolling to bottom } else { // Connection status didn't change if (m_iPreviousRowCount != iRowCount) { m_pList->SetItemCount(iRowCount); } } } if ((iRowCount > 1) && (EnsureLastItemVisible()) && (m_iPreviousRowCount != iRowCount)) { m_pList->EnsureVisible(iRowCount - 1); } #if 0 // This was in ViewMessages.cpp; is it needed herre? if (isConnected) { pDoc->GetConnectedComputerName(strNewMachineName); if (strLastMachineName != strNewMachineName) { strLastMachineName = strNewMachineName; if (iRowCount) { m_pList->EnsureVisible(iRowCount - 1); } } } #endif if (m_iPreviousRowCount != iRowCount) { m_iPreviousRowCount = iRowCount; } UpdateButtons(); m_bProcessingRefreshEvent = false; } } bool CDlgEventLog::SaveState() { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::SaveState - Function Begin")); wxString strBaseConfigLocation = wxString(wxT("/Messages/")); wxConfigBase* pConfig = wxConfigBase::Get(FALSE); wxListItem liColumnInfo; wxInt32 iIndex = 0; wxInt32 iColumnCount = 0; wxASSERT(pConfig); // An odd case happens every once and awhile where wxWidgets looses // the pointer to the config object, or it is cleaned up before // the window has finished it's cleanup duty. If we detect a NULL // pointer, return false. if (!pConfig) return false; // // Save Frame State // // Reterieve and store the latest window dimensions. SaveWindowDimensions(); pConfig->SetPath(strBaseConfigLocation); // Convert to a zero based index iColumnCount = m_pList->GetColumnCount() - 1; // Which fields are we interested in? liColumnInfo.SetMask( wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH | wxLIST_MASK_FORMAT ); // Cycle through the columns recording anything interesting for (iIndex = 0; iIndex <= iColumnCount; iIndex++) { m_pList->GetColumn(iIndex, liColumnInfo); pConfig->SetPath(strBaseConfigLocation + liColumnInfo.GetText()); pConfig->Write(wxT("Width"), m_pList->GetColumnWidth(iIndex)); // Work around bug in wxMac-2.8.0 wxListCtrl::SetColumn() } wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::SaveState - Function End")); return true; } void CDlgEventLog::SaveWindowDimensions() { wxString strBaseConfigLocation = wxString(wxT("/EventLog")); wxConfigBase* pConfig = wxConfigBase::Get(FALSE); wxASSERT(pConfig); pConfig->SetPath(strBaseConfigLocation); pConfig->Write(wxT("WindowIconized"), IsIconized()); pConfig->Write(wxT("WindowMaximized"), IsMaximized()); pConfig->Write(wxT("Width"), GetSize().GetWidth()); pConfig->Write(wxT("Height"), GetSize().GetHeight()); #ifdef __WXMAC__ pConfig->Write(wxT("XPos"), GetPosition().x); pConfig->Write(wxT("YPos"), GetPosition().y); #endif // ! __WXMAC__ } bool CDlgEventLog::RestoreState() { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::RestoreState - Function Begin")); wxString strBaseConfigLocation = wxString(wxT("/Messages/")); wxConfigBase* pConfig = wxConfigBase::Get(FALSE); wxListItem liColumnInfo; wxInt32 iIndex = 0; wxInt32 iColumnCount = 0; wxInt32 iTempValue = 0; wxASSERT(pConfig); // An odd case happens every once and awhile where wxWidgets looses // the pointer to the config object, or it is cleaned up before // the window has finished it's cleanup duty. If we detect a NULL // pointer, return false. if (!pConfig) return false; // // Restore Frame State // // Restore the windows properties RestoreWindowDimensions(); pConfig->SetPath(strBaseConfigLocation); // Convert to a zero based index iColumnCount = m_pList->GetColumnCount() - 1; // Which fields are we interested in? liColumnInfo.SetMask( wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH | wxLIST_MASK_FORMAT ); // Cycle through the columns recording anything interesting for (iIndex = 0; iIndex <= iColumnCount; iIndex++) { m_pList->GetColumn(iIndex, liColumnInfo); pConfig->SetPath(strBaseConfigLocation + liColumnInfo.GetText()); pConfig->Read(wxT("Width"), &iTempValue, -1); if (-1 != iTempValue) { liColumnInfo.SetWidth(iTempValue); #if (defined(__WXMAC__) && wxCHECK_VERSION(2,8,0)) m_pList->SetColumnWidth(iIndex,iTempValue); // Work around bug in wxMac-2.8.0 wxListCtrl::SetColumn() #endif } m_pList->SetColumn(iIndex, liColumnInfo); } wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::RestoreState - Function End")); return true; } void CDlgEventLog::RestoreWindowDimensions() { wxString strBaseConfigLocation = wxString(wxT("/EventLog")); wxConfigBase* pConfig = wxConfigBase::Get(FALSE); bool bWindowIconized = false; bool bWindowMaximized = false; int iHeight = 0; int iWidth = 0; int iTop = 0; int iLeft = 0; wxASSERT(pConfig); pConfig->SetPath(strBaseConfigLocation); pConfig->Read(wxT("YPos"), &iTop, 30); pConfig->Read(wxT("XPos"), &iLeft, 30); pConfig->Read(wxT("Width"), &iWidth, 640); pConfig->Read(wxT("Height"), &iHeight, 480); pConfig->Read(wxT("WindowIconized"), &bWindowIconized, false); pConfig->Read(wxT("WindowMaximized"), &bWindowMaximized, false); #ifndef __WXMAC__ Iconize(bWindowIconized); Maximize(bWindowMaximized); if (!IsIconized() && !IsMaximized()) { SetSize(-1, -1, iWidth, iHeight); } #else // ! __WXMAC__ // If the user has changed the arrangement of multiple // displays, make sure the window title bar is still on-screen. Rect titleRect = {iTop, iLeft, iTop+22, iLeft+iWidth }; InsetRect(&titleRect, 5, 5); // Make sure at least a 5X5 piece visible RgnHandle displayRgn = NewRgn(); CopyRgn(GetGrayRgn(), displayRgn); // Region encompassing all displays Rect menuRect = ((**GetMainDevice())).gdRect; menuRect.bottom = GetMBarHeight() + menuRect.top; RgnHandle menuRgn = NewRgn(); RectRgn(menuRgn, &menuRect); // Region hidden by menu bar DiffRgn(displayRgn, menuRgn, displayRgn); // Subtract menu bar retion if (!RectInRgn(&titleRect, displayRgn)) iTop = iLeft = 30; DisposeRgn(menuRgn); DisposeRgn(displayRgn); SetSize(iLeft, iTop, iWidth, iHeight); #endif // ! __WXMAC__ } /*! * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_COPYAll */ void CDlgEventLog::OnMessagesCopyAll( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnMessagesCopyAll - Function Begin")); #ifdef wxUSE_CLIPBOARD wxInt32 iIndex = -1; wxInt32 iRowCount = 0; iRowCount = m_pList->GetItemCount(); OpenClipboard( iRowCount * 1024 ); for (iIndex = 0; iIndex < iRowCount; iIndex++) { CopyToClipboard(iIndex); } CloseClipboard(); #endif wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnMessagesCopyAll - Function End")); } /*! * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_COPYSELECTED */ void CDlgEventLog::OnMessagesCopySelected( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnMessagesCopySelected - Function Begin")); #ifdef wxUSE_CLIPBOARD wxInt32 iIndex = -1; wxInt32 iRowCount = 0; // Count the number of items selected for (;;) { iIndex = m_pList->GetNextItem( iIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); if (iIndex == -1) break; iRowCount++; } OpenClipboard( iRowCount * 1024 ); // Reset the position indicator iIndex = -1; for (;;) { iIndex = m_pList->GetNextItem( iIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); if (iIndex == -1) break; CopyToClipboard(iIndex); } CloseClipboard(); #endif wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnMessagesCopySelected - Function End")); } /*! * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SIMPLE_HELP */ void CDlgEventLog::OnButtonHelp( wxCommandEvent& event ) { wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnHelp - Function Begin")); if (IsShown()) { wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl(); wxString wxurl; wxurl.Printf( wxT("%s?target=simple_messages&version=%s&controlid=%d"), strURL.c_str(), wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(), event.GetId() ); wxLaunchDefaultBrowser(wxurl); } wxLogTrace(wxT("Function Start/End"), wxT("CDlgEventLog::OnHelp - Function End")); } void CDlgEventLog::UpdateButtons() { bool enableFilterButton = m_bIsFiltered; bool enableCopySelectedButon = false; if ((! m_bIsFiltered) && (m_iTotalDocCount > 0)) { int n = m_pList->GetSelectedItemCount(); if (n > 0) { enableCopySelectedButon = true; } if (n == 1) { n = m_pList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); MESSAGE* message = wxGetApp().GetDocument()->message(n); if ((message->project).size() > 0) { enableFilterButton = true; } } } m_pFilterButton->Enable(enableFilterButton); m_pCopySelectedButton->Enable(enableCopySelectedButon); } wxString CDlgEventLog::OnListGetItemText(long item, long column) const { wxString strBuffer = wxEmptyString; wxInt32 index = GetFilteredMessageIndex(item); switch(column) { case COLUMN_PROJECT: FormatProjectName(index, strBuffer); break; case COLUMN_TIME: FormatTime(index, strBuffer); break; case COLUMN_MESSAGE: FormatMessage(index, strBuffer); break; } return strBuffer; } wxListItemAttr* CDlgEventLog::OnListGetItemAttr(long item) const { wxListItemAttr* pAttribute = NULL; MESSAGE* message = wxGetApp().GetDocument()->message(item); if (message) { switch(message->priority) { case MSG_USER_ALERT: pAttribute = item % 2 ? m_pMessageErrorGrayAttr : m_pMessageErrorAttr; break; default: pAttribute = item % 2 ? m_pMessageInfoGrayAttr : m_pMessageInfoAttr; break; } } return pAttribute; } bool CDlgEventLog::EnsureLastItemVisible() { int numVisible = m_pList->GetCountPerPage(); // Auto-scroll only if already at bottom of list if ((m_iPreviousRowCount > numVisible) && ((m_pList->GetTopItem() + numVisible) < (m_iPreviousRowCount-1)) ) { return false; } return true; } wxInt32 CDlgEventLog::FormatProjectName(wxInt32 item, wxString& strBuffer) const { MESSAGE* message = wxGetApp().GetDocument()->message(item); if (message) { strBuffer = wxString(message->project.c_str(), wxConvUTF8); } return 0; } wxInt32 CDlgEventLog::FormatTime(wxInt32 item, wxString& strBuffer) const { wxDateTime dtBuffer; MESSAGE* message = wxGetApp().GetDocument()->message(item); if (message) { dtBuffer.Set((time_t)message->timestamp); strBuffer = dtBuffer.Format(); } return 0; } wxInt32 CDlgEventLog::FormatMessage(wxInt32 item, wxString& strBuffer) const { MESSAGE* message = wxGetApp().GetDocument()->message(item); if (message) { strBuffer = wxString(message->body.c_str(), wxConvUTF8); } strBuffer.Replace(wxT("\n"), wxT(""), true); return 0; } #ifdef wxUSE_CLIPBOARD bool CDlgEventLog::OpenClipboard( wxInt32 size ) { bool bRetVal = false; bRetVal = wxTheClipboard->Open(); if (bRetVal) { m_bClipboardOpen = true; m_strClipboardData = wxEmptyString; m_strClipboardData.Alloc( size ); wxTheClipboard->Clear(); } return bRetVal; } wxInt32 CDlgEventLog::CopyToClipboard(wxInt32 item) { wxInt32 iRetVal = -1; if (m_bClipboardOpen) { wxString strBuffer = wxEmptyString; wxString strTimeStamp = wxEmptyString; wxString strProject = wxEmptyString; wxString strMessage = wxEmptyString; FormatTime(item, strTimeStamp); FormatProjectName(item, strProject); FormatMessage(item, strMessage); #ifdef __WXMSW__ strBuffer.Printf(wxT("%s|%s|%s\r\n"), strTimeStamp.c_str(), strProject.c_str(), strMessage.c_str()); #else strBuffer.Printf(wxT("%s|%s|%s\n"), strTimeStamp.c_str(), strProject.c_str(), strMessage.c_str()); #endif m_strClipboardData += strBuffer; iRetVal = 0; } return iRetVal; } bool CDlgEventLog::CloseClipboard() { bool bRetVal = false; if (m_bClipboardOpen) { wxTheClipboard->SetData(new wxTextDataObject(m_strClipboardData)); wxTheClipboard->Close(); m_bClipboardOpen = false; m_strClipboardData = wxEmptyString; } return bRetVal; } #endif