Skip to content

Commit c134d0f

Browse files
authored
Merge pull request #4898 from Vulpine05/Vulpine05-3403-Revised
Add estimated completion date and completion before deadline columns to Tasks tab
2 parents 2a261b4 + 832c64b commit c134d0f

File tree

4 files changed

+145
-31
lines changed

4 files changed

+145
-31
lines changed

clientgui/MainDocument.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2660,10 +2660,8 @@ wxString FormatTime(double secs) {
26602660
if (secs <= 0) {
26612661
return wxT("---");
26622662
}
2663-
wxInt32 iHour = (wxInt32)(secs / (60 * 60));
2664-
wxInt32 iMin = (wxInt32)(secs / 60) % 60;
2665-
wxInt32 iSec = (wxInt32)(secs) % 60;
2666-
wxTimeSpan ts = wxTimeSpan(iHour, iMin, iSec);
2663+
2664+
wxTimeSpan ts = convert_to_timespan(secs);
26672665
return ts.Format((secs>=86400)?"%Dd %H:%M:%S":"%H:%M:%S");
26682666
}
26692667

@@ -2672,6 +2670,14 @@ wxString format_number(double x, int nprec) {
26722670

26732671
}
26742672

2673+
wxTimeSpan convert_to_timespan(double secs) {
2674+
wxInt32 iHour = (wxInt32)(secs / (60 * 60));
2675+
wxInt32 iMin = (wxInt32)(secs / 60) % 60;
2676+
wxInt32 iSec = (wxInt32)(secs) % 60;
2677+
wxTimeSpan ts = wxTimeSpan(iHour, iMin, iSec);
2678+
return (ts);
2679+
}
2680+
26752681
// the autoattach process deletes the installer filename file when done
26762682
//
26772683
bool autoattach_in_progress() {

clientgui/MainDocument.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ extern void remove_eols(wxString& strMessage);
422422
extern void https_to_http(wxString& strMessage);
423423
extern void color_cycle(int i, int n, wxColour& color);
424424
extern wxString FormatTime(double secs);
425+
extern wxTimeSpan convert_to_timespan(double secs);
425426
extern bool autoattach_in_progress();
426427

427428

clientgui/ViewWork.cpp

Lines changed: 123 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is part of BOINC.
22
// http://boinc.berkeley.edu
3-
// Copyright (C) 2020 University of California
3+
// Copyright (C) 2022 University of California
44
//
55
// BOINC is free software; you can redistribute it and/or modify it
66
// under the terms of the GNU Lesser General Public License
@@ -52,17 +52,21 @@
5252
#define COLUMN_REPORTDEADLINE 5
5353
#define COLUMN_APPLICATION 6
5454
#define COLUMN_NAME 7
55+
#define COLUMN_ESTIMATEDCOMPLETION 8
56+
#define COLUMN_DEADLINEDIFF 9
57+
5558

5659
// DefaultShownColumns is an array containing the
5760
// columnIDs of the columns to be shown by default,
5861
// in ascending order. It may or may not include
5962
// all columns.
63+
// Columns ESTIMATEDCOMPLETION and DEADLINEDIFF are hidden by default.
64+
// Not all users may want to see those columns.
6065
//
61-
// For now, show all columns by default
6266
static int DefaultShownColumns[] = { COLUMN_PROJECT, COLUMN_PROGRESS, COLUMN_STATUS,
6367
COLUMN_CPUTIME, COLUMN_TOCOMPLETION,
6468
COLUMN_REPORTDEADLINE, COLUMN_APPLICATION,
65-
COLUMN_NAME};
69+
COLUMN_NAME };
6670

6771
// groups that contain buttons
6872
#define GRP_TASKS 0
@@ -81,7 +85,9 @@ CWork::CWork() {
8185
m_fCPUTime = -1.0;
8286
m_fProgress = -1.0;
8387
m_fTimeToCompletion = -1.0;
84-
m_tReportDeadline = (time_t)0;
88+
m_fDeadlineDiff = -1.0;
89+
m_tReportDeadline = (time_t)-1;
90+
m_tEstimatedCompletion = (time_t)-1;
8591
}
8692

