Commit ac08f85b authored by Lucio Zambon's avatar Lucio Zambon
Browse files

Initial import

parent bf2dae71
include(/usr/local/qtango/include/qtango6/qtango.pri)
SOURCES += src/laserpssokintck.cpp \
src/main.cpp
HEADERS += src/laserpssokintck.h
FORMS = src/laserpssokintck.ui
TARGET = ./bin/laserpssokintck-gui
/***************************************************************************
* Copyright (C) 2007 by *
* *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "laserpssokintck.h"
#include <qtango.h>
char tmBuffer[80];
QFont myFont("Helvetica", 14, QFont::Bold);
void timestamp()
{
struct tm *mytime;
time_t myTime_t;
myTime_t = time(NULL);
mytime = localtime(&myTime_t);
strftime(tmBuffer, 79, "%Y-%m-%d %H:%M:%S ", mytime);
return;
}
int laserpssokintck::myReadBoolArray(QString attrName, vector<bool> & attrVal)
{
try {
plc_server->read_attribute((const char *)attrName.toStdString().c_str()) >> attrVal;
return 1;
}
catch (const Tango::DevFailed &e) {
timestamp();
cout << tmBuffer << "exception reading attribute: " << attrName.toStdString() << endl;
}
catch (...) {
timestamp();
cout << tmBuffer << "default exception reading attribute: " << attrName.toStdString() << endl;
}
return 0;
}
void laserpssokintck::refresh() {
vector<bool> stat;
for (unsigned i=0; i < attributes.size(); i++) {
if (myReadBoolArray(attributes[i], stat)) {
for (unsigned j=0; j < states.size(); j++) {
if (states[j].attr == attributes[i]) {
states[j].value = (int) (states[j].bit>=0? stat[states[j].bit]: !stat[-1 - states[j].bit]);
mySetTextColor(states[j].label, (states[j].value? "OK": "NOK"), "#000000", (states[j].value? "#00C800": "#DC0000"));
}
}
}
}
for (unsigned k=0; k < derivedCond.size(); k++) {
derivedCond[k].value = derivedCond[k].isAnd;
for (unsigned a=0; a < derivedCond[k].attr.size(); a++) {
derivedCond[k].value = derivedCond[k].isAnd? derivedCond[k].value && states[derivedCond[k].attr[a]].value: derivedCond[k].value || states[derivedCond[k].attr[a]].value;
}
for (unsigned c=0; c < derivedCond[k].cond.size(); c++) {
derivedCond[k].value = derivedCond[k].isAnd? derivedCond[k].value && derivedCond[derivedCond[k].cond[c]].value: derivedCond[k].value || derivedCond[derivedCond[k].cond[c]].value;
}
mySetTextColor(derivedCond[k].label, (derivedCond[k].value? "OK": "NOK"), "#000000", (derivedCond[k].value? "#00C800": "#DC0000"));
}
}
bool readJsonFile(std::string file_path, QVariantList& result) {
QFile file_obj(QString::fromStdString(file_path));
if (!file_obj.open(QIODevice::ReadOnly)) {
std::cout << "Failed to open " << file_path << std::endl;
exit(0);
}
QTextStream file_text(&file_obj);
QString json_string;
json_string = file_text.readAll();
file_obj.close();
QByteArray json_bytes = json_string.toLocal8Bit();
QJsonParseError error;
auto json_doc = QJsonDocument::fromJson(json_bytes, &error);
if (json_doc.isNull()) {
std::cout << "Failed to create JSON doc: " << error.errorString().toStdString() << std::endl;
return false;
}
if (json_doc.isArray()) {
QJsonArray json_obj = json_doc.array();
result = json_obj.toVariantList();
}
else {
std::cout << "JSON is not an array." << std::endl;
return false;
}
return true;
}
int laserpssokintck::mySetTextColor(QLabel *widget, const char *text, const char *color, const char *bgcolor) {
QPalette button;
widget->setText(text);
button.setColor(QPalette::Window, QColor(bgcolor));
button.setColor(QPalette::WindowText, QColor(color));
widget->setPalette(button);
return 0;
}
void laserpssokintck::handleButton(int n) {
cout << "button: " << n << ", cmd: " << infoButton[n].toStdString() << endl;
if (myprocess->state() == QProcess::Running) {
myprocess->kill();
myprocess->waitForFinished(3000);
}
myprocess->start(infoButton[n]);
}
int laserpssokintck::displayRow(QMap<QString, QVariant> map, int x) {
// https://stackoverflow.com/questions/21150890/qt-5-assign-slot-with-parameters-to-a-qpushbutton
int pbOffset = 0;
if (map["link"].toString() != "") {
pbOffset = 30;
QPushButton *pb = new QPushButton(this);
pb->setGeometry(5, y+5, 20, 21);
pb->setIconSize(QSize(20, 21));
pb->setIcon(QPixmap(imgpath+"/info.png"));
connect(pb, SIGNAL(clicked()), &mapper, SLOT(map()));
mapper.setMapping(pb, infoButton.size());
infoButton.push_back(map["link"].toString());
}
QString str = (map["operation"].toString() == "NOT"? "NOT ": "")+map["title"].toString();
QLabel* t = new QLabel(str, this);
t->setGeometry(5+pbOffset, y, x-10-pbOffset, yStep);
t->setToolTip(map["description"].toString());
if (description) {
QTextEdit* d = new QTextEdit("", this);
d->setGeometry(this->x, y, descriptionWidth, yStep);
d->setReadOnly(true);
d->setFontPointSize(10);
d->setPlainText(map["description"].toString());
}
QLabel* s = new QLabel("?", this);
mySetTextColor(s, "???", "#000000", "#888888");
s->setAutoFillBackground(true);
s->setAlignment(Qt::AlignCenter);
s->setGeometry(x+10, y+4, 50, yStep-8);
s->setToolTip("DBX "+map["data-db"].toString()+" - "+map["attr"].toString()+"["+map["attr-bit"].toString()+"]");
int bit = (int) map["attr-bit"].toDouble();
if (map["operation"].toString() == "NOT") bit = -1 - bit;
states.push_back({s, map["attr"].toString(), bit, -1});
appendAttr(map["attr"].toString());
return states.size()-1;
}
void laserpssokintck::appendAttr(QString attr) {
for (unsigned i=0; i < attributes.size(); i++) {
if (attributes[i] == attr) return;
}
attributes.push_back(attr);
}
int laserpssokintck::parseBlock(QMap<QString, QVariant> map, int x, int &cond) {
if (map["operands"].canConvert<QVariantList>()) {
QLabel* l = new QLabel("?", this);
l->setGeometry(x+xStep, 0, 70, yStep);
mySetTextColor(l, (map["operation"].toString()=="AND"? "AND":"OR"), "#0000FF", "#444444");
l->setAlignment(Qt::AlignCenter);
QVariantList list = map["operands"].toList();
int dy = 0;
int c;
dercond dc;
dc.isAnd = map["operation"].toString()=="AND";
for (int i=0; i < list.count(); i++) {
dy += parseBlock(list[i].toMap(), x+xStep, c);
if (c>=0) dc.attr.push_back(c);
else dc.cond.push_back(-1 - c);
}
QFrame* f = new QFrame(this);
f->setFrameStyle(QFrame::Box);
f->setGeometry(0, by, x+1, y-by+1);
f->lower();
if (x != this->x) {
QFrame* s = new QFrame(this);
s->setFrameStyle(QFrame::Box);
s->setGeometry(x, yStep, 71, y-yStep+1);
QLabel* cl = new QLabel("?", this);
mySetTextColor(cl, "???", "#000000", "#888888");
cl->setAutoFillBackground(true);
cl->setAlignment(Qt::AlignCenter);
cl->setGeometry(x+10, (y)/2, 50, yStep-8);
dc.label = cl;
derivedCond.push_back(dc);
cond = 0 - derivedCond.size();
}
else {
connect(&mapper, SIGNAL(mapped(int)), this, SLOT(handleButton(int)));
}
by = y;
return dy;
}
else {
cond = displayRow(map, x);
y += yStep;
return yStep;
}
}
void laserpssokintck::preDisplayRow(QMap<QString, QVariant> map, int x) {
int pbOffset = 0;
if (map["link"].toString() != "") pbOffset = 30;
QString str = (map["operation"].toString() == "NOT"? "NOT ": "")+map["title"].toString();
QFontMetrics fm(myFont);
int width=fm.horizontalAdvance(str);
if (xOffset > x-10-pbOffset-width) xOffset = x-10-pbOffset-width;
}
void laserpssokintck::preParseBlock(QMap<QString, QVariant> map, int x) {
QVariantList list = map["operands"].toList();
if (map["operands"].canConvert<QVariantList>()) {
for (int i=0; i < list.count(); i++) {
preParseBlock(list[i].toMap(), x+xStep);
}
}
else {
preDisplayRow(map, x);
}
}
laserpssokintck::laserpssokintck(QWidget *parent) : QWidget(parent) {
if (qApp->arguments().count() < 2 || qApp->arguments()[1]=="-h" || qApp->arguments()[1]=="--help") {
cout << "Usage: " << qApp->arguments()[0].toStdString() << " configuration file (JSON)" << endl;
exit(0);
}
description = false;
descriptionWidth = 0;
if (qApp->arguments().count() > 2 && qApp->arguments()[2]=="description") {
description = true;
descriptionWidth = 500;
}
x=620; y=30; xStep=-70; yStep=30, by=30, xOffset = 10000;
QSettings settings("fermi", "acs");
// load (or set) path for images
if (settings.contains("imgpath")) {
imgpath = settings.value("imgpath").toString();
}
else {
settings.setValue("imgpath", "/runtime/fermi/share/images/acs");
}
if (!imgpath.endsWith("/")) {
imgpath = imgpath + "/";
}
try {
plc_server = new Tango::DeviceProxy("srv-tango-srf-01.fcs.elettra.trieste.it:20000/slu/interlock/laser_pss");
}
catch (const Tango::DevFailed &e) {
timestamp();
cout << tmBuffer << "Fatal Error: Access Control Device Server not responding, the application will be terminated immediately" << endl;
exit(1);
}
catch (...) {
timestamp();
cout << tmBuffer << "Fatal Error: Access Control Device Server not responding, the application will be terminated immediately" << endl;
exit(1);
}
ui.setupUi(this);
myprocess = new QProcess(this);
QApplication::setFont(myFont);
QVariantList list0;
if (readJsonFile(qApp->arguments()[1].toStdString() , list0)) {
QMap<QString, QVariant> map0 = list0[0].toMap();
int c;
preParseBlock(list0[1].toMap(), x);
preDisplayRow(map0, x+xStep);
x -= xOffset;
parseBlock(list0[1].toMap(), x, c);
this->setGeometry(0, 0, x+descriptionWidth, y+yStep);
this->setMaximumSize(x+descriptionWidth, y+yStep);
this->setMinimumSize(x+descriptionWidth, y+yStep);
this->setWindowTitle(map0["title"].toString());
QFrame* f = new QFrame(this);
f->setFrameStyle(QFrame::Box);
f->setGeometry(0, y, x, yStep+1);
f->setStyleSheet("background-color: rgb(200,255,200)");
displayRow(map0, x+xStep);
}
else {
cout << "ERROR: cannot read JSON file" << endl;
exit(0);
}
refresh();
try {
timer = new QTimer(this);
timer->setInterval(1000);
timer->setSingleShot(false);
connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
timer->start();
}
catch (const Tango::DevFailed &e) {
timestamp();
cout << tmBuffer << "cannot connect UI" << endl;
}
catch (...) {int
timestamp();
cout << tmBuffer << "default exception, cannot setup UI" << endl;
}
}
laserpssokintck::~laserpssokintck() {
exit(0);
}
/***************************************************************************
* Copyright (C) 2007 by *
* *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef laserpssokintck_H
#define laserpssokintck_H
#include "ui_laserpssokintck.h"
#include <tango.h>
#include <QProcess>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QSignalMapper>
#include <QSettings>
class laserpssokintck: public QWidget
{
Q_OBJECT
public:
laserpssokintck(QWidget * =NULL);
~laserpssokintck();
public slots:
void refresh();
void handleButton(int);
private:
int xOffset;
QProcess *myprocess;
int x, y, by, xStep, yStep;
Ui::laserpssokintck ui;
QString imgpath;
int parseBlock(QMap<QString, QVariant>, int, int &);
int displayRow(QMap<QString, QVariant>, int);
void preParseBlock(QMap<QString, QVariant>, int);
void preDisplayRow(QMap<QString, QVariant>, int);
struct state {
QLabel *label;
QString attr;
int bit;
int value;
};
vector <state> states;
vector <QString> attributes;
struct dercond {
QLabel *label;
bool isAnd;
vector<int> attr;
vector<int> cond;
int value;
};
vector <dercond> derivedCond;
vector <QString> infoButton;
QSignalMapper mapper;
void appendAttr(QString attr);
int mySetTextColor(QLabel *widget, const char *text, const char *color, const char *bgcolor);
int myReadBoolArray(QString, vector<bool> &);
Tango::DeviceProxy *plc_server;
QTimer *timer;
bool description;
int descriptionWidth;
};
#endif
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>laserpssokintck</class>
<widget class="QWidget" name="laserpssokintck"/>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
/***************************************************************************
* Copyright (C) 2007 by *
* *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <TApplication>
#include "laserpssokintck.h"
#include <X11/Xlib.h>
#include <QX11Info>
//# define CVSVERSION "$Name: $"
int main( int argc, char ** argv ) {
TApplication a( argc, argv );
// a.setApplicationVersion(CVSVERSION);
laserpssokintck mw;
mw.show();
/* register to window manager */
Display *disp = QX11Info::display();
Window root_win = (Window) mw.winId();
XSetCommand(disp, root_win, argv, argc);
return a.exec();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment