#include "command.h" #include #include #include #include #include #include #include #include #include #include #include "utils.h" class CmdLine : public QLineEdit { public: CmdLine(QWidget *parent, const char *name) : QLineEdit(parent, name), history(""), edit("") { p = history.end(); atEnd = true; } void keyPressEvent(QKeyEvent *e) { int key = e->key(); if (key == Qt::Key_Up) { if (p == history.end()) { if (text().isEmpty()) { if (!edit.isEmpty()) { setText(edit); return; } } else { edit = text(); } } if (p != history.begin()) { --p; setText(*p); } } else if (key == Qt::Key_Down) { if (p != history.end()) { p++; } if (p == history.end()) { if (edit.compare(text()) == 0) { setText(""); } else { setText(edit); } } else { setText(*p); } } else if (key == Qt::Key_Return || key == Qt::Key_Enter) { edit=""; QLineEdit::keyPressEvent(e); } else { QLineEdit::keyPressEvent(e); if (p == history.end()) { edit = text(); } } } void addToHistory(const QString &txt) { p = history.find(txt); if (p != history.end()) { history.remove(p); } history.append(txt); p = history.end(); while (history.count() > 256) { history.remove(history.begin()); } } private: QStringList history; QStringList::Iterator p; QString edit; bool atEnd; }; Command::Command(QWidget * parent, const char *name, SicsConnection *initConn) : QWidget(parent, name, 0) { //QGridLayout *grid; QVBoxLayout *vbox; QFont monospace("Courier"); getHistory = true; //grid = new QGridLayout(this, 2, 2, 4, 4, "grid"); vbox = new QVBoxLayout(this, 4, 4, "cmdBox"); logStartupState = 1; log = new MyTextEdit(this, "log"); log->setReadOnly(TRUE); //add_to_log(" "); log->setBuffered(true); vbox->addWidget(new QLabel("Input/Output History:", this)); vbox->addWidget(log); ownCommand = false; quiet = false; vbox->addWidget(new QLabel("Command Input:", this)); monospace.setStyleHint(QFont::TypeWriter); cmd = new CmdLine(this, "cmd"); cmd->setFont(monospace); vbox->addWidget(cmd,3,0); clearWState(WState_Polished); conn=0; cmd->setFocusPolicy(StrongFocus); setConn(initConn); scrollH = 0; QTimer *timer = new QTimer(this, "repeat"); connect(timer, SIGNAL(timeout()), this, SLOT(handler())); timer->start(10); checktmo = false; /* dirtyLog = 0; QTimer *logTimer = new QTimer(this); connect(logTimer, SIGNAL(timeout()), SLOT(showLog())); logTimer->start(50); connect(log, SIGNAL(contentsMoving(int, int)), this, SLOT(scrolling(int, int))); */ } void Command::showIt(bool yes) { setShown(yes); } void Command::showText() { printf("%s\n", log->text().latin1()); } int str_beg(const char *text, const char *name) { return (strncmp(text, name, strlen(name)) == 0); } void Command::add_to_log(QString line, Style style) { /* QFont f = font(); static bool x=true; if (x) { printf("family %s size %d %d s %d\n", f.family().latin1(), f.pointSize(), f.pixelSize(), f.styleStrategy()); x = false; } */ if (ownCommand) { log->appendHtml(""); } switch (style) { case style_command: log->appendHtml(""); break; case style_error: log->appendHtml(""); break; case style_normal: break; } log->appendText(line); if (style > 0) { log->appendHtml(""); } if (ownCommand) { log->appendHtml(""); } log->appendText("\n"); } /* void Command::showLog(void) { if (dirtyLog) { dirtyLog = 0; log->setText(logText); log->scrollToBottom(); } } void Command::scrolling(int x, int y) { scrolled = true; } */ void Command::handleSics(const char * text, bool *done) { if (str_beg(text, "TRANSACTIONFINISHED")) { if (logStartupState) { log->setBuffered(false); } ownCommand = false; if (done) *done = false; return; } if (str_beg(text, "Deleting connection") || str_beg(text, "Accepted connection") || (str_beg(text, "User ") && strstr(text, " privilege") != 0) || str_beg(text, "Change of Authorisation") || str_beg(text, "fulltransact config ") || str_beg(text, "UserRights =") || str_beg(text, "fulltransact status") || (str_beg(text, "OK") && strlen(text) <= 3) || str_beg(text, "fulltransact commandlog tail") || str_beg(text, "Login OK")) { if (done) *done = false; return; } activate(); if (str_beg(text, "fulltransact") || str_beg(text, "transact") || str_beg(text, "TRANSACTIONSTART")) { if (str_beg(text, "TRANSACTIONSTART config listen")) { if (done) *done = false; return; } if (text[0] == 'f') { text += 13; } else if (text[0] == 'T') { text += 17; ownCommand = true; } else { text += 8; } // if (!blankLine) { // add_to_log(" "); // } if (strcmp(text, " ") > 0) { add_to_log(" "); if (timeStamp != "") { add_to_log(timeStamp); timeStamp = ""; } add_to_log(text, style_command); // printf("*** BB {%s}\n", text); if (getHistory) { ((CmdLine *)cmd)->addToHistory(text); } } } else if (strstr(text, "transAct") == text || strstr(text, "fulltransAct") == text) { // hide these commands // quiet = true; return; } else if (strstr(text, "ERROR:")) { add_to_log(text, style_error); // printf("*** RR %s\n", text); } else if (quiet) { quiet = false; /* swallow only one line. this is for nicos read -> frappy read -> sea spam*/ } else { if (strcmp(text, " ") > 0) { if (str_beg(text, "===")) { timeStamp = text; } else { if (timeStamp != "") { add_to_log(timeStamp); timeStamp = ""; } add_to_log(text); } // printf("*** N %s %s %s\n", text); } } if (done) *done = true; return; } void Command::handler() { int iret; iret = conn->handleBuffer(0); if (iret == -2) { // connect_error // printf("*** reconnect\n"); conn->reconnect(); if (getCommandLog == 0) { getCommandLog = 1; /* force config listen to be done on the new connection */ } } else if (iret > 0) { // success checktmo = false; if (getCommandLog == 2) { conn->sendCommand("commandlog tail 999"); getCommandLog = 1; } else if (getCommandLog == 1) { conn->getResponse(); getCommandLog = 0; conn->sendCommand("config listen 1"); // printf("*** config listen\n"); } else if (!cmdbuffer.isEmpty()) { if (sendCmd1(cmdbuffer.first().latin1())) { tmot.start(); checktmo = true; cmdbuffer.pop_front(); } } } else if (checktmo && tmot.elapsed() > 10000) { tmot.start(); // printf("*** timeout\n"); handleSics("ERROR: timeout -> reconnect\n"); conn->reconnect(); getCommandLog = 1; /* force config listen to be done on the new connection */ } if (height() < scrollH) { printf("%d\n", scrollH); log->scrollToBottom(); } scrollH = height(); if (conn) { conn->handleMessages(0); } } void Command::sendCmd(const char *command) { QString qs(command); cmdbuffer.append(qs); ((CmdLine *)cmd)->addToHistory(command); } int Command::sendCmd1(const char *command) { int iret; QString line; QString cCmd; iret = conn->sendCommand(command); if (iret < 0) { handleSics("ERROR: connection failed\n"); return 0; } // if (!blankLine) { // add_to_log(" "); // } // add_to_log(command, style_command); cmd->setText(""); log->scrollToBottom(); while ((iret=conn->getLine(line)) > 0) { handleSics(line.latin1()); } // add_to_log(" "); // blankLine = true; log->scrollToBottom(); return 1; } void Command::handleCmd() { if (getHistory) { getHistory = false; } sendCmd(cmd->text().latin1()); } void Command::setConn(SicsConnection *conn) { assert(conn); if (this->conn != conn) { this->conn = conn; connect(conn, SIGNAL(handle(const char *, bool *)), this, SLOT(handleSics(const char *, bool *))); connect(cmd, SIGNAL(returnPressed()), this, SLOT(handleCmd())); getCommandLog = 2; } getHistory = true; }