alarm.cpp 12.8 KB
Newer Older
Giacomo Strangolino's avatar
Giacomo Strangolino committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/***************************************************************************
 *   Copyright (C) 2007 by Claudio Scafuri, Giacomo Strangolino   *
 *   claudio@hyo   *
 *                                                                         *
 *   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 "alarm.h"
#include "filter.h"
Giacomo Strangolino's avatar
Giacomo Strangolino committed
24
#include "acmd.h"
Giacomo Strangolino's avatar
Giacomo Strangolino committed
25
26
27
28
29
30
31
32
33
#include "AlarmTreeWidget.h"
#include "AlarmTreeWidgetItem.h"
#include <QMessageBox>
#include <QDateTime>
#include <QHeaderView>
#include <QCloseEvent>
#include "AlarmHistoryTree.h"
#include <QDebug>
#include <QMap>
34
#include <QDesktopServices> // open url
Giacomo Strangolino's avatar
Giacomo Strangolino committed
35

36
37
38
39
40
41
42
43
44
// cumbia
#include <qulogimpl.h>
#include <cucontrolsfactorypool.h>
#include <cumbiapool.h>
#include <cuserviceprovider.h>
#include <cumacros.h>
#include <quapps.h>
#include <quwriter.h>
#include <quwatcher.h>
45
46
#include <qustring.h>
#include <qustringlist.h>
47
#include <QTimer>
48
49
50
// cumbia

Alarm::Alarm(CumbiaPool *cu_p, QWidget *parent) : QWidget(parent)
Giacomo Strangolino's avatar
Giacomo Strangolino committed
51
{
52
53
54
55
56
57
58
59
60
    // cumbia
    CuModuleLoader mloader(cu_p, &m_ctrl_factory_pool, &m_log_impl);
    cu_pool = cu_p;
    ui = new Ui::Alarm;
    ui->setupUi(this, cu_p, m_ctrl_factory_pool);

    // mloader.modules() to get the list of loaded modules
    // cumbia

Giacomo Strangolino's avatar
Giacomo Strangolino committed
61
62
63
    QString soundFileName, alarmSysTestServerName;
    QStringList args = qApp->arguments();

64
    connect(ui->pBAckAll, SIGNAL(clicked()), this, SLOT(ackAll()));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
65
    connect(ui->pBStopSound, SIGNAL(clicked()), this, SLOT(stopSound()));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
66
67

    /* silence alarm */
68
69
    connect(ui->treeWidgetAlarms, SIGNAL(silence()), this, SLOT(silence()));
    connect(ui->treeWidgetAlarms, SIGNAL(silence()), this, SLOT(stopSound()));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
70
    /* ack. Also uses QTWriter to impart StopNew command */
71
    connect(ui->treeWidgetAlarms, SIGNAL(ack()), this, SLOT(ack()));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
72

73
74
75
76
    connect(ui->pBApplyFilter, SIGNAL(clicked()), this, SLOT(applyFilter()));
    connect(ui->pBClearFilter, SIGNAL(clicked()), this, SLOT(clearFilter()));
    connect(ui->pBStopSound, SIGNAL(clicked()), this, SLOT(stopSound()));
    connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
77
78
79


    /* message label */
80
81
82
83
84
85
86
87
88
    ui->msgLabel->setVisible(false);
    connect(ui->treeWidgetAlarms, SIGNAL(message(QString)), ui->msgLabel, SLOT(setText(QString)));
    connect(ui->treeWidgetAlarms, SIGNAL(mouseOverItem(bool)), ui->msgLabel, SLOT(setVisible(bool)));

    ui->pBClearFilter->setDisabled(true);
    ui->tWGroup->sortItems(0, Qt::AscendingOrder);
    ui->tWGroup->header()->setHidden(true);
    ui->pBConfHistory->setHidden(true);

89
90
91
92
    // device list from Tango DB free prop
    QString devlist_prop;
    args.contains("--device-list-prop") && args.size() > args.indexOf("--device-list-prop") + 1
            ? devlist_prop = args.at(args.indexOf("--device-list-prop") + 1) : devlist_prop = "DeviceList";
93
    QuWatcher *db_dlist_w = new QuWatcher(this, cu_pool, m_ctrl_factory_pool); // device prop watcher
94
    db_dlist_w->setObjectName("free_prop_w");
