most files - check if this is all we need

This commit is contained in:
2025-06-10 11:43:29 +02:00
parent 34244cacb5
commit 0fa6f49d7f
28 changed files with 9004 additions and 0 deletions

386
Makefile_rhel7 Normal file
View File

@ -0,0 +1,386 @@
#############################################################################
# Makefile for building: rhel7/SeaClient
# Generated by qmake (1.07a) (Qt 3.3.4) on: Thu Apr 6 11:05:39 2017
# Project: SeaClient.pro
# Template: app
# Command: $(QMAKE) -o Makefile_rhel7 SeaClient.pro
#############################################################################
####### Compiler, tools and options
CC = gcc
CXX = g++
LEX = flex
YACC = yacc
CFLAGS = -pipe -Wall -W -g -D_REENTRANT -DQT_THREAD_SUPPORT -DQT_SHARED
CXXFLAGS = -pipe -Wall -W -Wno-non-virtual-dtor -Wno-unused-parameter -Wno-write-strings -Wno-unused-but-set-variable -Wno-type-limits -g -D_REENTRANT -DQT_THREAD_SUPPORT -DQT_SHARED
LEXFLAGS =
YACCFLAGS= -d
INCPATH = -I/afs/psi.ch/user/z/zolliker/public/qt64/mkspecs/default -I. -I../qtx64/qt-x11-free-3.3.4/include -I../qtx64/qwt-4.2.0/include -I$(QTDIR)/include -I.ui/ -I.moc/
LINK = g++
LFLAGS = -Wl,-rpath,$(QTDIR)/lib
LIBS = $(SUBLIBS) -L$(QTDIR)/lib -L/usr/X11R6/lib -L/afs/psi.ch/user/z/zolliker/public/qwt64/lib -lqwt -lqt-mt -lXext -lX11 -lm -lpthread
AR = ar cqs
RANLIB =
MOC = $(QTDIR)/bin/moc
UIC = $(QTDIR)/bin/uic
QMAKE = qmake
TAR = tar -cf
GZIP = gzip -9f
COPY = cp -f
COPY_FILE= $(COPY)
COPY_DIR = $(COPY) -r
INSTALL_FILE= $(COPY_FILE)
INSTALL_DIR = $(COPY_DIR)
DEL_FILE = rm -f
SYMLINK = ln -sf
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
####### Output directory
OBJECTS_DIR = rhel7/
####### Files
HEADERS = main.h \
seaset.h \
seaplot.h \
sicsconn.h \
tab.h \
settings.h \
command.h \
graph.h \
utils.h \
export.h \
report.h \
device.h
SOURCES = main.cpp \
seaset.cpp \
seaplot.cpp \
instr_hosts.cpp \
sicsconn.cpp \
tab.cpp \
settings.cpp \
command.cpp \
graph.cpp \
utils.cpp \
export.cpp \
report.cpp \
device.cpp
OBJECTS = rhel7/main.o \
rhel7/seaset.o \
rhel7/seaplot.o \
rhel7/instr_hosts.o \
rhel7/sicsconn.o \
rhel7/tab.o \
rhel7/settings.o \
rhel7/command.o \
rhel7/graph.o \
rhel7/utils.o \
rhel7/export.o \
rhel7/report.o \
rhel7/device.o
FORMS =
UICDECLS =
UICIMPLS =
SRCMOC = .moc/moc_main.cpp \
.moc/moc_seaset.cpp \
.moc/moc_seaplot.cpp \
.moc/moc_sicsconn.cpp \
.moc/moc_tab.cpp \
.moc/moc_settings.cpp \
.moc/moc_command.cpp \
.moc/moc_graph.cpp \
.moc/moc_utils.cpp \
.moc/moc_export.cpp \
.moc/moc_report.cpp \
.moc/moc_device.cpp
OBJMOC = rhel7/moc_main.o \
rhel7/moc_seaset.o \
rhel7/moc_seaplot.o \
rhel7/moc_sicsconn.o \
rhel7/moc_tab.o \
rhel7/moc_settings.o \
rhel7/moc_command.o \
rhel7/moc_graph.o \
rhel7/moc_utils.o \
rhel7/moc_export.o \
rhel7/moc_report.o \
rhel7/moc_device.o
DIST = SeaClient.pro
QMAKE_TARGET = SeaClient
DESTDIR = rhel7/
TARGET = rhel7/SeaClient
first: all
####### Implicit rules
.SUFFIXES: .c .o .cpp .cc .cxx .C
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
####### Build rules
all: Makefile_rhel7 $(TARGET)
$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC)
test -d rhel7/ || mkdir -p rhel7/
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(OBJCOMP) $(LIBS)
mocables: $(SRCMOC)
uicables: $(UICDECLS) $(UICIMPLS)
$(MOC):
( cd $(QTDIR)/src/moc && $(MAKE) )
Makefile_rhel7: SeaClient.pro /afs/psi.ch/user/z/zolliker/public/qt64/mkspecs/default/qmake.conf ../qt64/lib/libqt-mt.prl
$(QMAKE) -o Makefile_rhel7 SeaClient.pro
qmake:
@$(QMAKE) -o Makefile_rhel7 SeaClient.pro
dist:
@mkdir -p rhel7/SeaClient && $(COPY_FILE) --parents $(SOURCES) $(HEADERS) $(FORMS) $(DIST) rhel7/SeaClient/ && ( cd `dirname rhel7/SeaClient` && $(TAR) SeaClient.tar SeaClient && $(GZIP) SeaClient.tar ) && $(MOVE) `dirname rhel7/SeaClient`/SeaClient.tar.gz . && $(DEL_FILE) -r rhel7/SeaClient
mocclean:
-$(DEL_FILE) $(OBJMOC)
-$(DEL_FILE) $(SRCMOC)
uiclean:
yaccclean:
lexclean:
clean: mocclean
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core
####### Sub-libraries
distclean: clean
-$(DEL_FILE) rhel7/$(TARGET) $(TARGET)
FORCE:
####### Compile
rhel7/main.o: main.cpp main.h \
instr_hosts.h \
tab.h \
graph.h \
settings.h \
device.h \
export.h \
report.h \
seaset.h \
sicsconn.h \
seaplot.h \
command.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/main.o main.cpp
rhel7/seaset.o: seaset.cpp seaset.h \
utils.h \
sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/seaset.o seaset.cpp
rhel7/seaplot.o: seaplot.cpp seaplot.h \
utils.h \
seaset.h \
sicsconn.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/seaplot.o seaplot.cpp
rhel7/instr_hosts.o: instr_hosts.cpp instr_hosts.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/instr_hosts.o instr_hosts.cpp
rhel7/sicsconn.o: sicsconn.cpp sicsconn.h \
instr_hosts.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/sicsconn.o sicsconn.cpp
rhel7/tab.o: tab.cpp tab.h \
graph.h \
settings.h \
device.h \
export.h \
report.h \
seaset.h \
sicsconn.h \
seaplot.h \
command.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/tab.o tab.cpp
rhel7/settings.o: settings.cpp settings.h \
utils.h \
seaset.h \
device.h \
sicsconn.h \
seaplot.h \
command.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/settings.o settings.cpp
rhel7/command.o: command.cpp command.h \
utils.h \
sicsconn.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/command.o command.cpp
rhel7/graph.o: graph.cpp graph.h \
seaset.h \
utils.h \
sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/graph.o graph.cpp
rhel7/utils.o: utils.cpp utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/utils.o utils.cpp
rhel7/export.o: export.cpp export.h \
seaset.h \
sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/export.o export.cpp
rhel7/report.o: report.cpp report.h \
sicsconn.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/report.o report.cpp
rhel7/device.o: device.cpp device.h \
utils.h \
seaset.h \
command.h \
sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/device.o device.cpp
rhel7/moc_main.o: .moc/moc_main.cpp main.h tab.h \
graph.h \
settings.h \
device.h \
export.h \
report.h \
seaset.h \
sicsconn.h \
seaplot.h \
command.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_main.o .moc/moc_main.cpp
rhel7/moc_seaset.o: .moc/moc_seaset.cpp seaset.h sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_seaset.o .moc/moc_seaset.cpp
rhel7/moc_seaplot.o: .moc/moc_seaplot.cpp seaplot.h seaset.h \
sicsconn.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_seaplot.o .moc/moc_seaplot.cpp
rhel7/moc_sicsconn.o: .moc/moc_sicsconn.cpp sicsconn.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_sicsconn.o .moc/moc_sicsconn.cpp
rhel7/moc_tab.o: .moc/moc_tab.cpp tab.h graph.h \
settings.h \
device.h \
export.h \
report.h \
seaset.h \
sicsconn.h \
seaplot.h \
command.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_tab.o .moc/moc_tab.cpp
rhel7/moc_settings.o: .moc/moc_settings.cpp settings.h seaset.h \
device.h \
sicsconn.h \
seaplot.h \
command.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_settings.o .moc/moc_settings.cpp
rhel7/moc_command.o: .moc/moc_command.cpp command.h sicsconn.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_command.o .moc/moc_command.cpp
rhel7/moc_graph.o: .moc/moc_graph.cpp graph.h seaset.h \
sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_graph.o .moc/moc_graph.cpp
rhel7/moc_utils.o: .moc/moc_utils.cpp utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_utils.o .moc/moc_utils.cpp
rhel7/moc_export.o: .moc/moc_export.cpp export.h seaset.h \
sicsconn.h \
seaplot.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_export.o .moc/moc_export.cpp
rhel7/moc_report.o: .moc/moc_report.cpp report.h sicsconn.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_report.o .moc/moc_report.cpp
rhel7/moc_device.o: .moc/moc_device.cpp device.h seaset.h \
command.h \
sicsconn.h \
seaplot.h \
utils.h
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o rhel7/moc_device.o .moc/moc_device.cpp
.moc/moc_main.cpp: $(MOC) main.h
$(MOC) main.h -o .moc/moc_main.cpp
.moc/moc_seaset.cpp: $(MOC) seaset.h
$(MOC) seaset.h -o .moc/moc_seaset.cpp
.moc/moc_seaplot.cpp: $(MOC) seaplot.h
$(MOC) seaplot.h -o .moc/moc_seaplot.cpp
.moc/moc_sicsconn.cpp: $(MOC) sicsconn.h
$(MOC) sicsconn.h -o .moc/moc_sicsconn.cpp
.moc/moc_tab.cpp: $(MOC) tab.h
$(MOC) tab.h -o .moc/moc_tab.cpp
.moc/moc_settings.cpp: $(MOC) settings.h
$(MOC) settings.h -o .moc/moc_settings.cpp
.moc/moc_command.cpp: $(MOC) command.h
$(MOC) command.h -o .moc/moc_command.cpp
.moc/moc_graph.cpp: $(MOC) graph.h
$(MOC) graph.h -o .moc/moc_graph.cpp
.moc/moc_utils.cpp: $(MOC) utils.h
$(MOC) utils.h -o .moc/moc_utils.cpp
.moc/moc_export.cpp: $(MOC) export.h
$(MOC) export.h -o .moc/moc_export.cpp
.moc/moc_report.cpp: $(MOC) report.h
$(MOC) report.h -o .moc/moc_report.cpp
.moc/moc_device.cpp: $(MOC) device.h
$(MOC) device.h -o .moc/moc_device.cpp
####### Install
install:
uninstall:

47
SeaClient.pro Normal file
View File

@ -0,0 +1,47 @@
TEMPLATE = app
LANGUAGE = C++
CONFIG += qt-mt warn_on thread debug static
QMAKE_CXXFLAGS_WARN_ON += -Wno-non-virtual-dtor -Wno-unused-parameter -Wno-write-strings \
-Wno-unused-but-set-variable -Wno-type-limits
LIBS += -L$$(QWTDIR)/lib -lqwt
INCLUDEPATH += $$(QTDIR)/include
INCLUDEPATH += $$(QWTDIR)/include
HEADERS += main.h \
seaset.h \
seaplot.h \
sicsconn.h \
tab.h \
settings.h \
command.h \
graph.h \
utils.h \
export.h \
report.h \
device.h
SOURCES += main.cpp \
seaset.cpp \
seaplot.cpp \
instr_hosts.cpp \
sicsconn.cpp \
tab.cpp \
settings.cpp \
command.cpp \
graph.cpp \
utils.cpp \
export.cpp \
report.cpp \
device.cpp
unix {
UI_DIR = .ui
MOC_DIR = .moc
OBJECTS_DIR = $$(linuxsys)
DESTDIR = $$(linuxsys)
}

351
command.cpp Normal file
View File

@ -0,0 +1,351 @@
#include "command.h"
#include <qlayout.h>
#include <qlabel.h>
#include <qfont.h>
#include <qcolor.h>
#include <qlabel.h>
#include <qcheckbox.h>
#include <qevent.h>
#include <qtimer.h>
#include <qstylesheet.h>
#include <assert.h>
#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("<b>");
}
switch (style) {
case style_command: log->appendHtml("<font color=#0000FF>"); break;
case style_error: log->appendHtml("<font color=#FF0000>"); break;
case style_normal: break;
}
log->appendText(line);
if (style > 0) {
log->appendHtml("</font>");
}
if (ownCommand) {
log->appendHtml("</b>");
}
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;
}

51
command.h Normal file
View File

@ -0,0 +1,51 @@
#include <stddef.h>
#include <qlineedit.h>
#include <qtextedit.h>
#include <qdialog.h>
#include <qdatetime.h>
#include "sicsconn.h"
#include "utils.h"
class QCheckBox;
class Command : public QWidget
{
Q_OBJECT
public:
Command(QWidget *parent, const char *name, SicsConnection *conn);
void setConn(SicsConnection *conn);
void showText();
QLineEdit *cmd;
MyTextEdit *log;
enum Style {style_normal, style_command, style_error};
signals:
void activate();
public slots:
void handleSics(const char *text, bool *done = NULL);
void sendCmd(const char *cmd);
void handleCmd();
void handler();
void showIt(bool show);
// void showLog();
// void scrolling(int x, int y);
private:
void add_to_log(QString text, Style style = style_normal);
int sendCmd1(const char *cmd);
SicsConnection *conn;
int scrollH;
bool getHistory;
bool ownCommand;
bool quiet; /* for suppressing 'spam' when reading values from nicos/frappy */
bool blankLine;
QString timeStamp;
int getCommandLog;
QStringList cmdbuffer;
QTime tmot;
bool checktmo;
int logStartupState;
// bool dirtyLog;
};

1458
device.cpp Normal file

File diff suppressed because it is too large Load Diff

267
device.h Normal file
View File

@ -0,0 +1,267 @@
#include <stddef.h>
#include <qlayout.h>
#ifndef DEVICE_H
#define DEVICE_H
#include <qdict.h>
#include <qtabbar.h>
#include <qgrid.h>
#include <qvbox.h>
#include <qscrollview.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qradiobutton.h>
#include "seaset.h"
#include "command.h"
class Device;
class Group;
class LineInput : public QHBox {
Q_OBJECT
public:
LineInput(QWidget *parent, QString &labelText, const char *var);
void setLength(int l);
int stdWidth();
void setEraseColor(const QColor & color);
signals:
void sendCmd(const char *cmd);
void changed();
public slots:
void handleReturn();
void focusLost();
void setValue(const QString &value);
public:
QLineEdit *le;
QLabel *label;
// bool graphOn;
private:
QString value;
};
class RdOnly : public QHBox {
Q_OBJECT
public:
RdOnly(QWidget *parent, QString &labelText, QString &val, const char *var);
void setLength(int l);
public slots:
void setValue(const QString &val);
public:
QLabel *label, *value;
private:
unsigned int len;
};
class CheckBox : public QCheckBox {
Q_OBJECT
public:
CheckBox(const QString &label, QWidget *parent, const char *var);
signals:
void sendCmd(const char *cmd);
void changed();
public slots:
void handleReturn();
void setValue(const QString &value);
};
class ClickButton : public QPushButton {
Q_OBJECT
public:
ClickButton(QWidget *parent, const char *var);
void setLabel(const QString &label);
signals:
void sendCmd(const char *cmd);
void changed();
public slots:
void handleReturn();
private:
int dx;
};
class RadioButton : public QRadioButton {
Q_OBJECT
public:
RadioButton(const QString &label, QWidget *parent, const QString &cmd, const char *value);
signals:
void sendCmd(const char *cmd);
void clearOthers(const QString &cmd);
void changed();
public slots:
void handleClick();
void setValue(const QString &value);
private:
QString cmd;
};
class Menu : public QComboBox {
Q_OBJECT
public:
Menu(const QString &label, QWidget *parent, const char *var);
signals:
void sendCmd(const char *cmd);
void changed();
public slots:
void handleAct(const QString &value);
void setValue(const QString &value);
};
class ColorMenu : public QComboBox {
Q_OBJECT
public:
ColorMenu(QWidget *parent, const char *var);
ColorMenu(QString &color, QWidget *parent);
int getColorIndex();
void setLength(int min, int max=0);
signals:
void sendCmd(const char *cmd);
void changed();
public slots:
void handleAct(int index);
void handleChange(const QString &value);
void setValue(const QString &value);
private:
QString value;
void init();
bool nochange;
};
class Item {
public:
QWidget *w;
bool used;
char wStyle;
QFont normalFont;
Group *grp;
// QPushButton *graphButton;
Item() {
this->used = true;
this->w = 0;
this->wStyle = 0;
// this->graphButton = 0;
}
};
/*
class GraphButton : public QPushButton {
Q_OBJECT
public:
GraphButton(QWidget *parent, const char *name);
signals:
void selectItem(const char *id);
void changed();
public slots:
void handleClick();
};
*/
class Group : public QVBox {
Q_OBJECT
public:
Group(Device *p, const char *name, bool selectMenu=false);
Group(Group *p, const QString &tit, const char *name);
void updateLayout(QStringList::Iterator &it);
void appendTo(QString &c);
void hideContents();
void autocloseAll();
bool openGroup(QString &path);
Group* findGroup(QString &path);
bool shown;
bool autoclose;
signals:
void changeHeight();
void clearRadioButtons(const QString &except);
public slots:
void toggle();
private:
void init();
void add(Item *item, QWidget *w = 0);
void initItem(Item *item, QWidget *w, const char *line, bool active = false);
Item *findItem(const char *name);
void showIt(bool show);
void newline();
QPushButton *arrow;
QLabel *title;
Device *device;
Group *parentGroup;
QDict<Item> items;
int indent; // x indentation
bool sameRow;
bool tight;
QString tip;
char wStyle;
bool isSelectMenu;
int colDiv;
//bool closeLater;
};
typedef enum {select_idle, select_open} SelectState;
class Device : public QScrollView
{
Q_OBJECT
friend class Group;
public:
Device(QWidget* parent);
void init(Command *command, SeaSet *initSet);
signals:
void restart(const char *vars);
public slots:
void update(bool refresh = true);
void timedUpdate();
void switchLayout();
void selectIt();
void setSelectCmd(const char *cmd);
// void graphToggle();
// void selectGraphItem(const char *id);
void rebuild();
void activate();
void closeMarkedGroups();
void openGrps(const char *groups);
private:
void resizeEvent(QResizeEvent *e);
void updateStart();
void updateComplete();
QString selectCmd;
SeaSet *set;
Group *mainGroup;
Group *device;
Group *select;
Command *com;
// GraphButton *gButton;
QStringList code;
int x, y;
int nextY;
int maxWid;
int xspace, yspace;
int labelWidth;
int leWidth;
int columnWidth;
// int graphButtonWidth;
int lineHeight;
QString graphDesc;
// bool graphOn;
// QString visibleGr;
// bool doJump;
QString openGroup; /* group path to open */
SelectState selectState;
//int yJump;
bool stopUpdate;
double updateInterval;
double lastUpdate;
double rebuildTime;
// Group *closeGroup;
enum {update_idle, update_start, update_complete} updateMode;
QTime tmot;
};
#endif

