boinctui-2.3.4/src/ 0000755 0000000 0000000 00000000000 12301564455 012626 5 ustar root root boinctui-2.3.4/src/cfgform.h 0000644 0000000 0000000 00000003066 12301564455 014427 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef CFGFORM_H
#define CFGFORM_H
#include
#include
#include "nform.h"
#include "cfg.h"
#include "nstatictext.h"
class CfgForm : public NForm
{
public:
CfgForm(int lines, int rows/*, Config* cfg*/);
void genfields(bool extfields); //создаст массив полей (extfields если нужно добавить хост)
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
void updatecfg(); //сохраняет данные из формы в cfg
//Config* cfg;
bool extfields; //true если поле для доп хоста видимо
int nhost; //макс номер хоста с 0го (включаа дополнительный если есть)
};
#endif //CFGFORM_H boinctui-2.3.4/src/nwin.h 0000644 0000000 0000000 00000001522 12301564455 013752 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NWIN_H
#define NWIN_H
#endif //NWIN_H boinctui-2.3.4/src/addprojectform.h 0000644 0000000 0000000 00000003154 12301564455 016005 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef ADDPROJECTFORM_H
#define ADDPROJECTFORM_H
#include
#include
#include "nform.h"
#include "nstatictext.h"
#include "srvdata.h"
class AddProjectForm : public NForm
{
public:
AddProjectForm(int lines, int rows, Srv* srv, const char* projname, bool userexist);
void genfields(int& line, Item* project); //создаст массив полей
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
int emailfield;
int passwfield;
int errmsgfield;
int usernamefield;
int teamfield;
Srv* srv;
std::string projname; //имя подключаемого проекта
std::string projurl; //url подключаемого проекта
bool userexist; //true если юзер уже создан
};
#endif //ADDPROJECTFORM_H boinctui-2.3.4/src/cfg.cpp 0000644 0000000 0000000 00000010717 12301564455 014077 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include
#include "cfg.h"
#include "resultparse.h"
#include "kclog.h"
Config* gCfg;
Config::Config(const char* filename)
{
root = NULL;
//полный путь к конфигу
if (filename == NULL)
fullname = NULL;
else
{
//хоум каталог
const char* homepath = getenv("HOME");
//полный путь
fullname = (char*)malloc(strlen(homepath)+strlen(filename)+2);
sprintf(fullname,"%s/%s",homepath,filename);
kLogPrintf("FULLCFGPATH=%s\n",fullname); fflush(stdout);
}
//загружаем если файл уже есть или генерируем дефолтный
load();
asciilinedraw = getivalue("line_draw_mode");
}
Config::~Config()
{
save();
if (root != NULL)
delete root;
if (fullname == NULL)
free(fullname);
}
void Config::load()
{
isdefault = true;
if (fullname == NULL)
{
generatedefault();
return;
}
struct stat st;
int retcode = lstat(fullname, &st);
if (retcode != 0) //файла нет?
{
//делаем дефолтный
generatedefault();
return;
}
//читаем файл
FILE* pfile;
pfile = fopen(fullname,"r");
if (pfile!=NULL)
{
kLogPrintf("SIZE=%ld\n",st.st_size);
char* buf = (char*)malloc(st.st_size + 1);
size_t n = fread (buf,1,st.st_size,pfile);
buf[n]=0;
kLogPrintf("%s\n",buf);
root = xmlparse(buf, st.st_size);
fclose (pfile);
isdefault = false;
}
}
void Config::save()
{
if (fullname == NULL)
return;
if (root == NULL)
return;
kLogPrintf("Save Config to FULLCFGPATH=%s\n",fullname);
Item* cfg = root->findItem("boinctui_cfg");
if (cfg == NULL)
return;
std::string configxml = cfg->toxmlstring();
kLogPrintf("\n%s\n",cfg->toxmlstring().c_str());
FILE* pfile = fopen(fullname,"w");
if (pfile!=NULL)
{
fwrite(cfg->toxmlstring().c_str(),1, strlen(cfg->toxmlstring().c_str()),pfile);
fclose (pfile);
}
}
void Config::addhost(const char* shost, const char* sport, const char* spwd)
{
if ( (strlen(shost) == 0)||(strlen(sport) == 0) )
return; //пустые не заносим
Item* boinctui_cfg = getcfgptr();
if (boinctui_cfg == NULL)
return;
Item* srv = new Item("server");
Item* host = new Item("host");
host->appendvalue(shost);
srv->addsubitem(host);
Item* port = new Item("port");
port->appendvalue(sport);
srv->addsubitem(port);
if (strlen(spwd) > 0)
{
Item* pwd = new Item("pwd");
pwd->appendvalue(spwd);
srv->addsubitem(pwd);
}
boinctui_cfg->addsubitem(srv);
}
void Config::generatedefault()
{
kLogPrintf("generatedafault()\n");
root = new Item(""); //корневой
Item* cfg = new Item("boinctui_cfg");
root->addsubitem(cfg);
addhost("127.0.0.1","31416","");
}
int Config::getivalue(Item* node, const char* name) //ищет name начиная с node
{
int result = 0;
if (node != NULL)
{
Item* item = node->findItem(name);
if (item != NULL)
result = item->getivalue();
}
return result;
}
void Config::setivalue(Item* node, const char* name, int value) //создаст в node подэл-т name со значением value
{
Item* basenode = node;
if (basenode == NULL)
basenode = root; //если узел не указан используем корневой
if (basenode == NULL)
return; //ничего не делаем
Item* item = basenode->findItem(name);
//эл-та нет - нужно создать
if (item == NULL)
{
item = new Item(name);
basenode->addsubitem(item);
}
//устнавливаем значение
item->setivalue(value);
}
boinctui-2.3.4/src/nscrollview.h 0000644 0000000 0000000 00000005410 12301564455 015346 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NSCROLLVIEW_H
#define NSCROLLVIEW_H
#include
#include "nview.h"
#include "ncolorstring.h"
#include "nscrollbar.h"
class NScrollView : public NView //область со скроллингом
{
public:
NScrollView(NRect rect, NScrollBar* scrollbar = NULL) : NView(rect) { this->scrollbar=scrollbar; startindex = 0; autoscroll = false; needrefresh = true;};
virtual ~NScrollView();
void addstring(int attr, const char* fmt, ...);
void addstring(NColorString* s) { content.push_back(s); needrefresh = true; }; //добавляет строку
void eventhandle(NEvent* ev); //обработчик событий
void clearcontent(); //очищает строковый буфер
virtual void drawcontent(); //отрисовывает буфер строк
void scrollto(int delta); //сдвинуть отображение на drlta строк вверх или вниз
void setstartindex(int n); //установить отображение со строки n
int getstartindex() { return startindex; }; //получить номер первой видимой строки
bool getautoscroll() { return autoscroll; }; //true если включен режим автоскроллинга
void setautoscroll(bool b); //true чтобы включить автоскроллинг
void setscrollbar(NScrollBar* scrollbar) { this->scrollbar = scrollbar; };
virtual void resize(int rows, int cols);
virtual void refresh();
int getstringcount() { return content.size();}; //число строк
protected:
std::vector content; //массив строк с цветовыми аттрибутами
int startindex; //номер первой видимой строки
bool autoscroll; //если true то будет прокручивать автоматом до конца
NScrollBar* scrollbar; //скроллбар для этого эл-та (NULL если нет)
};
#endif //NSCROLLVIEW_H boinctui-2.3.4/src/nhline.cpp 0000644 0000000 0000000 00000002050 12301564455 014604 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "nhline.h"
void NHLine::refresh()
{
wbkgd(win,bgcolor);
wattrset(win,getcolorpair(COLOR_WHITE,COLOR_BLACK));
if ( asciilinedraw == 1)
whline(win, '-', getwidth()-0);
else
whline(win, ACS_HLINE, getwidth()-0);
NView::refresh();
}; boinctui-2.3.4/src/topmenu.cpp 0000644 0000000 0000000 00000076717 12301564455 015043 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "topmenu.h"
#include "tuievent.h"
#include "kclog.h"
//Названия пунктов верхнего меню
#define M_FILE "File"
#define M_VIEW "View"
#define M_PROJECTS "Projects"
#define M_TASKS "Tasks"
#define M_ACTIVITY "Activity"
#define M_HELP "Help"
//Названия пунктов меню "File"
#define M_NEXT_HOST "Next BOINC host"
#define M_CONFIG_HOSTS "Configure host list"
#define M_RUN_BENCHMARKS "Run CPU benchmarks"
#define M_QUIT "Quit boinctui"
//Названия пунктов меню "View"
#define M_VIEW_NUMBER "Task number column"
#define M_VIEW_STATE "Task state column"
#define M_VIEW_DONE "Percent done column"
#define M_VIEW_PROJECT "Project name column"
#define M_VIEW_ESTIMATE "Estimate time column"
#define M_VIEW_DEADLINE "Deadline time column"
#define M_VIEW_APPNAME "Application name column"
#define M_VIEW_TASKNAME "Task name column"
#define M_ALL_TASKS "All tasks"
#define M_HIDE_DONE "Hide done tasks"
#define M_ACTIVE_ONLY "Active tasks only"
#define M_UNSORTED "Unsorted tasks list"
#define M_SORT_BY_STATE "Sort by state"
#define M_SORT_BY_DONE "Sort by done %"
#define M_SORT_BY_PROJECT "Sort by project name"
#define M_SORT_BY_ESTIMATE "Sort by estimate time"
#define M_SORT_BY_DL "Sort by deadline"
#define M_SORT_BY_APP "Sort by application"
#define M_SORT_BY_TASK "Sort by task name"
#define M_ASCII_LINE_DRAW "ASCII line draw"
//Названия пунктов меню "Projects"
#define M_ADD_PROJECT "Add project"
#define M_CONNECT_MANAGER "Connect to account manager"
#define M_SYNCHRONIZE_MANAGER "Synchronize with manager"
#define M_DISCONNECT_MANAGER "Stop using account manager"
//Названия пунктов подменю "Projects/Имя проекта"
#define M_UPDATE_PROJECT "Update project"
#define M_SUSPEND_PROJECT "Suspend project"
#define M_RESUME_PROJECT "Resume project"
#define M_NO_NEW_TASKS_PROJECT "No new tasks"
#define M_ALLOW_NEW_TASKS_PROJECT "Allow new tasks"
#define M_RESET_PROJECT "Reset project"
#define M_DETACH_PROJECT "Detach project"
//Названия пунктов меню "Add project/User Exist"
#define M_PROJECT_USER_EXIST "Existing user"
#define M_PROJECT_NEW_USER "Create new user account"
//Названия пунктов меню "Tasks"
#define M_SUSPEND_TASK "Suspend task"
#define M_RESUME_TASK "Resume task"
#define M_ABORT_TASK "Abort task"
#define M_INFO_TASK "View raw task info"
//Названия пунктов меню "Activity"
#define M_ACTIVITY_ALWAYS "Run always"
#define M_ACTIVITY_AUTO "Run based on preferences"
#define M_ACTIVITY_NEVER "Suspend"
#define M_GPU_ACTIVITY_ALWAYS "GPU run always"
#define M_GPU_ACTIVITY_AUTO "GPU run based on preferences"
#define M_GPU_ACTIVITY_NEVER "GPU suspend"
#define M_NET_ACTIVITY_ALWAYS "Network activity always available"
#define M_NET_ACTIVITY_AUTO "Network activity based on preferences"
#define M_NET_ACTIVITY_NEVER "Network activity suspend"
//Названия пунктов меню "Help"
#define M_ABOUT "About"
#define M_KEY_BINDINGS "Hot keys list"
TopMenu::TopMenu(/*Config* cfg*/) : NMenu(NRect(1,getmaxx(stdscr),0,0),true)
{
setserver(NULL);
//this->cfg = cfg;
additem(M_FILE,"");
additem(M_VIEW,"");
additem(M_PROJECTS,"");
additem(M_TASKS,"");
additem(M_ACTIVITY,"");
additem(M_HELP,"");
additem(NULL,NULL);
setbackground(getcolorpair(COLOR_WHITE,COLOR_GREEN)|A_BOLD);
enableflag = true;
disable();
}
bool TopMenu::action() //открыть субменю
{
bool result = false;
if (!items.empty()) //если уже открыто выходим
return false;
//создаем подменю
int begincol = (menu->itemlen+menu->spc_cols)*item_index(current_item(menu)) + menu->spc_cols; //смещение на экране по горизонтали
if ( strcmp(item_name(current_item(menu)),M_FILE) == 0 )
{
insert(new FileSubMenu(NRect(5,25,1, begincol)));
result = true;
}
if ( strcmp(item_name(current_item(menu)),M_VIEW) == 0 )
{
insert(new ViewSubMenu(NRect(5,25,1, begincol)/*, cfg*/));
result = true;
}
if ( strcmp(menu->curitem->name.str,M_PROJECTS) == 0 )
{
insert(new ProjectsSubMenu(NRect(5,25,1, begincol), srv));
result = true;
}
if ( strcmp(item_name(current_item(menu)),M_TASKS) == 0 )
{
insert(new TasksSubMenu(NRect(5,25,1, begincol)));
result = true;
}
if ( strcmp(item_name(current_item(menu)),M_ACTIVITY) == 0 )
{
insert(new ActivitySubMenu(NRect(5,25,1, begincol), srv));
result = true;
}
if ( strcmp(item_name(current_item(menu)),M_HELP) == 0 )
{
insert(new HelpSubMenu(NRect(5,25,1, begincol)));
result = true;
}
return result;
}
void TopMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( !isenable() /*&& ( ev->type != NEvent::evMOUSE)*/ )
{
if ( ev->type == NEvent::evMOUSE)
{
NMouseEvent* mevent = (NMouseEvent*)ev;
if ((mevent->cmdcode & BUTTON1_CLICKED) && (isinside(mevent->row, mevent->col)))
enable(); //влючить по клику
}
else
return; //не обрабатывать клавиатурные если меню не активно
}
if ( ev->done )
return; //не обрабатывать если уже обработано кем-то ранее
//отправляем событие всем подменю
NMenu::eventhandle(ev); //предок
if ( ev->done )
return; //выход если какое-то подменю отработало событие
//пытаемся обработать самостоятельно
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_ENTER:
case '\n':
if (!createsubmenu())
ev->done = false; //пусть обрабатывает владелец
break;
case KEY_UP: //открыть подменю по стрелкевверх
case KEY_DOWN: //открыть подменю по стрелкевниз
action();
break;
case 27:
if ( !items.empty() )
destroysubmenu();
else
ev->done = false; //пусть обрабатывает владелец
break;
case KEY_RIGHT:
menu_driver(menu, REQ_RIGHT_ITEM);
if ( !items.empty() ) //подменю открыто
{
destroysubmenu(); //закрыть старое
action(); //открыть новое
}
break;
case KEY_LEFT:
menu_driver(menu, REQ_LEFT_ITEM);
if ( !items.empty() ) //подменю открыто
{
destroysubmenu(); //закрыть старое
action(); //открыть новое
}
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
}
//если клик мыши до сих пор не обработан
//значит он за пределами меню и меню нужно гасить
if ( ev->type == NEvent::evMOUSE)
{
NMouseEvent* mevent = (NMouseEvent*)ev;
if ((mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED)) && (!ev->done))
disable(); //выключить по клику вне меню
}
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
//=============================================================================================
FileSubMenu::FileSubMenu(NRect rect) : NMenu(rect)
{
additem(M_NEXT_HOST," N");
additem(M_CONFIG_HOSTS," C");
additem(M_RUN_BENCHMARKS,"");
additem(M_QUIT," Q");
additem(NULL,NULL);
}
bool FileSubMenu::action()
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть осн меню
if ( strcmp(item_name(current_item(menu)),M_NEXT_HOST) == 0 )
putevent(new NEvent(NEvent::evKB, 'N')); //создаем событие иммитирующее нажатие 'N'
if ( strcmp(item_name(current_item(menu)),M_CONFIG_HOSTS) == 0 )
putevent(new NEvent(NEvent::evKB, 'C')); //создаем событие иммитирующее нажатие 'C'
if ( strcmp(item_name(current_item(menu)),M_RUN_BENCHMARKS) == 0 )
putevent(new TuiEvent(evBENCHMARK)); //NEvent(NEvent::evPROG, 5)); //создаем событие запускающее бенчмарк
if ( strcmp(item_name(current_item(menu)),M_QUIT) == 0 )
putevent(new NEvent(NEvent::evKB, 'Q')); //создаем событие иммитирующее нажатие 'Q'
return true;
}
//=============================================================================================
ViewSubMenu::ViewSubMenu(NRect rect/*, Config* cfg*/) : NMenu(rect)
{
int colnum = 0;
additem(M_VIEW_NUMBER, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_STATE, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_DONE, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_PROJECT, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_ESTIMATE, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_DEADLINE, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_APPNAME, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem(M_VIEW_TASKNAME, iscolenable(/*cfg,*/colnum++) ? "[*]" : "[ ]");
additem("","");
int taskslistmode = 0;
if (gCfg != NULL)
{
Item* rootcfg = gCfg->getcfgptr();
if (rootcfg != NULL)
{
Item* tasks_list_mode = rootcfg->findItem("tasks_list_mode");
taskslistmode = tasks_list_mode->getivalue();
}
}
additem(M_ALL_TASKS, (taskslistmode == 0) ? "(*)" : "( )");
additem(M_HIDE_DONE, (taskslistmode == 1) ? "(*)" : "( )");
additem(M_ACTIVE_ONLY, (taskslistmode == 2) ? "(*)" : "( )");
additem("","");
int taskssortmode = 0;
if (gCfg != NULL)
{
Item* rootcfg = gCfg->getcfgptr();
if (rootcfg != NULL)
{
Item* tasks_sort_mode = rootcfg->findItem("tasks_sort_mode");
taskssortmode = tasks_sort_mode->getivalue();
}
}
additem(M_UNSORTED, (taskssortmode == 0) ? "(*)" : "( )");
additem(M_SORT_BY_STATE, (taskssortmode == 1) ? "(*)" : "( )");
additem(M_SORT_BY_DONE, (taskssortmode == 2) ? "(*)" : "( )");
additem(M_SORT_BY_PROJECT, (taskssortmode == 3) ? "(*)" : "( )");
additem(M_SORT_BY_ESTIMATE, (taskssortmode == 4) ? "(*)" : "( )");
additem(M_SORT_BY_DL, (taskssortmode == 5) ? "(*)" : "( )");
//additem(M_SORT_BY_APP, (taskssortmode == 6) ? "(*)" : "( )"); //not implemented yet
additem(M_SORT_BY_TASK, (taskssortmode == 7) ? "(*)" : "( )");
additem("","");
additem(M_ASCII_LINE_DRAW, (asciilinedraw == 1) ? "[*]" : "[ ]");
additem(NULL,NULL);
}
bool ViewSubMenu::iscolenable(/*Config* cfg,*/ int n)
{
bool result = false;
//читаем из конфига
if (gCfg != NULL)
{
Item* rootcfg = gCfg->getcfgptr();
if (rootcfg != NULL)
{
Item* column_view_mask = rootcfg->findItem("column_view_mask");
unsigned int columnmask = column_view_mask->getivalue();
result = (1 << n) & columnmask;
}
}
return result;
}
bool ViewSubMenu::action()
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть осн меню
if ( strcmp(item_name(current_item(menu)),M_ALL_TASKS) == 0 )
{
putevent(new TuiEvent(evVIEWMODECH, 0));
return true;
}
if ( strcmp(item_name(current_item(menu)),M_HIDE_DONE) == 0 )
{
putevent(new TuiEvent(evVIEWMODECH, 1));
return true;
}
if ( strcmp(item_name(current_item(menu)),M_ACTIVE_ONLY) == 0 )
{
putevent(new TuiEvent(evVIEWMODECH, 2));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_UNSORTED) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 0));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_STATE) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 1));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_DONE) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 2));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_PROJECT) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 3));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_ESTIMATE) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 4));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_DL) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 5));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_APP) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 6));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_SORT_BY_TASK) == 0 )
{
putevent(new TuiEvent(evSORTMODECH, 7));
return true;
}
if ( strcmp(item_name(current_item(menu)), M_ASCII_LINE_DRAW) == 0 )
{
asciilinedraw = !asciilinedraw;
putevent(new TuiEvent(evASCIIMODECHANGE));
return true;
}
putevent(new TuiEvent(evCOLVIEWCH,item_index(current_item(menu)), false));
return true;
}
//=============================================================================================
HelpSubMenu::HelpSubMenu(NRect rect) : NMenu(rect)
{
additem(M_ABOUT,"");
additem(M_KEY_BINDINGS,"");
additem(NULL,NULL);
}
bool HelpSubMenu::action()
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть осн меню
if ( strcmp(item_name(current_item(menu)),M_ABOUT) == 0 )
putevent(new TuiEvent(evABOUT)); //NEvent(NEvent::evPROG, 3)); //создаем событие с кодом 3 "окно About"
if ( strcmp(item_name(current_item(menu)),M_KEY_BINDINGS) == 0 )
putevent(new TuiEvent(evKEYBIND));//NEvent(NEvent::evPROG, 4)); //создаем событие с кодом 4 "окно Key Bindings"
return true;
}
//=============================================================================================
ProjectsSubMenu::ProjectsSubMenu(NRect rect, Srv* srv) : NMenu(rect)
{
this->srv = srv;
std::string acctmgrname = "";
if (srv != NULL)
{
if (!srv->acctmgrinfodom.empty())
{
Item* tmpacctmgrinfodom = srv->acctmgrinfodom.hookptr();
Item* acct_mgr_name = tmpacctmgrinfodom->findItem("acct_mgr_name");
if (acct_mgr_name != NULL)
acctmgrname = acct_mgr_name->getsvalue();
Item* acct_mgr_url = tmpacctmgrinfodom->findItem("acct_mgr_url");
if (acct_mgr_url != NULL)
accmgrurl = acct_mgr_url->getsvalue();
srv->acctmgrinfodom.releaseptr(tmpacctmgrinfodom);
}
}
additem(M_ADD_PROJECT,"");
if (acctmgrname.empty())
additem(M_CONNECT_MANAGER,"");
else
{
additem(M_SYNCHRONIZE_MANAGER,acctmgrname.c_str());
additem(M_DISCONNECT_MANAGER,acctmgrname.c_str());
}
//имена подключенных проектов
additem("","");
if ((srv != NULL)&&(!srv->statedom.empty()))
{
Item* tmpstatedom = srv->statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
if (client_state != NULL)
{
std::vector- projects = client_state->getItems("project");
for (int i = 0; i < projects.size(); i++)
{
Item* project_name = projects[i]->findItem("project_name");
if (project_name != NULL)
{
std::string status = ""; //строка состояния
if (projects[i]->findItem("suspended_via_gui") != NULL)
status = status + "[Susp.]";
if (projects[i]->findItem("dont_request_more_work") != NULL)
status = status + "[N.N.Tsk]";
additem(project_name->getsvalue(),status.c_str());
}
}
}
srv->statedom.releaseptr(tmpstatedom);
}
additem(NULL,NULL);
}
bool ProjectsSubMenu::action()
{
bool result = false;
if (items.size() > 1) //если уже открыто выходим (>1 из-за скроллбара)
return false;
//формируем код операции для подменю
bool actiondone = false;
//создаем подменю
int begincol = 2/*getwidth() - 2*/; //смещение на экране по горизонтали
int beginrow = 2 + item_index(current_item(menu)); //смещение на экране по вертикали
if ( strcmp(item_name(current_item(menu)), M_ADD_PROJECT) == 0 ) //подключиться к новому проекту
{
insert(new ProjectAllListSubMenu(NRect(5,25,beginrow, begincol), srv));
actiondone = true;
}
if ( strcmp(item_name(current_item(menu)), M_CONNECT_MANAGER) == 0 ) //подключить менеджер
{
insert(new ProjectAccMgrSubMenu(NRect(5,25,beginrow, begincol), srv));
actiondone = true;
}
if ( strcmp(item_name(current_item(menu)), M_DISCONNECT_MANAGER) == 0 ) //отключить менеджер
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть осн меню
std::string errmsg;
if (srv != NULL)
srv->accountmanager("","","",false,errmsg);
actiondone = true;
}
if ( strcmp(item_name(current_item(menu)), M_SYNCHRONIZE_MANAGER) == 0 ) //синхронизироваться с менеджером
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть осн меню
std::string errmsg;
if (srv != NULL)
srv->accountmanager(accmgrurl.c_str(),"","",true,errmsg);
actiondone = true;
}
//если ни одна M_ константа не подошла значит это название проекта
if (!actiondone)
{
insert(new ProjectListSubMenu(NRect(5,25,beginrow, begincol), srv, item_name(current_item(menu))));
}
return true;
}
void ProjectsSubMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMenu::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case 27:
if ( items.size() > 1 ) //1 из-за скроллбара
destroysubmenu();
else
ev->done = false; //пусть обрабатывает владелец
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
//=============================================================================================
TasksSubMenu::TasksSubMenu(NRect rect) : NMenu(rect)
{
additem(M_SUSPEND_TASK," S");
additem(M_RESUME_TASK ," R");
additem(M_ABORT_TASK ," A");
additem(M_INFO_TASK ," Enter");
additem(NULL,NULL);
}
bool TasksSubMenu::action()
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть осн меню
if ( strcmp(item_name(current_item(menu)),M_SUSPEND_TASK) == 0 )
putevent(new NEvent(NEvent::evKB, 'S')); //создаем событие иммитирующее нажатие 'S'
if ( strcmp(item_name(current_item(menu)),M_RESUME_TASK) == 0 )
putevent(new NEvent(NEvent::evKB, 'R')); //создаем событие иммитирующее нажатие 'R'
if ( strcmp(item_name(current_item(menu)),M_ABORT_TASK) == 0 )
{
TuiEvent* ev = new TuiEvent(evABORTRES);
ev->bdata1 = false;
putevent(ev); //NEvent(NEvent::evPROG, 2)); //создаем событие с кодом 2 "abort_result"
}
if ( strcmp(item_name(current_item(menu)),M_INFO_TASK) == 0 )
putevent(new NEvent(NEvent::evKB, KEY_ENTER)); //создаем событие имитирующее нажатие 'Enter'
return true;
}
//=============================================================================================
ActivitySubMenu::ActivitySubMenu(NRect rect, Srv* srv) : NMenu(rect)
{
unpost_menu(menu);
this->srv = srv;
if ((srv != NULL)&&(!srv->ccstatusdom.empty()))
{
Item* tmpccstatusdom = srv->ccstatusdom.hookptr();
Item* task_mode = tmpccstatusdom->findItem("task_mode");
additem(M_ACTIVITY_ALWAYS, ((task_mode!=NULL)&&(task_mode->getivalue() == 1)) ? "(*)" : "( )"); //1 always
additem(M_ACTIVITY_AUTO,((task_mode!=NULL)&&(task_mode->getivalue() == 2)) ? "(*)" : "( )"); //2 pref
additem(M_ACTIVITY_NEVER,((task_mode!=NULL)&&(task_mode->getivalue() == 3)) ? "(*)" : "( )"); //3 never
if (!srv->statedom.empty())
{
Item* tmpstatedom = srv->statedom.hookptr();
Item* have_ati = tmpstatedom->findItem("have_ati");
Item* have_cuda = tmpstatedom->findItem("have_cuda");
if ( (have_cuda != NULL)||(have_ati !=NULL) )
{
Item* gpu_mode = tmpccstatusdom->findItem("gpu_mode");
additem("",""); //delimiter
additem(M_GPU_ACTIVITY_ALWAYS, ((gpu_mode!=NULL)&&(gpu_mode->getivalue() == 1)) ? "(*)" : "( )"); //1 always
additem(M_GPU_ACTIVITY_AUTO,((gpu_mode!=NULL)&&(gpu_mode->getivalue() == 2)) ? "(*)" : "( )"); //2 pref
additem(M_GPU_ACTIVITY_NEVER,((gpu_mode!=NULL)&&(gpu_mode->getivalue() == 3)) ? "(*)" : "( )"); //3 never
}
srv->statedom.releaseptr(tmpstatedom);
}
Item* network_mode = tmpccstatusdom->findItem("network_mode");
additem("",""); //delimiter
additem(M_NET_ACTIVITY_ALWAYS, ((network_mode!=NULL)&&(network_mode->getivalue() == 1)) ? "(*)" : "( )"); //1 always
additem(M_NET_ACTIVITY_AUTO,((network_mode!=NULL)&&(network_mode->getivalue() == 2)) ? "(*)" : "( )"); //2 pref
additem(M_NET_ACTIVITY_NEVER,((network_mode!=NULL)&&(network_mode->getivalue() == 3)) ? "(*)" : "( )"); //3 never
srv->ccstatusdom.releaseptr(tmpccstatusdom);
}
additem(NULL,NULL);
}
bool ActivitySubMenu::action()
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //закрыть все меню
if (srv != NULL)
{
if ( strcmp(item_name(current_item(menu)),M_ACTIVITY_ALWAYS) == 0 )
srv->opactivity("always");
if ( strcmp(item_name(current_item(menu)),M_ACTIVITY_AUTO) == 0 )
srv->opactivity("auto");
if ( strcmp(item_name(current_item(menu)),M_ACTIVITY_NEVER) == 0 )
srv->opactivity("never");
if ( strcmp(item_name(current_item(menu)),M_GPU_ACTIVITY_ALWAYS) == 0 )
srv->opgpuactivity("always");
if ( strcmp(item_name(current_item(menu)),M_GPU_ACTIVITY_AUTO) == 0 )
srv->opgpuactivity("auto");
if ( strcmp(item_name(current_item(menu)),M_GPU_ACTIVITY_NEVER) == 0 )
srv->opgpuactivity("never");
if ( strcmp(item_name(current_item(menu)),M_NET_ACTIVITY_ALWAYS) == 0 )
srv->opnetactivity("always");
if ( strcmp(item_name(current_item(menu)),M_NET_ACTIVITY_AUTO) == 0 )
srv->opnetactivity("auto");
if ( strcmp(item_name(current_item(menu)),M_NET_ACTIVITY_NEVER) == 0 )
srv->opnetactivity("never");
}
return true;
}
//=============================================================================================
ProjectListSubMenu::ProjectListSubMenu(NRect rect, Srv* srv, std::string projname) : NMenu(rect)
{
this->srv = srv;
this->projname = projname;
additem(M_UPDATE_PROJECT,"");
additem(M_SUSPEND_PROJECT ,"");
additem(M_RESUME_PROJECT,"");
additem(M_NO_NEW_TASKS_PROJECT,"");
additem(M_ALLOW_NEW_TASKS_PROJECT,"");
additem(M_RESET_PROJECT,"");
additem(M_DETACH_PROJECT,"");
additem(NULL,NULL);
}
bool ProjectListSubMenu::action()
{
if (srv != NULL)
{
const char* sop = NULL;
bool confirmed = false;
if ( strcmp(item_name(current_item(menu)),M_SUSPEND_PROJECT) == 0 )
{//Suspend project
confirmed = true; //действие не требует подтверждения юзером
sop = "project_suspend";
}
if ( strcmp(item_name(current_item(menu)),M_RESUME_PROJECT) == 0 )
{//Resume project
confirmed = true; //действие не требует подтверждения юзером
sop = "project_resume";
}
if ( strcmp(item_name(current_item(menu)),M_UPDATE_PROJECT) == 0 )
{//Update project
confirmed = true; //действие не требует подтверждения юзером
sop = "project_update";
}
if ( strcmp(item_name(current_item(menu)),M_NO_NEW_TASKS_PROJECT) == 0 )
{//No New Task project
confirmed = true; //действие не требует подтверждения юзером
sop = "project_nomorework";
}
if ( strcmp(item_name(current_item(menu)),M_ALLOW_NEW_TASKS_PROJECT) == 0 )
{//Allow More Work project
confirmed = true; //действие не требует подтверждения юзером
sop = "project_allowmorework";
}
if ( strcmp(item_name(current_item(menu)),M_RESET_PROJECT) == 0 )
{//Reset project
sop = "project_reset";
}
if ( strcmp(item_name(current_item(menu)),M_DETACH_PROJECT) == 0 )
{//Detach project
sop = "project_detach";
}
if (sop)
{
TuiEvent* ev = new TuiEvent(evPROJECTOP, srv, projname.c_str(),sop);
ev->bdata1 = confirmed;
putevent(ev);
}
}
//создаем событие закрывающее меню
putevent(new NEvent(NEvent::evKB, KEY_F(9)));
}
void ProjectListSubMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMenu::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_RIGHT: //блокируем стрелку вправо
break;
case KEY_LEFT:
putevent(new NEvent(NEvent::evKB, 27)); //закрыть это подменю
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
//=============================================================================================
ProjectAllListSubMenu::ProjectAllListSubMenu(NRect rect, Srv* srv) : NMenu(rect)
{
this->srv = srv;
if (srv != NULL)
{
srv->updateallprojects();
if ( srv->allprojectsdom != NULL)
{
Item* projects = srv->allprojectsdom->findItem("projects");
if (projects != NULL)
{
std::vector
- projlist = projects->getItems("project");
for (int i = 0; i < projlist.size(); i++)
{
Item* name = projlist[i]->findItem("name");
Item* general_area = projlist[i]->findItem("general_area");
if (name != NULL)
{
std::string status = ""; //строка тематика проекта
if (general_area != NULL)
status = general_area->getsvalue();
status.resize(20);
additem(name->getsvalue(),status.c_str());
}
}
}
}
}
additem(NULL,NULL);
}
bool ProjectAllListSubMenu::action()
{
if (srv != NULL)
{
const char* prjname = item_name(current_item(menu));
//создаем подменю для выбора новый/существующий пользователь
int begincol = getwidth() - 2; //смещение на экране по горизонтали
int beginrow = 2 + item_index(current_item(menu)) - top_row(menu); //смещение на экране по вертикали
insert(new ProjectUserExistSubMenu(NRect(5,25,beginrow, begincol), srv, prjname));
}
}
void ProjectAllListSubMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMenu::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_RIGHT: //блокируем стрелку вправо
break;
case KEY_LEFT:
putevent(new NEvent(NEvent::evKB, 27)); //закрыть это подменю
break;
case 27:
if ( items.size() > 1 ) //1 из-за кроллбара
destroysubmenu();
else
ev->done = false; //пусть обрабатывает владелец
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
//=============================================================================================
ProjectAccMgrSubMenu::ProjectAccMgrSubMenu(NRect rect, Srv* srv) : NMenu(rect)
{
this->srv = srv;
if (srv != NULL)
{
srv->updateallprojects();
if ( srv->allprojectsdom != NULL)
{
Item* projects = srv->allprojectsdom->findItem("projects");
if (projects != NULL)
{
std::vector
- mgrlist = projects->getItems("account_manager");
for (int i = 0; i < mgrlist.size(); i++)
{
Item* name = mgrlist[i]->findItem("name");
if (name != NULL)
additem(name->getsvalue(),"");
}
}
}
}
additem(NULL,NULL);
}
bool ProjectAccMgrSubMenu::action()
{
putevent(new NEvent(NEvent::evKB, KEY_F(9))); //создаем событие закрывающее меню
if (srv != NULL)
putevent(new TuiEvent(evADDACCMGR, srv, item_name(current_item(menu)))); //создаем событие открвыающее форму менеджера
}
void ProjectAccMgrSubMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMenu::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_RIGHT: //блокируем стрелку вправо
break;
case KEY_LEFT:
putevent(new NEvent(NEvent::evKB, 27)); //закрыть это подменю
break;
case 27:
if ( items.empty() > 1 ) //1 из-за скроллбара
destroysubmenu();
else
ev->done = false; //пусть обрабатывает владелец
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
//=============================================================================================
ProjectUserExistSubMenu::ProjectUserExistSubMenu(NRect rect, Srv* srv, const char* prjname) : NMenu(rect)
{
this->srv = srv;
this->prjname = prjname;
additem(M_PROJECT_USER_EXIST,"");
additem(M_PROJECT_NEW_USER,"");
additem(NULL,NULL);
}
bool ProjectUserExistSubMenu::action()
{
//создаем событие закрывающее меню
putevent(new NEvent(NEvent::evKB, KEY_F(9)));
if (srv != NULL)
{
if ( strcmp(item_name(current_item(menu)),M_PROJECT_USER_EXIST) == 0 )
putevent(new TuiEvent(evADDPROJECT, srv, prjname.c_str(), true));
if ( strcmp(item_name(current_item(menu)),M_PROJECT_NEW_USER) == 0 )
putevent(new TuiEvent(evADDPROJECT, srv, prjname.c_str(), false));
}
}
void ProjectUserExistSubMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMenu::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_RIGHT: //блокируем стрелку вправо
break;
case KEY_LEFT:
putevent(new NEvent(NEvent::evKB, 27)); //закрыть это подменю
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
boinctui-2.3.4/src/addprojectform.cpp 0000644 0000000 0000000 00000022144 12301564455 016340 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "addprojectform.h"
#include "mbstring.h"
#include "kclog.h"
#include "tuievent.h"
char* strupcase(char* s) //в верхний регистр
{
char *p;
for (p = s; *p != '\0'; p++)
*p = (char) toupper(*p);
return s;
}
char* strlowcase(char* s) //в нижний регистр
{
char *p;
for (p = s; *p != '\0'; p++)
*p = (char) tolower(*p);
return s;
}
AddProjectForm::AddProjectForm(int rows, int cols, Srv* srv, const char* projname, bool userexist) : NForm(rows,cols)
{
this->srv = srv;
settitle(projname);
this->projname = projname;
this->userexist = userexist;
Item* project = NULL;
if (srv !=NULL)
project = srv->findprojectbynamefromall(projname);
int row = 1;
//поля
genfields(row,project);
//пересчитываем высоту формы, чтобы влезли все поля и центрируем
resize(row + 2,getwidth());
move(getmaxy(stdscr)/2-getheight()/2,getmaxx(stdscr)/2-getwidth()/2);
set_form_fields(frm, fields);
set_current_field(frm, fields[0]); //фокус на поле
post_form(frm);
this->refresh();
}
void AddProjectForm::genfields(int& line, Item* project) //создаст массив полей
{
FIELD* f;
delfields();
if (project != NULL)
{
//сообщение об ошибке
errmsgfield = getfieldcount();
f = addfield(new_field(1, getwidth()-2, line++, 1, 0, 0));
set_field_buffer(f, 0, "Errr");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_RED) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
field_opts_off(f, O_VISIBLE); //по умолчанию невидима
//url
Item* url = project->findItem("url");
std::string s = "url : ";
if (url !=NULL)
projurl = url->getsvalue();
s = s + projurl;
f = addfield(new_field(1, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//area
Item* general_area = project->findItem("general_area");
s = "General area : ";
if (general_area !=NULL)
s = s + general_area->getsvalue();
f = addfield(new_field(1, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//specific area
Item* specific_area = project->findItem("specific_area");
s = "Specific area: ";
if (specific_area !=NULL)
s = s + specific_area->getsvalue();
f = addfield(new_field(1, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//home
s = "Home : ";
Item* home = project->findItem("home");
if (home !=NULL)
s = s + home->getsvalue();
f = addfield(new_field(1, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//description
s = "";
line++;
Item* description = project->findItem("description");
if (description !=NULL)
s = s + description->getsvalue();
f = addfield(new_field(3, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
line = line + 3;
//platforms
Item* platforms = project->findItem("platforms");
if (platforms !=NULL)
{
std::vector
- namelist = platforms->getItems("name"); //список названий платформ
std::vector
- ::iterator it;
for (it = namelist.begin(); it!=namelist.end(); it++)
{
Item* name = (*it)->findItem("name");
//NStaticText* text6 = new NStaticText(NRect(1, getwidth()-4, row++, 2));
s = name->getsvalue();
f = addfield(new_field(1, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
}
}
}
//email
line++;
f = addfield(new_field(1, 10, line, 2 , 0, 0));
set_field_buffer(f, 0, "email");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
emailfield = getfieldcount();
f = addfield(new_field(1, 40, line++, 15, 0, 0));
field_opts_off(f, O_AUTOSKIP);
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
//password
line++;
f = addfield(new_field(1, 10, line, 2 , 0, 0));
set_field_buffer(f, 0, "password");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
passwfield = getfieldcount();
f = addfield(new_field(1, 40, line++, 15, 0, 0));
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
field_opts_off(f, O_AUTOSKIP);
if (!userexist)
{
//user name
line++;
f = addfield(new_field(1, 10, line, 2 , 0, 0));
set_field_buffer(f, 0, "username");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
usernamefield = getfieldcount();
f = addfield(new_field(1, 40, line++, 15, 0, 0));
field_opts_off(f, O_AUTOSKIP);
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
//team name
line++;
f = addfield(new_field(1, 10, line, 2 , 0, 0));
set_field_buffer(f, 0, "teamname");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
teamfield = getfieldcount();
f = addfield(new_field(1, 40, line++, 15, 0, 0));
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
field_opts_off(f, O_AUTOSKIP);
}
//подсказки
line++;
f = addfield(new_field(1, getwidth()-25, line++, 20 , 0, 0));
set_field_buffer(f, 0, "Enter-Ok Esc-Cancel");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//финализация списка полей
addfield(NULL);
}
void AddProjectForm::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMouseEvent* mevent = (NMouseEvent*)ev;
if ( ev->type == NEvent::evMOUSE)
{
NForm::eventhandle(ev); //предок
}
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_ENTER:
case '\n': //ENTER
{
form_driver(frm, REQ_NEXT_FIELD); //костыль чтобы текущее поле не потеряло значение
char* email = strlowcase(rtrim(field_buffer(fields[emailfield],0)));
char* passw = rtrim(field_buffer(fields[passwfield],0));
kLogPrintf("AddProjectForm OK name=[%s] url=[%s] email=[%s]\n passw=[%s]\n", projname.c_str(), projurl.c_str(), email, passw);
if (srv!=NULL)
{
std::string errmsg;
bool success = true;
if (!userexist) //если аккаунта еще нет то создаем
{
char* username = strlowcase(rtrim(field_buffer(fields[usernamefield],0)));
char* teamname = rtrim(field_buffer(fields[teamfield],0));
success = srv->createaccount(projurl.c_str(),email,passw, username, teamname, errmsg);
}
if (success)
success = srv->projectattach(projurl.c_str(), projname.c_str(), email, passw, errmsg); //подключить проект
if (success)
putevent(new TuiEvent(evADDPROJECT)); //создаем событие чтобы закрыть форму
else
{
//СООБЩЕНИЕ ОБ ОШИБКЕ
errmsg = " Error: " + errmsg;
set_field_buffer(fields[errmsgfield], 0, errmsg.c_str());
field_opts_on(fields[errmsgfield], O_VISIBLE); //делаем видимой строку ошибки
this->refresh();
}
}
break;
}
case 27:
putevent(new TuiEvent(evADDPROJECT)); //код закрытия окна
break;
default:
kLogPrintf("AddProjectForm::KEYCODE=%d\n", ev->keycode);
ev->done = false;
NForm::eventhandle(ev); //предок
break;
} //switch
}
}
boinctui-2.3.4/src/nmessagebox.h 0000644 0000000 0000000 00000003316 12301564455 015315 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NMESSAGEBOX_H
#define NMESSAGEBOX_H
#include
#include "ngroup.h"
#include "nstatictext.h"
#include "tuievent.h"
class NMButton : public NStaticText //кнопка внутри NMessageBox
{
public:
NMButton(const char* text, NEvent* pevent, ...);
~NMButton() { if (pevent) delete pevent; };
void eventhandle(NEvent* ev); //обработчик событий
private:
NEvent* pevent; //евент генерируемый кнопкой при нажатии
std::list keys; //на какие коды она реагирует
};
class NMessageBox : public NGroup //стандартный диалог вида Ok/Cancel или Yes/No
{
public:
NMessageBox(const char* text);
void eventhandle(NEvent* ev); //обработчик событий
void addbutton(NMButton* button); //добавить кнопку
private:
NStaticText* content;
};
#endif //NMESSAGEBOX_H boinctui-2.3.4/src/kclog.cpp 0000644 0000000 0000000 00000005557 12301564455 014445 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
// * для ведения логов
#ifdef LINUX
#include
#endif
#include
#include
#include
#include "kclog.h"
#define K_NO_THREAD_COLOR_LOG //отключаем раскраску тредов ибо в этом проекте нахрен не нужно
#ifdef DEBUG
FILE* kLog = NULL;
/// ANSI цвета
const char* colors[7] = {"\033[0;0;31m","\033[0;0;32m","\033[0;0;33m","\033[0;0;34m","\033[0;0;35m","\033[0;0;36m","\033[0;0;37m"};
#endif
/// открывает лог файл на запись
void kLogOpen(const char* filename)
{
#ifdef DEBUG
if (filename == NULL)
{
kLog = stdout;
}
else
{
char* tmpfile = (char*) malloc(256);
#ifdef WIN32
sprintf(tmpfile,"%s/%s",getenv("TEMP"),filename); //для win32 используем юзерский temp
//const char* tmpdir = getenv("TEMP");
#else //для линукса используем фиксированный путь
sprintf(tmpfile,"/tmp/%s",filename);
#endif
if ((kLog = fopen(tmpfile,"a")) == NULL)
{
//kLogPrintf("ERROR: can't create log file %s\n",tmpfile.c_str());
}
else
{
kLogPrintf("\nINFO: log opened success\n");
}
free(tmpfile);
}
#endif
}
/// закрывает лог файл
void kLogClose()
{
#ifdef DEBUG
kLogPrintf("\nINFO: log close\n");
fclose(kLog);
#endif
}
/// вывести информацию в лог заданным цветом
void kCLogPrintf(char* color, char* fmt, ...)
{
#ifdef DEBUG
if (kLog == NULL)
kLogOpen();
fprintf(kLog,"%s",color);
va_list args;
va_start(args, fmt);
vfprintf(kLog, fmt, args);
va_end(args);
fprintf(kLog,"\033[0m");
fflush(kLog);
#endif
}
/// вывести информацию в лог
void kLogPrintf(const char* fmt, ...)
{
#ifdef DEBUG
if (kLog == NULL)
kLogOpen();
#ifndef K_NO_THREAD_COLOR_LOG
fprintf(kLog,"%s",colors[pthread_self() % (sizeof(colors)/sizeof(colors[0]))]);
#endif
va_list args;
va_start(args, fmt);
vfprintf(kLog, fmt, args);
va_end(args);
#ifndef K_NO_THREAD_COLOR_LOG
fprintf(kLog,"\033[0m");
#endif
fflush(kLog);
#endif
}
boinctui-2.3.4/src/srvdata.h 0000644 0000000 0000000 00000020006 12301564455 014441 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef SRVDATA_H
#define SRVDATA_H
#include
#include
#include
#include
#include "net.h"
#include "resultdom.h"
#include "cfg.h"
struct DomPtr
{
DomPtr(Item* ptr) {refcount = 0; dom = ptr; };
Item* dom; //указатель на данные
int refcount; //количество hook-ов данного указателя
};
class PtrList
{
public:
PtrList() { pthread_mutex_init(&mutex, NULL); needupdate = true; };
~PtrList();
void lock() { pthread_mutex_lock(&mutex); };
void unlock() { pthread_mutex_unlock(&mutex); };
Item* hookptr(); //получить указатель из хвоста списка
void releaseptr(Item* ptr); //сообщить списку что указатель больше не нужен (список сам решит нужно ли его удалять)
void addptr(Item* ptr) { pthread_mutex_lock(&mutex); if (ptr != NULL) list.push_back(new DomPtr(ptr)); needupdate = false; pthread_mutex_unlock(&mutex);}; //добавить указатель в хвост списка
bool empty() { pthread_mutex_lock(&mutex); bool result = list.empty(); pthread_mutex_unlock(&mutex); return result; };
bool needupdate; //говорит треду что нужно незамедлительно обновлять данные
private:
std::list list;
pthread_mutex_t mutex;
};
bool daily_statisticsCmpAbove( Item* stat1, Item* stat2 ); //для сортировки статистики true если дата stat1 > stat2
class Srv : public TConnect //описание соединения с сервером
{
public:
Srv(const char* shost, const char* sport, const char* pwd);
virtual ~Srv();
void updateallprojects(); //обновить статистику
static std::string findProjectName(Item* tree, const char* url); //найти в дереве tree имя проекта с заданным url
std::string findProjectUrl(Item* tree, const char* name); //найти в дереве tree url проекта с заданным именем
Item* findresultbyname(const char* resultname);
Item* findprojectbyname(const char* projectname); //ищет в getstate
Item* findprojectbynamefromall(const char* projectname); //ищет в allprojectsdom
Item* findaccountmanager(const char* mgrname); //ищет менеджер по имени
Item* findappbywuname(const char* wuname); //найти приложение для данного WU
void opactivity(const char* op); //изменение режима активности BOINC сервера "always" "auto" "newer"
void opnetactivity(const char* op); //изменение режима активности сети "always" "auto" "newer"
void opgpuactivity(const char* op); //изменение режима активности GPU "always" "auto" "newer"
void optask(const char* url, const char* name, const char* op); //действия над задачей ("suspend_result",...)
void opproject(const char* name, const char* op); //действия над проектом ("project_suspend","project_resume",...)
void runbenchmarks(); //запустить бенчмарк
bool projectattach(const char* url, const char* prjname, const char* email, const char* pass, std::string& errmsg); //подключить проект
bool createaccount(const char* url, const char* email, const char* pass, const char* username, const char* teamname, std::string& errmsg); //создать аккаунт
bool accountmanager(const char* url, const char* username, const char* pass, bool useconfigfile, std::string& errmsg); //подключить аккаунт менеджер
bool getprojectconfig(const char* url, std::string& errmsg); //получить c сервера файл конфигурации
time_t getlaststattime(); //вернет время последней имеющейся статистики
PtrList msgdom; //xml дерево сообщений
int lastmsgno; //номер последнего сообщения полученного с сервера
PtrList statedom; //xml дерево состояний
PtrList ccstatusdom; //xml дерево для
PtrList dusagedom; //xml дерево для
PtrList statisticsdom; //xml дерево для
Item* allprojectsdom; //xml дерево для
PtrList acctmgrinfodom; //xml дерево для
bool ccstatusdomneedupdate; //если true тред обновит ccstatusdom без ожидания
Item* req(const char* fmt, ...); //выполнить запрос (вернет дерево или NULL)
virtual void createconnect();
void setactive(bool b); //включить/выключить тред обновления данных
bool isactive() {return active;};
void lock() { pthread_mutex_lock(&mutex); };
void unlock() { pthread_mutex_unlock(&mutex); };
bool loginfail; //true если получен unauthorize
protected:
void updatestate(); //обновить состояние
void updatemsgs(); //обновить список сообщений
void updatestatistics(); //обновить статистику
void updatediskusage(); //обновить состояние
void updateccstatus(); //обновить состояние
void updateacctmgrinfo();//обновить статистику
time_t gettimeelapsed(time_t t); //вернет соличество секунд между t и тек. временем
bool login(); //авторизоваться на сервере
char* pwd;
private:
unsigned int takt; //номер оборота цикла updatethread()
static void* updatethread(void* args); //трейд опрашивающий сервер
pthread_t thread;
bool active; //true если трейд активен
pthread_mutex_t mutex;
};
class SrvList //список всех серверов
{
public:
SrvList(/*Config* cfg*/);
virtual ~SrvList();
//Srv* addserver(const char* shost, const char* sport) { return new Srv(shost, sport); }; //добавить сервер (вернет указаталь на сервер)
void requestdata() {}; //опросить все сервера
//Srv* findserver(const char* shost, const char* sport) { return servers.front(); }; //ЗАГЛУШКА здесь нужен поиск по аресу проту
Srv* getcursrv() { if (cursrv != servers.end()) return (*cursrv); else return NULL; }; //получить текущий сервер или NULL
void refreshcfg(); //перечитать из конфига
void clear(); //удалить все соединения
void nextserver(); //переключиться на след сервер в списке
protected:
void addserver(Srv* c) { servers.push_back(c); };
std::list servers; //список соединений
std::list::iterator cursrv; //текущиq сервер
// Config* cfg;
};
#endif //SRVDATA_H
boinctui-2.3.4/src/infopanel.h 0000644 0000000 0000000 00000007534 12301564455 014763 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef INFOPANEL_H
#define INFOPANEL_H
#include "nview.h"
#include "resultdom.h"
#include "srvdata.h"
struct ProjectStat //статистика по проекту
{
std::string name; //имя проекта
std::string sstatus; //строка состояния проекта
double user; //очки по проекту (всего для юзера)
double host; //очки по проекту (всего для хоста)
time_t laststattime; //дата последней статистики
double userlastday; //очки юзера за последний день по каждому проекту
double hostlastday; //очки хоста за последний день по каждому проекту
static bool CmpAbove( ProjectStat stat1, ProjectStat stat2 ) //для сортировки проектов true если дата stat1 > stat2
{
//суммарная для юзера и хоста
double score1 = stat1.userlastday + stat1.hostlastday;
double score2 = stat2.userlastday + stat2.hostlastday;
if (stat1.laststattime == stat2.laststattime)
return (score1 > score2); //даты равны -> больше тот у кого больше очков
else
return (stat1.laststattime > stat2.laststattime); //больше тот у кого дата больше
/*
//оба с нулевыми (или оба с ненеулевыми) очками -> ставниваем по датам
if ( ((score1 == 0)&&(score2 == 0)) ||
((score1 > 0)&&(score2 > 0)) )
{
if (stat1.laststattime == stat2.laststattime)
{
//даты равны -> больше тот у кого больше очков
return (score1 > score2);
}
else //больше stat1 если у него дата больше
return (stat1.laststattime > stat2.laststattime);
}
// если stat1 с ненулевыми очками (stat2 соотв с нулевыми) -> stat1 больше
return (score1 > 0 );
*/
};
};
class InfoPanel : public NView
{
public:
InfoPanel(NRect rect) : NView(rect) {};
void updatedata();
virtual void refresh();
void* setserver(Srv* srv) { this->srv = srv; };
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
Srv* srv;
std::string getdayname(time_t ltime); //название дня "today" "yesterday" ""
//---для процессов---
int nalltasks;
int nactivetasks;
int nruntasks;
int nqueuetasks;
int ndonetasks;
int nothertasks;
//---для дисков---
double dtotal;
double dfree;
double dboinc;
double dallowed;
//---статистика cуммарная---
double usertotal;
double useravg;
double hosttotal;
double hostavg;
//---статистика за сегодня---
time_t laststattime; //дата последней статистики
double lastdayuser;
double lastdayhost;
std::vector projects; //статистика по отдельным проектам
};
#endif //INFOPANEL_H
boinctui-2.3.4/src/nstatictext.h 0000644 0000000 0000000 00000003046 12301564455 015354 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NSTATICTEXT_H
#define NSTATICTEXT_H
#include "nview.h"
#include "ncolorstring.h"
class NStaticText : public NView
{
public:
NStaticText(NRect rect) : NView(rect) { content = new NColorString(0,""); align = 0; setbgcolor(getcolorpair(COLOR_WHITE,COLOR_BLACK));};
virtual ~NStaticText() { delete content; };
void appendstring(int attr, const char* fmt, ...);
void setstring(int attr, const char* fmt, ...);
void setbgcolor(int colorpair) { bgcolor = colorpair; };
void setalign(int align) { this->align = align; }; //0-левое 2-правое 1-центр
virtual void refresh();
protected:
NColorString* content;
int align; //вравнивание
int bgcolor; //цвет фона
};
#endif //NSTATICTEXT_H boinctui-2.3.4/src/mbstring.cpp 0000644 0000000 0000000 00000004613 12301564455 015163 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include "mbstring.h"
int mbstrlen(const char* s) //вернет размер строки utf8 в СИМВОЛАХ (не байтах) без учета '\0'
{
int bsize = strlen(s); //количество байт
int result = 0; //подсчитанное кол-во символов
int nbytes = 0; //просмотренное кол-во байтов
const char* p = s;
do
{
int symlen = mblen(p,bsize-nbytes);
nbytes = nbytes + symlen;
result++;
p = p + symlen; //адрес начала след символа
}
while ( (*p != 0)&&(nbytes < bsize) );
return result;
}
char* mbstrtrunc(char* s, int slen) //обрезать до длины slen символов (не байтов) без учета \0
{
if (mbstrlen(s)<=slen) //обрезать не надо и так короткая
return s;
int bsize = strlen(s); //количество байт
int nbytes = 0; //просмотренное кол-во байтов
int ns = 0; //просмотренное кол-во символов
char* p = s;
do
{
int symlen = mblen(p,bsize-nbytes);
nbytes = nbytes + symlen;
ns++;
p = p + symlen;
}
while ( (*p != '\0')&&(nbytes < bsize)&&(ns < slen) );
*p = '\0'; //обрезаем
return s;
}
char* rtrim(char* s) //удалить завершающие пробелы в строке
{
if (s == NULL)
return NULL;
if (strlen(s) == 0)
return s;
char* p = s + strlen(s) - 1;
while ( p >= s)
{
if (*p == ' ')
*p = 0;
else
break;
p--;
}
return s;
}
boinctui-2.3.4/src/nhline.h 0000644 0000000 0000000 00000002253 12301564455 014256 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NHLINE_H
#define NHLINE_H
#include "nview.h"
class NHLine : public NView
{
public:
NHLine(NRect rect, const char* s) : NView(rect) { bgcolor = 0; };
virtual ~NHLine() { };
void setbgcolor(int colorpair) { bgcolor = colorpair; };
virtual void refresh();
protected:
int bgcolor; //цвет фона
const char* mbsym; //символ
};
#endif //NHLINE_H boinctui-2.3.4/src/resultdom.h 0000644 0000000 0000000 00000006407 12301564455 015024 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef RESULTDOM_H
#define RESULTDOM_H
#include
#include
#include
#include
class Item //элемент дерева данных (например 1129827635.000000)
{
public:
Item(const char* name) { this->name = name; parent = NULL; };
virtual ~Item();
bool isnode() { return !subitems.empty(); }; //true если имеет подэлементы
void addsubitem(Item* item) { item->parent = this; subitems.push_back(item); }; //добавляет подэлемент
void appendvalue(const char* svalue) { this->svalue = this->svalue + svalue; }; //дополняет строку значения
void setsvalue(const char* svalue) { this->svalue = svalue; }; //устанавливает строку значения
void setivalue(int ivalue); //присвоить целочисленное значение
void mergetree(Item* tree); //объединяет tree с текущим эл-том
void clearsubitems(); //удалить все подэл-ты текущего узла
void delsubitem(Item* subitem); //удалить подэлемент subitem из узла
const char* getsvalue() { return svalue.c_str(); }; //получить строку значения
int getivalue() { return atoi(svalue.c_str());};//получить целочисленное
double getdvalue(); //получить значение double
const char* getname() { return name.c_str(); }; //получить имя эл-та
std::string getfullname() { if (parent == NULL) return name; else return parent->getfullname()+"/"+name; }; //получить имя вместе со всеми владельщами
Item* findItem(const char* name); //возвращает подэлемент с именем name или NULL (поиск на всю глубину)
std::vector- getItems(const char* name); //получить из текущего эл-та список подэлементов с именем name (поиска в глубину НЕТ)
std::string toxmlstring(); //сериализация в строку
Item* getparent() {return parent;};
protected:
std::string name; //имя эл-та "disk_usage"
std::string svalue; //строка значения "1129827635.000000"
std::list
- subitems; //список вложенных эл-тов (если они есть)
Item* parent;
};
#endif //RESULTDOM_H boinctui-2.3.4/src/mbstring.h 0000644 0000000 0000000 00000002317 12301564455 014627 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef MBSTRING_H
#define MBSTRING_H
int mbstrlen(const char* s); //вернет размер строки utf8 в СИМВОЛАХ (не байтах) без учета '\0'
char* mbstrtrunc(char* s, int slen); //обрезать до длины slen символов (не байтов) без учета \0
char* rtrim(char* s); //удалить завершающие пробелы в строке
#endif // MBSTRING_H
boinctui-2.3.4/src/nview.h 0000644 0000000 0000000 00000006315 12301564455 014134 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NVIEW_H
#define NVIEW_H
#include
#include
#include "nrect.h"
#include "nevent.h"
class NGroup;
void initcolorpairs();
int getcolorpair(int fcolor, int bcolor); //получить пару для комбинации цветов
extern int asciilinedraw; //1-рисовать рамки символами +----+
class NView //базовый визуальный класс
{
public:
NView(NRect rect);
virtual ~NView() { del_panel(pan); delwin(win); };
//virtual void draw() {};
virtual void resize(int rows, int cols);
virtual void move(int begrow, int begcol);
PANEL* getpan() { return pan; }; //!!!!!!!!!!!!!!!!!!!!
int getwidth() { return rect.cols; }; //ширина в символах
int getheight() { return rect.rows; }; //высота в строках
int getbegrow() { return rect.begrow; }; //начальная строка
int getbegcol() { return rect.begcol; }; //начальный столбец
void erase() { werase(win); }; //очистить
bool isinside(int row, int col); //true если координаты внутри окна (row col абсолютные!)
virtual void refresh(); //перерисовать
virtual void setneedrefresh() { needrefresh = true; };
virtual void eventhandle(NEvent* ev) {/*EMPTY*/}; //обработчик событий
virtual void putevent(NEvent* ev); //отправить событие по цепочке владельцев в очередь
void setowner(NGroup* owner);
virtual const char* getid() { return typeid(*this).name(); }; //возвращает имя класса
virtual bool ismodal() { return modalflag; };
protected:
NGroup* owner; //владелец эл-та
WINDOW* win; //окно curses
PANEL* pan; //панель curses на основе окна win
bool needrefresh; //устанавливается в true когда нужна перерисовка
#ifdef DEBUG
int refreshcount; //счетчик обновлений
#endif
bool modalflag; //true если этот эл-т модальный
int getabsbegrow(); //получить начальную строку (абсолютную на экране)
int getabsbegcol(); //получить начальный столбец (абсолютный на экране)
private:
NRect rect; //координаты и размер
};
#endif //NVIEW_H boinctui-2.3.4/src/helpwin.h 0000644 0000000 0000000 00000002247 12301564455 014452 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef HELPWIN_H
#define HELPWIN_H
#include "ngroup.h"
#include "nstatictext.h"
class HelpWin : public NGroup
{
public:
HelpWin(int rows, int cols);
~HelpWin() { delete caption; };
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
char* caption; //строка заголовка
NStaticText* text1;
};
#endif //HELPWIN_H boinctui-2.3.4/src/mainprog.cpp 0000644 0000000 0000000 00000041013 12301564455 015145 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include "kclog.h"
#include "mainprog.h"
#include "tuievent.h"
#include "nmessagebox.h"
#define EVTIMERINTERVAL 2 //число секунд через которые генерируется evTIMER
MainProg::MainProg()
{
uistate = 0;
done = false;
gCfg = new Config(".boinctui.cfg");
gsrvlist = new SrvList(/*cfg*/);
evtimertime = 0; //запускаем таймер с нуля
//основное окно
wmain = new MainWin(NRect(getmaxy(stdscr)-2, getmaxx(stdscr), 1, 0)/*, cfg*/); //создаем основное окно
insert(wmain);
wmain->setserver(gsrvlist->getcursrv()); //отображать первый в списке сервер
menu = new TopMenu(/*cfg*/);
menu->setserver(gsrvlist->getcursrv()); //отображать первый в списке сервер
insert(menu);
wmain->updatecaption();
//статус строка
wstatus = new NStaticText(NRect(1, getmaxx(stdscr), getmaxy(stdscr)-1, 0)); //создаем окно статуса
insert(wstatus);
wstatus->setbgcolor(getcolorpair(COLOR_WHITE,COLOR_GREEN));
updatestatuslinecontent();
}
MainProg::~MainProg()
{
gCfg->save();
delete gsrvlist;
}
void MainProg::smartresize()
{
if (!MainProg::needresize)
return;
struct winsize size;
ioctl(fileno(stdout), TIOCGWINSZ, (char *) &size);
resizeterm(size.ws_row, size.ws_col);
menu->resize(1, getmaxx(stdscr)); //ширина верхнего меню
wmain->resize(getmaxy(stdscr)-2, getmaxx(stdscr));
wstatus->resize(1, getmaxx(stdscr)); //ширина статус строки
wstatus->move(getmaxy(stdscr)-1,0); //позиция статус строки
centermodalitems(getmaxy(stdscr),getmaxx(stdscr)); //центрировать модальные формы (если есть)
MainProg::needresize = false;
}
void MainProg::updatestatuslinecontent()
{
int attrYG = A_BOLD | getcolorpair(COLOR_YELLOW,COLOR_GREEN);
int attrWG = A_BOLD | getcolorpair(COLOR_WHITE,COLOR_GREEN);
int attrBG = A_BOLD | getcolorpair(COLOR_BLACK,COLOR_GREEN) | A_BOLD;
if (uistate & stUIMODALFORM)
{
wstatus->setstring(attrYG, " Esc");
wstatus->appendstring(attrWG, " Cancel");
}
if (uistate & stUITASKINFO)
{
wstatus->setstring(attrYG, " Esc");
wstatus->appendstring(attrWG, " Cancel");
wstatus->appendstring(attrWG, " |");
wstatus->appendstring(attrYG, " PgUp/PgDn");
wstatus->appendstring(attrWG, " Scroll ");
}
if ( (uistate == 0)||(uistate == stUISELECTOR) )
{
wstatus->setstring(attrYG, " PgUp/PgDn");
wstatus->appendstring(attrWG, " Scroll Msg |");
wstatus->appendstring(attrYG, " Up/Dn");
wstatus->appendstring(attrWG, " Select |");
if (uistate & stUISELECTOR)
{
wstatus->appendstring(attrYG, " S");
wstatus->appendstring(attrWG, "uspend");
wstatus->appendstring(attrWG, " |");
wstatus->appendstring(attrYG, " R");
wstatus->appendstring(attrWG, "esume |");
wstatus->appendstring(attrYG, " Enter");
wstatus->appendstring(attrWG, " Info");
}
else
{
wstatus->appendstring(attrBG, " Suspend");
wstatus->appendstring(attrWG, " |");
wstatus->appendstring(attrBG, " Resume");
wstatus->appendstring(attrWG, " |");
wstatus->appendstring(attrBG, " Enter Info");
}
wstatus->appendstring(attrWG, " |");
wstatus->appendstring(attrYG, " F9");
wstatus->appendstring(attrWG, " Menu |");
}
}
void MainProg::eventhandle(NEvent* ev) //обработчик событий КОРНЕВОЙ!
{
NProgram::eventhandle(ev);
if (ev->done) //если событие не обработано обработать здесь
return;
if (ev->type == NEvent::evKB) //клавиатурные
{
switch(ev->keycode)
{
case 'q':
case 'Q':
done = true; //выходим
break;
case 'n':
case 'N':
menu->disable();
gsrvlist->nextserver();
wmain->setserver(gsrvlist->getcursrv());
menu->setserver(gsrvlist->getcursrv());
evtimertime = 0; //для перезапуска таймера для форсированонй перерисовки
wmain->updatecaption();
break;
case 'c':
case 'C':
if (getitembyid(typeid(CfgForm).name()) == NULL)
{
menu->disable();
CfgForm* cfgform = new CfgForm(15,54/*,cfg*/);
insert(cfgform);
cfgform->settitle("Configuration");
cfgform->refresh();
uistate = uistate | stUIMODALFORM;
updatestatuslinecontent();
}
break;
case 'S':
case 's':
{
TaskInfo* tinfo = (TaskInfo*)wmain->wtask->getselectedobj();
if (tinfo) //только если есть выделенный эл-т
gsrvlist->getcursrv()->optask(tinfo->projecturl.c_str(), tinfo->taskname.c_str(),"suspend_result");
break;
}
case 'R':
case 'r':
{
TaskInfo* tinfo = (TaskInfo*)wmain->wtask->getselectedobj();
if (tinfo) //только если есть выделенный эл-т
gsrvlist->getcursrv()->optask(tinfo->projecturl.c_str(), tinfo->taskname.c_str(),"resume_result");
break;
}
case 'A':
case 'a':
{
TaskInfo* tinfo = (TaskInfo*)wmain->wtask->getselectedobj();
if (tinfo) //только если есть выделенный эл-т
{
TuiEvent* ev = new TuiEvent(evABORTRES);
ev->bdata1 = false;
putevent(ev); //создаем событие с кодом 2 "abort_result"
}
break;
}
case 27:
menu->disable();
//деструктим все какие есть модельные окна
destroybyid(typeid(CfgForm).name()); //деструктим форму
destroybyid(typeid(NMessageBox).name()); //деструктим форму
if (destroybyid(typeid(TaskInfoWin).name())) //деструктим форму
{
wmain->wtask->setselectorenable(true);
uistate = uistate & ~stUITASKINFO;
}
uistate = uistate & ~stUIMODALFORM;
updatestatuslinecontent();
break;
case KEY_F(9):
if (!menu->isenable())
{
menu->enable();
menu->action();
}
else
menu->disable();
break;
default:
kLogPrintf("KEYCODE=%d\n", ev->keycode);
break;
} //switch
}
if (ev->type == NEvent::evPROG) //прграммные
{
switch(ev->cmdcode)
{
case evCFGCH: //событие при изменении конфига
{
menu->disable();
destroybyid(typeid(CfgForm).name()); //деструктим форму
//реакция на изменение конфига
gsrvlist->refreshcfg();
wmain->setserver(gsrvlist->getcursrv()); //отображать первый в списке сервер
menu->setserver(gsrvlist->getcursrv()); //отображать первый в списке сервер
wmain->updatecaption();
evtimertime = 0; //для перезапуска таймера для форсированонй перерисовки
break;
}
case evABOUT: //событие About win
{
if (!destroybyid(typeid(AboutWin).name()))
{
AboutWin* about = new AboutWin(2,40);
insert(about);
about->move(getmaxy(stdscr)/2-about->getheight()/2,getmaxx(stdscr)/2-about->getwidth()/2); //центрируем
uistate = uistate | stUIMODALFORM;
}
else
uistate = uistate & ~stUIMODALFORM;
updatestatuslinecontent();
break;
}
case evKEYBIND: //событие KeyBinding win
{
if (!destroybyid(typeid(HelpWin).name()))
{
HelpWin* help = new HelpWin(2,40);
insert(help);
help->move(getmaxy(stdscr)/2-help->getheight()/2,getmaxx(stdscr)/2-help->getwidth()/2); //центрируем
uistate = uistate | stUIMODALFORM;
}
else
uistate = uistate & ~stUIMODALFORM;
updatestatuslinecontent();
break;
}
case evBENCHMARK: //запустить бенчмарк
{
Srv* srv = gsrvlist->getcursrv();
if (srv != NULL)
srv->runbenchmarks();
break;
}
case evADDPROJECT: //добавить проект
{
if (!destroybyid(typeid(AddProjectForm).name()))
{
TuiEvent* ev1 = (TuiEvent*)ev;
Srv* srv = gsrvlist->getcursrv();
if (ev1->srv != NULL)
{
AddProjectForm* addform = new AddProjectForm(30,65,ev1->srv,ev1->sdata1.c_str(),ev1->bdata1);
insert(addform);
addform->move(getmaxy(stdscr)/2-addform->getheight()/2,getmaxx(stdscr)/2-addform->getwidth()/2); //центрируем
uistate = uistate | stUIMODALFORM;
}
}
else
uistate = uistate & ~stUIMODALFORM;
updatestatuslinecontent();
break;
}
case evADDACCMGR: //добавить акк менеджер
{
if (!destroybyid(typeid(AddAccMgrForm).name()))
{
TuiEvent* ev1 = (TuiEvent*)ev;
Srv* srv = gsrvlist->getcursrv();
if (ev1->srv != NULL)
{
AddAccMgrForm* addmgrform = new AddAccMgrForm(30,65,ev1->srv,ev1->sdata1.c_str());
insert(addmgrform);
addmgrform->move(getmaxy(stdscr)/2-addmgrform->getheight()/2,getmaxx(stdscr)/2-addmgrform->getwidth()/2); //центрируем
uistate = uistate | stUIMODALFORM;
}
}
else
uistate = uistate & ~stUIMODALFORM;
updatestatuslinecontent();
break;
}
case evPROJECTOP: //операции над проектом
{
TuiEvent* ev1 = (TuiEvent*)ev;
const char* projname = ev1->sdata1.c_str();
const char* projop = ev1->sdata2.c_str();
if (!ev1->bdata1) //если нет флага подтвержденного события, то не выполняем а спрашиваем юзера
{
menu->disable(); //выключаем меню
//создаем окно сообщения с подтверждением
std::stringstream s;
s << "Please Confirm\n\n" << "Project : "<< projname << "\nOperation : " << projop;
NMessageBox* mbox = new NMessageBox(s.str().c_str());
TuiEvent* buttonYev = new TuiEvent(evPROJECTOP, ev1->srv, projname, projop); //событие для кнопки Y
buttonYev->bdata1 = true; //флаг подтвержденности
mbox->addbutton(new NMButton("Yes",buttonYev, 'Y','y',0));
NEvent* buttonNev = new NEvent(NEvent::evKB, 27); //событие для кнопки N
mbox->addbutton(new NMButton("No",buttonNev, 'N','n',27,0));
insert(mbox);
uistate = uistate | stUIMODALFORM;
}
else
{
kLogPrintf("evPROJECT confirmed event detected\n");
ev1->srv->opproject(projname, projop); //выполняем действие
if (destroybyid(typeid(NMessageBox).name())) //удаляем окно подтверждения (если есть)
uistate = uistate & ~stUIMODALFORM;
}
updatestatuslinecontent();
break;
}
case evABORTRES: //событие действий над проектами "abort_result" и.т.д.
{
TaskInfo* tinfo = (TaskInfo*)wmain->wtask->getselectedobj();
if (tinfo) //только если есть выделенный эл-т
{
TuiEvent* ev1 = (TuiEvent*)ev;
if (!ev1->bdata1) //если нет флага подтвержденного события, то не выполняем а спрашиваем юзера
{
menu->disable(); //выключаем меню
//создаем окно сообщения с подтверждением
std::stringstream s;
s << "Please Confirm\n\n" << "Task : " << tinfo->taskname << "\nOperation : " << "Abort";
NMessageBox* mbox = new NMessageBox(s.str().c_str());
TuiEvent* buttonYev = new TuiEvent(evABORTRES); //событие для кнопки Y
buttonYev->bdata1 = true; //флаг подтвержденности
mbox->addbutton(new NMButton("Yes",buttonYev, 'Y','y',0));
NEvent* buttonNev = new NEvent(NEvent::evKB, 27); //событие для кнопки N
mbox->addbutton(new NMButton("No",buttonNev, 'N','n',27,0));
insert(mbox);
uistate = uistate | stUIMODALFORM;
}
else
{
kLogPrintf("evABORTRES confirmed event detected\n");
Srv* srv = gsrvlist->getcursrv();
srv->optask(tinfo->projecturl.c_str(), tinfo->taskname.c_str(),"abort_result"); //выполняем действие
if (destroybyid(typeid(NMessageBox).name())) //удаляем окно подтверждения (если есть)
uistate = uistate & ~stUIMODALFORM;
}
updatestatuslinecontent();
break;
}
}
case evTASKSELECTORON:
{
uistate = uistate | stUISELECTOR;
updatestatuslinecontent();
break;
}
case evTASKSELECTOROFF:
{
uistate = uistate & ~stUISELECTOR;
updatestatuslinecontent();
break;
}
case evTASKINFO:
{
TaskInfo* tinfo = (TaskInfo*)wmain->wtask->getselectedobj();
if (tinfo) //только если есть выделенный эл-т
{
wmain->wtask->setselectorenable(false);
TaskInfoWin* taskinfowin = new TaskInfoWin("Task Info Raw View", gsrvlist->getcursrv(), tinfo->projecturl.c_str(), tinfo->taskname.c_str());
insert(taskinfowin);
taskinfowin->move(getmaxy(stdscr)/2-taskinfowin->getheight()/2,getmaxx(stdscr)/2-taskinfowin->getwidth()/2); //центрируем
uistate = uistate | stUITASKINFO;
updatestatuslinecontent();
}
}
case evASCIIMODECHANGE:
{
gCfg->setivalue("line_draw_mode",asciilinedraw);
refresh();
break;
}
} //switch
}
}
bool MainProg::mainloop() //основной цикл порождающий события
{
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, SIGWINCH); //маска для сигнала
if (gCfg->isdefault) //если конфига нет то открыть форму
putevent(new NEvent(NEvent::evKB, 'C')); //создаем событие иммитирующее нажатие 'C'
do
{
//блокировка сигнала изменения окна SIGWINCH на время отрисовки (из-за нереентерабельности курсес)
sigprocmask(SIG_BLOCK, &newset, 0);
//если нужен ресайз - перерисовать полностью
if (MainProg::needresize)
{
smartresize();
refresh();
menu->refresh();
//wmain->erase();
wstatus->erase();
wmain->refresh();
wstatus->refresh();
}
//если настало время посылаем evTIMER
if (time(NULL) - evtimertime > EVTIMERINTERVAL)
{
NEvent* event = new NEvent(NEvent::evTIMER, 0); //создаем событие таймера
putevent(event); //отправить в очередь
time(&evtimertime);
}
//есть символ в буфере -> нужно создать событие
int ic;
if ( (ic = getch()) != ERR ) //символ(ы) есть?
{
NEvent* event = NULL;
if (KEY_MOUSE == ic)
{
// mouse event
MEVENT mevent;
if (OK == getmouse(&mevent))
event = new NMouseEvent(mevent.bstate, mevent.y, mevent.x); //создаем мышиное событие
else
kLogPrintf("getmouse() err\n");
}
else // keyboard event
event = new NEvent(NEvent::evKB, ic); //создаем клавиатурное событие
if (event != NULL)
putevent(event); //отправить в очередь
}
//есть события в очереди - выполняем
while(!evqueue.empty())
{
NEvent* event = evqueue.front(); //получить первое событие из очереди
evqueue.pop();
this->eventhandle(event); //отправить событие обработчику
#ifdef DEBUG
if ((event->type != NEvent::evTIMER)&&(!event->done))
kLogPrintf("WARNING! lost event %s\n", event->tostring().c_str());
#endif
delete event; //удаляем отработанное событие
//обновляем экран
update_panels();
doupdate(); //физически выполняет перерисовку
}
//разблокируем SIGWINCH
sigprocmask(SIG_UNBLOCK, &newset, 0);
}
while(!done);
}
boinctui-2.3.4/src/helpwin.cpp 0000644 0000000 0000000 00000006507 12301564455 015010 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "helpwin.h"
#include "tuievent.h"
HelpWin::HelpWin(int rows, int cols) : NGroup(NRect(rows, cols, getmaxy(stdscr)/2-rows/2,getmaxx(stdscr)/2-cols/2))
{
caption = strdup(" Hot keys list ");
modalflag = true;
resize(17,60);
wattrset(win,getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD);
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(win,0,0);
mvwprintw(win,0,getwidth()/2-(strlen(caption)/2),caption);
text1 = new NStaticText(NRect(getheight()-2,getwidth()-2,/*rect.begrow+*/1,/*rect.begcol+*/1));
int attr1 = getcolorpair(COLOR_YELLOW, COLOR_BLACK) | A_BOLD;
int attr2 = getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD;
text1->setstring(attr1, "\n Common Controls:\n");
text1->appendstring(attr2," \"N\" - Toogle between BOINC hosts\n");
text1->appendstring(attr2," \"C\" - Edit configuration\n");
text1->appendstring(attr2," \"Q\" - Quit boinctui\n");
text1->appendstring(attr2," \"F9\" - Toogle main menu\n");
text1->appendstring(attr2," \"PgUp\"/\"PgDn\" - Scroll Messages Window\n");
text1->appendstring(attr2,"\n");
text1->appendstring(attr1," Task Controls:\n");
text1->appendstring(attr2," \"Up\"/\"Dn\" - Select task\n");
text1->appendstring(attr2," \"S\" - Suspend selected running task\n");
text1->appendstring(attr2," \"R\" - Resume selected suspended task\n");
text1->appendstring(attr2," \"A\" - Abort selected task\n");
text1->appendstring(attr2," \"Enter\" - View selected task raw info\n");
insert(text1);
}
void HelpWin::eventhandle(NEvent* ev) //обработчик событий
{
NGroup::eventhandle(ev); //предок
if ( ev->done )
return;
//закрываем при любом клике независимо от координат
NMouseEvent* mevent = (NMouseEvent*)ev;
if (( ev->type == NEvent::evMOUSE ) && (mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED)))
putevent(new TuiEvent(evKEYBIND));
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->cmdcode)
{
case 27:
case KEY_ENTER:
case ' ':
case '\n':
putevent(new TuiEvent(evKEYBIND)); //NEvent(NEvent::evPROG, 4)); //создаем событие с кодом 4 "окно Help"
break;
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
boinctui-2.3.4/src/nform.h 0000644 0000000 0000000 00000003131 12301564455 014116 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NFORM_H
#define NFORM_H
#include
#include
#include
#include "ngroup.h"
class NForm : public NGroup
{
public:
NForm(int lines, int rows);
virtual ~NForm();
virtual void refresh();
virtual void settitle(const char* title);
virtual void eventhandle(NEvent* ev); //обработчик событий
virtual FIELD* addfield(FIELD* field);
int getfieldcount() { return fieldcount; };
virtual void delfields(); //удаляет все поля
protected:
bool clickatfield(int mrow, int mcol, FIELD* f); //true если клик внутри этого поля
char* title; //заголовок
FIELD** fields;
int fieldcount; //число полей включая NULL
FORM* frm; //форма ncurses
};
#endif //NFORM_H boinctui-2.3.4/src/nstatictext.cpp 0000644 0000000 0000000 00000004030 12301564455 015701 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "nstatictext.h"
#include "kclog.h"
void NStaticText::appendstring(int attr, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
content->vappend(attr, fmt, args);
va_end(args);
needrefresh = true;
this->refresh();
}
void NStaticText::setstring(int attr, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
delete content;
content = new NColorString(attr,fmt,args);
va_end(args);
needrefresh = true;
this->refresh();
}
void NStaticText::refresh()
{
wbkgd(win,bgcolor);
std::list::iterator it;
werase(win);
wmove(win,0,0);
if (align == 1) //центрирование
{
wmove(win,0,(getwidth()/2)-(content->getlen()+1)/2);
}
if (align == 2) //правое
{
wmove(win,0,getwidth()-content->getlen()/*+1*/);
}
for (it = content->parts.begin(); it != content->parts.end(); it++) //цикл по частям тек строки
{
NColorStringPart* part = *it;
//kLogPrintf("[%d] %s\n", part->attr, part->s.c_str());
wattrset(win,part->attr);
wprintw(win,"%s",part->s.c_str());
//wattrset(win,0);
}
wbkgdset(win,bgcolor);
wclrtoeol(win); //очищаем до конца строки
NView::refresh();
}
boinctui-2.3.4/src/addmgrform.h 0000644 0000000 0000000 00000002726 12301564455 015130 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef ADDMGRFORM_H
#define ADDMGRFORM_H
#include
#include
#include "nform.h"
#include "nstatictext.h"
#include "srvdata.h"
class AddAccMgrForm : public NForm
{
public:
AddAccMgrForm(int lines, int rows, Srv* srv, const char* mgrname);
void genfields(int& line, Item* project); //создаст массив полей
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
int passwfield;
int errmsgfield;
int usernamefield;
Srv* srv;
std::string mgrname; //имя акк менеджера
std::string mgrurl; //url подключаемого менеджера
};
#endif //ADDMGRFORM_H boinctui-2.3.4/src/tuievent.h 0000644 0000000 0000000 00000007467 12301564455 014660 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef TUIEVENT_H
#define TUIEVENT_H
#include "srvdata.h"
#include "nevent.h"
enum TuiEventType
{
evCFGCH, //конфигурация изменена
evABORTRES, //abort selected result
evABOUT, //открыть/закрыть откно About
evKEYBIND, //открыть/закрыть откно Key Bindings
evBENCHMARK, //run benchmark
evADDPROJECT, //форма добавить проект
evCOLVIEWCH, //переключение видимости колонки
evVIEWMODECH, //переключение режима видимости All/Hide done/Active tasks only
evSORTMODECH, //переключение режима сортировки списка задач 0-unsorted 1-state e.t.c.
evADDACCMGR, //форма акк менеджера
evPROJECTOP, //операции над проектом
evTASKINFO, //генерируется когда нужно открыть окно детальной информации о задаче
evTASKSELECTORON, //генерируется когда селектор задач становится видимым
evTASKSELECTOROFF, //генерируется когда селектор задач становится скрытым
evASCIIMODECHANGE //генерируется при переключении режима ASCII рамок
};
class TuiEvent : public NEvent //класс программных событий специфичных для boinctui
{
public:
TuiEvent(TuiEventType type) : NEvent(evPROG, type) {};
TuiEvent(TuiEventType type, Srv* srv, const char* prjname, bool userexist) : NEvent(evPROG, type) //событие для добавления проекта
{
this->srv = srv;
this->sdata1 = prjname;
this->bdata1 = userexist;
};
TuiEvent(TuiEventType type, Srv* srv, const char* mgrname) : NEvent(evPROG, type) //событие для подключения к менеджеру
{
this->srv = srv;
this->sdata1 = mgrname;
};
TuiEvent(TuiEventType type, Srv* srv, const char* projname, const char* projop) : NEvent(evPROG, type) //событие для действий с проектами
{
this->srv = srv;
this->sdata1 = projname;
this->sdata2 = projop;
this->bdata1 = false; //true - если получено подтверждение
};
TuiEvent(TuiEventType type ,int ncolumn, bool enable) : NEvent(evPROG, type) //событие переключения видимости колонки
{
this->idata1 = ncolumn;
this->bdata1 = enable;
};
TuiEvent(TuiEventType type ,int mode) : NEvent(evPROG, type) //событие режим видимости задач
{
this->idata1 = mode;
};
virtual ~TuiEvent() { /*kLogPrintf("~TuiEvent()\n");*/ };
Srv* srv;
std::string sdata1; //произвольная строка
std::string sdata2; //произвольная строка
bool bdata1; //произаольная bool переменная
int idata1; //произвольное целое
};
#endif //TUIEVENT_H boinctui-2.3.4/src/mainprog.h 0000644 0000000 0000000 00000004064 12301564455 014617 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef MAINPROG_H
#define MAINPROG_H
#include "nprogram.h"
#include "msgwin.h"
#include "taskwin.h"
#include "mainwin.h"
#include "cfgform.h"
#include "cfg.h"
#include "srvdata.h"
#include "topmenu.h"
#include "about.h"
#include "helpwin.h"
#include "addprojectform.h"
#include "addmgrform.h"
#include "taskinfowin.h"
#define stUISELECTOR 1 //бит означающий что селектор задач включен
#define stUIMODALFORM 2 //бит означающий что активна модальная форма
#define stUITASKINFO 4 //бит означающий что активно окно и-и о задаче
class MainProg : public NProgram
{
public:
MainProg();
~MainProg();
void smartresize();
bool mainloop();
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
TopMenu* menu;
MainWin* wmain;
NStaticText* wstatus;
//Config* cfg;
SrvList* gsrvlist; //глобальный список серверов
bool done; //флаг требования завершения
// void setcaption();
time_t evtimertime; //time of last evTIMER
unsigned int uistate; //маска состояния интерфейса
void updatestatuslinecontent();
};
#endif //MAINPROG_H
boinctui-2.3.4/src/nselectlist.cpp 0000644 0000000 0000000 00000011123 12301564455 015661 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include "nselectlist.h"
#include "kclog.h"
void NSelectList::addstring(void* userobj, int attr, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
NColorString* cs = new NColorString(attr, fmt, args);
va_end(args);
NScrollView::addstring(cs);
objects.push_back(userobj);
}
void NSelectList::addstring(void* userobj, NColorString* cstring)
{
NScrollView::addstring(cstring);
objects.push_back(userobj);
}
void NSelectList::drawcontent() //отрисовывает буфер строк
{
//выводим строки начиная со startindex
for (int line = 0; line < getheight(); line++) //цикл по экранным строкам
{
if (startindex+line < content.size()) //цикл по строкам
{
NColorString* cstring = content[startindex + line];
std::list::iterator it;
wmove(win,line,0);
for (it = cstring->parts.begin(); it != cstring->parts.end(); it++) //цикл по частям тек строки
{
NColorStringPart* part = *it;
if ((!selectorenable)||(startindex + line != selectedindex)) //эта строка не выделена или селектор выключен
wattrset(win,part->attr); //включаем атрибут
else
{
//получаем из атрибута цвета для текста и фона
short f,b;
f = b = 0;
unsigned int a = 0;
a = a | (part->attr & A_BOLD); //нужен-ли аттрибут
pair_content(PAIR_NUMBER(part->attr),&f,&b); //цвета тек куска для пары с номером PAIR_NUMBER(part->attr)
//kLogPrintf("part->attr=%X PAIR_NUMBER(%X) -> #%d f=%x b=%x attr=%x\n",part->attr, part->attr,PAIR_NUMBER(part->attr),f,b,a);
//kLogPrintf("A_BOLD=%X\n",A_BOLD);
wattrset(win, getcolorpair(f, selectorbgcolor) | a); //включаем новый цвет и атрибут
}
wprintw(win,"%s",part->s.c_str());
} //цикл частей одной строки
//wattrset(win,0); //отключаем атрибут
//очищаем до конца строки
if ((!selectorenable)||(startindex + line != selectedindex))
wclrtoeol(win);
else
{
wbkgdset(win,getcolorpair(COLOR_WHITE,selectorbgcolor));
wclrtoeol(win); //очищаем до конца строки
wbkgdset(win,getcolorpair(COLOR_WHITE, COLOR_BLACK));
}
}
else //очищаем нижнюю незанятую часть окна (если есть)
{
wmove(win,line,0);
wclrtoeol(win); //очищаем до конца строки
}
}
if (scrollbar) //если есть связанный скроллбар то обновляем его
{
scrollbar->setpos(0,content.size(),startindex, startindex+getheight());
}
}
void NSelectList::refresh()
{
if (needrefresh)
{
drawcontent();
NView::refresh(); //Именно так!!!
}
}
void* NSelectList::getselectedobj()
{
if ((selectedindex >= 0)&&(selectedindex < objects.size()))
{
return objects[selectedindex];
}
else
return NULL;
}
void NSelectList::selectorup()
{
if (selectedindex >= 0)
{
selectedindex--;
needrefresh = true;
//проверяем не нужно ли скролить
if (selectedindex - startindex < 4) //видимых строк выше серлектора осталось
{
scrollto(-1);
}
}
}
void NSelectList::selectordown()
{
if (selectedindex < (int)content.size())
{
selectedindex++;
needrefresh = true;
//проверяем не нужно ли скролить
if ((startindex + getheight() < content.size())&&(startindex + getheight() - selectedindex < 4)) //видимых строк ниже серлектора осталось
{
scrollto(1);
}
}
}
boinctui-2.3.4/src/nscrollbar.h 0000644 0000000 0000000 00000003474 12301564455 015150 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013,2014 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NSCROLLBAR_H
#define NSCROLLBAR_H
#include "nview.h"
class NScrollBar : public NView
{
public:
NScrollBar(NRect rect, chtype chtop = 0, chtype chbottom = 0, chtype chinactive = ACS_VLINE);
virtual ~NScrollBar() { };
void setbgcolor(int colorpair) { bgcolor = colorpair; };
virtual void refresh();
void setpos(int vmin, int vmax, int vpos1, int vpos2);
void setvisible(bool value) { visible = value; };
protected:
int bgcolor; //цвет фона
chtype chtop; //символ вверху
chtype chbottom;//символ внизу
chtype chinactive; //символ которым заполняется когда неактивный
int vmin; //минимальное значение
int vmax; //максимальное значение
int vpos1; //минимальное видимое значение
int vpos2; //максимальное видимое значение
bool visible;//true если скроллер видимый
};
#endif //NSCROLLBAR_H boinctui-2.3.4/src/msgwin.cpp 0000644 0000000 0000000 00000010712 12301564455 014637 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "kclog.h"
#include "msgwin.h"
#include "net.h"
#include "resultparse.h"
void MsgWin::updatedata() //обновить данные с сервера
{
if (srv == NULL)
return;
if (srv->msgdom.empty())
{
clearcontent();
lastmsgno = 0;
return;
}
Item* tmpmsgdom = srv->msgdom.hookptr();
srv->msgdom.lock();
if (lastmsgno == srv->lastmsgno) //в srv есть новые еще не отрисованные сообщения?
{
srv->msgdom.unlock();
srv->msgdom.releaseptr(tmpmsgdom);
return;
}
// === дополняем массив визуальных строк ===
if (lastmsgno == 0)
clearcontent(); //очищаем если отображение идет с начала
Item* msgs = tmpmsgdom->findItem("msgs");
if (msgs != NULL)
{
std::vector
- mlist = msgs->getItems("msg");
std::vector
- ::iterator it;
for (it = mlist.begin(); it != mlist.end(); it++) //цикл по сообщениям
{
Item* number = (*it)->findItem("seqno"); //номер текущего сообщения
if (number->getivalue()<=lastmsgno)
continue; //пропускаем старые (уже добавленные ранее) сообщения
Item* body = (*it)->findItem("body"); //текст сообщения
Item* time = (*it)->findItem("time"); //время сообщения
if ((body != NULL)&&(time != NULL))
{
time_t t = time->getivalue(); //время в секундах от 1.1.1970
tm* ltime = localtime(&t);
char tbuf[128];
strftime(tbuf, sizeof(tbuf),"%-e %b %-k:%M",ltime);
Item* project = (*it)->findItem("project");
std::string sproject = "_no_";
if (project != NULL)
sproject = project->getsvalue();
addstring(getcolorpair(COLOR_CYAN,COLOR_BLACK) /*| A_BOLD*/,"#%d %s ", number->getivalue(), tbuf); //номер и время сообщения
content.back()->append(getcolorpair(COLOR_YELLOW,COLOR_BLACK),"%s",sproject.c_str()); //добавить имя проекта другим цветом
addstring(getcolorpair(COLOR_WHITE,COLOR_BLACK), "%s", body->getsvalue()); //само сообщение
}
}
}
lastmsgno = srv->lastmsgno;
//поскольку есть новые сообщения, то делаем автоскроллинг в конец
setautoscroll(true);
srv->msgdom.unlock();
srv->msgdom.releaseptr(tmpmsgdom);
}
void MsgWin::eventhandle(NEvent* ev) //обработчик событий
{
NScrollView::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_PPAGE:
//wprintw(win,"PgUp");
scrollto(-getheight()/2); //вверх на полокна
setautoscroll(false);
break;
case KEY_NPAGE:
//wprintw(win,"PgDn");
if (!getautoscroll())
{
int oldpos = startindex;
scrollto(getheight()/2); //вниз на пол окна
if ( oldpos == startindex) //позиция не изменилась (уже достигли конца)
setautoscroll(true); //включаем автоскроллинг
}
break;
case KEY_HOME:
scrollto(-content.size());
setautoscroll(false);
break;
case KEY_END:
scrollto(content.size());
setautoscroll(false);
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
if ( ev->type == NEvent::evTIMER )
{
updatedata(); //запросить данные с сервера
refresh(); //перерисовать окно
}
}
boinctui-2.3.4/src/net.cpp 0000644 0000000 0000000 00000010163 12301564455 014121 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "net.h"
#include "kclog.h"
void TConnect::createconnect(/*const char* shost, const char* sport*/)
{
kLogPrintf("connecting...");
//this->shost = strdup(shost);
//this->sport = strdup(sport);
struct sockaddr_in boincaddr;
//resolving
memset(&boincaddr,0, sizeof(boincaddr));
boincaddr.sin_family = AF_INET;
boincaddr.sin_port = htons(atoi(sport));
if (inet_aton(shost,&boincaddr.sin_addr) == 0) //в shost не ip адрес
{
struct hostent *hostp = gethostbyname(shost); //пытаемся отресолвить
if ( hostp == NULL )
kLogPrintf("host %s lookup failed\n",shost);
else
memcpy(&boincaddr.sin_addr, hostp->h_addr, sizeof(boincaddr.sin_addr));
}
int hsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//connection
if (connect(hsock, (struct sockaddr *) &boincaddr, sizeof(boincaddr)) < 0)
{
kLogPrintf("connect %s:%s failed!\n",shost,sport);
this->hsock = -1;
}
else
{
this->hsock = hsock;
kLogPrintf("OK\n");
}
}
void TConnect::disconnect()
{
kLogPrintf("disconnecting %s:%s ...",shost,sport);
if (hsock != -1)
close(hsock);
hsock = -1;
kLogPrintf("OK\n");
}
void TConnect::sendreq(const char* fmt, ...) //отправить запрос на сервер
{
va_list args;
va_start(args, fmt);
sendreq(fmt,args);
va_end(args);
}
void TConnect::sendreq(const char* fmt, va_list vl) //отправить запрос на сервер
{
//формируем строку запроса
char req[1024];
vsnprintf(req, sizeof(req), fmt, vl);
//kLogPrintf("[%s]\n",req);
//конектимся (если соединения еще нет)
if (hsock == -1)
createconnect(/*shost,sport*/);
//отправляем запрос
if (send(hsock, req, strlen(req), 0) != strlen(req))
{
kLogPrintf("send request %s:%s error\n",shost,sport);
disconnect();
}
}
char* TConnect::waitresult() //получить ответ от сервера (потом нужно освобождать память извне)
{
if (hsock == -1)
createconnect(/*shost,sport*/);
//чтение частями из сокета
char* answbuf = NULL;
int totalBytesRcvd = 0;
int answbuflen = 0;
char bufpart[1024]; //фрагмент
int bytesRcvd;
do
{
if ((bytesRcvd = recv(hsock, bufpart, sizeof(bufpart), 0)) <= 0 )
{
kLogPrintf("recv fail %s:%s\n",shost,sport);
disconnect();
return NULL;
}
else
//printf("allbytes= %d received %d bytes\n",totalBytesRcvd,bytesRcvd);
//копируем в суммарный буфер
answbuflen = answbuflen+bytesRcvd;
answbuf = (char*)realloc(answbuf,answbuflen);
memcpy(&answbuf[totalBytesRcvd], bufpart, bytesRcvd);
totalBytesRcvd += bytesRcvd;
if (answbuf[totalBytesRcvd-1] == '\003')
{
answbuf = (char*)realloc(answbuf,answbuflen + 1);
answbuf[totalBytesRcvd-1] = '\0'; //003 -> 0
answbuf[totalBytesRcvd] = '\0'; //терминирующий 0
break;
}
}
while (true);
// printf("'%s' \nlen=%d\n", answbuf, strlen(answbuf));
return answbuf;
}
boinctui-2.3.4/src/taskwin.h 0000644 0000000 0000000 00000004756 12301564455 014473 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef TASKWIN_H
#define TASKWIN_H
#include "nselectlist.h"
#include "resultdom.h"
#include "srvdata.h"
struct TaskInfo
{
TaskInfo(const char* taskname, const char* projecturl) {this->taskname = taskname; this->projecturl = projecturl; };
std::string taskname;
std::string projecturl;
};
class TaskWin : public NSelectList
{
public:
TaskWin(NRect rect/*, Config* cfg*/);
virtual ~TaskWin();
void updatedata(); //обновить данные с серверa
virtual void clearcontent();
virtual void eventhandle(NEvent* ev); //обработчик событий
void* setserver(Srv* srv) { this->srv = srv; startindex = 0; clearcontent(); selectedindex = -1; };
bool iscolvisible(int n) { return ((1 << n)&columnmask); }; //true если n-ная колонка видимая
void coldisable(int n) { columnmask = columnmask & (~(1 << n)); saveopttoconfig();}; //установить флаг невидимости n-ной колонки
void colenable(int n) { columnmask = columnmask | (1 << n); saveopttoconfig();}; //установить флаг видимости n-ной колонки
void saveopttoconfig(); //сохранить маску и т.д. в дереве конфига
//unsigned int getcolumnmask() { return columnmask; };
protected:
Srv* srv; //текущий отображаемый сервер
unsigned int columnmask; //маска видмсости колонок
int taskslistmode; //0 все задачи 1 кроме завершенных 2 только активные
int taskssortmode; //0 нет сортировки 1 state 2 done 3 project 4 est 5 d/l 6 app 7 task
// Config* cfg;
};
#endif //TASKWIN_H
boinctui-2.3.4/src/srvdata.cpp 0000644 0000000 0000000 00000072445 12301564455 015012 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#ifdef HAVE_OPENSSL
#include
#else
#include
#endif
#include
#include "srvdata.h"
#include "resultparse.h"
#include "kclog.h"
#define STATE_TIME_INTERVAL 2 //интервал в секундах между запросами
#define MSG_TIME_INTERVAL 2 //интервал в секундах между запросами
#define DISKUSAGE_TIME_INTERVAL 60 //интервал в секундах между запросами
#define STATISTICS_TIME_INTERVAL 300 //интервал в секундах между запросами
#define CCSTATUS_TIME_INTERVAL 600 //интервал в секундах между запросами
const int ERR_IN_PROGRESS = -204;
const int BOINC_SUCCESS = 0;
//=============================================================================================
PtrList::~PtrList()
{
kLogPrintf("PtrList::~PtrList() list.size()=%d\n",list.size());
while(!list.empty())
{
delete list.front();
list.erase(list.begin());
}
pthread_mutex_destroy(&mutex);
}
Item* PtrList::hookptr() //получить указатель из хвоста списка
{
Item* result = NULL;
pthread_mutex_lock(&mutex);
if (!list.empty())
{
list.back()->refcount++;
result = list.back()->dom;
}
pthread_mutex_unlock(&mutex);
return result;
}
void PtrList::releaseptr(Item* ptr) //сообщить списку что указатель больше не нужен (список сам решит нужно ли его удалять)
{
std::list::iterator it;
pthread_mutex_lock(&mutex);
//ищем элемент связанный с ptr
for( it = list.begin(); it != list.end(); it++)
{
if ( (*it)->dom == ptr) //нашли
{
(*it)->refcount--; //уменьшаем счетчик ссылок
}
}
//очищаем старые ненужные эл-ты
bool done;
do
{
done = true;
for( it = list.begin(); it != list.end(); it++)
{
if ( ((*it) != list.back()) && ((*it)->refcount <= 0) ) //нашли (последний не трогаем)
{
delete (*it)->dom;
delete (*it);
list.erase(it);
done = false;
break;
}
}
}
while (!done);
pthread_mutex_unlock(&mutex);
}
//=============================================================================================
bool daily_statisticsCmpAbove( Item* stat1, Item* stat2 ) //для сортировки статистики true если дата stat1 > stat2
{
Item* day1 = stat1->findItem("day");
Item* day2 = stat2->findItem("day");
if ( (day1 != NULL)&&(day2 != NULL) )
{
if (day1->getdvalue() > day2->getdvalue())
return true;
else
return false;
}
return false;
}
//=============================================================================================
SrvList::SrvList(/*Config* cfg*/)
{
// this->cfg = cfg;
refreshcfg();
}
SrvList::~SrvList()
{
clear();
}
void SrvList::refreshcfg() //перечитать из конфига
{
clear(); //удаляем старые сервера (если есть)
Item* boinctui_cfg = gCfg->getcfgptr();
if (boinctui_cfg == NULL)
return;
std::vector- slist = boinctui_cfg->getItems("server");
std::vector
- ::iterator it;
for (it = slist.begin(); it != slist.end(); it++)
{
Item* host = (*it)->findItem("host");
Item* port = (*it)->findItem("port");
Item* pwd = (*it)->findItem("pwd");
if ((host != NULL)&&(port != NULL))
{
if (pwd == NULL)
servers.push_back(new Srv(host->getsvalue(), port->getsvalue(), ""));
else
servers.push_back(new Srv(host->getsvalue(), port->getsvalue(), pwd->getsvalue()));
}
}
if (!servers.empty())
{
cursrv = servers.begin();
(*cursrv)->setactive(true);
}
}
void SrvList::clear() //удалить все соединения
{
std::list::iterator it;
cursrv = servers.begin();
for (it = servers.begin(); it != servers.end(); it++) //чистим все соединения
{
delete (*it);
}
servers.clear();
}
void SrvList::nextserver() //переключиться на след сервер в списке
{
(*cursrv)->setactive(false); //деактивируем тред
cursrv++;
if (cursrv == servers.end()) //дошли до конца переходим в начало списка
cursrv = servers.begin();
(*cursrv)->setactive(true); //активиркем тред
}
//=============================================================================================
Srv::Srv(const char* shost, const char* sport, const char* pwd) : TConnect(shost, sport)
{
allprojectsdom = NULL;
this->pwd = strdup(pwd);
lastmsgno = 0;
active = false;
loginfail = false;
ccstatusdomneedupdate = false;
pthread_mutex_init(&mutex, NULL);
}
Srv::~Srv()
{
setactive(false); //завершаем опросный тред (если он есть)
pthread_join(thread, NULL); //ждем пока тред остановится
if (allprojectsdom != NULL) delete allprojectsdom;
if (pwd != NULL) delete pwd;
pthread_mutex_destroy(&mutex);
}
Item* Srv::req(const char* fmt, ...) //выполнить запрос (вернет дерево или NULL)
{
if (hsock == -1)
createconnect();
if (hsock == -1)
return NULL;
// === посылаем запрос ===
char req[1024];
strcpy(req, "\n");
strcat(req, fmt);
strcat(req, "\n\n\003");
va_list args;
lock();
va_start(args, fmt);
sendreq(req, args);
va_end(args);
char* result = waitresult();
unlock();
if (result != NULL) //получен ответ
{
// === отрезаем теги
const char* teg1 = "";
const char* teg2 = "";
char* b = strstr(result,teg1);
char* e = strstr(result,teg2);
if (( b == NULL)||( e == NULL))
{
free(result);
return NULL;
}
*e = '\0';
b = b + strlen(teg1);
while ( (*b != '\0')&&(*b != '<') )
b++; //отрезаем лидирующие переводы строки и т.д.
// === костыль ТОЛЬКО для
if (strstr(fmt, "") != NULL)
b = (char*)stripinvalidtag(b, strlen(b)); //убираем кривые теги
// === разбираем ответ ===
lock();
Item* dom = xmlparse(b, strlen(b)); //парсим xml
unlock();
free(result); //рез-т в тесктовом виде больше не нужен
return dom;
}
else
return NULL;
}
void Srv::createconnect()
{
lock();
TConnect::createconnect();
unlock();
loginfail = false;
if (hsock != -1)
loginfail = login();
}
bool Srv::login() //авторизоваться на сервере
{
bool result = false;
// if (strlen(pwd) == 0)
// return true; //пароль не задан (считаем что логин серверу не требуется)
//получить случайную строку (nonce)
Item* r1 = req("");
if (r1 == NULL)
return result;
kLogPrintf("login() nonce='%s'\n", r1->toxmlstring().c_str());
Item* nonce = r1->findItem("nonce");
if ( nonce == NULL )
{
delete r1;
return result;
}
const char* snonce = r1->findItem("nonce")->getsvalue();
//расчитать хэш md5 от nonce+pwd
unsigned char md5digest[MD5_DIGEST_LENGTH];
MD5_CTX c;
MD5_Init(&c);
MD5_Update(&c, snonce, strlen(snonce));
MD5_Update(&c, pwd , strlen(pwd));
MD5_Final(md5digest,&c);
char shash[1024]; //строковое представление хэша
for (int i=0;i\n%s\n",shash);
kLogPrintf("login() Boinc answer ---\n%s\n", r2->toxmlstring().c_str());
if ( r2->findItem("unauthorized") != NULL ) //авторизация неуспешна
result = true;
delete r2;
return result;
}
void Srv::updatestatistics()
{
statisticsdom.addptr(req(""));
}
void Srv::updateccstatus() //обновить состояние
{
ccstatusdom.addptr(req(""));
}
void Srv::updatediskusage()
{
dusagedom.addptr(req(""));
}
void Srv::updatestate()
{
statedom.addptr(req(""));
}
void Srv::updatemsgs() //обновить сообщения
{
Item* domtree1 = req("");
if (domtree1 == NULL)
return;
Item* seqno = domtree1->findItem("seqno");
if (seqno == NULL)
{
delete domtree1;
return;
}
int curseqno = seqno->getivalue(); //кол-во сообщений на сервере в тек. момент
delete domtree1;
if (curseqno == lastmsgno) //если с прошлого вызова updatedata() новых сообщений нет, то просто выходим
return;
// === запрашиваем содержимое сообщений начиная с lastmsg сервере ===
char req2[256];
int msgno; //номер первого запрашиваемого сообщения
if (lastmsgno>0)
msgno = lastmsgno; //запрашиваем начиная с последнего отображенного
else
msgno = 0; //начинаем с первого
snprintf(req2,sizeof(req2),"\n%d\n",msgno);
Item* domtree = req(req2);
if (domtree == NULL)
return;
// === дополняем массив визуальных строк ===
if (!msgdom.empty()) //если есть ранее полученные сообщения
{
Item* tmpmsgdom = msgdom.hookptr();
//объединяем ветку "msgs" новых сообщений с основным деревом (msgdom)
msgdom.lock();
(tmpmsgdom->findItem("msgs"))->mergetree(domtree->findItem("msgs"));
msgdom.unlock();
delete domtree; //очищаем рез-т
msgdom.releaseptr(tmpmsgdom);
}
else
msgdom.addptr(domtree);
lastmsgno = curseqno;
}
void Srv::updateallprojects()
{
if (allprojectsdom != NULL)
delete allprojectsdom; //очищаем предыдущий рез-т
allprojectsdom = req("");
}
void Srv::updateacctmgrinfo()//обновить статистику
{
acctmgrinfodom.addptr(req(""));
}
void Srv::opactivity(const char* op) //изменение режима активности BOINC сервера "always" "auto" "newer"
{
Item* d = req("<%s/>0",op);
if (d != NULL)
delete d;
ccstatusdomneedupdate = true;
}
void Srv::opnetactivity(const char* op) //изменение режима активности сети "always" "auto" "newer"
{
Item* d = req("<%s/>0",op);
if (d != NULL)
delete d;
ccstatusdomneedupdate = true;
}
void Srv::opgpuactivity(const char* op) //изменение режима активности GPU "always" "auto" "newer"
{
Item* d = req("<%s/>0",op);
if (d != NULL)
delete d;
ccstatusdomneedupdate = true;
}
void Srv::optask(const char* url, const char* name, const char* op) //действия над задачей ("suspend_result",...)
{
Item* d = req("<%s>\n%s\n%s\n%s>",op,url,name,op);
if (d != NULL)
delete d;
}
void Srv::opproject(const char* name, const char* op) //действия над проектом ("project_suspend","project_resume",...)
{
if (statedom.empty())
return;
Item* tmpdom = statedom.hookptr();
std::string url = findProjectUrl(tmpdom,name);
Item* d = req("<%s>\n%s\n%s>",op,url.c_str(),op);
statedom.releaseptr(tmpdom);
if (d != NULL)
delete d;
}
void Srv::runbenchmarks() //запустить бенчмарк
{
Item* d = req("");
if (d != NULL)
delete d;
}
bool Srv::getprojectconfig(const char* url, std::string& errmsg) //получить c сервера файл конфигурации
{
//запрос на начало передачи
Item* res = req("\n%s\n", url);
if (res == NULL)
return false;
kLogPrintf("request=\n ?\n\n answer=\n%s\n", res->toxmlstring().c_str());
free(res);
//ждем завершения
bool done = false;
int count = 30; //не больше 30 запросов
do
{
res = req("");
if (res == NULL)
return false;
kLogPrintf("request=\n ?\n\n answer=\n%s\n", res->toxmlstring().c_str());
Item* error_num = res->findItem("error_num");
if (error_num != NULL)
{
int errnum = error_num->getivalue();
if (errnum == ERR_IN_PROGRESS) //ждать?
sleep(1); //ERR_IN_PROGRESS ждем 1 сек
else
{
free(res);
break;
}
}
else
{
Item* project_config = res->findItem("project_config");
if (project_config != NULL)
done = true;
else
{
free(res);
break;
}
}
free(res);
}
while((count--)&&(!done));
return done;
}
bool Srv::createaccount(const char* url, const char* email, const char* pass, const char* username, const char* teamname, std::string& errmsg) //создать аккаунт
{
kLogPrintf("createaccount(url=%s, email=%s, pass=%s, username=%s, teamname=%s)\n", url, email, pass, username, teamname);
//расчитать хэш md5 от pass+email
unsigned char md5digest[MD5_DIGEST_LENGTH];
MD5_CTX c;
MD5_Init(&c);
MD5_Update(&c, pass , strlen(pass));
MD5_Update(&c, email, strlen(email));
MD5_Final(md5digest,&c);
char shash[1024]; //строковое представление хэша
for (int i=0;i\n"
" %s\n"
" %s\n"
" %s\n"
" %s\n"
" %s\n"
"\n",
url,email,shash,username,teamname);
Item* res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
free(res);
//ждем завершения
int count = 30; //не больше 30 запросов
snprintf(sreq,sizeof(sreq),"");
bool done = false;
do
{
res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
Item* error_num = res->findItem("error_num");
if ((error_num != NULL)&&(error_num->getivalue() != ERR_IN_PROGRESS))
{
Item* error_msg = res->findItem("error_msg");
if (error_msg != NULL)
errmsg = error_msg->getsvalue(); //возврат строки ошибки
return false;
}
if (res->findItem("authenticator") != NULL)
done = true;
free(res);
sleep(1); //ждем 1 сек
}
while((count--)&&(!done));
return true;
}
bool Srv::projectattach(const char* url, const char* prjname, const char* email, const char* pass, std::string& errmsg) //подключить проект
{
//расчитать хэш md5 от pass+email
unsigned char md5digest[MD5_DIGEST_LENGTH];
MD5_CTX c;
MD5_Init(&c);
MD5_Update(&c, pass , strlen(pass));
MD5_Update(&c, email, strlen(email));
MD5_Final(md5digest,&c);
char shash[1024]; //строковое представление хэша
for (int i=0;i\n%s\n%s\n%s\n\n",url,email,shash);
Item* res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
free(res);
int count = 30; //не больше 30 запросов
snprintf(sreq,sizeof(sreq),"");
std::string sauthenticator;
bool done = false;
do
{
res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
Item* error_num = res->findItem("error_num");
if ((error_num != NULL)&&(error_num->getivalue() != ERR_IN_PROGRESS))
{
Item* error_msg = res->findItem("error_msg");
if (error_msg != NULL)
errmsg = error_msg->getsvalue(); //возврат строки ошибки
return false;
}
Item* authenticator = res->findItem("authenticator");
if (authenticator != NULL)
{
sauthenticator = authenticator->getsvalue();
done = true;
}
free(res);
sleep(1); //ждем 1 сек
}
while((count--)&&(!done));
if (!done)
return false;
//формируем запрос для подключения к проекту
snprintf(sreq,sizeof(sreq),"\n%s\n%s\n%s\n\n",url,sauthenticator.c_str(),prjname);
res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
bool result = (res->findItem("success") != NULL);
free(res);
return result;
}
bool Srv::accountmanager(const char* url, const char* username, const char* pass, bool useconfigfile, std::string& errmsg) //подключить аккаунт менеджер
{
if (strlen(url) > 0)
{
//получить конфиг (не знаю зачем!!!)
if (!getprojectconfig(url,errmsg))
{
errmsg = "Can't get config";
return false;
}
}
char sreq[1024];
//формируем запрос
if (useconfigfile)
snprintf(sreq,sizeof(sreq),"\n\n\n");
else
snprintf(sreq,sizeof(sreq),"\n%s\n%s\n%s\n\n",url,username,pass);
Item* res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
//ждем завершения
snprintf(sreq,sizeof(sreq),"");
bool done = false;
int count = 30; //не больше 30 запросов
do
{
res = req(sreq);
if (res == NULL)
return false;
kLogPrintf("request=\n %s\n\n answer=\n%s\n",sreq, res->toxmlstring().c_str());
Item* error_num = res->findItem("error_num");
if (error_num != NULL)
{
int errnum = error_num->getivalue();
if (errnum == BOINC_SUCCESS) //успешно
done = true;
else
if (errnum != ERR_IN_PROGRESS) //ошибка выходим
{
Item* message = res->findItem("message");
if (message != NULL)
errmsg = message->getsvalue(); //возврат строки ошибки
free(res);
return false;
}
else
sleep(1); //ERR_IN_PROGRESS ждем 1 сек
}
free(res);
}
while((count--)&&(!done));
acctmgrinfodom.needupdate = true; //чтобы тред обновил данные
sleep(1); //даем треду 1 сек на обновление
kLogPrintf("RET %b\n",done);
return done;
}
std::string Srv::findProjectName(Item* tree, const char* url) //найти в дереве tree имя проекта с заданным url
{
Item* client_state = tree->findItem("client_state");
if (client_state == NULL)
return "ERR2";
std::vector
- projects = client_state->getItems("project"); //список проектов
std::vector
- ::iterator it;
for (it = projects.begin(); it!=projects.end(); it++)
{
Item* master_url = (*it)->findItem("master_url");
if ( strcmp(url,master_url->getsvalue()) == 0 ) //url совпали НАШЛИ!
{
Item* project_name = (*it)->findItem("project_name");
return project_name->getsvalue();
}
}
return "???";
}
std::string Srv::findProjectUrl(Item* tree, const char* name) //найти в дереве tree url проекта с заданным именем
{
Item* client_state = tree->findItem("client_state");
if (client_state == NULL)
return "ERR2";
std::vector
- projects = client_state->getItems("project"); //список проектов
std::vector
- ::iterator it;
for (it = projects.begin(); it!=projects.end(); it++)
{
Item* project_name = (*it)->findItem("project_name");
if ( strcmp(name, project_name->getsvalue()) == 0 ) //имена совпали НАШЛИ!
{
Item* master_url = (*it)->findItem("master_url");
return master_url->getsvalue();
}
}
return "";
}
Item* Srv::findresultbyname(const char* resultname)
{
if (statedom.empty())
return NULL;
if (resultname == NULL)
return NULL;
Item* tmpstatedom = statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
if (client_state == NULL)
{
statedom.releaseptr(tmpstatedom);
return NULL;
}
std::vector
- results = client_state->getItems("result"); //список задач
std::vector
- ::iterator it;
for (it = results.begin(); it!=results.end(); it++)
{
Item* name = (*it)->findItem("name");
if ( strcmp(resultname,name->getsvalue()) == 0 ) //имена совпали НАШЛИ!
{
statedom.releaseptr(tmpstatedom);
return (*it);
}
}
statedom.releaseptr(tmpstatedom);
return NULL;
}
Item* Srv::findprojectbyname(const char* projectname)
{
if (statedom.empty())
return NULL;
if (projectname == NULL)
return NULL;
Item* tmpstatedom = statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
if (client_state == NULL)
{
statedom.releaseptr(tmpstatedom);
return NULL;
}
std::vector
- projects = client_state->getItems("project"); //список проектов
std::vector
- ::iterator it;
for (it = projects.begin(); it!=projects.end(); it++)
{
Item* name = (*it)->findItem("project_name");
if ( strcmp(projectname,name->getsvalue()) == 0 ) //имена совпали НАШЛИ!
{
statedom.releaseptr(tmpstatedom);
return (*it);
}
}
statedom.releaseptr(tmpstatedom);
return NULL;
}
Item* Srv::findprojectbynamefromall(const char* projectname) //ищет в allprojectsdom
{
if (allprojectsdom == NULL)
return NULL;
if (projectname == NULL)
return NULL;
Item* projects = allprojectsdom->findItem("projects");
if (projects == NULL)
return NULL;
std::vector
- projectlist = projects->getItems("project"); //список проектов
std::vector
- ::iterator it;
for (it = projectlist.begin(); it!=projectlist.end(); it++)
{
Item* name = (*it)->findItem("name");
if ( strcmp(projectname,name->getsvalue()) == 0 ) //имена совпали НАШЛИ!
{
return (*it);
}
}
return NULL;
}
Item* Srv::findaccountmanager(const char* mgrname) //ищет менеджер по имени
{
if (allprojectsdom == NULL)
return NULL;
if (mgrname == NULL)
return NULL;
Item* projects = allprojectsdom->findItem("projects");
if (projects == NULL)
return NULL;
std::vector
- mgrlist = projects->getItems("account_manager"); //список менеджеров
std::vector
- ::iterator it;
for (it = mgrlist.begin(); it!=mgrlist.end(); it++)
{
Item* name = (*it)->findItem("name");
if ( strcmp(mgrname,name->getsvalue()) == 0 ) //имена совпали НАШЛИ!
{
return (*it);
}
}
return NULL;
}
Item* Srv::findappbywuname(const char* wuname) //найти приложение для данного WU
{
if (statedom.empty())
return NULL;
if (wuname == NULL)
return NULL;
Item* tmpstatedom = statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
if (client_state == NULL)
{
statedom.releaseptr(tmpstatedom);
return NULL;
}
std::vector
- wulist = client_state->getItems("workunit"); //список WU
std::vector
- ::iterator it;
//ищем WU
for (it = wulist.begin(); it!=wulist.end(); it++)
{
Item* name = (*it)->findItem("name");
if ( strcmp(wuname,name->getsvalue()) == 0 ) //имена совпали НАШЛИ WU!
{
Item* app_name = (*it)->findItem("app_name");
std::vector
- applist = client_state->getItems("app"); //список APP
std::vector
- ::iterator it2;
for (it2 = applist.begin(); it2!=applist.end(); it2++)
{
Item* name = (*it2)->findItem("name");
if ( strcmp(app_name->getsvalue(),name->getsvalue()) == 0 ) //имена совпали НАШЛИ APP!
{
statedom.releaseptr(tmpstatedom);
return (*it2);
}
}
}
}
statedom.releaseptr(tmpstatedom);
return NULL;
}
time_t Srv::getlaststattime() //вернет время последней имеющейся статистики
{
time_t result = 0;
if (statisticsdom.empty())
return 0;
Item* tmpstatisticsdom = statisticsdom.hookptr();
Item* statistics = tmpstatisticsdom->findItem("statistics");
if (statistics!=NULL)
{
std::vector
- project_statistics = statistics->getItems("project_statistics");
std::vector
- ::iterator it;
for (it = project_statistics.begin(); it!=project_statistics.end(); it++) //цикл списка проектов
{
std::vector
- daily_statistics = (*it)->getItems("daily_statistics"); //все дни проекта в этом векторе
if (!daily_statistics.empty())
{
std::sort(daily_statistics.begin(), daily_statistics.end(), daily_statisticsCmpAbove); //сортируем по убыванию дат
Item* lastday = daily_statistics.front(); //последний день должен быть сверху
double d = lastday->findItem("day")->getdvalue();
if (d > result)
result = d;
}
} //проекты
}
statisticsdom.releaseptr(tmpstatisticsdom);
return result;
}
time_t Srv::gettimeelapsed(time_t t) //вернет соличество секунд между t и тек. временем
{
return (time(NULL) - t);
}
void* Srv::updatethread(void* args) //трейд опрашивающий сервер
{
Srv* me = (Srv*)args;
kLogPrintf("%s:%s::updatethread() started\n",me->gethost(),me->getport());
me->takt = 0;
while(me->active)
{
//get data from remote server
if ( me->statedom.empty() || ( (me->takt % STATE_TIME_INTERVAL) == 0 ) )
me->updatestate(); //
if (me->isconnected()&&(!me->loginfail)) //если нет коннекта то пропускаем прочие запросы
{
if ( me->msgdom.empty() || ( (me->takt % MSG_TIME_INTERVAL) == 0 ) )
me->updatemsgs(); ///
if ( me->statisticsdom.empty() || ( (me->takt % STATISTICS_TIME_INTERVAL) == 0 ) )
me->updatestatistics(); //
if ( me->dusagedom.empty() || ( (me->takt % DISKUSAGE_TIME_INTERVAL) == 0 ) )
me->updatediskusage(); //
if ( me->ccstatusdom.empty() || ( (me->takt % CCSTATUS_TIME_INTERVAL) == 0 ) || me->ccstatusdomneedupdate )
{
me->updateccstatus(); //
me->ccstatusdomneedupdate = false;
}
if (me->acctmgrinfodom.needupdate)
me->updateacctmgrinfo(); //ин-я по аккаунт менеджеру
}
//спим 1 секунду проверяя me->ccstatusdomneedupdate
for (int i = 0; i < 10; i++)
{
usleep(100000); //100 milisec
if (me->ccstatusdomneedupdate)
break; //прервать сон если нужен срочный апдейт
}
me->takt++;
}
kLogPrintf("%s:%s::updatethread() stoped\n",me->gethost(),me->getport());
return NULL;
}
void Srv::setactive(bool b) //включить/выключить тред обновления данных
{
if (isactive() != b)
if (b)
{
active = true;
if ( 0 != pthread_create(&thread, NULL, updatethread, this))
kLogPrintf("pthread_create() error\n");
}
else
{
active = false; //сигнализирует треду остановиться
}
}
boinctui-2.3.4/src/mainwin.h 0000644 0000000 0000000 00000004272 12301564455 014446 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef MAINWIN_H
#define MAINWIN_H
#include "ngroup.h"
#include "taskwin.h"
#include "msgwin.h"
#include "nstatictext.h"
#include "nhline.h"
#include "nvline.h"
#include "nscrollbar.h"
#include "infopanel.h"
#include "srvdata.h"
class MainWin : public NGroup
{
public:
MainWin(NRect rect/*, Config* cfg*/);
virtual void refresh();
virtual void resize(int rows, int cols);
void setserver(Srv* srv); //установить отображаемый сервер
// virtual void move(int begrow, int begcol);
virtual void eventhandle(NEvent* ev); //обработчик событий
TaskWin* wtask; //окно задач
MsgWin* wmsg; //окно эвентов
NStaticText* tablheader; //заголовок таблицы процессов
NScrollBar* msgscrollbar; //скроллбар панели сообщений
NScrollBar* taskscrollbar; //скроллбар панели задач
InfoPanel* panel1; //инф-ная панель
NColorString* caption; //строка заголовка
void updatecaption();
protected:
Srv* srv;
NHLine* hline; //гориз линия завершающая таблицу процессов
NVLine* vline; //верт линия отделяющая инф панель
std::vector colname; //список названий колонок
void setcoltitle();
};
#endif //MAINWIN_H boinctui-2.3.4/src/nscrollview.cpp 0000644 0000000 0000000 00000014616 12301564455 015711 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "nscrollview.h"
NScrollView::~NScrollView()
{
clearcontent();
}
void NScrollView::addstring(int attr, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
NColorString* cs = new NColorString(attr, fmt, args);
va_end(args);
addstring(cs);
}
void NScrollView::clearcontent()
{
std::vector::iterator it;
for (it = content.begin(); it != content.end(); it++)
{
delete (*it);
}
content.clear();
startindex=0;
needrefresh = true;
}
void NScrollView::drawcontent() //отрисовывает буфер строк
{
//выводим строки начиная со startindex
for (int line = 0; line < getheight(); line++) //цикл по экранным строкам
{
if (startindex+line < content.size())
{
NColorString* cstring = content[startindex + line];
std::list::iterator it;
wmove(win,line,0);
for (it = cstring->parts.begin(); it != cstring->parts.end(); it++) //цикл по частям тек строки
{
NColorStringPart* part = *it;
wattrset(win,part->attr); //включаем атрибут
wprintw(win,"%s",part->s.c_str());
// wattrset(win,0); //отключаем атрибут
}
wclrtoeol(win); //очищаем до конца строки
}
else //очищаем нижнюю незанятую часть окна (если есть)
{
wmove(win,line,0);
wclrtoeol(win); //очищаем до конца строки
}
}
if (scrollbar) //если есть связанный скроллбар то обновляем его
{
scrollbar->setpos(0,content.size(),startindex, startindex+getheight());
}
}
void NScrollView::refresh()
{
if (needrefresh)
{
drawcontent();
NView::refresh();
}
}
void NScrollView::resize(int rows, int cols)
{
NView::resize(rows, cols);
if (autoscroll)
{
setautoscroll(true); //костыль чтобы при ресайзе переустановилась позиция при автоскроле
}
}
void NScrollView::scrollto(int delta)//сдвинуть отображение на drlta строк вверх или вниз
{
int oldstartindex = startindex;
startindex = startindex + delta;
if ( startindex < 0 )
startindex = 0;
if ( startindex > content.size()-getheight() )
startindex = content.size()-getheight()/* + 1*/; //+1 чтобы оставлять пустую строку
if (oldstartindex != startindex) //позиция изменилась нужно перерисовываться
needrefresh = true;
};
void NScrollView::setautoscroll(bool b) //true чтобы включить автоскроллинг
{
int oldstartindex = startindex;
autoscroll = b;
if (b)
startindex = content.size()-getheight();
if (oldstartindex != startindex) //позиция изменилась нужно перерисовываться
needrefresh = true;
};
void NScrollView::setstartindex(int n) //установить отображение со строки n
{
if ((content.size()-n) < getheight()) //последняя строка видима на экране
{
startindex = content.size()-getheight(); //поднять вверх
if (startindex < 0) //но не выше нулевой
startindex = 0;
}
else
startindex = n;
}
void NScrollView::eventhandle(NEvent* ev) //обработчик событий
{
NView::eventhandle(ev); //предок
if ( ev->done )
return;
//реакция на мышь
NMouseEvent* mevent = (NMouseEvent*)ev;
if ( ev->type == NEvent::evMOUSE )
{
//скроллинг по колесу
if (isinside(mevent->row, mevent->col))
{
//колесо вверх
#if NCURSES_MOUSE_VERSION > 1
if (mevent->cmdcode & BUTTON4_PRESSED) //NOT TESTED
#else
if (mevent->cmdcode & BUTTON4_PRESSED)
#endif
{
scrollto(-getheight()/2); //вверх на полокна
setautoscroll(false);
ev->done = true;
}
//колесо вниз
#if NCURSES_MOUSE_VERSION > 1
if (mevent->cmdcode & BUTTON5_PRESSED) //NOT TESTED
#else
if ( mevent->cmdcode & (BUTTON2_PRESSED | REPORT_MOUSE_POSITION)) //REPORT_MOUSE_POSITION подпорка иначе теряет эвенты при быстрой прокрутке вниз
#endif
{
if (!getautoscroll())
{
int oldpos = getstartindex();
scrollto(getheight()/2); //вниз на пол окна
if ( oldpos == getstartindex()) //позиция не изменилась (уже достигли конца)
setautoscroll(true); //включаем автоскроллинг
ev->done = true;
}
}
}
}
//клавиатура
/*
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_PPAGE:
content->scrollto(-getheight()/2); //вверх на полокна
content->setautoscroll(false);
break;
case KEY_NPAGE:
if (!content->getautoscroll())
{
int oldpos = content->getstartindex();
content->scrollto(getheight()/2); //вниз на пол окна
if ( oldpos == content->getstartindex()) //позиция не изменилась (уже достигли конца)
content->setautoscroll(true); //включаем автоскроллинг
}
break;
default:
//блокировать все клавиатурные кроме кода закрытия формы
if (ev->keycode == 27)
ev->done = false;
} //switch
}
*/
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
boinctui-2.3.4/src/cfgform.cpp 0000644 0000000 0000000 00000015165 12301564455 014765 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "cfgform.h"
#include "mbstring.h"
#include "kclog.h"
#include "tuievent.h"
CfgForm::CfgForm(int rows, int cols/*, Config* cfg*/) : NForm(rows,cols)
{
genfields(false);
set_form_fields(frm, fields);
post_form(frm);
}
void CfgForm::genfields(bool extfields) //создаст массив полей (extfields если нужно добавить хост)
{
delfields();
this->extfields = extfields;
//читаем из конфига
Item* boinctui_cfg = gCfg->getcfgptr();
if (boinctui_cfg == NULL)
return;
std::vector
- slist = boinctui_cfg->getItems("server");
if (slist.empty())
extfields = true;
//поля ввода для серверов
nhost = slist.size(); //число хостов
if (extfields)
nhost++; //новый добавочный хост
std::vector
- ::iterator it;
int i = 0; //номер хоста
int nl = 2; //номер экранной строки
//статический заголовок полей хостов
FIELD* field = addfield(new_field(1, 44, nl, 5, 0, 0));
field_opts_off(field, O_ACTIVE); //статический текст
set_field_buffer(field, 0, "host port pwd");
set_field_back(field, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
nl = nl + 1;
//поля для хостов
for (i = 0; i < nhost; i++) //цикл по хостам
{
//поле для хоста
field = addfield(new_field(1, 15, nl, 5, 0, 0));
set_field_back(field, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
field_opts_off(field, O_AUTOSKIP);
field_opts_off(field, O_STATIC);
set_max_field(field,128); //max width 128
//set_field_type(field[nf], TYPE_ALNUM, 0);
if (i < slist.size())
{
Item* host = slist[i]->findItem("host");
if (host != NULL)
set_field_buffer(field, 0, host->getsvalue());
}
if (i == 0)
set_current_field(frm, field); //фокус на поле
//поле для порта
field = addfield(new_field(1, 5, nl, 17+5, 0, 0));
set_field_back(field, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
set_field_type(field, TYPE_INTEGER, 0, 0, 65535);
field_opts_off(field, O_AUTOSKIP);
if (i < slist.size())
{
Item* port = slist[i]->findItem("port");
if (port != NULL)
set_field_buffer(field, 0, port->getsvalue());
}
//поле для пароля
field = addfield(new_field(1, 20, nl, 29, 0, 0));
set_field_back(field, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
field_opts_off(field, O_AUTOSKIP);
field_opts_off(field, O_STATIC);
set_max_field(field,128); //max width 128
if (i < slist.size())
{
Item* pwd = slist[i]->findItem("pwd");
if (pwd != NULL)
set_field_buffer(field, 0, pwd->getsvalue());
}
nl = nl + 2;
}
//клавиши упр-я
nl++;
field = addfield(new_field(1, 44, nl, 5, 0, 0));
field_opts_off(field, O_ACTIVE); //статический текст
if (extfields)
set_field_buffer(field, 0, "Esc-Cancel Enter-Accept");
else
set_field_buffer(field, 0, "Esc-Cancel Enter-Accept Ins-Add host");
set_field_back(field, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
nl = nl + 2;
//финализация списка полей
addfield(NULL);
//пересчитываем высоту формы, чтобы влезли все поля и центрируем
resize(nl + 1,getwidth());
move(getmaxy(stdscr)/2-getheight()/2,getmaxx(stdscr)/2-getwidth()/2);
}
void CfgForm::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMouseEvent* mevent = (NMouseEvent*)ev;
if ( ev->type == NEvent::evMOUSE)
{
//if (isinside(mevent->row, mevent->col))
NForm::eventhandle(ev); //предок
}
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_IC: //INSERT
if (!extfields)
{
unpost_form(frm);
genfields(true);
post_form(frm);
refresh();
kLogPrintf("INSERT NEW HOST\n");
}
break;
case KEY_ENTER:
case '\n': //ENTER
{
form_driver(frm, REQ_NEXT_FIELD); //костыль чтобы текущее поле не потеряло значение
kLogPrintf("ENTER\n");
updatecfg(); //обновить данные в cfg
gCfg->save(); //сохранить на диск
//gsrvlist->refreshcfg();
//ev->keycode = 27; //костыль чтобы осн программа сдестркутила форму конфига
NEvent* event = new TuiEvent(evCFGCH);//NEvent(NEvent::evPROG, 1); //создаем програмное событие
putevent(event);
break;
}
case 27:
kLogPrintf("ESC\n");
ev->done = false; //нет реакции на этот код (пусть получает владелец)
break;
default:
kLogPrintf("CfgForm::KEYCODE=%d\n", ev->keycode);
ev->done = false;
NForm::eventhandle(ev); //предок
break;
} //switch
}
}
void CfgForm::updatecfg() //сохраняет данные из формы в cfg
{
Item* boinctui_cfg = gCfg->getcfgptr();
if (boinctui_cfg == NULL)
return;
if (fields == NULL)
return;
//удаляем все старые записи "server" из конфига
std::vector
- slist = boinctui_cfg->getItems("server");
std::vector
- ::iterator it;
for (it = slist.begin(); it != slist.end(); it++)
boinctui_cfg->delsubitem(*it);
//создаем новые записи
//int n = field_count(frm);
for (int i = 0; i < nhost; i++) //хосты из формы
{
int nf = 1 + i*3; //номер поля для имени хоста
char* shost = rtrim(field_buffer(fields[nf],0));
char* sport = rtrim(field_buffer(fields[nf+1],0));
char* spwd = rtrim(field_buffer(fields[nf+2],0));
kLogPrintf("SERVER %d [%s:%s <%s>]\n", i, shost, sport, spwd);
gCfg->addhost(shost, sport, spwd);
}
}
boinctui-2.3.4/src/taskinfowin.cpp 0000644 0000000 0000000 00000017774 12301564455 015706 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "kclog.h"
#include "taskinfowin.h"
void Tree2Text(Item* item, std::vector >& vout, int& maxlen1, int& maxlen2)
{
std::vector
- v = item->getItems(""); //получить все эл-ты
std::vector
- ::iterator it2;
for (it2 = v.begin(); it2!=v.end(); it2++) //цикл по эл-там задачи
{
if ((*it2)->isnode())
{
vout.push_back(std::pair( "", "")); //разделитель
Tree2Text(*it2, vout, maxlen1, maxlen2); //рекурсия
vout.push_back(std::pair( "", "")); //разделитель
}
else
{
if (strlen((*it2)->getname()) > maxlen1)
maxlen1 = strlen((*it2)->getname());
if (strlen((*it2)->getsvalue()) > maxlen2)
maxlen2 = strlen((*it2)->getsvalue());
vout.push_back(std::pair((*it2)->getname(), (*it2)->getsvalue()));
}
}
}
//поиск в векторе v переменной с именем varname. Вернет значение или ""
std::string FindVar(std::vector >& v, std::string& varname)
{
std::string result = "";
std::vector >::iterator it;
for (it = v.begin(); it!=v.end(); it++)
{
if ((*it).first == varname)
{
result = (*it).second;
break;
}
}
return result;
}
// =============================================================================
TaskInfoWin::TaskInfoWin(const char* caption, Srv* srv, const char* projecturl, const char* taskname)
: NGroup(NRect(getmaxy(stdscr) - 10, getmaxx(stdscr) - 60, 3, 3))
{
modalflag = true;
this->srv = srv;
this->projecturl = projecturl;
this->taskname = taskname;
this->caption = " ";
this->caption = this->caption + caption;
this->caption = this->caption + " ";
content = new NScrollView(NRect(getheight()-4, getwidth()-4, 2, 2));
insert(content);
updatedata();
//корректируем высоту в меньшую сторону если возможно
if (content->getstringcount() < content->getheight())
{
content->resize(content->getstringcount(), content->getwidth());
resize(content->getheight() + 4, getwidth());
}
//растягиваем по ширине
content->resize(content->getheight(), maxlen1 + maxlen2 + 10);
resize(getheight(), content->getwidth() + 4);
if (getwidth() > getmaxx(stdscr) - 10) //если слишком широко обрезаем
{
resize(getheight(), getmaxx(stdscr) - 10);
content->resize(content->getheight(), getwidth() - 4);
}
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(win,0,0);
mvwprintw(win,0,getwidth()/2-(strlen(caption)/2), this->caption.c_str());
scrollbar = new NScrollBar(NRect(content->getheight()+2,1, content->getbegrow()-1, getwidth()-1), 0, 0, ACS_VLINE);
content->setscrollbar(scrollbar);
insert(scrollbar);
refresh();
}
void TaskInfoWin::updatedata()
{
if (srv == NULL)
return;
//===данные по процессам===
if (srv->statedom.empty())
return;
Item* tmpstatedom = srv->statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
std::vector > ss;
maxlen1 = 0;
maxlen2 = 0;
if (client_state != NULL)
{
int oldstartindex = content->getstartindex();
content->clearcontent();
std::vector
- results = client_state->getItems("result");
std::vector
- ::iterator it;
for (it = results.begin(); it!=results.end(); it++) //цикл списка задач
{
Item* project_url = (*it)->findItem("project_url");
Item* name = (*it)->findItem("name");
if ((project_url != NULL)&&
(name != NULL)&&
(strcmp(project_url->getsvalue(), projecturl.c_str()) == 0)&&
(strcmp(name->getsvalue(), taskname.c_str()) == 0))
{
//имя проекта
std::string pname = srv->findProjectName(tmpstatedom, (*it)->findItem("project_url")->getsvalue());
ss.push_back(std::pair("PROJECT NAME", pname));
//имя приложения
char buf[256];
snprintf(buf, sizeof(buf),"%s","unknown application");
Item* wu_name = (*it)->findItem("wu_name");
if (wu_name != NULL)
{
Item* app = srv->findappbywuname(wu_name->getsvalue());
if (app != NULL)
{
Item* user_friendly_name = app->findItem("user_friendly_name");
if (user_friendly_name != NULL)
snprintf(buf, sizeof(buf),"%s",user_friendly_name->getsvalue());
}
}
ss.push_back(std::pair("APP NAME", buf));
ss.push_back(std::pair("", ""));
//raw данные
Tree2Text(*it, ss, maxlen1, maxlen2);
break;
}
} //цикл списка задач
content->setstartindex(oldstartindex);
needrefresh = true;
}
srv->statedom.releaseptr(tmpstatedom);
//заполняем визуальные строки
std::vector >::iterator it;
for (it = ss.begin(); it!=ss.end(); it++)
{
int varcolor = getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD;
int valcolor = getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD;
if ((FindVar(ssbak, (*it).first) != (*it).second)&&(!ssbak.empty()))
valcolor = getcolorpair(COLOR_CYAN, COLOR_BLACK) | A_BOLD;
NColorString* cs = new NColorString(varcolor, "%-*s ", maxlen1, (*it).first.c_str());
cs->append(valcolor, "%s\n", (*it).second.c_str());
content->addstring(cs);
}
ssbak = ss;
}
void TaskInfoWin::eventhandle(NEvent* ev) //обработчик событий
{
NGroup::eventhandle(ev); //предок
if ( ev->done )
return;
//реакция на мышь
NMouseEvent* mevent = (NMouseEvent*)ev;
if ( ev->type == NEvent::evMOUSE )
{
//блокируем все что внутри
if (isinside(mevent->row, mevent->col))
ev->done = true;
//закрываем при любом клике независимо от координат
if (mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED))
{
putevent(new NEvent(NEvent::evKB, 27));
ev->done = true;
}
}
//клавиатура
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_PPAGE:
content->scrollto(-getheight()/2); //вверх на полокна
content->setautoscroll(false);
break;
case KEY_NPAGE:
if (!content->getautoscroll())
{
int oldpos = content->getstartindex();
content->scrollto(getheight()/2); //вниз на пол окна
if ( oldpos == content->getstartindex()) //позиция не изменилась (уже достигли конца)
content->setautoscroll(true); //включаем автоскроллинг
}
break;
default:
//блокировать все клавиатурные кроме кода закрытия формы
if (ev->keycode == 27)
ev->done = false;
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
if ( ev->type == NEvent::evTIMER )
{
updatedata(); //запросить данные с сервера
refresh(); //перерисовать окно
}
}
boinctui-2.3.4/src/taskwin.cpp 0000644 0000000 0000000 00000047626 12301564455 015031 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include "taskwin.h"
#include "net.h"
#include "resultparse.h"
#include "mbstring.h"
#include "tuievent.h"
#include "kclog.h"
typedef bool (*FnResultCmpLess)( Item* res1, Item* res2 ); //тип для сортировки списка задач
bool resultCmpLessByState( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
Item* active_task1 = res1->findItem("active_task");
Item* active_task2 = res2->findItem("active_task");
Item* ready_to_report1 = res1->findItem("ready_to_report");
Item* ready_to_report2 = res2->findItem("ready_to_report");
if ( (active_task1 != NULL)&&(active_task2 == NULL) )
return true;
if ( (active_task2 != NULL)&&(active_task1 == NULL) )
return false;
if ( (ready_to_report1 == NULL)&&(ready_to_report2 != NULL) )
return true;
if ( (ready_to_report2 != NULL)&&(ready_to_report1 == NULL) )
return false;
return false;
}
bool resultCmpLessByDone( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
Item* fraction_done1 = res1->findItem("fraction_done");
Item* fraction_done2 = res2->findItem("fraction_done");
Item* ready_to_report1 = res1->findItem("ready_to_report");
Item* ready_to_report2 = res2->findItem("ready_to_report");
//kLogPrintf("resultCmpLessByDone: res1 (%s) %p\n", res1->findItem("name")->getsvalue(), fraction_done1);
//kLogPrintf("resultCmpLessByDone: res2 (%s) %p\n", res2->findItem("name")->getsvalue(), fraction_done2);
if ( (fraction_done1 == NULL)&&(fraction_done2 == NULL) )
{
if ((ready_to_report1 != NULL)&&(ready_to_report2 == NULL)) //завершенные считаем как наименьшие !!!
return true;
}
if ( (fraction_done1 == NULL)&&(fraction_done2 != NULL) )
return true; //неактивные меньше активных
if ( (fraction_done1 != NULL)&&(fraction_done2 != NULL) )
{
//kLogPrintf("resultCmpLessByDone(%f,%f) = %c\n\n",fraction_done1->getdvalue(), fraction_done2->getdvalue(),fraction_done1->getdvalue() < fraction_done2->getdvalue() ? 't' : 'f');
return (fraction_done1->getdvalue() < fraction_done2->getdvalue());
}
//kLogPrintf("false\n");
return false;
}
bool resultCmpAboveByDone( Item* res1, Item* res2 ) //для сортировки задач true если res1 > res2
{
return resultCmpLessByDone(res2, res1);
}
bool resultCmpLessByProject( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
std::string pname1 = Srv::findProjectName(res1->getparent()/*->statedom*/, res1->findItem("project_url")->getsvalue());
std::string pname2 = Srv::findProjectName(res2->getparent()/*->statedom*/, res2->findItem("project_url")->getsvalue());
std::transform(pname1.begin(), pname1.end(),pname1.begin(), ::toupper);
std::transform(pname2.begin(), pname2.end(),pname2.begin(), ::toupper);
return (pname1 < pname2);
}
bool resultCmpLessByEstimate( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
Item* estimated_cpu_time_remaining1 = res1->findItem("estimated_cpu_time_remaining");
Item* estimated_cpu_time_remaining2 = res2->findItem("estimated_cpu_time_remaining");
Item* ready_to_report1 = res1->findItem("ready_to_report");
Item* ready_to_report2 = res2->findItem("ready_to_report");
Item* active_task1 = res1->findItem("active_task");
Item* active_task2 = res2->findItem("active_task");
if ( (ready_to_report1 == NULL) && (ready_to_report2 != NULL) )
return true;
if ( (ready_to_report1 != NULL) && (ready_to_report2 == NULL) )
return false;
if ( (active_task1 != NULL) && (active_task2 == NULL) )
return true;
if ( (active_task1 == NULL) && (active_task2 != NULL) )
return false;
if ( ( estimated_cpu_time_remaining1 != NULL) && (estimated_cpu_time_remaining2 != NULL) )
return (estimated_cpu_time_remaining1->getdvalue() < estimated_cpu_time_remaining2->getdvalue());
if ( ( estimated_cpu_time_remaining1 != NULL) && (estimated_cpu_time_remaining2 == NULL) )
return true;
return false;
}
bool resultCmpLessByDL( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
Item* report_deadline1 = res1->findItem("report_deadline");
Item* report_deadline2 = res2->findItem("report_deadline");
if ( ( report_deadline1 != NULL) && (report_deadline2 != NULL) )
return (report_deadline1->getdvalue() < report_deadline2->getdvalue());
if ( ( report_deadline1 != NULL) && (report_deadline2 == NULL) )
return true;
return false;
}
/*
bool resultCmpLessByApp( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
return false; //not implemented yet
}
*/
bool resultCmpLessByTask( Item* res1, Item* res2 ) //для сортировки задач true если res1 < res2
{
Item* name1 = res1->findItem("name");
Item* name2 = res2->findItem("name");
std::string sname1 = name1->getsvalue();
std::string sname2 = name2->getsvalue();
std::transform(sname1.begin(), sname1.end(), sname1.begin(), ::toupper);
std::transform(sname2.begin(), sname2.end(), sname2.begin(), ::toupper);
return (sname1 < sname2);
}
std::string getresultstatestr(Item* result)
{
Item* state = result->findItem("state");
// Item* ready_to_report = result->findItem("ready_to_report");
Item* active_task_state = result->findItem("active_task_state");
if (result->findItem("ready_to_report") != NULL) //расчет завершен
{
if (state->getivalue() == 3)
return "DoneEr"; //была завершена с ошибкой
else
return "Done";
}
if (result->findItem("suspended_via_gui") != NULL) //задача suspend via gui
return "GSusp.";
switch(state->getivalue())
{
case 0:
return "New";
case 1:
return "Dwnld";
case 3:
return "Err";
case 4:
return "Upld";
}
if (active_task_state != NULL)
{
switch(active_task_state->getivalue())
{
case 0:
return "WaitR"; //разобраться с суспендом и возобновлением
case 1:
return "Run";
case 9:
return "Susp.";
case 5:
return "Abort";
case 8:
return "Quit";
case 10:
return "Copy";
default:
return "A"+active_task_state->getivalue();
}
}
return "Wait";
}
std::string gethumanreadabletimestr(time_t time) //получить в виде строки прогнозируемое время завершения задачи
{
std::stringstream s;
tm* t = gmtime(&time);
if ( t->tm_yday > 0 )
s << t->tm_yday << "d";
else
if ( t->tm_hour > 0 )
s << t->tm_hour << "h";
else
if ( t->tm_min > 0 )
s << t->tm_min << "m";
else
if ( t->tm_sec > 0 )
s << t->tm_sec << "s";
else
s << "- ";
return s.str();
}
TaskWin::TaskWin(NRect rect/*, Config* cfg*/) : NSelectList(rect)
{
setselectorbgcolor(COLOR_CYAN);
columnmask = ~0;
taskslistmode = 0;
taskssortmode = 1;
//читаем опции из конфига если нет то создаем
if (gCfg != NULL)
{
Item* rootcfg = gCfg->getcfgptr();
if (rootcfg != NULL)
{
Item* column_view_mask = rootcfg->findItem("column_view_mask");
if (column_view_mask == NULL) //создать
{
column_view_mask = new Item("column_view_mask");
column_view_mask->setivalue(columnmask);
rootcfg->addsubitem(column_view_mask);
}
columnmask = column_view_mask->getivalue();
Item* tasks_list_mode = rootcfg->findItem("tasks_list_mode");
if (tasks_list_mode == NULL) //создать
{
tasks_list_mode = new Item("tasks_list_mode");
tasks_list_mode->setivalue(taskslistmode);
rootcfg->addsubitem(tasks_list_mode);
}
taskslistmode = tasks_list_mode->getivalue();
Item* tasks_sort_mode = rootcfg->findItem("tasks_sort_mode");
if (tasks_sort_mode == NULL) //создать
{
tasks_sort_mode = new Item("tasks_sort_mode");
tasks_sort_mode->setivalue(taskssortmode);
rootcfg->addsubitem(tasks_sort_mode);
}
taskssortmode = tasks_sort_mode->getivalue();
}
}
// this->cfg = cfg;
};
TaskWin::~TaskWin()
{
kLogPrintf("TaskWin::~TaskWin()\n");
clearcontent();
}
void TaskWin::saveopttoconfig() //сохранить маску и т.д. в дереве конфига
{
//пишем в конфиг
if (gCfg != NULL)
{
Item* rootcfg = gCfg->getcfgptr();
if (rootcfg != NULL)
{
Item* column_view_mask = rootcfg->findItem("column_view_mask");
if (column_view_mask != NULL)
column_view_mask->setivalue(columnmask);
Item* tasks_list_mode = rootcfg->findItem("tasks_list_mode");
if (tasks_list_mode != NULL)
tasks_list_mode->setivalue(taskslistmode);
Item* tasks_sort_mode = rootcfg->findItem("tasks_sort_mode");
if (tasks_sort_mode != NULL)
tasks_sort_mode->setivalue(taskssortmode);
}
}
}
void TaskWin::clearcontent()
{
int oldindex = getstartindex();
std::vector::iterator it;
for (it = objects.begin(); it != objects.end(); it++) //очищаем строки ассоцииронанные с визуальными
{
if ((*it) != NULL)
{
TaskInfo* d = (TaskInfo*)(*it);
delete d;
}
}
objects.clear();
NSelectList::clearcontent();
setstartindex(oldindex);
}
void TaskWin::updatedata() //обновить данные с сервера
{
if (srv == NULL)
return;
clearcontent();
if (srv->statedom.empty())
return;
Item* tmpstatedom = srv->statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
int i = 1; //счетчик заданий строк
if (client_state != NULL)
{
std::vector
- results = client_state->getItems("result");
std::vector
- ::iterator it;
if (taskssortmode != 0)
{
//критерий сортировки
FnResultCmpLess fcmpless = resultCmpLessByState; //по умолчанию
switch(taskssortmode)
{
case 1:
fcmpless = resultCmpLessByState; //по state
break;
case 2:
fcmpless = resultCmpAboveByDone; //по done%
break;
case 3:
fcmpless = resultCmpLessByProject; //по project
break;
case 4:
fcmpless = resultCmpLessByEstimate; //по estimate
break;
case 5:
fcmpless = resultCmpLessByDL; //по deadline
break;
case 7:
fcmpless = resultCmpLessByTask; //по task
break;
}//switch
std::sort(results.begin(), results.end(), fcmpless); //сортируем
}
int tasknumber = 1;
for (it = results.begin(); it!=results.end(); it++,i++) //цикл списка задач
{
Item* name = (*it)->findItem("name");
Item* fraction_done = (*it)->findItem("fraction_done");
if (name)
{
int column = 0;
int attr = getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_NORMAL; //ставим цвет по умолчанию
NColorString* cs = new NColorString(attr, "");
std::string sstate = getresultstatestr(*it); //состояние задачи
//цвет и атрибут в зависимости от состояния задачи
if ((*it)->findItem("ready_to_report") != NULL)
attr = getcolorpair(COLOR_BLACK,COLOR_BLACK) | A_BOLD;
if ((*it)->findItem("active_task") != NULL)
attr = getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD; //ставим цвет по умолчанию + A_BOLD;
if ( sstate == "Run")
attr = getcolorpair(COLOR_YELLOW,COLOR_BLACK) | A_BOLD;
if ( sstate == "Upld")
attr = getcolorpair(COLOR_BLUE,COLOR_BLACK) | A_BOLD;
if ( sstate == "Dwnld")
attr = getcolorpair(COLOR_GREEN,COLOR_BLACK) | A_BOLD;
int stateattr = attr;
if ( sstate == "DoneEr")
stateattr = getcolorpair(COLOR_RED,COLOR_BLACK);
//проверяем нужно-ли отображать эту задачу
if
( !(
(taskslistmode == 0)
|| ( ( taskslistmode == 1) && (sstate != "Done" ) )
|| ( ( taskslistmode == 2) && ((*it)->findItem("active_task") != NULL) )
) )
continue; //пропускаем задачи не подходящие фильтру tasklistmode
//колонка 0 номер задачи
if(iscolvisible(column++))
cs->append(attr, " %2d ", tasknumber++);
//колонка 1 состояние
char sdone[64];
if (!fraction_done) //для неактивных секция fraction_done отсутствует
strcpy(sdone," - ");
else
sprintf(sdone,"%6.2f",100*fraction_done->getdvalue());
if (iscolvisible(column++))
cs->append(stateattr, "%-6s", sstate.c_str());
//колонка 2 процент выполнения и подвсетка для GPU задач
int attrgpu = attr;
Item* plan_class = (*it)->findItem("plan_class");
if (plan_class != NULL)
{
if ((strstr(plan_class->getsvalue(),"ati") != NULL )||(strstr(plan_class->getsvalue(),"opencl") != NULL))
attrgpu = getcolorpair(COLOR_MAGENTA,COLOR_BLACK) | A_BOLD;
if (strstr(plan_class->getsvalue(),"cuda") != NULL )
attrgpu = getcolorpair(COLOR_GREEN,COLOR_BLACK) | A_BOLD;
if (strstr(plan_class->getsvalue(),"intel") != NULL ) //NEED CHECK !!!
attrgpu = getcolorpair(COLOR_BLUE,COLOR_BLACK) | A_BOLD;
}
if (( sstate != "Run" )&&( sstate != "Done"))
attrgpu = attrgpu & (~A_BOLD); //выключаем болд для незапущенных
if(iscolvisible(column++))
cs->append(attrgpu, " %6s", sdone);
//колонка 3 имя проекта
std::string pname = srv->findProjectName(tmpstatedom, (*it)->findItem("project_url")->getsvalue());//findProjectName(srv->statedom, *it);
char* sproject = strdup(pname.c_str());
if(iscolvisible(column++))
cs->append(attr, " %-20s", mbstrtrunc(sproject,20));
//колонка 4 время эстимейт
if(iscolvisible(column++))
{
Item* estimated_cpu_time_remaining = (*it)->findItem("estimated_cpu_time_remaining");
int attr2 = attr;
if ( estimated_cpu_time_remaining != NULL )
{
double dtime = estimated_cpu_time_remaining->getdvalue();
if ( ( sstate == "Run" )&&( dtime < 600)&&( dtime >= 0 ) ) //осталось [0-600[ сек
attr2 = getcolorpair(COLOR_RED,COLOR_BLACK) | A_BOLD;
if ( dtime >= 0)
cs->append(attr2," %4s", gethumanreadabletimestr(dtime).c_str()); //естимейт
else
cs->append(attr2," %4s", "?"); //естимейт отрицательный (BOINC bug?)
}
else
cs->append(attr2," %4s", "?");
}
//колонка 5 время дедлайн
if(iscolvisible(column++))
{
Item* report_deadline = (*it)->findItem("report_deadline");
int attr2 = attr;
if (report_deadline != NULL)
{
double dtime = report_deadline->getdvalue();
double beforedl = dtime - time(NULL); //число секунд до дедлайна
if ( ( sstate != "Done")&&( beforedl < 3600 * 24 * 2) ) //осталось меньше 2-х дней
attr2 = getcolorpair(COLOR_BLUE,COLOR_BLACK) | A_BOLD;
cs->append(attr2," %4s", gethumanreadabletimestr(beforedl).c_str());
}
else
cs->append(attr2," %4s", "?");
}
//колонка 6 имя приложения
if(iscolvisible(column++))
{
char buf[256];
snprintf(buf, sizeof(buf),"%s","unknown application");
Item* wu_name = (*it)->findItem("wu_name");
if (wu_name != NULL)
{
Item* app = srv->findappbywuname(wu_name->getsvalue());
if (app != NULL)
{
Item* user_friendly_name = app->findItem("user_friendly_name");
if (user_friendly_name != NULL)
snprintf(buf, sizeof(buf),"%s",user_friendly_name->getsvalue());
}
}
if (iscolvisible(column)) //если след колонка (task) видима нужно обрезать
mbstrtrunc(buf,30);
cs->append(attr," %-30s", buf);
}
//колонка 7 имя задачи
if(iscolvisible(column++))
cs->append(attr," %s", name->getsvalue());
//добавляем сформированную строку и поле данных с именем задачи (для селектора)
//addstring(strdup(name->getsvalue()),cs);
addstring(new TaskInfo(name->getsvalue(),(*it)->findItem("project_url")->getsvalue()), cs);
free(sproject);
}
} //цикл списка задач
}
srv->statedom.releaseptr(tmpstatedom);
}
void TaskWin::eventhandle(NEvent* ev) //обработчик событий
{
NSelectList::eventhandle(ev); //предок
if ( ev->done )
return;
bool selectorvisiblebak = (selectedindex >= 0)&&(selectedindex < content.size()); //состояние селектора до
//одиночный или двойной клик
NMouseEvent* mevent = (NMouseEvent*)ev;
if (( ev->type == NEvent::evMOUSE ) && (mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED)))
{
if (isinside(mevent->row, mevent->col))
{
//передвигаем слектор
setselectorpos(mevent->row - getabsbegrow() + startindex);
if (mevent->cmdcode & BUTTON1_DOUBLE_CLICKED) //даблклик
putevent(new TuiEvent(evTASKINFO)); //событие для открытия raw task info
ev->done = true;
}
}
//клавиатура
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_UP:
selectorup();
break;
case KEY_DOWN:
selectordown();
break;
case KEY_ENTER:
case '\n':
if ((selectedindex >= 0)&&(selectedindex < content.size())) //селектор видимый
putevent(new TuiEvent(evTASKINFO));
break;
default:
ev->done = false; //нет реакции на этот код
} //switch
}
if (ev->type == NEvent::evPROG) //прграммные
{
if (ev->cmdcode == evABORTRES) //событие "abort_result"
{
ev->done =false;
}
if (ev->cmdcode == evCOLVIEWCH) //событие изменения видимости колонки
{
TuiEvent* ev1 = (TuiEvent*) ev;
if (iscolvisible(ev1->idata1))
coldisable(ev1->idata1);
else
colenable(ev1->idata1);
}
if (ev->cmdcode == evVIEWMODECH)
{
TuiEvent* ev1 = (TuiEvent*) ev;
taskslistmode = ev1->idata1;
saveopttoconfig();
setstartindex(0); //отображать с начала
selectedindex = -1; //указатель
}
if (ev->cmdcode == evSORTMODECH)
{
TuiEvent* ev1 = (TuiEvent*) ev;
taskssortmode = ev1->idata1;
saveopttoconfig();
}
}
//если изменилась видимость селектора, то генерируем соотв евент
if (((selectedindex >= 0)&&(selectedindex < content.size()) )&&(!selectorvisiblebak))
putevent(new TuiEvent(evTASKSELECTORON)); //селектор включился
if (((selectedindex == -1)||(selectedindex == content.size()))&&(selectorvisiblebak))
putevent(new TuiEvent(evTASKSELECTOROFF)); //селектор выключился
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
//событие таймера
if (ev->type == NEvent::evTIMER) //таймер
{
updatedata(); //запросить данные с сервера
refresh(); //перерисовать окно
}
}
boinctui-2.3.4/src/resultdom.cpp 0000644 0000000 0000000 00000011276 12301564455 015357 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "resultdom.h"
#include
#include
Item::~Item()
{
std::list
- ::iterator it;
//деструктим подэлементы
for (it=subitems.begin(); it!=subitems.end(); it++)
{
delete *it;
}
//очищаем список
subitems.clear();
}
std::vector
- Item::getItems(const char* name) //получить из текущего эл-та список подэлементов с именем name (поиска в глубину НЕТ)
{
std::vector
- result;
std::list
- ::iterator it;
if (strlen(name) > 0)
{
for (it=subitems.begin(); it!=subitems.end(); it++)
{
if ( strcmp((*it)->getname(),name) == 0 )
result.push_back(*it);
}
}
else //если имя не задано вернет все имеющиеся
{
for (it=subitems.begin(); it!=subitems.end(); it++)
result.push_back(*it);
}
return result;
}
Item* Item::findItem(const char* name) //ищет в поддереве (на всю глубину) элемент с именем name (вернет NULL если такого нет)
{
Item* result;
if (strcmp(this->name.c_str(), name) == 0)
{
return this; //нашли - он сам и есть искомый эл-т
}
else //ищем во всех подэлементах
{
std::list
- ::iterator it;
for (it=subitems.begin(); it!=subitems.end(); it++)
{
result = (*it)->findItem(name);
if (result != NULL)
return result; //нашли!
}
}
return NULL; //не нашли
}
void Item::setivalue(int ivalue) //присвоить целочисленное значение
{
char buff[256];
snprintf(buff,sizeof(buff),"%d",ivalue);
setsvalue(buff);
}
double Item::getdvalue() //получить значение double
{
double result = 0.0;
std::string numlocale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "C"); //чтобы работала sscanf с числами вида 1.234 а не 1,234
sscanf(svalue.c_str(), "%lf", &result);
setlocale(LC_NUMERIC, numlocale.c_str());
return result;
}
void Item::mergetree(Item* tree) //объединяет tree с текущим эл-том
{
if (tree->getfullname() == this->getfullname()) //полные пути одинаковые
{
// Сливаем два узла в один
std::list
- ::iterator it;
for (it = tree->subitems.begin(); it != tree->subitems.end(); it++)
{
addsubitem(*it); //все подэлементы из tree переносим в текущий узел
}
tree->subitems.clear();
//delete tree; //сам узел уже не нужен (все его эл-ты перенесены в this)
}
//else
//{
// добавляем tree к текущему узлу
// addsubitem(tree);
//}
}
void Item::clearsubitems() //удалить все подэл-ты текущего узла
{
std::list
- ::iterator it;
for (it = subitems.begin(); it != subitems.end(); it++)
delete (*it);
subitems.clear();
}
void Item::delsubitem(Item* subitem) //удалить подэлемент subitem из узла
{
std::list
- ::iterator it;
for (it = subitems.begin(); it != subitems.end(); it++)
{
if ((*it) == subitem)
{
delete (*it);
subitems.remove(*it);
break;
}
}
}
std::string Item::toxmlstring() //сериализация в строку
{
static int indent;
std::string result = "";
std::string sindent = ""; //отступ
for (int i = 0; i < indent; i++)
sindent = sindent + " ";
indent++;
result = sindent + "<" + name + ">" + svalue + "\n";
std::list
- ::iterator it;
for (it=subitems.begin(); it!=subitems.end(); it++)
{
result = result + (*it)->toxmlstring();
}
result = result + sindent + "" + name + /* " full="+ getfullname() +*/">\n";
indent--;
return result;
}
boinctui-2.3.4/src/nselectlist.h 0000644 0000000 0000000 00000004654 12301564455 015341 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NSELECTLIST_H
#define NSELECTLIST_H
#include "nscrollview.h"
class NSelectList : public NScrollView //список со скроллингом и селектором
{
public:
NSelectList(NRect rect) : NScrollView(rect) { selectedindex = -1; setselectorenable(true); setselectorbgcolor(COLOR_WHITE); };
void addstring(void* userobj, int attr, const char* fmt, ...); //userobj произвольные данные связанные со строкой
void addstring(void* userobj, NColorString* sctring);
virtual void drawcontent();
virtual void refresh();
virtual void selectorup();
virtual void selectordown();
virtual void setselectorpos(int n) { selectedindex = n; needrefresh = true; }; //передвинуть селектор на строку n
void* getselectedobj(); //вернет указатель или NULL
void setselectorbgcolor(short color) { selectorbgcolor = color; };
//virtual bool objcmpeqv(void* obj1, void* obj2) { return obj1==obj2; };
void setselectorenable(bool b) { selectorenable = b; }; //изменить видимость селектора
protected:
//void* selectedobj; //выделенный объект
int selectedindex; //номер выделенной строки
bool selectorenable; //true если видимость селектора разрешена (не значит что он видим)
std::vector objects; //объекты, ассоциированные с визуальными строками
short selectorbgcolor; //номер цвета фона выделеной строки
};
#endif //NSELECTLIST_H boinctui-2.3.4/src/cfg.h 0000644 0000000 0000000 00000003675 12301564455 013551 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef CFG_H
#define CFG_H
#include "resultdom.h"
#include "nview.h"
class Config
{
public:
Config(const char* filename);
~Config();
void load();
void save();
void generatedefault();
Item* getcfgptr() { if ( root!= NULL) return root->findItem("boinctui_cfg"); else return NULL; };
int getivalue(Item* node, const char* name); //ищет name начиная с node
int getivalue(const char* name) { return getivalue(getcfgptr(), name); }; //ищет name начиная с корня
void setivalue(Item* node, const char* name, int value); //создаст в node подэл-т name со значением value
void setivalue(const char* name, int value) { setivalue(getcfgptr(), name, value); }; //создаст в корне подэл-т name со значением value
void addhost(const char* host, const char* port, const char* pwd);
bool isdefault; //true если конфиг не найден и создан дефолтный
protected:
char* fullname; //полное имя файла
Item* root; //корень дерева конфига
};
extern Config* gCfg;
#endif //CFG_H boinctui-2.3.4/src/nvline.h 0000644 0000000 0000000 00000002253 12301564455 014274 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NVLINE_H
#define NVLINE_H
#include "nview.h"
class NVLine : public NView
{
public:
NVLine(NRect rect, const char* s) : NView(rect) { bgcolor = 0; };
virtual ~NVLine() { };
void setbgcolor(int colorpair) { bgcolor = colorpair; };
virtual void refresh();
protected:
int bgcolor; //цвет фона
const char* mbsym; //символ
};
#endif //NVLINE_H boinctui-2.3.4/src/nmessagebox.cpp 0000644 0000000 0000000 00000013143 12301564455 015647 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include "kclog.h"
#include "nmessagebox.h"
// =============================================================================
NMButton::NMButton(const char* text, NEvent* pevent, ...) : NStaticText(NRect(3, 20, getmaxy(stdscr)/2-3/2,getmaxx(stdscr)/2-20/2))
{
appendstring(getcolorpair(COLOR_WHITE, COLOR_CYAN)," ");
appendstring(getcolorpair(COLOR_WHITE, COLOR_CYAN) | A_BOLD ,text);
appendstring(getcolorpair(COLOR_WHITE, COLOR_CYAN)," ");
this->pevent = pevent;
//размер кнопки
resize(1, mbstrlen(text) + 2);
//список клавиш на которые реагирует эта кнопка
va_list pk;
va_start(pk, pevent);
int ch = va_arg(pk, int);
while ( ch != 0)
{
keys.push_back((char)ch);
ch = va_arg(pk, int); //следующий ключ
}
va_end(pk);
}
void NMButton::eventhandle(NEvent* ev) //обработчик событий
{
NStaticText::eventhandle(ev); //предок
if ( ev->done )
return;
//одиночный или двойной клик
NMouseEvent* mevent = (NMouseEvent*)ev;
if (( ev->type == NEvent::evMOUSE ) && (mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED)))
{
if (isinside(mevent->row, mevent->col))
{
ev->done = true;
NEvent* tmp = pevent;
pevent = NULL;
putevent(tmp); //активируем событие связанное с этой кнопкой
}
}
//клавиатура
if ( ev->type == NEvent::evKB )
{
if ( keys.end() != std::find(keys.begin(), keys.end(), ev->cmdcode) )
{
kLogPrintf("NMButton::eventhandle() got '%c' key\n", ev->cmdcode);
if (pevent)
{
ev->done = true;
NEvent* tmp = pevent;
pevent = NULL;
putevent(tmp); //активируем событие связанное с этой кнопкой
}
}
}
}
// =============================================================================
NMessageBox::NMessageBox(const char* text) : NGroup(NRect(3, 40, 1, 1))
{
//расчитать сколько строк нужно для отображения контента
int contentheight = 0;
int bsize = strlen(text); //количество байт
int result = 0; //подсчитанное кол-во символов
int nbytes = 0; //просмотренное кол-во байтов
int nlines = 0; //количество экранных строк
int col = getwidth() - 4;
const char* p = text;
do
{
col++;
if ((col >= getwidth() - 4)||(*p == '\n'))
{
if (*p == '\n')
col = 0;
else
col = 1;
contentheight++; //след строка
}
int symlen = mblen(p,bsize-nbytes);
nbytes = nbytes + symlen;
result++;
p = p + symlen; //адрес начала след символа
}
while ( (*p != 0)&&(nbytes < bsize) ); //дошли до конца
//заполняем содержимое
content = new NStaticText(NRect(contentheight, getwidth()-4, 2, 2));
content->setbgcolor(getcolorpair(COLOR_WHITE, COLOR_BLACK));
insert(content);
content->appendstring(getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD, text);
modalflag = true;
resize(contentheight + 6,getwidth());
wattrset(win,getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD);
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(win,0,0);
//content->setalign(1);
move(getmaxy(stdscr)/2-getheight()/2,getmaxx(stdscr)/2-getwidth()/2); //центрируем
}
void NMessageBox::addbutton(NMButton* button) //добавить кнопку
{
insert(button);
std::list::iterator it;
int w = 0; //суммарная ширина всех кнопок
for (it = ++items.begin(); it != items.end(); it++) // ++ пропустить content
{
w = w + (*it)->getwidth() + 2; // +2 промежутки между кнопками
}
int row = getheight() - 3;
int col = (getwidth() - w) / 2 + 2;
for (it = ++items.begin(); it != items.end(); it++)
{
(*it)->move(row, col);
col = col + (*it)->getwidth() + 2;
}
}
void NMessageBox::eventhandle(NEvent* ev) //обработчик событий
{
NGroup::eventhandle(ev); //предок
if ( ev->done )
return;
//одиночный или двойной клик
NMouseEvent* mevent = (NMouseEvent*)ev;
if (( ev->type == NEvent::evMOUSE )/* && (mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED))*/)
{
//блокируем все мышиные мнутри окна
// if (isinside(mevent->row, mevent->col))
ev->done = true;
}
//клавиатура
if (ev->type == NEvent::evKB )
{
//блокировать все клавиатурные кроме кода закрытия формы
if (ev->keycode != 27)
ev->done = true;
}
}
boinctui-2.3.4/src/nrect.h 0000644 0000000 0000000 00000002412 12301564455 014111 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NRECT_H
#define NRECT_H
class NRect //прямоугольная область //нумерация строк и столбцов идет от 0
{
public:
NRect() {};
NRect(int rows, int cols, int begrow, int begcol) {this->begrow = begrow; this->begcol = begcol; this->rows = rows; this->cols = cols;};
int begrow;
int begcol;
int rows; //высота (число строк)
int cols; //ширина (число колонок)
};
#endif //NRECT_H boinctui-2.3.4/src/taskinfowin.h 0000644 0000000 0000000 00000003077 12301564455 015342 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef TASKINFOWIN_H
#define TASKINFOWIN_H
#include
#include
#include "ngroup.h"
#include "nscrollview.h"
#include "tuievent.h"
#include "nscrollbar.h"
class TaskInfoWin : public NGroup //стандартный диалог вида Ok/Cancel или Yes/No
{
public:
TaskInfoWin(const char* caption, Srv* srv, const char* projecturl, const char* taskname);
void eventhandle(NEvent* ev); //обработчик событий
void updatedata();
private:
int maxlen1;
int maxlen2;
std::vector > ssbak; //прошлое значение
std::string caption;
std::string projecturl;
std::string taskname;
Srv* srv;
NScrollView* content;
NScrollBar* scrollbar;
};
#endif //TASKINFOWIN_H boinctui-2.3.4/src/about.cpp 0000644 0000000 0000000 00000005023 12301564455 014444 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "about.h"
#include "tuievent.h"
//стрингификатор
#define XSTR(S) STR(S)
#define STR(S) #S
AboutWin::AboutWin(int rows, int cols) : NGroup(NRect(rows, cols, getmaxy(stdscr)/2-rows/2,getmaxx(stdscr)/2-cols/2))
{
modalflag = true;
caption = strdup(" BOINCTUI ");
resize(10,getwidth());
wattrset(win,getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD);
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(win,0,0);
mvwprintw(win,0,getwidth()/2-(strlen(caption)/2),caption);
char buf[1024];
snprintf(buf,sizeof(buf),"%s ver %s","BOINC Client manager", XSTR(VERSION));
mvwprintw(win,3,getwidth()/2-(strlen(buf)/2),buf);
mvwprintw(win,5,getwidth()/2-(strlen("(c) Sergey Suslov")/2),"(c) Sergey Suslov");
mvwprintw(win,6,getwidth()/2-(strlen("suleman1971@gmail.com")/2),"suleman1971@gmail.com");
}
void AboutWin::eventhandle(NEvent* ev) //обработчик событий
{
NGroup::eventhandle(ev); //предок
if ( ev->done )
return;
//закрываем при любом клике независимо от координат
NMouseEvent* mevent = (NMouseEvent*)ev;
if (( ev->type == NEvent::evMOUSE ) && (mevent->cmdcode & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED)))
putevent(new TuiEvent(evABOUT));
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->cmdcode)
{
case 27:
case KEY_ENTER:
case ' ':
case '\n':
putevent(new TuiEvent(evABOUT)); //NEvent(NEvent::evPROG, 3)); //создаем событие с кодом 3 "окно About"
break;
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
boinctui-2.3.4/src/ncolorstring.cpp 0000644 0000000 0000000 00000005554 12301564455 016066 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "ncolorstring.h"
NColorStringPart::NColorStringPart(int attr, const char* fmt, va_list vl)
{
char buf[1024];
vsnprintf(buf, sizeof(buf), fmt, vl);
this->s = buf;
this->attr = attr;
}
NColorString::NColorString(int attr, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vappend(attr,fmt,args);
va_end(args);
}
NColorString::NColorString(int attr, const char* fmt, va_list vl)
{
vappend(attr,fmt,vl);
}
NColorString::~NColorString()
{
std::list::iterator it;
for (it = parts.begin(); it != parts.end(); it++)
{
delete (*it);
}
}
void NColorString::append(int attr, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
NColorStringPart* part = new NColorStringPart(attr, fmt, args);
va_end(args);
append(part);
}
void NColorString::vappend(int attr, const char* fmt, va_list vl)
{
NColorStringPart* part = new NColorStringPart(attr, fmt, vl);
append(part);
}
int NColorString::getlen() //вернет длинну в ЭКРАННЫХ СИМВОЛАХ
{
int result = 0;
std::list::iterator it;
for (it = parts.begin(); it != parts.end(); it++)
{
result = result + (*it)->getlen();
}
return result;
}
NColorString& NColorString::operator=(const NColorString& v)
{
clear();
std::list::const_iterator it;
for ( it = v.parts.begin(); it != v.parts.end(); it++ )
{
append((*it)->attr, (*it)->s.c_str());
}
return *this;
}
bool NColorString::operator==(const NColorString& v)
{
bool result = true;
if (v.parts.size() != parts.size())
return false; //различается кол-во эл-тов
//сравниваем поэлементно
std::list::const_iterator it1;
std::list::const_iterator it2;
it2 = v.parts.begin();
for ( it1 = parts.begin(); it1 != parts.end(); it1++ )
{
if (*(*it1) == *(*it2))
it2++;
else
return false; //часть отличается
}
return result;
}
boinctui-2.3.4/src/msgwin.h 0000644 0000000 0000000 00000002731 12301564455 014306 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef MSGWIN_H
#define MSGWIN_H
#include "nscrollview.h"
#include "resultdom.h"
#include "srvdata.h"
class MsgWin : public NScrollView
{
public:
MsgWin(NRect rect):NScrollView(rect) { };
//virtual ~MsgWin() { };
void updatedata(); //обновить данные с сервера
virtual void eventhandle(NEvent* ev); //обработчик событий
void* setserver(Srv* srv) { if (this->srv != srv) { this->srv = srv; clearcontent(); lastmsgno = 0; } };
protected:
Srv* srv; //текущий отображаемый сервер
int lastmsgno; //номер последнего полученного сообщения
};
#endif //MSGWIN_H
boinctui-2.3.4/src/about.h 0000644 0000000 0000000 00000002162 12301564455 014112 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef ABOUT_H
#define ABOUT_H
#include "ngroup.h"
class AboutWin : public NGroup
{
public:
AboutWin(int rows, int cols);
~AboutWin() { delete caption; };
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
char* caption; //строка заголовка
};
#endif //ABOUT_H boinctui-2.3.4/src/kclog.h 0000644 0000000 0000000 00000002217 12301564455 014100 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
// * для ведения логов
#ifndef KCLOG_H_
#define KCLOG_H_
#include
/// открывает лог файл на запись
void kLogOpen(const char* filename = NULL);
/// закрывает лог файл
void kLogClose();
/// вывести информацию в лог
void kLogPrintf(const char* fmt, ...);
#endif /*KCLOG_H_*/
boinctui-2.3.4/src/infopanel.cpp 0000644 0000000 0000000 00000033566 12301564455 015322 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include "kclog.h"
#include "infopanel.h"
#include "net.h"
#include "resultparse.h"
Item* findDay( std::vector- & days, time_t d ) //ищем в статистике день d если нет вернет NULL
{
std::vector
- ::reverse_iterator rit;
for (rit = days.rbegin(); rit != days.rend(); rit++)
{
Item* day = (*rit)->findItem("day");
if (day != NULL)
{
if ( day->getdvalue() == d )
return (*rit);
}
}
return NULL;
}
std::string InfoPanel::getdayname(time_t ltime) //название дня "today" "yesterday" ""
{
time_t now = time(NULL);
if ( now/(3600 * 24) == ltime/(3600 * 24) )
return "today";
if ( now/(3600 * 24) == 1+ltime/(3600 * 24) )
return "yesterday";
return "";
}
void InfoPanel::refresh()
{
if (srv == NULL)
return;
if (srv->statedom.empty())
{
needrefresh = true;
werase(win);
mvwprintw(win,0,0,"%s:%s\noffline",srv->gethost(),srv->getport());
NView::refresh();
return;
}
wattrset(win,getcolorpair(COLOR_WHITE,COLOR_BLACK));
wattron(win, A_REVERSE);
mvwprintw(win,0,0," Tasks ");
wattroff(win, A_REVERSE);
mvwprintw(win,1,0,"all %3d",nalltasks);
mvwprintw(win,2,0,"active %3d",nactivetasks);
mvwprintw(win,3,0,"run %3d",nruntasks);
mvwprintw(win,4,0,"wait %3d",nqueuetasks);
mvwprintw(win,5,0,"done %3d",ndonetasks);
mvwprintw(win,6,0,"other %3d",nothertasks);
wattron(win,A_REVERSE);
mvwprintw(win,7,0," Storage ");
wattroff(win,A_REVERSE);
mvwprintw(win,8,0, "total %8.2fGb",dtotal/(1024*1024*1024));
mvwprintw(win,9,0, "free %8.2fGb",dfree/(1024*1024*1024));
mvwprintw(win,10,0,"allowed %8.2fGb",dallowed/(1024*1024*1024));
mvwprintw(win,11,0,"boinc %8.2fGb",dboinc/(1024*1024*1024));
wattron(win,A_REVERSE);
mvwprintw(win,12,0," Statistics ");
wattroff(win,A_REVERSE);
bool compact = true; //компактный вывод статистики если user=host
int line,col;
getyx(win,line,col);
if ( (!compact)||(usertotal != hosttotal) )
{
mvwprintw(win,line++,0,"user total%10.0f\n",usertotal);
mvwprintw(win,line++,0,"host total%10.0f\n",hosttotal);
}
else
mvwprintw(win,line++,0,"total %10.0f\n",usertotal);
if ( (!compact)||(useravg != hostavg) )
{
mvwprintw(win,line++,0,"user avg %10.0f\n",useravg);
mvwprintw(win,line++,0,"host avg %10.0f\n",hostavg);
}
else
mvwprintw(win,line++,0,"average %10.0f\n",useravg);
tm* ltime = localtime(&laststattime);
char buf[128];
strftime(buf, sizeof(buf),"%-e %b",ltime); //"%-e %b %-k:%M"
mvwprintw(win,line++,0,"%-s %s\n", buf, getdayname(laststattime).c_str()); //дата/время последней статистики
//wattrset(win,0);
if ( (!compact)||(lastdayuser != lastdayhost) )
{
if ( asciilinedraw == 1)
{
wmove(win,line++,0); wprintw(win,"+->user %10.0f\n",lastdayuser);
wmove(win,line++,0); wprintw(win,"+->host %10.0f\n",lastdayhost);
}
else
{
mvwaddch(win,line++,0,ACS_LTEE); waddch(win,ACS_HLINE); wprintw(win,">user %10.0f\n",lastdayuser);
mvwaddch(win,line++,0,ACS_LLCORNER); waddch(win,ACS_HLINE); wprintw(win,">host %10.0f\n",lastdayhost);
}
}
else
{
if( asciilinedraw == 1)
{
wmove(win,line++,0); wprintw(win,"-->daily %10.0f\n",lastdayhost);
}
else
{
mvwaddch(win,line++,0,ACS_LLCORNER); waddch(win,ACS_HLINE); wprintw(win,">daily %10.0f\n",lastdayhost);
}
}
//по проектам
mvwprintw(win, line++,0,"\n");
for (int i = 0; i < projects.size(); i++) //цикл по названиям проектов
{
//расчитываем нужное кол-во строк
int needlines = 2;
if (!projects[i].sstatus.empty())
needlines++;
if ( (!compact)||(projects[i].user != projects[i].host) )
needlines += 2;
else
needlines++;
if ( (!compact)||(projects[i].userlastday != projects[i].hostlastday) )
needlines += 2;
else
needlines++;
//проверяем сколько свободных строк осталось в окне
if ( ( getheight()-line ) < needlines )
break; //не выводим если осталось мало строк
//вывод на экран о проекте
wattrset(win,getcolorpair(COLOR_YELLOW,COLOR_BLACK));
mvwprintw(win,line++,0,"%s\n",projects[i].name.c_str());
if (!projects[i].sstatus.empty())
{
wattrset(win,getcolorpair(COLOR_RED,COLOR_BLACK));
mvwprintw(win,line++,0,"%s\n",projects[i].sstatus.c_str());
}
wattrset(win,getcolorpair(COLOR_WHITE,COLOR_BLACK));
if ( (!compact)||(projects[i].user != projects[i].host) )
{
mvwprintw(win,line++,0,"user total%10.0f\n",projects[i].user);
mvwprintw(win,line++,0,"host total%10.0f\n",projects[i].host);
}
else
mvwprintw(win,line++,0,"total %10.0f\n",projects[i].user);
ltime = localtime(&projects[i].laststattime);
strftime(buf, sizeof(buf),"%-e %b",ltime); //"%-e %b %-k:%M"
mvwprintw(win,line++,0,"%-s %s\n",buf, getdayname(projects[i].laststattime).c_str());
if ( (!compact)||(projects[i].userlastday != projects[i].hostlastday) )
{
if (asciilinedraw == 1)
{
wmove(win,line++,0); wprintw(win,"+->user %10.0f\n",projects[i].userlastday);
wmove(win,line++,0); wprintw(win,"+->host %10.0f\n",projects[i].hostlastday);
}
else
{
mvwaddch(win,line++,0,ACS_LTEE); waddch(win,ACS_HLINE); wprintw(win,">user %10.0f\n",projects[i].userlastday);
mvwaddch(win,line++,0,ACS_LLCORNER); waddch(win,ACS_HLINE); wprintw(win,">host %10.0f\n",projects[i].hostlastday);
}
}
else
{
if (asciilinedraw == 1)
{
wmove(win,line++,0); wprintw(win,"-->daily %10.0f\n",projects[i].userlastday);
}
else
{
mvwaddch(win,line++,0,ACS_LLCORNER); waddch(win,ACS_HLINE); wprintw(win,">daily %10.0f\n",projects[i].userlastday);
}
}
}
if ( line < getheight() )
wclrtobot(win); //чистим нижню часть окна (если не это не последняя строка иначе сотрем символ в правом нижнем)
NView::refresh();
}
void InfoPanel::updatedata()
{
if (srv == NULL)
return;
//===данные по процессам===
if (srv->statedom.empty())
return;
Item* tmpstatedom = srv->statedom.hookptr();
Item* client_state = tmpstatedom->findItem("client_state");
nactivetasks = 0;
ndonetasks = 0;
nruntasks = 0;
nqueuetasks = 0;
if (client_state != NULL)
{
std::vector
- results = client_state->getItems("result");
std::vector
- ::iterator it;
nalltasks = results.size();
for (it = results.begin(); it!=results.end(); it++) //цикл списка задач
{
Item* ready_to_report = (*it)->findItem("ready_to_report");
if (ready_to_report != NULL)
ndonetasks++;
Item* active_task = (*it)->findItem("active_task");
if (active_task != NULL)
{
nactivetasks++;
if (active_task->findItem("active_task_state")->getivalue() == 1)
nruntasks++;
}
else
{
if (ready_to_report == NULL)
nqueuetasks++;
}
} //цикл списка задач
nothertasks = nalltasks-nruntasks-ndonetasks-nqueuetasks;
needrefresh = true;
}
//===данные по дискам===
if (srv->dusagedom.empty())
{
srv->statedom.releaseptr(tmpstatedom);
return;
}
Item* tmpdusagedom = srv->dusagedom.hookptr();
Item* disk_usage_summary = tmpdusagedom->findItem("disk_usage_summary");
if (disk_usage_summary != NULL)
{
dtotal = disk_usage_summary->findItem("d_total")->getdvalue();
dfree = disk_usage_summary->findItem("d_free")->getdvalue();
dboinc = disk_usage_summary->findItem("d_boinc")->getdvalue();
dallowed = disk_usage_summary->findItem("d_allowed")->getdvalue();
std::vector
- results = disk_usage_summary->getItems("project");
std::vector
- ::iterator it;
for (it = results.begin(); it!=results.end(); it++) //цикл списка задач
{
dboinc = dboinc + (*it)->findItem("disk_usage")->getdvalue();
}
}
//===данные статистики===
if (srv->statisticsdom.empty())
{
srv->statedom.releaseptr(tmpstatedom);
srv->dusagedom.releaseptr(tmpdusagedom);
return;
}
laststattime = srv->getlaststattime();
// time_t predstattime = laststattime - (24*60*60); //предыдущий день
usertotal = 0;
useravg = 0;
hosttotal = 0;
hostavg = 0;
lastdayuser = 0;
lastdayhost = 0;
double usertotallastday = 0;
double hosttotallastday = 0;
double usertotalpredday = 0;
double hosttotalpredday = 0;
projects.clear();
Item* tmpstatisticsdom = srv->statisticsdom.hookptr();
Item* statistics = tmpstatisticsdom->findItem("statistics");
if (statistics!=NULL)
{
std::vector
- project_statistics = statistics->getItems("project_statistics");
std::vector
- ::iterator it;
for (it = project_statistics.begin(); it!=project_statistics.end(); it++) //цикл списка проектов
{
ProjectStat st; //заполнить эту структуру
st.name = srv->findProjectName(tmpstatedom,((*it)->findItem("master_url")->getsvalue()));
st.sstatus = "";
//строка статуса
if (!srv->statedom.empty())
{
Item* project = srv->findprojectbyname(st.name.c_str());
if (project != NULL)
{
st.sstatus = st.sstatus + (project->findItem("suspended_via_gui")? "[Susp.] " : "");
st.sstatus = st.sstatus + (project->findItem("dont_request_more_work") ? "[N.N.Tsk.] " : "");
}
}
std::vector
- daily_statistics = (*it)->getItems("daily_statistics"); //все дни проекта в этом векторе
std::sort(daily_statistics.begin(), daily_statistics.end(), daily_statisticsCmpAbove); //сортируем по убыванию дат
if (!daily_statistics.empty())
{
Item* lastday = findDay(daily_statistics, laststattime); //последний день
Item* predday = NULL;
// time_t d = lastday->findItem("day")->getdvalue(); //время из статистики
if ( lastday != NULL) //для этого проекта последний день есть
{
usertotallastday = usertotallastday + lastday->findItem("user_total_credit")->getdvalue();
hosttotallastday = hosttotallastday + lastday->findItem("host_total_credit")->getdvalue();
//берем предпоследний
if (daily_statistics.size() > 1)
predday = daily_statistics[1];
}
// else //в этом проекте за последний день ничего нет
// {
// predday = daily_statistics.front(); //последний день этого проекта учитываем как предыдущий
// }
//накапливаем статистику за предыдущий день (если есть)
if (predday != NULL)
{
usertotalpredday = usertotalpredday + predday->findItem("user_total_credit")->getdvalue();
hosttotalpredday = hosttotalpredday + predday->findItem("host_total_credit")->getdvalue();
}
//суммарно по всем дням и проектам
Item* frontday = daily_statistics.front(); //берем последний несмотря на его дату
if (daily_statistics.size() > 1)
{
Item* predfrontday;
predfrontday = daily_statistics[1];
st.userlastday = frontday->findItem("user_total_credit")->getdvalue()-predfrontday->findItem("user_total_credit")->getdvalue();
st.hostlastday = frontday->findItem("host_total_credit")->getdvalue()-predfrontday->findItem("host_total_credit")->getdvalue();
}
st.laststattime = frontday->findItem("day")->getdvalue();
usertotal = usertotal + frontday->findItem("user_total_credit")->getdvalue();
useravg = useravg + frontday->findItem("user_expavg_credit")->getdvalue();
hosttotal = hosttotal + frontday->findItem("host_total_credit")->getdvalue();
hostavg = hostavg + frontday->findItem("host_expavg_credit")->getdvalue();
st.user = frontday->findItem("user_total_credit")->getdvalue();
st.host = frontday->findItem("host_total_credit")->getdvalue();
}
else
{
st.user = 0;
st.host = 0;
st.laststattime = 0;
st.userlastday = 0;
st.hostlastday = 0;
}
projects.push_back(st); //вставляем статистику в вектор проектов
} //проекты
lastdayuser = usertotallastday - usertotalpredday;
lastdayhost = hosttotallastday - hosttotalpredday;
//сортируем проекты чтобы наиболее актуальные отображались первыми
std::sort(projects.begin(), projects.end(), ProjectStat::CmpAbove);
}
srv->statisticsdom.releaseptr(tmpstatisticsdom);
srv->statedom.releaseptr(tmpstatedom);
}
void InfoPanel::eventhandle(NEvent* ev) //обработчик событий
{
NView::eventhandle(ev); //предок
if ( ev->done )
return;
if ( ev->type == NEvent::evTIMER )
{
updatedata(); //запросить данные с сервера
refresh(); //перерисовать окно
}
}
boinctui-2.3.4/src/ngroup.cpp 0000644 0000000 0000000 00000007425 12301564455 014654 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "ngroup.h"
NGroup::~NGroup()
{
std::list::iterator it;
for(it = items.begin(); it != items.end(); it++)
{
delete (*it);
}
}
NView* NGroup::getitembyid(const char* id) //получить эл-т зная id его класса
{
NView* result = NULL;
std::list::iterator it;
for(it = items.begin(); it != items.end(); it++)
{
if (strcmp((*it)->getid(), id) == 0)
{
result = (*it);
break;
}
}
return result;
}
bool NGroup::destroybyid(const char* id) //удалить (с деструкцией) эл-т зная id его класса
{
bool result = false;
NView* item = getitembyid(id);
if (item != NULL)
{
remove(item);
delete(item);
result = true;
}
return result;
}
void NGroup::setneedrefresh()
{
NView::setneedrefresh();
std::list::iterator it;
for(it = items.begin(); it != items.end(); it++) //перерисовать все подэлементы
{
(*it)->setneedrefresh();
}
}
void NGroup::refresh()
{
NView::refresh(); //предок
std::list::iterator it;
for(it = items.begin(); it != items.end(); it++) //перерисовать все подэлементы
{
(*it)->refresh();
}
}
void NGroup::move(int begrow, int begcol)
{
//перемещаем само окно
NView::move(begrow, begcol); //предок
//перемещаем содержимое (относительно этого окна)
std::list::iterator it;
for(it = items.begin(); it != items.end(); it++) //перместить все подэлементы
{
(*it)->move((*it)->getbegrow(),(*it)->getbegcol());
}
}
void NGroup::centermodalitems(int maxy, int maxx) //центрировать все модальные эл-ты (maxy,maxx -размер экрана)
{
std::list::iterator it;
for(it = items.begin(); it != items.end(); it++) //ищем модальные подэлементы
{
if ((*it)->ismodal())
(*it)->move(maxy/2-(*it)->getheight()/2,maxx/2-(*it)->getwidth()/2);
}
}
void NGroup::eventhandle(NEvent* ev) //обработчик событий
{
//если событие уже кем-то обработано, то просто выходим
if (ev->done)
return;
//посылаем событие всем своим подэлементам (последние вставленные
//получат первыми. Если один из подэл-тов обработал, то выходим
std::list::reverse_iterator rit;
for(rit = items.rbegin(); rit != items.rend(); rit++) //отправить всем подэлементам
{
(*rit)->eventhandle(ev);
if (ev->done)
return; //прекращаем если событие обработано
}
//раз подэл-ты не обработали пытаемся обработать самостоятельно
NView::eventhandle(ev); //предок
}
boinctui-2.3.4/src/ngroup.h 0000644 0000000 0000000 00000003400 12301564455 014306 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NGROUP_H
#define NGROUP_H
#include
#include "nview.h"
class NGroup : public NView
{
public:
NGroup(NRect rect) : NView(rect) {};
virtual ~NGroup();
void insert(NView* view) { view->setowner(this); items.push_back(view); };
void remove(NView* view) { items.remove(view); };
NView* getitembyid(const char* id); //получить эл-т зная id его класса
bool destroybyid(const char* id); //удалить (с деструкцией) эл-т зная id его класса
virtual void refresh();
virtual void eventhandle(NEvent* ev); //обработчик событий
virtual void setneedrefresh();
virtual void move(int begrow, int begcol);
void centermodalitems(int maxy, int maxx); //центрировать все модальные эл-ты (maxy,maxx -размер экрана)
protected:
std::list items; //список вложенных элементов
};
#endif // NGROUP_H
boinctui-2.3.4/src/nevent.h 0000644 0000000 0000000 00000004715 12301564455 014305 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NEVENT_H
#define NEVENT_H
#ifdef DEBUG
#include
#include
#endif
//#include "kclog.h"
class NEvent //класс описывающий событие создаваемое например при нажатии клавиш
{
public:
enum Type { evKB, evMOUSE, evPROG, evTIMER }; //evPROG событие генерируемое самой прораммой
NEvent(NEvent::Type type, int keycode) { this->type = type; this->done = false; this->keycode = keycode;};
virtual ~NEvent() { /*kLogPrintf("~NEvent()\n");*/ };
NEvent::Type type;
bool done; //true если обработано
union
{
int keycode; //код клавиатуры
int cmdcode; //произвольный код команды
};
#ifdef DEBUG
virtual std::string tostring()
{
std::stringstream s;
s << this << " " << type << "(";
switch (type)
{
case evKB:
s << "evKB keycode=" << keycode;
break;
case evMOUSE:
s << "evMOUSE";
break;
case evPROG:
s << "evPROG";
break;
case evTIMER:
s << "evTIMER";
break;
};
s << ")";
return s.str();
};
#endif
};
class NMouseEvent : public NEvent
{
public:
NMouseEvent(int bstate, int row, int col) : NEvent(evMOUSE, bstate) //bstate (see mmask_t ncurses.h)
{
this->col = col;
this->row = row;
};
virtual ~NMouseEvent() { /*kLogPrintf("~NMouseEvent()\n");*/ };
int row;
int col;
#ifdef DEBUG
virtual std::string tostring()
{
std::stringstream s;
s << NEvent::tostring() << "{row=" << row << ",col=" << col << ",bstate=" << std::hex << cmdcode;
s << "}";
return s.str();
};
#endif
};
#endif //NEVENT_H boinctui-2.3.4/src/nscrollbar.cpp 0000644 0000000 0000000 00000010210 12301564455 015465 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013,2014 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "nscrollbar.h"
#include "kclog.h"
NScrollBar::NScrollBar(NRect rect, chtype chtop, chtype chbottom, chtype chinactive) : NView(rect)
{
bgcolor = 0;
this->chtop = chtop;
this->chbottom = chbottom;
this->chinactive = chinactive;
setvisible(true);
}
void NScrollBar::setpos(int vmin, int vmax, int vpos1, int vpos2)
{
//если видимая часть больше или равна контенту то выключаем
setvisible(!((vpos1==vmin)&&(vpos2==vmax)));
if ((this->vmin!=vmin)||(this->vmax!=vmax)||(this->vpos1!=vpos1)||(this->vpos2!=vpos2))
{
this->vmin=vmin;
this->vmax=vmax;
this->vpos1=vpos1;
this->vpos2=vpos2;
if (vmin>vmax)
vmax = vmin;
if (vpos1 > vpos2)
vpos2 = vpos1;
if (vpos1 < vmin)
vpos1 = vmin;
if (vpos2 > vmax)
vpos2 = vmax;
//kLogPrintf("NScrollBar::setpos(vmin=%d, vmax=%d, vpos1=%d, vpos2=%d)\n",vmin, vmax, vpos1, vpos2);
refresh();
}
}
void NScrollBar::refresh()
{
wbkgd(win,bgcolor);
wattrset(win,getcolorpair(COLOR_WHITE,COLOR_BLACK));
chtype topsymbol = asciilinedraw ? '+'| (chtop & A_BOLD) : chtop;
chtype bottomsymbol = asciilinedraw ? '+' | (chbottom & A_BOLD) : chbottom;
chtype bodysymbol = asciilinedraw ? 'X' : ACS_CKBOARD;
if (!visible)
bodysymbol = asciilinedraw ? '|' | (chinactive & A_BOLD) : chinactive;
int rowmin = 0; //строка с которой начинаем рисовать фон
int rowmax = getheight() - 1; //строка до которой рисуем фон включительно
if (chtop != 0) //верхний концевой символ есть
{
mvwaddch(win,0,0,topsymbol);
rowmin = 1;
}
if (chbottom != 0)//нижний концевой символ есть
{
mvwaddch(win,getheight()-1,0,bottomsymbol);
rowmax--; //укорачиваем
}
//фоновый заполнитель
int len = rowmax - rowmin + 1; //высота заполнителя в символах
mvwvline(win, rowmin, 0, bodysymbol, len);
if (visible)
{
//отрисовка позиции
if ((vpos2>vpos1)&&(vmax>vmin))
{
double scale = double(len-1)/(vmax-vmin); //сколько единиц на экранную строку
int len2 = round(scale * (vpos2-vpos1)); //число выделенных строк
int rowpos1 = rowmin + round(scale * (vpos1-vmin)); //строка начала выделения
if (len2<1) //len2 всегда 1 и более
len2=1;
//подпорки с краем диапазона чтобы были видны малые фрагменты
//в начале и в конце
if ((rowpos1==rowmin)&&(vpos1>vmin))
{
if (rowpos1=rowmax)&&(vpos2rowmin)
rowpos1--; //слегка приподнять вверх чтобы показать что это не конец
}
if (vpos2==vmax)
len2=len-rowpos1+1;
//kLogPrintf("len=%d vmin=%d vmax=%d vpos1=%d vpos2=%d scale=%f rowmin=%d rowmax=%d rowpos1=%d len2=%d\n",len, vmin,vmax,vpos1,vpos2,scale,rowmin,rowmax,rowpos1,len2);
//рисуем выделение
mvwvline(win,rowpos1,0,' ' | getcolorpair(COLOR_CYAN,COLOR_WHITE), len2);
}
}
NView::refresh();
}
boinctui-2.3.4/src/resultparse.h 0000644 0000000 0000000 00000002353 12301564455 015353 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef RESULTPARSE_H
#define RESULTPARSE_H
#include "resultdom.h"
Item* xmlparse(const char* xml, int len); //xml строка с xml len ее размер в байтах
char* stripinvalidtag(char* xml, int len); //ГРЯЗНЫЙ ХАК нужен чтобы до парсинга удалить кривые теги
//в сообщениях вида иначе будет ошибка парсинга
#endif // RESULTPARSE_H boinctui-2.3.4/src/tui-main.cpp 0000644 0000000 0000000 00000004016 12301564455 015056 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include "kclog.h"
#include "mainprog.h"
std::string locale;
void initcurses()
{
locale = setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "");
initscr();
noecho();
curs_set(0);
keypad(stdscr,true); //разрешаем стрелки и т.п.
#ifdef ENABLEMOUSE
mousemask(ALL_MOUSE_EVENTS, NULL); // Report all mouse events
#endif
timeout(100); //ожидание для getch() 100 милисекунд
start_color();
initcolorpairs();
}
void donecurses()
{
clear();
refresh();
endwin();
setlocale(LC_ALL, locale.c_str());
}
int main(int argc, char ** argv)
{
MainProg* mainprog;
kLogOpen("boinctui.log");
initcurses();
#ifdef DEBUG
struct mallinfo minf1 = mallinfo();
#endif
mainprog = new MainProg();
mainprog->refresh();
mainprog->mainloop(); //запускаем осн. цикл событий
delete mainprog;
#ifdef DEBUG
struct mallinfo minf2 = mallinfo();
kLogPrintf("mallinfo.uordblks= %d-%d = %d (bytes leak)\n",minf1.uordblks,minf2.uordblks, minf2.uordblks-minf1.uordblks);
//malloc_stats();
#endif
donecurses();
kLogClose();
exit(EXIT_SUCCESS);
}
boinctui-2.3.4/src/nvline.cpp 0000644 0000000 0000000 00000002051 12301564455 014623 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "nvline.h"
void NVLine::refresh()
{
wbkgd(win,bgcolor);
wattrset(win,getcolorpair(COLOR_WHITE,COLOR_BLACK));
if (asciilinedraw == 1)
wvline(win, '|', getheight()-0);
else
wvline(win, ACS_VLINE, getheight()-0);
NView::refresh();
}; boinctui-2.3.4/src/nview.cpp 0000644 0000000 0000000 00000007355 12301564455 014474 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "nview.h"
#include "ngroup.h"
#include "kclog.h"
int asciilinedraw = 0; //1-рисовать рамки символами +----+
void initcolorpairs()
{
//kLogPrintf("COLORS=%d COLOR_PAIRS=%d\n",COLORS,COLOR_PAIRS);
//COLORS 0..7
//COLOR_PAIRS 64 [(0),1..63] 0-predfined
int npair; //номер генерируемой пары
for ( int b = 0; b < COLORS; b++ ) //фон
{
for ( int f = 0; f < COLORS; f++ ) //текст
{
npair = 1 + b * COLORS + f;
if ( npair < COLOR_PAIRS )
init_pair(npair, f, b);
}
}
}
int getcolorpair(int fcolor, int bcolor) //получить пару для комбинации цветов
{
int npair = 1 + bcolor * COLORS + fcolor;
if ( npair <= COLOR_PAIRS)
return COLOR_PAIR(npair);
else
return COLOR_PAIR(0);
}
NView::NView(NRect rect)
{
this->rect = rect;
win = newwin(rect.rows, rect.cols, rect.begrow, rect.begcol); //создаем окно curses
pan = new_panel(win);
scrollok(win,false);
needrefresh = true;
owner = NULL;
modalflag = false;
#ifdef DEBUG
refreshcount = 0; //счетчик обновлений
#endif
wbkgdset(win,getcolorpair(COLOR_WHITE,COLOR_BLACK)); //бакграунд
werase(win); //заполняем цветом фона
}
void NView::setowner(NGroup* owner)
{
this->owner = owner;
//позиционировать относительно овнера
move(getbegrow(),getbegcol());
}
void NView::resize(int rows, int cols)
{
wresize(win, rows, cols);
rect.rows = rows;
rect.cols = cols;
needrefresh = true;
}
void NView::refresh() //перерисовать
{
if (needrefresh)
{
#ifdef DEBUG
refreshcount++;
mvwprintw(win,0,getmaxx(win)-10,"r=%d",refreshcount);
#endif
update_panels();
//doupdate();
needrefresh = false;
}
}
int NView::getabsbegrow() //получить начальную строку (на экране)
{
if (owner == NULL)
return getbegrow();
else
return getbegrow() + owner->getabsbegrow();
}
int NView::getabsbegcol() //получить начальный столбец (на экране)
{
if (owner == NULL)
return getbegcol();
else
return getbegcol() + owner->getabsbegcol();
}
bool NView::isinside(int row, int col) //true если координаты внутри окна (row col абсолютные!)
{
bool result = true;
int absbegrow = getabsbegrow();
int absbegcol = getabsbegcol();
if ((row < absbegrow)||(col < absbegcol))
result = false;
if ((row > absbegrow + rect.rows - 1)||(col > absbegcol+ rect.cols - 1))
result = false;
return result;
}
void NView::move(int begrow, int begcol)
{
rect.begrow = begrow;
rect.begcol = begcol;
move_panel(pan, getabsbegrow(), getabsbegcol());
}
void NView::putevent(NEvent* ev) //отправить событие по цепочке владельцев в очередь
{
if (owner != NULL)
owner->putevent(ev);
}
boinctui-2.3.4/src/nmenu.h 0000644 0000000 0000000 00000004561 12301564455 014127 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NMENU_H
#define NMENU_H
#include
#include
#include "ngroup.h"
#include "nscrollbar.h"
class NMenu : public NGroup
{
public:
NMenu(NRect rect, bool horis = false);
virtual ~NMenu();
virtual void refresh();
void additem(const char* name, const char* comment); //добавить эл-т в меню
virtual void eventhandle(NEvent* ev); //обработчик событий
void setbackground(int attr) { set_menu_back(menu, attr); wattrset(win, attr); bgattr = attr; wbkgdset(win,attr); };
void setforeground(int attr) { set_menu_fore(menu, attr); fgattr = attr; };
void postmenu() { if (!posted) {post_menu(menu); posted = true;} };
void unpostmenu() { if (posted) {unpost_menu(menu); posted = false;} };
virtual bool createsubmenu() { return false; }; //открыть субменю
virtual void destroysubmenu(); //закрыть субменю
virtual bool action() { return false; }; //вызывается при нажатии Enter
protected:
MENU* menu;
ITEM** mitems; //масив элементов
std::list itemnames; //имена эл-тов меню
std::list itemcomments; //комментарии к эл-там меню
int bgattr; //цвет текста и фона невыделенного эл-та
int fgattr; //цвет текста и фона выделенного эл-та
bool ishoris;//true если меню горизонтальное
private:
bool posted; //true после post_menu()
NScrollBar* scrollbar;
};
#endif //NMENU_H boinctui-2.3.4/src/nmenu.cpp 0000644 0000000 0000000 00000021722 12301564455 014460 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "nmenu.h"
#include "kclog.h"
NMenu::NMenu(NRect rect, bool horis) : NGroup(rect)
{
mitems = NULL;
ishoris = horis;
posted = false;
menu = new_menu(mitems);
setbackground(getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
setforeground(getcolorpair(COLOR_BLACK,COLOR_WHITE));
set_menu_grey(menu, getcolorpair(COLOR_RED,COLOR_BLACK)); //цвет разделителей
set_menu_win(menu, win);
postmenu();
if (horis)
scrollbar = NULL;
else
{
scrollbar = new NScrollBar(NRect(getheight(),1, 1, getwidth()-1), 0, 0, ACS_VLINE | A_BOLD);
insert(scrollbar);
}
}
NMenu::~NMenu()
{
//kLogPrintf("NMenu::~NMenu()\n");
unpostmenu();
if (!ishoris)
delwin(menu_sub(menu));
free_menu(menu);
//освобождаем строки
std::list::iterator it;
for (it = itemnames.begin(); it != itemnames.end(); it++)
{
delete (*it);
}
for (it = itemcomments.begin(); it != itemcomments.end(); it++)
{
delete (*it);
}
//массив эл-тов
if (mitems != NULL)
{
int i = 0;
while (mitems[i] != NULL)
free_item(mitems[i++]);
free(mitems);
}
}
void NMenu::destroysubmenu() //закрыть субменю
{
std::list::iterator it;
bool done = false;
while (!done)
{
done = true;
for (it = items.begin(); it != items.end(); it++)
{
if (scrollbar==*it)
continue; //подпорка
delete *it;
remove (*it);
done = false;
break;
}
}
}
void NMenu::additem(const char* name, const char* comment) //добавить эл-т в меню
{
unpostmenu();
mitems = (ITEM**)realloc(mitems,(itemnames.size()+1)*sizeof(ITEM*));
if (name == NULL) //финализация списка
{
mitems[itemnames.size()] = NULL;
set_menu_items(menu, mitems);
set_menu_mark(menu, " ");
if ( !ishoris ) //для вертикальных есть рамка
{
int lines = itemnames.size(); //видимых эл-тов
if ((lines>2)&&(lines + getbegrow() > getmaxy(stdscr) - 8))
lines = getmaxy(stdscr)-getbegrow() - 8;
set_menu_format(menu, lines, 1);
resize(lines+2,menu->width+3); //изменяем размер под кол-во эл-тов
set_menu_sub(menu,derwin(win,getheight()-2,getwidth()-2,1,1));
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(win,0,0); //рамка
if (scrollbar)
{
scrollbar->resize(getheight()-2,1);
scrollbar->move(1,getwidth()-1);
scrollbar->setpos(0,itemnames.size(),top_row(menu),top_row(menu)+getheight()-2);
scrollbar->refresh();
}
}
else //горизонтальное
{
set_menu_format(menu, 1, itemnames.size());
menu_opts_off(menu, O_ROWMAJOR);
menu_opts_off(menu, O_SHOWDESC);
set_menu_mark(menu, " ");
}
//set_menu_win(menu, win);
menu_opts_off(menu,O_SHOWMATCH);
postmenu();
}
else
{
if (strlen(name) > 0)
{
itemnames.push_back(strdup(name));
itemcomments.push_back(strdup(comment));
mitems[itemnames.size()-1] = new_item(itemnames.back(),itemcomments.back());
}
else
{
itemnames.push_back(strdup(" "));
itemcomments.push_back(strdup(" "));
mitems[itemnames.size()-1] = new_item(itemnames.back(),itemcomments.back());
item_opts_off(mitems[itemnames.size()-1], O_SELECTABLE);
}
}
}
void NMenu::refresh()
{
//int rows, cols;
//menu_format(menu, &rows, &cols);
if (getheight() == 1) //только для горизонтального меню
{
//закрашиваем фоном правую часть строки
wattrset(win,bgattr);
wmove(win,0,menu->width);
//clrtoeol();
int x,y;
do
{
getyx(win, y, x);
wprintw(win," ");
}
while (x < getwidth() - 1);
//wattrset(win,0);
}
if (scrollbar)
{
scrollbar->setpos(0,itemnames.size(),top_row(menu),top_row(menu)+getheight()-2);
scrollbar->refresh();
}
NGroup::refresh();
}
void NMenu::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return; //событие уже обработано кем-то ранее
//отправляем всем подменю
NGroup::eventhandle(ev);
if ( ev->done )
return; //выходим если какое-то подменю обработало событие
//пытаемся обработать самостоятельно
int y,x;
menu_format(menu, &y, &x);
NMouseEvent* mevent = (NMouseEvent*)ev;
//колесо прокрутки мыши
if ( ev->type == NEvent::evMOUSE )
{
if (isinside(mevent->row, mevent->col))
{
//колесо вверх
#if NCURSES_MOUSE_VERSION > 1
if (mevent->cmdcode & BUTTON4_PRESSED) //NOT TESTED
#else
if (mevent->cmdcode & BUTTON4_PRESSED)
#endif
{
if ( y > 1 )
{
if (item_index(current_item(menu)) > 0) //элемент не первый
{
ITEM* preditem = mitems[item_index(current_item(menu)) - 1]; //предыдущий
menu_driver(menu, REQ_SCR_UPAGE);
}
ev->done = true;
}
}
//колесо вниз
#if NCURSES_MOUSE_VERSION > 1
if (mevent->cmdcode & BUTTON5_PRESSED) //NOT TESTED
#else
if ( mevent->cmdcode & (BUTTON2_PRESSED | REPORT_MOUSE_POSITION)) //REPORT_MOUSE_POSITION подпорка иначе теряет эвенты при быстрой прокрутке вниз
#endif
{
if ( y > 1 ) //вертикальное
{
ITEM* nextitem = mitems[item_index(current_item(menu)) + 1]; //какой следующий
if (nextitem != NULL) //элемент не последний
menu_driver(menu, REQ_SCR_DPAGE);
ev->done = true;
}
}
}
}
//одиночный или двойной клик
if (( ev->type == NEvent::evMOUSE ) && (((mevent->cmdcode & BUTTON1_CLICKED))||((mevent->cmdcode & BUTTON1_DOUBLE_CLICKED))))
{
if (isinside(mevent->row, mevent->col))
{
int n;
if (y > 1) //вертикальное
n = mevent->row - getabsbegrow() - 1 + menu->toprow;
else //горизонтальное
n = mevent->col/(menu->itemlen+menu->spc_cols) - getabsbegcol();
if ((n >= 0)&&(n < item_count(menu)))
{
if ( (item_opts(mitems[n]) & O_SELECTABLE) != 0 )
{
set_current_item(menu, mitems[n]); //сделеть n-ный активным
destroysubmenu(); //закрыть субменю
if ((y == 1)||(mevent->cmdcode & BUTTON1_DOUBLE_CLICKED))
action(); //putevent(new NEvent(NEvent::evKB, KEY_ENTER)); //открыть соотв субменю
}
ev->done = true;
}
}
}
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_ENTER:
case '\n':
action();
break;
/*
case KEY_RIGHT:
if ( x > 1)
menu_driver(menu, REQ_RIGHT_ITEM);
else
ev->done = false;
break;
case KEY_LEFT:
if ( x > 1 )
menu_driver(menu, REQ_LEFT_ITEM);
else
ev->done = false;
break;
*/
case KEY_UP:
if ( y > 1 )
{
if (item_index(current_item(menu)) > 0) //элемент не первый
{
ITEM* preditem = mitems[item_index(current_item(menu)) - 1]; //предыдущий
menu_driver(menu, REQ_UP_ITEM);
if ( (item_opts(preditem) & O_SELECTABLE) == 0 )
menu_driver(menu, REQ_UP_ITEM); //чтобы пропустить разделитель
}
}
else
ev->done = false;
break;
case KEY_DOWN:
if ( y > 1 ) //вертикальное
{
ITEM* nextitem = mitems[item_index(current_item(menu)) + 1]; //какой следующий
if (nextitem != NULL) //элемент не последний
{
menu_driver(menu, REQ_DOWN_ITEM);
if ( (item_opts(nextitem) & O_SELECTABLE) == 0 )
menu_driver(menu, REQ_DOWN_ITEM); //чтобы пропустить разделитель
}
}
else
ev->done = false;
break;
default:
//если событие нам неизвестно, то отказываемся от его
//обработки (снимаем флаг done)
ev->done = false;
} //switch
}
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
boinctui-2.3.4/src/addmgrform.cpp 0000644 0000000 0000000 00000013207 12301564455 015457 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "addmgrform.h"
#include "mbstring.h"
#include "kclog.h"
#include "tuievent.h"
char* strlowcase(char* s); //в нижний регистр
AddAccMgrForm::AddAccMgrForm(int rows, int cols, Srv* srv, const char* mgrname) : NForm(rows,cols)
{
this->srv = srv;
settitle(mgrname);
this->mgrname = mgrname;
Item* account_manager = NULL;
if (srv !=NULL)
account_manager = srv->findaccountmanager(mgrname);
//поля
int row = 1;
genfields(row,account_manager);
//пересчитываем высоту формы, чтобы влезли все поля и центрируем
resize(row + 2,getwidth());
move(getmaxy(stdscr)/2-getheight()/2,getmaxx(stdscr)/2-getwidth()/2);
set_form_fields(frm, fields);
set_current_field(frm, fields[0]); //фокус на поле
post_form(frm);
this->refresh();
}
void AddAccMgrForm::genfields(int& line, Item* mgr) //создаст массив полей
{
FIELD* f;
if (mgr != NULL)
{
delfields();
//сообщение об ошибке
errmsgfield = getfieldcount();
f = addfield(new_field(1, getwidth()-2, line++, 1, 0, 0));
set_field_buffer(f, 0, "Errr");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_RED) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
field_opts_off(f, O_VISIBLE); //по умолчанию невидима
//url
Item* url = mgr->findItem("url");
std::string s = "url : ";
if (url !=NULL)
mgrurl = url->getsvalue();
s = s + mgrurl;
f = addfield(new_field(1, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, s.c_str());
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//help
line++;
f = addfield(new_field(3, getwidth()-4, line++, 2, 0, 0));
set_field_buffer(f, 0, "If you have not yet registered with this account manager" \
" please do so before proceeding.");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
line = line + 2;
//user name
line++;
f = addfield(new_field(1, 10, line, 2 , 0, 0));
set_field_buffer(f, 0, "username");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
usernamefield = getfieldcount();
f = addfield(new_field(1, 40, line++, 15, 0, 0));
field_opts_off(f, O_AUTOSKIP);
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
//password
line++;
f = addfield(new_field(1, 10, line, 2 , 0, 0));
set_field_buffer(f, 0, "password");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
passwfield = getfieldcount();
f = addfield(new_field(1, 40, line++, 15, 0, 0));
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_CYAN) | A_BOLD);
field_opts_off(f, O_AUTOSKIP);
}
//подсказки
line++;
f = addfield(new_field(1, getwidth()-25, line++, 20 , 0, 0));
set_field_buffer(f, 0, "Enter-Ok Esc-Cancel");
set_field_back(f, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
field_opts_off(f, O_ACTIVE); //статический текст
//финализация списка полей
addfield(NULL);
}
void AddAccMgrForm::eventhandle(NEvent* ev) //обработчик событий
{
if ( ev->done )
return;
NMouseEvent* mevent = (NMouseEvent*)ev;
if ( ev->type == NEvent::evMOUSE)
{
NForm::eventhandle(ev); //предок
}
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case KEY_ENTER:
case '\n': //ENTER
{
form_driver(frm, REQ_NEXT_FIELD); //костыль чтобы текущее поле не потеряло значение
char* username = strlowcase(rtrim(field_buffer(fields[usernamefield],0)));
char* passw = rtrim(field_buffer(fields[passwfield],0));
kLogPrintf("AddAccMgrForm OK username=[%s] passw=[%s]\n", username, passw);
if (srv!=NULL)
{
std::string errmsg;
bool success = srv->accountmanager(mgrurl.c_str(),username, passw, false, errmsg);
if (success)
putevent(new TuiEvent(evADDACCMGR)); //создаем событие чтобы закрыть форму
else
{
//СООБЩЕНИЕ ОБ ОШИБКЕ
errmsg = " Error: " + errmsg;
set_field_buffer(fields[errmsgfield], 0, errmsg.c_str());
field_opts_on(fields[errmsgfield], O_VISIBLE); //делаем видимой строку ошибки
this->refresh();
}
}
break;
}
case 27:
putevent(new TuiEvent(evADDACCMGR, srv, mgrname.c_str())); //код закрытия окна
break;
default:
kLogPrintf("AddAccMgrForm::KEYCODE=%d\n", ev->keycode);
ev->done = false;
NForm::eventhandle(ev); //предок
break;
} //switch
}
}
boinctui-2.3.4/src/nprogram.cpp 0000644 0000000 0000000 00000003047 12301564455 015163 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include "nprogram.h"
#include "kclog.h"
bool NProgram::needresize;
NProgram::NProgram() : NGroup(NRect(getmaxy(stdscr), getmaxx(stdscr), 0, 0))
{
NProgram::needresize = false;
signal(SIGWINCH, NProgram::sig_winch); //обработчик сигнала ресайза терминала
}
void NProgram::sig_winch(int signo) //вызывается при изменении размеров терминала
{
NProgram::needresize = true;
}
void NProgram::putevent(NEvent* ev) //отправить событие по цепочке владельцев в очередь
{
evqueue.push(ev); //поместить в очередь
#ifdef DEBUG
kLogPrintf("NProgram::putevent(%s)\n",ev->tostring().c_str());
#endif
}
boinctui-2.3.4/src/nprogram.h 0000644 0000000 0000000 00000002610 12301564455 014623 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NPROGRAM_H
#define NPROGRAM_H
#include
#include "ngroup.h"
class NProgram : public NGroup
{
public:
static bool needresize; //true если произошло изменение размеров терминала
NProgram();
virtual void putevent(NEvent* ev); //отправить событие по цепочке владельцев в очередь
static void sig_winch(int signo); //вызывается при изменении размеров терминала
protected:
std::queue evqueue; //очередь событий
};
#endif //NPROGRAM_H boinctui-2.3.4/src/nform.cpp 0000644 0000000 0000000 00000011433 12301564455 014455 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "nform.h"
#include "mbstring.h"
#include "kclog.h"
NForm::NForm(int rows, int cols) : NGroup(NRect(rows,cols,0,0))
{
fields = NULL;
fieldcount = 0;
modalflag = true;
frm = new_form(NULL);
scale_form(frm,&rows,&cols);
addfield(NULL);
set_form_win(frm, win);
set_form_sub(frm, derwin(win, rows, cols, 2,2));
wattrset(win,getcolorpair(COLOR_WHITE, COLOR_BLACK) | A_BOLD);
title = NULL;
needrefresh = true;
//перемещаем в центр экрана
this->move(getmaxy(stdscr)/2-getheight()/2,getmaxx(stdscr)/2-getwidth()/2);
curs_set(1); //курсор
}
NForm::~NForm()
{
unpost_form(frm);
free_form(frm);
delfields();
if (title != NULL)
free(title);
curs_set(0); //курсор
}
void NForm::settitle(const char* title)
{
this->title = (char*)malloc(strlen(title)+3);
snprintf(this->title, strlen(title)+3," %s ",title);
}
FIELD* NForm::addfield(FIELD* field)
{
fields = (FIELD**)realloc(fields, (fieldcount+1)*sizeof(FIELD*)); //выделяем память под массив полей
fields[fieldcount] = field;
fieldcount++;
if (field == NULL)
set_form_fields(frm, fields);
return field;
}
void NForm::delfields()
{
if (fields != NULL)
{
set_form_fields(frm, NULL);
int n = fieldcount - 1; //последний NULL
for (int i = 0; i < n; i++)
{
if (fields[i] != NULL)
{
int retcode = free_field(fields[i]);
if (retcode != E_OK)
kLogPrintf("NForm::delfields(): free_field(%p) retcode=%d\n", fields[i], retcode);
}
}
free(fields);
fields = NULL;
fieldcount = 0;
}
}
void NForm::refresh()
{
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(frm->win, ACS_VLINE, ACS_HLINE);
if(title != NULL)
{
mvwprintw(frm->win,0,getwidth()/2-mbstrlen(title)/2,"%s",title); //посередине
}
pos_form_cursor(frm); //восстановить позицию курсора ( после mvprintw() )
NGroup::refresh();
}
bool NForm::clickatfield(int mrow, int mcol, FIELD* f) //true если клик внутри этого поля
{
bool result = true;
int absbegrow = getabsbegrow();
int absbegcol = getabsbegcol();
kLogPrintf("frow=%d fcol=%d rows=%d cols=%d\n",f->frow,f->fcol,f->rows,f->cols);
if ((mrow < absbegrow + f->frow)||(mcol < absbegcol + f->fcol))
result = false;
if ((mrow > absbegrow + f->frow + f->rows - 1)||(mcol > absbegcol + f->fcol + f->cols - 1))
result = false;
return result;
}
void NForm::eventhandle(NEvent* ev) //обработчик событий
{
NGroup::eventhandle(ev); //предок
if ( ev->done )
return;
NMouseEvent* mevent = (NMouseEvent*)ev;
//одиночный или двойной клик
if ( ev->type == NEvent::evMOUSE )
ev->done = true;
if (( ev->type == NEvent::evMOUSE ) && (((mevent->cmdcode & BUTTON1_CLICKED))||((mevent->cmdcode & BUTTON1_DOUBLE_CLICKED))))
{
if (isinside(mevent->row, mevent->col))
{
if (fields != NULL)
{
int n = field_count(frm);
for (int i = 0; i < n; i++)
{
if (clickatfield(mevent->row, mevent->col, fields[i]))
{
set_current_field(frm, fields[i]);
form_driver(frm, REQ_END_LINE);
break;
}
}
}
}
}
//клавиатура
if ( ev->type == NEvent::evKB )
{
ev->done = true;
switch(ev->keycode)
{
case '\t':
form_driver(frm, REQ_NEXT_FIELD);
form_driver(frm, REQ_END_LINE);
break;
case KEY_BACKSPACE:
form_driver(frm, REQ_DEL_PREV);
break;
case KEY_LEFT:
form_driver(frm, REQ_PREV_CHAR);
break;
case KEY_RIGHT:
form_driver(frm, REQ_NEXT_CHAR);
break;
case KEY_DC:
form_driver(frm, REQ_DEL_CHAR);
break;
default:
form_driver(frm,ev->keycode); //передаем в форму
//ev->done = false; //нет реакции на этот код
} //switch
if (ev->done) //если обработали, то нужно перерисоваться
refresh();
}
}
boinctui-2.3.4/src/net.h 0000644 0000000 0000000 00000003445 12301564455 013573 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NET_H
#define NET_H
#include
#include
class TConnect //информация о соединении с boinc сервером
{
public:
TConnect(const char* shost, const char* sport) { this->shost = strdup(shost); this->sport = strdup(sport); hsock = -1; };
virtual ~TConnect() { disconnect(); free(shost); free(sport); };
int getsock() {return hsock;};
void sendreq(const char* fmt, va_list vl); //отправить запрос на сервер
void sendreq(const char* fmt, ...); //отправить запрос на сервер
char* waitresult(); //получить ответ на запрос
char* gethost() { return shost; };
char* getport() { return sport; };
bool isconnected() { return (hsock != -1); };
protected:
virtual void createconnect (/*const char* shost, const char* sport*/);
virtual void disconnect();
int hsock; //дескриптор сокета
char* shost;
char* sport;
};
#endif // NET_H
boinctui-2.3.4/src/mainwin.cpp 0000644 0000000 0000000 00000014130 12301564455 014773 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include "mainwin.h"
#include "tuievent.h"
#include "kclog.h"
#define INFPANWIDTH 20 //ширина инф панели
MainWin::MainWin(NRect rect/*, Config* cfg*/) : NGroup(rect)
{
colname.push_back(" # ");
colname.push_back("state ");
colname.push_back(" done%%");
colname.push_back(" project ");
colname.push_back(" est");
colname.push_back(" d/l");
colname.push_back(" application ");
colname.push_back(" task");
tablheader = new NStaticText(NRect(1, rect.cols -2-(INFPANWIDTH)-1, 1, 1));
tablheader->setstring(getcolorpair(COLOR_CYAN,COLOR_BLACK) | A_BOLD," # state done%% project est d/l task");
wtask = new TaskWin(NRect(getheight()/2, getwidth()-2-(INFPANWIDTH)-1, 2, 1)); //создаем окно процессов внутри wmain
setcoltitle();
taskscrollbar = new NScrollBar(NRect(wtask->getheight()+2,1, wtask->getbegrow()-2, getwidth()-INFPANWIDTH-2), ACS_TTEE | A_BOLD, 0, ACS_VLINE | A_BOLD); //скроллбар панели задач
wtask->setscrollbar(taskscrollbar);
wmsg = new MsgWin(NRect(getheight()-wtask->getheight()-4, getwidth()-2-(INFPANWIDTH+1), wtask->getheight()+3, 1)); //создаем окно евентов
hline = new NHLine(NRect(1, getwidth()-2-(INFPANWIDTH+1), wtask->getheight()+2, 1), NULL); //горизонтальная линия
// vline = new NVLine(NRect(wtask->getheight()+1/*getheight()-2*/, 1, 1, getwidth()-INFPANWIDTH-2), NULL); //вертикальная линия
msgscrollbar = new NScrollBar(NRect(wmsg->getheight()+2,1, wmsg->getbegrow()-1, getwidth()-INFPANWIDTH-2/*vline->getbegcol()*/),/*ACS_RTEE*/ACS_VLINE | A_BOLD,ACS_BTEE | A_BOLD, ACS_VLINE | A_BOLD); //скроллбар панели сообщений
wmsg->setscrollbar(msgscrollbar);
panel1 = new InfoPanel(NRect(getheight()-2,INFPANWIDTH,1,getwidth()-INFPANWIDTH-1));
caption = new NColorString(0,"");
insert(tablheader);
insert(wtask);
insert(wmsg);
insert(hline);
// insert(vline);
insert(taskscrollbar);
insert(msgscrollbar);
insert(panel1);
}
void MainWin::resize(int rows, int cols)
{
NGroup::resize(rows, cols);
tablheader->resize(1, getwidth()-2-(INFPANWIDTH)-1);
wtask->resize(getheight()/2, getwidth()-2-(INFPANWIDTH)-1); //размер окна задач
wmsg->resize(getheight()-wtask->getheight()-4, getwidth()-2-(INFPANWIDTH+1));
wmsg->move(wtask->getheight()+3, 1);
hline->resize(1, getwidth()-2-(INFPANWIDTH+1)); //горизонтальная линия
hline->move(wtask->getheight()+2, 1);
// vline->resize(wtask->getheight()+1/*getheight()-2*/, 1);
// vline->move(1 , getwidth()-INFPANWIDTH-2);
msgscrollbar->resize(wmsg->getheight()+2,1);
msgscrollbar->move(wmsg->getbegrow()-1, getwidth()-INFPANWIDTH-2/*vline->getbegcol()*/);
taskscrollbar->resize(wtask->getheight()+2,1);
taskscrollbar->move(wtask->getbegrow()-2, getwidth()-INFPANWIDTH-2);
panel1->resize(getheight()-2,INFPANWIDTH);
panel1->move(1,getwidth()-INFPANWIDTH-1);
}
void MainWin::setserver(Srv* srv) //установить отображаемый сервер
{
this->srv = srv;
wmsg->setserver(srv);
wtask->setserver(srv);
panel1->setserver(srv);
}
void MainWin::setcoltitle()
{
std::string s = "";
for (size_t i = 0; i < colname.size(); i++)
{
if (wtask->iscolvisible(i))
s = s + colname[i];
}
tablheader->setstring(getcolorpair(COLOR_CYAN,COLOR_BLACK) | A_BOLD, s.c_str());
}
void MainWin::refresh()
{
wattrset(win, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
if(asciilinedraw == 1)
wborder(win, '|', '|', '-', '-', '+', '+', '+', '+');
else
box(win, ACS_VLINE, ACS_HLINE);
//рисуем заголовок
wmove(win,0,(getwidth()/2)-(caption->getlen()+1)/2);
std::list::iterator it;
for (it = caption->parts.begin(); it != caption->parts.end(); it++) //цикл по частям тек строки
{
NColorStringPart* part = *it;
wattrset(win,part->attr);
wprintw(win,"%s",part->s.c_str());
//wattrset(win,0);
}
//wborder(win, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER);
//wattroff(win, getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD);
NGroup::refresh();
}
void MainWin::updatecaption()
{
NColorString oldcaption = *caption;
caption->clear();
caption->append(getcolorpair(COLOR_WHITE,COLOR_BLACK) | A_BOLD," Host %s:%s ",srv->gethost(),srv->getport());
if (srv->loginfail)
caption->append(getcolorpair(COLOR_WHITE,COLOR_RED) | A_BOLD,"unauthorized!");
else
{
if (!srv->isconnected())
caption->append(getcolorpair(COLOR_WHITE,COLOR_RED) | A_BOLD,"offline!");
}
if (oldcaption != *caption)
refresh();
}
void MainWin::eventhandle(NEvent* ev) //обработчик событий
{
NGroup::eventhandle(ev); //предок
if ( ev->done )
return;
if (ev->type == NEvent::evPROG) //прграммные
{
switch(ev->cmdcode)
{
case evCOLVIEWCH: //изменился набор колонок
{
setcoltitle();
tablheader->refresh();
wtask->refresh();
}
} //switch
}
//событие таймера
if (ev->type == NEvent::evTIMER) //таймер
{
updatecaption();
}
}
boinctui-2.3.4/src/ncolorstring.h 0000644 0000000 0000000 00000004515 12301564455 015527 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef NCOLORSTRING_H
#define NCOLORSTRING_H
#include
#include
#include
#include "mbstring.h"
#include "kclog.h"
class NColorStringPart
{
public:
NColorStringPart(int attr, const char* s) { this->s = s; this->attr = attr;};
NColorStringPart(int attr, const char* fmt, va_list vl);
int getlen() { return mbstrlen(s.c_str()); }; //вернет длинну в ЭКРАННЫХ СИМВОЛАХ
bool operator==(const NColorStringPart& v) { return (s == v.s)&&(attr == v.attr); };
NColorStringPart& operator=(const NColorStringPart& v) { s=v.s; attr=v.attr; return *this;};
std::string s;
int attr;
};
class NColorString
{
public:
NColorString() { };
NColorString(int attr, const char* fmt, ...);
NColorString(int attr, const char* fmt, va_list vl);
NColorString(const NColorString& v) { *this=v; };
~NColorString();
void append(int attr, const char* fmt, ...);
void vappend(int attr, const char* fmt, va_list vl);
std::list parts;
int getlen(); //вернет длинну в ЭКРАННЫХ СИМВОЛАХ
void clear() { while(!parts.empty()) { delete parts.front(); parts.remove(parts.front());} }; //очищаем строку
NColorString& operator=(const NColorString& v);
bool operator==(const NColorString& v);
bool operator!=(const NColorString& v) { return !(*this==v); };
protected:
void append(NColorStringPart* part) { parts.push_back(part); }; //добавить подстроку к строке
};
#endif //NCOLORSTRING_H boinctui-2.3.4/src/resultparse.cpp 0000644 0000000 0000000 00000011602 12301564455 015703 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#include
#include
#include
#include
#include "resultparse.h"
#include "kclog.h"
std::stack- curitem; //на верху стека указатель на текущий заполняемый эл-т а голова это вершина дерева
void callbackStartElement(void* userdata, const char* name, const char** atts); //колбэк начала эл-та
void callbackEndElement(void* userdata, const char* name); //коллбэк завершения эл-та
void callbackData(void *userdata, const char *content, int len); //коллбэк значения эл-та
char* stripinvalidtag(char* xml, int len) //ГРЯЗНЫЙ ХАК нужен чтобы до парсинга удалить кривые теги
//в сообщениях вида иначе будет ошибка парсинга
{
const char* teg1 = "";
const char* teg2 = "";
int bytesdone = 0; //просмотрено байт
char* pos = (char*)xml;
while (pos < xml + len)
{
char* x1 = strstr(pos, teg1);
char* x2 = strstr(pos, teg2);
if ((x1 != NULL)&&(x2 != NULL))
{
for(char* p = x1 + strlen(teg1); p < x2; p++)
{
if ((*p == '<')||(*p == '>')) //убираем html теги
*p = ' ';
}
pos = (x1>x2)? x1:x2; //берем наибольшую
pos++;
}
else
break;
}
return xml;
}
Item* xmlparse(const char* xml, int len) //xml строка с xml len ее размер в байтах
{
XML_Parser parser;
void* ret;
parser = XML_ParserCreate(NULL/*"UTF-8"*/);
XML_SetUserData(parser, (void*) &ret);
XML_SetElementHandler(parser, callbackStartElement, callbackEndElement); //устанавливаем колбэки
XML_SetCharacterDataHandler(parser, callbackData);
Item* roottree = new Item(""); //создаем корневой эл-т дерева
curitem.push(roottree); //и делаем его текущим
int retcode = XML_Parse(parser, xml, len, XML_TRUE); //собственно парсинг
if (retcode == XML_STATUS_ERROR)
{
kLogPrintf("XML Error: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
}
XML_ParserFree(parser);
while (!curitem.empty())
curitem.pop(); //очищаем стек
return roottree; //возвращаем постороенное дерево
}
void callbackStartElement(void* userdata, const char* name, const char** atts)
{
//kLogPrintf("\t+ %s\n",name);
//аттрибуты тегов типа
//length=4 это атрибут (в boinc таких тегов нет?)
/*
for(int i = 0; atts[i]; i += 2)
printf(" %s= '%s'", atts[i], atts[i + 1]);
printf("\n");
*/
//создаем новый эл-т дерева
Item* pitem = new Item(name);
//добавляем созданный эл-т в вышестоящий (если он есть)
if (!curitem.empty())
{
Item* parentitem = curitem.top(); //владелец всегда на верху стека
parentitem->addsubitem(pitem);
}
//делаем созданный эл-т текущим (кладем в стек)
curitem.push(pitem);
}
void callbackEndElement(void* userdata, const char* name)
{
//kLogPrintf("\t- %s\n",name);
//удаляем текущий эл-т из стека (текущим становится его родитель)
curitem.pop();
}
void callbackData(void *userdata, const char *content, int len)
{
char *tmp = (char*)malloc(len+1);
strncpy(tmp, content, len);
tmp[len] = '\0';
//data = (void *) tmp;
//kLogPrintf("\ncallbackData()-->[%s]<-- len=%d\n",tmp,len);
//заносим значение в текущий эл-т
bool empty = true;
for (int i = 0; i < strlen(tmp); i++)
{
if (tmp[i] != ' ')
{
empty = false;
break;
}
}
if ( (!empty) && (strcmp(tmp,"\n") != 0) ) //пропускаем пустые строки
{
Item* pitem = curitem.top(); //текущий на верху стека
pitem->appendvalue(tmp);
}
free(tmp);
}
boinctui-2.3.4/src/topmenu.h 0000644 0000000 0000000 00000012513 12301564455 014470 0 ustar root root // =============================================================================
// This file is part of boinctui.
// http://boinctui.googlecode.com
// Copyright (C) 2012,2013 Sergey Suslov
//
// boinctui is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// boinctui 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 General Public License for more details
// .
// =============================================================================
#ifndef TOPMENU_H
#define TOPMENU_H
#include "nmenu.h"
#include "srvdata.h"
class TopMenu : public NMenu //верхний уровень меню
{
public:
TopMenu(/*Config* cfg*/);
virtual void eventhandle(NEvent* ev); //обработчик событий
void enable() { if (!enableflag) {enableflag = true; set_menu_fore(menu, selectorattr); /*action();*/ } };
void disable() { if (enableflag) {enableflag = false; selectorattr = menu_fore(menu); set_menu_fore(menu, menu_back(menu)); destroysubmenu(); }; /*цвет указателя = цвет фона*/ };
bool isenable() { return enableflag; };
void setserver(Srv* srv) { this->srv = srv; }; //установить отображаемый сервер
virtual bool action(); //открыть субменю
protected:
int selectorattr; //цвет указателя
bool enableflag; //true если меню активно
Srv* srv; //текущий отображаемый сервер
// Config* cfg;
};
class ViewSubMenu : public NMenu //выпадающие меню "View"
{
public:
ViewSubMenu(NRect rect/*, Config* cfg*/);
protected:
virtual bool action(); //вызывается при нажатии Enter
bool iscolenable(/*Config* cfg,*/ int n);
};
class ProjectsSubMenu : public NMenu //выпадающие меню "Projects"
{
public:
ProjectsSubMenu(NRect rect, Srv* srv);
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
virtual bool action(); //вызывается при нажатии Enter
Srv* srv; //текущий отображаемый сервер
std::string accmgrurl; //url акк менеджера если есть
};
class TasksSubMenu : public NMenu //выпадающие меню "Tasks"
{
public:
TasksSubMenu(NRect rect);
protected:
virtual bool action(); //вызывается при нажатии Enter
};
class FileSubMenu : public NMenu //выпадающие меню "File"
{
public:
FileSubMenu(NRect rect);
protected:
virtual bool action(); //вызывается при нажатии Enter
};
class ProjectListSubMenu : public NMenu //выпадающие меню второго уровня Список проектов
{
public:
ProjectListSubMenu(NRect rect, Srv* srv, std::string projname);
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
virtual bool action(); //вызывается при нажатии Enter
Srv* srv; //текущий отображаемый сервер
std::string projname; //имя проекта
};
class ProjectAllListSubMenu : public NMenu //выпадающие меню второго уровня Список ВСЕХ проектов
{
public:
ProjectAllListSubMenu(NRect rect, Srv* srv);
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
virtual bool action(); //вызывается при нажатии Enter
Srv* srv; //текущий отображаемый сервер
};
class ProjectAccMgrSubMenu : public NMenu //выпадающие меню второго уровня Список Аккаунт менеджеров
{
public:
ProjectAccMgrSubMenu(NRect rect, Srv* srv);
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
virtual bool action(); //вызывается при нажатии Enter
Srv* srv; //текущий отображаемый сервер
};
class ProjectUserExistSubMenu : public NMenu //выпадающие меню третего New/Exist user
{
public:
ProjectUserExistSubMenu(NRect rect, Srv* srv, const char* prjname);
virtual void eventhandle(NEvent* ev); //обработчик событий
protected:
virtual bool action(); //вызывается при нажатии Enter
Srv* srv; //текущий отображаемый сервер
std::string prjname; //имя выбранного проекта
};
class ActivitySubMenu : public NMenu //выпадающие меню второго уровня Activity
{
public:
ActivitySubMenu(NRect rect, Srv* srv);
protected:
virtual bool action(); //вызывается при нажатии Enter
Srv* srv; //текущий отображаемый сервер
};
class HelpSubMenu : public NMenu //выпадающие меню "Help"
{
public:
HelpSubMenu(NRect rect);
protected:
virtual bool action(); //вызывается при нажатии Enter
};
#endif //TOPMENU_H boinctui-2.3.4/redhat/ 0000755 0000000 0000000 00000000000 12301564455 013306 5 ustar root root boinctui-2.3.4/redhat/boinctui.spec 0000644 0000000 0000000 00000001345 12301564455 016001 0 ustar root root Name: boinctui
Version: 2.2.1
Release: 0%{?dist}
Summary: curses based manager for Boinc client
Group: Applications/Communications
License: GPL-3.0+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
#Source0: boinctui-%{version}.tgz
Source0: boinctui-%{version}.tar.gz
BuildRequires: autoconf ncurses-devel expat-devel openssl-devel
#Requires: libcurses libexpat
%description
boinctui is a fullscreen text based control tool for BOINC client.
based on curses library
%prep
#echo ----- %{SOURCE0}
#cp %{SOURCE0} %{buildroot}
#%setup -q -n %{name}
%setup -q -n %{name}-%{version}
%build
autoconf
./configure --without-gnutls
make clean
make
%install
make DESTDIR=%{buildroot} install
%files
%{_bindir}/%{name}
boinctui-2.3.4/Makefile.in 0000644 0000000 0000000 00000004041 12301564455 014103 0 ustar root root include config
DEFS += -DVERSION=$(VERSION) @DEFS@
CPP = @CXX@
INSTALL_PROGRAM = install
SRCS = ncolorstring.cpp nhline.cpp nvline.cpp nscrollview.cpp nselectlist.cpp nview.cpp \
ngroup.cpp nstatictext.cpp nform.cpp nprogram.cpp nmenu.cpp nmessagebox.cpp \
nscrollbar.cpp \
kclog.cpp cfg.cpp srvdata.cpp mbstring.cpp net.cpp resultparse.cpp resultdom.cpp \
mainprog.cpp infopanel.cpp mainwin.cpp msgwin.cpp taskwin.cpp tui-main.cpp \
cfgform.cpp topmenu.cpp about.cpp helpwin.cpp addprojectform.cpp addmgrform.cpp \
taskinfowin.cpp
OBJS = $(patsubst %.cpp,$(ODIR)/%.o,$(SRCS))
LIBS = @LIBS@
LDFLAGS = @LDFLAGS@ $(LIBS)
CXXFLAGS = @CXXFLAGS@
ODIR = .obj
SDIR = src
exec_prefix = @prefix@
prefix = @prefix@
DATAROOTDIR = @datarootdir@
BINDIR = @bindir@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
DOCDIR = $(DATAROOTDIR)@docdir@
BINDIR = @bindir@
ifeq (@HAVE_OPENSSL@, 1)
DEFS += -DHAVE_OPENSSL
endif
###############################################################################
all: createobj $(OBJS)
@echo "\nLinking...\n"
$(CPP) -o $(PACKAGE_TARNAME) $(OBJS) $(LDFLAGS)
$(ODIR)/%.o: $(SDIR)/%.cpp
@echo " "
$(CPP) -c $(CXXFLAGS) $(CPPFLAGS) $(DEFS) -o $(ODIR)/$*.o $<
clean:
rm -f $(ODIR)/*.o $(PACKAGE_TARNAME) config.log
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) $(PACKAGE_TARNAME) $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(DOCDIR)
$(INSTALL_PROGRAM) changelog $(DESTDIR)$(DOCDIR)
createobj:
@if ! [ -d "$(ODIR)" ] ; then echo "create $(ODIR)"; mkdir $(ODIR); fi
#srctgz: clean
# @if ! [ -d "../$(PACKAGE_TARNAME)-$(VERSION)" ] ; then echo "create symlink ../$(PACKAGE_TARNAME)-$(VERSION)->$(notdir $(CURDIR))"; ln -n -s $(notdir $(CURDIR)) ../$(PACKAGE_TARNAME)-$(VERSION); fi
# cd ..; tar --exclude-vcs -vzcf $(PACKAGE_TARNAME)_$(VERSION).orig.tar.gz \
# $(PACKAGE_TARNAME)-$(VERSION)/src \
# $(PACKAGE_TARNAME)-$(VERSION)/redhat \
# $(PACKAGE_TARNAME)-$(VERSION)/Makefile.in \
# $(PACKAGE_TARNAME)-$(VERSION)/configure.in \
# $(PACKAGE_TARNAME)-$(VERSION)/config
boinctui-2.3.4/configure.in 0000644 0000000 0000000 00000006045 12301564455 014355 0 ustar root root # -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
AC_INIT([boinctui], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src])
#AC_CONFIG_HEADER([config.h:config.h.in])
#AC_CONFIG_HEADERS([config])
AC_PREFIX_DEFAULT(/usr)
#AC_PREFIX_PROGRAM(make)
AC_SYS_LARGEFILE
# Checks for programs.
AC_PROG_CXX
#AC_PROG_CC
#AC_PROG_CPP
# Checks for libraries.
AC_ARG_WITH(
[ncursesw],
[AS_HELP_STRING([--without-ncursesw],[fallback to plain ncurses (disable utf8 support)])],
[
AC_CHECK_LIB(ncurses, main, , [AC_MSG_ERROR([Couldn't find ncurses library])] )
AC_CHECK_LIB(form, main, , [AC_MSG_ERROR([Couldn't find form library])] )
AC_CHECK_LIB(panel, main, , [AC_MSG_ERROR([Couldn't find panel library])] )
AC_CHECK_LIB(menu, main, , [AC_MSG_ERROR([Couldn't find menu library])] )
],
[
#use unicode ncursesw (default case)
AC_CHECK_LIB(ncursesw, main, , [AC_MSG_ERROR([Couldn't find ncursesw library])] )
#AC_CHECK_LIB(ncurses++w, main, , [AC_MSG_ERROR([Couldn't find ncurses++w library])] )
AC_CHECK_LIB(formw, main, , [AC_MSG_ERROR([Couldn't find formw library])] )
AC_CHECK_LIB(panelw, main, , [AC_MSG_ERROR([Couldn't find panelw library])] )
AC_CHECK_LIB(menuw, main, , [AC_MSG_ERROR([Couldn't find menuw library])] )
]
)
AC_CHECK_LIB(expat, main, , [AC_MSG_ERROR([Couldn't find expat library])] )
AC_CHECK_LIB(pthread, main, , [AC_MSG_ERROR([Couldn't find pthread library])] )
AC_ARG_WITH(
[gnutls],
[AS_HELP_STRING([--without-gnutls],[use openssl instead gnutls-openssl])],
[
HAVE_OPENSSL=1
AC_SUBST([HAVE_OPENSSL])
AC_CHECK_LIB(crypto , MD5_Init, , [AC_MSG_ERROR([Couldn't find crypto library])] )
],
[
#use gnutls-openssl (default case)
AC_CHECK_LIB(gnutls-openssl , MD5_Init, , [AC_MSG_ERROR([Couldn't find gnutls-openssl library])] )
#AC_CHECK_LIB(gnutls , MD5_Init, , [AC_MSG_ERROR([Couldn't find gnutls library])] )
]
)
# Checks for header files.
AC_LANG_PUSH([C++])
AC_CHECK_HEADERS( \
[ \
pthread.h \
string.h stdlib.h stdio.h sys/stat.h unistd.h stdarg.h sys/ioctl.h arpa/inet.h \
locale.h malloc.h sys/socket.h netdb.h signal.h ctype.h \
algorithm string list vector queue stack sstream \
expat.h curses.h form.h panel.h \
] , , [AC_MSG_ERROR([Couldn't find any headers])] )
AC_ARG_WITH(
[gnutls],
[AS_HELP_STRING([--without-gnutls],[use openssl instead gnutls-openssl])],
[
AC_CHECK_HEADERS( \
[ openssl/md5.h ] , , [AC_MSG_ERROR([Couldn't find openssl/md5.h header])] )
],
[
#use gnutls-openssl (default case)
AC_CHECK_HEADERS( \
[ gnutls/openssl.h ] , , [AC_MSG_ERROR([Couldn't find gnutls/openssl.h header])] )
]
)
AC_LANG_POP([C++])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS([mblen memset setlocale socket strdup strstr])
# Output files
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
boinctui-2.3.4/changelog 0000644 0000000 0000000 00000006000 12301564455 013705 0 ustar root root boinctui (2.3.4)
* bugfix: message list was shrink after any html tags in message body
* bugfix: unusable scrollbar in some of menues
boinctui (2.3.3)
* implemented mouse support
* scrollable widgets has scrollbars now
* optional ASCII line drawing mode (useful for wrong terminals
like putty etc.)
* message "unauthorize" add to caption then authorization failed
on boinc-client
* bugfix: last item of long menu has incomplet submenu
* bugfix: many memory leaks
boinctui (2.3.1)
* implemented detail task raw info window
* network requests moved to separete threads (ui not freeze then
network hang)
* confirmation dialogs for some operations (abort task, detach
project etc.)
* "Projects" menu restructured
* shortcut "A" added for abort selected task
* status line context depended
* configuration form automatically show at first boinctui start
* at "sort by estimate time" mode completed tasks moved to the end of list
boinctui (2.2.1)
* bugfix: double free memory (potential crash after edit host
list via Config form)
* "Sort by deadline" was added into View menu
boinctui (2.2.0)
* tasks list can be sorted by some columns
* implemented toggle "all tasks"/"hide done tasks"/"active only"
* migrate from openssl to gnutls-openssl
* bugfixes:
- unexpected crash in configuration form
- sometimes statistics panel doesn't update immediately after
switch between hosts
boinctui (2.1.1)
*bugfix: Configuration host list form's fields don't allow long strings
boinctui (2.1.0)
*"application name" column was added to task list
* each column in task list can on/off via menu "View"
* optional key "--without-ncursesw" was added to configure script. This key can disable utf8 and
perform linking with plain ncurses
* implemented support account managers (BAM etc). Attach/Detach/Syncronize
* implemented add/detach project directly (without account manager) as existing user or as new user
boinctui (1.2.0)
* bugfixes:
- percent done was always 0% on same locale setting
- workaround for negative estimate time
* Percent done for GPU tasks are color highlight (green for CUDA tasks, magenta for OpenCL)
* implemented GPU activity operations:
- run GPU always.
- run GPU based on preferences.
- suspend GPU always.
boinctui (1.1.0)
* bugfixes:
- any color combinations are invisible on any terminals
- incorrect visualization on any white background terminals
* implemented network activity operations:
- run always.
- run based on preferences.
- suspend always.
* implemented "Run benchmarks"
boinctui (1.0.0)
* implemented project operations:
- suspend.
- resume.
- reset.
- no new tasks.
- allow new tasks.
* add "abort task" in task menu
* implemented "Activity" features:
- run always.
- run based on preferences.
- suspend always.
* any bugfixes.
* color schem optimization.
boinctui (0.0.1)
* Initial Release.
boinctui-2.3.4/config 0000644 0000000 0000000 00000000156 12301564455 013231 0 ustar root root TARGET = boinctui
VERSION = 2.3.4
#DEFS += -DVERSION=$(VERSION)
#DEFS += -DDEBUG
DEFS += -DENABLEMOUSE