95
96
97
    db_dlist_w->setSingleShot(true);
    db_dlist_w->setAutoDestroy(true);
    connect(db_dlist_w, SIGNAL(newData(CuData)), this, SLOT(onDevList(CuData)));
98
    db_dlist_w->setSource(QString("tango://#AlarmHandler#%1").arg(devlist_prop));
99

100
101
102
103
104
105
106
107
    // groups
    QuWatcher *grpW = new QuWatcher(this, cu_pool, m_ctrl_factory_pool);
    grpW->setObjectName("group_w");
    grpW->setSingleShot(true);
    grpW->setAutoDestroy(true);
    connect(grpW, SIGNAL(newData(CuData)), this, SLOT(onGroupList(CuData)));
    grpW->setSource(QString("tango://AlarmHandler(GroupNames)").arg(devlist_prop));

Giacomo Strangolino's avatar
Giacomo Strangolino committed
108
    //---------------------------------------------------------------------------------------
Giacomo Strangolino's avatar
Giacomo Strangolino committed
109
    if(args.contains("--alarm-test-devname") && args.size() > args.indexOf("--alarm-test-devname") + 1) {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
110
111
        alarmSysTestServerName = args.at(args.indexOf("--alarm-test-devname") + 1);
        // printf("\e[1;32m --alarm-test-devname specified: \"%s\"\e[0m\n", qstoc(alarmSysTestServerName));
112
113
        ui->tPBTestAlarm->setTarget(alarmSysTestServerName + "/alarm_test(true)");
        ui->tPBTestAlarmStop->setTarget(alarmSysTestServerName + "/alarm_test(false)");
Giacomo Strangolino's avatar
Giacomo Strangolino committed
114
    }
Giacomo Strangolino's avatar
Giacomo Strangolino committed
115
    else if(args.contains("--alarm-test-default-dev")) {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
116
        printf("no --alarm-test-devname specified: using ecrfpsa/alarmtest/0/alarm_test\n");
117
118
        ui->tPBTestAlarm->setTarget("ecrfpsa/alarmtest/0/alarm_test(true)");
        ui->tPBTestAlarmStop->setTarget("ecrfpsa/alarmtest/0/alarm_test(false)");
Giacomo Strangolino's avatar
Giacomo Strangolino committed
119
120
121
    }
    //---------------------------------------------------------------------------------------

Giacomo Strangolino's avatar
Giacomo Strangolino committed
122
    if(args.contains("--sound-file-name") && args.size() > args.indexOf("--sound-file-name")) {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
123
        soundFileName = args.at(args.indexOf("--sound-file-name") + 1);
124
        qDebug() <<"Sound file name: "<< soundFileName;
Giacomo Strangolino's avatar
Giacomo Strangolino committed
125
126
    }
    else
127
        printf("--> Alarm::Alarm: use \e[1;32m--sound-file-name path/to/sound_file_name.wav\e[0m to enable sounds\n");
Giacomo Strangolino's avatar
Giacomo Strangolino committed
128
    sound = new Sound(soundFileName);
129
130
131
132
    connect( ui->pBTestSoundOn,SIGNAL(clicked()), sound, SLOT(play()));
    connect( ui->pBTestSoundOff,SIGNAL(clicked()), sound, SLOT(stop()));
    ui->groupBoxFilter->setHidden(true);
    connect(ui->pBFilter, SIGNAL(toggled(bool)), ui->groupBoxFilter, SLOT(setVisible(bool)));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
133
134

    /* connections for filter group box */
135
136
137
138
139
    connect(ui->cBAck, SIGNAL(toggled(bool)), ui->rBAck, SLOT(setEnabled(bool)));
    connect(ui->cBAck, SIGNAL(toggled(bool)), ui->rBNack, SLOT(setEnabled(bool)));
    connect(ui->cBLevel, SIGNAL(toggled(bool)), ui->comboLog, SLOT(setEnabled(bool)));
    connect(ui->cBStatus, SIGNAL(toggled(bool)), ui->comboStatus, SLOT(setEnabled(bool)));
    connect(ui->cBGroup, SIGNAL(toggled(bool)), ui->tWGroup, SLOT(setEnabled(bool)));
140
141
    ui->pbInfo->setEnabled(false);
    ui->liViewInfo->setVisible(false);
142
    connect(ui->liViewInfo, SIGNAL(urlClicked(QString)), this, SLOT(openUrl(QString)));