373
export.cpp Normal file
View File

@ -0,0 +1,373 @@
#include "export.h"
#include <qapplication.h>
#include <qvariant.h>
#include <qdialog.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <stdio.h>
#include <qvalidator.h>
#include <math.h>
#include <unistd.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qsizepolicy.h>
#include <qfiledialog.h>
#include "seaset.h"
#include "sicsconn.h"
#include <assert.h>
#include <stdlib.h>
void Export::addRow(QString label, QWidget *widget, QString tip) {
QLabel *labelW;
if (label != "") {
labelW = new QLabel(label, this);
lay->addWidget(labelW, row, 0);
if (tip != "") {
QToolTip::add(labelW, tip);
}
}
lay->addWidget(widget, row, 1);
if (tip != "") {
QToolTip::add(widget, tip);
}
row++;
}
Export::Export(SeaSet *setArg, QWidget *parent, const char *instr)
: QWidget(parent)
{
QPushButton *ok, *cancel;
char wd[PATH_MAX];
set = setArg;
row = 0;
instrument = instr;
lay = new QGridLayout(this, 1, 3, 3, -1, "exportLayout");
lay->setColStretch(2,1);
addRow("export: ", new QLabel("all active curves", this), "");
lay->addWidget(new QLabel("step [sec]", this), 1, 0);
stepLE = new QLineEdit(this);
QValidator* validator = new QIntValidator( 1, 24*3600, this );
stepLE->setValidator(validator);
stepLE->setText("auto");
stepLE->setAlignment(Qt::AlignRight);
stepLE->setFixedWidth(100);
addRow("step [sec]", stepLE,
"time step [sec] (auto: 5 sec or more, max. 1000 points)"
);
scaleLE = new QLineEdit(this);
scaleLE->setText("1");
scaleLE->setAlignment(Qt::AlignRight);
scaleLE->setFixedWidth(100);
addRow("x-scale [sec]", scaleLE, "enter 60 for minutes / 3600 for hours");
noneLE = new QLineEdit(this);
noneLE->setText("NaN");
noneLE->setFixedWidth(100);
addRow("none value", noneLE, "value to be used for undefined numbers");
filePath = getcwd(wd, sizeof wd);
filePath.append("/seaexport.dat");
cancel = new QPushButton("Quit", this);
lay->addWidget(cancel, row, 0);
connect(cancel, SIGNAL(clicked()), this, SIGNAL(finish()));
ok = new QPushButton("Export", this);
lay->addWidget(ok, 5, 1);
ok->setDefault(true);
ok->setFixedWidth(100);
addRow("", ok, "");
connect(ok, SIGNAL(clicked()), this, SLOT(exportXY()));
message = new QLabel("", this);
lay->addWidget(message, row, 1);
row++;
lay->setRowStretch(row,1);
}
void Export::showMe() {
show();
updateCurveList();
}
void Export::updateCurveList() {
QString text("The following curves are active and to be exported:");
int cnt=0;
SeaData *d;
if (isHidden()) return;
for (d = set->dataList.first(); d != 0; d = set->dataList.next()) {
if (d->isActive()) {
text.append("\n ");
text.append(d->label);
cnt++;
}
}
if (cnt == 0) {
text = "no active curves";
}
text.append("\n\ncurves are de-/activated by clicking on their legend");
message->setText(text);
show();
}
void Export::progress(int bytes) {
QString text;
if (progressBytes < 0) return;
if (isHidden()) return;
progressBytes += bytes;
if (progressBytes >= 0 && lastProgress.elapsed() > 250) {
lastProgress.start();
text.sprintf("%.2f MBytes read", progressBytes * 0.000001);
message->setText(text);
show();
procEvt();
}
}
void Export::exportXY() {
QString cmd;
QString line;
int iret, cnt, icol;
bool ok;
time_t dt, t, from, to, step, lastRead, basis;
time_t i, lasti, len, siz, scale, mag, endi;
int prec;
SeaData *d;
QString text;
double val;
double *data;
double yy, yy0;
FILE *fil;
QString fileResult;
double eps;
static double undefpluseps = 0;
fileResult = QFileDialog::getSaveFileName(
filePath, QString::null, this,
"save file dialog",
"select file to save exported data"
);
if (fileResult == "") {
return;
}
filePath = fileResult;
from = set->startRange;
to = set->endRange;
step = stepLE->text().toInt();
if (step == 0) { /* auto */
step = ((to - from) / 5000 + 1) * 5;
}
from = (from / step) * step;
scale = scaleLE->text().toInt();
if (scale < 1) {
scale = 1;
}
len = (to - from - 1) / step;
to = from + len * step;
if (step == 1) {
cmd.sprintf("graph %ld %ld text", from, to);
} else {
cmd.sprintf("graph %ld %ld np %ld", from, to, to - from + 2);
}
cnt = 0;
for (d = set->dataList.first(); d != 0; d = set->dataList.next()) {
if (d->isActive()) {
cmd.append(" ");
cmd.append(d->name);
cnt++;
}
}
if (cnt == 0) {
message->setText("no curves active");
show();
return;
}
siz = len * cnt;
data = (double *)malloc(siz * sizeof(*data));
if (data == NULL) {
message->setText("no memory");
show();
return;
}
progressBytes = 0;
message->setText("waiting for server");
procEvt();
lastProgress.start();
iret = set->ec->command(cmd);
progressBytes = -1;
if (iret < 0) {
message->setText("can not connect to the GraphServer");
goto err2;
}
//printf("%s\n", cmd.latin1());
text = "Curves:";
message->setText(text);
procEvt();
iret = set->ec->getLine(line);
if (iret <= 0) {
message->setText("can not get response 1");
goto err2;
}
//printf("> %s\n", line.latin1());
/* get returned absolute time */
lastRead = line.toLong();
//sscanf(line, "%ld", &lastRead);
iret = set->ec->getLine(line);
if (iret <= 0) {
message->setText("can not get response 2");
goto err2;
}
//printf("> %s\n", line.latin1());
if (!line.startsWith("*")) {
message->setText("missing *");
goto err2;
}
icol = 0;
fil = fopen(filePath.latin1(), "w");
fprintf(fil, "# SEA export from %s\n", instrument);
fprintf(fil, "# col 1: Time/%d sec since %s 0:00\n", (int)scale, set->dateLabel(0).latin1());
endi = 0;
for (d = set->dataList.first(); d != 0; set->dataList.findRef(d), d = set->dataList.next()) {
if (d->isActive()) {
yy0 = DATA_UNDEF;
yy = DATA_UNDEF;
lasti = -1;
//printf("- %s\n", d->label.latin1());
fprintf(fil, "# col %d: %s (%s) %s\n",
icol + 2, d->name.latin1(), d->label.latin1(),
d->row->tagLabel->text().latin1());
text.append("\n ");
text.append(d->label);
line = line.section(' ', 0, 0);
if (d->name == line.mid(1)) {
t = 0;
do {
iret = set->ec->getLine(line);
if (iret <= 0) {
message->setText("can not get line");
goto err;
}
//printf("> %s\n", line.latin1());
if (line.startsWith("*")) {
i = len;
} else {
/* decode line to x[n] / y[n] */
dt = line.section(' ', 0, 0).toLong(&ok);
/*
iret = sscanf(line, "%ld %n", &dt, &pos);
if (iret < 1) {
*/
if (!ok) {
message->setText("bad timestep");
goto err;
}
t += dt;
i = (t - from) / step;
yy0 = yy;
yy = line.section(' ', 1, 1).toDouble(&ok);
//iret = sscanf(line + pos, "%lf", &yy);
// printf("scan %8ld %9.4f\n", t - from, yy);
if (!ok) { // not a valid value
yy = DATA_UNDEF;
} else {
if (yy == DATA_UNDEF) { // by chance
if (undefpluseps == 0) { // create closest possible (but different) value to DATA_UNDEF
undefpluseps = yy;
eps = undefpluseps * 1e-9;
while (undefpluseps == DATA_UNDEF) {
undefpluseps += eps;
eps = eps * 2;
}
}
yy = undefpluseps;
}
}
}
/*---*/
if (lasti < i) {
if (lasti < 0) {
lasti = 0;
}
while (lasti < i - 1 && lasti < len) {
assert(lasti * cnt + icol < siz);
data[lasti*cnt + icol] = yy0;
lasti++;
}
if (lasti < len) {
data[lasti*cnt + icol] = yy;
// printf("%ld %9.4f\n", lasti, yy);
if (yy != DATA_UNDEF) {
if (lasti > endi && lasti != len) endi = lasti;
}
}
lasti++;
}
} while (!line.startsWith("*"));
} else {
for (i = 0; i<len; i++) {
assert(i * cnt + icol < siz);
data[i*cnt + icol] = DATA_UNDEF;
}
}
icol++;
message->setText(text);
procEvt();
}
}
//fprintf(fil, "\n");
basis = (from - set->base) / step;
//printf("endi %ld\n", endi);
for (i = 0; i < endi; i++) {
if (scale == 1) {
fprintf(fil, "%ld", (basis + i) * step);
} else {
mag = 10 * scale / step;
for (prec = 0; mag > 1; prec++,mag/=10);
fprintf(fil, "%.*f", prec, (double)(basis + i) * step / scale);
}
for (icol = 0; icol < cnt; icol++) {
val = data[i*cnt + icol];
if (val == DATA_UNDEF) {
fprintf(fil, "\t%s", noneLE->text().latin1());
} else {
// fprintf(fil, "\t%.7g", val);
// we might write here full precision, this will not watse space in case step is not 1
fprintf(fil, "\t%.14g", val);
}
}
fprintf(fil,"\n");
}
text.append("\n\nwritten to\n");
text.append(filePath.latin1());
message->setText(text);
err:
fclose(fil);
err2:
free(data);
show();
}

39
export.h Normal file
View File

@ -0,0 +1,39 @@
#include <stddef.h>
#include <qdialog.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qbutton.h>
#include <qlayout.h>
#include <qstring.h>
#include <qdatetime.h>
#include "seaset.h"
class Export : public QWidget
{
Q_OBJECT
public:
Export(SeaSet *setArg, QWidget *parent=0, const char *instr=0);
void showMe();
private:
QLineEdit *stepLE;
QLineEdit *noneLE;
QLineEdit *scaleLE;
QLabel *message;
SeaSet *set;
QGridLayout *lay;
int row;
QString filePath;
const char *instrument;
int progressBytes;
QTime lastProgress;
signals:
void finish();
void procEvt();
public slots:
void updateCurveList();
void exportXY();
void addRow(QString label, QWidget *widget, QString tip);
void progress(int bytes);
};

355
graph.cpp Normal file
View File

@ -0,0 +1,355 @@
#include "graph.h"
#include <qapplication.h>
#include <qvariant.h>
#include <qdialog.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qpixmap.h>
#include <qimage.h>
#include <stdio.h>
#include <qpixmap.h>
#include <qvalidator.h>
#include <math.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qcombobox.h>
#include <qsplitter.h>
#include <qsizepolicy.h>
#include <stdlib.h>
#include "seaset.h"
#include "utils.h"
static char *xZoomPix[] = {
"16 16 2 1",
" c None",
"X c #000000",
" ",
" ",
" X X ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" XX XX ",
" X X ",
" ",
" "
};
static char *leftPix[] = {
"16 16 2 1",
" c None",
"X c #000000",
" ",
" ",
" X ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" X ",
" ",
" "
};
static char *rightPix[] = {
"16 16 2 1",
" c None",
"X c #000000",
" ",
" ",
" X ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" XX ",
" X ",
" ",
" "
};
static char *undoPix[] = {
"16 16 2 1",
" c None",
"X c #000000",
" ",
" XXXXXXXXX ",
" XX ",
" XX ",
" X ",
" X ",
" X ",
" X X ",
" XX XX ",
" XX XX ",
" XXXXXXXXXXXX ",
" XX ",
" XX ",
" X ",
" ",
" "
};
Graph::Graph(const char* arg, QWidget *parent, long range)
: QWidget(parent, 0)
{
QPixmap pmOut((const char **)xZoomPix);
QPixmap pmLeft((const char **)leftPix);
QPixmap pmRight((const char **)rightPix);
QPixmap pmUndo((const char **)undoPix);
QString str;
//QHBox *buttonBar;
QPushButton* buttonOk;
QPushButton* buttonAll;
QPushButton* buttonUndo;
QPushButton* buttonLeft;
QPushButton* buttonOut;
QPushButton* buttonRight;
QPushButton* buttonSettings;
QPushButton* buttonXY;
QSplitter *graphSplit;
QVBoxLayout* graphLayout;
QHBoxLayout* buttonLayout;
int w,h;
const char * vars;
setName("Graph");
graphLayout = new QVBoxLayout(this, 0, 0, "graphLayout");
graphSplit = new QSplitter(Qt::Vertical, this, "splitter");
graphLayout->add(graphSplit);
buttonLayout = new QHBoxLayout(0, 6, 2, "buttonBar");
graphLayout->addLayout(buttonLayout);
buttonLayout->addWidget(new QLabel("Range", this));
lineEditRange = new QComboBox(true, this);
//SetLength(lineEditRange, 5, 6);
buttonLayout->addWidget(lineEditRange);
QToolTip::add(lineEditRange, "enter a number and m,h or d");
buttonOk = new QPushButton(this);
buttonOk->setDefault(true);
buttonOk->setText("OK");
ShrinkButton(buttonOk);
buttonLayout->addWidget(buttonOk);
buttonSettings = new QPushButton(this);
buttonSettings->setText("Settings");
ShrinkButton(buttonSettings);
buttonLayout->addWidget(buttonSettings);
QToolTip::add(buttonSettings, "edit shown curves");
buttonAll = new QPushButton(this);
buttonAll->setText("Show All");
ShrinkButton(buttonAll);
buttonLayout->addWidget(buttonAll);
QToolTip::add(buttonAll, "show all curves");
buttonXY = new QPushButton(this);
buttonXY->setText("export");
ShrinkButton(buttonXY);
buttonLayout->addWidget(buttonXY);
QToolTip::add(buttonXY, "export data");
liveBox = new QCheckBox(this);
liveBox->setText("live mode");
buttonLayout->addWidget(liveBox);
liveBox->setChecked(false);
buttonLayout->addStretch(1);
buttonUndo = new QPushButton(this);
buttonUndo->setPixmap(pmUndo);
w = QMAX(22, buttonUndo->sizeHint().width() - 6);
h = QMAX(22, buttonUndo->sizeHint().height() - 6);
if (w > h) { // Mac like
h += 6;
w -= 6;
}
buttonUndo->setFixedSize(w, h);
buttonLayout->addWidget(buttonUndo);
buttonUndo->setEnabled(false);
QToolTip::add(buttonUndo, "undo zoom or shift action");
buttonLeft = new QPushButton(this);
buttonLeft->setPixmap(pmLeft);
buttonLeft->setFixedSize(w, h);
buttonLayout->addWidget(buttonLeft);
QToolTip::add(buttonLeft, "scroll left");
buttonRight = new QPushButton(this);
buttonRight->setPixmap(pmRight);
buttonRight->setFixedSize(w, h);
buttonLayout->addWidget(buttonRight);
QToolTip::add(buttonRight, "scroll right");
buttonOut = new QPushButton(this);
buttonOut->setPixmap(pmOut);
buttonOut->setFixedSize(w, h);
buttonLayout->addWidget(buttonOut);
QToolTip::add(buttonOut, "zoom out horizontally");
str="Sea ";
str.append(arg);
topLevelWidget()->setCaption(str);
clearWState(WState_Polished);
unit='m';
str="30m";
set = new SeaSet(graphSplit, range, "seaset");
const char *items[]={
"1m","2m","5m","10m","15m","30m"
,"1h","2h","4h","8h","16h"
,"1d","2d","4d","8d",0};
lineEditRange->insertStrList(items);
lineEditRange->setSizeLimit(15);
lineEditRange->setMaxCount(15);
lineEditRange->setEditText(str);
lineEditRange->lineEdit()->selectAll();
connect(lineEditRange, SIGNAL(activated(int)),
this, SLOT(activateRange()));
connect(buttonOk, SIGNAL(clicked()),
this, SLOT(activateRange()));
connect(buttonAll, SIGNAL(clicked()),
set, SLOT(showAll()));
connect(buttonSettings, SIGNAL(clicked()),
this, SIGNAL(gotoSettings()));
connect(buttonXY, SIGNAL(clicked()),
this, SIGNAL(openExport()));
connect(buttonUndo, SIGNAL(clicked()),
set, SLOT(undoZoom()));
connect(buttonLeft, SIGNAL(clicked()),
set, SLOT(shiftLeft()));
connect(buttonOut, SIGNAL(clicked()),
set, SLOT(zoomOutX()));
connect(buttonRight, SIGNAL(clicked()),
set, SLOT(shiftRight()));
connect(liveBox, SIGNAL(toggled(bool)),
set, SLOT(setLive(bool)));
connect(set, SIGNAL(undoEnabled(bool)),
buttonUndo, SLOT(setEnabled(bool)));
connect(lineEditRange->lineEdit(), SIGNAL(textChanged(const QString &)),
this, SLOT(autoReturn(const QString &)));
set->setHost(arg);
if (printit()) {
printf("reading curve list,\n");
}
if (range < 365*24*3600) {
vars = "now";
} else {
vars = NULL;
}
set->autoCurves(vars);
if (printit()) {
printf("opening window.\n");
}
//lineEditRange->selectAll();
QTimer *timer = new QTimer(this, "repeat");
connect(timer, SIGNAL(timeout()), this, SLOT(liveUpdate()));
timer->start(2500);
}
void Graph::liveUpdate() {
if (isShown() && width() > 3) {
set->liveUpdate();
}
}
void Graph::showIt(bool yes) {
if (yes) {
set->liveUpdate();
show();
} else {
hide();
}
}
void Graph::activateRange() {
long fact;
QString t;
double rng;
unsigned int j;
//setFocus();
t = lineEditRange->currentText();
for (j = 0; j < t.length(); j++) {
if (t[j] > '9') {
unit = t.latin1()[j];
t.truncate(j);
break;
}
}
switch (unit) {
case 'D': unit='d';
case 'd': fact = 24*3600; break;
case 'H': unit='h';
case 'h': fact = 3600; break;
case 'M': unit='m';
case 'm': fact = 60; break;
case 'S': unit='s';
case 's': fact = 1; break;
default: fact = 60; unit = 'm';
}
rng = t.toDouble() * fact;
//printf("%s %lf %ld\n", t.latin1(), rng, fact);
if (rng > SEA_MAX_RANGE) {
unit = 'd';
t.sprintf("%d%c", (SEA_MAX_RANGE + 36000) / 24 / 3600, unit);
lineEditRange->setEditText(t);
rng = SEA_MAX_RANGE;
} else if (rng < 59.5) {
rng = 60;
if (unit == 's') {
lineEditRange->setEditText("60s");
} else {
unit = 'm';
lineEditRange->setEditText("1m");
}
} else {
t.append(unit);
lineEditRange->setEditText(t);
}
set->rescaleRange(long(rng));
lineEditRange->lineEdit()->selectAll();
}
void Graph::autoReturn(const QString &text) {
if (0 == text.find(QRegExp("\\d{1,4}[DdHhMmSs]"))) {
activateRange();
} else if (0 == text.find(QRegExp("[Qq]"))) {
exit(0);
}
}

