#include "device.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "utils.h" static const char *rPix[] = { "10 10 2 1", " c None", "X c #0000CC", "XX ", "XXXX ", "XXXXXX ", "XXXXXXXX ", "XXXXXXXXXX", "XXXXXXXXXX", "XXXXXXXX ", "XXXXXX ", "XXXX ", "XX ", }; static const char *dPix[] = { "10 10 2 1", " c None", "X c #0000CC", "XXXXXXXXXX", "XXXXXXXXXX", " XXXXXXXX ", " XXXXXXXX ", " XXXXXX ", " XXXXXX ", " XXXX ", " XXXX ", " XX ", " XX ", }; /* static const char *grPix[] = { "16 12 4 1", " c None", "/ c #CC0000", "- c #0000CC", "X c #000000", "XXXXXXXXXXXXXXXX", "X X", "X X", "X - X", "X ---- X", "X -- ----- X", "X ---- ----X", "X----- -X", "X-- X", "X X", "X X", "XXXXXXXXXXXXXXXX", }; static const char *gnPix[] = { "16 12 4 1", " c None", "/ c #CC0000", "- c #0000CC", "X c #000000", "X//XXXXXXXXXX//X", "X // // X", "X // // X", "X // - // X", "X //--// X", "X ////---- X", "X ----// ----X", "X-----//// -X", "X-- // // X", "X // // X", "X // // X", "XX//XXXXXXXX//XX", }; */ static int lineEditFrameWidth = 0; LineInput::LineInput(QWidget *parent, QString &labelTxt, const char *var) : QHBox(parent, var), value("") { QBoxLayout *l = dynamic_cast(layout()); l->setAutoAdd(false); label = new QLabel(labelTxt, this); label->setAlignment(Qt::AlignRight); l->addWidget(label); le = new QLineEdit(this, var); connect(le, SIGNAL(returnPressed()), this, SLOT(handleReturn())); connect(le, SIGNAL(lostFocus()), this, SLOT(focusLost())); QFont monospace("Courier"); monospace.setStyleHint(QFont::TypeWriter); le->setFont(monospace); l->addWidget(le); l->setSpacing(6); } void LineInput::setLength(int l) { QFontMetrics fm = le->fontMetrics(); if (l==0) { l = 9; } if (l <= 9) { le->setAlignment(Qt::AlignRight); } else { le->setAlignment(Qt::AlignLeft); } lineEditFrameWidth = le->frameWidth(); le->setFixedWidth(fm.width("0") * l + 2 * lineEditFrameWidth + 4); } int LineInput::stdWidth() { QBoxLayout *l = dynamic_cast(layout()); setLength(0); l->activate(); return label->width() + l->spacing() + 2 * l->margin() + le->width(); } void LineInput::handleReturn() { QString c(name()); if (le->text().isEmpty()) { c.append(" \"\""); } else { c.append(" "); c.append(le->text()); } sendCmd(c.latin1()); value = le->text(); changed(); } void LineInput::focusLost() { if (value.compare(le->text()) != 0) { handleReturn(); } } void LineInput::setValue(const QString &value) { if ((this->value.compare(le->text()) == 0) && this->value.compare(value) != 0) { le->setText(value); this->value = value; } } void LineInput::setEraseColor(const QColor & color) { QHBox::setEraseColor(color); label->setEraseColor(color); label->setEraseColor(color); } RdOnly::RdOnly(QWidget *parent, QString &labelTxt, QString &val, const char *var) : QHBox(parent, var) { QBoxLayout *l = dynamic_cast(layout()); l->setAutoAdd(false); label = new QLabel(labelTxt, this); value = new QLabel(val, this); QFont monospace("Courier"); monospace.setStyleHint(QFont::TypeWriter); value->setFont(monospace); label->setAlignment(Qt::AlignRight); value->setAlignment(Qt::AlignRight); l->addWidget(label); l->addWidget(value); l->setSpacing(6); len = 9; } void RdOnly::setLength(int l) { QFontMetrics fm = value->fontMetrics(); if (l==0) { l = 9; } len = l; if (l <= 9) { value->setAlignment(Qt::AlignRight); } else { value->setAlignment(Qt::AlignLeft); } value->setFixedWidth(fm.width("0") * l + 2 * lineEditFrameWidth + 4); } void RdOnly::setValue(const QString &val) { bool ok; double f; int p, i; QString v, ve; if (val.length() <= len) { // length is ok value->setText(val); return; } f = val.stripWhiteSpace().toDouble(&ok); if (!ok) { // it's not a number value->setText(val); return; } // try to reduce the length by reducing the precision for (p = 6; p > 0; p--) { v.setNum(f, 'g', p); i = v.find('e'); if (i >= 0) { i++; if (v[i] == '-') { i++; } else if (v[i] == '+') { // skip + in exponent v.remove(i,1); } if (v[i] == '0') { // skip leading 0 in exponent v.remove(i,1); } } if (v.length() <= len) { value->setText(v); return; } } value->setText(v); } CheckBox::CheckBox(const QString &label, QWidget *parent, const char *var) : QCheckBox(label, parent, var) { connect(this, SIGNAL(clicked()), this, SLOT(handleReturn())); } void CheckBox::handleReturn() { QString c(name()); if (isOn()) { c.append(" 1"); } else { c.append(" 0"); } sendCmd(c.latin1()); changed(); } void CheckBox::setValue(const QString &value) { if (value[0] == '0' || value[0] <= ' ') { if (isOn()) { setChecked(false); } } else { if (!isOn()) { setChecked(true); } } } ClickButton::ClickButton(QWidget *parent, const char *var) : QPushButton(parent, var) { dx = 0; } void ClickButton::handleReturn() { setFocus(); sendCmd(name()); changed(); } void ClickButton::setLabel(const QString &label) { QFontMetrics fm = fontMetrics(); if (dx == 0) { setText("BUTTON"); dx = (width() - fm.width("BUTTON")) / 3; } setText(label); setMaximumWidth(fm.width(text()) + dx); } RadioButton::RadioButton(const QString &label, QWidget *parent, const QString &cmdArg, const char *value) : QRadioButton(label, parent, value) { cmd = cmdArg; connect(this, SIGNAL(clicked()), this , SLOT(handleClick())); } void RadioButton::handleClick() { QString c(cmd); c.append(" "); c.append(name()); sendCmd(c.latin1()); clearOthers(name()); changed(); setFocus(); } void RadioButton::setValue(const QString &value) { setChecked(value.compare(name()) == 0); } void ColorMenu::init() { const QPixmap *pixmap; int i; setEditable(true); listBox()->setRowMode(QListBox::FitToHeight); insertItem(QString("auto"), 0); for (i=1; i < 16; i++) { pixmap = thisPixmap(i); if (pixmap == NULL) { i = -1; break; } insertItem(*pixmap, i); } connect(this, SIGNAL(activated(int)), this, SLOT(handleAct(int))); } ColorMenu::ColorMenu(QString &color, QWidget *parent) : QComboBox(parent, "settings") { init(); setCurrentItem(0); setCurrentText(color); } ColorMenu::ColorMenu(QWidget *parent, const char *var) : QComboBox(parent, var) { init(); nochange = true; setCurrentItem(0); setCurrentText(""); nochange = false; setLength(0); value = ""; connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(handleChange(const QString &))); } void ColorMenu::handleAct(int index) { QString text; // printf("*** handleAct %d\n", index); if (index > 0 && index < 16) { Convert2ColorName(index, text); nochange = true; setCurrentItem(0); nochange = false; value = text; setCurrentText(text); } // printf("*** handleAct end\n"); } void ColorMenu::setValue(const QString &text) { if (value.compare(currentText()) == 0 && value.compare(text) != 0) { // printf("*** setValue %s -> %s\n", value.latin1(), text.latin1()); nochange = true; setCurrentItem(0); value = text; setCurrentText(text); nochange = false; } } void ColorMenu::handleChange(const QString &text) { QString c(name()); int index; // printf("*** nochange %d empty %d\n", nochange, (text == "")); if (nochange || text == "") return; index = Convert2ColorIndex(text); if (index < -1) return; // not a valid text value = text; // printf("*** handleChange %s\n", text.latin1()); c.append(" "); c.append(text); sendCmd(c.latin1()); changed(); } int ColorMenu::getColorIndex() { int index = Convert2ColorIndex(currentText()); if (index < -1) { index = -1; } return index; } void ColorMenu::setLength(int min, int max) { QFontMetrics fm = fontMetrics(); if (min == 0) { min = 10; } if (max < min) { max = min; } setMinimumWidth(fm.width("0") * min + 8); setMaximumWidth(fm.width("0") * max + 8); } Menu::Menu(const QString &label, QWidget *parent, const char *var) : QComboBox(parent, var) { connect(this, SIGNAL(activated(const QString &)), this, SLOT(handleAct(const QString &))); } void Menu::handleAct(const QString &value) { QString c(name()); c.append(" "); c.append(value); sendCmd(c.latin1()); changed(); } void Menu::setValue(const QString &value) { setCurrentText(value); } /* GraphButton::GraphButton(QWidget *parent, const char *name) : QPushButton(parent, name) { setFlat(true); setPixmap(QPixmap(grPix)); connect(this, SIGNAL(clicked()), this, SLOT(handleClick())); setFixedSize(24,20); hide(); } void GraphButton::handleClick() { selectItem(name()); changed(); } */ bool PathStartsWith(QString &path, const char *name) { if (path.startsWith(name)) { int l = strlen(name); // if (path.length(name) == l || path[l] == '/') return true; if (path[l] == 0 || path[l] == '/') return true; } return false; } void Group::init() { indent = 0; isSelectMenu = false; colDiv = 1; } Group::Group(Device *p, const char *name, bool selectMenu) : QVBox(p->viewport(), name) , items(101,false) { //title = new QLabel("Title", this); //boxLayout->addWidget(title); parentGroup = 0; device = p; init(); arrow = 0; shown=true; title = 0; isSelectMenu = selectMenu; autoclose = false; } Group::Group(Group *p, const QString &tit, const char *name) : QVBox(p->device->viewport(), name) , items(101,false) { QFont bold; QBoxLayout *lay; parentGroup = p; device = p->device; init(); isSelectMenu = p->isSelectMenu; if (tit.isEmpty()) { arrow = 0; shown = true; } else { title = new QLabel(tit, this); lay = dynamic_cast(layout()); lay->setAutoAdd(false); lay->add(title); lay->addStretch(1); setFrameStyle(QFrame::MenuBarPanel); indent = p->indent + 20; arrow = new QPushButton(this, "arrow"); arrow->setFlat(true); SetEraseColor(arrow, topLevelWidget(), true); arrow->setPixmap(QPixmap(rPix)); arrow->setFixedSize(16, 16); bold = font(); bold.setWeight(75); setFont(bold); connect(arrow, SIGNAL(clicked()), this, SLOT(toggle())); shown=false; } } void Group::showIt(bool yes) { shown = yes; if (arrow) { // && arrow->isShown()) { if (shown) { arrow->setPixmap(QPixmap(dPix)); } else { arrow->setPixmap(QPixmap(rPix)); } } } void Group::newline() { device->x = indent; device->y = device->nextY; } void Group::add(Item *item, QWidget *w) { int frac, offs, hei, wid; QFont font; if (w == 0) w = item->w; if (wStyle != item->wStyle) { switch (item->wStyle) { case 0: item->normalFont = w->font(); case 'W': // remove warning style case 'A': // remove warning style // case 'G': // remove graph settings style w->setEraseColor(eraseColor()); break; case 'H': // remove header style w->setFont(item->normalFont); } switch (wStyle) { case 'W': // warning: yellow background w->setEraseColor(QColor(255,255,0)); break; case 'A': // warning: orange background w->setEraseColor(QColor(255,127,0)); break; // case 'G': // graph settings: grey background // w->setEraseColor(QColor(150,150,150)); // break; case 'H': // header style font = item->normalFont; font.setWeight(QFont::Normal); if (font.pointSize() > 0) { font.setPointSize(font.pointSize() * 6 / 4); } else { font.setPixelSize(font.pixelSize() * 6 / 4); } w->setFont(font); } item->wStyle = wStyle; } wStyle = 0; //printf("%s: add %s/%s %d\n", name(), w->className(), w->name(), sameRow); if (!sameRow) { frac = (device->x - indent) % (device->columnWidth / colDiv); device->x -= frac; if (frac > device->xspace / 2) { device->x += device->columnWidth / colDiv; } } if (item->w->layout()) { item->w->layout()->activate(); } w->resize(w->sizeHint()); wid = w->width(); hei = w->height(); if (device->x + wid > device->visibleWidth()) { newline(); } device->x += device->xspace; if (hei >= device->lineHeight) { offs = 0; device->nextY = QMAX(device->nextY, device->y + hei + device->yspace); } else { offs = (device->lineHeight - hei) / 2; device->nextY = QMAX(device->nextY, device->y + device->lineHeight + device->yspace); } device->addChild(item->w, device->x, device->y + offs); device->x += wid; device->maxWid = QMAX(device->maxWid, device->x); item->w->show(); item->used = true; sameRow = false; tight = false; if (!tip.isEmpty()) { QToolTip::add(item->w, tip); tip=""; } } void Group::initItem(Item *item, QWidget *w, const char *line, bool activate) { if (activate) { connect(w, SIGNAL(sendCmd(const char *)), device->com, SLOT(sendCmd(const char *))); connect(w, SIGNAL(changed()), device, SLOT(update())); } if (item->w) delete item->w; item->w = w; items.replace(line, item); } void Group::toggle() { if (shown) { if (autoclose) { autocloseAll(); // close containing groups } else { } autoclose = false; } showIt(!shown); device->update(false); } Item *Group::findItem(const char *name) { Item *item; item = items.find(name); if (!item) { item = new Item(); item->grp = this; } return item; } void Group::hideContents() { Item *item; Group *g; for (QDictIterator it(items); (item = it.current()); ++it) { if (item->used) { g = dynamic_cast(item->w); if (g) { if (g->shown) { g->hideContents(); } g->arrow->hide(); } item->w->hide(); /* if (item->graphButton) { item->graphButton->hide(); } */ } } } void Group::updateLayout(QStringList::Iterator &sit) { QString lineQ; int lwid=0; LineInput *lineInp; CheckBox *cb; QLabel *label; RdOnly *rdonly; Menu *menu=0; ColorMenu *colorMenu=0; ClickButton *pb; QString tit(""); QPtrStack stack; Group *grp; QString value; const char *line; Item *item; Item *rightItem = 0; int labelNum=0; char labelCode[8]; const char *arg; RadioButton *rb; QString radioName(""); QString radioLine(""); int i; int menuItem; int yline; bool autocloseOnRadio = false; // obsolete graph: char groupName[256]; device->x = indent; tip=""; sameRow = false; tight = false; wStyle = 0; for (QDictIterator it(items); (item = it.current()); ++it) { item->used = false; } for (; sit != device->code.end(); ++sit) { lineQ = (*sit); line = lineQ.latin1(); if (line[0] != '-') { if (line[0]) { if (printit()) printf("%s\n", line); } continue; } arg = line+2; //printf("L %s\n", line); switch (line[1]) { case '-': // no line break for next item tight = true; if (line[2] != '-') { sameRow = true; } break; case 'P': // line break newline(); break; case 'W': // custom width lwid = atoi(arg); break; case 'T': // group title tit = arg; break; case 'H': // help (tool tip) if (!tip.isEmpty()) { tip.append("\n"); } tip.append(arg); break; case '>': // add last item to group title line (experimental) rightItem = item; break; /* case 's': // auto open (for stick group), will be obsolete if (device->openGroups == "") { device->openGroups = "sticks"; device->update(); } break; */ case 'G': // group item = findItem(line); grp = dynamic_cast(item->w); if (grp == 0) { grp = new Group(this, tit, arg); initItem(item, grp, line); } else { grp->title->setText(tit); } if (device->openGroup != "" && PathStartsWith(device->openGroup, arg)) { grp->autoclose = false; if (device->openGroup == arg) { device->openGroup = ""; // opening finished } if (!grp->shown) grp->showIt(true); device->update(false); } if (arg[0] != '-' || grp->shown) { newline(); sameRow = true; device->x += 14; add(item, grp->title); if (shown && grp->arrow) { yline = device->y + 2; device->addChild(grp->arrow, indent + 2, yline); grp->arrow->show(); } /* if (device->doJump && !grp->shown) { // open automatically group tree in visibleGr (clicked on graph icon) snprintf(groupName, sizeof groupName, " %s ", grp->name()); if (device->visibleGr.find(groupName) >= 0) { grp->showIt(true); grp->closeLater = true; //printf("open %s\n", groupName); } } */ if (rightItem) { // device->addChild(rightItem->w, device->x + device->xspace, device->y); rightItem = 0; } else { newline(); } } tit=""; ++sit; grp->updateLayout(sit); newline(); if (grp->shown) { grp->setLineWidth(1); grp->setFrameStyle(QFrame::Box | QFrame::Sunken); grp->setFixedSize(device->width(), device->y - yline); device->y += 4; device->nextY += 4; } else { grp->setFrameStyle(QFrame::MenuBarPanel); grp->setFixedSize(device->width(), grp->title->height()); } grp->update(); if (sit == device->code.end()) --sit; break; case 'V': // value for next item value = arg; break; case 'i': // readonly item = findItem(line); rdonly = dynamic_cast(item->w); if (rdonly == 0) { rdonly = new RdOnly(device->viewport(), tit, value, arg); initItem(item, rdonly, line); } else { rdonly->label->setText(tit); } if (tight) { rdonly->label->setMinimumWidth(0); rdonly->value->setMinimumWidth(0); } else { rdonly->label->setMinimumWidth(device->labelWidth); rdonly->value->setMinimumWidth(device->leWidth); } add(item); lwid = 0; rdonly->setValue(value); value=""; break; case 'I': // text input item = findItem(line); lineInp = dynamic_cast(item->w); if (lineInp == 0) { lineInp = new LineInput(device->viewport(), tit, arg); initItem(item, lineInp, line, true); } else { lineInp->label->setText(tit); } lineInp->setLength(lwid); if (tight) { lineInp->label->setMinimumWidth(0); } else { lineInp->label->setMinimumWidth(device->labelWidth); } add(item); lwid = 0; lineInp->setValue(value); value=""; break; case 'S': // set style wStyle = arg[0]; break; case 'D': // divide column (typically -D2: double number of columns) colDiv = atoi(arg); break; case 'L': // label snprintf(labelCode, sizeof labelCode, "%d", labelNum); labelNum++; item = findItem(labelCode); label = dynamic_cast(item->w); if (label == 0) { label = new QLabel(arg, device->viewport()); initItem(item, label, labelCode); } else { label->setText(arg); } add(item); break; case 'M': // menu (experimental ?) if (arg[0] == 0) { // end of menu if (menu) { for (i=menu->count(); iremoveItem(i); } } menu=0; value = ""; break; } item = findItem(line); menu = dynamic_cast(item->w); if (menu == 0) { menu = new Menu(tit, device->viewport(), arg); initItem(item, menu, line, true); } menuItem = 0; add(item); break; case 'm': // menu item if (menu) { if (menuItem < menu->count()) { if (menu->text(menuItem).compare(value) != 0) { menu->changeItem(arg, menuItem); } } else { menu->insertItem(arg, menuItem); } menuItem++; } break; case 'c': // pen style menu item = findItem(line); colorMenu = dynamic_cast(item->w); if (colorMenu == 0) { colorMenu = new ColorMenu(device->viewport(), arg); initItem(item, colorMenu, line, true); } colorMenu->setValue(value); colorMenu->setLength(lwid); add(item); case 'a': // autoclose on radio button (experimental?) //device->closeGroup = this; autocloseOnRadio = true; //closeLater = true; break; case 'R': // radio button group radioName = arg; device->selectCmd = radioName; device->selectCmd.append(" "); device->selectCmd.append(value); break; case 'r': // radio button if (radioName.isEmpty()) break; radioLine = radioName + line; line = radioLine.latin1(); item = findItem(line); if (tit == "") { tit = arg; } rb = dynamic_cast(item->w); if (rb == 0) { rb = new RadioButton(tit, device->viewport(), radioName, arg); if (isSelectMenu) { initItem(item, rb, line, false); connect(rb, SIGNAL(sendCmd(const char *)), device, SLOT(setSelectCmd(const char *))); connect(rb, SIGNAL(clearOthers(const QString &)), this, SIGNAL(clearRadioButtons(const QString &))); connect(this, SIGNAL(clearRadioButtons(const QString &)), rb, SLOT(setValue(const QString &))); } else { initItem(item, rb, line, true); // if (device->closeGroup) { // connect(rb, SIGNAL(clicked()), device->closeGroup, SLOT(toggle())); // } if (autocloseOnRadio) { connect(rb, SIGNAL(clicked()), device, SLOT(closeMarkedGroups())); } } } else { rb->setText(tit); } if (sameRow) { rb->setMinimumWidth(0); } else { rb->setMinimumWidth(device->labelWidth / 2); } add(item); rb->setChecked(value.compare(arg) == 0); tit=""; break; case 'B': // push button item = findItem(line); pb = dynamic_cast(item->w); if (pb == 0) { pb = new ClickButton(device->viewport(), arg); pb->setLabel(tit); switch (arg[0]) { case 'C': initItem(item, pb, line, false); connect(pb, SIGNAL(clicked()), device, SLOT(switchLayout())); break; case 'D': initItem(item, pb, line, false); connect(pb, SIGNAL(clicked()), device, SLOT(selectIt())); pb->setDefault(true); break; case 'S': initItem(item, pb, line, false); connect(pb, SIGNAL(sendCmd(const char *)), device, SLOT(openGrps(const char *))); connect(pb, SIGNAL(changed()), device, SLOT(update())); connect(pb, SIGNAL(clicked()), pb, SLOT(handleReturn())); break; default: initItem(item, pb, line, true); connect(pb, SIGNAL(clicked()), pb, SLOT(handleReturn())); break; } } add(item); pb->setLabel(tit); tit=""; break; case 'C': // check box item = findItem(line); cb = dynamic_cast(item->w); if (cb == 0) { cb = new CheckBox(tit, device->viewport(), arg); initItem(item, cb, line, true); if (autocloseOnRadio) { connect(cb, SIGNAL(clicked()), device, SLOT(closeMarkedGroups())); } } else { cb->setText(tit); } add(item); cb->setValue(value); value=""; tit=""; break; /* case 'X': // make graphic button if (item) { if (item->graphButton == 0) { item->graphButton = new GraphButton(this, arg); connect(item->graphButton, SIGNAL(selectItem(const char *)), device, SLOT(selectGraphItem(const char *))); } if (device->graphOn) { device->addChild(item->graphButton, device->x, device->y); device->x += device->graphButtonWidth; item->graphButton->show(); arg = strrchr(arg, ' '); if (arg) { tip = "go to graph settings for this item ("; tip.append(arg + 3); tip.append(")"); QToolTip::add(item->graphButton, tip); tip = ""; } } else { item->graphButton->hide(); } } break; */ case 'g': // graph descriptor if (device->graphDesc == "") { device->graphDesc = arg; } else if (device->graphDesc != arg) { device->graphDesc = arg; device->rebuildTime = DoubleTime() + 1; // printf("*** desc changed\n"); // a graph rebuild will become necessary } else if (device->rebuildTime != 0 && DoubleTime() > device->rebuildTime) { // but we do not rebuild before the descriptor was two times the // same in succession and at least 1 second has passed device->rebuildTime = 0; device->updateInterval = 0.5; // printf("*** rebuild\n"); QTimer::singleShot(1, device, SLOT(rebuild())); } break; /* case 'J': // jump to me if (device->doJump) { device->doJump = false; device->yJump = device->y; } break; */ case 'E': // end of nested group goto END; default: if (printit()) printf("%s\n", line); } } END: // if (device->closeGroup == this) { // device->closeGroup = 0; // } /* graph obsolete if (device->closeGr && shown && closeLater) { // check if group is to be closed snprintf(groupName, sizeof groupName, " %s ", name()); if (device->visibleGr.find(groupName) < 0) { closeLater = false; showIt(false); for (QDictIterator it(items); (item = it.current()); ++it) { item->used = false; } } } */ for (QDictIterator it(items); (item = it.current()); ++it) { if (!item->used) { grp = dynamic_cast(item->w); if (grp) { grp->hideContents(); grp->arrow->hide(); } item->w->hide(); /* if (item->graphButton) { item->graphButton->hide(); } */ } } } void Group::appendTo(QString &c) { Group *g; Item *item; c.append(" "); c.append(name()); for (QDictIterator it(items); (item = it.current()); ++it) { g = dynamic_cast(item->w); if (g) { if (g->shown) { g->appendTo(c); } } } } void Group::autocloseAll() { Group *g; Item *item; for (QDictIterator it(items); (item = it.current()); ++it) { g = dynamic_cast(item->w); if (g) { g->autocloseAll(); if (g->shown && g->autoclose) { printf("autoclose %s\n", g->name()); g->toggle(); } } } } bool Group::openGroup(QString &path) { Group *g; Item *item; for (QDictIterator it(items); (item = it.current()); ++it) { g = dynamic_cast(item->w); if (g && PathStartsWith(path, g->name())) { if (!g->shown) { g->toggle(); // g->autoclose = true; } if (path == g->name()) { return g->shown; } return g->openGroup(path); } } return false; } Group* Group::findGroup(QString &path) { Group *g; Item *item; for (QDictIterator it(items); (item = it.current()); ++it) { g = dynamic_cast(item->w); if (g) { if (PathStartsWith(path, g->name())) { if (path == g->name()) return g; return g->findGroup(path); } } } return NULL; } Device::Device(QWidget* parent) : QScrollView(parent) { LineInput *lineInp; SetEraseColor(viewport(), topLevelWidget()); setFrameStyle(0); xspace=6; yspace=4; QString tit("This is a very long label"); lineInp = new LineInput(this, tit, "test"); lineInp->setLength(0); columnWidth = lineInp->stdWidth() + xspace; leWidth = lineInp->le->width(); labelWidth = lineInp->label->width(); // graphButtonWidth = 24; lineHeight = QMAX(lineInp->le->sizeHint().height(), lineInp->label->sizeHint().height()); delete lineInp; /* gButton = new GraphButton(this, "g-0"); graphOn = false; visibleGr = ""; doJump = false; yJump = 0; */ updateMode = update_idle; stopUpdate = false; //selectState = select_idle; rebuildTime = 0; //enableClipper(true); } void Device::init(Command *command, SeaSet *initSet) { set = initSet; com = command; device = new Group(this, "main"); select = new Group(this, "select", true); mainGroup = device; addChild(mainGroup, 0, 0); y = yspace; update(false); /* QToolTip::add(gButton, "graph settings"); connect(gButton, SIGNAL(clicked()), this, SLOT(graphToggle())); */ updateInterval = 5.0; QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(timedUpdate())); timer->start(10); } void Device::rebuild() { restart(graphDesc); } /* void Device::graphToggle() { if (graphOn) { QToolTip::add(gButton, "graph settings"); columnWidth -= graphButtonWidth; graphOn = false; gButton->setPixmap(QPixmap(grPix)); visibleGr = ""; closeGr = true; } else { QToolTip::add(gButton, "close graph settings"); columnWidth += graphButtonWidth; graphOn = true; gButton->setPixmap(QPixmap(gnPix)); } visibleGr = ""; update(false); } */ void Device::switchLayout() { mainGroup->hideContents(); if (mainGroup == select) { mainGroup = device; } else { mainGroup = select; } update(false); } void Device::selectIt() { mainGroup->hideContents(); com->sendCmd(selectCmd.latin1()); mainGroup = device; update(false); QTimer::singleShot(100,this,SLOT(update())); } void Device::setSelectCmd(const char *cmd) { selectCmd = cmd; } void Device::resizeEvent(QResizeEvent *e) { if (e->size().width() != e->oldSize().width()) { if (e->size().width() > 10 || e->oldSize().width() > 10) { if (updateInterval > 0) { updateInterval = 0; QTimer::singleShot(100,this,SLOT(update())); } } } QScrollView::resizeEvent(e); } /* void Device::selectGraphItem(const char *id) { //printf("SELECT %s\n", id); visibleGr = ""; if (id) { visibleGr = " "; visibleGr.append(id); closeGr = true; doJump = true; } update(false); } */ void Device::timedUpdate() { double now; if (updateMode == update_start) { // printf("*** update start\n"); updateStart(); updateMode = update_complete; tmot.start(); } if (updateMode == update_complete) { if (tmot.elapsed() > 10000) { set->sc->reconnect(); tmot.start(); printf("timeout -> reconnect\n"); updateMode = update_idle; } if (set->sc->handleBuffer(0) <= 0) return; // printf("*** update complete\n"); if (set->sc->getResponse() < 0) { set->sc->reconnect(); printf("timeout -> reconnected\n"); updateMode = update_idle; return; } updateComplete(); updateMode = update_idle; return; } if (mainGroup == select && lastUpdate > 0) { return; } now = DoubleTime(); if (updateInterval == 0) { updateInterval = 0.5; // printf("*** immediate update\n"); } else { if (now < lastUpdate + updateInterval) { return; } if (updateInterval < 0.99) { updateInterval += 0.1; } else { updateInterval *= 2; } if (updateInterval >= 10) { updateInterval = 10; } // printf("*** next update in %g sec\n", updateInterval); } if (isHidden() || height() < 3) { lastUpdate = now; return; } updateMode = update_start; } void Device::activate() { double now; if (mainGroup == select) return; now = DoubleTime(); if (now > lastUpdate) { update(false); // lastUpdate = now; } } void Device::closeMarkedGroups() { mainGroup->autocloseAll(); //selectState = select_idle; } void Device::openGrps(const char *groups) { Group *g; bool openit; openGroup = groups + 1; // skip first letter S in button name g = mainGroup->findGroup(openGroup); openit = !g || !g->shown; mainGroup->autocloseAll(); if (openit) { if (!mainGroup->openGroup(openGroup)) { update(false); return; } } openGroup = ""; update(false); } void Device::update(bool refresh) { if (refresh) { updateInterval = 0.5; stopUpdate = true; } lastUpdate = 0; } void Device::updateStart() { QString c("layout"); lastUpdate = DoubleTime(); code.clear(); mainGroup->appendTo(c); /* if (graphOn && !visibleGr.isEmpty()) { if (doJump) { c.append(visibleGr); } else { int i = visibleGr.findRev(' '); if (i >= 0) { c.append(visibleGr.mid(i)); } } } */ // printf("*** SEND %s\n", c.latin1()); set->sc->sendCommand(c.latin1()); //printf("%s\n", c.latin1()); } void Device::updateComplete() { QString line; while (set->sc->getLine(line) > 0) { code.append(line); } if (stopUpdate) { stopUpdate = false; return; } QStringList::Iterator it = code.begin(); y = yspace; nextY = yspace; maxWid = 0; /* graph obsolete: addChild(gButton, this->visibleWidth() - graphButtonWidth, 2); gButton->show(); */ // closeGroup = 0; mainGroup->updateLayout(it); resizeContents(maxWid, y); /* if (yJump > 0) { ensureVisible(0, yJump); yJump = 0; } */ }