143
144
    connect(ui->pbInfo, SIGNAL(toggled(bool)), this, SLOT(onInfoListViewVisibilityChange(bool)));
    connect(ui->treeWidgetAlarms, SIGNAL(itemSelectionChanged()), this, SLOT(onItemSelectionChange()));
145
    connect(ui->treeWidgetAlarms, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onItemDoubleClicked(QModelIndex)));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
146
    /* connections for test section */
147
148
    //connect(ui->pBTestSoundOn, SIGNAL(clicked()), this, SLOT(testSound()));
    //connect(ui->pBTestSoundOff, SIGNAL(clicked()), this, SLOT(stopSound()));
149
150
    /* sound: beep on new alarm */
    connect(ui->treeWidgetAlarms, SIGNAL(newAlarmDetected()), this, SLOT(beep()));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
151
152
}

153
154
Alarm::~Alarm() {
    if(sound) {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
155
156
157
        sound->stop();
        delete sound;
    }
158
}
Giacomo Strangolino's avatar
Giacomo Strangolino committed
159

160
161
162
163
void Alarm::refresh(const CuData &da) {
    ui->treeWidgetAlarms->refresh(da);
    if(filtering && ui->cBDynamic->isChecked())
        applyFilter();
164
}
Giacomo Strangolino's avatar
Giacomo Strangolino committed
165

166
167
168
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"));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
169
    }
170
171
172
    else {
        QuStringList devs(da, "value");
        m_connect_devs(devs);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
173
174
175
    }
}

176
177
178
179
180
181
182
183
void Alarm::onGroupList(const CuData &da) {
    if(!da["err"].toBool() && da.containsKey("value")) {
        foreach(QString g, QuStringList(da, "value"))
            new QTreeWidgetItem(ui->tWGroup, QStringList() << g.remove("gr_"));
    } else
        perr("Alarm.onGroupList: error fetching groups from %s: %s", vtoc2(da, "src"), vtoc2(da, "msg"));
}

184
void Alarm::m_connect_devs(const QStringList &devs) {
185
186
187
188
189
    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");
Giacomo Strangolino's avatar
Giacomo Strangolino committed
190
191
192
193
194
195
196
    }
}

QList<QTreeWidgetItem *> Alarm::mGetSelectedItems()
{
    QList<QTreeWidgetItem *> selItems;
    /* get the tree widget that is currently visible */
197
198
    if(ui->treeWidgetAlarms->isVisible())
        selItems = ui->treeWidgetAlarms->selectedItems();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
199
200
201
202
203
    return selItems;
}

void Alarm::silence()
{
Giacomo Strangolino's avatar
Giacomo Strangolino committed
204
205
    Acmd acmd;
    acmd.silence(ui->treeWidgetAlarms, false, cu_pool, m_ctrl_factory_pool);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
206
207
}

208
void Alarm::testSound() {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
209
210
211
    sound->play();
}

212
213
214
void Alarm::beep() {
    showNormal();
    sound->play();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
215
216
}

217
218
219
220
void Alarm::openUrl(const QString &u) const {
    QDesktopServices::openUrl(QUrl(u));
}

221
void Alarm::stopSound() {
222
223
    Acmd acmd;
    acmd.stop_new(ui->treeWidgetAlarms, true, cu_pool, m_ctrl_factory_pool);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
224
225
226
    sound->stop();
}

227
void Alarm::ack() {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
228
    Acmd acmd;
Giacomo Strangolino's avatar
Giacomo Strangolino committed
229
    acmd.ack(ui->treeWidgetAlarms, false, cu_pool, m_ctrl_factory_pool);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
230
231
}

Giacomo Strangolino's avatar
Giacomo Strangolino committed
232
void Alarm::ackAll() {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
233
    Acmd acmd;
Giacomo Strangolino's avatar
Giacomo Strangolino committed
234
    acmd.ack(ui->treeWidgetAlarms, true, cu_pool, m_ctrl_factory_pool);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
235
236
237
238
239
240
}