44
graph.h Normal file
View File

@ -0,0 +1,44 @@
#include <stddef.h>
#include <qvariant.h>
#include <qdialog.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <qptrlist.h>
#include <qcombobox.h>
#include <qptrcollection.h>
#include "seaset.h"
class QVBoxLayout;
class QHBoxLayout;
class QSpacerItem;
class QPushButton;
class QCheckBox;
class Graph : public QWidget
{
Q_OBJECT
public:
Graph(const char* host = 0, QWidget *parent=0, long range=1800);
SeaSet *set;
QComboBox* lineEditRange;
QCheckBox* liveBox;
public slots:
void activateRange();
void autoReturn(const QString &);
void showIt(bool show);
void liveUpdate();
signals:
void gotoSettings();
void openExport();
private:
char unit;
void init();
};

1
instr_hosts.cpp Symbolic link
View File

@ -0,0 +1 @@
../six/instr_hosts.c

1
instr_hosts.h Symbolic link
View File

@ -0,0 +1 @@
../six/instr_hosts.h

521
main.cpp Normal file
View File

@ -0,0 +1,521 @@
#include "main.h"
#include <qwindowsstyle.h>
#include <qstylefactory.h>
#include <qstyle.h>
#include <qpalette.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qbuttongroup.h>
#include <qtooltip.h>
#include <qtimer.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/stat.h>
#include "instr_hosts.h"
QPoint firstPos;
FILE *fil;
char preffile[PATH_MAX]="";
int prefdirlen = 0;
char prefil[80]="";
char homeinstr[64]="";
const char *instr;
//char prefinstr[64]="";
char frominstr[128];
char *strtoupper(const char *str) {
static char buf[128];
int i;
for (i = 0; i < 127; i++) {
if (str[i] == 0) break;
buf[i] = toupper(str[i]);
}
buf[i] = 0;
return buf;
}
const char *fullinstr(const char *host, const char *instr) {
static char buf[128];
if (strncasecmp(host, instr, strlen(instr)) == 0) {
return host;
}
snprintf(buf, sizeof buf, "%s at %s", host, strtoupper(instr));
return buf;
}
SeaApp::SeaApp(int &argc, char **argv) : QApplication(argc, argv) {
char *arg;
char *style=0;
char instrList[1024];
QString deviceList;
int i;
int port;
char host[64];
int query;
struct tm tm;
time_t startupTime, now, range;
QString tip;
SicsConnection *seaman;
char *remotehost;
char *remoteinstr;
char *hostname;
char warning[256];
int x, y, w, h;
QFont afont = font();
afont.setPointSize(12);
setFont(afont);
time(&lastActive);
time(&lastTimer);
tab = NULL;
sleepTime = 3600;
sleeping = false;
frominstr[0] = 0;
home = InstrHost("sea", "", homeinstr, sizeof homeinstr, host, sizeof host, &port);
if (port == 0) {
homeinstr[0]='\0';
}
remoteinstr = InstrHostRemoteInstr();
hostname = InstrHostName();
remotehost = InstrHostRemoteName();
instr = NULL;
query = -1;
range = 1800;
setprintit(0);
for (i=1; i<argc; i++) {
arg = argv[i];
if (strcmp(arg,"-q") == 0) {
query = 1; /* ask for instrument */
} else if (strcmp(arg,"-r") == 0) {
/* disable verbose startup, obsolete */
} else if (strcmp(arg,"-v") == 0) {
/* verbose startup */
setprintit(2);
} else if (strcmp(arg,"-d") == 0) {
/* give date & time, +- 0.5 h */
i++;
if (i<argc) {
time(&now);
tm = *localtime(&now);
strptime(argv[i], "%Y-%m-%d:%H:%M:%S", &tm);
range = mktime(&tm);
}
} else if (strcmp(arg,"-s") == 0) {
/* select style */
i++;
if (i>=argc) {
QStringList keys=QStyleFactory::keys();
printf("styles: %s\n", keys.join(", ").latin1());
ciao();
}
style = argv[i];
} else if (strcasecmp(arg,"-h") == 0) {
/* ??? */
home = 1;
} else if (strcasecmp(arg,"-p") == 0) {
i++;
/* ignore obsolete pid file option */
} else if (strcasecmp(arg,"-c") == 0) {
i++;
/* ignore obsolete watch/restart option */
} else if (strcasecmp(arg,"-t") == 0) {
/* set sleep time (1 h by default) */
i++;
if (i<argc) {
sleepTime = atoi(argv[i]);
if (sleepTime == 0) {
sleepTime = 365 * 24 * 3600;
}
}
} else if (strcasecmp(arg,"start") == 0) {
printf("'start' is an illegal argument\n");
fail();
} else if (arg[0] !='-') {
/* an instrument or a hostname */
if (query < 0) query = 0;
if (home == 1 && strcasecmp(homeinstr, arg) != 0) {
snprintf(frominstr, sizeof frominstr, "but logged in to %s", fullinstr(hostname, homeinstr));
//prefinstr[0] = 0;
} else if (remoteinstr[0] && strcasecmp(remoteinstr, arg) != 0) {
snprintf(frominstr, sizeof frominstr, "but logged in from %s", fullinstr(remotehost, remoteinstr));
//prefinstr[0] = 0;
}
/*
else if (home == 1 && strcasecmp(homeinstr, arg) == 0) {
prefinstr[0] = 0;
} else if (prefinstr[0] && strcasecmp(prefinstr, arg) != 0) {
snprintf(frominstr, sizeof frominstr, "but preferred instrument is %s", strtoupper(prefinstr));
}
*/
instr = strdup(arg);
port = -1;
}
}
if (query < 0) {
if (remoteinstr[0] && home == 1 && strcasecmp(remoteinstr, homeinstr) != 0) {
snprintf(frominstr, sizeof frominstr, "but logged in from %s", fullinstr(remotehost, remoteinstr));
query = 2; /* no checkbox for default instrument */
instr = homeinstr;
} else if (home == 1) { /* one instr found with home as host */
instr = homeinstr;
query = 0;
printf("\nconnect to %s as started from %s (other selection: sea -q)\n", strtoupper(instr), hostname);
/*
} else if (prefinstr[0] != 0) { // a default instrument is defined
instr = prefinstr;
query = 0;
printf("\nconnect to %s by preference (other selection: sea -q)\n", strtoupper(prefinstr));
*/
} else {
query = 1;
}
}
if (instr == NULL) {
instr = ""; //prefinstr;
}
QColor bgr(221, 221, 221);
if (style) {
if (setStyle(style)) {
printf("set style to %s\n", style);
}
} else {
setStyle("windows");
QPalette pal = palette();
pal.setColor(QColorGroup::Background, bgr);
pal.setColor(QColorGroup::Button, bgr);
setPalette(pal);
}
QDialog menu(0);
QButtonGroup bg(&menu);
QGridLayout grid(&menu,1,1,12,12);
QRadioButton *rb;
if (port == 0 || query) {
if (instr[0] == 0) {
/* determine default instrument */
if (home == 1) {
instr = homeinstr;
/*
} else if (prefinstr[0]) {
instr = prefinstr;
*/
} else if (remoteinstr[0]) {
instr = remoteinstr;
}
}
InstrList("graph", instrList, sizeof instrList);
QStringList list(QStringList::split(' ', instrList, true));
QString seamancmd = list.join(",");
seamancmd.insert(0, "_tcl get_devices ");
seaman = new SicsConnection(&menu);
seaman->setHost("seaman", "sea");
seaman->setUser("seauser seaser\n");
seaman->command(seamancmd.latin1());
if (!seaman->getLine(deviceList)) {
deviceList = "";
}
QStringList devlist(QStringList::split(',', deviceList, true));
seaman->disconnect();
int row = 1, col=0, cols = 4;
menu.setCaption("Sea");
// grid.setMargin(5);
QLabel *label = new QLabel("Select instrument", &menu);
QFont font = label->font();
font.setPointSize(18);
label->setFont(font);
QFont tooltipfont = QToolTip::font();
QToolTip::setFont(font);
grid.addMultiCellWidget(label, 0, 0, 0, cols-1);
QStringList::Iterator dit = devlist.begin();
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it, ++dit) {
if ((*it).isEmpty()) {
if (col >= 0) {
col = 0;
row++;
}
} else {
rb = new QRadioButton(*it, &menu);
rb->setFont(font);
if (!(*dit).isEmpty()) {
QToolTip::add(rb, *dit);
}
grid.addWidget(rb, row, col);
QObject::connect(rb, SIGNAL(clicked()), &menu, SLOT(accept()));
bg.insert(rb);
col++;
if (col >= cols) {
col = 0;
row++;
}
if ((*it).compare(instr) == 0) {
rb->setChecked(true);
}
}
}
if (col > 0) {
row++;
col = 0;
}
if (query == 1) {
/*
QString cbtext("default instrument when started from ");
cbtext += remotehost;
defi = new QCheckBox(cbtext, &menu);
if (prefinstr[0]) defi->setChecked(true);
grid.addMultiCellWidget(defi, row, row, 0, cols-1);
row++;
*/
}
QPushButton ok("OK", &menu);
ok.setDefault(true);
ok.setFont(font);
connect(&ok, SIGNAL(clicked()), &menu, SLOT(accept()));
grid.addWidget(&ok, row, 0);
QPushButton cancel("Quit", &menu);
cancel.setFont(font);
connect(&cancel, SIGNAL(clicked()), &menu, SLOT(reject()));
grid.addWidget(&cancel, row, cols-1);
bg.hide();
if (printit()) {
printf("Instrument selection\n");
}
if (menu.exec() == QDialog::Rejected) ciao();
rb = dynamic_cast<QRadioButton *>(bg.selected());
if (!rb) ciao();
instr = strdup(rb->text());
/*
if (defi) {
if (defi->isChecked()) {
snprintf(prefinstr, sizeof prefinstr, "%s", instr);
} else {
prefinstr[0] = 0;
}
}
*/
QToolTip::setFont(tooltipfont);
}
if (frominstr[0]) {
snprintf(warning, sizeof warning, "WARNING: connected to %s,\n%s\n", strtoupper(instr), frominstr);
printf("\n%s\n", warning);
} else {
warning[0] = 0;
}
time(&startupTime);
if (printit()) {
printf("Sea %s starting,\n", instr);
}
// read preferences
// include the screen size into the name: this helps if clients are used
// remotely from different screen sizes
// new pref. file: include remote host name
snprintf(preffile, sizeof preffile, "%s/.seapref/%s_%s_%dx%d",
getenv("HOME"), remotehost, instr, desktop()->width(), desktop()->height());
prefdirlen = strstr(preffile, "seapref/") + 7 - preffile;
fil = fopen(preffile, "r");
if (fil) { /* new style pref file */
char header[128];
fgets(header, sizeof header, fil); // skip header
if (4 != fscanf(fil, "%d %d %d %d", &x, &y, &w, &h)) {
x = -1;
}
fclose(fil);
prefil[0] = 0;
} else {
// old style pref. file
snprintf(prefil, sizeof prefil, ".sea_%dx%d_%s",
desktop()->width(), desktop()->height(), instr);
fil = fopen(prefil, "r");
if (fil) {
if (4 != fscanf(fil, "%d %d %d %d", &x, &y, &w, &h)) {
x = -1;
}
fclose(fil);
} else {
x = -1;
}
}
tab = new Tab(strdup(instr), 0, range, warning);
if (tab->graph == NULL) ciao();
connect(tab->device, SIGNAL(restart(const char*)), tab->graph->set, SLOT(restart(const char *)));
if (x >= 0) {
tab->initSize(w, h);
tab->move(x, y);
} else {
tab->initSize(1000, 800);
}
tab->show();
/*
QBoxLayout *lay = dynamic_cast<QBoxLayout *>(tab->layout());
QLayoutIterator it = lay->iterator();
QLayoutItem *child;
while ( (child = it.current()) != 0 ) {
if (child->widget()) {
printf("- widget %s\n", child->widget()->name());
} else if (child->spacerItem()) {
printf("- spacer\n");
} else if (child->layout()) {
printf("- layout\n");
} else {
printf("- null\n");
}
++it;
}
lay->insertWidget(3,tab->split);
*/
firstPos = tab->pos();
tab->move(firstPos);
time(&now);
if (range > 365*24*3600) {
tip.sprintf("initially off");
} else if ((int)(now - startupTime) < 7) {
tip.sprintf("initially on\n%d sec for startup:\nconnection seems fast enough", (int)(now - startupTime));
tab->graph->liveBox->setChecked(true);
} else {
tip.sprintf("initially off\n%d sec for startup:\nconnection seems slow", (int)(now - startupTime));
}
QToolTip::add(tab->graph->liveBox, tip);
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit()));
// connect(this, SIGNAL(lastWindowClosed()), this, SLOT(ciao()));
connect(tab->exportXY, SIGNAL(procEvt()), this, SLOT(procEvt()));
connect(tab->settings->set, SIGNAL(gotoTime(time_t, time_t, time_t, bool)),
tab->report, SLOT(gotoTime(time_t, time_t, time_t, bool)));
connect(tab->report, SIGNAL(setMarker(time_t)),
tab->settings->set, SLOT(setMarker(time_t)));
connect(tab->settings->set->ec, SIGNAL(progress(int)), tab->exportXY, SLOT(progress(int)));
return;
}
void Exit(int code) {
exit(code);
}
void SeaApp::ciao() {
Exit(0);
}
void SeaApp::fail() {
Exit(257);
}
void SeaApp::procEvt() {
processEvents(100);
}
QRect savedWinGeo;
bool moveOrResize = true;
bool SeaApp::notify(QObject *receiver, QEvent *e) {
time_t now;
bool result;
QEvent::Type t = e->type();
switch (t) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick:
case QEvent::KeyPress:
lastActive = time(NULL);
if (tab) {
if (sleeping) {
tab->wake();
sleeping = FALSE;
}
tab->graph->set->runningMarkerOff(true);
result = QApplication::notify(receiver, e);
tab->graph->set->runningMarkerOff(false);
return result;
}
break;
case QEvent::Timer:
time(&now);
if (now > lastActive + sleepTime) {
if (frominstr[0])
exit();
if (lastTimer < now - 120) {
lastActive = now + 120 - sleepTime;
}
// if (home != 1 && now > lastActive + 24*3600) {
// exit(); // exit when not on instrument computer after one day
// }
if (now > lastActive + 24*3600) {
exit(); // exit anyway when not active for one day
}
if (!sleeping && tab != NULL) {
tab->sleep("sleeping ... click to wake up");
sleeping = TRUE;
}
}
if (moveOrResize && now != lastTimer && tab != NULL &&
tab->settings->set->sc->state != disconnected) {
moveOrResize = false;
QRect winGeo(tab->pos(), tab->size());
if (winGeo != savedWinGeo) {
savedWinGeo = winGeo;
fil = fopen(preffile, "w");
if (fil == NULL) {
preffile[prefdirlen] = 0;
mkdir(preffile, 0755);
chmod(preffile, 0755);
preffile[prefdirlen] = '/';
fil = fopen(preffile, "w");
}
if (fil) {
fprintf(fil, "#seaclient preferences V1.1\n%d %d %d %d\n",
winGeo.x(), winGeo.y(),
winGeo.width(), winGeo.height());
fclose(fil);
}
}
}
lastTimer = now;
break;
case QEvent::Move:
case QEvent::Resize:
moveOrResize = true;
break;
case QEvent::WindowDeactivate:
// printf("deact\n");
break;
default:
break;
}
return QApplication::notify(receiver, e);
}
int main(int argc, char ** argv) {
SeaApp sea(argc, argv);
// printf("exit %d\n", sea.exec());
// return 0;
return sea.exec();
}

