boinctui-2.3.6/src/0000755000175000017500000000000012644146335011771 5ustar ssssboinctui-2.3.6/src/tui-main.cpp0000644000175000017500000000401612644146301014212 0ustar ssss// ============================================================================= // 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.6/src/addmgrform.h0000644000175000017500000000272612644146301014264 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/cfg.cpp0000644000175000017500000001137512644146335013243 0ustar ssss// ============================================================================= // 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, errmsg); if (!errmsg.empty()) errmsg = fullname + std::string("\n") + errmsg; fclose (pfile); isdefault = false; } } void Config::save() { if (!errmsg.empty()) return; //если была ошибка при загрузке то файл не перезаписываем 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.6/src/srvdata.cpp0000644000175000017500000007250512644146335014152 0ustar ssss// ============================================================================= // 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(); std::string errmsg; Item* dom = xmlparse(b, strlen(b), errmsg); //парсим 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",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",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.6/src/nmessagebox.cpp0000644000175000017500000001314312644146301015003 0ustar ssss// ============================================================================= // 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.6/src/mainwin.cpp0000644000175000017500000001436612644146335014151 0ustar ssss// ============================================================================= // 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(); if (srv) { 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!"); } } else caption->append(getcolorpair(COLOR_WHITE,COLOR_RED) | A_BOLD,"no servers"); 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.6/src/nscrollview.h0000644000175000017500000000541012644146301014502 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/resultparse.cpp0000644000175000017500000001200012644146335015037 0ustar ssss// ============================================================================= // 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, std::string& errmsg) //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))); errmsg = std::string("XML error:") + std::string(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.6/src/taskinfowin.cpp0000644000175000017500000002675612644146301015042 0ustar ssss// ============================================================================= // This file is part of boinctui. // http://boinctui.googlecode.com // Copyright (C) 2012-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 #include "kclog.h" #include "taskinfowin.h" std::string raw2hr (Item* item) { std::stringstream result; if ( 0 == strcmp(item->getname(), "fraction_done") ) { double d = item->getdvalue(); result << std::setprecision(4) << d*100 << " %"; } if ( 0 == strcmp(item->getname(), "active_task_state") ) { int i = item->getivalue(); switch (i) { case 0: result << "uninitialized"; break; case 1: result << "executing"; break; case 9: result << "suspended"; break; case 5: result << "abort pending"; break; case 8: result << "quit pending"; break; case 10: result << "copy panding"; break; }//switch } if ( 0 == strcmp(item->getname(), "scheduler_state") ) { int i = item->getivalue(); switch (i) { case 1: result << "preempted"; break; case 2: result << "scheduled"; break; }//switch } if ( 0 == strcmp(item->getname(), "state") ) { int i = item->getivalue(); switch (i) { case 0: result << "new"; break; case 1: result << "downloading"; break; case 2: result << "downloaded"; break; case 3: result << "compute error"; break; case 4: result << "uploading"; break; case 5: result << "uploaded"; break; case 6: result << "aborted"; break; case 7: result << "upload failed"; break; }//switch } if ( 0 == strcmp(item->getname(), "exit_status") ) { int i = item->getivalue(); switch (i) { case 192: result << "exit statfile write"; break; case 193: result << "exit signal"; break; case 194: result << "aborted by client"; break; case 195: result << "exit child failed"; break; case 196: result << "exit disk limit exceeded"; break; case 197: result << "exit time limit exceeded"; break; case 198: result << "exit mem limit exceeded"; break; case 199: result << "exit client exiting"; break; case 200: result << "exit unstarted late"; break; case 201: result << "exit missing coproc"; break; case 202: result << "exit aborted by project"; break; case 203: result << "aborted via gui"; break; case 204: result << "exit unknown"; break; }//switch } if ( !strcmp(item->getname(), "received_time") || !strcmp(item->getname(), "report_deadline") || !strcmp(item->getname(), "completed_time") ) { time_t t = (time_t)item->getdvalue(); std::string s = ctime(&t); if (s.size() > 0) s.resize(s.size()-1); //убрать символ \n в конце result << s; } if ( !strcmp(item->getname(), "estimated_cpu_time_remaining") || !strcmp(item->getname(), "current_cpu_time") || !strcmp(item->getname(), "final_cpu_time") || !strcmp(item->getname(), "final_elapsed_time") || !strcmp(item->getname(), "checkpoint_cpu_time") || !strcmp(item->getname(), "elapsed_time") ) { time_t t = (time_t)item->getdvalue(); time_t t2; int days = t / (24 * 3600); t2 = t - (days * 24 * 3600); int hours = t2 / 3600; t2 = t2 - hours * 3600; int mins = t2 / 60; int secs = t2 - mins * 60; if (days) result << days << "d " << hours << "h " << mins << "m " << secs << "s"; else { if (hours) result << hours << "h " << mins << "m " << secs << "s"; else { if (mins) result << mins << "m " << secs << "s"; else result << secs << "s"; } } } return result.str(); } 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 { std::string sval = (*it2)->getsvalue(); std::string svalhr = raw2hr(*it2); if (svalhr.length()) sval = sval + " (" + svalhr + ")"; if (strlen((*it2)->getname()) > maxlen1) maxlen1 = strlen((*it2)->getname()); if (sval.length()/*strlen((*it2)->getsvalue())*/ > maxlen2) maxlen2 = sval.length() /*strlen((*it2)->getsvalue())*/; vout.push_back(std::pair((*it2)->getname(), sval/*(*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.6/src/tuievent.h0000644000175000017500000001020412644146335014002 0ustar ssss// ============================================================================= // 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 рамок evPOPUPMSG //генерируется когда нужно открыть попап сообщение }; 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; }; TuiEvent(TuiEventType type, const char* caption, const char* msg) : NEvent(evPROG, type) //событие попап сообщения { this->sdata1 = caption; this->sdata2 = msg; }; virtual ~TuiEvent() { /*kLogPrintf("~TuiEvent()\n");*/ }; Srv* srv; std::string sdata1; //произвольная строка std::string sdata2; //произвольная строка bool bdata1; //произаольная bool переменная int idata1; //произвольное целое }; #endif //TUIEVENT_H boinctui-2.3.6/src/addmgrform.cpp0000644000175000017500000001320712644146301014613 0ustar ssss// ============================================================================= // 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.6/src/nevent.h0000644000175000017500000000471512644146301013441 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nrect.h0000644000175000017500000000241212644146301013245 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/mainprog.h0000644000175000017500000000406412644146301013753 0ustar ssss// ============================================================================= // 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.6/src/nview.h0000644000175000017500000000631512644146301013270 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nvline.h0000644000175000017500000000225312644146301013430 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/cfgform.h0000644000175000017500000000306612644146301013563 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/infopanel.h0000644000175000017500000000753412644146301014117 0ustar ssss// ============================================================================= // 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.6/src/helpwin.cpp0000644000175000017500000000650712644146301014144 0ustar ssss// ============================================================================= // 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.6/src/nform.h0000644000175000017500000000313112644146301013252 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nhline.h0000644000175000017500000000225312644146301013412 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/mbstring.h0000644000175000017500000000231712644146301013763 0ustar ssss// ============================================================================= // 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.6/src/nvline.cpp0000644000175000017500000000205112644146301013757 0ustar ssss// ============================================================================= // 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.6/src/mbstring.cpp0000644000175000017500000000461312644146301014317 0ustar ssss// ============================================================================= // 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.6/src/resultparse.h0000644000175000017500000000240112644146335014510 0ustar ssss// ============================================================================= // 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, std::string& errmsg); //xml строка с xml len ее размер в байтах char* stripinvalidtag(char* xml, int len); //ГРЯЗНЫЙ ХАК нужен чтобы до парсинга удалить кривые теги //в сообщениях вида иначе будет ошибка парсинга #endif // RESULTPARSE_H boinctui-2.3.6/src/nscrollbar.h0000644000175000017500000000347412644146301014304 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/addprojectform.h0000644000175000017500000000315412644146301015141 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nmenu.h0000644000175000017500000000456112644146301013263 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nview.cpp0000644000175000017500000000735512644146301013630 0ustar ssss// ============================================================================= // 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.6/src/mainwin.h0000644000175000017500000000427212644146301013602 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/taskinfowin.h0000644000175000017500000000307712644146301014476 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/msgwin.cpp0000644000175000017500000001071212644146301013773 0ustar ssss// ============================================================================= // 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.6/src/resultdom.cpp0000644000175000017500000001127612644146301014513 0ustar ssss// ============================================================================= // 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 + "\n"; indent--; return result; } boinctui-2.3.6/src/taskwin.h0000644000175000017500000000475612644146301013627 0ustar ssss// ============================================================================= // 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.6/src/nselectlist.h0000644000175000017500000000465412644146301014475 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/srvdata.h0000644000175000017500000002000612644146301013575 0ustar ssss// ============================================================================= // 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.6/src/helpwin.h0000644000175000017500000000224712644146301013606 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/taskwin.cpp0000644000175000017500000005222512644146335014163 0ustar ssss// ============================================================================= // 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"; //была завершена с ошибкой if (state->getivalue() == 6) return "Abort"; //была прервана // 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"; case 6: return "Abort"; } 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; time_t value = time; //секунды if (value == 0) s << "- "; else { if (value <= 99) s << value << "s"; //возвращаем только секунды else { value = value / 60; //минуты if (value <= 99) s << value << "m"; //возвращаем только минуты else { value = value / 60; //часы if (value <= 99) s << value << "h"; //возвращаем только часы else { value = value / 24; //дни if (value <= 99) s << value << "d"; //возвращаем только дни else s << "inf"; // возвращаем "inf" дни не умещаются в два разряда } } } } /* 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") || ( sstate == "Abort")) stateattr = getcolorpair(COLOR_RED,COLOR_BLACK)/* | A_BOLD*/; //проверяем нужно-ли отображать эту задачу 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); //выключаем болд для незапущенных 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", (beforedl>0) ? gethumanreadabletimestr(beforedl).c_str() : "dead"); } 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.6/src/nmenu.cpp0000644000175000017500000002172212644146301013614 0ustar ssss// ============================================================================= // 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.6/src/topmenu.h0000644000175000017500000001251312644146301013624 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/ngroup.h0000644000175000017500000000340012644146301013442 0ustar ssss// ============================================================================= // 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.6/src/nprogram.h0000644000175000017500000000453312644146301013765 0ustar ssss// ============================================================================= // 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 #ifdef EVENTTHREAD #include #endif #include #include "ngroup.h" #define EVTIMERINTERVAL 2 //число секунд через которые генерируется evTIMER class NProgram : public NGroup { public: static bool needresize; //true если произошло изменение размеров терминала NProgram(); #ifdef EVENTTHREAD ~NProgram() { stopflag=true; pthread_join(thread, NULL); pthread_mutex_destroy(&mutex); }; void lock() { pthread_mutex_lock(&mutex); }; void unlock() { pthread_mutex_unlock(&mutex); }; bool evqueueempty() { bool result; lock(); result=evqueue.empty(); unlock(); return result; }; NEvent* popevent() { NEvent* result; lock(); result=evqueue.front(); evqueue.pop(); unlock(); return result; }; #else bool evqueueempty() { return evqueue.empty(); }; NEvent* popevent() { NEvent* result=evqueue.front(); evqueue.pop(); return result; }; #endif virtual void putevent(NEvent* ev); //отправить событие по цепочке владельцев в очередь static void sig_winch(int signo); //вызывается при изменении размеров терминала private: std::queue evqueue; //очередь событий #ifdef EVENTTHREAD pthread_mutex_t mutex; pthread_t thread; bool stopflag; static void* evcreationthread(void* args); //трейд опрашивающий клавиатуру и мышь #endif }; #endif //NPROGRAM_Hboinctui-2.3.6/src/cfgform.cpp0000644000175000017500000001516512644146301014121 0ustar ssss// ============================================================================= // 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.6/src/nwin.h0000644000175000017500000000152212644146301013106 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/ncolorstring.h0000644000175000017500000000451512644146301014663 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/addprojectform.cpp0000644000175000017500000002214412644146301015474 0ustar ssss// ============================================================================= // 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.6/src/about.cpp0000644000175000017500000000502312644146301013600 0ustar ssss// ============================================================================= // 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.6/src/kclog.h0000644000175000017500000000221712644146301013234 0ustar ssss// ============================================================================= // 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.6/src/mainprog.cpp0000644000175000017500000004210512644146335014313 0ustar ssss// ============================================================================= // 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" 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(); if (gsrvlist->getcursrv()) { 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 evPOPUPMSG: { TuiEvent* ev1 = (TuiEvent*)ev; NMessageBox* mbox = new NMessageBox((ev1->sdata1 + "\n" + ev1->sdata2).c_str()); NEvent* buttonNev = new NEvent(NEvent::evKB, 27); //событие для кнопки Ok mbox->addbutton(new NMButton("Ok",buttonNev, 'O','o',27,'\n',0)); insert(mbox); uistate = uistate | stUIMODALFORM; 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->errmsg.empty()) putevent(new TuiEvent(evPOPUPMSG, "Config error:", gCfg->errmsg.c_str())); else { 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(); } #ifndef EVENTTHREAD //если настало время посылаем 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); //отправить в очередь } #endif //есть события в очереди - выполняем while(!evqueueempty()) { NEvent* event = popevent(); //получить первое событие из очереди 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); #ifdef EVENTTHREAD usleep(10000); //10 milisec #endif } while(!done); } boinctui-2.3.6/src/msgwin.h0000644000175000017500000000273112644146301013442 0ustar ssss// ============================================================================= // 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.6/src/about.h0000644000175000017500000000216212644146301013246 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nselectlist.cpp0000644000175000017500000001112312644146301015015 0ustar ssss// ============================================================================= // 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.6/src/ncolorstring.cpp0000644000175000017500000000555412644146301015222 0ustar ssss// ============================================================================= // 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.6/src/resultdom.h0000644000175000017500000000640712644146301014160 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/nstatictext.h0000644000175000017500000000304612644146301014510 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/net.h0000644000175000017500000000344512644146301012727 0ustar ssss// ============================================================================= // 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.6/src/cfg.h0000644000175000017500000000406712644146335012710 0ustar ssss// ============================================================================= // 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 если конфиг не найден и создан дефолтный std::string errmsg; //строка ошибки возникшей при загрузке файла конфига protected: char* fullname; //полное имя файла Item* root; //корень дерева конфига }; extern Config* gCfg; #endif //CFG_H boinctui-2.3.6/src/ngroup.cpp0000644000175000017500000000742512644146301014010 0ustar ssss// ============================================================================= // 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.6/src/infopanel.cpp0000644000175000017500000003356612644146301014456 0ustar ssss// ============================================================================= // 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.6/src/nprogram.cpp0000644000175000017500000000655112644146301014322 0ustar ssss// ============================================================================= // 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 "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); //обработчик сигнала ресайза терминала #ifdef EVENTTHREAD pthread_mutex_init(&mutex,NULL); stopflag = false; if ( 0 != pthread_create(&thread, NULL, evcreationthread, this)) kLogPrintf("NProgram::NProgram() pthread_create() error\n"); #endif } void NProgram::sig_winch(int signo) //вызывается при изменении размеров терминала { NProgram::needresize = true; } void NProgram::putevent(NEvent* ev) //отправить событие по цепочке владельцев в очередь { #ifdef EVENTTHREAD lock(); #endif evqueue.push(ev); //поместить в очередь #ifdef EVENTTHREAD unlock(); #endif #ifdef DEBUG kLogPrintf("NProgram::putevent(%s)\n",ev->tostring().c_str()); #endif } #ifdef EVENTTHREAD void* NProgram::evcreationthread(void* args) //трейд опрашивающий клавиатуру и мышь { NProgram* me = (NProgram*)args; kLogPrintf("NProgram::evcreationthread started\n"); time_t evtimertime; //time of last evTIMER time(&evtimertime); evtimertime=evtimertime-2; //костыль для уменьшения задержки первой отрисовки while(!me->stopflag) { //если настало время посылаем evTIMER if (time(NULL) - evtimertime > EVTIMERINTERVAL) { NEvent* event = new NEvent(NEvent::evTIMER, 0); //создаем событие таймера me->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) me->putevent(event); //отправить в очередь } } kLogPrintf("NProgram::evcreationthread stopped\n"); pthread_exit(0); } #endif boinctui-2.3.6/src/nscrollview.cpp0000644000175000017500000001517712644146301015050 0ustar ssss// ============================================================================= // 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 строк вверх или вниз { if (content.size()>getheight()) { //kLogPrintf("NScrollView::scrollto(%d) startindex=%d content.size()=%d getheight()=%d\n",delta, startindex, content.size(), getheight()); 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 ( startindex < 0 ) startindex = 0; } 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.6/src/kclog.cpp0000644000175000017500000000555712644146301013601 0ustar ssss// ============================================================================= // 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.6/src/nscrollbar.cpp0000644000175000017500000001021012644146301014621 0ustar ssss// ============================================================================= // 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.6/src/nhline.cpp0000644000175000017500000000205012644146301013740 0ustar ssss// ============================================================================= // 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.6/src/nmessagebox.h0000644000175000017500000000331612644146301014451 0ustar ssss// ============================================================================= // 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_Hboinctui-2.3.6/src/net.cpp0000644000175000017500000001016312644146301013255 0ustar ssss// ============================================================================= // 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.6/src/nform.cpp0000644000175000017500000001143312644146301013611 0ustar ssss// ============================================================================= // 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.6/src/nstatictext.cpp0000644000175000017500000000403012644146301015035 0ustar ssss// ============================================================================= // 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.6/src/topmenu.cpp0000644000175000017500000007671712644146301014177 0ustar ssss// ============================================================================= // 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.6/redhat/0000755000175000017500000000000012644146301012442 5ustar ssssboinctui-2.3.6/redhat/boinctui.spec0000644000175000017500000000134512644146301015135 0ustar ssssName: 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.6/Makefile.in0000644000175000017500000000404112644146301013237 0ustar ssssinclude 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.6/configure.in0000644000175000017500000000604512644146301013511 0ustar ssss# -*- 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.6/changelog0000644000175000017500000000637212650136342013056 0ustar ssssboinctui (2.3.6) * bugfix: crach due boinctui.cfg incorrect. * more informative time format at task panel boinctui (2.3.5) * implemented human readable values in raw task info window * bugfix: incorrect dead line time for expired tasks 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.6/config0000644000175000017500000000020712650136342012363 0ustar ssssTARGET = boinctui VERSION = 2.3.6 #DEFS += -DVERSION=$(VERSION) #DEFS += -DDEBUG DEFS += -DENABLEMOUSE #DEFS += -DEVENTTHREAD