diff --git a/checkin_notes b/checkin_notes index 0b0020946b..18569b29d1 100755 --- a/checkin_notes +++ b/checkin_notes @@ -13710,3 +13710,17 @@ David 27 Dec 2006 am_set_info.php edit_email_action.php validate_email.php (removed) + +David 27 Dec 2006 + - Manager: new version of Work tab with progress bar. + This is a work in progress; for now, include both old and new tabs. + (from Frank Weiler) + + clientgui/ + AdvancedFrame.cpp + BOINCGridCtrl.cpp,h (new) + Events.h + ViewWorkGrid.cpp,h (new) + stdwx.h + win_build/ + boincmgr_curl.vcproj diff --git a/clientgui/AdvancedFrame.cpp b/clientgui/AdvancedFrame.cpp index 94dceb849d..a00c4ddadc 100644 --- a/clientgui/AdvancedFrame.cpp +++ b/clientgui/AdvancedFrame.cpp @@ -42,6 +42,7 @@ #include "AdvancedFrame.h" #include "ViewProjects.h" #include "ViewWork.h" +#include "ViewWorkGrid.h" #include "ViewTransfers.h" #include "ViewMessages.h" #include "ViewStatistics.h" @@ -602,6 +603,7 @@ bool CAdvancedFrame::CreateNotebook() { CreateNotebookPage(new CViewMessages(m_pNotebook)); CreateNotebookPage(new CViewStatistics(m_pNotebook)); CreateNotebookPage(new CViewResources(m_pNotebook)); + CreateNotebookPage(new CViewWorkGrid(m_pNotebook)); pPanel->SetSizer(pPanelSizer); diff --git a/clientgui/BOINCGridCtrl.cpp b/clientgui/BOINCGridCtrl.cpp new file mode 100644 index 0000000000..cb615db2db --- /dev/null +++ b/clientgui/BOINCGridCtrl.cpp @@ -0,0 +1,108 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This 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 2.1 of the License, or (at your option) any later version. +// +// This software 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. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma implementation "BOINCGridCtrl.h" +#endif + +#include "stdwx.h" +#include "BOINCGridCtrl.h" + + +CBOINCGridCtrl::CBOINCGridCtrl( + wxWindow* parent, wxWindowID iGridWindowID +) : wxGrid( + parent, iGridWindowID) { +} + + +CBOINCGridCtrl::~CBOINCGridCtrl() { +} + +#pragma warning( disable : 4100) +bool CBOINCGridCtrl::isReadOnly(int row,int col) const { + return true; +} + +int CBOINCGridCtrl::GetFirstSelectedRow() { + int ret= -1; + //Row mode ? + wxArrayInt selRows = this->GetSelectedRows(); + if(selRows.size() >0) { + return selRows[0]; + } + //block mode ? + wxGridCellCoordsArray selBlocks = this->GetSelectionBlockTopLeft(); + if(selBlocks.size()>0) { + return selBlocks[0].GetRow(); + } + //cell mode + wxGridCellCoordsArray selCells = this->GetSelectionBlockTopLeft(); + if(selCells.size()>0) { + return selCells[0].GetRow(); + } + + return ret; +} + +/* ############# */ +CBOINCGridCellProgressRenderer::CBOINCGridCellProgressRenderer(int col) : wxGridCellStringRenderer() +{ + column = col; +} + +void CBOINCGridCellProgressRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool isSelected) { + if(col==column) { + DoDrawing(grid,attr,dc,rect,row,col,isSelected); + } + else { + wxGridCellStringRenderer::Draw(grid,attr,dc,rect,row,col,isSelected); + } +} + +void CBOINCGridCellProgressRenderer::DoDrawing(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rectCell, int row, int col, bool isSelected) { + wxRect rect = rectCell; + rect.Inflate(-1); + + // erase only this cells background, overflow cells should have been erased + wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected); + + int hAlign, vAlign; + attr.GetAlignment(&hAlign, &vAlign); + + // now we only have to draw the text + SetTextColoursAndFont(grid, attr, dc, isSelected); + + wxString value = grid.GetCellValue(row,col); + wxString strValue = value + " %"; + double dv = atof(value); + wxRect p1(rect); + wxRect p2(rect); + int r = (int)((rect.GetRight()-rect.GetLeft())*dv / 100.0); + p1.SetRight(rect.GetLeft()+r); + p2.SetLeft(rect.GetLeft()+r+1); + dc.SetClippingRegion(rect); + wxBrush old = dc.GetBrush(); + dc.SetBrush(*wxBLUE_BRUSH); + dc.DrawRectangle(p1); + dc.SetBrush(old); + dc.DrawRectangle(p2); + dc.DestroyClippingRegion(); + grid.DrawTextRectangle(dc, strValue, rect, hAlign, vAlign); +} diff --git a/clientgui/BOINCGridCtrl.h b/clientgui/BOINCGridCtrl.h new file mode 100644 index 0000000000..e37416161e --- /dev/null +++ b/clientgui/BOINCGridCtrl.h @@ -0,0 +1,50 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This 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 2.1 of the License, or (at your option) any later version. +// +// This software 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. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#ifndef _BOINCGRIDCTRL_H_ +#define _BOINCGRIDCTRL_H_ + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma interface "BOINCGridCtrl.cpp" +#endif + +/* default progress renderer */ +class CBOINCGridCellProgressRenderer : public wxGridCellStringRenderer { + int column; +public: + CBOINCGridCellProgressRenderer(int col); + void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool isSelected); +protected: + void DoDrawing(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rectCell, int row, int col, bool isSelected); +}; + +/* grid ctrl */ +class CBOINCGridCtrl : public wxGrid +{ +public: + CBOINCGridCtrl(wxWindow* parent, wxWindowID iGridWindowID); +public: + ~CBOINCGridCtrl(); + bool isReadOnly(int row, int col) const; + int GetFirstSelectedRow(); +}; + + + +#endif //_BOINCGRIDCTRL_H_ diff --git a/clientgui/Events.h b/clientgui/Events.h index 502c673e1e..45801fb15a 100644 --- a/clientgui/Events.h +++ b/clientgui/Events.h @@ -73,6 +73,7 @@ #define ID_LIST_RESOURCEUTILIZATIONVIEW 7004 #define ID_LIST_STATISTICSVIEW 7005 #define ID_LIST_RESOURCEUTILIZATIONVIEWTOTAL 7006 +#define ID_LIST_WORKGRIDVIEW 7007 #define ID_TASK_BASE 8000 #define ID_TASK_PROJECTSVIEW 8000 #define ID_TASK_WORKVIEW 8001 @@ -80,6 +81,7 @@ #define ID_TASK_MESSAGESVIEW 8003 #define ID_TASK_STATISTICSVIEW 8004 #define ID_TASK_RESOURCEUTILIZATIONVIEW 8005 +#define ID_TASK_WORKGRIDVIEW 8006 #define ID_TASK_PROJECT_UPDATE 9000 #define ID_TASK_PROJECT_SUSPEND 9002 #define ID_TASK_PROJECT_RESUME 9003 diff --git a/clientgui/ViewWorkGrid.cpp b/clientgui/ViewWorkGrid.cpp new file mode 100644 index 0000000000..6ef1d1b339 --- /dev/null +++ b/clientgui/ViewWorkGrid.cpp @@ -0,0 +1,820 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This 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 2.1 of the License, or (at your option) any later version. +// +// This software 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. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma implementation "ViewWorkGrid.h" +#endif + +#include "stdwx.h" +#include "BOINCGUIApp.h" +#include "BOINCBaseFrame.h" +#include "MainDocument.h" +#include "AdvancedFrame.h" +#include "BOINCTaskCtrl.h" +#include "ViewWorkGrid.h" +#include "Events.h" +#include "error_numbers.h" + +#include "res/result.xpm" + + +#define COLUMN_PROJECT 0 +#define COLUMN_APPLICATION 1 +#define COLUMN_NAME 2 +#define COLUMN_CPUTIME 3 +#define COLUMN_PROGRESS 4 +#define COLUMN_TOCOMPLETION 5 +#define COLUMN_REPORTDEADLINE 6 +#define COLUMN_STATUS 7 + +// groups that contain buttons +#define GRP_TASKS 0 +#define GRP_WEBSITES 1 + +// buttons in the "tasks" area +#define BTN_GRAPHICS 0 +#define BTN_SUSPEND 1 +#define BTN_ABORT 2 + + + +IMPLEMENT_DYNAMIC_CLASS(CViewWorkGrid, CBOINCBaseView) + +BEGIN_EVENT_TABLE (CViewWorkGrid, CBOINCBaseView) + EVT_BUTTON(ID_TASK_WORK_SUSPEND, CViewWorkGrid::OnWorkSuspend) + EVT_BUTTON(ID_TASK_WORK_SHOWGRAPHICS, CViewWorkGrid::OnWorkShowGraphics) + EVT_BUTTON(ID_TASK_WORK_ABORT, CViewWorkGrid::OnWorkAbort) + EVT_CUSTOM_RANGE(wxEVT_COMMAND_BUTTON_CLICKED, ID_TASK_PROJECT_WEB_PROJDEF_MIN, ID_TASK_PROJECT_WEB_PROJDEF_MAX, CViewWorkGrid::OnProjectWebsiteClicked) + EVT_GRID_SELECT_CELL( CViewWorkGrid::OnSelectCell ) +END_EVENT_TABLE () + + +CViewWorkGrid::CViewWorkGrid() +{} + + +CViewWorkGrid::CViewWorkGrid(wxNotebook* pNotebook) : + CBOINCBaseView(pNotebook) +{ + + // + // Setup View + // + wxFlexGridSizer* itemFlexGridSizer = new wxFlexGridSizer(2, 0, 0); + wxASSERT(itemFlexGridSizer); + + itemFlexGridSizer->AddGrowableRow(0); + itemFlexGridSizer->AddGrowableCol(1); + + m_pTaskPane = new CBOINCTaskCtrl(this, ID_TASK_WORKGRIDVIEW, DEFAULT_TASK_FLAGS); + wxASSERT(m_pTaskPane); + + m_pGridPane = new CBOINCGridCtrl(this, ID_LIST_WORKGRIDVIEW); + wxASSERT(m_pGridPane); + + itemFlexGridSizer->Add(m_pTaskPane, 1, wxGROW|wxALL, 1); + itemFlexGridSizer->Add(m_pGridPane, 1, wxGROW|wxALL, 1); + + SetSizer(itemFlexGridSizer); + + Layout(); + + // Setup TaskPane + CTaskItemGroup* pGroup = NULL; + CTaskItem* pItem = NULL; + + pGroup = new CTaskItemGroup( _("Commands") ); + m_TaskGroups.push_back( pGroup ); + + pItem = new CTaskItem( + _("Show graphics"), + _("Show application graphics in a window."), + ID_TASK_WORK_SHOWGRAPHICS + ); + pGroup->m_Tasks.push_back( pItem ); + + pItem = new CTaskItem( + _("Suspend"), + _("Suspend work for this result."), + ID_TASK_WORK_SUSPEND + ); + pGroup->m_Tasks.push_back( pItem ); + + pItem = new CTaskItem( + _("Abort"), + _("Abandon work on the result. " + "You will get no credit for it."), + ID_TASK_WORK_ABORT + ); + pGroup->m_Tasks.push_back( pItem ); + + + // Create Task Pane Items + m_pTaskPane->UpdateControls(); + + // Create Grid + m_pGridPane->CreateGrid(0,8,wxGrid::wxGridSelectRows); + m_pGridPane->SetRowLabelSize(1); + m_pGridPane->SetColLabelSize(20); + // init grid columns + m_pGridPane->SetColLabelValue(COLUMN_PROJECT, _("Project")); + m_pGridPane->SetColLabelValue(COLUMN_APPLICATION, _("Application")); + m_pGridPane->SetColLabelValue(COLUMN_NAME, _("Name")); + m_pGridPane->SetColLabelValue(COLUMN_CPUTIME, _("CPU time")); + m_pGridPane->SetColLabelValue(COLUMN_PROGRESS, _("Progress")); + m_pGridPane->SetColLabelValue(COLUMN_TOCOMPLETION, _("To completion")); + m_pGridPane->SetColLabelValue(COLUMN_REPORTDEADLINE, _("Report deadline")); + m_pGridPane->SetColLabelValue(COLUMN_STATUS, _("Status")); + //change the default cell renderer + m_pGridPane->SetDefaultRenderer(new CBOINCGridCellProgressRenderer(COLUMN_PROGRESS)); + // + UpdateSelection(); +} + + +CViewWorkGrid::~CViewWorkGrid() { + EmptyTasks(); +} + + +wxString& CViewWorkGrid::GetViewName() { + static wxString strViewName(_("TasksGrid")); + return strViewName; +} + + +const char** CViewWorkGrid::GetViewIcon() { + return result_xpm; +} + + +void CViewWorkGrid::OnWorkSuspend( wxCommandEvent& WXUNUSED(event) ) { + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnWorkSuspend - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + CAdvancedFrame* pFrame = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + wxASSERT(pFrame); + wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame)); + wxASSERT(m_pTaskPane); + wxASSERT(m_pGridPane); + + RESULT* result = pDoc->result(m_pGridPane->GetFirstSelectedRow()); + if (result->suspended_via_gui) { + pFrame->UpdateStatusText(_("Resuming task...")); + pDoc->WorkResume(result->project_url, result->name); + pFrame->UpdateStatusText(wxT("")); + } else { + pFrame->UpdateStatusText(_("Suspending task...")); + pDoc->WorkSuspend(result->project_url, result->name); + pFrame->UpdateStatusText(wxT("")); + } + + UpdateSelection(); + pFrame->FireRefreshView(); + + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnWorkSuspend - Function End")); +} + +void CViewWorkGrid::OnWorkShowGraphics( wxCommandEvent& WXUNUSED(event) ) { + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnWorkShowGraphics - Function Begin")); + + wxInt32 iAnswer = 0; + wxString strMachineName = wxEmptyString; + CMainDocument* pDoc = wxGetApp().GetDocument(); + CAdvancedFrame* pFrame = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + wxASSERT(pFrame); + wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame)); + wxASSERT(m_pTaskPane); + wxASSERT(m_pGridPane); + + pFrame->UpdateStatusText(_("Showing graphics for task...")); + + // TODO: implement hide as well as show +#if (defined(_WIN32) || defined(__WXMAC__)) + pDoc->GetConnectedComputerName(strMachineName); + if (!pDoc->IsComputerNameLocal(strMachineName)) { + iAnswer = ::wxMessageBox( + _("Are you sure you want to display graphics on a remote machine?"), + _("Show graphics"), + wxYES_NO | wxICON_QUESTION, + this + ); + } else { + iAnswer = wxYES; + } +#else + iAnswer = wxYES; +#endif + + if (wxYES == iAnswer) { + RESULT* result = pDoc->result(m_pGridPane->GetFirstSelectedRow()); + std::string strDefaultWindowStation = std::string((const char*)wxGetApp().m_strDefaultWindowStation.mb_str()); + std::string strDefaultDesktop = std::string((const char*)wxGetApp().m_strDefaultDesktop.mb_str()); + std::string strDefaultDisplay = std::string((const char*)wxGetApp().m_strDefaultDisplay.mb_str()); + pDoc->WorkShowGraphics( + result->project_url, + result->name, + MODE_WINDOW, + strDefaultWindowStation, + strDefaultDesktop, + strDefaultDisplay + ); + } + + pFrame->UpdateStatusText(wxT("")); + + UpdateSelection(); + pFrame->FireRefreshView(); + + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnWorkShowGraphics - Function End")); +} + + +void CViewWorkGrid::OnWorkAbort( wxCommandEvent& WXUNUSED(event) ) { + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnWorkAbort - Function Begin")); + + wxInt32 iAnswer = 0; + wxInt32 iResult = 0; + wxString strMessage = wxEmptyString; + wxString strName = wxEmptyString; + wxString strProgress = wxEmptyString; + wxString strStatus = wxEmptyString; + CMainDocument* pDoc = wxGetApp().GetDocument(); + CAdvancedFrame* pFrame = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame); + + wxASSERT(pDoc); + wxASSERT(pFrame); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame)); + wxASSERT(m_pTaskPane); + wxASSERT(m_pGridPane); + + if (!pDoc->IsUserAuthorized()) + return; + + pFrame->UpdateStatusText(_("Aborting result...")); + + iResult = m_pGridPane->GetFirstSelectedRow(); + FormatName(iResult, strName); + FormatProgress(iResult, strProgress); + FormatStatus(iResult, strStatus); + + strMessage.Printf( + _("Are you sure you want to abort this task '%s'?\n" + "(Progress: %s %%, Status: %s)"), + strName.c_str(), + strProgress.c_str(), + strStatus.c_str() + ); + + iAnswer = ::wxMessageBox( + strMessage, + _("Abort task"), + wxYES_NO | wxICON_QUESTION, + this + ); + + if (wxYES == iAnswer) { + RESULT* result = pDoc->result(m_pGridPane->GetFirstSelectedRow()); + pDoc->WorkAbort(result->project_url, result->name); + } + + pFrame->UpdateStatusText(wxT("")); + + UpdateSelection(); + pFrame->FireRefreshView(); + + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnWorkAbort - Function End")); +} + + +void CViewWorkGrid::OnProjectWebsiteClicked( wxEvent& event ) { + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnProjectWebsiteClicked - Function Begin")); + + CAdvancedFrame* pFrame = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame); + + wxASSERT(pFrame); + wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame)); + wxASSERT(m_pTaskPane); + wxASSERT(m_pGridPane); + + pFrame->UpdateStatusText(_("Launching browser...")); + + int website_task_index = event.GetId() - ID_TASK_PROJECT_WEB_PROJDEF_MIN; + pFrame->ExecuteBrowserLink( + m_TaskGroups[1]->m_Tasks[website_task_index]->m_strWebSiteLink + ); + + pFrame->UpdateStatusText(wxT("")); + + UpdateSelection(); + pFrame->FireRefreshView(); + + wxLogTrace(wxT("Function Start/End"), wxT("CViewWorkGrid::OnProjectWebsiteClicked - Function End")); +} + +void CViewWorkGrid::UpdateSelection() { + CTaskItemGroup* pGroup = NULL; + RESULT* result = NULL; + PROJECT* project = NULL; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(NULL != pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + wxASSERT(NULL != m_pTaskPane); + + + CBOINCBaseView::PreUpdateSelection(); + + + pGroup = m_TaskGroups[0]; + if (m_pGridPane->GetFirstSelectedRow() >= 0) { + result = pDoc->result(m_pGridPane->GetFirstSelectedRow()); + m_pTaskPane->EnableTask(pGroup->m_Tasks[BTN_SUSPEND]); + if (result) { + if (result->suspended_via_gui) { + m_pTaskPane->UpdateTask( + pGroup->m_Tasks[BTN_SUSPEND], + _("Resume"), + _("Resume work for this task.") + ); + } else { + m_pTaskPane->UpdateTask( + pGroup->m_Tasks[BTN_SUSPEND], + _("Suspend"), + _("Suspend work for this task.") + ); + } + if (result->supports_graphics) { + m_pTaskPane->EnableTask(pGroup->m_Tasks[BTN_GRAPHICS]); + } else { + m_pTaskPane->DisableTask(pGroup->m_Tasks[BTN_GRAPHICS]); + } + + project = pDoc->state.lookup_project(result->project_url); + UpdateWebsiteSelection(GRP_WEBSITES, project); + } else { + UpdateWebsiteSelection(GRP_WEBSITES, NULL); + } + + m_pTaskPane->EnableTask(pGroup->m_Tasks[BTN_ABORT]); + } else { + m_pTaskPane->DisableTaskGroupTasks(pGroup); + } + + CBOINCBaseView::PostUpdateSelection(); +} + +void CViewWorkGrid::UpdateWebsiteSelection(long lControlGroup, PROJECT* project){ + unsigned int i; + CTaskItemGroup* pGroup = NULL; + CTaskItem* pItem = NULL; + + wxASSERT(m_pTaskPane); + wxASSERT(m_pGridPane); + + // Update the websites list + // + if (m_bForceUpdateSelection) { + if (m_TaskGroups.size() > 1) { + + // Delete task group, objects, and controls. + pGroup = m_TaskGroups[lControlGroup]; + + m_pTaskPane->DeleteTaskGroupAndTasks(pGroup); + for (i=0; im_Tasks.size(); i++) { + delete pGroup->m_Tasks[i]; + } + pGroup->m_Tasks.clear(); + delete pGroup; + + pGroup = NULL; + + m_TaskGroups.erase( m_TaskGroups.begin() + 1 ); + } + + // If something is selected create the tasks and controls + if (m_pGridPane->GetFirstSelectedRow()>=0) { + if (project) { + // Create the web sites task group + pGroup = new CTaskItemGroup( _("Web sites") ); + m_TaskGroups.push_back( pGroup ); + + // Default project url + pItem = new CTaskItem( + wxString(project->project_name.c_str(), wxConvUTF8), + wxT(""), + wxString(project->master_url.c_str(), wxConvUTF8), + ID_TASK_PROJECT_WEB_PROJDEF_MIN + ); + pGroup->m_Tasks.push_back(pItem); + + + // Project defined urls + for (i=0;(igui_urls.size())&&(i<=ID_TASK_PROJECT_WEB_PROJDEF_MAX);i++) { + pItem = new CTaskItem( + wxGetTranslation(wxString(project->gui_urls[i].name.c_str(), wxConvUTF8)), + wxGetTranslation(wxString(project->gui_urls[i].description.c_str(), wxConvUTF8)), + wxString(project->gui_urls[i].url.c_str(), wxConvUTF8), + ID_TASK_PROJECT_WEB_PROJDEF_MIN + 1 + i + ); + pGroup->m_Tasks.push_back(pItem); + } + } + } + + m_bForceUpdateSelection = false; + } + +} + + +wxInt32 CViewWorkGrid::FormatProjectName(wxInt32 item, wxString& strBuffer) const { + CMainDocument* doc = wxGetApp().GetDocument(); + RESULT* result = wxGetApp().GetDocument()->result(item); + PROJECT* state_project = NULL; + std::string project_name; + + wxASSERT(doc); + wxASSERT(wxDynamicCast(doc, CMainDocument)); + + if (result) { + state_project = doc->state.lookup_project(result->project_url); + if (state_project) { + state_project->get_name(project_name); + strBuffer = wxString(project_name.c_str(), wxConvUTF8); + } else { + doc->ForceCacheUpdate(); + } + } + + return 0; +} + +wxInt32 CViewWorkGrid::FormatApplicationName(wxInt32 item, wxString& strBuffer) const { + CMainDocument* pDoc = wxGetApp().GetDocument(); + RESULT* result = wxGetApp().GetDocument()->result(item); + RESULT* state_result = NULL; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (result) { + state_result = pDoc->state.lookup_result(result->project_url, result->name); + if (!state_result) { + pDoc->ForceCacheUpdate(); + state_result = pDoc->state.lookup_result(result->project_url, result->name); + } + wxASSERT(state_result); + + wxString strLocale = wxString(setlocale(LC_NUMERIC, NULL), wxConvUTF8); + setlocale(LC_NUMERIC, "C"); + strBuffer.Printf( + wxT("%s %.2f"), + wxString(state_result->wup->avp->app_name.c_str(), wxConvUTF8).c_str(), + state_result->wup->avp->version_num/100.0 + ); + setlocale(LC_NUMERIC, (const char*)strLocale.mb_str()); + + } + + return 0; +} + + +wxInt32 CViewWorkGrid::FormatName(wxInt32 item, wxString& strBuffer) const { + RESULT* result = wxGetApp().GetDocument()->result(item); + + wxASSERT(result); + + if (result) { + strBuffer = wxString(result->name.c_str(), wxConvUTF8); + } + + return 0; +} + + +wxInt32 CViewWorkGrid::FormatCPUTime(wxInt32 item, wxString& strBuffer) const { + float fBuffer = 0; + wxInt32 iHour = 0; + wxInt32 iMin = 0; + wxInt32 iSec = 0; + wxTimeSpan ts; + RESULT* result = wxGetApp().GetDocument()->result(item); + + if (result) { + if (result->active_task) { + fBuffer = result->current_cpu_time; + } else { + if(result->state < RESULT_COMPUTE_ERROR) { + fBuffer = 0; + } else { + fBuffer = result->final_cpu_time; + } + } + } + + if (0 == fBuffer) { + strBuffer = wxT("---"); + } else { + iHour = (wxInt32)(fBuffer / (60 * 60)); + iMin = (wxInt32)(fBuffer / 60) % 60; + iSec = (wxInt32)(fBuffer) % 60; + + ts = wxTimeSpan(iHour, iMin, iSec); + + strBuffer = ts.Format(); + } + + return 0; +} + + +wxInt32 CViewWorkGrid::FormatProgress(wxInt32 item, wxString& strBuffer) const { + float fBuffer = 0; + RESULT* result = wxGetApp().GetDocument()->result(item); + + if (result) { + if (result->active_task) { + fBuffer = floor(result->fraction_done * 100000)/1000; + } else { + if(result->state < RESULT_COMPUTE_ERROR) { + fBuffer = 0.0; + } else { + fBuffer = 100.0; + } + } + } + + strBuffer.Printf(wxT("%.3f"), fBuffer); + + return 0; +} + + +wxInt32 CViewWorkGrid::FormatTimeToCompletion(wxInt32 item, wxString& strBuffer) const { + float fBuffer = 0; + wxInt32 iHour = 0; + wxInt32 iMin = 0; + wxInt32 iSec = 0; + wxTimeSpan ts; + RESULT* result = wxGetApp().GetDocument()->result(item); + + if (result) { + fBuffer = result->estimated_cpu_time_remaining; + } + + if (0 >= fBuffer) { + strBuffer = wxT("---"); + } else { + iHour = (wxInt32)(fBuffer / (60 * 60)); + iMin = (wxInt32)(fBuffer / 60) % 60; + iSec = (wxInt32)(fBuffer) % 60; + + ts = wxTimeSpan(iHour, iMin, iSec); + + strBuffer = ts.Format(); + } + + return 0; +} + + +wxInt32 CViewWorkGrid::FormatReportDeadline(wxInt32 item, wxString& strBuffer) const { + wxDateTime dtTemp; + RESULT* result = wxGetApp().GetDocument()->result(item); + + if (result) { + dtTemp.Set((time_t)result->report_deadline); + strBuffer = dtTemp.Format(); + } + + return 0; +} + + +wxInt32 CViewWorkGrid::FormatStatus(wxInt32 item, wxString& strBuffer) const { + CMainDocument* doc = wxGetApp().GetDocument(); + RESULT* result = wxGetApp().GetDocument()->result(item); + CC_STATUS status; + + wxASSERT(doc); + wxASSERT(wxDynamicCast(doc, CMainDocument)); + + doc->GetCoreClientStatus(status); + + if (result) { + switch(result->state) { + case RESULT_NEW: + strBuffer = _("New"); + break; + case RESULT_FILES_DOWNLOADING: + if (result->ready_to_report) { + strBuffer = _("Download failed"); + } else { + strBuffer = _("Downloading"); + } + break; + case RESULT_FILES_DOWNLOADED: + if (result->project_suspended_via_gui) { + strBuffer = _("Project suspended by user"); + } else if (result->suspended_via_gui) { + strBuffer = _("Task suspended by user"); + } else if (status.task_suspend_reason > 0) { + strBuffer = _("Suspended"); + if (status.task_suspend_reason & SUSPEND_REASON_BATTERIES) { + strBuffer += _(" - on batteries"); + } + if (status.task_suspend_reason & SUSPEND_REASON_USER_ACTIVE) { + strBuffer += _(" - user active"); + } + if (status.task_suspend_reason & SUSPEND_REASON_USER_REQ) { + strBuffer += _(" - computation suspended"); + } + if (status.task_suspend_reason & SUSPEND_REASON_TIME_OF_DAY) { + strBuffer += _(" - time of day"); + } + if (status.task_suspend_reason & SUSPEND_REASON_BENCHMARKS) { + strBuffer += _(" - CPU benchmarks"); + } + if (status.task_suspend_reason & SUSPEND_REASON_DISK_SIZE) { + strBuffer += _(" - need disk space"); + } + if (status.task_suspend_reason & SUSPEND_REASON_CPU_USAGE_LIMIT) { + strBuffer += _(" - CPU throttled"); + } + } else if (result->active_task) { + if (result->too_large) { + strBuffer = _("Waiting for memory"); + } else if (result->scheduler_state == CPU_SCHED_SCHEDULED) { + strBuffer = _("Running"); + } else if (result->scheduler_state == CPU_SCHED_PREEMPTED) { + strBuffer = _("Preempted"); + } else if (result->scheduler_state == CPU_SCHED_UNINITIALIZED) { + strBuffer = _("Ready to run"); + } + } else { + strBuffer = _("Ready to run"); + } + break; + case RESULT_COMPUTE_ERROR: + strBuffer = _("Computation error"); + break; + case RESULT_FILES_UPLOADING: + if (result->ready_to_report) { + strBuffer = _("Upload failed"); + } else { + strBuffer = _("Uploading"); + } + break; + case RESULT_ABORTED: + switch(result->exit_status) { + case ERR_ABORTED_VIA_GUI: + strBuffer = _("Aborted by user"); + break; + case ERR_ABORTED_BY_PROJECT: + strBuffer = _("Aborted by project"); + break; + default: + strBuffer = _("Aborted"); + } + break; + default: + if (result->got_server_ack) { + strBuffer = _("Acknowledged"); + } else if (result->ready_to_report) { + strBuffer = _("Ready to report"); + } else { + strBuffer.Format(_("Error: invalid state '%d'"), result->state); + } + break; + } + } + + if (!status.task_suspend_reason && status.task_mode == RUN_MODE_NEVER) { + strBuffer = wxT(" (") + strBuffer + wxT(") "); + strBuffer = _("Activities suspended by user") + strBuffer; + } + + return 0; +} + +bool CViewWorkGrid::OnSaveState(wxConfigBase* pConfig) { + bool bReturnValue = true; + + wxASSERT(pConfig); + wxASSERT(m_pTaskPane); + + if (!m_pTaskPane->OnSaveState(pConfig)) { + bReturnValue = false; + } + + return bReturnValue; +} + +bool CViewWorkGrid::OnRestoreState(wxConfigBase* pConfig) { + wxASSERT(pConfig); + wxASSERT(m_pTaskPane); + + if (!m_pTaskPane->OnRestoreState(pConfig)) { + return false; + } + + return true; +} + +wxInt32 CViewWorkGrid::GetDocCount() { + return wxGetApp().GetDocument()->GetWorkCount(); +} + +void CViewWorkGrid::OnListRender( wxTimerEvent& WXUNUSED(event) ) { + //prevent grid from flicker + m_pGridPane->BeginBatch(); + //remember selected rows + wxArrayInt arrSelRows = m_pGridPane->GetSelectedRows(); + //(re)create rows, if necessary + if(this->GetDocCount()!= m_pGridPane->GetRows()) { + //at first, delet all current rows + if(m_pGridPane->GetRows()>0) { + m_pGridPane->DeleteRows(0,m_pGridPane->GetRows()); + } + //insert new rows + for(int rownum=0; rownum < this->GetDocCount();rownum++) { + m_pGridPane->AppendRows(); + } + } + + //update cell values + wxString buffer; + for(int rownum=0; rownum < this->GetDocCount();rownum++) { + this->FormatProjectName(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_PROJECT,buffer); + + this->FormatApplicationName(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_APPLICATION,buffer); + + this->FormatName(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_NAME,buffer); + + this->FormatCPUTime(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_CPUTIME,buffer); + + this->FormatProgress(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_PROGRESS,buffer); + m_pGridPane->SetCellAlignment(rownum,COLUMN_PROGRESS,wxALIGN_CENTRE,wxALIGN_CENTRE); + + this->FormatTimeToCompletion(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_TOCOMPLETION,buffer); + + this->FormatReportDeadline(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_REPORTDEADLINE,buffer); + + this->FormatStatus(rownum,buffer); + m_pGridPane->SetCellValue(rownum,COLUMN_STATUS,buffer); + } + + //restore selection + for(unsigned int i=0;i < arrSelRows.size();i++) { + m_pGridPane->SelectRow(arrSelRows[i]); + } + m_pGridPane->EndBatch(); + // + UpdateSelection(); +} + +/** + handle selection events +*/ +void CViewWorkGrid::OnSelectCell( wxGridEvent& ev ) +{ + // you must call Skip() if you want the default processing + // to occur in wxGrid + ev.Skip(); + m_bForceUpdateSelection = true; +} + + + diff --git a/clientgui/ViewWorkGrid.h b/clientgui/ViewWorkGrid.h new file mode 100644 index 0000000000..33daedb6ab --- /dev/null +++ b/clientgui/ViewWorkGrid.h @@ -0,0 +1,78 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This 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 2.1 of the License, or (at your option) any later version. +// +// This software 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. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#ifndef _VIEWWORKGRID_H_ +#define _VIEWWORKGRID_H_ + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma interface "ViewWorkGrid.cpp" +#endif + + +#include "BOINCBaseView.h" +#include "BOINCGridCtrl.h" + + +class CViewWorkGrid : public CBOINCBaseView +{ + DECLARE_DYNAMIC_CLASS( CViewWorkGrid ) + + CBOINCGridCtrl* m_pGridPane; +public: + CViewWorkGrid(); + CViewWorkGrid(wxNotebook* pNotebook); + + ~CViewWorkGrid(); + + virtual wxString& GetViewName(); + virtual const char** GetViewIcon(); + + virtual wxInt32 GetDocCount(); + + void OnWorkSuspend( wxCommandEvent& event ); + void OnWorkShowGraphics( wxCommandEvent& event ); + void OnWorkAbort( wxCommandEvent& event ); + + void OnProjectWebsiteClicked( wxEvent& event ); + +protected: + virtual void UpdateSelection(); + + virtual bool OnSaveState( wxConfigBase* pConfig ); + virtual bool OnRestoreState( wxConfigBase* pConfig ); + virtual void OnListRender( wxTimerEvent& event ); + + wxInt32 FormatProjectName( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatApplicationName( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatName( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatCPUTime( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatProgress( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatTimeToCompletion( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatReportDeadline( wxInt32 item, wxString& strBuffer ) const; + wxInt32 FormatStatus( wxInt32 item, wxString& strBuffer ) const; + + void UpdateWebsiteSelection(long lControlGroup, PROJECT* project); + + void OnSelectCell( wxGridEvent& ); + DECLARE_EVENT_TABLE() +}; + + +#endif + diff --git a/clientgui/stdwx.h b/clientgui/stdwx.h index 314c6d6557..7067cffaae 100644 --- a/clientgui/stdwx.h +++ b/clientgui/stdwx.h @@ -104,6 +104,7 @@ #include #include #include +#include #ifdef _WIN32 @@ -217,17 +218,17 @@ #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) -// The following macros set and clear, respectively, given bits -// of the C runtime library debug flag, as specified by a bitmask. -#define SET_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) -#define CLEAR_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) +// The following macros set and clear, respectively, given bits +// of the C runtime library debug flag, as specified by a bitmask. +#define SET_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) +#define CLEAR_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #else //_DEBUG #define DEBUG_NEW new -#define SET_CRT_DEBUG_FIELD(a) ((void) 0) -#define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) +#define SET_CRT_DEBUG_FIELD(a) ((void) 0) +#define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) #endif //_DEBUG diff --git a/win_build/boincmgr_curl.vcproj b/win_build/boincmgr_curl.vcproj index 06ea7c4e08..2a60acf39a 100644 --- a/win_build/boincmgr_curl.vcproj +++ b/win_build/boincmgr_curl.vcproj @@ -1527,6 +1527,14 @@ + + + + @@ -1591,6 +1599,14 @@ RelativePath="..\clientgui\ViewWork.h" > + + + +