26
main.h Normal file
View File

@ -0,0 +1,26 @@
#include <stddef.h>
#include <qapplication.h>
#include <qstring.h>
#include "tab.h"
class SeaApp : public QApplication {
Q_OBJECT
public:
SeaApp(int &argc, char **argv);
Tab *tab;
int home;
time_t sleepTime;
public slots:
void ciao();
void fail();
void procEvt();
private:
bool notify(QObject *recevier, QEvent *e);
time_t lastActive;
time_t lastTimer;
bool sleeping;
};

182
report.cpp Normal file
View File

@ -0,0 +1,182 @@
#include "report.h"
#include <stddef.h>
#include <qlayout.h>
#include <qdatetime.h>
#include <qcolor.h>
Report::Report(QWidget *parent, SicsConnection *conn) : QWidget(parent, "report")
{
QVBoxLayout *vbox = new QVBoxLayout(this, 0, 0, "report_vbox");
QHBoxLayout *hdr = new QHBoxLayout(0, 3, 3, "report_hdr");
this->conn = conn;
editButton = new QPushButton("edit", this);
hdr->addWidget(editButton);
varEdit = new QLineEdit("tt.main", this);
hdr->addWidget(varEdit);
leaveButton = new QPushButton("close", this);
hdr->addWidget(leaveButton);
vbox->addLayout(hdr);
textedit = new MyTextEdit(this, "report_edit");
textedit->setReadOnly(TRUE);
textedit->setSelectionAttributes(1, QColor(255,255,128), FALSE);
vbox->addWidget(textedit, 1);
timer = new QTimer(this, "reportTimer");
connect(leaveButton, SIGNAL(clicked()), this, SIGNAL(leave()));
connect(editButton, SIGNAL(clicked()), this, SLOT(editReport()));
connect(timer, SIGNAL(timeout()), this, SLOT(updatePos()));
}
void Report::gotoTime(time_t from, time_t at, time_t to, bool silent) {
char cmd[128];
int iret;
QString line;
time_t lastRead, t, dt;
bool ok;
QString message;
QDateTime datim;
int l;
int p;
if (isHidden()) {
if (silent) return;
openMe();
}
if (variable != varEdit->text() || from != this->from || to != this->to) {
this->to = to;
this->from = from;
times.clear();
variable = varEdit->text();
snprintf(cmd, sizeof cmd, "graph %ld %ld text np %ld %s",
from, to, to - from, variable.latin1());
textedit->clear();
conn->command(cmd);
iret = conn->getLine(line);
if (iret <= 0) {
message = ("can not get response 1");
goto err;
}
/* get returned absolute time */
lastRead = line.toLong();
iret = conn->getLine(line);
if (iret <= 0) {
message = "can not get response 2";
goto err;
}
if (!line.startsWith("*" + variable)) {
message = "response '" + line + "' must start with '*" + variable + "'";
goto err;
}
t = 0;
for (;;) {
iret = conn->getLine(line);
if (iret <= 0) {
message = "can not get line";
goto err;
}
//printf("> %s\n", line.latin1());
if (line.startsWith("*")) {
break;
}
dt = line.section(' ', 0, 0).toLong(&ok);
if (!ok) {
message = "bad timestep";
goto err;
}
t += dt;
times.append(t);
datim.setTime_t(t);
textedit->appendHtml("<font color=#00FF00>" + datim.toString("hh:mm:ss ") + "</font>");
textedit->appendText(
line.section(' ', 1).replace("\\n","\n").replace("\\t","\t").replace("\\\\","\\")
+"\n"
);
}
textedit->append("\n");
pos = -1;
}
l = times.count();
p = l - 1;
for (int ipos = 0; ipos < l; ipos++) {
if (times[ipos] >= at) {
p = ipos - 1;
break;
}
}
if (p < 0) p = 0;
if (pos < 0) {
pos = l;
}
setCursorPos(p);
timer->start(200);
return;
err:
textedit->append("error: "+message);
}
void Report::setCursorPos(int newpos) {
int index;
textedit->setCursorPosition(newpos, 0);
if (newpos > pos) {
textedit->moveCursor(QTextEdit::MoveDown, false);
textedit->moveCursor(QTextEdit::MoveDown, false);
} else {
textedit->moveCursor(QTextEdit::MoveUp, false);
textedit->moveCursor(QTextEdit::MoveUp, false);
}
textedit->getCursorPosition(&posc, &index);
pos = newpos;
textedit->setSelection(pos, 0, pos+1, 0, 1);
textedit->setCursorPosition(posc, 0);
textedit->ensureCursorVisible();
}
void Report::updatePos() {
int para, index;
textedit->getCursorPosition(&para, &index);
if (para == pos) return;
if (para == posc && index == 0) {
// cursor repositioning pending
posc = pos;
textedit->setCursorPosition(posc, 0);
textedit->ensureCursorVisible();
} else {
setCursorPos(para);
}
if (pos < (int)times.count()) {
setMarker(times[pos]);
}
}
void Report::editReport() {
QString text;
if (textedit->isReadOnly()) {
textedit->setReadOnly(FALSE);
timer->stop();
setMarker(0);
} else {
printf("%s\n", textedit->text().latin1());
textedit->setText(textedit->text());
}
}

38
report.h Normal file
View File

@ -0,0 +1,38 @@
#include <stddef.h>
#include <qtextedit.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qvaluevector.h>
#include <qtimer.h>
#include <time.h>
#include "sicsconn.h"
#include "utils.h"
class Report : public QWidget
{
Q_OBJECT
public:
Report(QWidget *parent, SicsConnection *conn);
signals:
void leave();
void openMe();
void setMarker(time_t t);
public slots:
void gotoTime(time_t from, time_t at, time_t to, bool silent);
void updatePos();
void editReport();
private:
void setCursorPos(int newpos);
MyTextEdit *textedit;
QPushButton *editButton;
QPushButton *leaveButton;
QLineEdit *varEdit;
time_t atTime;
QString variable;
SicsConnection *conn;
int pos;
int posc;
time_t from, to;
QValueVector<time_t> times;
QTimer *timer;
};

722
seaplot.cpp Normal file
View File

