boinc/client/win/wingui_mainwindow.cpp

2315 lines
78 KiB
C++
Executable File

// 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
#include "stdafx.h"
#include "client_msgs.h"
#include "diagnostics.h"
#include "hostinfo.h"
#include "network.h"
#include "wingui_mainwindow.h"
using std::min;
using std::string;
using std::vector;
CMyApp g_myApp;
CMainWindow* g_myWnd = NULL;
static bool winsock_inited = false;
int check_unique_instance() {
// on Windows, we set a mutex so that the screensaver
// can find out that the core client is running
//
HANDLE h = CreateMutex(NULL, true, RUN_MUTEX);
if ((h==0) || (GetLastError() == ERROR_ALREADY_EXISTS)) {
return ERR_ALREADY_RUNNING;
}
return 0;
}
/////////////////////////////////////////////////////////////////////////
// CMyApp member functions
//////////
// CMyApp::InitInstance
// arguments: void
// returns: true if initialization is successful, otherwise false
// function: creates and shows the main window if boinc is not running,
// otherwise shows the currently running window
BOOL CMyApp::InitInstance()
{
// Initialize Diagnostics
unsigned long dwDiagnosticsFlags = 0;
dwDiagnosticsFlags =
BOINC_DIAG_DUMPCALLSTACKENABLED |
BOINC_DIAG_HEAPCHECKENABLED |
BOINC_DIAG_ARCHIVESTDERR |
BOINC_DIAG_ARCHIVESTDOUT |
BOINC_DIAG_REDIRECTSTDERROVERWRITE |
BOINC_DIAG_REDIRECTSTDOUTOVERWRITE |
BOINC_DIAG_TRACETOSTDERR;
int retval = boinc_init_diagnostics(dwDiagnosticsFlags);
if (retval) {
MessageBox(NULL, NULL, "BOINC GUI Diagnostic Error", MB_OK);
}
retval = check_unique_instance();
if (retval) {
TRACE(TEXT("Another instance of BOINC is running\n"));
UINT nShowMsg = RegisterWindowMessage(SHOW_WIN_MSG);
PostMessage(HWND_BROADCAST, nShowMsg, 0, 0);
return FALSE;
}
// Initialize WinSock
if ( WinsockInitialize() != 0 ) {
MessageBox(NULL, "Failed to initialize the Windows Sockets Interface\nTerminating Application", "BOINC GUI Error", MB_OK);
return FALSE;
}
winsock_inited = true;
m_pMainWnd = new CMainWindow();
TRACE(TEXT("not already running; %d projects\n"), gstate.projects.size());
if(gstate.projects.size() == 0) {
TRACE(TEXT("sending login msg\n"));
((CMainWindow*)m_pMainWnd)->SendMessage(WM_COMMAND, ID_SETTINGS_LOGIN);
}
if(gstate.started_by_screensaver) {
TRACE(TEXT("sending start_ss msg\n"));
UINT nStartSaver = RegisterWindowMessage(START_SS_MSG);
((CMainWindow*)m_pMainWnd)->SendMessage(nStartSaver, 0);
}
return TRUE;
}
int CMyApp::ExitInstance()
{
if (m_pMainWnd)
m_pMainWnd->DestroyWindow();
//gstate.free_mem();
// Cleanup WinSock
if (winsock_inited) {
WinsockCleanup();
}
return CWinApp::ExitInstance();
}
////////
void GetLanguageFilename(CString& path)
{
GetCurrentDirectory(256, path.GetBuffer(256));
path.ReleaseBuffer();
path += '\\';
path += LANGUAGE_FILE_NAME;
}
inline bool UpdateLanguageString(LPCSTR szSection, CString& strItem, LPCSTR szPath)
{
CString strItemNoAmp = strItem; strItemNoAmp.Remove('&');
if(strItemNoAmp.IsEmpty()) return false;
char szValue[256];
GetPrivateProfileString(szSection, strItemNoAmp, strItem, szValue, 256, szPath);
strItem = szValue;
return true;
}
void UpdateLanguageStrings(CWnd* wnd, char const * windowname, int const* pnIDs, CString * const * pStrs)
{
CString strPath, strKey;
char szVal[256];
GetLanguageFilename(strPath);
// title
wnd->GetWindowText(strKey);
GetPrivateProfileString(windowname, "Title", strKey, szVal, 256, strPath);
wnd->SetWindowText(szVal);
while (*pnIDs) {
int nID = *pnIDs++;
wnd->GetDlgItemText(nID, strKey);
GetPrivateProfileString(windowname, strKey, strKey, szVal, 256, strPath);
wnd->SetDlgItemText(nID, szVal);
}
if (pStrs) {
while (*pStrs) {
CString& str = **pStrs++;
GetPrivateProfileString(windowname, str, str, szVal, 256, strPath);
str = szVal;
}
}
}
inline CString GetStrTime(CTime timeObj = CTime::GetCurrentTime())
{
CString strTime;
strTime = timeObj.Format("%Y-%m-%d %H:%M:%S"); // TODO: use windows time locale
return strTime;
}
/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions
// ID of show window request message
const UINT WM_BSHOWWINDOW = RegisterWindowMessage(SHOW_WIN_MSG);
// ID of net activity message
const UINT WM_BNETACTIVITY = RegisterWindowMessage(NET_ACTIVITY_MSG);
// ID of start screensaver request message
const UINT WM_BSTARTSCREENSAVER = RegisterWindowMessage(START_SS_MSG);
// ID of end screensaver request message
const UINT WM_BENDSCREENSAVER = RegisterWindowMessage(STOP_SS_MSG);
// ID of taskbar created message
const UINT WM_BTASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));
BEGIN_MESSAGE_MAP(CMainWindow, CWnd)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_CREATE()
ON_WM_RBUTTONDOWN()
ON_WM_SIZE()
ON_WM_SETFOCUS()
ON_WM_TIMER()
//ON_COMMAND(ID_FILE_CLEARINACTIVE, OnCommandFileClearInactive)
//ON_COMMAND(ID_FILE_CLEARMESSAGES, OnCommandFileClearMessages)
ON_COMMAND(ID_FILE_RUN_REQUEST_ALWAYS, OnCommandRunRequestAlways)
ON_COMMAND(ID_FILE_RUN_REQUEST_AUTO, OnCommandRunRequestAuto)
ON_COMMAND(ID_FILE_RUN_REQUEST_NEVER, OnCommandRunRequestNever)
ON_COMMAND(ID_FILE_TOGGLE_NETWORK_ACCESS, OnFileDisableNetworkAccess)
ON_COMMAND(ID_FILE_RUN_BENCHMARKS, OnCommandRunBenchmarks)
ON_COMMAND(ID_FILE_HIDE, OnCommandHide)
ON_COMMAND(ID_FILE_EXIT, OnCommandExit)
ON_COMMAND(ID_SETTINGS_LOGIN, OnCommandSettingsLogin)
ON_COMMAND(ID_SETTINGS_PROXYSERVER, OnCommandSettingsProxyServer)
ON_COMMAND(ID_HELP_ABOUT, OnCommandHelpAbout)
ON_COMMAND(ID_PROJECT_WEB_SITE, OnCommandProjectWebSite)
ON_COMMAND(ID_PROJECT_GET_PREFS, OnCommandProjectGetPrefs)
ON_COMMAND(ID_PROJECT_DETACH, OnCommandProjectDetach)
ON_COMMAND(ID_PROJECT_RESET, OnCommandProjectReset)
ON_COMMAND(ID_PROJECT_NOMOREWORK, OnCommandProjectNoMoreWork)
ON_COMMAND(ID_STATUSICON_SHOW, OnCommandShow)
ON_COMMAND(ID_STATUSICON_HIDE, OnCommandHide)
ON_COMMAND(ID_STATUSICON_EXIT, OnCommandExit)
ON_COMMAND(ID_WORK_SHOWGRAPHICS, OnCommandWorkShowGraphics)
ON_COMMAND(ID_TRANSFERS_RETRYNOW, OnCommandTransfersRetryNow)
ON_COMMAND(ID_MESSAGE_COPY_TO_CLIP, OnCommandMessageCopyToClip) // Added by JBK.
ON_MESSAGE(STATUS_ICON_ID, OnStatusIcon)
ON_MESSAGE(WM_QUERYENDSESSION, OnSystemLogoff)
ON_REGISTERED_MESSAGE(WM_BSHOWWINDOW, OnShowWindow)
ON_REGISTERED_MESSAGE(WM_BNETACTIVITY, OnNetworkActivity)
ON_REGISTERED_MESSAGE(WM_BSTARTSCREENSAVER, OnStartScreensaver)
ON_REGISTERED_MESSAGE(WM_BENDSCREENSAVER, OnEndScreensaver)
ON_REGISTERED_MESSAGE(WM_BTASKBARCREATED, OnTaskbarCreated)
END_MESSAGE_MAP()
//////////
// CMainWindow::CMainWindow
// arguments: void
// returns: void
// function: registers window class, creates and poisitions window.
CMainWindow::CMainWindow()
{
WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
wndcls.style = 0;
//wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = g_myApp.LoadIcon(IDI_ICON);
wndcls.hCursor = g_myApp.LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
wndcls.lpszMenuName = NULL;
// Specify class name for using FindWindow in the installer
wndcls.lpszClassName = _T("BOINCWindowClass");
// Register the new class and exit if it fails
if(!AfxRegisterClass(&wndcls)) return;
// register window class
//CString strWndClass = AfxRegisterWndClass (0, g_myApp.LoadStandardCursor(IDC_ARROW),
// (HBRUSH)(COLOR_3DFACE+1), g_myApp.LoadIcon(IDI_ICON));
m_MenuLabelRetryNow = "&Update (retry now)";
m_MenuLabelGetPreferences = "&Update";
m_DialogResetQuery = "Are you sure you want to reset the project %1?";
m_DialogDetachQuery = "Are you sure you want to detach from the project %1?";
m_MenuLabelGetWork = "&Allow new work request";
m_MenuLabelNoMoreWork = "Don't request more work";
// create and position window
CreateEx(0, wndcls.lpszClassName, WND_TITLE,
WS_OVERLAPPEDWINDOW|WS_EX_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL);
}
//////////
// CMainWindow::GetPieColor
// arguments: nPiece: index of pie piece
// returns: the color that piece should be
// function: detemines colors for pie pieces in usage control
COLORREF CMainWindow::GetPieColor(int nPiece)
{
return RGB( (32*(nPiece%6))%256, 0, (256-32*(nPiece%6)-1)%256 );
}
//////////
// CMainWindow::ClearProjectItems
// arguments: proj_url: master url of the project
// returns: void
// function: removes all active and inactive projects, transfers,
// and workunits associated with the project
void CMainWindow::ClearProjectItems(char *proj_url) {
int i;
CString ItemURL;
// TODO: find out how proj_url can be null
if (!proj_url) {
fprintf(stderr, "CMainWindow::ClearProjectItems failed: proj_url is null");
return;
}
for(i = 0; i < m_ProjectListCtrl.GetItemCount();) {
ItemURL = m_ProjectListCtrl.GetProjectURL(i);
if(!ItemURL.Compare(proj_url)) {
m_ProjectListCtrl.DeleteItem(i);
} else {
i ++;
}
}
for(i = 0; i < m_ResultListCtrl.GetItemCount();) {
ItemURL = m_ResultListCtrl.GetProjectURL(i);
if(!ItemURL.Compare(proj_url)) {
m_ResultListCtrl.DeleteItem(i);
} else {
i ++;
}
}
for(i = 0; i < m_XferListCtrl.GetItemCount();) {
ItemURL = m_XferListCtrl.GetProjectURL(i);
if(!ItemURL.Compare(proj_url)) {
m_XferListCtrl.DeleteItem(i);
} else {
i ++;
}
}
}
//////////
// CMainWindow::UpdateGUI
// arguments: pcs: pointer to the client state for the gui to display
// returns: void
// function: syncronizes list controls with vectors in client state
// and displays them.
void CMainWindow::UpdateGUI(CLIENT_STATE* pcs)
{
CString strBuf;
double totalres;
unsigned int ui;
int i, n;
string appname;
// If we failed to set the taskbar icon before, keep trying!
if (m_nDesiredIconState != m_nIconState)
SetStatusIcon(m_nDesiredIconState);
switch (m_TabCtrl.GetCurSel()) {
case PROJECT_ID:
// display projects
m_ProjectListCtrl.SetRedraw(FALSE);
totalres = 0;
Syncronize(&m_ProjectListCtrl, (vector<void*>*)(&pcs->projects));
for(ui = 0; ui < pcs->projects.size(); ui ++) {
totalres += pcs->projects[ui]->resource_share;
}
for(i = 0; i < m_ProjectListCtrl.GetItemCount(); i ++) {
PROJECT* pr = (PROJECT*)m_ProjectListCtrl.GetItemData(i);
if(!pr) {
m_ProjectListCtrl.DeleteItem(i--);
continue;
}
// Set the master URL for this object
if (m_ProjectListCtrl.GetProjectURL(i) != pr->master_url)
m_ProjectListCtrl.SetProjectURL(i, pr->master_url);
// project
if (m_ProjectListCtrl.GetItemText(i, 0) != pr->get_project_name())
m_ProjectListCtrl.SetItemText(i, 0, pr->get_project_name());
// account
if (m_ProjectListCtrl.GetItemText(i, 1) != pr->user_name)
m_ProjectListCtrl.SetItemText(i, 1, pr->user_name);
// total credit
strBuf.Format("%0.2f", pr->user_total_credit);
if (m_ProjectListCtrl.GetItemText(i, 2) != strBuf)
m_ProjectListCtrl.SetItemText(i, 2, strBuf);
// avg credit
strBuf.Format("%0.2f", pr->user_expavg_credit);
if (m_ProjectListCtrl.GetItemText(i, 3) != strBuf)
m_ProjectListCtrl.SetItemText(i, 3, strBuf);
// resource share
if(totalres <= 0) {
if (m_ProjectListCtrl.GetItemProgress(i, 4) != 100)
m_ProjectListCtrl.SetItemProgress(i, 4, 100);
} else {
if (m_ProjectListCtrl.GetItemProgress(i, 4) != (100 * pr->resource_share) / totalres)
m_ProjectListCtrl.SetItemProgress(i, 4, (100 * pr->resource_share) / totalres);
}
}
m_ProjectListCtrl.SetRedraw(TRUE);
break;
case RESULT_ID:
// update results
m_ResultListCtrl.SetRedraw(FALSE);
Syncronize(&m_ResultListCtrl, (vector<void*>*)(&pcs->results));
for(i = 0; i < m_ResultListCtrl.GetItemCount(); i ++) {
RESULT* re = (RESULT*)m_ResultListCtrl.GetItemData(i);
if(!re) {
m_ResultListCtrl.DeleteItem(i--);
continue;
}
// Set the master URL for this object
if (m_ResultListCtrl.GetProjectURL(i) != re->project->master_url)
m_ResultListCtrl.SetProjectURL(i, re->project->master_url);
// project
if (m_ResultListCtrl.GetItemText(i, 0) != re->project->project_name)
m_ResultListCtrl.SetItemText(i, 0, re->project->project_name);
// application
re->get_app_version_string(appname);
if (strcmp(m_ResultListCtrl.GetItemText(i, 1), appname.c_str())) {
m_ResultListCtrl.SetItemText(i, 1, appname.c_str());
}
// name
if (m_ResultListCtrl.GetItemText(i, 2) != re->name)
m_ResultListCtrl.SetItemText(i, 2, re->name);
// cpu time
ACTIVE_TASK* at = gstate.lookup_active_task_by_result(re);
double cur_cpu;
if (at) {
cur_cpu = at->current_cpu_time;
} else {
if(re->state < RESULT_COMPUTE_ERROR) cur_cpu = 0;
else cur_cpu = re->final_cpu_time;
}
int cpuhour = (int)(cur_cpu / (60 * 60));
int cpumin = (int)(cur_cpu / 60) % 60;
int cpusec = (int)(cur_cpu) % 60;
if (cur_cpu == 0)
strBuf.Format("---");
else
strBuf.Format("%0.2d:%0.2d:%0.2d", cpuhour, cpumin, cpusec);
if (m_ResultListCtrl.GetItemText(i, 3) != strBuf)
m_ResultListCtrl.SetItemText(i, 3, strBuf);
// progress
if(!at) {
if(re->state < RESULT_COMPUTE_ERROR)
m_ResultListCtrl.SetItemProgress(i, 4, 0);
else
m_ResultListCtrl.SetItemProgress(i, 4, 100);
} else {
m_ResultListCtrl.SetItemProgress(i, 4, at->fraction_done * 100);
}
// to completion
double tocomp = re->estimated_cpu_time_remaining();
if (tocomp > 0) {
cpuhour = (int)(tocomp / (60 * 60));
cpumin = (int)(tocomp / 60) % 60;
cpusec = (int)(tocomp) % 60;
strBuf.Format("%0.2d:%0.2d:%0.2d", cpuhour, cpumin, cpusec);
//strBuf.Format("%s [%.f]", strBuf, tocomp);
//if (at) {
// strBuf.Format("%s frac_done=%.7f frac_r=%.9f rec_ch=%.9f", strBuf, at->fraction_done, at->frac_rate_of_change, at->recent_change);
//}
} else {
strBuf = "---";
}
if (m_ResultListCtrl.GetItemText(i, 5) != strBuf)
m_ResultListCtrl.SetItemText(i, 5, strBuf);
// report deadline
if (re->report_deadline) {
strBuf = GetStrTime((__time64_t)re->report_deadline);
} else {
strBuf = "---";
}
if (m_ResultListCtrl.GetItemText(i,6) != strBuf) {
m_ResultListCtrl.SetItemText(i, 6, strBuf);
}
// status
switch(re->state) {
case RESULT_NEW:
strBuf.Format(g_szMiscItems[0]); break;
case RESULT_FILES_DOWNLOADING:
if (re->ready_to_report) {
strBuf.Format(g_szMiscItems[11]);
} else {
strBuf.Format(g_szMiscItems[9]);
}
break;
case RESULT_FILES_DOWNLOADED:
if (at) {
if (at->scheduler_state == CPU_SCHED_SCHEDULED) {
strBuf.Format(g_szMiscItems[1]);
} else if (at->scheduler_state == CPU_SCHED_PREEMPTED) {
strBuf.Format(g_szMiscItems[14]);
} else if (at->scheduler_state == CPU_SCHED_UNINITIALIZED) {
strBuf.Format(g_szMiscItems[2]);
}
}
else strBuf.Format(g_szMiscItems[2]);
break;
case RESULT_COMPUTE_ERROR:
strBuf.Format(g_szMiscItems[3]); break;
break;
case RESULT_FILES_UPLOADING:
if (re->ready_to_report) {
strBuf.Format(g_szMiscItems[12]);
} else {
strBuf.Format(g_szMiscItems[8]);
}
break;
default:
if (re->got_server_ack) strBuf.Format(g_szMiscItems[5]);
else if (re->ready_to_report) strBuf.Format(g_szMiscItems[4]);
else {
strBuf.Format("%s %d", g_szMiscItems[6], re->state);
}
break;
}
if (gstate.activities_suspended) {
strBuf = CString(g_szMiscItems[13]) + " (" + strBuf + ")";
}
if (m_ResultListCtrl.GetItemText(i, 7) != strBuf)
m_ResultListCtrl.SetItemText(i, 7, strBuf);
}
m_ResultListCtrl.SetRedraw(TRUE);
break;
case XFER_ID:
// update xfers
m_XferListCtrl.SetRedraw(FALSE);
Syncronize(&m_XferListCtrl, (vector<void*>*)(&pcs->pers_file_xfers->pers_file_xfers));
for(i = 0; i < m_XferListCtrl.GetItemCount(); i ++) {
PERS_FILE_XFER* pfx = (PERS_FILE_XFER*)m_XferListCtrl.GetItemData(i);
if(!pfx) {
m_XferListCtrl.DeleteItem(i--);
continue;
}
// Set the master URL for this object
if (m_XferListCtrl.GetProjectURL(i) != pfx->fip->project->master_url)
m_XferListCtrl.SetProjectURL(i, pfx->fip->project->master_url);
// project
if (m_XferListCtrl.GetItemText(i, 0) != pfx->fip->project->project_name)
m_XferListCtrl.SetItemText(i, 0, pfx->fip->project->project_name);
// file
if (m_XferListCtrl.GetItemText(i, 1) != pfx->fip->name)
m_XferListCtrl.SetItemText(i, 1, pfx->fip->name);
// progress
double xSent = 0, f_size;
char pathnm[256];
if (pfx->fxp) {
xSent = pfx->fxp->bytes_xferred;
}
else if (pfx->is_upload) {
xSent = 0;
} else {
get_pathname(pfx->fip, pathnm);
if (file_size(pathnm, f_size)) {
f_size = 0;
}
xSent = f_size;
}
// if (m_XferListCtrl.GetItemProgress(i, 2) != 100 * xSent / pfx->fip->nbytes)
m_XferListCtrl.SetItemProgress(i, 2, 100 * xSent / pfx->fip->nbytes);
// size
char size_buf[256];
nbytes_to_string(xSent, pfx->fip->nbytes, size_buf, 256);
if (strcmp(m_XferListCtrl.GetItemText(i, 3).GetBuffer(0), size_buf))
m_XferListCtrl.SetItemText(i, 3, size_buf);
// time
double xtime = 0;
xtime = pfx->time_so_far;
int xhour = (int)(xtime / (60 * 60));
int xmin = (int)(xtime / 60) % 60;
int xsec = (int)(xtime) % 60;
strBuf.Format("%0.2d:%0.2d:%0.2d", xhour, xmin, xsec);
if (m_XferListCtrl.GetItemText(i, 4) != strBuf.GetBuffer(0))
m_XferListCtrl.SetItemText(i, 4, strBuf.GetBuffer(0));
// speed
strBuf.Format("0.00 KBps");
if(pfx->fxp) {
strBuf.Format("%0.2f KBps", pfx->fxp->xfer_speed/1024);
}
if (m_XferListCtrl.GetItemText(i, 5) != strBuf.GetBuffer(0))
m_XferListCtrl.SetItemText(i, 5, strBuf.GetBuffer(0));
// status
if (pfx->next_request_time > dtime()) {
double xtime = pfx->next_request_time-dtime();
int xhour = (int)(xtime / (60 * 60));
int xmin = (int)(xtime / 60) % 60;
int xsec = (int)(xtime) % 60;
strBuf.Format("%s %0.2d:%0.2d:%0.2d", g_szMiscItems[10], xhour, xmin, xsec);
} else if (pfx->fip->status == ERR_GIVEUP_DOWNLOAD) {
strBuf.Format(g_szMiscItems[11]);
} else if (pfx->fip->status == ERR_GIVEUP_UPLOAD) {
strBuf.Format(g_szMiscItems[12]);
} else {
strBuf.Format(pfx->fip->generated_locally?g_szMiscItems[8]:g_szMiscItems[9]);
}
if (gstate.activities_suspended) {
strBuf = CString(g_szMiscItems[13]) + " (" + strBuf + ")";
}
if (m_XferListCtrl.GetItemText(i, 6) != strBuf)
m_XferListCtrl.SetItemText(i, 6, strBuf);
}
m_XferListCtrl.SetRedraw(TRUE);
break;
case USAGE_ID:
// update usage
double xDiskTotal;
double xDiskFree; get_filesystem_info(xDiskTotal, xDiskFree);
double xDiskUsed = xDiskTotal - xDiskFree;
double xDiskUsage; gstate.total_disk_usage(xDiskUsage);
double xDiskAllow; gstate.allowed_disk_usage(xDiskAllow); xDiskAllow = xDiskAllow - xDiskUsage;
m_UsagePieCtrl.SetTotal(xDiskTotal);
if(xDiskAllow > 0) {
m_UsagePieCtrl.SetPiece(0, xDiskFree - xDiskAllow); // Free space
m_UsagePieCtrl.SetPiece(3, xDiskAllow);
} else {
m_UsagePieCtrl.SetPiece(0, xDiskFree); // Free space
m_UsagePieCtrl.SetPiece(3, 0);
}
m_UsagePieCtrl.SetPiece(1, xDiskUsed - xDiskUsage); // Used space
m_UsagePieCtrl.SetPiece(2, xDiskUsage); // Used space: BOINC
m_UsagePieCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME);
while(m_UsageBOINCPieCtrl.GetItemCount() - 2 < (int)gstate.projects.size()) {
m_UsageBOINCPieCtrl.AddPiece("", GetPieColor(m_UsageBOINCPieCtrl.GetItemCount()), 0);
}
while(m_UsageBOINCPieCtrl.GetItemCount() - 2 > (int)gstate.projects.size()) {
m_UsageBOINCPieCtrl.RemovePiece(m_UsageBOINCPieCtrl.GetItemCount() - 2);
}
if(xDiskAllow > 0) m_UsageBOINCPieCtrl.SetTotal(xDiskUsage + xDiskAllow);
else m_UsageBOINCPieCtrl.SetTotal(xDiskUsage);
m_UsageBOINCPieCtrl.SetPiece(0, 1); // BOINC: core application
m_UsageBOINCPieCtrl.SetPiece(1, 1);
for(ui = 0; ui < gstate.projects.size(); ui ++) {
double xUsage;
CString strLabel;
strLabel.Format("%s", gstate.projects[ui]->project_name);
gstate.project_disk_usage(gstate.projects[ui], xUsage);
m_UsageBOINCPieCtrl.SetPieceLabel(ui + 2, strLabel.GetBuffer(0));
m_UsageBOINCPieCtrl.SetPiece(ui + 2, xUsage);
xDiskUsage -= xUsage;
}
m_UsageBOINCPieCtrl.SetPiece(0, xDiskUsage); // BOINC: core application
m_UsageBOINCPieCtrl.SetPiece(1, xDiskAllow);
m_UsageBOINCPieCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME);
break;
}
// check message pane size, and reduce if there are too many
n = m_MessageListCtrl.GetItemCount();
if (n > 200) {
m_MessageListCtrl.SetRedraw(FALSE);
for (i = 0 ; i < n - 200 ; i++)
m_MessageListCtrl.DeleteItem(0);
m_MessageListCtrl.SetRedraw(TRUE);
}
// make icon flash if needed
TCITEM tcItem;
memset(&tcItem, 0, sizeof(TCITEMW)); // start with NULL defaults
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_HIGHLIGHTED;
if(m_bMessage || m_bRequest) {
if(m_bRequest){
if(m_nToggleIconState == ICON_NORMAL){
SetStatusIcon(ICON_NORMAL);
m_nToggleIconState = ICON_NETWORK;
} else {
SetStatusIcon(ICON_NETWORK);
m_nToggleIconState = ICON_NORMAL;
}
} else {
if(m_nIconBlinkCount < (ICON_BLINKCOUNT * 2)) // blink the icon to grab users attention
{
if(m_nToggleIconState == ICON_NORMAL){
SetStatusIcon(ICON_NORMAL);
m_nIconBlinkCount++;
switch(m_nMessage)
{
case MSG_INFO: m_nToggleIconState = ICON_INFO; break;
case MSG_ERROR: m_nToggleIconState = ICON_ERROR; break;
case MSG_WARNING: m_nToggleIconState = ICON_WARNING; break;
}
} else {
SetStatusIcon(m_nToggleIconState);
tcItem.dwState = TCIS_HIGHLIGHTED;
m_nToggleIconState = ICON_NORMAL;
}
}
else // We should only display the message icon now instead of blinking
{
switch(m_nMessage)
{
case MSG_INFO: m_nToggleIconState = ICON_INFO; break;
case MSG_ERROR: m_nToggleIconState = ICON_ERROR; break;
case MSG_WARNING: m_nToggleIconState = ICON_WARNING; break;
}
SetStatusIcon(m_nToggleIconState);
tcItem.dwState = TCIS_HIGHLIGHTED;
}
}
} else {
SetStatusIcon(ICON_NORMAL);
m_nIconBlinkCount = 0;
}
m_TabCtrl.SetItem(3, &tcItem);
}
//////////
// CMainWindow::MessageUser
// arguments: message: message string to display
// priority: string with priority of message
// returns: void
// function: if message is MSG_ERROR priority, flashes the status icon,
// then adds to message edit control.
void CMainWindow::MessageUser(char* szProject, char* szMessage, int nPriority)
{
if(!m_MessageListCtrl.GetSafeHwnd()) return;
int nNewPos = m_MessageListCtrl.GetItemCount();
m_MessageListCtrl.InsertItem(nNewPos, szProject);
m_MessageListCtrl.SetItemText(nNewPos, 1, GetStrTime());
m_MessageListCtrl.SetItemText(nNewPos, 2, szMessage);
m_MessageListCtrl.Scroll(CSize(0, m_MessageListCtrl.ApproximateViewRect().cy));
// set status icon to flash
if((m_TabCtrl.GetCurSel() != MESSAGE_ID) || (GetForegroundWindow() != this)) {
m_bMessage = TRUE;
if (nPriority == MSG_ERROR){
m_nMessage = nPriority;
} else if ((nPriority == MSG_WARNING) && (m_nMessage != MSG_ERROR)){
m_nMessage = nPriority;
} else if ((nPriority == MSG_INFO) && ((m_nMessage != MSG_WARNING) || (m_nMessage != MSG_ERROR))){
m_nMessage = nPriority;
}
}
}
//////////
// CMainWindow::RequestNetConnect
// arguments: void
// returns: true if the user can connect, false otherwise
// function: asks the user for permission to connect to the network
BOOL CMainWindow::RequestNetConnect()
{
if(GetForegroundWindow() != this || !IsWindowVisible()) {
m_bRequest = true;
return FALSE;
}
CConnectDialog dlg(IDD_CONNECT);
int retval = dlg.DoModal();
m_bRequest = false;
if(retval == IDOK) {
return TRUE;
}
return FALSE;
}
//////////
// CMainWindow::ShowTab
// arguments: nTab: tab number to show
// returns: void
// function: handles everything necessary to switch to a new tab
void CMainWindow::ShowTab(int nTab)
{
m_TabCtrl.SetCurSel(nTab);
// hide all windows except the newly selected control
m_ProjectListCtrl.ShowWindow(SW_HIDE);
m_ResultListCtrl.ShowWindow(SW_HIDE);
m_XferListCtrl.ShowWindow(SW_HIDE);
m_MessageListCtrl.ShowWindow(SW_HIDE);
m_UsagePieCtrl.ShowWindow(SW_HIDE);
m_UsageBOINCPieCtrl.ShowWindow(SW_HIDE);
if(nTab == PROJECT_ID) {
m_ProjectListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
m_ProjectListCtrl.ShowWindow(SW_SHOW);
} else if(nTab == RESULT_ID) {
m_ResultListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
m_ResultListCtrl.ShowWindow(SW_SHOW);
} else if(nTab == XFER_ID) {
m_XferListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
m_XferListCtrl.ShowWindow(SW_SHOW);
} else if(nTab == MESSAGE_ID) {
if(m_bMessage) {
m_bMessage = false;
SetStatusIcon(ICON_NORMAL);
}
m_MessageListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
m_MessageListCtrl.ShowWindow(SW_SHOW);
} else if(nTab == USAGE_ID) {
m_UsagePieCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
m_UsagePieCtrl.ShowWindow(SW_SHOW);
m_UsageBOINCPieCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
m_UsageBOINCPieCtrl.ShowWindow(SW_SHOW);
}
m_TabCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
RedrawWindow();
UpdateGUI(&gstate);
}
//////////
// CMainWindow::SetStatusIcon
// arguments: dwMessage: hide or show the icon
// returns: void
// function: controls the status icon in the taskbar
bool CMainWindow::SetStatusIcon(DWORD dwMessage)
{
BOOL success = false;
NOTIFYICONDATA icon_data;
if((dwMessage != ICON_OFF) &&
(dwMessage != ICON_NORMAL) &&
(dwMessage != ICON_NETWORK) &&
(dwMessage != ICON_ERROR) &&
(dwMessage != ICON_INFO) &&
(dwMessage != ICON_WARNING)) {
return false;
}
// if icon is in that state already, there is nothing to do
if(dwMessage == m_nIconState) return true;
m_nDesiredIconState = dwMessage;
memset( &icon_data, 0, sizeof(NOTIFYICONDATA) );
icon_data.cbSize = sizeof(NOTIFYICONDATA);
icon_data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
icon_data.hWnd = GetSafeHwnd();
icon_data.uID = STATUS_ICON_ID;
safe_strncpy(icon_data.szTip, WND_TITLE, min(sizeof(icon_data.szTip), sizeof(WND_TITLE)));
icon_data.uCallbackMessage = STATUS_ICON_ID;
if(dwMessage == ICON_OFF) {
icon_data.hIcon = NULL;
success = Shell_NotifyIcon(NIM_DELETE, &icon_data);
} else if(dwMessage == ICON_NORMAL) {
icon_data.hIcon = g_myApp.LoadIcon(IDI_ICONSMALL);
if(m_nIconState == ICON_OFF) {
success = Shell_NotifyIcon(NIM_ADD, &icon_data);
} else {
success = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
}
} else if(dwMessage == ICON_NETWORK) {
icon_data.hIcon = g_myApp.LoadIcon(IDI_ICONNETWORK);
if(m_nIconState == ICON_OFF) {
success = Shell_NotifyIcon(NIM_ADD, &icon_data);
} else {
success = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
}
} else if(dwMessage == ICON_ERROR) {
icon_data.hIcon = g_myApp.LoadIcon(IDI_ICONERROR);
if(m_nIconState == ICON_OFF) {
success = Shell_NotifyIcon(NIM_ADD, &icon_data);
} else {
success = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
}
} else if(dwMessage == ICON_INFO) {
icon_data.hIcon = g_myApp.LoadIcon(IDI_ICONINFO);
if(m_nIconState == ICON_OFF) {
success = Shell_NotifyIcon(NIM_ADD, &icon_data);
} else {
success = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
}
} else if(dwMessage == ICON_WARNING) {
icon_data.hIcon = g_myApp.LoadIcon(IDI_ICONWARNING);
if(m_nIconState == ICON_OFF) {
success = Shell_NotifyIcon(NIM_ADD, &icon_data);
} else {
success = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
}
}
if (!success) return false;
m_nIconState = dwMessage;
return true;
}
//////////
// CMainWindow::SaveListControls
// arguments: void
// returns: void
// function: saves relevant elements of list controls
void CMainWindow::SaveListControls()
{
char szPath[256];
CString strKey, strVal;
GetCurrentDirectory(256, szPath);
strcat(szPath, "\\");
strcat(szPath, LIST_STATE_FILE_NAME);
boinc_delete_file(szPath);
m_ProjectListCtrl.SaveInactive(szPath, "PROJECTS");
m_ResultListCtrl.SaveInactive(szPath, "WORK");
m_XferListCtrl.SaveInactive(szPath, "TRANSFERS");
m_MessageListCtrl.SaveInactive(szPath, "MESSAGES");
}
//////////
// CMainWindow::LoadListControls
// arguments: void
// returns: void
// function: loads relevant elements of list controls
void CMainWindow::LoadListControls()
{
char szPath[256];
CString strKey, strVal;
GetCurrentDirectory(256, szPath);
strcat(szPath, "\\");
strcat(szPath, LIST_STATE_FILE_NAME);
m_ProjectListCtrl.LoadInactive(szPath, "PROJECTS");
m_ResultListCtrl.LoadInactive(szPath, "WORK");
m_XferListCtrl.LoadInactive(szPath, "TRANSFERS");
m_MessageListCtrl.LoadInactive(szPath, "MESSAGES");
}
inline void SaveColumns(CProgressListCtrl& listCtrl,
const char* header_name,
const char* szPath
)
{
int colOrder[MAX_COLS];
int itemCount = listCtrl.GetHeaderCtrl()->GetItemCount();
listCtrl.GetColumnOrderArray(colOrder, itemCount);
CString strKey, strVal;
strKey.Format("%s-order", header_name);
WritePrivateProfileStruct("HEADERS", strKey, colOrder, sizeof(int)*itemCount, szPath);
for(int i = 0; i < itemCount; i ++) {
strKey.Format("%s-%d", header_name, i);
strVal.Format("%d", listCtrl.GetColumnWidth(i));
WritePrivateProfileString("HEADERS", strKey, strVal, szPath);
}
}
inline void LoadColumns(CProgressListCtrl& listCtrl,
const char* header_name,
const char* szPath,
int const* default_widths = NULL
)
{
int colOrder[MAX_COLS];
int itemCount = listCtrl.GetHeaderCtrl()->GetItemCount();
CString strKey;
strKey.Format("%s-order", header_name);
memset(colOrder, 0, sizeof(colOrder));
if(GetPrivateProfileStruct("HEADERS", strKey, colOrder, sizeof(int)*itemCount, szPath)) {
listCtrl.SetColumnOrderArray(itemCount, colOrder);
}
for(int i = 0; i < itemCount; i ++) {
strKey.Format("%s-%d", header_name, i);
int width = default_widths ? default_widths[i] : DEF_COL_WIDTH;
width = GetPrivateProfileInt("HEADERS", strKey, width, szPath);
listCtrl.SetColumnWidth(i, width);
}
}
//////////
// CMainWindow::SaveUserSettings
// arguments: void
// returns: void
// function: saves relevant user settings to boinc ini file
void CMainWindow::SaveUserSettings()
{
char szPath[256];
CString strKey, strVal;
GetCurrentDirectory(256, szPath);
strcat(szPath, "\\");
strcat(szPath, INI_FILE_NAME);
// get rid of old lists
boinc_delete_file(szPath);
// save window size/position
CRect rt;
GetWindowRect(&rt);
strVal.Format("%d", rt.left);
WritePrivateProfileString("WINDOW", "xposition", strVal, szPath);
strVal.Format("%d", rt.top);
WritePrivateProfileString("WINDOW", "yposition", strVal, szPath);
strVal.Format("%d", rt.Width());
WritePrivateProfileString("WINDOW", "width", strVal, szPath);
strVal.Format("%d", rt.Height());
WritePrivateProfileString("WINDOW", "height", strVal, szPath);
// save selected tab
strVal.Format("%d", m_TabCtrl.GetCurSel());
WritePrivateProfileString("WINDOW", "selection", strVal, szPath);
SaveColumns(m_ProjectListCtrl, "projects", szPath);
SaveColumns(m_ResultListCtrl, "results", szPath);
SaveColumns(m_XferListCtrl, "xfers", szPath);
SaveColumns(m_MessageListCtrl, "messages", szPath);
}
static const int message_header_widths[] = {
DEF_COL_WIDTH,
(int)(DEF_COL_WIDTH*1.5),
DEF_COL_WIDTH*4
};
//////////
// CMainWindow::LoadUserSettings
// arguments: void
// returns: void
// function: loads relevant user settings from boinc ini file
void CMainWindow::LoadUserSettings()
{
char szPath[256];
CString strKey;
GetCurrentDirectory(256, szPath);
strcat(szPath, "\\");
strcat(szPath, INI_FILE_NAME);
int nBuf;
// load window size/position
CRect rt;
nBuf = GetPrivateProfileInt("WINDOW", "xposition", 100, szPath);
rt.left = nBuf;
nBuf = GetPrivateProfileInt("WINDOW", "yposition", 100, szPath);
rt.top = nBuf;
nBuf = GetPrivateProfileInt("WINDOW", "width", 600, szPath);
rt.right = nBuf + rt.left;
nBuf = GetPrivateProfileInt("WINDOW", "height", 400, szPath);
rt.bottom = nBuf + rt.top;
CRect rtScreen, rtInt;
HDC screenDC=::GetDC(NULL);
rtScreen.left = rtScreen.top = 0;
rtScreen.right=GetDeviceCaps(screenDC, HORZRES);
rtScreen.bottom=GetDeviceCaps(screenDC, VERTRES);
::ReleaseDC(NULL, screenDC);
rtInt.IntersectRect(&rt, &rtScreen);
if(rtInt.IsRectEmpty()) {
rt.SetRect(100, 100, 600, 400);
}
SetWindowPos(&wndNoTopMost, rt.left, rt.top, rt.Width(), rt.Height(), 0);
// load selected tab
nBuf = GetPrivateProfileInt("WINDOW", "selection", 0, szPath);
ShowTab(nBuf);
LoadColumns(m_ProjectListCtrl, "projects", szPath);
LoadColumns(m_ResultListCtrl, "results", szPath);
LoadColumns(m_XferListCtrl, "xfers", szPath);
LoadColumns(m_MessageListCtrl, "messages", szPath, message_header_widths);
}
//////////
// CMainWindow::LoadLanguage
// arguments: void
// returns: void
// function: loads new captions from language file
void CMainWindow::LoadLanguage()
{
CString strPath;
GetLanguageFilename(strPath);
int col;
CString strSection;
// load column headers
strSection.Format("HEADER-%s", g_szTabItems[PROJECT_ID]);
for(col = 0; col < PROJECT_COLS; col ++) {
GetPrivateProfileString(strSection, g_szColumnTitles[PROJECT_ID][col], g_szColumnTitles[PROJECT_ID][col], g_szColumnTitles[PROJECT_ID][col], 256, strPath);
}
GetPrivateProfileString(strSection, "Title", g_szTabItems[PROJECT_ID], g_szTabItems[PROJECT_ID], 16, strPath);
strSection.Format("HEADER-%s", g_szTabItems[RESULT_ID]);
for(col = 0; col < RESULT_COLS; col ++) {
GetPrivateProfileString(strSection, g_szColumnTitles[RESULT_ID][col], g_szColumnTitles[RESULT_ID][col], g_szColumnTitles[RESULT_ID][col], 256, strPath);
}
GetPrivateProfileString(strSection, "Title", g_szTabItems[RESULT_ID], g_szTabItems[RESULT_ID], 16, strPath);
strSection.Format("HEADER-%s", g_szTabItems[XFER_ID]);
for(col = 0; col < XFER_COLS; col ++) {
GetPrivateProfileString(strSection, g_szColumnTitles[XFER_ID][col], g_szColumnTitles[XFER_ID][col], g_szColumnTitles[XFER_ID][col], 256, strPath);
}
GetPrivateProfileString(strSection, "Title", g_szTabItems[XFER_ID], g_szTabItems[XFER_ID], 16, strPath);
strSection.Format("HEADER-%s", g_szTabItems[MESSAGE_ID]);
for(col = 0; col < MESSAGE_COLS; col ++) {
GetPrivateProfileString(strSection, g_szColumnTitles[MESSAGE_ID][col], g_szColumnTitles[MESSAGE_ID][col], g_szColumnTitles[MESSAGE_ID][col], 256, strPath);
}
GetPrivateProfileString(strSection, "Title", g_szTabItems[MESSAGE_ID], g_szTabItems[MESSAGE_ID], 16, strPath);
// load usage labels
strSection.Format("HEADER-%s", g_szTabItems[USAGE_ID]);
for(col = 0; col < MAX_USAGE_STR; col ++) {
GetPrivateProfileString(strSection, g_szUsageItems[col], g_szUsageItems[col], g_szUsageItems[col], 256, strPath);
}
GetPrivateProfileString(strSection, "Title", g_szTabItems[USAGE_ID], g_szTabItems[USAGE_ID], 16, strPath);
// load miscellaneous text
strSection.Format("HEADER-MISC");
for(col = 0; col < MAX_MISC_STR; col ++) {
GetPrivateProfileString(strSection, g_szMiscItems[col], g_szMiscItems[col], g_szMiscItems[col], 256, strPath);
}
// load menu items
CString strItem, strItemNoAmp;
char szItem[256];
int i, is;
for(i = 0; i < (int)m_MainMenu.GetMenuItemCount(); i ++) {
m_MainMenu.GetMenuString(i, strItem, MF_BYPOSITION);
strItemNoAmp = strItem; strItemNoAmp.Remove('&');
strSection.Format("MENU-%s", strItemNoAmp);
GetPrivateProfileString(strSection, "Title", strItem, szItem, 256, strPath);
m_MainMenu.ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, szItem);
CMenu* pSubMenu = m_MainMenu.GetSubMenu(i);
if(!pSubMenu) continue;
for(is = 0; is < (int)pSubMenu->GetMenuItemCount(); is ++) {
pSubMenu->GetMenuString(is, strItem, MF_BYPOSITION);
if (UpdateLanguageString(strSection, strItem, strPath)) {
pSubMenu->ModifyMenu(is, MF_BYPOSITION|MF_STRING, pSubMenu->GetMenuItemID(is), strItem);
}
}
}
for(i = 0; i < (int)m_ContextMenu.GetMenuItemCount(); i ++) {
m_ContextMenu.GetMenuString(i, strItem, MF_BYPOSITION);
strItemNoAmp = strItem; strItemNoAmp.Remove('&');
strSection.Format("MENU-%s", strItemNoAmp);
GetPrivateProfileString(strSection, "Title", strItem, szItem, 256, strPath);
m_ContextMenu.ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, szItem);
CMenu* pSubMenu = m_ContextMenu.GetSubMenu(i);
if(!pSubMenu) continue;
for(is = 0; is < (int)pSubMenu->GetMenuItemCount(); is ++) {
pSubMenu->GetMenuString(is, strItem, MF_BYPOSITION);
if (UpdateLanguageString(strSection, strItem, strPath)) {
pSubMenu->ModifyMenu(is, MF_BYPOSITION|MF_STRING, pSubMenu->GetMenuItemID(is), strItem);
}
}
}
UpdateLanguageString("MENU-Project", m_MenuLabelGetPreferences, strPath);
UpdateLanguageString("MENU-Project", m_MenuLabelRetryNow, strPath);
UpdateLanguageString("MENU-Project2", m_MenuLabelGetWork, strPath);
UpdateLanguageString("MENU-Project2", m_MenuLabelNoMoreWork, strPath);
UpdateLanguageString("DIALOG-RESET", m_DialogResetQuery, strPath);
UpdateLanguageString("DIALOG-DETACH", m_DialogDetachQuery, strPath);
}
//////////
// CMainWindow::Syncronize
// arguments: pProg: pointer to a progress list control
// pVect: pointer to a vector of pointers
// returns: void
// function: first, goes through the vector and adds items to the list
// control for any pointers it does not already contain, then
// goes through the list control and removes any pointers the
// vector does not contain.
void CMainWindow::Syncronize(CProgressListCtrl* pProg, vector<void*>* pVect)
{
int i, j;
// add items to list that are not already in it
for(i = 0; i < (int)pVect->size(); i ++) {
void* item = (*pVect)[i];
BOOL contained = false;
for(j = 0; j < pProg->GetItemCount(); j ++) {
if((DWORD)item == pProg->GetItemData(j)) {
contained = true;
break;
}
}
if(!contained) {
pProg->InsertItem(i, "");
pProg->SetItemData(i, (DWORD)item);
}
}
// remove items from list that are not in vector
// now just set the pointer to NULL but leave the item in the list
for(i = 0; i < pProg->GetItemCount(); i ++) {
DWORD item = pProg->GetItemData(i);
BOOL contained = false;
for(j = 0; j < (int)pVect->size(); j ++) {
if(item == (DWORD)(*pVect)[j]) {
contained = true;
break;
}
}
if(!contained) {
pProg->SetItemData(i, (DWORD)NULL);
}
}
}
//////////
// CMainWindow::PostNcDestroy
// arguments: void
// returns: void
// function: takes care of window being destroyed
void CMainWindow::PostNcDestroy()
{
delete this;
}
//////////
// CMainWindow::OnClose
// arguments: void
// returns: void
// function: hides the window, keeps status icon
void CMainWindow::OnClose()
{
ShowWindow(SW_HIDE);
}
//////////
// CMainWindow::OnDestroy
// arguments: void
// returns: void
// function: quits the program
void CMainWindow::OnDestroy()
{
OnCommandExit();
}
//////////
// CMainWindow::OnCommandSettingsLogin
// arguments: void
// returns: void
// function: shows the account login dialog box
void CMainWindow::OnCommandSettingsLogin()
{
if(GetForegroundWindow() != this || !IsWindowVisible()) {
return;
}
CLoginDialog dlg(IDD_LOGIN, "", "");
int nResult = dlg.DoModal();
if(nResult == IDOK) {
gstate.add_project(
dlg.m_strUrl.GetBuffer(dlg.m_strUrl.GetLength()+10),
dlg.m_strAuth.GetBuffer(0));
dlg.m_strUrl.ReleaseBuffer(); // might have been changed by canonicalize_url()
}
}
//////////
// CMainWindow::OnCommandSettingsProxyServer
// arguments: void
// returns: void
// function: shows the proxy dialog box
void CMainWindow::OnCommandSettingsProxyServer()
{
CProxyServerDlg dlg;
int nResult = dlg.DoModal();
}
//////////
// CMainWindow::OnCommandHelpAbout
// arguments: void
// returns: void
// function: shows the about dialog box
void CMainWindow::OnCommandHelpAbout()
{
CAboutDialog dlg(IDD_ABOUTBOX);
int nResult = dlg.DoModal();
}
/*
//////////
// CMainWindow::OnCommandFileClearInactive
// arguments: void
// returns: void
// function: clears inactive items from lists
void CMainWindow::OnCommandFileClearInactive()
{
int i;
for(i = 0; i < m_ProjectListCtrl.GetItemCount();) {
if(!m_ProjectListCtrl.GetItemData(i)) {
m_ProjectListCtrl.DeleteItem(i);
} else {
i ++;
}
}
for(i = 0; i < m_ResultListCtrl.GetItemCount();) {
if(!m_ResultListCtrl.GetItemData(i)) {
m_ResultListCtrl.DeleteItem(i);
} else {
i ++;
}
}
for(i = 0; i < m_XferListCtrl.GetItemCount();) {
if(!m_XferListCtrl.GetItemData(i)) {
m_XferListCtrl.DeleteItem(i);
} else {
i ++;
}
}
}
//////////
// CMainWindow::OnCommandFileClearMessages
// arguments: void
// returns: void
// function: clears messages
void CMainWindow::OnCommandFileClearMessages()
{
m_MessageListCtrl.DeleteAllItems();
}
*/
//////////
// CMainWindow::GetProjectFromContextMenu
// arguments: void
// returns: PROJECT *
// function: returns the project associated with the most
// recently selected context menu item
PROJECT* CMainWindow::GetProjectFromContextMenu() {
if(m_nContextItem < 0 || m_nContextItem > m_ProjectListCtrl.GetItemCount()) return NULL;
PROJECT* proj = (PROJECT*)m_ProjectListCtrl.GetItemData(m_nContextItem);
m_nContextItem = -1;
return proj;
}
//////////
// CMainWindow::OnCommandProjectWebSite
// arguments: void
// returns: void
// function: lets the user quit a project
void CMainWindow::OnCommandProjectWebSite()
{
PROJECT *proj;
char url[263] = "";
proj = GetProjectFromContextMenu();
if (proj) {
if (strncmp(proj->master_url, "http://", 7) != 0) // ***WARNING*** ASSUMING LOWER-CASE URL
sprintf(url, "http://");
ShellExecute(GetSafeHwnd(), "open", strcat(url, proj->master_url), "", "", SW_SHOWNORMAL);
}
}
//////////
// CMainWindow::OnCommandProjectGetPrefs
// arguments: void
// returns: void
// function: reset rpc time to get prefences now
void CMainWindow::OnCommandProjectGetPrefs()
{
PROJECT *proj;
proj = GetProjectFromContextMenu();
if (proj) {
proj->sched_rpc_pending = true;
proj->min_rpc_time = 0;
}
}
//////////
// CMainWindow::OnCommandProjectDetach
// arguments: void
// returns: void
// function: lets the user quit a project
void CMainWindow::OnCommandProjectDetach()
{
PROJECT *proj;
proj = GetProjectFromContextMenu();
if (!proj) return;
CString strBuf = m_DialogDetachQuery;
strBuf.Replace("%1", proj->get_project_name());
if(AfxMessageBox(strBuf, MB_YESNO, 0) == IDYES) DetachProject(proj);
}
//////////
// CMainWindow::DetachProject
// arguments: void
// returns: void
// function: detaches from a project and clears its items
void CMainWindow::DetachProject(PROJECT *proj) {
ClearProjectItems(proj->master_url);
gstate.detach_project(proj);
}
//////////
// CMainWindow::OnCommandProjectReset
// arguments: void
// returns: void
// function: lets the user quit a project
void CMainWindow::OnCommandProjectReset()
{
PROJECT *proj;
proj = GetProjectFromContextMenu();
if (!proj) return;
CString strBuf = m_DialogResetQuery;
strBuf.Replace("%1", proj->get_project_name());
if(AfxMessageBox(strBuf, MB_YESNO, 0) == IDYES) {
gstate.reset_project(proj);
}
}
// CMainWindow::OnCommandProjectNoMoreWork
// arguments: void
// returns: void
// function: lets the user stop/start work fetches from project
void CMainWindow::OnCommandProjectNoMoreWork (){
PROJECT *proj;
proj = GetProjectFromContextMenu();
if (!proj) return;
if (proj->dont_request_more_work) {
proj->dont_request_more_work = false;
show_message(proj,"Allowing more work to be requested from project",MSG_INFO);
} else {
proj->dont_request_more_work = true;
show_message(proj,"Won't request any more work from project",MSG_INFO);
}
}
//////////
// CMainWindow::OnCommandWorkShowGraphics
// arguments: void
// returns: void
// function: brings up the graphics window for the selescted app
void CMainWindow::OnCommandWorkShowGraphics()
{
RESULT* resToShow = (RESULT*)m_ResultListCtrl.GetItemData(m_nContextItem);
if(resToShow) {
ACTIVE_TASK* at = gstate.lookup_active_task_by_result(resToShow);
if(at) {
GRAPHICS_MSG gm;
gm.mode = MODE_WINDOW;
at->request_graphics_mode(gm);
}
}
}
void CMainWindow::OnCommandTransfersRetryNow()
{
PERS_FILE_XFER* pfx = (PERS_FILE_XFER*)m_XferListCtrl.GetItemData(m_nContextItem);
if (pfx) {
pfx->next_request_time = 0;
}
}
//////////
// CMainWindow::OnCommandShow
// arguments: void
// returns: void
// function: shows the window
void CMainWindow::OnCommandShow()
{
CMenu* pMainMenu;
pMainMenu = GetMenu();
ShowWindow(SW_SHOW);
pMainMenu->GetSubMenu(0)->EnableMenuItem(ID_STATUSICON_HIDE, MF_ENABLED);
pMainMenu->GetSubMenu(0)->EnableMenuItem(ID_STATUSICON_SHOW, MF_GRAYED);
}
//////////
// CMainWindow::OnCommandHide
// arguments: void
// returns: void
// function: hides the window
void CMainWindow::OnCommandHide()
{
CMenu* pMainMenu;
pMainMenu = GetMenu();
ShowWindow(SW_HIDE);
pMainMenu->GetSubMenu(0)->EnableMenuItem(ID_STATUSICON_HIDE, MF_GRAYED);
pMainMenu->GetSubMenu(0)->EnableMenuItem(ID_STATUSICON_SHOW, MF_ENABLED);
}
void CMainWindow::UpdateRunRequestMenu(CMenu* pMenu)
{
if (!pMenu) return;
/*switch(gstate.user_run_request) {
case USER_RUN_REQUEST_ALWAYS:
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_ALWAYS, MF_GRAYED);
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_AUTO, MF_ENABLED);
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_NEVER, MF_ENABLED);
break;
case USER_RUN_REQUEST_AUTO:
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_ALWAYS, MF_ENABLED);
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_AUTO, MF_GRAYED);
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_NEVER, MF_ENABLED);
break;
case USER_RUN_REQUEST_NEVER:
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_ALWAYS, MF_ENABLED);
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_AUTO, MF_ENABLED);
pMenu->EnableMenuItem(ID_FILE_RUN_REQUEST_NEVER, MF_GRAYED);
break;
}*/
// NOTE:
// ID_FILE_RUN_REQUEST_ALWAYS, ID_FILE_RUN_REQUEST_AUTO, ID_FILE_RUN_REQUEST_NEVER
// and
// USER_RUN_REQUEST_ALWAYS, USER_RUN_REQUEST_AUTO, USER_RUN_REQUEST_NEVER
// must be #defined sequentially
pMenu->CheckMenuRadioItem(ID_FILE_RUN_REQUEST_ALWAYS, ID_FILE_RUN_REQUEST_NEVER,
ID_FILE_RUN_REQUEST_ALWAYS+gstate.user_run_request-USER_RUN_REQUEST_ALWAYS,
MF_BYCOMMAND);
}
void CMainWindow::UpdateRunRequestFileMenu()
{
UpdateRunRequestMenu(GetMenu()->GetSubMenu(0));
}
void CMainWindow::OnCommandRunRequestAlways()
{
gstate.user_run_request = USER_RUN_REQUEST_ALWAYS;
UpdateRunRequestFileMenu();
}
void CMainWindow::OnCommandRunRequestAuto()
{
gstate.user_run_request = USER_RUN_REQUEST_AUTO;
UpdateRunRequestFileMenu();
}
void CMainWindow::OnCommandRunRequestNever()
{
gstate.user_run_request = USER_RUN_REQUEST_NEVER;
UpdateRunRequestFileMenu();
}
void CMainWindow::OnFileDisableNetworkAccess()
{
CMenu* pMenu;
UINT uiState;
// Get the File menu
pMenu = GetMenu()->GetSubMenu( 0 );
uiState = pMenu->GetMenuState( ID_FILE_TOGGLE_NETWORK_ACCESS, MF_BYCOMMAND );
ASSERT(uiState != 0xFFFFFFFF);
if ( MF_CHECKED & uiState ) {
pMenu->CheckMenuItem( ID_FILE_TOGGLE_NETWORK_ACCESS, MF_UNCHECKED | MF_BYCOMMAND );
gstate.user_network_request = USER_RUN_REQUEST_ALWAYS;
} else {
pMenu->CheckMenuItem( ID_FILE_TOGGLE_NETWORK_ACCESS, MF_CHECKED | MF_BYCOMMAND );
gstate.user_network_request = USER_RUN_REQUEST_NEVER;
}
}
void CMainWindow::OnCommandRunBenchmarks()
{
gstate.start_cpu_benchmarks();
}
void CMainWindow::OnBenchmarksBegin()
{
CMenu* pMainMenu;
CMenu* pFileMenu;
pMainMenu = GetMenu();
if(pMainMenu) {
pFileMenu = pMainMenu->GetSubMenu(0);
}
if(pFileMenu) {
pFileMenu->EnableMenuItem(ID_FILE_RUN_BENCHMARKS, MF_GRAYED);
}
}
void CMainWindow::OnBenchmarksEnd()
{
CMenu* pMainMenu;
CMenu* pFileMenu;
pMainMenu = GetMenu();
if(pMainMenu) {
pFileMenu = pMainMenu->GetSubMenu(0);
}
if(pFileMenu) {
pFileMenu->EnableMenuItem(ID_FILE_RUN_BENCHMARKS, MF_ENABLED);
}
}
//////////
// CMainWindow::OnCommandExit
// arguments: void
// returns: void
// function: cleans up, closes and quits everything
void CMainWindow::OnCommandExit()
{
static bool already_exited = false;
TRACE(TEXT("CMainWindow::onCommandExit\n"));
if (already_exited) return;
already_exited = true;
gstate.quit_activities();
PostQuitMessage(0);
KillTimer(m_nGuiTimerID);
// status icon in taskbar
SetStatusIcon(ICON_OFF);
// clean up and delete objects
m_Font.DeleteObject();
m_TabBMP[0].DeleteObject();
m_TabBMP[1].DeleteObject();
m_TabBMP[2].DeleteObject();
m_TabBMP[3].DeleteObject();
m_TabBMP[4].DeleteObject();
m_TabIL.DeleteImageList();
m_MainMenu.DestroyMenu();
m_ContextMenu.DestroyMenu();
// free dll and idle detection
if(g_hIdleDetectionDll) {
typedef void (CALLBACK* TermFn)();
TermFn fn;
fn = (TermFn)GetProcAddress(g_hIdleDetectionDll, "IdleTrackerTerm");
if(!fn) {
show_message(NULL, "Error in DLL \"boinc.dll\"", MSG_INFO);
} else {
fn();
}
FreeLibrary(g_hIdleDetectionDll);
g_hIdleDetectionDll = NULL;
}
SaveUserSettings();
//SaveListControls();
// This was causing trouble in the installer because the SS window
// would recieve the WM_DESTROY message first, thereby causing
// this delete to access already freed memory
//delete m_pSSWnd;
CWnd::OnClose();
}
//////////
// CMainWindow::OnCommandMessageCopyToClip
// arguments: void
// returns: 0 if successful, otherwise -1
// function: copies the selected message(s) to the clipboard as
// formatted text
void CMainWindow::OnCommandMessageCopyToClip()
{
HGLOBAL hClipboardData;
POSITION pos;
char * pchData;
const int NUM_COLS = 3;
CString strData = "";
if (!OpenClipboard())
goto END_ONCOMMANDMESSAGECOPYTOCLIP;
EmptyClipboard();
/* Get strings from selected items:
- If GetFirstSelectedItem() returns null, the user
right-clicked a single item without selecting it first.
Use click location to determine the chosen item.
- Otherwise, iterate through the selected items.
*/
pos = m_MessageListCtrl.GetFirstSelectedItemPosition();
if (pos == NULL) {
if(m_nContextItem < 0 || m_nContextItem > m_MessageListCtrl.GetItemCount()) goto END_ONCOMMANDMESSAGECOPYTOCLIP;
// TODO: Allow arbitrary # of columns instead of hardcoding 3, if possible.
for (int i = 0; i < NUM_COLS-1; i++) {
strData += m_MessageListCtrl.GetItemTextOrPos(m_nContextItem, i);
strData += " - ";
}
// Add last column here to avoid concatenating an extra delimiter to the end.
// NOTE: Carriage-return/Newline combination is required to separate lines
// in the CF_TEXT clipboard format.
strData += m_MessageListCtrl.GetItemTextOrPos(m_nContextItem, i) + "\r\n";
} else {
while (pos) {
int nItem = m_MessageListCtrl.GetNextSelectedItem(pos);
for (int i = 0; i < NUM_COLS-1; i++) {
strData += m_MessageListCtrl.GetItemTextOrPos(nItem, i);
strData += " - ";
}
strData += m_MessageListCtrl.GetItemTextOrPos(nItem, i) + "\r\n";
}
}
// allocate a global memory block to hold the copied text
// (size is +1 to account for the null terminator).
hClipboardData = GlobalAlloc(GMEM_DDESHARE, strData.GetLength()+1);
pchData = (char*)GlobalLock(hClipboardData);
strcpy(pchData, LPCSTR(strData));
GlobalUnlock(hClipboardData);
SetClipboardData(CF_TEXT,hClipboardData);
CloseClipboard();
END_ONCOMMANDMESSAGECOPYTOCLIP:;
}
//////////
// CMainWindow::OnCreate
// arguments: lpcs: a pointer to the create structure
// returns: 0 if successful, otherwise -1
// function: sets window's global variable, loads resource, creates child
// windows, and initializes client state and timer
int CMainWindow::OnCreate(LPCREATESTRUCT lpcs)
{
char curDir[512];
char* szTitles[MAX_COLS];
int i;
if (CWnd::OnCreate(lpcs) == -1) {
return -1;
}
// Determine the OS version
UtilInitOSVersion();
g_myWnd = this;
m_nIconState = ICON_OFF;
m_bMessage = false;
m_bRequest = false;
m_nContextItem = -1;
// m_pSSWnd = new CSSWindow();
// load menus
m_ContextMenu.LoadMenu(IDR_CONTEXT);
m_MainMenu.LoadMenu(IDR_MAINFRAME);
SetMenu(&m_MainMenu);
LoadLanguage();
TRACE(TEXT("CMainWIndow:OnCreate\n"));
// create project list control
m_ProjectListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, PROJECT_ID);
m_ProjectListCtrl.SetExtendedStyle(m_ProjectListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT);
for (i = 0; i < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[PROJECT_ID][i];
m_ProjectListCtrl.SetMenuItems(szTitles, PROJECT_COLS);
for (i = 0; i < PROJECT_COLS; i ++) {
m_ProjectListCtrl.InsertColumn(i, g_szColumnTitles [PROJECT_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH, -1,g_nColSortTypes[PROJECT_ID][i]);
}
// create result list control
m_ResultListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, RESULT_ID);
m_ResultListCtrl.SetExtendedStyle(m_ResultListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT);
m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0);
for(i = 0; i < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[RESULT_ID][i];
m_ResultListCtrl.SetMenuItems(szTitles, RESULT_COLS);
for(i = 0; i < RESULT_COLS; i ++) {
m_ResultListCtrl.InsertColumn(i, g_szColumnTitles[RESULT_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH, -1,g_nColSortTypes[RESULT_ID][i]);
}
// create xfer list control
m_XferListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, XFER_ID);
m_XferListCtrl.SetExtendedStyle(m_XferListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT);
m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0);
for(i = 0; i < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[XFER_ID][i];
m_XferListCtrl.SetMenuItems(szTitles, XFER_COLS);
for(i = 0; i < XFER_COLS; i ++) {
m_XferListCtrl.InsertColumn(i, g_szColumnTitles[XFER_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH, -1,g_nColSortTypes[XFER_ID][i]);
}
// create message edit control
m_MessageListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, MESSAGE_ID);
m_MessageListCtrl.SetExtendedStyle(m_MessageListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT);
m_MessageListCtrl.ModifyStyle(WS_VISIBLE, 0);
for(i = 0; i < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[MESSAGE_ID][i];
m_MessageListCtrl.SetMenuItems(szTitles, MESSAGE_COLS);
for(i = 0; i < MESSAGE_COLS; i ++) {
int width = DEF_COL_WIDTH;
if(i == 1) width = (int)(width*1.5);
if(i == 2) width *= 4;
m_MessageListCtrl.InsertColumn(i, g_szColumnTitles[MESSAGE_ID][i], LVCFMT_LEFT, width, -1,g_nColSortTypes[MESSAGE_ID][i]);
}
// create usage pie control
m_UsagePieCtrl.Create(WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, USAGE_ID);
m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0);
m_UsagePieCtrl.AddPiece(g_szUsageItems[0], RGB(255, 0, 255), 0);
m_UsagePieCtrl.AddPiece(g_szUsageItems[1], RGB(192, 64, 192), 0);
m_UsagePieCtrl.AddPiece(g_szUsageItems[2], RGB(0, 0, 255), 0);
m_UsagePieCtrl.AddPiece(g_szUsageItems[3], RGB(0, 200, 0), 0);
m_UsageBOINCPieCtrl.Create(WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, USAGE_ID);
m_UsageBOINCPieCtrl.ModifyStyle(WS_VISIBLE, 0);
m_UsageBOINCPieCtrl.AddPiece(g_szUsageItems[4], GetPieColor(0), 0);
m_UsageBOINCPieCtrl.AddPiece(g_szUsageItems[5], RGB(0, 200, 0), 0);
// set up image list for tab control
m_TabIL.Create(16, 16, ILC_COLOR8|ILC_MASK, MAX_TABS, 1);
m_TabBMP[0].LoadBitmap(IDB_PROJ);
m_TabIL.Add(&m_TabBMP[0], RGB(255, 0, 255));
m_TabBMP[1].LoadBitmap(IDB_RESULT);
m_TabIL.Add(&m_TabBMP[1], RGB(255, 0, 255));
m_TabBMP[2].LoadBitmap(IDB_XFER);
m_TabIL.Add(&m_TabBMP[2], RGB(255, 0, 255));
m_TabBMP[3].LoadBitmap(IDB_MESS);
m_TabIL.Add(&m_TabBMP[3], RGB(255, 0, 255));
m_TabBMP[4].LoadBitmap(IDB_USAGE);
m_TabIL.Add(&m_TabBMP[4], RGB(255, 0, 255));
// create tab control
//m_TabCtrl.Create(TCS_FIXEDWIDTH|TCS_BUTTONS|TCS_FLATBUTTONS|TCS_FOCUSNEVER|WS_CHILD|WS_VISIBLE, CRect(0,0,0,0), this, TAB_ID);
m_TabCtrl.Create(TCS_FIXEDWIDTH|TCS_FOCUSNEVER|WS_CHILD|WS_VISIBLE, CRect(0,0,0,0), this, TAB_ID);
m_TabCtrl.SetImageList(&m_TabIL);
m_TabCtrl.InsertItem(1, g_szTabItems[0], 0);
m_TabCtrl.InsertItem(2, g_szTabItems[1], 1);
m_TabCtrl.InsertItem(3, g_szTabItems[2], 2);
m_TabCtrl.InsertItem(4, g_szTabItems[3], 3);
m_TabCtrl.InsertItem(5, g_szTabItems[4], 4);
// make all fonts the same nice font
CFont* pFont;
pFont = m_ProjectListCtrl.GetFont();
LOGFONT lf;
ZeroMemory(&lf, sizeof(LOGFONT));
pFont->GetLogFont(&lf);
m_Font.CreateFontIndirect(&lf);
m_TabCtrl.SetFont(&m_Font);
m_UsagePieCtrl.SetFont(&m_Font);
m_UsageBOINCPieCtrl.SetFont(&m_Font);
// Set the current directory to the default
UtilGetRegStr("ClientDir", curDir);
if (strlen(curDir))
SetCurrentDirectory(curDir);
// add status icon to taskbar
SetStatusIcon(ICON_NORMAL);
// take care of other things
//
// Check what (if any) activities should be logged
read_log_flags();
LoadUserSettings();
//LoadListControls();
int retval = gstate.init();
if (retval) {
OnCommandExit();
return 0;
}
LPSTR command_line;
char* argv[100];
int argc;
command_line = GetCommandLine();
argc = parse_command_line( command_line, argv );
gstate.parse_cmdline(argc, argv);
m_nGuiTimerID = SetTimer(GUI_TIMER, GUI_WAIT, (TIMERPROC) NULL);
// load dll and start idle detection
g_hIdleDetectionDll = LoadLibrary("boinc.dll");
if(!g_hIdleDetectionDll) {
show_message(NULL,"Can't load \"boinc.dll\", will not be able to determine idle time", MSG_ERROR);
} else {
typedef BOOL (CALLBACK* InitFn)();
InitFn fn;
fn = (InitFn)GetProcAddress(g_hIdleDetectionDll, "IdleTrackerInit");
if(!fn) {
show_message(NULL,"Error in DLL \"boinc.dll\", will not be able to determine idle time", MSG_INFO);
FreeLibrary(g_hIdleDetectionDll);
g_hIdleDetectionDll = NULL;
} else {
if(!fn()) {
show_message(NULL,"Error in DLL \"boinc.dll\", will not be able to determine idle time", MSG_INFO);
FreeLibrary(g_hIdleDetectionDll);
g_hIdleDetectionDll = NULL;
}
}
}
UpdateGUI(&gstate);
// see if we need to add this to startup
if(gstate.global_prefs.run_on_startup) {
UtilGetRegStr("ClientPath", curDir);
if(strlen(curDir)) {
strcat(curDir, " -min");
UtilSetRegStartupStr("boincclient", curDir);
}
} else {
UtilSetRegStartupStr("boincclient", "");
}
// see if we need to hide the window
if(gstate.global_prefs.run_minimized || gstate.started_by_screensaver) {
ShowWindow(SW_HIDE);
} else {
ShowWindow(SW_SHOW);
}
UpdateRunRequestFileMenu();
TRACE(TEXT("returning from OnCreate\n"));
return 0;
}
//////////
// CMainWindow::OnNotify
// arguments: wParam: notification's wparam
// lParam: notification's lparam
// pResult: pointer to result of notification
// returns: true if the notification is processed, otherwise false
// function: handles notifications from children, including:
// user selecting a new tab sets display to selected tab's control
BOOL CMainWindow::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
HD_NOTIFY* phdn = (HD_NOTIFY*)lParam;
// notification from tab control, user is changing the selection
if(phdn->hdr.code == TCN_SELCHANGE) {
int newTab = m_TabCtrl.GetCurSel();
ShowTab(newTab);
}
return CWnd::OnNotify(wParam, lParam, pResult);
}
//////////
// CMainWindow::OnRButtonDown
// arguments: nFlags: message flags (keys down)
// point: mouse's point
// returns: void
// function: shows context menu for list items
void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu* pContextMenu = NULL;
CRect rt;
CListCtrl* pMenuCtrl = NULL;
int nMenuId = -1;
GetCursorPos(&point);
int currentSelection = m_TabCtrl.GetCurSel();
if(currentSelection == PROJECT_ID) {
pMenuCtrl = &m_ProjectListCtrl;
nMenuId = PROJECT_MENU;
} else if(currentSelection == RESULT_ID) {
pMenuCtrl = &m_ResultListCtrl;
nMenuId = RESULT_MENU;
} else if(currentSelection == XFER_ID) {
pMenuCtrl = &m_XferListCtrl;
nMenuId = XFER_MENU;
} else if(currentSelection == MESSAGE_ID) {
pMenuCtrl = &m_MessageListCtrl;
nMenuId = MESSAGE_MENU;
}
if(pMenuCtrl) {
pMenuCtrl->SetFocus();
// clear all other items - this must be done first
int indexSelected = -1;
for(int i = 0; i < pMenuCtrl->GetItemCount(); i ++) {
pMenuCtrl->GetItemRect(i, &rt, LVIR_BOUNDS);
pMenuCtrl->ClientToScreen(&rt);
if(rt.PtInRect(point)) {
indexSelected = i;
break;
}
}
if (indexSelected == -1)
return;
bool shouldSetNewSelection = nMenuId != MESSAGE_MENU ||
!pMenuCtrl->GetItemState(indexSelected, LVIS_SELECTED);
if(shouldSetNewSelection) {
for(int i = 0; i < pMenuCtrl->GetItemCount(); i ++) {
pMenuCtrl->SetItemState(i, 0, LVIS_SELECTED);
}
pMenuCtrl->SetItemState(indexSelected, LVIS_SELECTED, LVIS_SELECTED);
}
pContextMenu = m_ContextMenu.GetSubMenu(nMenuId);
if(pContextMenu) {
switch(nMenuId) {
case PROJECT_MENU:
{
// if we are backing off, show "retry now", else "get preferences"
PROJECT *proj = (PROJECT *)pMenuCtrl->GetItemData(indexSelected);
pContextMenu->ModifyMenu(ID_PROJECT_GET_PREFS, 0, ID_PROJECT_GET_PREFS,
((proj && proj->min_rpc_time > dtime()) ?
m_MenuLabelRetryNow : m_MenuLabelGetPreferences));
pContextMenu->ModifyMenu(ID_PROJECT_NOMOREWORK, 0, ID_PROJECT_NOMOREWORK,
(proj->dont_request_more_work?m_MenuLabelGetWork:m_MenuLabelNoMoreWork));
break;
}
case RESULT_MENU:
{
pContextMenu->EnableMenuItem(ID_WORK_SHOWGRAPHICS,MF_GRAYED); //disable
RESULT *rp = (RESULT *)pMenuCtrl->GetItemData(indexSelected);
if (rp) {
ACTIVE_TASK *atp = gstate.lookup_active_task_by_result(rp);
if (atp && atp->supports_graphics())
pContextMenu->EnableMenuItem(ID_WORK_SHOWGRAPHICS,MF_ENABLED); // enable
}
break;
}
case XFER_MENU:
{
// enable "retry now" only if currently waiting to retry
PERS_FILE_XFER* pfx = (PERS_FILE_XFER*)m_XferListCtrl.GetItemData(indexSelected);
pContextMenu->EnableMenuItem(ID_TRANSFERS_RETRYNOW,
pfx && (pfx->next_request_time > dtime() ?
MF_ENABLED : MF_GRAYED));
break;
}
}
pContextMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this);
m_nContextItem = indexSelected;
}
}
//CWnd::OnRButtonDown(nFlags, point);
}
//////////
// CMainWindow::OnFocus
// arguments: pOldWnd: pointer to previous window that had focus
// returns: void
// function: if there is a message for the user when this window
// gets the focus, selects the message tab
void CMainWindow::OnSetFocus(CWnd* pOldWnd)
{
if(m_TabCtrl.GetSafeHwnd() && m_bMessage && (pOldWnd == NULL)) {
ShowTab(MESSAGE_ID);
m_bMessage = false;
SetStatusIcon(ICON_NORMAL);
}
// TODO: review this
if(m_bRequest) {
m_bRequest = false;
// if(RequestNetConnect()) OnCommandConnectionConnectNow();
}
UpdateGUI(&gstate);
}
//////////
// CMainWindow::OnSize
// arguments: nType: type of resizing
// cx: new width of window
// cy: new height of window
// returns: void
// function: calculates new rectangles for child windows and resizes
// them appropriately
void CMainWindow::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// calculate the main rect for the tab control
RECT rt = {EDGE_BUFFER, TOP_BUFFER, cx-EDGE_BUFFER, cy-EDGE_BUFFER*2};
RECT irt = {0, 0, 0, 0};
if(m_TabCtrl.GetSafeHwnd()) {
m_TabCtrl.MoveWindow(&rt, false);
m_TabCtrl.GetItemRect(0, &irt);
// calculate the rects for other controls inside the tab control
RECT srt = {rt.left+EDGE_BUFFER, irt.bottom+EDGE_BUFFER*2+TOP_BUFFER, rt.right-EDGE_BUFFER, rt.bottom-EDGE_BUFFER};
if(m_ProjectListCtrl.GetSafeHwnd()) {
m_ProjectListCtrl.MoveWindow(&srt, false);
m_ProjectListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
}
if(m_ResultListCtrl.GetSafeHwnd()) {
m_ResultListCtrl.MoveWindow(&srt, false);
m_ResultListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
}
if(m_XferListCtrl.GetSafeHwnd()) {
m_XferListCtrl.MoveWindow(&srt, false);
m_XferListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
}
if(m_MessageListCtrl.GetSafeHwnd()) {
m_MessageListCtrl.MoveWindow(&srt, false);
m_MessageListCtrl.Scroll(CSize(0, m_MessageListCtrl.ApproximateViewRect().cy));
m_MessageListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
}
if(m_UsagePieCtrl.GetSafeHwnd()) {
RECT mrt = {rt.left+EDGE_BUFFER, irt.bottom+EDGE_BUFFER*2+TOP_BUFFER, rt.right/2, rt.bottom-EDGE_BUFFER};
m_UsagePieCtrl.MoveWindow(&mrt, false);
m_UsagePieCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME);
}
if(m_UsageBOINCPieCtrl.GetSafeHwnd()) {
RECT brt = {rt.right/2-1, irt.bottom+EDGE_BUFFER*2+TOP_BUFFER, rt.right-EDGE_BUFFER, rt.bottom-EDGE_BUFFER};
m_UsageBOINCPieCtrl.MoveWindow(&brt, false);
m_UsageBOINCPieCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME);
}
m_TabCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME);
RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
}
}
//////////
// CMainWindow::OnStatusIcon
// arguments: wParam: id of icon clicked
// lParam: message from icon
// returns: true if the menu is shown, false otherwise
// function: handles messages from status icon, including:
// right click: shows popup menu
// double click: alternates visibility of window
LRESULT CMainWindow::OnStatusIcon(WPARAM wParam, LPARAM lParam)
{
if(lParam == WM_RBUTTONDOWN) {
CPoint point;
SetForegroundWindow();
GetCursorPos(&point);
CMenu* pSubmenu;
pSubmenu = m_ContextMenu.GetSubMenu(STATUS_MENU);
UpdateRunRequestMenu(pSubmenu);
if (IsWindowVisible()) {
pSubmenu->EnableMenuItem(ID_STATUSICON_SHOW, MF_GRAYED);
pSubmenu->EnableMenuItem(ID_STATUSICON_HIDE, MF_ENABLED);
} else {
pSubmenu->EnableMenuItem(ID_STATUSICON_SHOW, MF_ENABLED);
pSubmenu->EnableMenuItem(ID_STATUSICON_HIDE, MF_GRAYED);
}
pSubmenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this);
} else if(lParam == WM_LBUTTONDOWN) {
if(IsWindowVisible()) {
SetForegroundWindow();
}
} else if(lParam == WM_LBUTTONDBLCLK) {
if (IsIconic()) {
ShowWindow(SW_RESTORE);
} else if(IsWindowVisible()) {
ShowWindow(SW_HIDE);
} else {
ShowWindow(SW_SHOWNORMAL);
}
}
return TRUE;
}
//////////
// CMainWindow::OnTimer
// arguments: uEventID: timer's id
// returns: void
// function: updates client state, flushed output streams,
// and updates gui display.
void CMainWindow::OnTimer(UINT uEventID) {
static int counter = 0;
if(uEventID == m_nGuiTimerID) {
counter++;
// stop the timer while we do processing
KillTimer(m_nGuiTimerID);
// update state and gui
while(gstate.do_something(dtime()));
// check if network connection can be terminated
NetCheck(gstate.global_prefs.hangup_if_dialed);
UpdateGUI(&gstate);
// Start the timer again
m_nGuiTimerID = SetTimer(GUI_TIMER, GUI_WAIT, (TIMERPROC) NULL);
}
}
//////////
// CMainWindow::OnShowWindow
// function:
// arguments:
// returns:
LRESULT CMainWindow::OnShowWindow(WPARAM wParam, LPARAM lParam)
{
ShowWindow(SW_SHOW);
SetForegroundWindow();
return TRUE;
}
//////////
// CMainWindow::OnNetworkActivity
// function:
// arguments:
// returns:
LRESULT CMainWindow::OnNetworkActivity(WPARAM wParam, LPARAM lParam)
{
gstate.net_sleep(0);
return TRUE;
}
//////////
// CMainWindow::OnStartScreensaver
// function:
// arguments:
// returns:
LRESULT CMainWindow::OnStartScreensaver(WPARAM wParam, LPARAM lParam)
{
// Get the current screen blanking information
unsigned long reg_time_until_blank = 0, reg_blank_screen = 0;
unsigned long blank_time = 0;
UtilGetRegKey(REG_BLANK_NAME, reg_blank_screen);
UtilGetRegKey(REG_BLANK_TIME, reg_time_until_blank);
if (reg_blank_screen) {
if (reg_time_until_blank>0) {
blank_time = time(0) + reg_time_until_blank*60;
} else {
blank_time = time(0) + 1200; // After twenty mintues,
// blank the screen
}
} else {
blank_time = 0;
}
//gstate.ss_logic.start_ss( "", "", blank_time );
return TRUE;
}
//////////
// CMainWindow::OnEndScreensaver
// function:
// arguments:
// returns:
LRESULT CMainWindow::OnEndScreensaver(WPARAM wParam, LPARAM lParam)
{
//gstate.ss_logic.stop_ss();
return TRUE;
}
//////////
// CMainWindow::OnTaskbarCreated
// function:
// arguments:
// returns:
LRESULT CMainWindow::OnTaskbarCreated(WPARAM wParam, LPARAM lParam)
{
// Explorer has crashed, we need to re-register our icon with the shell
DWORD dwTempIconStatus;
dwTempIconStatus = m_nIconState;
m_nIconState = ICON_OFF;
SetStatusIcon(dwTempIconStatus);
return TRUE;
}
//////////
// CMainWindow::OnSystemLogoff
// function:
// arguments:
// returns:
LRESULT CMainWindow::OnSystemLogoff(WPARAM wParam, LPARAM lParam)
{
// The system has notified us that the user is logging off or the
// system is shutting down, so lets go ahead and shut ourselves
// down.
return PostMessage(WM_COMMAND, ID_STATUSICON_EXIT, NULL);
}
void create_curtain() {
// g_myWnd->m_pSSWnd->ShowSSWindow(true);
}
void delete_curtain() {
// g_myWnd->m_pSSWnd->ShowSSWindow(false);
}
void project_add_failed(PROJECT* project) {
char buf[512];
if (project->scheduler_urls.size()) {
sprintf( buf,
"BOINC failed to log in to %s.\n"
"Please check your account ID and try again.",
project->master_url
);
} else {
sprintf( buf,
"BOINC couldn't get main page for %s.\n"
"Please check the URL and try again.",
project->master_url
);
}
AfxMessageBox(buf);
g_myWnd->DetachProject(project);
// TODO: To be filled in
}
const char *BOINC_RCSID_3eaaa7525d = "$Id$";