8793

@@ -95,6 +101,8 @@ CWork::~CWork() {
95101
m_strProgress.Clear();
96102
m_strTimeToCompletion.Clear();
97103
m_strReportDeadline.Clear();
104+
m_strEstimatedCompletion.Clear();
105+
m_strDeadlineDiff.Clear();
98106
}
99107

100108

@@ -181,6 +189,20 @@ static bool CompareViewWorkItems(int iRowIndex1, int iRowIndex2) {
181189
case COLUMN_STATUS:
182190
result = work1->m_strStatus.CmpNoCase(work2->m_strStatus);
183191
break;
192+
case COLUMN_ESTIMATEDCOMPLETION:
193+
if (work1->m_tEstimatedCompletion < work2->m_tEstimatedCompletion) {
194+
result = -1;
195+
} else if (work1->m_tEstimatedCompletion > work2->m_tEstimatedCompletion) {
196+
result = 1;
197+
}
198+
break;
199+
case COLUMN_DEADLINEDIFF:
200+
if (work1->m_fDeadlineDiff < work2->m_fDeadlineDiff) {
201+
result = -1;
202+
} else if (work1->m_fDeadlineDiff > work2->m_fDeadlineDiff) {
203+
result = 1;
204+
}
205+
break;
184206
}
185207

186208
// Always return FALSE for equality (result == 0)
@@ -265,6 +287,8 @@ CViewWork::CViewWork(wxNotebook* pNotebook) :
265287
m_aStdColNameOrder->Insert(_("Deadline"), COLUMN_REPORTDEADLINE);
266288
m_aStdColNameOrder->Insert(_("Application"), COLUMN_APPLICATION);
267289
m_aStdColNameOrder->Insert(_("Name"), COLUMN_NAME);
290+
m_aStdColNameOrder->Insert(_("Estimated Completion"), COLUMN_ESTIMATEDCOMPLETION);
291+
m_aStdColNameOrder->Insert(_("Completion Before Deadline"), COLUMN_DEADLINEDIFF);
268292

269293
// m_iStdColWidthOrder is an array of the width for each column.
270294
// Entries must be in order of ascending Column ID. We initialize
@@ -281,6 +305,8 @@ CViewWork::CViewWork(wxNotebook* pNotebook) :
281305
m_iStdColWidthOrder.Insert(150, COLUMN_REPORTDEADLINE);
282306
m_iStdColWidthOrder.Insert(95, COLUMN_APPLICATION);
283307
m_iStdColWidthOrder.Insert(285, COLUMN_NAME);
308+
m_iStdColWidthOrder.Insert(150, COLUMN_ESTIMATEDCOMPLETION);
309+
m_iStdColWidthOrder.Insert(150, COLUMN_DEADLINEDIFF);
284310

285311
wxASSERT(m_iStdColWidthOrder.size() == m_aStdColNameOrder->size());
286312

@@ -331,6 +357,14 @@ void CViewWork::AppendColumn(int columnID){
331357
m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_NAME],
332358
wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_NAME]);
333359
break;
360+
case COLUMN_ESTIMATEDCOMPLETION:
361+
m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_ESTIMATEDCOMPLETION],
362+
wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_ESTIMATEDCOMPLETION]);
363+
break;
364+
case COLUMN_DEADLINEDIFF:
365+
m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_DEADLINEDIFF],
366+
wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_DEADLINEDIFF]);
367+
break;
334368
}
335369
}
336370

@@ -752,9 +786,15 @@ wxString CViewWork::OnListGetItemText(long item, long column) const {
752786
case COLUMN_STATUS:
753787
strBuffer = work->m_strStatus;
754788
break;
789+
case COLUMN_ESTIMATEDCOMPLETION:
790+
strBuffer = work->m_strEstimatedCompletion;
791+
break;
792+
case COLUMN_DEADLINEDIFF:
793+
strBuffer = work->m_strDeadlineDiff;
794+
break;
755795
}
756796
}
757-
797+
758798
return strBuffer;
759799
}
760800