@ -0,0 +1,722 @@
#include "seaplot.h"
#include <stdlib.h>
#include <math.h>
#include <qfont.h>
#include <qgrid.h>
#include <qtooltip.h>
#include <qwt_plot_layout.h>
#include <qwt_scale.h>
#include "utils.h"
#define SEA_RESOLUTION 0.00005 /* chagned from 0.0005 for Amy, July 2020 */
LegendButton::LegendButton(QWidget *parent, SeaPlot *plot, SeaCurve *crv) : QwtLegendButton(parent) {
this->plot = plot;
this->crv = crv;
connect(this, SIGNAL(clicked()), this, SLOT(legendClicked()));
connect(&clickTimer, SIGNAL(timeout()), this, SLOT(handleClickTimer()));
label = new FlatButton(crv->title(), parent);
setFixedHeight(label->sizeHint().height());
setFixedWidth(16);
connect(label, SIGNAL(clicked()), this, SLOT(legendClicked()));
connect(label, SIGNAL(mousePressed()), this, SLOT(mousePressed()));
};
void LegendButton::init(SeaPlot *plot, SeaCurve *crv) {
this->plot = plot;
this->crv = crv;
};
void LegendButton::mousePressed() {
clickDone = false;
clickTimer.stop();
clickTimer.start(300);
}
void LegendButton::handleClickTimer() {
if (!clickDone) {
clickTimer.stop();
clickDone = true;
longClick();
}
}
void LegendButton::legendClicked() {
if (!clickDone) {
clickDone = true;
clickTimer.stop();
plot->switchBold(crv);
}
};
void LegendButton::longClick() {
plot->setOneBold(crv);
};
void LegendButton::mousePressEvent(QMouseEvent *e) {
mousePressed();
QwtLegendButton::mousePressEvent(e);
}
void LegendButton::setTitle(const QString &title) {
label->setText(title);
}
class TimeScaleDraw: public QwtScaleDraw {
public:
TimeScaleDraw(SeaSet *set) : QwtScaleDraw() {
this->set = set;
}
virtual QString label(double v) const {
QTime time;
QwtScaleDiv div = scaleDiv();
double step = div.majStep();
int itic0 = lround(div.lBound() / step + 0.5001);
int itic1 = lround(div.hBound() / step - 0.5001);
int itic = lround(v / step);;
int m;
if (step < 23*3600) {
m = 2;
if (step > 59 && step < 121) {
m = 5;
} else if (lround(step) == 600) {
m = 3;
}
} else {
m = (itic1 - itic0) / 5 + 1;
}
time.setHMS(0,0,0);
itic0 = lround(div.lBound() / step / m + 0.5001);
itic1 = lround(div.hBound() / step / m - 0.5001);
if (itic1 - itic0 > 1 && v > div.hBound() - step) {
return ""; //do not show last label
} else if (itic % m == 0) {
if (step < 3599) {
return time.addSecs(lround(v)).toString("hh:mm");
} else if (lround(v/3600) % 24 == 0) {
return set->dateLabel(lround(v/(24*3600)));
} else {
return time.addSecs(lround(v)).toString("hh").append("h");
}
} else {
return "";
}
}
SeaSet *set;
};
class YScaleDraw: public QwtScaleDraw {
public:
YScaleDraw(SeaSet *set) : QwtScaleDraw() {
this->set = set;
}
virtual int maxLabelWidth(const QFontMetrics &fm) const {
return set->leftLabelWidth(QwtScaleDraw::maxLabelWidth(fm));
}
SeaSet *set;
};
class SeaZoomer: public QwtPlotZoomer {
friend class SeaPlot;
public:
SeaZoomer(SeaPlot *p) :
QwtPlotZoomer(QwtPlot::xBottom, QwtPlot::yLeft,
QwtPicker::DragSelection, QwtPicker::AlwaysOff,
p->canvas()) {
yAuto = true;
displayMarker = false;
pl = p;
doZoom = false;
};
SeaPlot *pl;
bool yAuto;
bool setMark;
bool displayMarker;
bool track;
bool doZoom;
int xp, yp;
QTime t;
protected:
QwtDoubleSize minZoomSize() const {
const QwtScaleDiv *scy = pl->axisScale(QwtPlot::yLeft);
double hei = fabs(scy->hBound() + scy->lBound()) * SEA_RESOLUTION;
return QwtDoubleSize(60., hei);
};
void rescale() {
QwtDoubleRect r = zoomRect();
if (doZoom && r != scaleRect()) {
pl->zoomTo(scaleRect(), r);
}
}
void enableMarker() {
if (!displayMarker) {
QWidget *parent = parentWidget();
track = parent->hasMouseTracking();
parent->setMouseTracking(true);
displayMarker = true;
}
}
void disableMarker() {
if (displayMarker) {
QWidget *parent = parentWidget();
displayMarker = false;
parent->setMouseTracking(track);
}
}
void widgetMousePressEvent(QMouseEvent *e) {
//printf("*** mousePress %d %d\n", e->x(), e->y());
xp = e->x();
yp = e->y();
if (pl->set->markerFix) {
setMark = true;
} else {
setMark = !pl->set->markerWasOn;
}
pl->set->markerFix = false;
t.start();
QwtPlotZoomer::widgetMousePressEvent(e);
}
void widgetMouseReleaseEvent(QMouseEvent *e) {
//printf("*** mouseRelease %d %d %d\n", e->x(), e->y(), t.elapsed());
// mechanism for avoiding unintended zooms:
// do not allow if the rectangle is too small
// or if the mouse was pressed for less than 200 ms
doZoom = abs(e->x() - xp) + abs(e->y() - yp) > 2 && t.elapsed() > 200;
QwtPlotZoomer::widgetMouseReleaseEvent(e);
if (!doZoom && !displayMarker && setMark) {
QwtDoublePoint p = invTransform(e->pos());
pl->set->setMarker(p.x());
}
}
void widgetMouseDoubleClickEvent(QMouseEvent *e) {
//printf("*** mouseDoubleClick %d %d %d\n", e->x(), e->y(), t.elapsed());
setMark = true;
pl->set->markerFix = true;
QwtDoublePoint at =invTransform(e->pos());
//pl->set->gotoTime(at.x(), FALSE);
}
void widgetMouseMoveEvent(QMouseEvent *e) {
if (displayMarker) {
QwtDoublePoint p = invTransform(e->pos());
if (!pl->set->markerFix) {
pl->set->setMarker(p.x());
pl->set->gotoTime(p.x(), TRUE);
}
} else {
QwtPlotZoomer::widgetMouseMoveEvent(e);
}
}
};
SeaCurve::SeaCurve(QwtPlot *parent, const QString &title) : QwtPlotCurve(parent, title) {
leg = NULL;
iColor = -1;
};
void SeaCurve::draw(QPainter *p, const QwtDiMap &xMap, const QwtDiMap &yMap,
int from, int to) {
int i, start;
double ylowlim;
if (leg->plot->logarithmic) {
ylowlim = 1e-30;
} else {
ylowlim = DATA_UNDEF;
}
start = -1;
if (to < 0) {
to = dataSize() - 1;
if (to < 0) return;
}
for (i=from; i<=to; i++) {
if (i > 0 && y(i) <= ylowlim) { /* undefined value */
if (start >= 0) {
QwtPlotCurve::draw(p, xMap, yMap, start, i-1);
start = -1;
}
} else {
if (start < 0) start = i;
}
}
if (start >= 0) {
QwtPlotCurve::draw(p, xMap, yMap, start, to);
}
};
void SeaCurve::setPen(const QPen &p) {
QwtCurve::setPen(p);
if (leg) leg->setCurvePen(p);
};
void SeaCurve::setTitle(const QString &t) {
QwtCurve::setTitle(t);
if (leg) leg->setTitle(t);
};
void SeaCurve::yBounds(double from, double to, double &ymin, double &ymax) {
int i, n = dataSize();
double y1, y2;
double ya, yb, yc, yd, yi;
int k, n1, n2, nn;
bool done;
double ylowlim;
// implementing a mechanism to ignore spikes:
// after the first pass, the whole range is divided into 3 ranges.
// in the next pass, only the points in the middle range are taken into account
// for minimum and maximum, the others are counted only. When the number of points
// in the upper or in the lower part are less than 2 %, the range is reduced by
// the upper and/or the lower part and a next pass is done
if (leg->plot->logarithmic) {
ylowlim = 1e-30;
} else {
ylowlim = DATA_UNDEF;
}
y1 = 1e30;
y2 = -1e30;
ya = -1e30;
yb = -1e30;
yc = 1e30;
yd = 1e30;
k = 0;
yi = 1e30;
while (1) {
n1 = 0;
n2 = 0;
nn = 0;
for (i=0; i<n; i++) {
if (x(i)>= from) {
break;
}
}
for (; i<n; i++) {
if (x(i) > to) {
break;
}
yi = y(i);
if (yi > ylowlim) { // and therefore yi != DATA_UNDEF
if (yi < yb) {
n1++;
} else if (yi > yc) {
n2++;
} else {
nn++;
if (yi > y2) {
y2 = yi;
}
if (yi < y1) {
y1 = yi;
}
}
}
}
if (i == n && yi > ylowlim) {
if (yi < y1) y1 = yi;
if (yi > y2) y2 = yi;
}
if (k == 0) {
ya = y1;
yd = y2;
} else {
done = true;
if (n1 * 49 < nn + n2 && y1 >= yb) {
ya = y1;
done = false;
}
if (n2 * 49 < nn + n1 && y2 <= yc) {
yd = y2;
done = false;
}
if (done || k > 20 || ya == yd) {
break;
}
//printf("%s %d %d %d %d %f %f\n", data->label.latin1(), k, n1, n2, nn, ya, yd);
}
k++;
yb = ya + (yd - ya) / 3;
yc = yd - (yd - ya) / 3;
y1 = yc;
y2 = yb;
}
if (yi < 0.9e30) {
ymin = QMIN(ymin, ya);
ymax = QMAX(ymax, yd);
}
return;
}
void SeaCurve::changeBold() {
int i;
if (iColor == -1) {
i = Convert2ColorIndex("black");
} else {
i = iColor;
}
leg->plot->set->saveBoldState(data);
if (data->bold) {
setPen(thisPen(i, 0));
QToolTip::add(leg, "hide curve (long click: show this curve only)");
QToolTip::add(leg->label, "hide curve (long click: show this curve only)");
} else {
setPen(thisPen(i, 1));
QToolTip::add(leg, "show curve (long click: this curve only)");
QToolTip::add(leg->label, "show curve (long click: this curve only)");
}
}
SeaPlot::SeaPlot(QWidget *p, SeaSet *set, const QString &name) : QwtPlot(p, name) {
QTime now(QTime::currentTime());
QTime midnight(0,0,0);
double dnow;
//setAutoLegend( TRUE );
//setLegendPosition( QwtPlot::Left , 0.5);
this->set = set;
dnow = midnight.secsTo(now);
setAxisScale(QwtPlot::xBottom, dnow-1800, dnow+600, 300.0);
setAxisScale(QwtPlot::yLeft, 0.0, 0.9999);
setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw(set));
setAxisScaleDraw(QwtPlot::yLeft, new YScaleDraw(set));
setAxisLabelFormat(QwtPlot::yLeft, 'g', 5);
zoom = new SeaZoomer(this);
zoom->setRubberBand(QwtPlotZoomer::RectRubberBand);
zoom->setRubberBandPen(QPen(Qt::red));
plotLayout()->setCanvasMargin(0, SeaPlot::yLeft);
plotLayout()->setCanvasMargin(0, SeaPlot::yRight);
canvas()->setPaletteBackgroundColor(QColor(238,238,238));
setGridPen(QPen(QColor(221, 221, 221), 1));
logarithmic = false;
removeAll();
};
void SeaPlot::removeAll() {
tag = "";
removeCurves();
marker = insertCurve("Marker");
// setCurvePen(marker, QPen(Qt::white, 3));
setCurvePen(marker, QPen(Qt::black, 1));
}
void SeaPlot::setMarker(double x) {
const QwtScaleDiv *s = axisScale(yLeft);
double xval[2], yval[2], h;
SeaCurve *crv;
QwtPlotCurveIterator itc = curveIterator();
if (x == DATA_UNDEF) {
zoom->disableMarker();
xval[0] = DATA_UNDEF;
xval[1] = DATA_UNDEF;
} else {
zoom->enableMarker();
xval[0] = x;
xval[1] = x;
}
h = s->hBound() - s->lBound();
if (logarithmic) {
yval[0] = s->lBound() * 0.5;
} else {
yval[0] = s->lBound() - h;
}
yval[1] = s->hBound() + h;
setCurveData(marker, xval, yval, 2);
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
crv = dynamic_cast<SeaCurve *>(c);
if (crv) {
crv->data->showValueAt(x);
}
}
}
void SeaPlot::refresh() {
const QwtScaleDiv *s = axisScale(xBottom);
replotRange(s->lBound(), s->hBound(), s->majStep());
};
void SeaPlot::autoColors() {
SeaCurve *crv;
QwtPlotCurveIterator itc = curveIterator();
int i;
usedColors.fill(false, N_SEACOLORS);
usedColors.setBit(0); // do not use white
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
crv = dynamic_cast<SeaCurve *>(c);
if (crv) {
if (crv->iColor >= 0 && crv->iColor < N_SEACOLORS) {
usedColors.setBit(crv->iColor);
}
}
}
i=0;
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
crv = dynamic_cast<SeaCurve *>(c);
if (crv) {
if (crv->iColor < 0) {
while (i < N_SEACOLORS && usedColors.at(i)) {
i++;
}
if (i >= N_SEACOLORS) {
crv->iColor = Convert2ColorIndex("black");
} else {
crv->iColor = i;
usedColors.setBit(i);
crv->changeBold();
}
}
}
}
}
LegendButton *SeaPlot::putCurve(SeaData *d, QWidget *parent, LegendButton *legButton) {
SeaCurve *crv = new SeaCurve(this, d->label);
d->plot = this;
d->key = insertCurve(crv);
if (legButton) {
legButton->init(this, crv);
} else {
legButton = new LegendButton(parent, this, crv);
}
legButton->setTitle(d->label);
//QFont myfont(legButton->font());
//myfont.setPointSize(12);
//legButton->setFont(myfont);
//legButton->setFixedHeight(legButton->fontMetrics().height()+2);
crv->leg = legButton;
//crv->leg->setTitle(crv->title());
//crv->leg->setTitle("");
//if (d->style >= 0 && d->style <= N_SEACOLORS) {
if (d->style >= 0) {
crv->iColor = d->style;
crv->autoColor = false;
} else {
crv->iColor = -1;
crv->autoColor = true;
}
crv->data = d;
crv->changeBold();
crv->setStyle(QwtCurve::Lines);
d->modified = true;
d->update();
return legButton;
}
void SeaPlot::showAgain() {
SeaCurve *crv;
QwtPlotCurveIterator itc = curveIterator();
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
crv = dynamic_cast<SeaCurve *>(c);
if (crv) {
crv->data->bold = true;
crv->changeBold();
}
}
autoColors();
//refresh();
set->replotAnyway();
}
bool SeaPlot::toggleLinLog() {
logarithmic = ! logarithmic;
if (logarithmic) {
setAxisOptions(QwtPlot::yLeft, QwtAutoScale::Logarithmic);
} else {
setAxisOptions(QwtPlot::yLeft, QwtAutoScale::None);
}
refresh();
return logarithmic;
}
void SeaPlot::zoomMax() {
autoZoom(true);
refresh();
}
void SeaPlot::autoZoom(bool on) {
zoom->yAuto = on;
setAutoOff(!on);
}
void SeaPlot::undoZoom(QwtDoubleRect &r) {
setAxisScale(QwtPlot::yLeft, r.y1(), r.y2());
zoom->setZoomBase();
}
void SeaPlot::zoomTo(QwtDoubleRect old, QwtDoubleRect &r) {
set->saveRange(this, old, zoom->yAuto);
autoZoom(false);
setAxisScale(QwtPlot::yLeft, r.y1(), r.y2());
set->rescale(r.x1(), r.x2());
zoom->setZoomBase();
}
void SeaPlot::zoomOut() {
QwtDoubleRect r = zoom->zoomRect();
QwtDoubleRect old= zoom->scaleRect();
set->saveRange(this, old, zoom->yAuto);
if (logarithmic) {
double h = log(r.y2()) - log(r.y1());
r.setY2(exp(log(r.y2()) + h / 2));
r.setY1(exp(log(r.y1()) - h / 2));
} else {
double h = r.y2() - r.y1();
r.setY2(r.y2() + h / 2);
r.setY1(r.y1() - h / 2);
}
zoom->setZoomBase(r);
zoom->zoom(0);
autoZoom(false);
refresh();
}
void SeaPlot::shiftUp() {
QwtDoubleRect r = zoom->zoomRect();
double h = (r.y2() - r.y1()) * 0.5;
QwtDoubleRect old= zoom->scaleRect();
set->saveRange(this, old, zoom->yAuto);
r.setY2(r.y2() + h);
r.setY1(r.y1() + h);
zoom->setZoomBase(r);
zoom->zoom(r);
zoom->setZoomBase();
zoom->zoom(0);
autoZoom(false);
refresh();
}
void SeaPlot::shiftDown() {
QwtDoubleRect r = zoom->zoomRect();
double h = (r.y2() - r.y1()) * 0.5;
QwtDoubleRect old= zoom->scaleRect();
set->saveRange(this, old, zoom->yAuto);
r.setY2(r.y2() - h);
r.setY1(r.y1() - h);
zoom->setZoomBase(r);
zoom->zoom(r);
zoom->setZoomBase();
zoom->zoom(0);
autoZoom(false);
refresh();
}
int SeaPlot::replotRange(double from, double to, double tick) {
SeaCurve *crv;
QwtDoubleRect r;
double ymin, ymax, yminA, ymaxA, y0, res;
int result;
bool nobold;
result = 1;
ymin = 1e30;
ymax = -1e30;
yminA = ymin;
ymaxA = ymax;
nobold = true;
QwtPlotCurveIterator itc = curveIterator();
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
crv = dynamic_cast<SeaCurve *>(c);
if (crv) {
crv->yBounds(from, to, yminA, ymaxA);
if (crv->data->bold) {
crv->yBounds(from, to, ymin, ymax);
}
}
}
if (ymin > ymax) {
ymin = yminA;
ymax = ymaxA;
if (ymin > ymax) {
ymin = 0;
ymax = 1;
result = 0;
}
}
r = zoom->zoomRect();
if (zoom->yAuto) {
res = 0.1;
} else {
ymin = r.y1();
ymax = r.y2();
res = SEA_RESOLUTION;
}
if (logarithmic) {
if (ymax <= 0) {
ymax = ymaxA;
ymin = yminA;
} else if (ymin <= 0) {
ymin = QMIN(ymax, yminA);
}
y0 = (log(ymin) + log(ymax)) / 2;
if ((log(ymax) - log(ymin)) < res) {
ymin = exp(y0 - res * 0.4999);
ymax = exp(y0 + res * 0.5);
}
} else {
y0 = (ymin + ymax) / 2;
if ((ymax - ymin) < y0 * res) {
ymin = y0 * (1 - res * 0.4999);
ymax = y0 * (1 + res * 0.5);
}
}
setAxisMaxMinor(QwtPlot::xBottom, 0);
setAxisScale(QwtPlot::xBottom, from, to, tick);
setAxisScale(QwtPlot::yLeft, ymin, ymax);
replot();
if (zoom->zoomRectIndex() == 0) {
zoom->setZoomBase();
}
return result;
};
int SeaPlot::replotRange() {
const QwtScaleDiv *scx = axisScale(QwtPlot::xBottom);
return replotRange(scx->lBound(), scx->hBound(), scx->majStep());
};
void SeaPlot::switchBold(SeaCurve *crv) {
crv->data->bold = !crv->data->bold;
crv->changeBold();
crv->leg->update();
set->replotAnyway();
set->updateCurveList();
}
void SeaPlot::setOneBold(SeaCurve *selectedCrv) {
QwtPlotCurveIterator itc = curveIterator();
SeaCurve *crv;
for (QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc ) {
crv = dynamic_cast<SeaCurve *>(c);
if (crv) { // omit Marker
crv->data->bold = crv == selectedCrv;
crv->changeBold();
crv->leg->update();
}
}
autoZoom(true);
set->replotAnyway();
set->updateCurveList();
}

97
seaplot.h Normal file
View File

@ -0,0 +1,97 @@
#ifndef SEAPLOT_H
#define SEAPLOT_H
#include <stddef.h>
#include <qwt_plot.h>
#include <qlayout.h>
#include <qbitarray.h>
#include "seaset.h"
class SeaSet;
class SeaData;
class SeaZoomer;
class SeaCurve;
class LegendButton;
class QGrid;
class QLineEdit;
class SeaPlot : public QwtPlot
{
Q_OBJECT
public:
SeaPlot(QWidget *p, SeaSet *set, const QString &name);
void removeAll();
LegendButton *putCurve(SeaData *d, QWidget *parent, LegendButton *legButton = NULL);
int replotRange(double from, double to, double tick);
int replotRange();
void refresh();
void switchBold(SeaCurve *crv);
void setOneBold(SeaCurve *crv);
void showAgain();
SeaSet *set;
QString tag;
void autoZoom(bool on);
QwtDoubleRect undoRect;
void zoomTo(QwtDoubleRect old, QwtDoubleRect &r);
void undoZoom(QwtDoubleRect &r);
bool toggleLinLog();
void autoColors();
long marker;
void setMarker(double x);
bool logarithmic;
QBitArray usedColors;
signals:
void setAutoOff(bool off);
private slots:
void zoomOut();
void zoomMax();
void shiftUp();
void shiftDown();
private:
SeaZoomer *zoom;
double y1, y2;
};
class FlatButton;
class LegendButton : public QwtLegendButton {
Q_OBJECT
public:
LegendButton(QWidget *parent, SeaPlot *plot, SeaCurve *crv);
void init(SeaPlot *plot, SeaCurve *crv);
void setTitle(const QString &title);
FlatButton *label;
QLabel *valueLabel;
SeaPlot *plot;
QTimer clickTimer;
protected:
void mousePressEvent(QMouseEvent *e);
public slots:
void legendClicked();
void longClick();
void handleClickTimer();
void mousePressed();
private:
SeaCurve *crv;
bool clickDone;
};
class SeaCurve : public QwtPlotCurve {
public:
SeaCurve(QwtPlot *parent, const QString &title);
void draw(QPainter *p, const QwtDiMap &xMap, const QwtDiMap &yMap, int from, int to);
void setPen(const QPen &p);
void setTitle(const QString &t);
void yBounds(double from, double to, double &ymin, double &ymax);
void changeBold();
SeaData *data;
bool bold;
int iColor;
bool autoColor;
LegendButton *leg;
};
#endif

1901
seaset.cpp Normal file

File diff suppressed because it is too large Load Diff

228
seaset.h Normal file
View File

@ -0,0 +1,228 @@
#ifndef SEASET_H
#define SEASET_H
#include <stddef.h>
#include <qstring.h>
#include <qlayout.h>
#include <qdatetime.h>
#include <qdict.h>
#include <qwt_plot.h>
#include <qwt_plot_zoomer.h>
#include <qptrlist.h>
#include <qptrcollection.h>
#include <qsplitter.h>
#include <qhbox.h>
#include <qvbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qpushbutton.h>
#include <qpixmap.h>
#include "sicsconn.h"
#include "seaplot.h"
#define SEA_MAX_RANGE (240*3600-60)
// values lower or equal than this value are considered as undefined
#define DATA_UNDEF (-1e33)
class SeaPlot;
class SeaSet;
class SeaRow;
class QGrid;
class LegendButton;
class SeaData {
public:
SeaData(const QString &name, const QString &label, const QString &plotName, int color=0);
~SeaData();
int addValue(double xx, QString value);
bool update();
void init(time_t step, int siz);
void showValueAt(double at);
bool isActive();
QString name;
QString label;
QString plotName;
int size;
double *x; // x[0..size_m-1]
double *y; // y[0..size_m-1]
double step_m;
double lastx;
int size_m;
bool clr;
bool dirty;
bool modified;
bool bold;
bool exact;
double period; // update period
long key;
SeaPlot *plot;
SeaRow *row;
QLabel *shownValue;
int decipos;
long style;
};
typedef enum {hiddenRow, shownRow, newRow} RowState;
class SeaRow: public QScrollView {
Q_OBJECT
public:
SeaRow(QWidget *parent);
QHBox *hBox;
// QScrollView *left;
SeaPlot *plot;
QGrid *leg;
QScrollView *legScroll;
QVBox *right;
SeaSet *set;
QPtrList<LegendButton> legendList;
uint usedLegend;
QHBox *bBox;
RowState state;
QPushButton *lBut;
QPixmap pmLin, pmLog;
QLabel *tagLabel;
QLabel *timeLabel;
void setInnerHeights(bool isfirstrow, int rowH);
void setTag(QString tag);
virtual void resizeEvent(QResizeEvent *e);
virtual QSize minimumSizeHint() const;
public slots:
void hideRow();
void linLog();
};
typedef enum {liveOff, liveAuto, liveOn} LiveState;
typedef struct GetArg {
bool all, append;
time_t from, to;
} GetArg;
typedef struct AutoArg {
QString vars;
} AutoArg;
class SeaSet : public QObject {
Q_OBJECT
friend class SeaPlot;
friend class SeaRow;
public:
SeaSet( QSplitter *parent, long range, const char *name);
SeaRow *newPlot(const char *name = "");
int leftLabelWidth(int in);
void insertData(const QString &cName, const QString &label, const QString &pName, const int color);
void clrDataList();
void finishDataList();
QString dateLabel(long dayOffset);
QPtrList<SeaData> dataList;
void readNewReplot();
void rescaleRange(time_t range);
void rescale(time_t from, time_t to);
void rescale(double from, double to);
void calcBase(time_t from);
void saveRange();
void saveRange(SeaPlot *plot, QwtDoubleRect &old, bool yAuto);
void hideRow();
void adjustSizes();
int sicsCommand(QString &cmd, int graph=0); // blocking
int sendSicsCommand(QString &cmd, int graph=0); // non-blocking
void setMarker(double x);
void setTimeLabel(double x);
void runningMarkerOff(bool beforeEvent);
void saveRowHeight(SeaRow *row, int height);
int getRowHeight(SeaRow *row);
void saveBoldState(SeaData *data);
void getBoldState(SeaData *data);
void setFirstRow();
void gotoTime(double at, bool silent);
SicsConnection *sc, *uc, *gc, *ec;
int legendWidth, actLegendWidth;
QString hostport;
time_t startRange, endRange;
time_t base;
double markerPos;
bool markerWasOn;
bool markerFix;
SeaRow *firstRow;
double lastTime;
public slots:
void autoCurves(const char *vars = 0);
void setHost(const QString &hostport);
void setTimeRange(time_t start, long seconds);
void showAll();
void liveUpdate();
//void handleSics(const char *line);
void shiftLeft();
void zoomOutX();
void shiftRight();
void undoZoom();
void setLive(bool on);
void restart(const char *vars);
void replot();
void replotAnyway();
void asyncHandler();
void setMarker(time_t t);
signals:
void putCurve(const QString &name, const QString &plot);
void undoEnabled(bool on);
void updateCurveList();
void gotoTime(time_t from, time_t at, time_t to, bool silent);
private:
void setBase();
void setDate();
void getCurves(bool all, time_t from, time_t to);
SeaData *findData(const QString &name);
void calcLeftLabelWidth();
bool autoCurvesP1();
void autoCurvesP2();
int getCurvesP1();
void getCurvesP2();
QSplitter *split;
QLayout *layout;
time_t lastRead; // time of last read on server
bool compressed;
QPtrList<SeaRow> rows;
int nplots;
QwtPlotZoomer *zoom;
int labelWidth;
int labelMode;
bool reread;
int refresh;
LiveState live;
time_t liveTime;
SeaPlot *undoPlot;
QwtDoubleRect undoRect;
time_t undoStart, undoEnd;
bool undoAuto;
bool initSizes;
int xSize;
time_t curveStep;
// asynchronous stuff:
enum {async_idle, async_auto, async_get} async_mode;
AutoArg autoArg, autoArgDo;
GetArg getArg, getArgDo;
bool autoDo, getDo, getNewData;
QTimer *asyncTimer;
QTime meas;
QTime tmot;
bool showPlot;
QDict<int> rowHeightDict;
QDict<bool> boldDict;
};
void setprintit(int p);
int printit(void);
#endif

