314 lines
7.2 KiB
C++
314 lines
7.2 KiB
C++
|
#include <algorithm>
|
||
|
#include "gui.h"
|
||
|
#include "unit++.h"
|
||
|
#ifdef HAVE_SSTREAM
|
||
|
#include <sstream>
|
||
|
#endif
|
||
|
using namespace unitpp;
|
||
|
using namespace std;
|
||
|
|
||
|
#ifdef GUI
|
||
|
static const char* const img_error[] = {
|
||
|
"14 14 2 1",
|
||
|
". c #ff0000",
|
||
|
"# c #ffffff",
|
||
|
"...########...",
|
||
|
"....######....",
|
||
|
".....####.....",
|
||
|
"#.....##.....#",
|
||
|
"##..........##",
|
||
|
"###........###",
|
||
|
"####......####",
|
||
|
"####......####",
|
||
|
"###........###",
|
||
|
"##..........##",
|
||
|
"#.....##.....#",
|
||
|
".....####.....",
|
||
|
"....######....",
|
||
|
"...########..."};
|
||
|
|
||
|
static const char* const img_fail[] = {
|
||
|
"14 14 2 1",
|
||
|
"# c #ff0000",
|
||
|
". c #ffffff",
|
||
|
"..............",
|
||
|
".##........##.",
|
||
|
".###......###.",
|
||
|
"..###....###..",
|
||
|
"...###..###...",
|
||
|
"....######....",
|
||
|
".....####.....",
|
||
|
".....####.....",
|
||
|
"....######....",
|
||
|
"...###..###...",
|
||
|
"..###....###..",
|
||
|
".###......###.",
|
||
|
".##........##.",
|
||
|
".............."};
|
||
|
|
||
|
static const char* const img_ok[] = {
|
||
|
"14 14 3 1",
|
||
|
"# c #00ff00",
|
||
|
"a c #00ff6a",
|
||
|
". c #ffffff",
|
||
|
"..........###.",
|
||
|
".........###..",
|
||
|
"........#a#...",
|
||
|
"........aa#...",
|
||
|
".......#aa....",
|
||
|
".......#a.....",
|
||
|
"......#aa.....",
|
||
|
"#.....aa#.....",
|
||
|
"###..#a#......",
|
||
|
".##.##a.......",
|
||
|
"..#aaa#.......",
|
||
|
"...#aa#.......",
|
||
|
"....##........",
|
||
|
".....#........"};
|
||
|
|
||
|
static const char* const img_empty[] = {
|
||
|
"14 14 2 1",
|
||
|
". c #f0f0f0",
|
||
|
"# c #ffffff",
|
||
|
"..............",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".############.",
|
||
|
".............."};
|
||
|
|
||
|
|
||
|
cnt_item::cnt_item(QWidget* par, const QString& txt, const QColor& col,
|
||
|
const char* name)
|
||
|
: QHBox(par, name), v(0)
|
||
|
{
|
||
|
setSpacing(3);
|
||
|
setMargin(5);
|
||
|
val = new QLabel("0", this);
|
||
|
val->setAlignment(QLabel::AlignVCenter | QLabel::AlignRight);
|
||
|
QPalette pal(val->palette());
|
||
|
QColorGroup cg(pal.active());
|
||
|
cg.setColor(QColorGroup::Foreground, col);
|
||
|
pal.setActive(cg);
|
||
|
val->setPalette(pal);
|
||
|
label = new QLabel(txt, this);
|
||
|
}
|
||
|
void cnt_item::value(int iv)
|
||
|
{
|
||
|
v = iv;
|
||
|
val->setNum(v);
|
||
|
}
|
||
|
void cnt_item::inc()
|
||
|
{
|
||
|
value(v+1);
|
||
|
}
|
||
|
|
||
|
cnt_line::cnt_line(const QString& txt, QWidget* par, const char* name)
|
||
|
: QHBox(par, name)
|
||
|
{
|
||
|
label = new QLabel(txt, this);
|
||
|
QFont font(label->font());
|
||
|
font.setBold(true);
|
||
|
label->setFont(font);
|
||
|
cnts[0] = new cnt_item(this, "Total");
|
||
|
cnts[1] = new cnt_item(this, "OK", green);
|
||
|
cnts[2] = new cnt_item(this, "Fail", red);
|
||
|
cnts[3] = new cnt_item(this, "Error", red);
|
||
|
setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
|
||
|
}
|
||
|
|
||
|
void cnt_line::max(int m) { cnts[id_max]->value(m); }
|
||
|
void cnt_line::inc_ok() { cnts[id_ok]->inc(); }
|
||
|
void cnt_line::inc_fail() { cnts[id_fail]->inc(); }
|
||
|
void cnt_line::inc_error() { cnts[id_error]->inc(); }
|
||
|
void cnt_line::reset()
|
||
|
{
|
||
|
for (int i = id_ok; i < n_id; ++i)
|
||
|
cnts[i]->value(0);
|
||
|
}
|
||
|
|
||
|
res_stack::res_stack(const QString& txt, QWidget* par, const char* name)
|
||
|
: QVBox(par, name)
|
||
|
{
|
||
|
cnts = new cnt_line(txt, this, name);
|
||
|
bar = new QProgressBar(this);
|
||
|
setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
|
||
|
}
|
||
|
void res_stack::max(int v)
|
||
|
{
|
||
|
cnts->max(v);
|
||
|
bar->setTotalSteps(v);
|
||
|
}
|
||
|
void res_stack::inc_progress(bool err)
|
||
|
{
|
||
|
QPalette pal(bar->palette());
|
||
|
QColorGroup cg(pal.active());
|
||
|
QColor red(255,0,0);
|
||
|
QColor green(0,244,0);
|
||
|
cg.setColor(QColorGroup::Highlight, err ? red : green);
|
||
|
cg.setColor(QColorGroup::HighlightedText, black);
|
||
|
pal.setActive(cg);
|
||
|
pal.setInactive(cg);
|
||
|
pal.setDisabled(cg);
|
||
|
bar->setPalette(pal);
|
||
|
bar->setProgress(bar->progress()+1);
|
||
|
}
|
||
|
void res_stack::reset() {
|
||
|
cnts->reset();
|
||
|
bar->setProgress(0);
|
||
|
}
|
||
|
void res_stack::inc_ok() { cnts->inc_ok(); inc_progress(false); }
|
||
|
void res_stack::inc_fail() { cnts->inc_fail(); inc_progress(true); }
|
||
|
void res_stack::inc_error() { cnts->inc_error(); inc_progress(true); }
|
||
|
|
||
|
QHBox* behave(QHBox* box, bool x_expand, bool y_expand)
|
||
|
{
|
||
|
box->setSizePolicy(QSizePolicy(
|
||
|
x_expand ? QSizePolicy::Preferred : QSizePolicy::Maximum,
|
||
|
y_expand ? QSizePolicy::Preferred : QSizePolicy::Maximum));
|
||
|
box->setFrameShape(QFrame::StyledPanel);
|
||
|
box->setFrameShadow(QFrame::Raised);
|
||
|
box->setMargin(11);
|
||
|
box->setSpacing(6);
|
||
|
return box;
|
||
|
}
|
||
|
|
||
|
void node::setImg()
|
||
|
{
|
||
|
static QPixmap i_emp((const char**)img_empty);
|
||
|
static QPixmap i_ok((const char**)img_ok);
|
||
|
static QPixmap i_fail((const char**)img_fail);
|
||
|
static QPixmap i_err((const char**)img_error);
|
||
|
static QPixmap* imgs[] = { &i_emp, &i_ok, &i_fail, &i_err };
|
||
|
item->setPixmap(0, *(imgs[st]));
|
||
|
if (st > is_ok)
|
||
|
for (QListViewItem* ip = item; ip != 0; ip = ip->parent())
|
||
|
ip->setOpen(true);
|
||
|
};
|
||
|
|
||
|
node::node(suite_node* par, test& t)
|
||
|
: item(new QListViewItem(par->lvi(), t.name().c_str())), t(t), st(none)
|
||
|
{
|
||
|
par->add_child(this);
|
||
|
setImg();
|
||
|
}
|
||
|
node::node(gui* gp, test& t)
|
||
|
: item(new QListViewItem(gp->test_tree(), t.name().c_str())), t(t), st(none)
|
||
|
{
|
||
|
setImg();
|
||
|
item->setOpen(true);
|
||
|
}
|
||
|
void node::run()
|
||
|
{
|
||
|
for (QListViewItem* ip=item->firstChild(); ip != 0; ip=item->firstChild())
|
||
|
delete ip;
|
||
|
try {
|
||
|
t();
|
||
|
status(is_ok);
|
||
|
emit ok();
|
||
|
} catch (assertion_error& e) {
|
||
|
status(is_fail);
|
||
|
show_error(e);
|
||
|
emit fail();
|
||
|
} catch (exception& e) {
|
||
|
status(is_error);
|
||
|
show_error(e.what());
|
||
|
emit error();
|
||
|
} catch (...) {
|
||
|
status(is_error);
|
||
|
show_error("unknown ... exception");
|
||
|
emit error();
|
||
|
}
|
||
|
}
|
||
|
void node::show_error(assertion_error& e)
|
||
|
{
|
||
|
#ifdef HAVE_SSTREAM
|
||
|
ostringstream oss;
|
||
|
oss << e;
|
||
|
show_error(oss.str().c_str());
|
||
|
#else
|
||
|
show_error(e.what()); // not well, but some sign
|
||
|
#endif
|
||
|
}
|
||
|
void node::show_error(const char* msg)
|
||
|
{
|
||
|
QListViewItem* elvi = new QListViewItem(item, msg);
|
||
|
elvi->setSelectable(false);
|
||
|
}
|
||
|
suite_node::suite_node(suite_node* par, suite& t) : node(par, t) { }
|
||
|
suite_node::suite_node(gui* par, suite& t) : node(par, t) { }
|
||
|
void suite_node::run()
|
||
|
{
|
||
|
status(is_ok);
|
||
|
for (cctyp::iterator p = cc.begin(); p != cc.end(); ++p) {
|
||
|
(*p)->run();
|
||
|
status(max(status(), (*p)->status()));
|
||
|
}
|
||
|
switch (status()) {
|
||
|
case is_ok: emit ok(); break;
|
||
|
case is_fail: emit fail(); break;
|
||
|
case is_error: emit error(); break;
|
||
|
}
|
||
|
}
|
||
|
gui::gui(QApplication& app, QWidget* par, const char* name)
|
||
|
: QVBox(par, name), app(app)
|
||
|
{
|
||
|
setMargin(6);
|
||
|
setSpacing(3);
|
||
|
tree = new QListView(behave(new QVBox(this), true, true), "tree");
|
||
|
tree->addColumn("Test");
|
||
|
tree->setFrameShadow(QListView::Sunken);
|
||
|
tree->setResizePolicy(QScrollView::Manual);
|
||
|
tree->setRootIsDecorated(true);
|
||
|
QVBox* f_cnts = new QVBox(this);
|
||
|
behave(f_cnts, true, false);
|
||
|
suites = new res_stack("Suites", f_cnts);
|
||
|
tests = new res_stack("Tests", f_cnts);
|
||
|
QHBox* hbox = behave(new QHBox(this), true, false);
|
||
|
b_run = new QPushButton("Run", hbox, "run");
|
||
|
b_stop = new QPushButton("Stop", hbox, "stop");
|
||
|
b_quit = new QPushButton("Quit", hbox, "quit");
|
||
|
connect(b_quit, SIGNAL(clicked()), &app, SLOT(quit()));
|
||
|
connect(b_run, SIGNAL(clicked()), this, SLOT(run_pressed()));
|
||
|
connect(b_stop, SIGNAL(clicked()), this, SLOT(stop_pressed()));
|
||
|
}
|
||
|
|
||
|
gui::~gui() { }
|
||
|
|
||
|
void gui::processEvents(int t)
|
||
|
{
|
||
|
app.processEvents(t);
|
||
|
}
|
||
|
void gui::reset()
|
||
|
{
|
||
|
tests->reset();
|
||
|
suites->reset();
|
||
|
}
|
||
|
void gui::nconnect(node* n, res_stack* rs)
|
||
|
{
|
||
|
connect(n, SIGNAL(ok()), rs, SLOT(inc_ok()));
|
||
|
connect(n, SIGNAL(fail()), rs, SLOT(inc_fail()));
|
||
|
connect(n, SIGNAL(error()), rs, SLOT(inc_error()));
|
||
|
}
|
||
|
void gui::add_test(node* n)
|
||
|
{
|
||
|
nconnect(n, tests);
|
||
|
}
|
||
|
void gui::add_suite(node* n)
|
||
|
{
|
||
|
nconnect(n, suites);
|
||
|
}
|
||
|
|
||
|
void gui::totSuites(int v) { suites->max(v); }
|
||
|
void gui::totTests(int v) { tests->max(v); }
|
||
|
|
||
|
#endif
|