@@ -870,7 +910,7 @@ void CViewWork::UpdateSelection() {
870910
// Step through all selected items
871911
row = m_pListPane->GetNextItem(row, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
872912
if (row < 0) break; // Should never happen
873-
913+
874914
result = pDoc->result(m_iSortedIndexes[row]);
875915
if (!result) continue;
876916
if (i == 0) {
@@ -919,7 +959,7 @@ void CViewWork::UpdateSelection() {
919959
enableShowGraphics = false;
920960
}
921961
}
922-
962+
923963
// Disable Show VM console if the selected task hasn't registered a remote
924964
// desktop connection
925965
//
@@ -941,7 +981,7 @@ void CViewWork::UpdateSelection() {
941981
enableShowGraphics = false;
942982
}
943983
}
944-
984+
945985
// Disable Abort button if any selected task already aborted
946986
if (
947987
result->active_task_state == PROCESS_ABORT_PENDING ||
@@ -959,7 +999,7 @@ void CViewWork::UpdateSelection() {
959999
all_same_project = false;
9601000
}
9611001
}
962-
1002+
9631003
if (n == 1) {
9641004
enableProperties = true;
9651005
}
@@ -1002,7 +1042,7 @@ void CViewWork::UpdateSelection() {
10021042
bool CViewWork::SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex) {
10031043
wxString strDocumentText = wxEmptyString;
10041044
wxString strDocumentText2 = wxEmptyString;
1005-
double x = 0.0;
1045+
double x = 0.0;
10061046
time_t tDocumentTime = (time_t)0;
10071047
CWork* work;
10081048

@@ -1011,9 +1051,9 @@ bool CViewWork::SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex) {
10111051
if (GetWorkCacheAtIndex(work, m_iSortedIndexes[iRowIndex])) {
10121052
return false;
10131053
}
1014-
1054+
10151055
if (iColumnIndex < 0) return false;
1016-
1056+
10171057
switch (m_iColumnIndexToColumnID[iColumnIndex]) {
10181058
case COLUMN_PROJECT:
10191059
GetDocProjectName(m_iSortedIndexes[iRowIndex], strDocumentText);
@@ -1066,7 +1106,39 @@ bool CViewWork::SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex) {
10661106
GetDocReportDeadline(m_iSortedIndexes[iRowIndex], tDocumentTime);
10671107
if (tDocumentTime != work->m_tReportDeadline) {
10681108
work->m_tReportDeadline = tDocumentTime;
1069-
FormatReportDeadline(tDocumentTime, work->m_strReportDeadline);
1109+
FormatDateTime(tDocumentTime, work->m_strReportDeadline);
1110+
return true;
1111+
}
1112+
break;
1113+
case COLUMN_ESTIMATEDCOMPLETION:
1114+
GetDocEstCompletionDate(m_iSortedIndexes[iRowIndex], tDocumentTime);
1115+
if (tDocumentTime != work->m_tEstimatedCompletion) {
1116+
work->m_tEstimatedCompletion = tDocumentTime;
1117+
if (work->m_tEstimatedCompletion == 0) {
1118+
work->m_strEstimatedCompletion = _("---");
1119+
}
1120+
else {
1121+
FormatDateTime(tDocumentTime, work->m_strEstimatedCompletion);
1122+
}
1123+
return true;
1124+
}
1125+
break;
1126+
case COLUMN_DEADLINEDIFF:
1127+
GetDocEstDeadlineDiff(m_iSortedIndexes[iRowIndex], x);
1128+
if (x != work->m_fDeadlineDiff) {
1129+
work->m_fDeadlineDiff = x;
1130+
if (x < 0) {
1131+
// A negative difference means the task will not meet the
1132+
// deadline. Because FormatTime does not recognize negative
1133+
// numbers, the adjustment will be made here.
1134+
//
1135+
x *= -1;
1136+
work->m_strDeadlineDiff = _("-");
1137+
work->m_strDeadlineDiff += FormatTime(x);
1138+
}
1139+
else {
1140+
work->m_strDeadlineDiff = FormatTime(x);
1141+
}
10701142
return true;
10711143
}
10721144
break;
@@ -1185,6 +1257,7 @@ void CViewWork::GetDocCPUTime(wxInt32 item, double& fBuffer) const {
11851257
}
11861258
}
11871259

1260+
11881261
void CViewWork::GetDocProgress(wxInt32 item, double& fBuffer) const {
11891262
RESULT* result = wxGetApp().GetDocument()->result(item);
11901263

@@ -1219,37 +1292,65 @@ void CViewWork::GetDocTimeToCompletion(wxInt32 item, double& fBuffer) const {
12191292
}
12201293
}
12211294

1222-
void CViewWork::GetDocReportDeadline(wxInt32 item, time_t& time) const {
1295+
1296+
void CViewWork::GetDocReportDeadline(wxInt32 item, time_t& tBuffer) const {
12231297
RESULT* result = wxGetApp().GetDocument()->result(item);
12241298

12251299
if (result) {
1226-
time = (time_t)result->report_deadline;
1300+
tBuffer = (time_t)result->report_deadline;
12271301
} else {
1228-
time = (time_t)0;
1302+
tBuffer = (time_t)0;
12291303
}
12301304
}
12311305

12321306

1233-
wxInt32 CViewWork::FormatReportDeadline(time_t deadline, wxString& strBuffer) const {
1307+
// Calculates the estimated date and time a task will be completed.
1308+
// This is only calculated for active tasks. If a task is not active,
1309+
// time pt will remain at zero. The intent is for the command calling this
1310+
// function to use that value to display '---', not the epoch time.
1311+
//
1312+
void CViewWork::GetDocEstCompletionDate(wxInt32 item, time_t& tBuffer) const {
1313+
RESULT* result = wxGetApp().GetDocument()->result(item);
1314+
tBuffer = 0;
1315+
if (result->active_task_state == 1) {
1316+
time_t ttime = time(0);
1317+
tBuffer = ttime;
1318+
tBuffer += (time_t)result->estimated_cpu_time_remaining;
1319+
}
1320+
}
1321+
1322+
1323+
void CViewWork::GetDocEstDeadlineDiff(wxInt32 item, double& fBuffer) const {
1324+
RESULT* result = wxGetApp().GetDocument()->result(item);
1325+
fBuffer = 0;
1326+
if (result->active_task_state == 1) {
1327+
time_t tdeadline, testcompletion;
1328+
GetDocEstCompletionDate(item, testcompletion);
1329+
GetDocReportDeadline(item, tdeadline);
1330+
fBuffer = (double)(tdeadline - testcompletion);
1331+
}
1332+
1333+
}
1334+
1335+
1336+
wxInt32 CViewWork::FormatDateTime(time_t datetime, wxString& strBuffer) const {
12341337
#ifdef __WXMAC__
12351338
// Work around a wxCocoa bug(?) in wxDateTime::Format()
12361339
char buf[80];
1237-
struct tm * timeinfo = localtime(&deadline);
1340+
struct tm * timeinfo = localtime(&datetime);
12381341
strftime(buf, sizeof(buf), "%c", timeinfo);
12391342
strBuffer = buf;
12401343
#else
12411344
wxDateTime dtTemp;
12421345

1243-
dtTemp.Set(deadline);
1346+
dtTemp.Set(datetime);
12441347
strBuffer = dtTemp.Format();
12451348
#endif
12461349

12471350
return 0;
12481351
}
12491352

12501353

1251-
1252-
12531354
wxInt32 CViewWork::FormatStatus(wxInt32 item, wxString& strBuffer) const {
12541355
CWork* work;
12551356

@@ -1319,7 +1420,7 @@ int CViewWork::GetWorkCacheAtIndex(CWork*& workPtr, int index) {
13191420
workPtr = NULL;
13201421
return -1;
13211422
}
1322-
1423+
13231424
return 0;
13241425
}
13251426

0 commit comments

Comments
 (0)