339
settings.cpp Normal file
View File

@ -0,0 +1,339 @@
#include "settings.h"
#include <qapplication.h>
#include <qdialog.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qvalidator.h>
#include <qscrollview.h>
#include <qvbox.h>
#include <qgrid.h>
#include <qstringlist.h>
#include <stdio.h>
#include <math.h>
#include "utils.h"
void SetLength(QLineEdit *lineEdit, int min, int max) {
lineEdit->setMaxLength(max);
int w0 = lineEdit->fontMetrics().width('0');
int w = lineEdit->frameWidth() * 2 + 6;
lineEdit->setMinimumWidth(w + w0 * min);
lineEdit->setMaximumWidth(w + w0 * max);
}
Settings::Settings(QWidget* parent)
: QWidget(parent)
{
QHBoxLayout *buttonLayout;
QVBoxLayout *vbox;
QString str;
time_t now;
struct tm date;
vbox = new QVBoxLayout(this, 0, 0, "vBox");
setName("Settings");
table = new QScrollView(this, "table");
form = new QWidget(table->viewport(), "form");
formVL = new QVBoxLayout(form, 0, 0, "formVL");
formLayout = new QGridLayout(0, 3, 3, 6, 3);
formVL->addLayout(formLayout);
formVL->addStretch(1);
/*
formBox = new QHBox(table->viewport(), "formBox");
form = new QGrid(4, formBox, "form");
*/
table->addChild(form);
table->setHScrollBarMode(QScrollView::AlwaysOff);
buttonLayout = new QHBoxLayout(0, 3, 3, "buttonLayout");
newButton = new QPushButton(this, "newButton");
newButton->setText("New Curve");
buttonLayout->addWidget(newButton);
/*
autoButton = new QPushButton(this, "autoButton");
autoButton->setText("Auto");
buttonLayout->addWidget(autoButton);
*/
cancelButton = new QPushButton(this, "cancelButton");
cancelButton->setText("Cancel");
buttonLayout->addWidget(cancelButton);
okButton = new QPushButton(this, "okButton");
okButton->setText("OK");
buttonLayout->addWidget(okButton);
okButton->setDefault(true);
buttonLayout->addStretch(1);
time(&now);
date = *localtime(&now);
buttonLayout->addWidget(new QLabel("# Days", this));
rLE = new QLineEdit(this);
SetLength(rLE, 2, 2);
rLE->setText(str);
rLE->setValidator(new QIntValidator(0, 99, this));
buttonLayout->addWidget(rLE);
buttonLayout->addWidget(new QLabel("starting from", this));
dLE = new QLineEdit(this);
SetLength(dLE, 2, 2);
str.sprintf("%d", date.tm_mday);
dLE->setText(str);
dLE->setValidator(new QIntValidator(0, 31, this));
buttonLayout->addWidget(dLE);
buttonLayout->addWidget(new QLabel(".", this));
mLE = new QLineEdit(this);
SetLength(mLE, 2, 2);
str.sprintf("%d", date.tm_mon+1);
mLE->setText(str);
mLE->setValidator(new QIntValidator(1, 12, this));
buttonLayout->addWidget(mLE);
buttonLayout->addWidget(new QLabel(".", this));
yLE = new QLineEdit(this);
SetLength(yLE, 4, 4);
str.sprintf("%d", date.tm_year+1900);
yLE->setText(str);
yLE->setValidator(new QIntValidator(2001, date.tm_year+1900, this));
buttonLayout->addWidget(yLE);
hrLE = new QLineEdit(this);
SetLength(hrLE, 5, 5);
hrLE->setText("00:00");
buttonLayout->addWidget(hrLE);
vbox->addLayout(buttonLayout);
vbox->addWidget(table, 1);
//vbox->addStretch(1);
formLayout->addWidget(new QLabel("Curve", form), 0, 0);
formLayout->addWidget(new QLabel("Label", form), 0, 1);
formLayout->addWidget(new QLabel("Unit", form), 0, 2);
formLayout->addWidget(new QLabel("Color", form), 0, 3);
/*
new QLabel("Curve", form);
new QLabel("Label", form);
new QLabel("Plot", form);
new QLabel("Color", form);
*/
row = 1;
connect(newButton, SIGNAL(clicked()),
this, SLOT(addEmpty()));
connect(okButton, SIGNAL(clicked()),
this, SLOT(ok()));
/*
connect(autoButton, SIGNAL(clicked()),
this, SLOT(autoCurves()));
*/
connect(cancelButton, SIGNAL(clicked()),
this, SLOT(cancel()));
connect(rLE, SIGNAL(textChanged(const QString &)),
this, SLOT(checkRange(const QString &)));
/*
connect(dLE, SIGNAL(textChanged(const QString &)),
this, SLOT(calcDate(const QString &)));
connect(mLE, SIGNAL(textChanged(const QString &)),
this, SLOT(calcDate(const QString &)));
connect(yLE, SIGNAL(textChanged(const QString &)),
this, SLOT(calcDate(const QString &)));
*/
clearWState(WState_Polished);
}
void Settings::updateHeight() {
form->setMinimumHeight(table->visibleHeight());
}
void Settings::resizeEvent(QResizeEvent *e) {
updateHeight();
form->setFixedWidth(table->visibleWidth());
QWidget::resizeEvent(e);
}
void Settings::showIt(bool yes) {
if (yes) {
clear();
putCurves(&set->dataList);
show();
} else {
hide();
}
}
#define YEAR (24*3600*360)
void Settings::checkRange(const QString &str0) {
if (str0.compare("") == 0) {
dLE->setEnabled(false);
mLE->setEnabled(false);
yLE->setEnabled(false);
hrLE->setEnabled(false);
} else {
dLE->setEnabled(true);
mLE->setEnabled(true);
yLE->setEnabled(true);
hrLE->setEnabled(true);
}
}
void Settings::putCurve(const QString &name, const QString &label,
const QString &plotName, long colorIndex) {
QLineEdit *n, *p;
ColorMenu *cm;
unsigned int idx;
QString colortext;
idx = row - 1;
if (idx < names.count()) {
n = names.at(idx);
} else {
n = new QLineEdit(form);
SetLength(n, 8, 64);
formLayout->addWidget(n, row, 0);
names.append(n);
}
n->setText(name);
n->show();
if (idx < labels.count()) {
p = labels.at(idx);
} else {
p = new QLineEdit(form);
SetLength(p, 8, 64);
formLayout->addWidget(p, row, 1);
labels.append(p);
}
p->setText(label);
p->show();
if (idx < plots.count()) {
p = plots.at(idx);
} else {
p = new QLineEdit(form);
SetLength(p, 4, 8);
formLayout->addWidget(p, row, 2);
plots.append(p);
}
p->setText(plotName);
p->show();
Convert2ColorName(colorIndex, colortext);
if (idx < colors.count()) {
cm = colors.at(idx);
cm->setCurrentItem(0);
cm->setCurrentText(colortext);
} else {
cm = new ColorMenu(colortext, form);
cm->setLength(12, 32);
formLayout->addWidget(cm, row, 3);
colors.append(cm);
}
cm->show();
row++;
}
void Settings::putCurves(QPtrList<SeaData> *dataList) {
SeaData *c;
for (c = dataList->first(); c != 0; c = dataList->next()) {
putCurve(c->name, c->label, c->plotName, c->style);
}
updateHeight();
}
void Settings::addEmpty() {
putCurve("","","",-1);
updateHeight();
/*
names.last()->show();
labels.last()->show();
plots.last()->show();
colors.last()->show();
*/
}
void Settings::apply() {
int i, n;
long days;
time_t t;
struct tm date;
QStringList hr_min;
if (rLE->text().compare("") != 0) {
days = rLE->text().toLong();
time(&t);
date = *localtime(&t);
date.tm_mday = dLE->text().toInt();
date.tm_mon = mLE->text().toInt() - 1;
date.tm_year = yLE->text().toInt() - 1900;
hr_min = QStringList::split(":", hrLE->text());
date.tm_hour = (int)hr_min[0].toFloat();
if (hr_min.size() > 1) {
date.tm_min = (int)hr_min[1].toFloat();
} else {
date.tm_min = 0;
}
date.tm_sec = 0;
date.tm_isdst = -1;
set->setTimeRange(mktime(&date), 24*3600*QMAX(1, days));
set->autoCurves();
} else {
set->clrDataList();
n = names.count();
for (i = 0; i < n; i++) {
//printf("%s\n", names.at(i)->text().latin1());
set->insertData(names.at(i)->text(), labels.at(i)->text(), plots.at(i)->text(), colors.at(i)->getColorIndex());
}
set->finishDataList();
}
}
void Settings::ok() {
apply();
leaveSettings();
}
void Settings::cancel() {
leaveSettings();
}
void Settings::clear() {
int i, n;
n = names.count();
for (i = 0; i < n; i++) {
names.at(i)->setText("");
plots.at(i)->setText("");
labels.at(i)->setText("");
colors.at(i)->setValue(0);
}
row = 1;
rLE->setText("");
}
void Settings::autoCurves() {
clear();
set->autoCurves();
putCurves(&set->dataList);
}

52
settings.h Normal file
View File

@ -0,0 +1,52 @@
#include <stddef.h>
#include <qdialog.h>
#include <qptrlist.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qcheckbox.h>
#include <qlayout.h>
#include "seaset.h"
// for ColorMenu:
#include "device.h"
class Settings : public QWidget
{
Q_OBJECT
public:
Settings(QWidget* parent = 0);
//~Settings();
void clear();
void putCurves(QPtrList<SeaData> *curves);
void apply();
SeaSet *set;
QPushButton *okButton, *cancelButton, *newButton;
/* QPushButton *autoButton; */
QLineEdit *rLE, *dLE, *mLE, *yLE, *hrLE;
signals:
void leaveSettings();
public slots:
void addEmpty();
void ok();
void cancel();
void autoCurves();
void checkRange(const QString &str);
void showIt(bool show);
void resizeEvent(QResizeEvent *e);
protected:
void putCurve(const QString &name, const QString &label, const QString &plotName, long colorIndex);
void updateHeight();
QScrollView *table;
QWidget *form;
QVBoxLayout *formVL;
QGridLayout *formLayout;
QPtrList<QLineEdit> names;
QPtrList<QLineEdit> labels;
QPtrList<QLineEdit> plots;
QPtrList<ColorMenu> colors;
int row;
};

601
sicsconn.cpp Normal file
View File

