Files
seaclient/main.cpp
Markus Zolliker bc33026b2c start sea server even remotely over ssh
this works on neutron instruments (account equal host)
and on linse-c
2025-06-10 16:39:49 +02:00

512 lines
14 KiB
C++

#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"
#include "utils.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];
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();
}