Commit 9bcec5d1 authored by Giacomo Strangolino's avatar Giacomo Strangolino
Browse files

ported to cumbia- code refactoring - initial sort algo

parent d6eaa1ec
......@@ -8,12 +8,17 @@
#include "AlarmTreeWidgetItem.h"
#include <QMouseEvent>
#include <QMenu>
#include <cumacros.h>
#include <QAction>
#include <QDesktopServices>
#include <QUrl>
#include <QScrollBar>
#include <QtDebug>
#include <cudata.h>
#include <cumacros.h>
#include <qustring.h>
#include <qustringlist.h>
using namespace std;
AlarmTreeWidget::AlarmTreeWidget(QWidget *parent) : QTreeWidget(parent)
......@@ -138,21 +143,97 @@ void AlarmTreeWidget::removeFilter()
headerItem()->setIcon(GROUP, QIcon(ICON_PATH + ""));
}
/*
void AlarmTreeWidget::cloneTreeWidget(QTreeWidget* it)
void AlarmTreeWidget::refresh(const CuData &v)
{
QStringList itemS;
clear();
QList<QTreeWidgetItem *>items = it->findItems("*", Qt::MatchWildcard);
for(int i = 0; i < items.size(); i++)
printf("Alarm.refresh: from \e[1;34m%s\e[0m\n", vtoc2(v, "src"));
const QuString src(v, "src");
bool err = v["err"].toBool();
//QAbstractItemModel *model = ui->treeWidgetAlarms->model();
/* remove the filter */
if (err)
{
setDisabled(true);
}
else
{
itemS.clear();
for(int j =0; j < items[i]->columnCount(); j++)
itemS << items[i]->text(j);
QTreeWidgetItem *clone = new QTreeWidgetItem(this, itemS);
setDisabled(false);
int scrollBarPos;
QStringList fields;
QStringList alrnames;
AlarmTreeWidgetItem* item = NULL;
QStringList data = QuStringList(v, "value");
QStringList high, medium, low, lowest, unknown_level;
// group by level in order to sort view
foreach(QString row, data) {
QString level = row.split("\t").at(AlarmTreeWidget::LEVEL);
if(level.contains("high"))
high << row;
else if(level.contains("lowest"))
lowest << row;
else if(level.contains("medium"))
medium << row;
else if(level.contains("low"))
low << row;
else
unknown_level << row;
}
data = unknown_level + lowest + low + medium + high;
int index = 0;
const QSet<QString> oldset = mSrcAlarmHash.value(src);
QSet<QString>& alsrcset = mSrcAlarmHash[src];
alsrcset.clear(); // empty set for src
/* add items to the tree(s) if not already present */
for (int i = data.size() - 1; i >= 0; i--) {
fields = data[i].split("\t");
alrnames << fields.at(AlarmTreeWidgetItem::Alarm);
/* save current scroll bar value */
scrollBarPos = verticalScrollBar()->value();
item = mItemHash.value(fields.at(AlarmTreeWidgetItem::Alarm));
if(!item) /* create a new item */ {
index = findPos(fields[0].toUInt(), fields[AlarmTreeWidgetItem::Level]);
m_insert_item(fields, index);
printf("\e[1;34m%s - number of tabs %d -- index %d\e[0m\n", qstoc(data[i]), data[i].count("\t"), index);
}
else /* update fields of existing items */
item->update(fields);
/* restore scrollbar value */
verticalScrollBar()->setValue(scrollBarPos);
// add alarm name to set of alarm names for this src
alsrcset.insert(fields.at(AlarmTreeWidgetItem::Alarm));
// notify new alarm detected. connected to Alarm::beep
if(fields.size() > 5 && fields[3] == "ALARM" && fields.last() == "NEW")
emit newAlarmDetected();
}
/* remove stale items */
QSet<QString> stale = oldset - alsrcset;
m_remove_stale_items(stale);
}
}
int AlarmTreeWidget::findPos(time_t ts, const QString &pri) {
int i = 0, prio = m_pri_to_int(pri);
while(i < topLevelItemCount() && topLevelItem(i)->data(AlarmTreeWidgetItem::Level, Qt::UserRole).toInt() > prio)
i++;
// i points to the first item with same pri or to the very last item in the view
while(i < topLevelItemCount() && topLevelItem(i)->data(AlarmTreeWidgetItem::DateTime, Qt::UserRole).toUInt() > ts
&& topLevelItem(i)->data(AlarmTreeWidgetItem::Level, Qt::UserRole).toInt() == prio) {
i++;
}
return i ;
}
*/
void AlarmTreeWidget::contextMenuEvent(QContextMenuEvent *e)
{
bool silenceAvail = true;
......@@ -183,6 +264,52 @@ void AlarmTreeWidget::contextMenuEvent(QContextMenuEvent *e)
}
}
void AlarmTreeWidget::m_insert_item(const QStringList &list, int index)
{
qDebug() << __PRETTY_FUNCTION__ << "inserting " << list << index;
AlarmTreeWidgetItem *item;
QStringList fields(list);
bool isNew = false;
if(fields.size() > 0)
fields[AlarmTreeWidgetItem::DateTime] = QDateTime::fromTime_t(list.at(AlarmTreeWidgetItem::DateTime).toUInt()).toString();
if(fields.at(AlarmTreeWidgetItem::Alarm).contains("internal_error_"))
item = new AlarmTreeWidgetItem(this, fields);
else
{
if(fields.last().toUpper() == "NEW"){
isNew = true;
}
fields.removeLast(); /* the last element contains info about "NEW", than must not be displayed */
// printf("\e[1;32m ADDING NEW AlarmTreeWidgetitem to index %d\e[0m\n", index);
item = new AlarmTreeWidgetItem(fields);
item->setData(AlarmTreeWidgetItem::Level, m_pri_to_int(fields[AlarmTreeWidgetItem::Level]), Qt::UserRole);
item->setData(AlarmTreeWidgetItem::DateTime, list.at(AlarmTreeWidgetItem::DateTime).toUInt(), Qt::UserRole);
insertTopLevelItem(index, item);
item->setNew(isNew);
}
/* add the couple identifier/AlarmTreeWidgetItem to the hash */
mItemHash.insert(fields.at(AlarmTreeWidgetItem::Alarm), item);
}
void AlarmTreeWidget::m_remove_stale_items(const QSet<QString> stale_names) {
foreach(const QString& name, stale_names) {
AlarmTreeWidgetItem *item = mItemHash.value(name);
if(item) {
mItemHash.remove(name);
delete item;
}
}
}
int AlarmTreeWidget::m_pri_to_int(const QString &pri) const {
if(pri == "high") return 100;
else if(pri == "medium") return 80;
else if(pri == "low") return 50;
else return 10;
}
void AlarmTreeWidget::mouseMoveEvent(QMouseEvent *event)
{
QTreeWidget::mouseMoveEvent(event);
......
......@@ -6,6 +6,8 @@
#include <vector>
#include <iostream>
class CuData;
class AlarmTreeWidgetItem;
using namespace std;
......@@ -19,6 +21,11 @@ public:
void removeFilter();
enum columns { DATET, MICROSEC, ALARM, STATUS, ACK, COUNT, LEVEL, SILENCED, GROUP, MESSAGE };
int findPos(time_t ts, const QString& pri);
public slots:
void refresh(const CuData &v);
protected slots:
void slotItemEntered(QTreeWidgetItem*,int);
......@@ -27,6 +34,8 @@ protected slots:
signals:
void newAlarmDetected();
void message(const QString& msg);
void mouseOverItem(bool);
......@@ -43,7 +52,13 @@ protected:
void contextMenuEvent(QContextMenuEvent *);
private:
int m_pri_to_int(const QString& pri) const;
void m_remove_stale_items(const QSet<QString> stale_names);
void m_insert_item(const QStringList &list, int index);
bool _filter_enabled;
QHash<QString, AlarmTreeWidgetItem*> mItemHash;
QHash<QString, QSet<QString> >mSrcAlarmHash;
};
......
......@@ -30,7 +30,6 @@
#include "AlarmHistoryTree.h"
#include <QDebug>
#include <QMap>
#include <QScrollBar>
// cumbia
#include <qulogimpl.h>
......@@ -41,11 +40,12 @@
#include <quapps.h>
#include <quwriter.h>
#include <quwatcher.h>
#include <qustring.h>
#include <qustringlist.h>
// cumbia
Alarm::Alarm(CumbiaPool *cu_p, QWidget *parent) : QWidget(parent)
{
// cumbia
CuModuleLoader mloader(cu_p, &m_ctrl_factory_pool, &m_log_impl);
cu_pool = cu_p;
......@@ -107,11 +107,24 @@ Alarm::Alarm(CumbiaPool *cu_p, QWidget *parent) : QWidget(parent)
ui->tWGroup->header()->setHidden(true);
ui->pBConfHistory->setHidden(true);
// data from Tango DB
// ////////////////////////////////////////////////////////////
QuWatcher *db_gn_w = new QuWatcher(this, cu_pool, m_ctrl_factory_pool); // device prop watcher
db_gn_w->setSingleShot(true);
db_gn_w->setAutoDestroy(true);
connect(db_gn_w, SIGNAL(newData(CuData)), this, SLOT(onDevProps(CuData)));
db_gn_w->setSource("$1(GroupNames,InstanceName)");
db_gn_w->setSource(QString("%1(GroupNames,InstanceName)").arg(qApp->arguments().at(1)));
QuWatcher *db_dlist_w = new QuWatcher(this, cu_pool, m_ctrl_factory_pool); // device prop watcher
db_dlist_w->setSingleShot(true);
db_dlist_w->setAutoDestroy(true);
connect(db_dlist_w, SIGNAL(newData(CuData)), this, SLOT(onDevList(CuData)));
db_dlist_w->setSource("tango://#AlarmHandler#DeviceList");
// ////////////////////////////////////////////////////////////
//
//---------------------------------------------------------------------------------------
if(args.contains("--alarm-test-devname") && args.size() > args.indexOf("--alarm-test-devname") + 1)
......@@ -158,6 +171,8 @@ Alarm::Alarm(CumbiaPool *cu_p, QWidget *parent) : QWidget(parent)
/* connections for test section */
//connect(ui->pBTestSoundOn, SIGNAL(clicked()), this, SLOT(testSound()));
//connect(ui->pBTestSoundOff, SIGNAL(clicked()), this, SLOT(stopSound()));
/* sound: beep on new alarm */
connect(ui->treeWidgetAlarms, SIGNAL(newAlarmDetected()), this, SLOT(beep()));
}
Alarm::~Alarm() {
......@@ -165,181 +180,50 @@ Alarm::~Alarm() {
sound->stop();
delete sound;
}
}
}
void Alarm::refresh(const CuData &v)
{
printf("Alarm.refresh: from \e[1;34m%s\e[0m --> alarm \e[1;35m%s\e[0m\n", vtoc2(v, "src"), vtoc2(v, "value"));
// QString line;
// //QAbstractItemModel *model = ui->treeWidgetAlarms->model();
// /* remove the filter */
// if (v.quality() == ATTR_INVALID)
// {
// setDisabled(true);
// }
// else if(v.canConvertToStringVector())
// {
// setDisabled(false);
// int scrollBarPos;
// QStringList fields;
// QStringList ids;
// AlarmTreeWidgetItem* item = NULL;
// QVector<QString> data = v.toStringVector();
// QVector<QString> high, medium, low, lowest, unknown_level;
// // group by level in order to sort view
// foreach(QString row, data) {
// QString level = row.split("\t").at(AlarmTreeWidget::LEVEL);
// if(level.contains("high"))
// high << row;
// else if(level.contains("lowest"))
// lowest << row;
// else if(level.contains("medium"))
// medium << row;
// else if(level.contains("low"))
// low << row;
// else
// unknown_level << row;
// }
// data = unknown_level + lowest + low + medium + high;
// int index = 0;
// /* add items to the tree(s) if not already present */
// for (int i = data.size() - 1; i >= 0; i--)
// {
// line = data[i];
// fields = line.split("\t");
// playSound(fields);
// /* add the device name (identifier of the alarm) to the list
// * of the current alarms
// */
// ids << fields.at(AlarmTreeWidgetItem::Alarm);
// /// item = mGetItem(fields);
// item = mItemsHash.value(fields.at(AlarmTreeWidgetItem::Alarm));
// /* save current scroll bar value */
// scrollBarPos = ui->treeWidgetAlarms->verticalScrollBar()->value();
// if(!item) /* create a new item */
// {
// insertItem(fields, index);
// }
// else /* update fields of existing items */ {
// item->update(fields);
// }
// /* restore scrollbar value */
// ui->treeWidgetAlarms->verticalScrollBar()->setValue(scrollBarPos);
// if(!fields.at(AlarmTreeWidgetItem::Alarm).contains("internal_error_"))
// index++;
// }
// /* after items have been added, we have to remove stale items */
// mRemoveStaleItems(ids);
// if(filtering && ui->cBDynamic->isChecked())
// applyFilter();
// /* remove block signals */
// // ui->treeWidgetAlarms->blockSignals(false);
// // ui->treeWidgetAlarms->model()->blockSignals(false);
// //
// // ui->treeWidgetAlarms->setUpdatesEnabled(true);
// /* update tree */
// // ui->treeWidgetAlarms->repaint();
// /* remove block signals */
// // model->blockSignals(false);
// // model->dataChanged(model->index(0, 0), model->index(model->rowCount()-1, model->columnCount()-1));
// }
void Alarm::refresh(const CuData &da) {
ui->treeWidgetAlarms->refresh(da);
ui->treeWidgetInternalErrors->refresh(da);
if(filtering && ui->cBDynamic->isChecked())
applyFilter();
}
void Alarm::onNewProps(const CuData &da)
void Alarm::onDevProps(const CuData &da)
{
printf("Alarm:onNewProps: %s\n", datos(da));
if(da["err"].toBool()) {
perr("Alarm.onDevProps: error fetching database properties specified in src %s", vtoc2(da, "src"));
}
else {
if(da.containsKey("GroupNames")) {
const std::vector<std::string> &gnames = da["GroupNames"].toStringVector();
QStringList statesList;
for(unsigned long i = 0; i < gnames.size(); i++)
statesList << QString::fromStdString(gnames[i]).remove("gr_");
statesList << "all";
}
if(da.containsKey("InstanceName"))
instance_name = QuString(da, "InstanceName");
}
// dbd[0] >> gnames;
// dbd[1] >> s_instanceName;
// instance_name = QString::fromStdString(s_instanceName);
// delete db;
// QStringList statesList;
// for(unsigned long i = 0; i < gnames.size(); i++)
// statesList << QString::fromStdString(gnames[i]).remove("gr_");
// statesList << "all";
}
void Alarm::m_connect_devs(const CuData &da)
{
QStringList srcs;
foreach(const QString src, srcs) {
QuWatcher *alrw = new QuWatcher(this, cu_pool, m_ctrl_factory_pool);
alrw->setObjectName(src + "+watcher");
connect(alrw, SIGNAL(newData(CuData)), this, SLOT(refresh(CuData)));
alrw->setSource(device_name + "/alarm");
void Alarm::onDevList(const CuData &da) {
if(da["err"].toBool()) {
perr("Alarm.onDevList: error fetching device list from database: src: \"%s\" msg: \"%s\"", vtoc2(da, "src"), vtoc2(da, "msg"));
}
}
/* called with signals blocked for the tree and the model
*/
void Alarm::insertItem(const QStringList &list, int index)
{
qDebug() << __PRETTY_FUNCTION__ << "inserting " << list << index;
AlarmTreeWidgetItem *item;
QStringList fields(list);
bool isNew = false;
if(fields.size() > 0)
fields[AlarmTreeWidgetItem::DateTime] =
QDateTime::fromTime_t(list.at(AlarmTreeWidgetItem::DateTime).toUInt()).toString();
if(fields.at(AlarmTreeWidgetItem::Alarm).contains("internal_error_"))
item = new AlarmTreeWidgetItem(ui->treeWidgetInternalErrors, fields);
else
{
if(fields.last().toUpper() == "NEW"){
isNew = true;
}
fields.removeLast(); /* the last element contains info about "NEW", than must not be displayed */
// printf("\e[1;32m ADDING NEW AlarmTreeWidgetitem to index %d\e[0m\n", index);
item = new AlarmTreeWidgetItem(fields);
ui->treeWidgetAlarms->insertTopLevelItem(index, item);
item->setNew(isNew);
else {
QuStringList devs(da, "value");
m_connect_devs(devs);
}
/* add the couple identifier/AlarmTreeWidgetItem to the hash */
mItemsHash.insert(fields.at(AlarmTreeWidgetItem::Alarm), item);
}
void Alarm::mRemoveStaleItems(const QStringList& currentIds)
void Alarm::m_connect_devs(const QStringList &devs)
{
foreach(QString id, mItemsHash.keys())
{
if(!currentIds.contains(id))
{
AlarmTreeWidgetItem *item = mItemsHash.value(id);
if(item)
{
mItemsHash.remove(id);
delete item;
}
}
foreach(const QString dev, devs) {
QuWatcher *alrw = new QuWatcher(this, cu_pool, m_ctrl_factory_pool);
alrw->setObjectName(dev + "/alarm" + "+watcher");
connect(alrw, SIGNAL(newData(CuData)), this, SLOT(refresh(CuData)));
alrw->setSource(dev + "/alarm");
}
}
......@@ -357,7 +241,7 @@ QList<QTreeWidgetItem *> Alarm::mGetSelectedItems()
void Alarm::silence()
{
QList<QTreeWidgetItem *> selItems = mGetSelectedItems();
vector<string> toSilenceAlarms;
QStringList toSilenceAlarms;
if(selItems.size() == 0)
QMessageBox::information(this, "Information", "Select one or more items with the\n"
"mouse and then click again.\nMultiple selections are possible: just\n"
......@@ -368,52 +252,28 @@ void Alarm::silence()
{
QTreeWidgetItem *it = selItems[i];
if(it->columnCount() > AlarmTreeWidgetItem::Alarm)
toSilenceAlarms.push_back(it->text(AlarmTreeWidgetItem::Alarm).toStdString());
toSilenceAlarms.push_back(it->text(AlarmTreeWidgetItem::Alarm));
}
tangoStringListCommand(toSilenceAlarms, "Silence");
}
}
/*
AlarmTreeWidgetItem* Alarm::mGetItem(const QStringList& sl) const
{
if(sl.size() < 3)
return NULL;
const QString id = sl.at(2);
printf("size mappa %d\n", mItemsHash.size());
return mItemsHash.value(id);
}
*/
void Alarm::testSound()
{
void Alarm::testSound() {
sound->play();
}
void Alarm::playSound(const QStringList &splitted)
{
if(splitted.size() > 5 && splitted[3] == "ALARM" && splitted.last() == "NEW")
{
showNormal();
sound->play();
// d_systray->showMessage("Alarm detected", "An alarm has been detected.\n"
// "To stop the sound, click on the \"Stop sound\" button in the application\n"
// "Check the new alarm in the list, and click on this message to hide the baloon",
// QSystemTrayIcon::Critical, 60000);
}
void Alarm::beep() {
showNormal();
sound->play();
}
void Alarm::stopSound()
{
void Alarm::stopSound() {
sound->stop();
}
void Alarm::ack()
{
void Alarm::ack() {
QList<QTreeWidgetItem *> selItems = mGetSelectedItems();
vector<string> ackedAlarms;
QStringList ackedAlarms;
if(selItems.size() == 0)
QMessageBox::information(this, "Information", "Select one or more items with the\n"
"mouse and then click again.\nMultiple selections are possible: just\n"
......@@ -424,7 +284,7 @@ void Alarm::ack()
{
QTreeWidgetItem *it = selItems[i];
if(it->columnCount() > AlarmTreeWidgetItem::Alarm)
ackedAlarms.push_back(it->text(AlarmTreeWidgetItem::Alarm).toStdString());
ackedAlarms.push_back(it->text(AlarmTreeWidgetItem::Alarm));
}
tangoStringListCommand(ackedAlarms, "ack");
}
......@@ -442,7 +302,7 @@ void Alarm::ack()
void Alarm::ackAll()
{
QList<QTreeWidgetItem *>items;
vector<string> ackedAlarms;
QStringList ackedAlarms;
/* a method to gather all items is search on wildcard */
if(ui->treeWidgetAlarms->isVisible())
items = ui->treeWidgetAlarms->findItems("*", Qt::MatchWildcard);
......@@ -454,7 +314,7 @@ void Alarm::ackAll()
{
QTreeWidgetItem *it = items[i];
if(it->columnCount() > AlarmTreeWidgetItem::Alarm)
ackedAlarms.push_back(it->text(AlarmTreeWidgetItem::Alarm).toStdString());
ackedAlarms.push_back(it->text(AlarmTreeWidgetItem::Alarm));
}
tangoStringListCommand(ackedAlarms, "ack");
}
......@@ -462,31 +322,14 @@ void Alarm::ackAll()
QMessageBox::information(this, "Information", "No items are present on the list.\n"
"There must be at least one item in the window to be\n"
"able to remove it.");
}
void Alarm::tangoStringListCommand(vector<string> &names, const char *cmdname)
void Alarm::tangoStringListCommand(const QStringList &names, const char *cmdname)
{
Tango::DeviceProxy *dev = NULL;
string devname = device_name.toStdString();
Tango::DevVarStringArray data;
data << names;
Tango::DeviceData dd;
dd << names;
try
{
dev = new Tango::DeviceProxy(devname);
dev->command_inout(cmdname,dd);
delete dev;
}
catch(Tango::DevFailed &e)
{
QMessageBox::information(this, "Error sending the \"%1\" command",
QString("Error sending the command \"ack\" to the tango device\n"
"\"%2\"\nThe problem was:\n%3").
arg(cmdname).
arg(device_name).arg(tangoException(e)));
}
QuWriter *w = new QuWriter(this, cu_pool, m_ctrl_factory_pool);
w->setAutoDestroy(true);
w->setTarget(QString("%s->%s").arg(device_name).arg(cmdname));
w->execute(names);
}
void Alarm::applyFilter()
......@@ -528,22 +371,6 @@ void Alarm::clearFilter()
filtering = false;
}
QString Alarm::tangoException(Tango::DevFailed &e)