@ -0,0 +1,601 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/select.h>
#include <string.h>
#include "sicsconn.h"
#include "instr_hosts.h"
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <assert.h>
#include <signal.h>
int printit(void);
int uselect(int nfds,
fd_set * readfds, fd_set * writefds, fd_set * exceptfds,
struct timeval *timeout)
{
sigset_t sigmask;
struct timespec tmo, *tmoPtr;
int result;
sigfillset(&sigmask);
if (timeout) {
tmo.tv_sec = timeout->tv_sec;
tmo.tv_nsec = timeout->tv_usec * 1000;
tmoPtr = &tmo;
} else {
tmoPtr = NULL;
}
result = pselect(nfds, readfds, writefds, exceptfds, tmoPtr, &sigmask);
return result;
}
static int sigpipe_ignored = 0;
int SicsSockAdr(struct sockaddr_in *sockaddr, const char *hostport,
int defaultPort, const char *server) {
// create sockadr from hostport (hostname and port number separated with colon)
// hostport may also be an instrument name, in this case server has to be defined
struct hostent *hostent; /* Host database entry */
struct in_addr addr; /* For 64/32 bit madness */
char *p;
char host[128], instr[32];
int port;
int l;
(void) memset((char *) sockaddr, '\0', sizeof(struct sockaddr_in));
if (hostport == NULL) hostport="";
p = strchr((char *)hostport, ':');
if (p != NULL) {
l = p - hostport;
port = atoi(p+1);
} else {
InstrHost((char *)server, (char *)hostport, instr, sizeof instr,
host, sizeof host, &port);
if (port == 0) {
port = atoi(hostport);
if (port != 0) {
l = 0;
} else {
l = strlen(hostport);
}
} else {
l = -1;
}
}
if (l>= 0) {
if (l >= (int)sizeof host) return -1;
strncpy(host, hostport, l);
host[l]='\0';
}
if (port == 0) port = defaultPort;
if (port == 0) return -1;
sockaddr->sin_family = AF_INET;
sockaddr->sin_port = htons((unsigned short) (port & 0xFFFF));
if (host[0]=='\0') {
addr.s_addr = INADDR_ANY;
} else {
hostent = gethostbyname(host);
if (hostent != NULL) {
memcpy((char *) &addr,
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
} else {
addr.s_addr = inet_addr(host);
if (addr.s_addr == (unsigned long)-1) {
return -1; /* error */
}
}
}
/*
* There is a rumor that this assignment may require care on
* some 64 bit machines.
*/
sockaddr->sin_addr.s_addr = addr.s_addr;
return 0;
}
int SicsConnect(const char *hostport, const char *server, bool async) {
struct sockaddr_in sadr;
int iret, fd;
int oldopts;
iret = SicsSockAdr(&sadr, hostport, 8641, server);
if (iret < 0) return -1;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) return -1;
if (async) {
oldopts = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, oldopts | O_NONBLOCK);
}
iret = connect(fd, (struct sockaddr *)&sadr, sizeof(sadr));
if (iret < 0) {
switch (errno) {
case EINPROGRESS:
case EALREADY:
case EISCONN:
return fd;
}
return -1;
}
return fd;
}
int SicsConnectSuccess(int fd)
{
// returns 1 on success, 0 when pending, -1 on error
fd_set wmask, rmask;
struct timeval tmo = { 0, 0 };
int oldopts;
int ret;
oldopts = fcntl(fd, F_GETFL, 0);
assert(oldopts | O_NONBLOCK); /* fd must be in non-blocking mode */
FD_ZERO(&wmask);
FD_ZERO(&rmask);
FD_SET(fd, &wmask);
FD_SET(fd, &rmask);
ret = uselect(fd + 1, &rmask, &wmask, NULL, &tmo);
if (ret > 0) {
if (FD_ISSET(fd, &rmask)) { /* there may already be data for read */
if (recv(fd, NULL, 0, 0) < 0) { /* zero length, check only return value */
ret = -1; /* first recv failed */
}
} else {
if (FD_ISSET(fd,&wmask)) {
if (send(fd, NULL, 0, 0) < 0) { /* zero length, check only return value */
ret = -2; /* first send failed */
}
}
}
}
fcntl(fd, F_SETFL, oldopts & ~O_NONBLOCK); /* reset to blocking mode */
return ret;
}
SicsConnection::SicsConnection(QObject *parent) : QObject(parent) {
hostport = NULL;
userpass = NULL;
server = NULL;
state = disconnected;
bufline = "";
bufstate = buf_got_line;
connect_state = connect_start;
command2send = "";
tmo = 0;
if (!sigpipe_ignored) {
signal (SIGPIPE, SIG_IGN);
sigpipe_ignored = 1;
}
rdbuffer = "";
progressPos = 0;
rdpos = 0;
debug = 0;
}
//SicsConnection::SicsConnection(SicsConnection *copy) {
// hostport = strdup(copy->hostport);
// userpass = NULL;
// state = disconnected;
//}
SicsConnection::~SicsConnection() {
if (state != disconnected) {
close(fd);
fd = -1;
}
if (hostport) free(hostport);
if (userpass) free(userpass);
if (server) free(server);
}
void SicsConnection::setHost(const char *hostport, const char *server) {
if (this->hostport != NULL) free(this->hostport);
if (hostport != NULL) {
this->hostport = strdup(hostport);
} else {
this->hostport = NULL;
}
if (this->server != NULL) free(this->server);
this->server = strdup(server);
}
void SicsConnection::setUser(const char *userpass) {
if (this->userpass != NULL) free(this->userpass);
if (userpass != NULL) {
this->userpass = strdup(userpass);
} else {
this->userpass = NULL;
}
}
int SicsConnection::handleBuffer(void) {
return handleBuffer(0);
}
int SicsConnection::handleBuffer(int tmo) {
fd_set mask;
struct timeval tmov;
int iret = 1;
int pos;
char ch;
char line[128];
switch (connect_state) {
case connect_start:
fd = SicsConnect(hostport, server, true);
if (fd < 0) {
connect_state = connect_error; // what else?
return -1;
}
connect_state = connect_wait;
return 0;
case connect_wait:
iret = SicsConnectSuccess(fd);
if (iret <= 0) {
if (startServer) {
iret = system(startServer);
if (iret) {
printf("can not connect to sea and failed to start the sea server\n");
printf("\n");
pos = strcspn(hostport, ":");
printf("please execute 'sea start' from the instrument account of %.*s\n", pos, hostport);
printf("\n");
exit(1);
}
} else {
iret = 1;
}
startServer = NULL;
return iret;
}
connect_state = connect_login;
return 0;
case connect_login:
if (userpass == NULL) {
snprintf(line, sizeof line, "Spy 007\n");
} else {
snprintf(line, sizeof line, "%s", userpass);
}
bufstate = buf_sent_line;
send(fd, line, strlen(line), 0);
connect_state = connect_waitlogin;
// if (strcmp(server, "sea") == 0 && userpass != NULL) {
// printf("*** send login (%s %s)\n", server, line);
// }
return 0;
case connect_error:
return -2;
default: break;
}
FD_ZERO(&mask);
while (bufstate > buf_got_finished) {
do {
FD_SET(fd, &mask);
tmov.tv_sec = tmo;
tmov.tv_usec = 0;
iret = select(fd+1, &mask, NULL, NULL, &tmov);
if (iret < 0) {
perror("select");
close(fd);
fd = -1;
connect_state = connect_error;
state = disconnected;
return -2;
} else if (iret == 0) {
return -1; /* no more data */
}
iret = recv(fd, &ch, 1, 0);
if (iret <= 0) {
close(fd);
fd = -1;
connect_state = connect_error;
state = disconnected;
if (printit()) printf("zero on receive -> disconnected\n");
// printf("*** disconnected (zero on receive)\n");
return -2;
}
bufline.append(ch);
} while (ch != '\n');
iret = 0;
rdbuffer += bufline;
if (debug) {
// printf("%s bufline{%s}\n", debug, bufline.latin1());
}
if ((int)rdbuffer.length() >= progressPos + 1000) {
progress(rdbuffer.length() - progressPos);
progressPos = rdbuffer.length();
}
// if (strcmp(server, "sea") == 0 && userpass != NULL) {
// printf("*** bufline %s", bufline.latin1());
// }
if (bufstate == buf_got_start && bufline.startsWith("TRANSACTIONFINISHED")) {
bufstate = buf_got_finished;
iret = 1;
}
if (bufstate == buf_sent_transact && bufline.startsWith("TRANSACTIONSTART")) {
bufstate = buf_got_start;
}
if (bufstate == buf_sent_line) {
bufstate = buf_got_line;
if (connect_state == connect_waitlogin) {
if (debug) {
printf("connectlogin %s\n", bufline.latin1());
}
if (bufline.startsWith("Login OK\n")) {
connect_state = connect_done;
state = connected;
if (command2send != "") {
sendThis(command2send.latin1());
command2send = "";
if (state == disconnected) {
return -1;
}
bufstate = buf_sent_transact;
}
} else {
bufstate = buf_sent_line;
}
} else {
iret = 1;
}
}
bufline = "";
}
return iret;
}
int SicsConnection::getLine(QString &line) {
QString qline;
int pos, len;
if (state == disconnected) {
return -1;
}
handleBuffer(0);
if (rdpos >= (int)rdbuffer.length() && tmo > 0) {
if (handleBuffer(tmo) < 0) {
printf("timeout %d\n", tmo);
}
}
if (rdpos < (long)rdbuffer.length()) {
pos = rdbuffer.find('\n', rdpos);
if (pos < rdpos) { // lf not found, return up to end of buffer (is this correct?)
return 0; /***/
len = rdbuffer.length() - rdpos;
line = rdbuffer.mid(rdpos);
progressPos -= rdbuffer.length();
rdbuffer="";
rdpos = 0;
} else {
len = pos - rdpos;
line = rdbuffer.mid(rdpos,len);
rdpos = pos + 1;
//rdbuffer.remove(0, pos + 1);
}
if (debug) {
//printf("%s getLine{%s}{%s}\n", debug, line.latin1(), rdbuffer.mid(rdpos,9).latin1());
printf("%s getLine{%s}\n", debug, line.latin1());
}
if (line.startsWith("TRANSACTIONFINISHED")) {
if (state == replying) {
state = connected;
return 0;
}
}
return len;
} else {
if (debug) {
// printf("%s error\n", debug);
}
return -1;
}
return 0;
}
void SicsConnection::swallow() {
QString line;
bool done;
if (debug) {
printf("%s swallow start\n", debug);
}
while (state == replying) {
if (getLine(line) > 0) {
done = false;
handle(line, &done);
if (!done) {
//printf("*** swallow {%s}\n", line);
}
}
}
if (debug) {
printf("%s swallow end\n", debug);
}
}
int SicsConnection::sendThis(const char *str) {
int l, iret;
if (state != disconnected) {
l = strlen(str);
// if (strcmp(server, "sea") == 0 && userpass != NULL) {
// printf("*** send {%s}\n", str);
// }
iret = send(fd, str, l, 0);
if (iret != l) {
printf("sent %d of %d, disconnect\n", iret, l);
close(fd);
fd = -1;
state = disconnected;
return -1;
}
return 1;
}
return -1;
}
void SicsConnection::reconnect(void) {
if (state != disconnected) {
close(fd);
fd = -1;
state = disconnected;
}
connect_state = connect_start;
command2send.sprintf("fulltransact config listen 1\n");
}
void SicsConnection::disconnect(void) {
close(fd);
fd = -1;
state = disconnected;
}
int SicsConnection::sendCommand(const char *cmd) {
char *nl;
if (debug) {
printf("%s swallow before %s\n", debug, cmd);
}
swallow();
if (debug) {
printf("%s sendCommand %s\n", debug, cmd);
}
nl = strrchr((char *)cmd, '\n'); /* check if we have to add a final line break */
if (nl == NULL || nl[1] != '\0') {
command2send.sprintf("fulltransact %s\n", cmd);
} else {
command2send.sprintf("fulltransact %s", cmd);
}
if (state == disconnected) {
// printf("*** reconnect!\n");
connect_state = connect_start;
} else {
sendThis(command2send.latin1());
bufstate = buf_sent_transact;
command2send = "";
if (state == disconnected) {
return -1;
}
}
return 1;
}
int SicsConnection::getResponse() { // get BEGINNING of response
int iret;
QString line;
state = connected;
tmo = 10;
while (1) {
iret = getLine(line);
if (iret <= 0) {
if (iret == -2) {
if (printit()) printf("timeout on sea command\n");
}
//printf("error in getLine %d\n", iret);
if (debug) {
printf("%s error in getResponse {%s}\n", debug, rdbuffer.latin1() + rdpos);
}
return iret;
}
if (line.startsWith("TRANSACTIONSTART")) break;
if (debug) {
printf("%s getResponse handle %s\n", debug, line.latin1());
}
handle(line.latin1());
};
state = replying;
if (debug) {
printf("%s gotResponse\n", debug);
}
return 1;
}
int SicsConnection::command(const char *cmd) {
int iret;
int cnt, tries;
tries = 3;
do {
cnt = 5;
while (cnt > 0 && (connect_state != connect_done || bufstate > buf_got_finished)) {
handleBuffer(1);
cnt--;
}
iret = sendCommand(cmd);
handleBuffer(5);
iret = getResponse();
tries--;
} while (iret < 0 && tries > 0);
return iret;
}
int SicsConnection::handleMessages(int tmoArg) {
int iret;
QString line;
bool bs=false;
tmo = tmoArg;
if (bufstate <= buf_got_finished) {
bufstate = buf_sent_line;
bs = true;
}
iret = getLine(line);
tmo = 0;
while (iret >= 0) {
if (iret > 0) {
handle(line.latin1());
}
iret = getLine(line);
}
if (bs && bufstate == buf_sent_line) {
bufstate = buf_got_line;
}
return iret;
}
#ifdef TESTSC
#include <stdio.h>
int main(void) {
SicsConnection *sc;
char line[256];
char *lin;
int iret;
sc = SicsNewConnection("lnsl15", 13006);
if (sc == NULL) return -1;
while (1) {
printf("> ");
lin = fgets(line, sizeof line, stdin);
if (lin == NULL) return 1;
iret = SicsCommand(sc, line);
if (iret < 0) return 2;
while (1) {
iret = getLine(line);
if (iret == 0) break;
if (iret < 0) return 3;
if (iret > 0) {
printf("(%s)\n", line.latin1());
}
}
}
}
#endif

72
sicsconn.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef SICSCONN_H
#define SICSCONN_H
#include <stddef.h>
#include <qobject.h>
typedef enum { disconnected, connected, replying } ConnState;
class SicsConnection : public QObject {
Q_OBJECT
public:
SicsConnection(QObject *parent);
~SicsConnection();
void setHost(const char *hostport, const char *server);
void setUser(const char *userpass);
int command(const char *cmd);
/* send a command (and connect before, if necessary)
return values: 1 on success
-1 on error (no connection)
0 on empty response (should not happen)
*/
int sendCommand(const char *cmd);
// send, but do not wait
int getResponse();
// get beginning of response
int getLine(QString &line);
/* get answer from command
the return value is:
- the number of characters read (excluding line break, but at least 1)
- 0 when the response is at its end
- negative on error
*/
int handleMessages(int tmo);
/* handle pending messages */
int handleBuffer(int tmo);
void swallow();
char *debug;
ConnState state;
char *startServer = NULL;
signals:
void handle(const char *line, bool *done = NULL);
void reconnected(void);
void progress(int bytes);
public slots:
void reconnect(void);
void disconnect(void);
int handleBuffer(void);
private:
int sendThis(const char *cmd);
int fd;
char *hostport;
char *userpass;
char *server;
int tmo;
enum {buf_got_line, buf_got_finished, buf_sent_line, buf_got_start, buf_sent_transact} bufstate;
enum {connect_done, connect_start, connect_wait, connect_login, connect_waitlogin, connect_error} connect_state;
QString command2send;
QString bufline;
QString rdbuffer;
int rdpos;
int progressPos;
long tim;
};
#endif

267
tab.cpp Normal file
View File

@ -0,0 +1,267 @@
#include "tab.h"
#include <unistd.h>
#include <qapplication.h>
#include <stdio.h>
#include <qstring.h>
#include <qregexp.h>
#include <unistd.h>
#include <qtimer.h>
#include <qsizepolicy.h>
#include <qdialog.h>
#include <qtabbar.h>
#include <qpainter.h>
#include <qstyle.h>
#include <qlayout.h>
#include <assert.h>
enum {GRAPH, SETTINGS, DEVICE, COMMAND};
void Tab::checkSplit(SplitNo splitNo) {
assert(widgetno == splitNo);
widgetno++;
}
//Tab::Tab(const char* instr, QWidget *parent, long range, const char *warning)
// : QDialog(parent, "tab", false, Qt::WType_TopLevel | Qt::WStyle_Minimize)
Tab::Tab(const char* instr, QWidget *parent, long range, const char *warning)
: QMainWindow(parent, "tab", Qt::WType_TopLevel | Qt::WStyle_Minimize)
{
//QBoxLayout *vbox;
QApplication::style().polish(this);
actFocus = -1;
//vbox = new QVBoxLayout(this, 0, 0, "vbx");
split = new QSplitter(Qt::Horizontal, this);
setCentralWidget(split);
//vbox->addWidget(split);
widgetno = 0;
leftWidgetNo = graph_split;
rightWidgetNo = right_split;
graph = new Graph(instr, split, range);
if (graph->set == NULL) {
graph = NULL;
return;
}
checkSplit(graph_split);
graph->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, 1, 1));
connect(graph, SIGNAL(gotoSettings()), this, SLOT(gotoSettings()));
settings = new Settings(split);
settings->set = graph->set;
connect(settings, SIGNAL(leaveSettings()),
this, SLOT(leaveSettings()));
settings->hide();
checkSplit(settings_split);
rightSplit = new QSplitter(Qt::Vertical, split, "rightSplit");
rightSplit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, 1, 1));
checkSplit(right_split);
if (warning[0]) {
foreignwarn = new QVBox(rightSplit);
warnlabel = new QLabel(warning, foreignwarn);
showparbutton = new QPushButton("show parameters", foreignwarn);
QSize siz = foreignwarn->minimumSizeHint();
foreignwarn->setFixedHeight(siz.height());
warnlabel->setEraseColor(QColor(255,127,0));
}
device = new Device(rightSplit);
if (warning[0]) {
device->hide();
connect(showparbutton, SIGNAL(clicked()), this, SLOT(showPars()));
}
command = new Command(rightSplit, "Command", graph->set->uc);
connect(command->cmd, SIGNAL(returnPressed()), device, SLOT(update()));
connect(command, SIGNAL(activate()), device, SLOT(activate()));
device->init(command, graph->set);
QTimer *timer = new QTimer(this, "repeat");
connect(timer, SIGNAL(timeout()), this, SLOT(handler()));
timer->start(100);
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
exportXY = new Export(graph->set, split, instr);
exportXY->hide();
exportXY->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, 1, 1));
connect(exportXY, SIGNAL(finish()), this, SLOT(finishExport()));
connect(graph, SIGNAL(openExport()), this, SLOT(openExport()));
connect(graph->set, SIGNAL(updateCurveList()), exportXY, SLOT(updateCurveList()));
checkSplit(export_split);
report = new Report(split, graph->set->ec);
report->hide();
checkSplit(report_split);
connect(report, SIGNAL(leave()), this, SLOT(leaveReport()));
connect(report, SIGNAL(openMe()), this, SLOT(openReport()));
message = new QLabel(split);
message->hide();
for (int i = 0; i < 2 * 3; i++) {
oldSizes[i] = 0;
}
}
bool Tab::shown(QWidget *w) {
return w->isShown() && w->width() > 3 && w->height() > 3;
}
void Tab::showPars() {
QValueList<int> splitsizes;
int h;
showparbutton->hide();
QSize siz = warnlabel->minimumSizeHint();
foreignwarn->setFixedHeight(siz.height());
device->show();
splitsizes = rightSplit->sizes();
h = (splitsizes[1] + splitsizes[2]) / 2;
splitsizes[1] = h;
splitsizes[2] = h;
rightSplit->setSizes(splitsizes);
device->update();
}
bool Tab::splitChange(SplitNo splitNo) {
int lw = 0, rw = 0;
int i;
int tot;
float s;
sizes = split->sizes();
lw = sizes[leftWidgetNo];
rw = sizes[rightWidgetNo];
i = leftWidgetNo + 2 * (rightWidgetNo - right_split);
if (splitNo < right_split) {
if (splitNo == leftWidgetNo) return FALSE;
leftWidgetNo = splitNo;
} else {
if (splitNo == rightWidgetNo) return FALSE;
rightWidgetNo = splitNo;
}
tot = lw + rw;
if (rw > 1 && lw > 1) {
oldSizes[i] = lw / float(tot);
}
s = oldSizes[leftWidgetNo + 2 * (rightWidgetNo - right_split)];
if (s != 0) {
lw = s * tot + 0.5;
rw = tot - lw;
}
for (i = 0; i < n_split; i++) {
sizes[i] = 0;
}
sizes[leftWidgetNo] = lw;
sizes[rightWidgetNo] = rw;
return TRUE;
}
void Tab::gotoSettings() {
if (splitChange(settings_split)) {
graph->showIt(false);
settings->showIt(true);
split->setSizes(sizes);
}
}
void Tab::leaveSettings() {
if (splitChange(graph_split)) {
settings->showIt(false);
graph->showIt(true);
}
split->setSizes(sizes);
}
void Tab::openExport() {
if (splitChange(export_split)) {
rightSplit->hide();
exportXY->showMe();
split->setSizes(sizes);
}
}
void Tab::finishExport() {
if (splitChange(right_split)) {
exportXY->hide();
rightSplit->show();
split->setSizes(sizes);
}
}
void Tab::openReport() {
if (splitChange(report_split)) {
rightSplit->hide();
report->show();
split->setSizes(sizes);
}
}
void Tab::leaveReport() {
if (splitChange(right_split)) {
report->hide();
rightSplit->show();
split->setSizes(sizes);
}
}
void Tab::sleep(const char *text) {
graph->hide();
rightSplit->hide();
message->setText(text);
message->show();
}
void Tab::wake() {
graph->show();
rightSplit->show();
exportXY->hide();
report->hide();
message->hide();
graph->set->sc->disconnect();
graph->set->uc->disconnect();
graph->set->gc->disconnect();
graph->set->ec->disconnect();
graph->set->sc->reconnect();
/* uc is connected automatically with sc */
graph->set->gc->reconnect();
graph->set->ec->reconnect();
}
void Tab::initSize(int w, int h) {
QSize qs = QSize(w, h).expandedTo(split->minimumSizeHint());
resize(qs);
sizes = split->sizes();
sizes[0] = w/2;
sizes[2] = w/2;
split->setSizes(sizes);
}
void Tab::handler() {
command->handler();
if (shown(command) && command->cmd->hasFocus()) {
actFocus = COMMAND;
}
if (shown(graph) && graph->lineEditRange->hasFocus()) {
actFocus = GRAPH;
}
if (!shown(settings) && !shown(device)) {
if (actFocus == COMMAND) {
command->cmd->setFocus();
} else {
if (!graph->lineEditRange->hasFocus()) {
graph->lineEditRange->setFocus();
graph->lineEditRange->lineEdit()->selectAll();
}
}
}
}
void Tab::resizeEvent(QResizeEvent *e) {
//QDialog::resizeEvent(e);
QMainWindow::resizeEvent(e);
}

