diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4003a792221ca1b5b550f98f18a9361c87374bd8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +.pydevproject +.project +.cproject +.settings +Makefile +moc +obj +bin +objects +core* +*~ +*.pyc +*.so +*.so* +.pylintrc +.metadata +.idea +.cvsignore +.nse_depinfo +software +oldsrc +ui_* +qrc*.cpp +.qmake.stash +CVS diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000000000000000000000000000000000000..38f70113d109df3c1aad4e69324195ba117c810b --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,26 @@ +release_10: porting to QT5 (from phonon to Qt Multimedia) + +release_09: Fixed sorting problem on the tree widgets. Added missing modulators to the combo box. + +release_08: Fixed scroll issue on updates in TTreeWidget + Ported to QTango5 + +release_07: added Test Sound button + +release_06: Ticket 975: General Interlock: sounds and important/blocking alarm + Added sound support. + Tabs with recent alarms are evidentiated by an alarm bell icon. + Recent alarms are bold. + + +release_04: Ticket 774 ferminterlock: manca history per "PS and Vacuum" + Added search box on each tab. Text based search. + Queries have been modified. + See http://acswww.elettra.trieste.it/bugzilla/show_bug.cgi?id=774 + + +release_05: ticket 983: +srv-tango-srf/interlock/plc_mod_ll --> f/interlock/plc_mod_ll +srv-tango-srf/interlock/plc_int_ll.01 --> f/interlock/plc_int_ll.01 +srv-tango-srf/interlock/plc_int_ll.02 --> f/interlock/plc_int_l +database: su srv-log-srf --> srv-db-srf diff --git a/README b/README new file mode 100644 index 0000000000000000000000000000000000000000..1eb9ab1376f970f9dd451af773deb0fe8aae972b --- /dev/null +++ b/README @@ -0,0 +1,11 @@ +ferminterlock + +USAGE: + +ferminterlock f/interlock/plc_mod_ll f/interlock/plc_int_ll.01 f/interlock/plc_int_ll.02 srv-padres-srf:20000/srv-padres-srf/interlock/plc_int_ll.03 --sound-file-name /runtime/share/sounds/generalintlkpanel_beep.ogg + +Contacts: + +giacomo.strangolino@elettra.... +graziano.scalamera@elettra... + diff --git a/README.md b/README.md index 7a48adc6e30a5ee66d57bbfe852bae3e4c41621d..e1032499add118143f73a8af7c047ae97c0689c9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ # ferminterlock pannello fermi interlock + + +# usage + +ferminterlock f/interlock/plc_mod_ll f/interlock/plc_int_ll.01 f/interlock/plc_int_ll.02 srv-padres-srf:20000/srv-padres-srf/interlock/plc_int_ll.03 --sound-file-name /runtime/share/sounds/generalintlkpanel_beep.ogg + +# contatcts + +giacomo.strangolino@elettra.... +graziano.scalamera@elettra... + diff --git a/general.pro b/general.pro new file mode 100644 index 0000000000000000000000000000000000000000..c33b9c8c32c1dfed6c4eae733ec90c7824fb9627 --- /dev/null +++ b/general.pro @@ -0,0 +1,51 @@ +include(/usr/local/qtango/include/qtango6/qtango.pri) + +CONFIG += debug +QT += sql +QT += multimedia + +DEFINES -= QT_NO_DEBUG_OUTPUT + +RESOURCES += general.qrc + +# DEFINES -= QT_NO_DEBUG_OUTPUT + + +SOURCES += src/tlabelitem.cpp \ + src/ttreewidget.cpp \ + src/ttablewidget.cpp \ + src/interlock.cpp \ + src/main.cpp \ + src/queryconfiguration.cpp \ + src/mysqlmodel.cpp \ + src/ttreeview.cpp \ + src/Sound.cpp \ + src/tabwidget.cpp \ + src/treeitem.cpp + +HEADERS += src/tlabelitem.h \ + src/ttreewidget.h \ + src/ttablewidget.h \ + src/interlock.h \ + src/queryconfiguration.h \ + src/mysqlmodel.h \ + src/ttreeview.h \ + src/Sound.h \ + src/tabwidget.h \ + src/treeitem.h + + +FORMS = src/interlock.ui src/queryconfiguration.ui + +TARGET = bin/ferminterlock-gui + +sounds.files = sounds/generalintlkpanel_beep.ogg +sounds.path = $${INSTALL_ROOT}/share/sounds + +INSTALLS += sounds + +OTHER_FILES += \ + properties.txt + + +QMAKE_POST_LINK = $(STRIP) $(TARGET) diff --git a/general.qrc b/general.qrc new file mode 100644 index 0000000000000000000000000000000000000000..af52b0ef565fbf1114dab091726c5a9b9b0b5214 --- /dev/null +++ b/general.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> + <qresource> + <file>icons/alarm.png</file> + </qresource> +</RCC> + diff --git a/icons/alarm.png b/icons/alarm.png new file mode 100644 index 0000000000000000000000000000000000000000..38859f8adc3df521c9a345fc859b048b0b18530f Binary files /dev/null and b/icons/alarm.png differ diff --git a/properties.txt b/properties.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/sounds/generalintlkpanel_bark.ogg b/sounds/generalintlkpanel_bark.ogg new file mode 100644 index 0000000000000000000000000000000000000000..045d609cd69238da7e360a4667a889a02d8c7fe1 Binary files /dev/null and b/sounds/generalintlkpanel_bark.ogg differ diff --git a/sounds/generalintlkpanel_beep.ogg b/sounds/generalintlkpanel_beep.ogg new file mode 100644 index 0000000000000000000000000000000000000000..20de4c76c7cfd5f8e0aecbcc691f71a43f3b3c74 Binary files /dev/null and b/sounds/generalintlkpanel_beep.ogg differ diff --git a/src/Sound.cpp b/src/Sound.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b81201a6b53ad2d2798c27732433d187f53378c --- /dev/null +++ b/src/Sound.cpp @@ -0,0 +1,67 @@ +#include "Sound.h" +#include <QString> +#include <QSound> +#include <QtDebug> +#include <macros.h> + +Sound::Sound(const QString& sound_file) +{ + m_init(sound_file); +} + +Sound::Sound(QObject *parent, const QString &sound_file) : QObject(parent) +{ + m_init(sound_file); +} + +void Sound::m_init(const QString& sound_file) +{ + mSoundEffect.setSource(QUrl::fromLocalFile(sound_file)); + set_loop_delay(500); + m_loop_timer.setSingleShot(true); + m_loop_enabled = false; + connect(&mSoundEffect, SIGNAL(playingChanged()), this, SLOT(playingChanged())); + connect(&m_loop_timer, SIGNAL(timeout()), &mSoundEffect, SLOT(play())); +} + +void Sound::play() +{ + if (m_loop_enabled) return; + mSoundEffect.play(); +} + +void Sound::loop() +{ + if(!m_loop_enabled){ + m_loop_enabled = true; + mSoundEffect.play(); + } +} + +void Sound::playingChanged() +{ + if(m_loop_enabled && !mSoundEffect.isPlaying()) + m_loop_timer.start(); +} + +void Sound::stop() +{ + m_loop_enabled = false; + m_loop_timer.stop(); + mSoundEffect.stop(); +} + +void Sound::set_loop_delay(int delay) +{ + m_loop_timer.setInterval(delay); +} + +int Sound::get_loop_delay() +{ + return m_loop_timer.interval(); +} + +void Sound::timer_timeout() { + mSoundEffect.play(); +} + diff --git a/src/Sound.h b/src/Sound.h new file mode 100644 index 0000000000000000000000000000000000000000..f143721422ceee1ed6c718c7688b073ae8602bf5 --- /dev/null +++ b/src/Sound.h @@ -0,0 +1,39 @@ +#ifndef SOUND_H +#define SOUND_H + +#include <QString> +#include <QObject> +#include <QTimer> +#include <QSoundEffect> +#include <QFile> + +class Sound:public QObject +{ + Q_OBJECT +public: + Sound(const QString& sound_file); + Sound(QObject *parent, const QString& sound_file); + void set_loop_delay(int); + int get_loop_delay(); +public slots: + void play(); + void stop(); + void loop(); +private slots: + void playingChanged(); + void timer_timeout(); +private: + bool m_loop_enabled; + QTimer m_loop_timer; + QSoundEffect mSoundEffect; + + void m_init(const QString &sound_file); +}; + + + + +#endif + + + diff --git a/src/interlock.cpp b/src/interlock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff2a443cb9a1cb733741f374592682bc3ba3815e --- /dev/null +++ b/src/interlock.cpp @@ -0,0 +1,393 @@ +/*************************************************************************** + * Copyright (C) 2007 by Vincenzo Forchi`,,, * + * vincenzo.forchi@elettra.trieste.it * + * * + * 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 "interlock.h" +#include "Sound.h" +#include <qtango.h> +#include <device_factory.h> +#include <QtSql> +#include <QScrollBar> +#include "mysqlmodel.h" +#include <TLog> +#include <QMessageBox> +#include <elettracolors.h> + +Interlock::Interlock(QWidget *parent) : QWidget(parent) +{ + QStringList args = qApp->arguments(); + if(args.size() < 5) + { + QMessageBox::information(this, "Usage", + QString("%1 f/interlock/plc_mod_ll f/interlock/plc_int_ll.01" + "\nf/interlock/plc_int_ll.02 srv-padres-srf:20000/srv-tango-srf/interlock/plc_int_ll.03"). + arg(args.first())); + exit(EXIT_FAILURE); + } + + if(args.contains("--sound-file-name") && args.size() > args.indexOf("--sound-file-name")) + { + Sound *sound = new Sound(this, args.at(args.indexOf("--sound-file-name") + 1)); + } + else + { + printf("\e[1;35m - if you want to enable sounds for alarms, provide as second argument the name of the sound file\e[0m\n"); + ui.pbTestSound->setHidden(true); + ui.line->setHidden(true); + } + + modDeviceName = QApplication::arguments()[1]; + vacPsDeviceName = QApplication::arguments()[2]; + + Config::instance()->setOverrideValuesAttributePropertyName("labels"); + + ui.setupUi(this); + setupDb(); + configureUi(); + createConnections(); + QTimer::singleShot(50, this, SLOT(connectTango())); +} + +void Interlock::setupDb() +{ + /* connect to db */ + db = QSqlDatabase::addDatabase("QMYSQL"); + db.setHostName("srv-db-srf-02"); + db.setDatabaseName("intlkfermi"); + db.setUserName("ifermi"); + db.setPassword("ferm"); + if (!db.open()) + QMessageBox::critical(0, "Error", "Can't establish connection with db intlkboost on host log"); + + queryType = QueryConfiguration::LastDay; + modulatorModel = new MySqlModel(); + psvacModel = new MySqlModel(); + ui.treeLogs->setModel(modulatorModel); + ui.treeLogsPSVAC->setModel(psvacModel); + + dbTimer = new QTimer(this); + connect(dbTimer, SIGNAL(timeout()), this, SLOT(readFromDb())); +} + +void Interlock::createConnections() +{ + connect(ui.treeAlarms, SIGNAL(acknowledgeSelected()), this, SLOT(acknowledgeSelected())); + connect(ui.pushRefresh, SIGNAL(clicked()), this, SLOT(readFromDb())); + connect(ui.pushRefreshPSVacuum, SIGNAL(clicked()), this, SLOT(readFromDb())); + connect(ui.pushQueryConfiguration, SIGNAL(clicked()), this, SLOT(queryConfiguration())); + connect(ui.pushQueryConfigurationPSVAC, SIGNAL(clicked()), this, SLOT(queryConfiguration())); + connect(ui.comboAck, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAckTarget(int))); + connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + + /* 1 tab: mod filter */ + connect(ui.pbClearModFilter, SIGNAL(clicked()), ui.leFilterMod, SLOT(clear())); + connect(ui.leFilterMod, SIGNAL(textChanged(QString)), ui.treeAlarms, SLOT(filter(QString))); + + /* 2 tab: mod history */ + connect(ui.pbClearModHist, SIGNAL(clicked()), ui.leFilterModHist, SLOT(clear())); + connect(ui.leFilterModHist, SIGNAL(textChanged(QString)), ui.treeLogs, SLOT(filter(QString))); + + /* 3 tab: ps vac linac */ + connect(ui.pbClearFilterVacLinac, SIGNAL(clicked()), ui.leFilterPsVacLinac, SLOT(clear())); + connect(ui.leFilterPsVacLinac, SIGNAL(textChanged(QString)), ui.treeAlarmsVPS, SLOT(filter(QString))); + + /* 4 tab: ps vacuum uh */ + connect(ui.pbClearFilterPSVacUH, SIGNAL(clicked()), ui.leFilterPsVacUH, SLOT(clear())); + connect(ui.leFilterPsVacUH, SIGNAL(textChanged(QString)), ui.treeAlarmsVUH, SLOT(filter(QString))); + + /* 5 tab ps vacuum padres */ + connect(ui.pbClearFilterPsVacPadres, SIGNAL(clicked()), ui.leFilterPsVacPadres, SLOT(clear())); + connect(ui.leFilterPsVacPadres, SIGNAL(textChanged(QString)), ui.treeAlarmsPadres, SLOT(filter(QString))); + + /* 6. tab ps and vacuum history */ + connect(ui.pbClearFilterPsVacHistory, SIGNAL(clicked()), ui.leFilterPsVacHistory, SLOT(clear())); + connect(ui.leFilterPsVacHistory, SIGNAL(textChanged(QString)), ui.treeLogsPSVAC, SLOT(filter(QString))); + + /* sound */ + Sound *sound = findChild<Sound *>(); + if(sound) + { + connect(ui.treeAlarms, SIGNAL(newAlarmArrived()), sound, SLOT(play())); + connect(ui.treeAlarmsPadres, SIGNAL(newAlarmArrived()), sound, SLOT(play())); + connect(ui.treeAlarmsVPS, SIGNAL(newAlarmArrived()), sound, SLOT(play())); + connect(ui.treeAlarmsVUH, SIGNAL(newAlarmArrived()), sound, SLOT(play())); + connect(ui.pbTestSound, SIGNAL(clicked()), sound, SLOT(play())); + } + connect(ui.treeAlarms, SIGNAL(newAlarmArrived()), this, SLOT(newAlarmArrived())); + connect(ui.treeAlarmsPadres, SIGNAL(newAlarmArrived()), this, SLOT(newAlarmArrived())); + connect(ui.treeAlarmsVPS, SIGNAL(newAlarmArrived()), this, SLOT(newAlarmArrived())); + connect(ui.treeAlarmsVUH, SIGNAL(newAlarmArrived()), this, SLOT(newAlarmArrived())); +} + +void Interlock::configureUi() +{ + QStringList headers; + headers << "Date Time" << "Name" << "Description"; + foreach(TTreeWidget *ttw, findChildren<TTreeWidget *>(QRegExp("treeAlarms.*"))) + ttw->setHeaderLabels(headers); + QStringList mods; + for(int i = 0; i <= 15; i++) + mods << QString("mod%1").arg(i, 2, 10, QChar('0')); + mods.push_front("General"); + ui.comboAck->insertItems(0, mods); +} + +Interlock::~Interlock() +{ +} + +void Interlock::connectTango() +{ + /* mod */ + ui.treeAlarms->setPeriod(1000); + ui.treeAlarms->setSource(modDeviceName + "/Db_alarm"); + ui.tAck->setTargets(modDeviceName + QString("->Acknowledge(%1)").arg(ui.comboAck->itemData(0).toInt())); + /* vacuum and power supply */ + ui.treeAlarmsVPS->setPeriod(1000); + ui.treeAlarmsVPS->setSource(vacPsDeviceName + "/Db_alarm"); + /* Ps and vacuum UH */ + ui.treeAlarmsVUH->setSource("$3/Db_alarm"); + /* padres */ + ui.treeAlarmsPadres->setSource("$4/Db_alarm"); +} + +void Interlock::changeAckTarget(int idx) +{ + /* item list (idx == 0) starts with "general". + * Then modulators follow, from mod00 (idx == 1) to mod12. + * So the correct argin is obtained subtracting 1 to the combo box index. + */ + int argin = idx - 1; + ui.tAck->setTargets(modDeviceName + QString("->Acknowledge(%1)").arg(argin)); +} + +void Interlock::newAlarmArrived() +{ + /* get sender */ + QString oName = sender()->objectName(); + int tabIndex = -1; + if(oName == "treeAlarms") + tabIndex = 0; + else if(oName == "treeAlarmsVPS") + tabIndex = 2; + else if(oName == "treeAlarmsVUH") + tabIndex = 3; + else if(oName == "treeAlarmsPadres") + tabIndex = 4; + + ui.tabWidget->setTabIcon(tabIndex, QIcon(":icons/alarm.png")); +} + +/* icon removal is made inside custom TabBar. + * See tabwidget.h + */ +void Interlock::tabChanged(int idx) +{ + if(idx == ModHistory || idx == PsVacHistory) + { + dbTimer->start(10000); + this->readFromDb(); + } + else + { + dbTimer->stop(); + } +} + +void Interlock::acknowledgeSelected() +{ + /// ////////////////// + printf("\e[1;33m - da implementare - \e[0m\n"); + return; + /// ////////////////// + + QVector<double> v_attr(ui.treeAlarms->dataSize(), 0); + // QVector<long> v_comm(ui.treeAlarms->dataSize(), 0); + foreach (QTreeWidgetItem *it, ui.treeAlarms->selectedItems()) + { + //qDebug() << it->text(3); + v_attr[it->text(3).toInt()] = 1; + // v_comm << it->text(3).toLong(); + } + try { + DeviceAttribute attr; + attr.set_name("Db_alarm"); + vector<double> dati = v_attr.toStdVector(); + attr << dati; + Tango::DeviceProxy *dpr = DeviceFactory::instance()->getDeviceProxy(modDeviceName); + if(dpr) + dpr->write_attribute(attr); + } + catch (DevFailed &e) + { + TLog log(e); + time_t now = time(NULL); + QPair<time_t, DevErrorList> err(now, e.errors); + TUtil::instance()->addLog(log.toTimeErrlistPair(), log.formatMessage()); + QMessageBox::critical(0, "Error", log.formatMessage()); + } + ui.treeAlarms->clearSelection(); +} + +void Interlock::queryConfiguration() +{ + QueryConfiguration win; + win.setQueryType(queryType); + if (queryType == QueryConfiguration::Interval) + { + win.setStartDateTime(begin); + win.setStopDateTime(end); + } + + if (win.exec() == QDialog::Accepted) + { + queryType = win.queryType(); + begin = win.startDateTime(); + end = win.stopDateTime(); + readFromDb(); + } +} + +void Interlock::readFromDb() +{ + MySqlModel *model = NULL; + QString dbnam; + bool modulator = true; + if(ui.tabWidget->currentIndex() == ModHistory) + { + model = modulatorModel; + dbnam = "real_time_"; + } + else if(ui.tabWidget->currentIndex() == PsVacHistory) + { + modulator = false; + model = psvacModel; + dbnam = "vac_mag_"; + } + else + return; + + if (!db.isOpen()) + { + if (!db.open()) + { + QMessageBox::critical(0, "Error", "Can't establish connection with db FastInterlock on host log"); + return; + } + } + QDateTime adesso = QDateTime::currentDateTime(); + int year = adesso.date().year(); + + QString query, endquery; + if(modulator) + { + query = "SELECT FROM_UNIXTIME(" + dbnam + "%1.timestamp) AS 'Date Time', mod_description.name AS 'Name', " + + dbnam + "%1.event AS 'Event', " + "mod_description.comment AS Description, mod_description.modulator AS 'Modulator' FROM " + + dbnam + "%1 left join mod_description on (" + dbnam + + "%1.id_mod_description=mod_description.id_mod_description) WHERE timestamp>%2 " + ; + endquery = " ORDER BY timestamp desc"; + } + else + { + query = "SELECT FROM_UNIXTIME(" + dbnam + "%1.timestamp) AS 'Date Time', vac_mag_desc.name AS 'Name', " + + dbnam + "%1.event AS 'Event', " + "vac_mag_desc.comment AS Description, vac_mag_desc.plc AS 'PLC' FROM " + + dbnam + "%1 left join vac_mag_desc on (" + dbnam + + "%1.id_vac_mag_desc=vac_mag_desc.id_vac_mag_desc) WHERE timestamp>%2 " + ; + endquery = " ORDER BY timestamp desc"; + } + unsigned int inizioRicerca; + switch (queryType) + { + case QueryConfiguration::LastDay: + inizioRicerca = adesso.addDays(-1).toTime_t(); + year = adesso.date().year(); + query = QString(query).arg(year).arg(inizioRicerca) + endquery; + break; + case QueryConfiguration::LastWeek: + inizioRicerca = adesso.addDays(-7).toTime_t(); + year = adesso.date().year(); + query = QString(query).arg(year).arg(inizioRicerca) + endquery; + break; + case QueryConfiguration::LastMonth: + inizioRicerca = adesso.addMonths(-1).toTime_t(); + year = adesso.date().year(); + query = QString(query).arg(year).arg(inizioRicerca) + endquery; + break; + case QueryConfiguration::Interval: + year = end.date().year(); + query = QString(query).arg(year).arg(begin.toTime_t()); + query += QString(" AND timestamp<%1").arg(end.toTime_t()) + endquery; + break; + default: + break; + } + model->setQuery(query); + + /* must apply filter if set */ + if(modulator) + ui.treeLogs->updateFilter(); + else + ui.treeLogsPSVAC->updateFilter(); + + QSqlError error = model->lastError(); + if (error.type() != QSqlError::NoError) + { + QMessageBox::critical(0, "Database Error", QString("Error reading from Db:\n") + error.text() + "\nreconnecting"); + db.close(); + if (!db.open()) + QMessageBox::critical(0, "Error", "Can't establish connection with db FastInterlock on host log"); + } +} + +void Interlock::on_tabWidget_currentChanged(int idx) +{ + if (idx == 3) + { + readFromDb(); + dbTimer->start(); + } + else + dbTimer->stop(); +} + +void Interlock::modSelected(bool en) +{ + // ui.cbStatSelection->setEnabled(en); + // changeStatView(ui.cbStatSelection->currentIndex()); /* will also update descriptions */ +} + +void Interlock::changeStatView(int index) +{ + QString attname; + QString devName = modDeviceName; + /* if Select is checked, then set Stat_mod_NUMBER, otherwise Stat_system */ + // if(ui.rbSelectMod->isChecked()) + // attname = QString("Stat_mod_%1").arg(index); + // else + attname = "Stat_system"; + + // QString src = devName + "/" + attname; + // ui.tableStates->setSource(src); +} + diff --git a/src/interlock.h b/src/interlock.h new file mode 100644 index 0000000000000000000000000000000000000000..e8e283b27810483e98e6a562a0beef8b4990f56a --- /dev/null +++ b/src/interlock.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2007 by Vincenzo Forchi`,,, * + * vincenzo.forchi@elettra.trieste.it * + * * + * 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 interlock_H +#define interlock_H + +#include "ui_interlock.h" +#include "queryconfiguration.h" +#include <QString> +#include <QSqlDatabase> + +//class QGraphicsScene; +class MySqlModel; + +class Interlock: public QWidget +{ + Q_OBJECT + +public: + + enum Tabs { Mod, ModHistory, PsVacLinac, PsVacUH, PsVacPadres, PsVacHistory }; + + Interlock(QWidget * =NULL); + ~Interlock(); + +// QStringList getProperty(string, string); + +protected slots: + void connectTango(); + void acknowledgeSelected(); + void queryConfiguration(); + void readFromDb(); + void on_tabWidget_currentChanged(int); + void changeStatView(int index); + void modSelected(bool en); + void changeAckTarget(int); + void tabChanged(int idx); + void newAlarmArrived(); + +private: + Ui::Interlock ui; + QString modDeviceName, vacPsDeviceName; + + QSqlDatabase db; + MySqlModel *modulatorModel, *psvacModel; + + QueryConfiguration::QueryType queryType; + QDateTime begin, end; + QTimer *dbTimer; + + void setupDb(); + void configureUi(); + void createConnections(); + +// QGraphicsScene *boosterScene; + +}; + + +#endif diff --git a/src/interlock.ui b/src/interlock.ui new file mode 100644 index 0000000000000000000000000000000000000000..daffa12150ad3356e7bb64737620962c63b74038 --- /dev/null +++ b/src/interlock.ui @@ -0,0 +1,553 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Interlock</class> + <widget class="QWidget" name="Interlock"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>898</width> + <height>530</height> + </rect> + </property> + <property name="windowTitle"> + <string>General Fermi Interlock</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <widget class="TabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tabAlarms"> + <attribute name="title"> + <string>Modulator</string> + </attribute> + <layout class="QGridLayout"> + <property name="margin"> + <number>9</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="1" column="8"> + <widget class="QPushButton" name="pbTestSound"> + <property name="text"> + <string>Test Sound</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="leFilterMod"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-weight:600;">Filter</span></p><p>Start typing text to filter items on the second column of the view.</p><p>The search is <span style=" font-style:italic;">case insensitive</span>.</p><p>Click on the <span style=" font-style:italic;">Clear</span> button to clear the text on the box.</p></body></html></string> + </property> + </widget> + </item> + <item row="1" column="3"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="6"> + <widget class="TPushButton" name="tAck"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Ack</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="9"> + <widget class="TTreeWidget" name="treeAlarms"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + <item row="1" column="5"> + <widget class="TComboBox" name="comboAck"> + <property name="enabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pbClearModFilter"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Filter by label:</string> + </property> + </widget> + </item> + <item row="1" column="7"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Modulator History</string> + </attribute> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <widget class="TTreeView" name="treeLogs"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="pushRefresh"> + <property name="text"> + <string>Refresh</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Filter by name:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="leFilterModHist"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-weight:600;">Filter</span></p><p>Start typing text to filter items on the second column of the view.</p><p>The search is <span style=" font-style:italic;">case insensitive</span>.</p><p>Click on the <span style=" font-style:italic;">Clear</span> button to clear the text on the box.</p></body></html></string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbClearModHist"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushQueryConfiguration"> + <property name="text"> + <string>Log Period</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>PS and Vacuum Linac</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="4"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="leFilterPsVacLinac"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-weight:600;">Filter</span></p><p>Start typing text to filter items on the second column of the view.</p><p>The search is <span style=" font-style:italic;">case insensitive</span>.</p><p>Click on the <span style=" font-style:italic;">Clear</span> button to clear the text on the box.</p></body></html></string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Filter by label:</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="7"> + <widget class="TTreeWidget" name="treeAlarmsVPS"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + <item row="1" column="6"> + <widget class="TPushButton" name="tAckPSV"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Ack</string> + </property> + <property name="targets"> + <string>$2->Acknowledge(0);;</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QPushButton" name="pbClearFilterVacLinac"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_3"> + <attribute name="title"> + <string>PS &and Vacuum UH</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="1" column="6"> + <widget class="TPushButton" name="tAckPSUH"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Ack</string> + </property> + <property name="targets"> + <string>$3->Acknowledge(0);;;</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="7"> + <widget class="TTreeWidget" name="treeAlarmsVUH"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + <item row="1" column="5"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="4"> + <widget class="QPushButton" name="pbClearFilterPSVacUH"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Filter by label:</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLineEdit" name="leFilterPsVacUH"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-weight:600;">Filter</span></p><p>Start typing text to filter items on the second column of the view.</p><p>The search is <span style=" font-style:italic;">case insensitive</span>.</p><p>Click on the <span style=" font-style:italic;">Clear</span> button to clear the text on the box.</p></body></html></string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_4"> + <attribute name="title"> + <string>PS and Vacuum Padres</string> + </attribute> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="4"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="5"> + <widget class="TPushButton" name="tpbAckPSVPadres"> + <property name="text"> + <string>Ack</string> + </property> + <property name="targets"> + <string>$4->Acknowledge(0);;</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="pbClearFilterPsVacPadres"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="leFilterPsVacPadres"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-weight:600;">Filter</span></p><p>Start typing text to filter items on the second column of the view.</p><p>The search is <span style=" font-style:italic;">case insensitive</span>.</p><p>Click on the <span style=" font-style:italic;">Clear</span> button to clear the text on the box.</p></body></html></string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Filter by label:</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="6"> + <widget class="TTreeWidget" name="treeAlarmsPadres"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_5"> + <attribute name="title"> + <string>PS and Vacuum History</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0" colspan="6"> + <widget class="TTreeView" name="treeLogsPSVAC"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="itemsExpandable"> + <bool>false</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="pushRefreshPSVacuum"> + <property name="text"> + <string>Refresh</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Filter by name:</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLineEdit" name="leFilterPsVacHistory"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-weight:600;">Filter</span></p><p>Start typing text to filter items on the second column of the view.</p><p>The search is <span style=" font-style:italic;">case insensitive</span>.</p><p>Click on the <span style=" font-style:italic;">Clear</span> button to clear the text on the box.</p></body></html></string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QPushButton" name="pbClearFilterPsVacHistory"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>245</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="5"> + <widget class="QPushButton" name="pushQueryConfigurationPSVAC"> + <property name="text"> + <string>Log Period</string> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> + <customwidgets> + <customwidget> + <class>TComboBox</class> + <extends>QComboBox</extends> + <header>TComboBox</header> + </customwidget> + <customwidget> + <class>TPushButton</class> + <extends>QPushButton</extends> + <header>TPushButton</header> + </customwidget> + <customwidget> + <class>TTreeWidget</class> + <extends>QTreeWidget</extends> + <header>ttreewidget.h</header> + </customwidget> + <customwidget> + <class>TTreeView</class> + <extends>QTreeView</extends> + <header>ttreeview.h</header> + </customwidget> + <customwidget> + <class>TabWidget</class> + <extends>QTabWidget</extends> + <header>tabwidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>treeAlarms</tabstop> + <tabstop>tAck</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..041d61ad313f2a0c2b2439deb4a05ef500fda805 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2007 by Vincenzo Forchi`,,, * + * vincenzo.forchi@elettra.trieste.it * + * * + * 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 "interlock.h" +#include <X11/Xlib.h> +#include <QX11Info> +#include <tutil.h> +#include <elettracolors.h> + +#define CVSVERSION "$Name: $" + +/* uncomment to set application color */ +//#include <elettracolors.h> + +int main( int argc, char ** argv ) { + + TApplication a( argc, argv ); + /* uncomment to set application color */ + a.setPalette(EPalette("fermi")); + QString version(CVSVERSION); + a.setApplicationVersion(version); + a.setApplicationName("FermiInterlock"); + a.setProperty("author", "Giacomo"); + a.setProperty("mail", "giacomo.strangolino@elettra.trieste.it"); + a.setProperty("phone", "375-8073"); + a.setProperty("office", "T2PT025"); + a.setProperty("hwReferent", "Graziano"); + + Interlock mw; + mw.setWindowTitle("Fermi Interlock"); + 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(); +} diff --git a/src/mysqlmodel.cpp b/src/mysqlmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fefdbb655b6b446898db4490b3686897a479b03f --- /dev/null +++ b/src/mysqlmodel.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include <QtGui> + +#include "mysqlmodel.h" + +MySqlModel::MySqlModel(QObject *parent) : QSqlQueryModel(parent) +{ +} + +QVariant MySqlModel::data(const QModelIndex &index, int role) const +{ + QVariant value = QSqlQueryModel::data(index, role); + if (value.isValid() && role == Qt::DisplayRole) { + if (index.column() == 0) + { + QString d = value.toString(); + d.replace('T', ' '); + return d; + } + } + return value; +} diff --git a/src/mysqlmodel.h b/src/mysqlmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..339749c661b89a3709c63ed25c8acde2fc5f84d1 --- /dev/null +++ b/src/mysqlmodel.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef MYSQLMODEL_H +#define MYSQLMODEL_H + +#include <QSqlQueryModel> + +class MySqlModel : public QSqlQueryModel +{ + Q_OBJECT + +public: + MySqlModel(QObject *parent = 0); + + QVariant data(const QModelIndex &item, int role) const; +}; + +#endif diff --git a/src/queryconfiguration.cpp b/src/queryconfiguration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f23ae0285c4c0b767e3971dee5a4cb107ddb253 --- /dev/null +++ b/src/queryconfiguration.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vincenzo Forchi`,,, * + * tus@ken * + * * + * 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 "queryconfiguration.h" + +#include <QDateTime> +#include <QMessageBox> + +#include <QtDebug> + +QueryConfiguration::QueryConfiguration(QDialog *parent) : QDialog(parent) +{ + ui.setupUi(this); + ui.dateStart->setDate(QDate::currentDate()); + ui.dateStop->setDate(QDate::currentDate()); + ui.timeStart->setTime(QTime::currentTime()); + ui.timeStop->setTime(QTime::currentTime()); + connect(ui.comboPeriod, SIGNAL(currentIndexChanged(int)), this, SLOT(enableFrame(int))); + connect((QObject*) ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(ok())); +} + +QueryConfiguration::~QueryConfiguration() +{ +} + +void QueryConfiguration::enableFrame(int index) +{ + if (index == 3) + ui.frame->setEnabled(true); + else + ui.frame->setEnabled(false); +} + +void QueryConfiguration::ok() +{ + if (ui.comboPeriod->currentIndex() == 3) + { + QDateTime begin, end; + begin.setDate(ui.dateStart->date()); + begin.setTime(ui.timeStart->time()); + end.setDate(ui.dateStop->date()); + end.setTime(ui.timeStop->time()); + if (begin >= end) + QMessageBox::warning(0, "Warning", "Invalid interval: check starting and ending dates"); + else + accept(); + } + else + accept(); +} + +void QueryConfiguration::setQueryType(QueryType qt) +{ + ui.comboPeriod->setCurrentIndex((int) qt); +} + +QueryConfiguration::QueryType QueryConfiguration::queryType() +{ + return (QueryType) ui.comboPeriod->currentIndex(); +} + +void QueryConfiguration::setStartDateTime(QDateTime dt) +{ + ui.dateStart->setDate(dt.date()); + ui.timeStart->setTime(dt.time()); +} + +void QueryConfiguration::setStopDateTime(QDateTime dt) +{ + ui.dateStop->setDate(dt.date()); + ui.timeStop->setTime(dt.time()); +} + +QDateTime QueryConfiguration::startDateTime() +{ + QDateTime dt; + dt.setDate(ui.dateStart->date()); + dt.setTime(ui.timeStart->time()); + return dt; +} + +QDateTime QueryConfiguration::stopDateTime() +{ + QDateTime dt; + dt.setDate(ui.dateStop->date()); + dt.setTime(ui.timeStop->time()); + return dt; +} diff --git a/src/queryconfiguration.h b/src/queryconfiguration.h new file mode 100644 index 0000000000000000000000000000000000000000..40cf385f9e8e3808c0710b544b88828f5e8cec11 --- /dev/null +++ b/src/queryconfiguration.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2006 by Vincenzo Forchi`,,, * + * tus@ken * + * * + * 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 QUERYCONFIGURATION_H +#define QUERYCONFIGURATION_H + +#include "ui_queryconfiguration.h" + +class QueryConfiguration : public QDialog +{ + Q_OBJECT + +public: + QueryConfiguration(QDialog * =NULL); + ~QueryConfiguration(); + + enum QueryType + { + LastDay, + LastWeek, + LastMonth, + Interval, + All + }; + + void setQueryType(QueryType); + QueryType queryType(); + + void setStartDateTime(QDateTime); + void setStopDateTime(QDateTime); + QDateTime startDateTime(); + QDateTime stopDateTime(); + +protected slots: + void enableFrame(int); + void ok(); + +private: + Ui::QueryConfiguration ui; +}; + + +#endif diff --git a/src/queryconfiguration.ui b/src/queryconfiguration.ui new file mode 100644 index 0000000000000000000000000000000000000000..e6be30920911e0a84dc765f402532fe3beab5584 --- /dev/null +++ b/src/queryconfiguration.ui @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QueryConfiguration</class> + <widget class="QDialog" name="QueryConfiguration"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>380</width> + <height>194</height> + </rect> + </property> + <property name="windowTitle"> + <string>Display</string> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>9</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="1" column="0"> + <widget class="QFrame" name="frame"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>220</width> + <height>60</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>9</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="1" column="1"> + <widget class="QDateEdit" name="dateStop"> + <property name="displayFormat"> + <string>dd MMM yyyy</string> + </property> + <property name="calendarPopup"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDateEdit" name="dateStart"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>0</height> + </size> + </property> + <property name="displayFormat"> + <string>dd MMM yyyy</string> + </property> + <property name="calendarPopup"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QTimeEdit" name="timeStop"> + <property name="displayFormat"> + <string>h:mm</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QTimeEdit" name="timeStart"> + <property name="displayFormat"> + <string>h:mm </string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>From:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>To:</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QComboBox" name="comboPeriod"> + <item> + <property name="text"> + <string>Last Day</string> + </property> + </item> + <item> + <property name="text"> + <string>Last Week</string> + </property> + </item> + <item> + <property name="text"> + <string>Last Month</string> + </property> + </item> + <item> + <property name="text"> + <string>Interval</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>QueryConfiguration</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>249</x> + <y>134</y> + </hint> + <hint type="destinationlabel"> + <x>258</x> + <y>148</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/tabwidget.cpp b/src/tabwidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbad1dc22b6715731d66b59efd3339eb0aa1c061 --- /dev/null +++ b/src/tabwidget.cpp @@ -0,0 +1,21 @@ +#include "tabwidget.h" + +void TabBar::mouseReleaseEvent(QMouseEvent *e) +{ + int ci = currentIndex(); + QIcon curIcon = tabIcon(ci); + if(!curIcon.isNull()) + { + setTabIcon(ci, QIcon()); + } + QTabBar::mouseReleaseEvent(e); +} + + +TabWidget::TabWidget(QWidget *parent) : + QTabWidget(parent) +{ + setTabBar(new TabBar(this)); +} + + diff --git a/src/tabwidget.h b/src/tabwidget.h new file mode 100644 index 0000000000000000000000000000000000000000..eca8ae555f90792a9c4009b8323d79043d92b41b --- /dev/null +++ b/src/tabwidget.h @@ -0,0 +1,31 @@ +#ifndef TABWIDGET_H +#define TABWIDGET_H + +#include <QTabWidget> +#include <QTabBar> + +class TabBar : public QTabBar +{ + Q_OBJECT +public: + TabBar(QWidget *parent ) : QTabBar(parent) {} + +protected: + void mouseReleaseEvent(QMouseEvent *e); + +}; + +class TabWidget : public QTabWidget +{ + Q_OBJECT +public: + explicit TabWidget(QWidget *parent = 0); + +signals: + +public slots: + + +}; + +#endif // TABICON_H diff --git a/src/tlabelitem.cpp b/src/tlabelitem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b86edd2f53616e10c12dc223a970d8e31e1bf808 --- /dev/null +++ b/src/tlabelitem.cpp @@ -0,0 +1,137 @@ +#include <QtGui> + +#include "tlabelitem.h" +#include <elettracolors.h> +#include <QGraphicsSceneHoverEvent> + +TLabelItem::TLabelItem(QObject *p) : QObject(p), QTangoComProxyReader(this)//, app(0) +{ + m_stateColors = QVector<QColor>(14, EColor(Elettra::darkYellow)); + m_stateColors[Tango::ON] = EColor(Elettra::green); + m_stateColors[Tango::FAULT] = EColor(Elettra::red); + m_stateColors[Tango::ALARM] = EColor(Elettra::red); + + m_trueColor = Qt::green; + m_trueString = "True"; + m_falseColor = Qt::red; + m_falseString = "False"; + + m_mode = Simple; + ellipseRect = QRectF(0,0,10,10); + + setAcceptHoverEvents(true); + setFlags(QGraphicsItem::ItemIsMovable); + + connect(qtangoComHandle(), SIGNAL(newData(const TVariant&)), this, SLOT(refresh(const TVariant&)), + Qt::DirectConnection); +} + +void TLabelItem::refresh(const TVariant& v) +{ + //setToolTip(QString::fromStdString(getDeviceName())); + if (v.quality() == ATTR_INVALID) + { + brushColor = Qt::gray; + setText("####"); + } + else + { + if (v.canConvertToState()) + { + Tango::DevState s = v.toState(); + brushColor = m_stateColors.at(s); + setText(Config::instance()->stateString(s)); + } + else if (v.canConvertToBool()) + { + if (v.toBool()) + { + brushColor = m_trueColor; + setText(m_trueString); + } + else + { + brushColor = m_falseColor; + setText(m_falseString); + } + } + else if (v.canConvertToString()) + { + brushColor = Qt::white; + setText(v.toString()); + } + } +} + +void TLabelItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + painter->setPen(Qt::black); + painter->setBrush(brushColor); + + QRectF r = boundingRect(); + if (m_mode == Simple) + { + painter->drawEllipse(ellipseRect); + } + else + { + painter->drawRect(r.x()-2, r.y()-1, r.width()+4, r.height()+2); + QGraphicsSimpleTextItem::paint(painter, option, widget); + } +} + +/*void TLabelItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + if (helperApplication.isNull()) + { + string a = TLoggingFactory::instance()->findHelperApplication(getDeviceName()); + if (a != "") + { + helperApplication = QString::fromStdString(a + " " + getDeviceName()); + } + else + helperApplication = QString("atkpanel ") + QString::fromStdString(getDeviceName()); + } + if (!helperApplication.isNull()) + { + launchHelperApplication(); + } +}*/ + +/*void TLabelItem::launchHelperApplication() +{ + if (!app) + app = new EApplicationLauncher(helperApplication); + app->Rise(); +}*/ + +void TLabelItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event); + if (ellipseRect.contains(event->pos())) + m_mode = Zoomed; + update(); +} + +void TLabelItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event); + if (ellipseRect.contains(event->pos())) + m_mode = Zoomed; + update(); +} + +void TLabelItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event); + m_mode = Simple; + update(); +} + +/*QRectF TLabelItem::boundingRect() +{ + qDebug("TLabelItem::boundingRect"); + return QGraphicsSimpleTextItem::boundingRect(); +}*/ + diff --git a/src/tlabelitem.h b/src/tlabelitem.h new file mode 100644 index 0000000000000000000000000000000000000000..cffb8a94df107c3284d9a1d47a42aea83c698e8b --- /dev/null +++ b/src/tlabelitem.h @@ -0,0 +1,60 @@ +#ifndef TLABELITEM_H +#define TLABELITEM_H + +#include <QGraphicsSimpleTextItem> +#include <qtangocore.h> +#include <QObject> +#include <QVector> +#include <QRectF> +#include <EApplicationLauncher> +#include <com_proxy_reader.h> + +class TLabelItem : public QObject, public QGraphicsSimpleTextItem, public QTangoComProxyReader +{ +Q_OBJECT + + enum Mode { Simple, Zoomed }; + +public: + TLabelItem(QObject * = 0); + + void setTrueColor(QColor c) { m_trueColor = c; }; + QColor trueColor() { return m_trueColor; }; + + void setFalseColor(QColor c) { m_falseColor = c; }; + QColor falseColor() { return m_falseColor; }; + + void setTrueString(QString s) { m_trueString = s; }; + QString trueString() { return m_trueString; }; + + void setFalseString(QString s) { m_falseString = s; }; + QString falseString() { return m_falseString; }; + +// QRectF boundingRect(); + +protected slots: + void refresh(const TVariant& v); + +protected: + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); +// void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + void hoverMoveEvent(QGraphicsSceneHoverEvent *event); +// void launchHelperApplication(); + + QVector<QColor> m_stateColors; + QColor m_trueColor; + QColor m_falseColor; + QString m_trueString; + QString m_falseString; + + QColor brushColor; + Mode m_mode; + QRectF ellipseRect; +// EApplicationLauncher *app; +// QString helperApplication; + +}; + +#endif diff --git a/src/treeitem.cpp b/src/treeitem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63070c47fcf8936088a4957c0f81e3df7a5eab7a --- /dev/null +++ b/src/treeitem.cpp @@ -0,0 +1,12 @@ +#include "treeitem.h" + +TreeItem::TreeItem(QTreeWidget *parent, const QStringList& items) + : QTreeWidgetItem(parent, items) +{ + +} + +bool TreeItem::operator< (const QTreeWidgetItem &other) const +{ + return this->data(0, Qt::UserRole).toInt() < other.data(0, Qt::UserRole).toInt(); +} diff --git a/src/treeitem.h b/src/treeitem.h new file mode 100644 index 0000000000000000000000000000000000000000..4c99846d86aef2fa3dd96bfc7d46d6b30dc5acd2 --- /dev/null +++ b/src/treeitem.h @@ -0,0 +1,18 @@ +#ifndef TREEITEM_H +#define TREEITEM_H + +#include <QTreeWidgetItem> + +class TreeItem : public QTreeWidgetItem +{ +public: + TreeItem(QTreeWidget *parent, const QStringList& items); + + bool operator <(const QTreeWidgetItem &other) const; +signals: + +public slots: + +}; + +#endif // TREEITEM_H diff --git a/src/ttablewidget.cpp b/src/ttablewidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a79f45a65ac6a4b4b7f3a226bdee25c91c4713a1 --- /dev/null +++ b/src/ttablewidget.cpp @@ -0,0 +1,61 @@ +#include <QtDebug> + +#include "ttablewidget.h" +#include <elettracolors.h> + +TTableWidget::TTableWidget(QWidget *p) : QTableWidget(p), QTangoComProxyReader(this) +{ + setColumnCount(16); + setAutoConfiguration(true); + connect(qtangoComHandle(), SIGNAL(newData(const TVariant&)), this, SLOT(refresh(const TVariant&)), + Qt::DirectConnection); + connect(qtangoComHandle(), SIGNAL(attributeAutoConfigured(const TangoConfigurationParameters *)), this, SLOT(configure(const TangoConfigurationParameters *))); + setDesiredAttributePropertyList(QStringList() << "labels"); +} + +void TTableWidget::configure(const TangoConfigurationParameters *cp) +{ + if(cp->propertyFound("labels")) + { + _labels = cp->attributePropertyValue("labels"); + printf("\e[1;32m configuring labels on ttable\e[0m\n"); + qslisttoc(_labels); + refresh(currentValue()); + } + else + perr("TTableWidget::configure(): source \"%s\" hasn't got the values property", qstoc(source())); + +} + +void TTableWidget::refresh(const TVariant& v) +{ + printf("\e[0;33mrefresh()\e[0m\n"); + if (v.quality() == ATTR_INVALID) + { + setDisabled(true); + } + else if (v.canConvertToBoolVector()) + { + setDisabled(false); + QVector<bool> data = v.toBoolVector(); + if (data == oldData) + return; + oldData = data; + clear(); + setRowCount(data.size() / columnCount() + (data.size()%columnCount() ? 1 : 0)); + for (unsigned int i = 0; i < data.size(); i++) + { + QTableWidgetItem *item = new QTableWidgetItem(); + item->setFlags(Qt::ItemIsEnabled); + item->setBackground(QBrush(EColor(data[i] ? Elettra::green : Elettra::red))); + item->setText(_labels.value(i)); + item->setTextAlignment(Qt::AlignCenter); + item->setToolTip(_descriptions.value(i)); + setItem(i / columnCount(), i % columnCount(), item); + printf("\e[1;36msetting label \"%s\" ", qstoc(_labels.value(i))); + } + printf("\n\e[1;32m --- done refresh()\e[0m\n"); + resizeColumnsToContents(); + } +} + diff --git a/src/ttablewidget.h b/src/ttablewidget.h new file mode 100644 index 0000000000000000000000000000000000000000..b74ee282e3df8d7af43eade9f7cf107b3c764f18 --- /dev/null +++ b/src/ttablewidget.h @@ -0,0 +1,33 @@ +#ifndef TTABLEWIDGET_H +#define TTABLEWIDGET_H + +#include <QTableWidget> +#include <QStringList> +#include <qtangocore.h> +#include <com_proxy_reader.h> + +class TTableWidget : public QTableWidget, public QTangoComProxyReader +{ +Q_OBJECT + +public: + TTableWidget(QWidget * = 0); + + void setLabels(QStringList l){ _labels = l; }; + QStringList labels(){ return _labels; }; + + void setDescriptions(QStringList d){ _descriptions = d; }; + QStringList descriptions(){ return _descriptions; }; + +protected slots: + void refresh(const TVariant &v); + void configure(const TangoConfigurationParameters *cp); + +protected: + QStringList _labels; + QStringList _descriptions; + QVector<bool> oldData; + +}; + +#endif diff --git a/src/ttreeview.cpp b/src/ttreeview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1654e6d51b719c3b51e73a4eb4cd1dbd21e805e --- /dev/null +++ b/src/ttreeview.cpp @@ -0,0 +1,26 @@ +#include "ttreeview.h" +#include <QHeaderView> + +TTreeView::TTreeView(QWidget *parent) : + QTreeView(parent) +{ + header()->setSectionResizeMode(QHeaderView::ResizeToContents); +} + +void TTreeView::updateFilter() +{ + filter(mCurrentFilter); +} + +void TTreeView::filter(const QString& text) +{ + mCurrentFilter = text; + for(int i = 0; i< this->model()->rowCount(); i++) + { + if(text.isEmpty()) + setRowHidden(i, QModelIndex(), false); + + setRowHidden(i, QModelIndex(), + !(model()->data(model()->index(i, 1)).toString().contains(text, Qt::CaseInsensitive))); + } +} diff --git a/src/ttreeview.h b/src/ttreeview.h new file mode 100644 index 0000000000000000000000000000000000000000..8988ffd103bea970048d42e4e640e22afe1379c3 --- /dev/null +++ b/src/ttreeview.h @@ -0,0 +1,24 @@ +#ifndef TTREEVIEW_H +#define TTREEVIEW_H + +#include <QTreeView> + +class TTreeView : public QTreeView +{ + Q_OBJECT +public: + explicit TTreeView(QWidget *parent = 0); + +signals: + +public slots: + void filter(const QString& text); + + void updateFilter(); + +private: + QString mCurrentFilter; + +}; + +#endif // TTREEVIEW_H diff --git a/src/ttreewidget.cpp b/src/ttreewidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2df60ef7d2ddac1e02b4e86d08ee23fc99b1307 --- /dev/null +++ b/src/ttreewidget.cpp @@ -0,0 +1,184 @@ +#include <QtDebug> + +#include <QMenu> +#include <QContextMenuEvent> +#include <QHeaderView> +#include <QDateTime> +#include "ttreewidget.h" +#include <elettracolors.h> +#include <QScrollBar> +#include "treeitem.h" + +#define DECOLOR_COUNT_MAX 10 +#define DECOLOR_INTERVAL 500 /* milliseconds of decoloring effect */ + +TTreeWidget::TTreeWidget(QWidget *p) : QTreeWidget(p), QTangoComProxyReader(this), _dataSize(0) +{ + setAutoConfiguration(true); + setDesiredAttributePropertyList(QStringList() << "labels" << "positions"); + header()->setSectionResizeMode(QHeaderView::ResizeToContents); + setSortingEnabled(true); + sortByColumn(0); + connect(qtangoComHandle(), SIGNAL(newData(const TVariant&)), this, SLOT(refresh(const TVariant&)), + Qt::DirectConnection); + connect(qtangoComHandle(), SIGNAL(attributeAutoConfigured(const TangoConfigurationParameters *)), this, SLOT(configure(const TangoConfigurationParameters *))); + + tmpCounter = 1; + +} + +void TTreeWidget::configure(const TangoConfigurationParameters *cp) +{ + if(cp->propertyFound("labels")) + _labels = cp->attributePropertyValue("labels"); + + if(cp->propertyFound("positions")) + _descriptions = cp->attributePropertyValue("positions"); +} + +void TTreeWidget::refresh(const TVariant& v) +{ + /* save scrollbar value */ + int scrollPos = this->verticalScrollBar()->value(); + /* first time do not emit signal for sound */ + bool alarmPresent; +// setToolTip(getMessage()); + if (v.quality() == ATTR_INVALID) + { + setDisabled(true); + } +/* else if (canConvertToBoolVector()) + { + setDisabled(false); + clear(); + vector<bool> data = getDataAsBoolVector(); + QList<QTreeWidgetItem *> items; + for (unsigned int i = 0; i < data.size(); i++) + { + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*) 0, QStringList(_labels.value(i))); + items.append(item); + } + insertTopLevelItems(0, items); + }*/ + else if (v.canConvertToDoubleVector()) + { + setDisabled(false); + QVector<double> data = v.toDoubleVector(); + // qSort(data.begin(), data.end()); + + if (data == oldData) + return; + + qDebug() << __FUNCTION__ << data << data.size(); + + double lastTimestamp = data.last(); + double previousLastTimestamp; + if(oldData.isEmpty()) /* first refresh, no matter if visible or not */ + { + previousLastTimestamp = QDateTime::currentDateTime().toTime_t(); + qDebug() << "setting last timestamp seen in first time " << objectName() << + previousLastTimestamp << QDateTime::currentDateTime(); + mLastTimestampSeen = previousLastTimestamp; + } + else + previousLastTimestamp = oldData.last(); + + alarmPresent = lastTimestamp > previousLastTimestamp && !oldData.isEmpty(); + if(lastTimestamp > previousLastTimestamp) + mAlarmColor = KRED; + + /* now we can update oldData, sorted */ + oldData = data; + clear(); + _dataSize = data.size(); + + + QList<QTreeWidgetItem *> items; + + for (int i = data.size() - 1; i >= 0; i--) + { + if (data[i]) + { + QStringList cells; + QDateTime date; + date.setTime_t((int) data[i]); + date = date.addMSecs((int)(1000 *(data[i] - (int) data[i]))); + cells << date.toString("d MMM yyyy hh:mm:ss.zzz") << _labels.value(i) << _descriptions.value(i) << QString().setNum(i); + TreeItem *item = new TreeItem(this, cells); + item->setData(0, Qt::UserRole, data[i]); + items.append(item); + if(data[i] > mLastTimestampSeen) /* red colour new alarms */ + { + QFont f = item->font(0); + f.setBold(true); + for(int i = 0; i < item->columnCount(); i++) + item->setFont(i, f); + } + } + } + insertTopLevelItems(0, items); + + if(alarmPresent) + { + emit newAlarmArrived(); + } + } + filter(mCurrentFilter); + + /* restore last scroll position */ + if(scrollPos != this->verticalScrollBar()->value()) + this->verticalScrollBar()->setValue(scrollPos); +} + +void TTreeWidget::filter(const QString& text) +{ + mCurrentFilter = text; + QList<QTreeWidgetItem *> items = this->findItems("*", Qt::MatchWildcard, 0); + if(text.isEmpty()) /* show all items */ + { + foreach(QTreeWidgetItem* it, items) + if(it->isHidden()) + it->setHidden(false); + } + else + { + foreach(QTreeWidgetItem* it, items) + { + it->setHidden(!it->text(1).contains(text, Qt::CaseInsensitive)); + } + } +} + +void TTreeWidget::ackSelected() +{ + emit acknowledgeSelected(); +} + +void TTreeWidget::ackAll() +{ + emit acknowledgeAll(); +} + +void TTreeWidget::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu *menu = new QMenu(this); + menu->addAction("Acknowledge Selected", this, SLOT(ackSelected())); + menu->addAction("Acknowledge All", this, SLOT(ackAll())); + menu->exec(event->globalPos()); +} + +void TTreeWidget::hideEvent(QHideEvent *e) +{ + QTreeWidget::hideEvent(e); + mLastTimestampSeen = QDateTime::currentDateTime().toTime_t(); + qDebug() << "hide event: last timestamp seen for " << objectName() << QDateTime::currentDateTime() << mLastTimestampSeen; +} + +void TTreeWidget::showEvent(QShowEvent *e) +{ + QTreeWidget::showEvent(e); + mLastTimestampSeen = QDateTime::currentDateTime().toTime_t(); + qDebug() << "show event : last timestamp seen for " << objectName() << QDateTime::currentDateTime() << mLastTimestampSeen; + +} + diff --git a/src/ttreewidget.h b/src/ttreewidget.h new file mode 100644 index 0000000000000000000000000000000000000000..ff8827546ce76519903f033d040b0da7f092c771 --- /dev/null +++ b/src/ttreewidget.h @@ -0,0 +1,56 @@ +#ifndef TTREEWIDGET_H +#define TTREEWIDGET_H + +#include <QTreeWidget> +#include <QStringList> +#include <qtangocore.h> +#include <com_proxy_reader.h> + +class TTreeWidget : public QTreeWidget, public QTangoComProxyReader +{ +Q_OBJECT + +public: + TTreeWidget(QWidget * = 0); + + void setLabels(QStringList l){ _labels = l; }; + QStringList labels(){ return _labels; }; + + void setDescriptions(QStringList d){ _descriptions = d; }; + QStringList descriptions(){ return _descriptions; }; + + unsigned int dataSize(){ return _dataSize; }; + +signals: + void acknowledgeAll(); + void acknowledgeSelected(); + void newAlarmArrived(); + +protected slots: + void refresh(const TVariant &v); + void configure(const TangoConfigurationParameters *cp); + void ackSelected(); + void ackAll(); + + void filter(const QString& text); + +protected: + void contextMenuEvent(QContextMenuEvent *); + QStringList _labels; + QStringList _descriptions; + unsigned int _dataSize; + QVector<double> oldData; + + void showEvent(QShowEvent *e); + void hideEvent(QHideEvent *); + +private: + QString mCurrentFilter; + int mDecolorCount; + QColor mAlarmColor; + double mLastTimestampSeen; + + int tmpCounter; +}; + +#endif