void Alarm::applyFilter()
{
    AlarmFilter filter;

241
    filter.ack_enable = ui->cBAck->isChecked();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
242
243

    if(filter.ack_enable)
244
        filter.ack = ui->rBAck->isChecked();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
245

246
    filter.lev = ui->cBLevel->isChecked();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
247
    if(filter.lev)
248
        filter.level = ui->comboLog->currentText();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
249

250
    filter.stat = ui->cBStatus->isChecked();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
251
    if(filter.stat)
252
        filter.status = ui->comboStatus->currentText();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
253

254
    filter.grp = ui->cBGroup->isChecked();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
255
256
    if(filter.grp)
    {
257
        QList<QTreeWidgetItem* >groups = ui->tWGroup->selectedItems();
Giacomo Strangolino's avatar
Giacomo Strangolino committed
258
259
260
        for(int i = 0; i < groups.size(); i++)
            filter.groups << groups[i]->text(0);
    }
261
    ui->treeWidgetAlarms->applyFilter(filter);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
262
    filtering = true;
263
    ui->pBClearFilter->setDisabled(false);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
264
265
}

266
void Alarm::clearFilter() {
267
268
269
    ui->treeWidgetAlarms->removeFilter();
    ui->pBClearFilter->setDisabled(true);
    ui->cBDynamic->setChecked(false);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
270
271
272
    filtering = false;
}

273
274
275
void Alarm::onInfoListViewVisibilityChange(bool vis) {
    if(!vis)
        ui->liViewInfo->activate("", "");
Giacomo Strangolino's avatar
Giacomo Strangolino committed
276
    else
277
278
279
280
        ui->treeWidgetAlarms->selectedItems().size() == 1 ?
                    ui->liViewInfo->activate(ui->treeWidgetAlarms->selectedItems().first()->data(AlarmTreeWidgetItem::Device, Qt::UserRole).toString(),
                                             ui->treeWidgetAlarms->selectedItems().first()->text(AlarmTreeWidgetItem::Alarm))
                  : ui->liViewInfo->activate("", "");
Giacomo Strangolino's avatar
Giacomo Strangolino committed
281
282
}

283
284
285
286
287
288
289
290
void Alarm::onItemSelectionChange() {
    QList<QTreeWidgetItem *> sits = ui->treeWidgetAlarms->selectedItems();
    QTreeWidgetItem *it = nullptr;
    if(sits.size() == 1)
        it = sits.first();
    ui->pbInfo->setEnabled(it != nullptr);
    if(ui->liViewInfo->isVisible() && it)
        ui->liViewInfo->activate(it->data(AlarmTreeWidgetItem::Device, Qt::UserRole).toString(), it->text(AlarmTreeWidgetItem::Alarm));
Giacomo Strangolino's avatar
Giacomo Strangolino committed
291
292
}

293
294
295
296
297
void Alarm::onItemDoubleClicked(const QModelIndex &mi) {
//    if(mi.column() == AlarmTreeWidgetItem::Alarm)
        ui->pbInfo->setChecked(true);
}

298
void Alarm::tabChanged(int t) {
Giacomo Strangolino's avatar
Giacomo Strangolino committed
299
    if(t == 1) {
300
301
302
303
304
305
306
        ui->pBAckAll->setHidden(true);
        ui->pBConfHistory->setHidden(false);
        ui->pBConfHistory->setChecked(true);
        ui->groupBoxFilter->setDisabled(true);
        ui->pBFilter->setHidden(true);
        ui->pBConfHistory->setHidden(true);
        ui->pBStopSound->setHidden(true);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
307
    }
Giacomo Strangolino's avatar
Giacomo Strangolino committed
308
    else if(t == 0) {
309
310
311
312
313
        ui->pBStopSound->setHidden(false);
        ui->pBAckAll->setHidden(false);
        ui->pBConfHistory->setHidden(true);
        ui->groupBoxFilter->setDisabled(false);
        ui->pBFilter->setHidden(false);
Giacomo Strangolino's avatar
Giacomo Strangolino committed
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
    }
}

void Alarm::closeEvent(QCloseEvent *e)
{
    int reply = QMessageBox::question(this, "Warning", "Are you really sure you want to close this application?\n"
                                                       "If you do, you will not receive alarm notifications",
                                      QMessageBox::Yes|QMessageBox::No);

    if(reply == QMessageBox::Yes)
        reply = QMessageBox::question(this, "Warning", "By closing this panel, I am aware that I will not receive"
                                                       "\nalarms from now on",
                                      QMessageBox::Yes|QMessageBox::Cancel);
    if(reply == QMessageBox::Yes)
        e->accept();

    else
        e->ignore();

}