64
tab.h Normal file
View File

@ -0,0 +1,64 @@
#include <stddef.h>
#include <qprocess.h>
#include <qstring.h>
#include <qvbox.h>
#include <qbutton.h>
#include <qmainwindow.h>
#include "graph.h"
#include "settings.h"
#include "device.h"
#include "export.h"
#include "report.h"
//class Tab : public QDialog
class Tab : public QMainWindow
{
Q_OBJECT
public:
Tab(const char* instr, QWidget *parent, long range, const char *fromInstr);
void initSize(int w, int h);
void sleep(const char *text);
void wake();
Graph *graph;
Settings *settings;
Command *command;
Device *device;
Export *exportXY;
Report *report;
QSplitter *split;
QSplitter *rightSplit;
QLabel *message;
QVBox *foreignwarn;
QPushButton *showparbutton;
QLabel *warnlabel;
public slots:
void leaveSettings();
void gotoSettings();
void handler();
void openExport();
void finishExport();
void openReport();
void leaveReport();
void showPars();
signals:
void restart();
private:
int actFocus;
int watchSocket;
void resizeEvent(QResizeEvent *e);
bool shown(QWidget *w);
enum SplitNo {graph_split, settings_split, right_split, export_split, report_split, n_split};
void checkSplit(SplitNo splitNo);
bool splitChange(SplitNo splitNo);
int widgetno;
float oldSizes[2*3];
SplitNo leftWidgetNo, rightWidgetNo;
QValueList<int> sizes;
};

462
utils.cpp Normal file
View File

@ -0,0 +1,462 @@
#include "utils.h"
#include <qpixmap.h>
#include <stdlib.h>
#include <sys/time.h>
#include <assert.h>
void SetEraseColor(QWidget *widget, QWidget *from, bool inclBgr) {
const QPixmap *p;
p = from->erasePixmap();
if (p) {
widget->setErasePixmap(*p);
if (inclBgr) {
widget->setPaletteBackgroundPixmap(*p);
}
} else {
widget->setEraseColor(from->eraseColor());
if (inclBgr) {
widget->setPaletteBackgroundColor(from->eraseColor());
}
}
}
FlatButton::FlatButton(const QString &label, QWidget *parent, const char *name)
: QLabel(label, parent, name) {
x = -1;
}
void FlatButton::mousePressEvent(QMouseEvent *e) {
x = e->x();
y = e->y();
mousePressed();
}
void FlatButton::mouseReleaseEvent(QMouseEvent *e) {
if (x >= 0 && abs(e->x() - x) + abs(e->y() - y) < 5) {
clicked();
}
x = -1;
}
void ShrinkButton(QPushButton *b) {
int margin;
QString text(b->text());
b->setText("This is a long text");
margin = b->sizeHint().width() - b->fontMetrics().width(b->text());
b->setText(text);
b->setFixedWidth(b->fontMetrics().width(text) + margin);
}
double DoubleTime(void)
{
struct timeval now;
/* the resolution of this function is usec, if the machine supports this
and the mantissa of a double is 51 bits or more (31 for sec and 20 for milliseconds)
*/
gettimeofday(&now, NULL);
return now.tv_sec + now.tv_usec / 1e6;
}
static char *coltab[N_SEACOLORS*2] = {
"X c #FFFFFF", "white",
"X c #FF0000", "red",
"X c #00FF00", "lime", // was green
"X c #0000FF", "blue",
"X c #FF00FF", "magenta", // fuchsia
"X c #FFFF00", "yellow",
"X c #00FFFF", "cyan", // aqua
"X c #000000", "black",
"X c #FFA500", "orange",
"X c #006400", "dark_green",
"X c #9400D3", "dark_violet",
"X c #A52A2A", "brown",
"X c #87CEEB", "sky_blue",
"X c #808080", "gray",
"X c #FF69B4", "hot_pink",
"X c #FFFFE0", "light_yellow",
"X c #00FF7F", "spring_green",
"X c #000080", "navy",
"X c #1E90FF", "dodger_blue",
"X c #9ACD32", "yellow_green",
"X c #008B8B", "dark_cyan",
"X c #808000", "olive",
"X c #DEB887", "burly_wood",
"X c #7B68EE", "medium_slate_blue",
"X c #483D8B", "dark_slate_blue",
"X c #98FB98", "pale_green",
"X c #FF1493", "deep_pink",
"X c #FF6347", "tomato",
"X c #32CD32", "lime_green",
"X c #DDA0DD", "plum",
"X c #7FFF00", "chartreuse",
"X c #800080", "purple",
"X c #00CED1", "dark_turquoise",
"X c #8FBC8F", "dark_sea_green",
"X c #4682B4", "steel_blue",
"X c #800000", "maroon",
"X c #3CB371", "medium_sea_green",
"X c #FF4500", "orange_red",
"X c #BA55D3", "medium_orchid",
"X c #2F4F4F", "dark_slate_gray",
"X c #CD853F", "peru",
"X c #228B22", "forest_green",
"X c #48D1CC", "medium_turquoise",
"X c #DC143C", "crimson",
"X c #D3D3D3", "light_gray",
"X c #ADFF2F", "green_yellow",
"X c #7FFFD4", "aquamarine",
"X c #BC8F8F", "rosy_brown",
"X c #20B2AA", "light_sea_green",
"X c #C71585", "medium_violet_red",
"X c #F0E68C", "khaki",
"X c #6495ED", "cornflower_blue",
"X c #556B2F", "dark_olive_green",
"X c #CD5C5C", "indian_red",
"X c #2E8B57", "sea_green",
"X c #F08080", "light_coral",
"X c #8A2BE2", "blue_violet",
"X c #AFEEEE", "pale_turquoise",
"X c #4169E1", "royal_blue",
"X c #0000CD", "medium_blue",
"X c #B8860B", "dark_goldenrod",
"X c #00BFFF", "deep_sky_blue",
"X c #FFC0CB", "pink",
"X c #4B0082", "indigo",
"X c #A0522D", "sienna",
"X c #FFD700", "gold",
"X c #F4A460", "sandy_brown",
"X c #DAA520", "goldenrod",
"X c #DA70D6", "orchid",
"X c #E6E6FA", "lavender",
"X c #5F9EA0", "cadet_blue",
"X c #D2691E", "chocolate",
"X c #66CDAA", "medium_aquamarine",
"X c #6B8E23", "olive_drab",
"X c #A9A9A9", "dark_gray",
"X c #BDB76B", "dark_khaki",
"X c #696969", "dim_gray",
"X c #B0C4DE", "light_steel_blue",
"X c #191970", "midnight_blue",
"X c #FFE4C4", "bisque",
"X c #6A5ACD", "slate_blue",
"X c #EE82EE", "violet",
"X c #8B4513", "saddle_brown",
"X c #FF7F50", "coral",
"X c #008000", "mid_green",
"X c #DB7093", "pale_violet_red",
"X c #C0C0C0", "silver",
"X c #E0FFFF", "light_cyan",
"X c #9370DB", "medium_purple",
"X c #FF8C00", "dark_orange",
"X c #00FA9A", "medium_spring_green",
"X c #E9967A", "dark_salmon",
"X c #778899", "light_slate_gray",
"X c #9932CC", "dark_orchid",
"X c #EEE8AA", "pale_goldenrod",
"X c #F8F8FF", "ghost_white",
"X c #FFA07A", "light_salmon",
"X c #ADD8E6", "light_blue",
"X c #D8BFD8", "thistle",
"X c #FFE4E1", "misty_rose",
"X c #FFDEAD", "navajo_white",
"X c #40E0D0", "turquoise",
"X c #90EE90", "light_green",
"X c #B22222", "fire_brick",
"X c #008080", "teal",
"X c #F0FFF0", "honeydew",
"X c #FFFACD", "lemon_chiffon",
"X c #FFF5EE", "seashell",
"X c #F5F5DC", "beige",
"X c #DCDCDC", "gainsboro",
"X c #FA8072", "salmon",
"X c #8B008B", "dark_magenta",
"X c #FFB6C1", "light_pink",
"X c #708090", "slate_gray",
"X c #87CEFA", "light_sky_blue",
"X c #FFEFD5", "papaya_whip",
"X c #D2B48C", "tan",
"X c #FFFFF0", "ivory",
"X c #F0FFFF", "azure",
"X c #F5DEB3", "wheat",
"X c #00008B", "dark_blue",
"X c #FFDAB9", "peach_puff",
"X c #8B0000", "dark_red",
"X c #FAF0E6", "linen",
"X c #B0E0E6", "powder_blue",
"X c #FFE4B5", "moccasin",
"X c #F5F5F5", "white_smoke",
"X c #FFF8DC", "cornsilk",
"X c #FFFAFA", "snow",
"X c #FFF0F5", "lavender_blush",
"X c #FFEBCD", "blanched_almond",
"X c #F0F8FF", "alice_blue",
"X c #FAEBD7", "antique_white",
"X c #FDF5E6", "old_lace",
"X c #FAFAD2", "light_goldenrod_yellow",
"X c #F5FFFA", "mint_cream",
"X c #FFFAF0", "floral_white",
"X c #7CFC00", "lawn_green"
};
static long seaColors[N_SEACOLORS]={0};
static void getRGB(long i, long &r, long &g, long &b) {
long code;
char *k;
if (i >= 0x1000000 && i < 0x2000000) {
code = i - 0x1000000;
} else {
if (i < 0 || i >= N_SEACOLORS) {
r = 0;
g = 0;
b = 0;
return;
}
if (seaColors[i] == 0) {
k = strchr(coltab[i*2], '#');
if (k) {
seaColors[i] = strtol(k+1, NULL, 16);
}
}
code = seaColors[i];
}
b = code % 256; code = code / 256;
g = code % 256; code = code / 256;
r = code % 256;
}
QPen thisPen(long i, int w) {
long r,g,b;
getRGB(i, r, g, b);
if (w == 0) {
w = (3 * r + 5 * g + b) / 460; /* make pen larger for bright colors, 0 <= w <= 4 */
if (w < 2) {
w = 2;
}
}
return QPen(QColor(r,g,b), w, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin);
};
static const char *miniPix[] = {
"1 1 1 1",
" c None",
" "
};
// the following routine is for a color widget
const QPixmap *thisPixmap(long i, int w) {
char *penpix[3+11];
long l, j, k;
if (i < 0) {
return new QPixmap(miniPix);
}
if (i >= N_SEACOLORS) {
return NULL;
}
l = thisPen(i, w).width();
if (l > 11) l = 11;
penpix[0] = "20 11 2 1";
penpix[1] = coltab[i*2];
penpix[2] = " c None";
k = (11 - l) / 2;
for (j = 0; j < k; j++) {
penpix[j+3] = " ";
}
for (j = k; j < k + l; j++) {
penpix[j+3] = "XXXXXXXXXXXXXXXXXXXX";
}
for (j = k + l; j < 11; j++) {
penpix[j+3] = " ";
}
return new QPixmap((const char **)penpix);
};
long Convert2ColorIndex(const QString &color) {
QString s=color.stripWhiteSpace();
long rgb;
bool ok;
long r,g,b,rr,gg,bb,d;
long dist;
long index;
long i;
const char *ccol;
if (s[0] == '#') { // hexadecimal color
s.remove(0,1);
rgb = s.toLong(&ok, 16);
if (!ok) {
return -2;
}
if (s.length() == 3) { // short form: find closest index
bb = rgb % 16 * 17; rgb = rgb / 16;
gg = rgb % 16 * 17; rgb = rgb / 16;
rr = rgb % 16 * 17;
dist = 9999999;
index = -2;
for (i = 0; i < N_SEACOLORS; i++) {
getRGB(i, r, g, b);
r -= rr;
g -= gg;
b -= bb;
d = 5*r*r + 8*g*g + 5*b*b;
if (d < dist) {
dist = d;
index = i;
}
}
} else if (s.length() == 6) { // long form: keep rgb code
index = 0x1000000 + rgb;
} else {
return -2;
}
return index;
}
index = s.toLong(&ok);
if (ok) { // color index
return index;
}
i = s.find("grey");
if (i >= 0) {
s.replace(i+2, 1, "a");
}
ccol = s.latin1();
if (strcasecmp(ccol, "auto") == 0) {
return -1;
}
for (i = 0; i < N_SEACOLORS; i++) {
if (strcasecmp(coltab[i*2+1], ccol) == 0) {
return i;
}
}
if (strcasecmp(ccol, "green") == 0) {
return 2;
}
if (strcasecmp(ccol, "fuchsia") == 0) {
return 4;
}
if (strcasecmp(ccol, "aqua") == 0) {
return 6;
}
return -2;
}
bool Convert2ColorName(long i, QString &result) {
if (i >= 0x1000000 && i < 0x2000000) {
result.sprintf("#%6.6lX", i - 0x1000000);
return true;
}
if (i < 0 || i >= N_SEACOLORS) {
result = "auto";
return false;
} else {
result = coltab[i*2+1];
return true;
}
}
QString toRichText(QString &txt, bool *finished) {
QString result("");
QChar ch;
int i, l;
bool wasspace;
if (txt == "" || txt == " ") {
return "&nbsp;";
}
l = txt.length();
wasspace = true;
for (i = 0; i < l; i++) {
ch = txt[i];
if (ch == ' ') {
if (wasspace) {
result.append("&nbsp;");
} else {
result.append(' ');
wasspace = true;
}
} else {
wasspace = false;
if (ch == '&') {
result.append("&amp;");
} else if (ch == '<') {
result.append("&lt;");
} else {
result.append(ch);
}
}
}
return result;
}
MyTextEdit::MyTextEdit(QWidget * parent, const char *name) : QTextEdit(parent, name)
{
QFont monospace("Courier");
setTextFormat(Qt::RichText);
setWordWrap(QTextEdit::WidgetWidth);
setWrapPolicy(QTextEdit::Anywhere);
monospace.setStyleHint(QFont::TypeWriter);
setFont(monospace);
linebuffer = "";
buffered = false;
buffer = QStringList();
}
void MyTextEdit::appendHtml(QString text) {
linebuffer.append(text);
}
void MyTextEdit::setBuffered(bool arg) {
if (buffered) {
hide();
for (QStringList::Iterator it = buffer.begin(); it != buffer.end(); ++it ) {
append(*it);
}
show();
buffer.clear();
}
buffered = arg;
}
void MyTextEdit::appendText(QString text) {
QChar ch;
int i, l;
bool wasspace;
l = text.length();
wasspace = true;
for (i = 0; i < l; i++) {
ch = text[i];
if (ch == ' ') {
if (wasspace) {
linebuffer.append("&nbsp;");
} else {
linebuffer.append(' ');
wasspace = true;
}
} else {
wasspace = false;
if (ch == '\n') {
if (linebuffer == "" || linebuffer == " ") {
linebuffer="<br>";
}
if (buffered) {
buffer.append(linebuffer);
} else {
append(linebuffer);
}
linebuffer = "";
} else if (ch == '&') {
linebuffer.append("&amp;");
} else if (ch == '<') {
linebuffer.append("&lt;");
} else {
linebuffer.append(ch);
}
}
}
}

59
utils.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef UTILS_H
#define UTILS_H
#include <stddef.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtextedit.h>
#include <qevent.h>
#include <qpixmap.h>
#include <qpen.h>
#define N_SEACOLORS 138
class FlatButton: public QLabel {
Q_OBJECT
public:
FlatButton(const QString &label, QWidget *parent, const char *name=0);
signals:
void clicked();
void mousePressed();
protected:
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
private:
int x, y;
};
void ShrinkButton(QPushButton *b);
void SetEraseColor(QWidget *widget, QWidget *from, bool inclBgr = false);
double DoubleTime(void);
QPen thisPen(long i, int w = 0);
const QPixmap *thisPixmap(long i, int w = 0);
long Convert2ColorIndex(const QString &color);
bool Convert2ColorName(long i, QString &result);
// my own textedit, making paragraphs for newlines, but with single line spacing
class MyTextEdit: public QTextEdit {
Q_OBJECT
public:
MyTextEdit(QWidget * parent, const char *name=0);
void appendHtml(QString text);
void appendText(QString text);
void setBuffered(bool arg);
private:
bool buffered;
QString linebuffer;
QStringList buffer;
};
#endif