artdaq_mfextensions  v1_03_01
mvdlg.cc
1 #include <QtGui>
2 #include <QMenu>
3 #include <QMessageBox>
4 #include <QProgressDialog>
5 
6 #include "cetlib/filepath_maker.h"
7 #include "fhiclcpp/make_ParameterSet.h"
8 #include "fhiclcpp/ParameterSet.h"
9 
10 #include "mfextensions/Binaries/mvdlg.hh"
11 
12 
13 #if GCC_VERSION >= 701000 || defined(__clang__)
14 #pragma GCC diagnostic push
15 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
16 #endif
17 
18 #include "trace.h"
19 
20 #if GCC_VERSION >= 701000 || defined(__clang__)
21 #pragma GCC diagnostic pop
22 #endif
23 
24 
25 #include "mvdlg.hh"
26 
27 // replace the ${..} part in the filename with env variable
28 // throw if the env does not exist
29 static void
30 process_fname(std::string& fname)
31 {
32  size_t sub_start = fname.find("${");
33  size_t sub_end = fname.find("}");
34 
35  const size_t npos = std::string::npos;
36 
37  if ((sub_start == npos && sub_end != npos)
38  || (sub_start != npos && sub_end == npos)
39  || (sub_start > sub_end))
40  {
41  throw std::runtime_error("Unrecognized configuration file. Use default configuration instead.");
42  }
43 
44  if (sub_start == npos) return;
45 
46  std::string env = std::string(getenv(fname.substr(sub_start + 2, sub_end - sub_start - 2).c_str()));
47  fname.replace(sub_start, sub_end - sub_start + 1, env);
48 
49  //printf("%s\n", fname.c_str());
50 }
51 
52 static fhicl::ParameterSet
53 readConf(std::string const& fname)
54 {
55  if (fname.empty()) return fhicl::ParameterSet();
56 
57  std::string filename = fname;
58  process_fname(filename);
59 
60  std::string env("FHICL_FILE_PATH=");
61 
62  if (filename[0] == '/')
63  {
64  env.append("/");
65  }
66  else
67  {
68  env.append(".");
69  }
70 
71  char* mfe_path = getenv("MFEXTENSIONS_DIR");
72  if (mfe_path) env.append(":").append(mfe_path).append("/config");
73 
74  putenv((char *)env.c_str());
75 
76  //printf("%s\n", env.c_str());
77 
78  cet::filepath_lookup policy("FHICL_FILE_PATH");
79 
80  // it throws when the file is not parsable
81  fhicl::ParameterSet pset;
82  fhicl::make_ParameterSet(filename, policy, pset);
83 
84  return pset;
85 }
86 
87 msgViewerDlg::msgViewerDlg(std::string const& conf, QDialog* parent)
88  : QDialog(parent)
89  , updating(false)
90  , paused(false)
91  , shortMode_(false)
92  , nMsgs(0)
93  , nSupMsgs(0)
94  , nThrMsgs(0)
95  , nFilters(0)
96  , simpleRender(true)
97  , sevThresh(SINFO)
98  , searchStr("")
99  , msg_pool_()
100  , host_msgs_()
101  , cat_msgs_()
102  , app_msgs_()
103  , sup_menu(new QMenu(this))
104  , thr_menu(new QMenu(this))
105  , receivers_(readConf(conf).get<fhicl::ParameterSet>("receivers", fhicl::ParameterSet()))
106 {
107  setupUi(this);
108 
109  // window geo settings
110  readSettings();
111 
112  // read configuration file
113  fhicl::ParameterSet pset = readConf(conf);
114 
115  // parse configuration file
116  parseConf(pset);
117 
118  // associate menu with push buttons
119  btnSuppression->setMenu(sup_menu);
120  btnThrottling->setMenu(thr_menu);
121 
122  // slots
123  connect(btnPause, SIGNAL(clicked()), this, SLOT(pause()));
124  connect(btnExit, SIGNAL(clicked()), this, SLOT(exit()));
125  connect(btnClear, SIGNAL(clicked()), this, SLOT(clear()));
126 
127  connect(btnRMode, SIGNAL(clicked()), this, SLOT(renderMode()));
128  connect(btnDisplayMode, SIGNAL(clicked()), this, SLOT(shortMode()));
129 
130  connect(btnSearch, SIGNAL(clicked()), this, SLOT(searchMsg()));
131  connect(btnSearchClear,
132  SIGNAL(clicked()), this, SLOT(searchClear()));
133 
134  connect(btnFilter, SIGNAL(clicked()), this, SLOT(setFilter()));
135 
136  connect(btnError, SIGNAL(clicked()), this, SLOT(setSevError()));
137  connect(btnWarning, SIGNAL(clicked()), this, SLOT(setSevWarning()));
138  connect(btnInfo, SIGNAL(clicked()), this, SLOT(setSevInfo()));
139  connect(btnDebug, SIGNAL(clicked()), this, SLOT(setSevDebug()));
140 
141  connect(sup_menu
142  , SIGNAL(triggered(QAction*))
143  , this
144  , SLOT(setSuppression(QAction*)));
145 
146  connect(thr_menu
147  , SIGNAL(triggered(QAction*))
148  , this
149  , SLOT(setThrottling(QAction*)));
150 
151  connect(vsSeverity
152  , SIGNAL(valueChanged(int))
153  , this
154  , SLOT(changeSeverity(int)));
155 
156  connect(&receivers_
157  , SIGNAL(newMessage(qt_mf_msg const &))
158  , this
159  , SLOT(onNewMsg(qt_mf_msg const &)));
160 
161  connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabWidgetCurrentChanged(int)));
162  connect(tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)));
163  MsgFilterDisplay allMessages;
164  allMessages.txtDisplay = txtMessages;
165  msgFilters_.push_back(allMessages);
166 
167  //https://stackoverflow.com/questions/2616483/close-button-only-for-some-tabs-in-qt
168  QTabBar *tabBar = tabWidget->findChild<QTabBar *>();
169  tabBar->setTabButton(0, QTabBar::RightSide, 0);
170  tabBar->setTabButton(0, QTabBar::LeftSide, 0);
171 
172  if (simpleRender) btnRMode->setChecked(true);
173  else btnRMode->setChecked(false);
174 
175  btnRMode->setEnabled(false);
176 
177  changeSeverity(sevThresh);
178 
179  QTextDocument* doc = new QTextDocument(txtMessages);
180  txtMessages->setDocument(doc);
181 
182  receivers_.start();
183 }
184 
185 msgViewerDlg::~msgViewerDlg()
186 {
187  receivers_.stop();
188  writeSettings();
189 }
190 
191 static void str_to_suppress(std::vector<std::string> const& vs, std::vector<suppress>& s, QMenu* menu)
192 {
193  QAction* act;
194 
195  if (vs.empty())
196  {
197  act = menu->addAction("None");
198  act->setEnabled(false);
199  return;
200  }
201 
202  s.reserve(vs.size());
203 
204  for (size_t i = 0; i < vs.size(); ++i)
205  {
206  s.push_back(suppress(vs[i]));
207  act = menu->addAction(QString(vs[i].c_str()));
208  act->setCheckable(true);
209  act->setChecked(true);
210  QVariant v = qVariantFromValue((void*)&s[i]);
211  act->setData(v);
212  }
213 }
214 
215 static void pset_to_throttle(std::vector<fhicl::ParameterSet> const& ps, std::vector<throttle>& t, QMenu* menu)
216 {
217  QAction* act;
218 
219  if (ps.empty())
220  {
221  act = menu->addAction("None");
222  act->setEnabled(false);
223  return;
224  }
225 
226  t.reserve(ps.size());
227 
228  for (size_t i = 0; i < ps.size(); ++i)
229  {
230  std::string name = ps[i].get<std::string>("name");
231  t.push_back(throttle(name
232  , ps[i].get<int>("limit", -1)
233  , ps[i].get<long>("timespan", -1)));
234  act = menu->addAction(QString(name.c_str()));
235  act->setCheckable(true);
236  act->setChecked(true);
237  QVariant v = qVariantFromValue((void*)&t[i]);
238  act->setData(v);
239  }
240 }
241 
242 void msgViewerDlg::parseConf(fhicl::ParameterSet const& conf)
243 {
244  fhicl::ParameterSet nulp;
245  //QAction * act;
246 
247  // suppression list
248  fhicl::ParameterSet sup = conf.get<fhicl::ParameterSet>("suppress", nulp);
249 
250  auto sup_host = sup.get<std::vector<std::string>>("hosts", std::vector<std::string>());
251  auto sup_app = sup.get<std::vector<std::string>>("applications", std::vector<std::string>());
252  auto sup_cat = sup.get<std::vector<std::string>>("categories", std::vector<std::string>());
253 
254  str_to_suppress(sup_host, e_sup_host, sup_menu);
255  sup_menu->addSeparator();
256 
257  str_to_suppress(sup_app, e_sup_app, sup_menu);
258  sup_menu->addSeparator();
259 
260  str_to_suppress(sup_cat, e_sup_cat, sup_menu);
261 
262  // throttling list
263  auto thr = conf.get<fhicl::ParameterSet>("throttle", nulp);
264 
265  auto thr_host = thr.get<std::vector<fhicl::ParameterSet>>("hosts", std::vector<fhicl::ParameterSet>());
266  auto thr_app = thr.get<std::vector<fhicl::ParameterSet>>("applications", std::vector<fhicl::ParameterSet>());
267  auto thr_cat = thr.get<std::vector<fhicl::ParameterSet>>("categories", std::vector<fhicl::ParameterSet>());
268 
269  pset_to_throttle(thr_host, e_thr_host, thr_menu);
270  thr_menu->addSeparator();
271 
272  pset_to_throttle(thr_app, e_thr_app, thr_menu);
273  thr_menu->addSeparator();
274 
275  pset_to_throttle(thr_cat, e_thr_cat, thr_menu);
276 
277  auto lvl = conf.get<std::string>("threshold", "INFO");
278  if (lvl == "DEBUG" || lvl == "debug" || lvl == "0") { sevThresh = SDEBUG; }
279  if (lvl == "INFO" || lvl == "info" || lvl == "1") { sevThresh = SINFO; }
280  if (lvl == "WARN" || lvl == "warn" || lvl == "2") { sevThresh = SWARNING; }
281  if (lvl == "ERROR" || lvl == "error" || lvl == "3") { sevThresh = SERROR; }
282 }
283 
284 bool msgViewerDlg::msg_throttled(qt_mf_msg const& mfmsg)
285 {
286  // suppression list
287 
288  ++nSupMsgs;
289 
290  for (size_t i = 0; i < e_sup_host.size(); ++i)
291  if (e_sup_host[i].match(mfmsg.host().toStdString()))
292  return true;
293 
294  for (size_t i = 0; i < e_sup_app.size(); ++i)
295  if (e_sup_app[i].match(mfmsg.app().toStdString()))
296  return true;
297 
298  for (size_t i = 0; i < e_sup_cat.size(); ++i)
299  if (e_sup_cat[i].match(mfmsg.cat().toStdString()))
300  return true;
301 
302  --nSupMsgs;
303 
304  // throttling
305 
306  ++nThrMsgs;
307 
308  for (size_t i = 0; i < e_thr_host.size(); ++i)
309  if (e_thr_host[i].reach_limit(mfmsg.host().toStdString(), mfmsg.time()))
310  return true;
311 
312  for (size_t i = 0; i < e_thr_app.size(); ++i)
313  if (e_thr_app[i].reach_limit(mfmsg.app().toStdString(), mfmsg.time()))
314  return true;
315 
316  for (size_t i = 0; i < e_thr_cat.size(); ++i)
317  if (e_thr_cat[i].reach_limit(mfmsg.cat().toStdString(), mfmsg.time()))
318  return true;
319 
320  --nThrMsgs;
321 
322  return false;
323 }
324 
325 void msgViewerDlg::writeSettings()
326 {
327  QSettings settings("ARTDAQ", "MsgViewer");
328 
329  settings.beginGroup("MainWindow");
330  settings.setValue("size", size());
331  settings.setValue("pos", pos());
332  settings.endGroup();
333 }
334 
335 void msgViewerDlg::readSettings()
336 {
337  QSettings settings("ARTDAQ", "MsgViewer");
338 
339  settings.beginGroup("MainWindow");
340  QPoint pos = settings.value("pos", QPoint(100, 100)).toPoint();
341  QSize size = settings.value("size", QSize(660, 760)).toSize();
342  resize(size);
343  move(pos);
344  settings.endGroup();
345 }
346 
347 void msgViewerDlg::onNewMsg(qt_mf_msg const& mfmsg)
348 {
349  // 21-Aug-2015, KAB: copying the incrementing (and displaying) of the number
350  // of messages to here. I'm also not sure if we want to
351  // count all messages or just non-suppressed ones or what. But, at least this
352  // change gets the counter incrementing on the display.
353  ++nMsgs;
354  lcdMsgs->display(nMsgs);
355 
356  // test if the message is suppressed or throttled
357  if (msg_throttled(mfmsg))
358  {
359  lcdSuppressionCount->display(nSupMsgs);
360  lcdThrottlingCount->display(nThrMsgs);
361  return;
362  }
363 
364  // push the message to the message pool
365  msg_pool_.emplace_back(mfmsg);
366  msgs_t::iterator it = --msg_pool_.end();
367 
368  // update corresponding lists of index
369  unsigned int flag = update_index(it);
370 
371  // update gui list
372  if (flag & LIST_APP) updateList<msg_iters_map_t>(lwApplication, app_msgs_);
373  if (flag & LIST_CAT) updateList<msg_iters_map_t>(lwCategory, cat_msgs_);
374  if (flag & LIST_HOST) updateList<msg_iters_map_t>(lwHost, host_msgs_);
375 
376  for (size_t d = 0; d < msgFilters_.size(); ++d)
377  {
378  bool hostMatch = msgFilters_[d].hostFilter.contains(it->host(), Qt::CaseInsensitive) || msgFilters_[d].hostFilter.size() == 0;
379  bool appMatch = msgFilters_[d].appFilter.contains(it->app(), Qt::CaseInsensitive) || msgFilters_[d].appFilter.size() == 0;
380  bool catMatch = msgFilters_[d].catFilter.contains(it->cat(), Qt::CaseInsensitive) || msgFilters_[d].catFilter.size() == 0;
381 
382  // Check to display the message
383  if (hostMatch && appMatch && catMatch)
384  {
385  msgFilters_[d].msgs.push_back(it);
386  displayMsg(it, d);
387  }
388  }
389 }
390 
391 unsigned int msgViewerDlg::update_index(msgs_t::iterator it)
392 {
393  QString const& app = it->app();
394  QString const& cat = it->cat();
395  QString const& host = it->host();
396 
397  unsigned int update = 0x0;
398 
399  if (cat_msgs_.find(cat) == cat_msgs_.end()) update |= LIST_CAT;
400  if (host_msgs_.find(host) == host_msgs_.end()) update |= LIST_HOST;
401  if (app_msgs_.find(app) == app_msgs_.end()) update |= LIST_APP;
402 
403  cat_msgs_[cat].push_back(it);
404  host_msgs_[host].push_back(it);
405  app_msgs_[app].push_back(it);
406 
407  return update;
408 }
409 
410 
411 void msgViewerDlg::displayMsg(msgs_t::const_iterator it, int display)
412 {
413  if (it->sev() < sevThresh) return;
414 
415  msgFilters_[display].nDisplayMsgs++;
416  if (display == tabWidget->currentIndex())
417  {
418  lcdDisplayedMsgs->display(msgFilters_[display].nDisplayMsgs);
419  }
420 
421  auto txt = it->text(shortMode_);
422  msgFilters_[display].txtDisplay->append(txt);
423  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
424 }
425 
426 void msgViewerDlg::displayMsg(int display)
427 {
428  int n = 0;
429  msgFilters_[display].txtDisplay->clear();
430  msgFilters_[display].nDisplayMsgs = 0;
431 
432  msg_iters_t::const_iterator it;
433 
434  n = msgFilters_[display].msgs.size();
435  it = msgFilters_[display].msgs.begin();
436  QProgressDialog progress("Fetching data...", "Cancel"
437  , 0, n / 1000, this);
438 
439  progress.setWindowModality(Qt::WindowModal);
440  progress.setMinimumDuration(2000); // 2 seconds
441 
442  QString txt;
443  int i = 0, prog = 0;
444 
445  updating = true;
446 
447  for (; it != msgFilters_[display].msgs.end(); ++it, ++i)
448  {
449  if (it->get()->sev() >= sevThresh)
450  {
451  txt += it->get()->text(shortMode_);
452  ++msgFilters_[display].nDisplayMsgs;
453  }
454 
455  if (i == 1000)
456  {
457  i = 0;
458  ++prog;
459  progress.setValue(prog);
460 
461  msgFilters_[display].txtDisplay->append(txt);
462  txt.clear();
463  }
464 
465  if (progress.wasCanceled())
466  break;
467  }
468 
469  if (display == tabWidget->currentIndex())
470  {
471  lcdDisplayedMsgs->display(msgFilters_[display].nDisplayMsgs);
472  }
473 
474  msgFilters_[display].txtDisplay->append(txt);
475  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
476 
477  updating = false;
478 }
479 
480 void msgViewerDlg::updateDisplays()
481 {
482  for (size_t ii = 0; ii < msgFilters_.size(); ++ii)
483  {
484  displayMsg(ii);
485  }
486 }
487 
488 template <typename M>
489 bool msgViewerDlg::updateList(QListWidget* lw, M const& map)
490 {
491  bool nonSelectedBefore = (lw->currentRow() == -1);
492  bool nonSelectedAfter = true;
493 
494  QString item = nonSelectedBefore ? "" : lw->currentItem()->text();
495 
496  lw->clear();
497  int row = 0;
498  typename M::const_iterator it = map.begin();
499 
500  while (it != map.end())
501  {
502  lw->addItem(it->first);
503  if (!nonSelectedBefore && nonSelectedAfter)
504  {
505  if (item == it->first)
506  {
507  lw->setCurrentRow(row);
508  nonSelectedAfter = false;
509  }
510  }
511  ++row;
512  ++it;
513  }
514 
515  if (!nonSelectedBefore && nonSelectedAfter) return true;
516 
517  return false;
518 }
519 
520 msg_iters_t msgViewerDlg::list_intersect(msg_iters_t const& l1, msg_iters_t const& l2)
521 {
522  msg_iters_t output;
523  msg_iters_t::const_iterator it1 = l1.begin();
524  msg_iters_t::const_iterator it2 = l2.begin();
525 
526  while (it1 != l1.end() && it2 != l2.end())
527  {
528  if (*it1 < *it2) { ++it1; }
529  else if (*it2 < *it1) { ++it2; }
530  else
531  {
532  output.push_back(*it1);
533  ++it1;
534  ++it2;
535  }
536  }
537 
538  TLOG(10) << "list_intersect: output list has " << output.size() << " entries";
539  return output;
540 }
541 
542 std::string sev_to_string(sev_code_t s)
543 {
544  switch (s)
545  {
546  case SDEBUG:
547  return "DEBUG";
548  case SINFO:
549  return "INFO";
550  case SWARNING:
551  return "WARNING";
552  case SERROR:
553  return "ERROR";
554  }
555  return "UNKNOWN";
556 }
557 
558 void msgViewerDlg::setFilter()
559 {
560  auto hostFilter = toQStringList(lwHost->selectedItems());
561  auto appFilter = toQStringList(lwApplication->selectedItems());
562  auto catFilter = toQStringList(lwCategory->selectedItems());
563 
564  lwHost->setCurrentRow(-1, QItemSelectionModel::Clear);
565  lwApplication->setCurrentRow(-1, QItemSelectionModel::Clear);
566  lwCategory->setCurrentRow(-1, QItemSelectionModel::Clear);
567 
568  if (hostFilter.isEmpty()
569  && appFilter.isEmpty()
570  && catFilter.isEmpty())
571  {
572  return;
573  }
574 
575  msg_iters_t result;
576  QString catFilterExpression = "";
577  QString hostFilterExpression = "";
578  QString appFilterExpression = "";
579  bool first = true;
580 
581  for (auto app = 0; app < appFilter.size(); ++app)
582  { // app-sev index
583  msg_iters_map_t::const_iterator it = app_msgs_.find(appFilter[app]);
584  appFilterExpression += QString(first ? "" : " || ") + appFilter[app];
585  first = false;
586  if (it != app_msgs_.end())
587  {
588  msg_iters_t temp(it->second);
589  TLOG(10) << "setFilter: app " << appFilter[app].toStdString() << " has " << temp.size() << " messages";
590  result.merge(temp);
591  }
592  }
593  TLOG(10) << "setFilter: result contains %zu messages", result.size();
594 
595  first = true;
596  if (!hostFilter.isEmpty())
597  {
598  msg_iters_t hostResult;
599  for (auto host = 0; host < hostFilter.size(); ++host)
600  { // host index
601  hostFilterExpression += QString(first ? "" : " || ") + hostFilter[host];
602  first = false;
603  msg_iters_map_t::const_iterator it = host_msgs_.find(hostFilter[host]);
604  if (it != host_msgs_.end())
605  {
606  msg_iters_t temp(it->second);
607  TLOG(10) << "setFilter: host " << hostFilter[host].toStdString() << " has " << temp.size() << " messages";
608  hostResult.merge(temp);
609  }
610  }
611  if (result.empty()) { result = hostResult; }
612  else { result = list_intersect(result, hostResult); }
613  TLOG(10) << "setFilter: result contains " << result.size() << " messages";
614  }
615 
616  first = true;
617  if (!catFilter.isEmpty())
618  {
619  msg_iters_t catResult;
620  for (auto cat = 0; cat < catFilter.size(); ++cat)
621  { // cat index
622  catFilterExpression += QString(first ? "" : " || ") + catFilter[cat];
623  first = false;
624  msg_iters_map_t::const_iterator it = cat_msgs_.find(catFilter[cat]);
625  if (it != cat_msgs_.end())
626  {
627  msg_iters_t temp(it->second);
628  TLOG(10) << "setFilter: cat " << catFilter[cat].toStdString() << " has " << temp.size() << " messages";
629  catResult.merge(temp);
630  }
631  }
632  if (result.empty()) { result = catResult; }
633  else { result = list_intersect(result, catResult); }
634  TLOG(10) << "setFilter: result contains " << result.size() << " messages";
635  }
636 
637  // Create the filter expression
638  auto nFilterExpressions = (appFilterExpression != "" ? 1 : 0) + (hostFilterExpression != "" ? 1 : 0) + (catFilterExpression != "" ? 1 : 0);
639  QString filterExpression = "";
640  if (nFilterExpressions == 1)
641  {
642  filterExpression = catFilterExpression + hostFilterExpression + appFilterExpression;
643  }
644  else
645  {
646  filterExpression = "(" + (catFilterExpression != "" ? catFilterExpression + ") && (" : "")
647  + hostFilterExpression
648  + (hostFilterExpression != "" && appFilterExpression != "" ? ") && (" : "")
649  + appFilterExpression + ")";
650  }
651 
652  // Add the tab and populate it
653 
654  auto newTabTitle = QString("Filter ") + QString::number(++nFilters);
655  QWidget* newTab = new QWidget();
656 
657  QTextEdit* txtDisplay = new QTextEdit(newTab);
658  QTextDocument* doc = new QTextDocument(txtDisplay);
659  txtDisplay->setDocument(doc);
660 
661  QVBoxLayout* layout = new QVBoxLayout();
662  layout->addWidget(txtDisplay);
663  layout->setContentsMargins(0, 0, 0, 0);
664  newTab->setLayout(layout);
665 
666  MsgFilterDisplay filteredMessages;
667  filteredMessages.msgs = result;
668  filteredMessages.hostFilter = hostFilter;
669  filteredMessages.appFilter = appFilter;
670  filteredMessages.catFilter = catFilter;
671  filteredMessages.txtDisplay = txtDisplay;
672  filteredMessages.nDisplayMsgs = result.size();
673  msgFilters_.push_back(filteredMessages);
674 
675  tabWidget->addTab(newTab, newTabTitle);
676  tabWidget->setTabToolTip(tabWidget->count() - 1, filterExpression);
677  tabWidget->setCurrentIndex(tabWidget->count() - 1);
678 
679  displayMsg(msgFilters_.size() - 1);
680 }
681 
682 void msgViewerDlg::pause()
683 {
684  if (!paused)
685  {
686  paused = true;
687  btnPause->setText("Resume");
688  //QMessageBox::about(this, "About MsgViewer", "Message receiving paused ...");
689  }
690  else
691  {
692  paused = false;
693  btnPause->setText("Pause");
694  }
695 }
696 
697 void msgViewerDlg::exit()
698 {
699  close();
700 }
701 
702 void msgViewerDlg::clear()
703 {
704  int ret = QMessageBox::question(this, tr("Message Viewer"), tr("Are you sure you want to clear all received messages?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
705  switch (ret)
706  {
707  case QMessageBox::Yes:
708  nMsgs = 0;
709  nSupMsgs = 0;
710  nThrMsgs = 0;
711  msg_pool_.clear();
712  host_msgs_.clear();
713  cat_msgs_.clear();
714  app_msgs_.clear();
715  updateList<msg_iters_map_t>(lwApplication, app_msgs_);
716  updateList<msg_iters_map_t>(lwCategory, cat_msgs_);
717  updateList<msg_iters_map_t>(lwHost, host_msgs_);
718  for (auto& display : msgFilters_)
719  {
720  display.txtDisplay->clear();
721  display.msgs.clear();
722  display.nDisplayMsgs = 0;
723  }
724 
725  lcdMsgs->display(nMsgs);
726  lcdDisplayedMsgs->display(0);
727  break;
728  case QMessageBox::No:
729  default:
730  break;
731  }
732 }
733 
734 void msgViewerDlg::shortMode()
735 {
736  if (!shortMode_)
737  {
738  shortMode_ = true;
739  btnDisplayMode->setText("Long View");
740  }
741  else
742  {
743  shortMode_ = false;
744  btnDisplayMode->setText("Compact View");
745  }
746  updateDisplays();
747 }
748 
749 void msgViewerDlg::changeSeverity(int sev)
750 {
751  switch (sev)
752  {
753  case SERROR:
754  setSevError();
755  break;
756 
757  case SWARNING:
758  setSevWarning();
759  break;
760 
761  case SINFO:
762  setSevInfo();
763  break;
764 
765  default: setSevDebug();
766  }
767 
768  updateDisplays();
769 }
770 
771 void msgViewerDlg::setSevError()
772 {
773  sevThresh = SERROR;
774  btnError->setChecked(true);
775  btnWarning->setChecked(false);
776  btnInfo->setChecked(false);
777  btnDebug->setChecked(false);
778  vsSeverity->setValue(sevThresh);
779 }
780 
781 void msgViewerDlg::setSevWarning()
782 {
783  sevThresh = SWARNING;
784  btnError->setChecked(false);
785  btnWarning->setChecked(true);
786  btnInfo->setChecked(false);
787  btnDebug->setChecked(false);
788  vsSeverity->setValue(sevThresh);
789 }
790 
791 void msgViewerDlg::setSevInfo()
792 {
793  sevThresh = SINFO;
794  btnError->setChecked(false);
795  btnWarning->setChecked(false);
796  btnInfo->setChecked(true);
797  btnDebug->setChecked(false);
798  vsSeverity->setValue(sevThresh);
799 }
800 
801 void msgViewerDlg::setSevDebug()
802 {
803  sevThresh = SDEBUG;
804  btnError->setChecked(false);
805  btnWarning->setChecked(false);
806  btnInfo->setChecked(false);
807  btnDebug->setChecked(true);
808  vsSeverity->setValue(sevThresh);
809 }
810 
811 void msgViewerDlg::renderMode()
812 {
813  simpleRender = !simpleRender;
814 
815  if (simpleRender)
816  {
817  btnRMode->setChecked(true);
818  for (auto display : msgFilters_)
819  {
820  display.txtDisplay->setPlainText(display.txtDisplay->toPlainText());
821  }
822  }
823  else
824  {
825  btnRMode->setChecked(false);
826  updateDisplays();
827  }
828 }
829 
830 void msgViewerDlg::searchMsg()
831 {
832  QString search = editSearch->text();
833 
834  if (search.isEmpty())
835  return;
836 
837  auto display = tabWidget->currentIndex();
838  if (search != searchStr)
839  {
840  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::Start);
841  if (!msgFilters_[display].txtDisplay->find(search))
842  {
843  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
844  searchStr = "";
845  }
846  else
847  searchStr = search;
848  }
849  else
850  {
851  if (!msgFilters_[display].txtDisplay->find(search))
852  {
853  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::Start);
854  if (!msgFilters_[display].txtDisplay->find(search))
855  {
856  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
857  searchStr = "";
858  }
859  }
860  }
861 }
862 
863 void msgViewerDlg::searchClear()
864 {
865  auto display = tabWidget->currentIndex();
866  editSearch->setText("");
867  searchStr = "";
868  msgFilters_[display].txtDisplay->find("");
869  msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
870 }
871 
872 void msgViewerDlg::setSuppression(QAction* act)
873 {
874  bool status = act->isChecked();
875  suppress* sup = (suppress *)act->data().value<void*>();
876  sup->use(status);
877 }
878 
879 void msgViewerDlg::setThrottling(QAction* act)
880 {
881  bool status = act->isChecked();
882  throttle* thr = (throttle *)act->data().value<void*>();
883  thr->use(status);
884 }
885 
886 void msgViewerDlg::tabWidgetCurrentChanged(int newTab)
887 {
888  lcdDisplayedMsgs->display(msgFilters_[newTab].nDisplayMsgs);
889 
890  lwHost->setCurrentRow(-1, QItemSelectionModel::Clear);
891  lwApplication->setCurrentRow(-1, QItemSelectionModel::Clear);
892  lwCategory->setCurrentRow(-1, QItemSelectionModel::Clear);
893 
894  for (auto host : msgFilters_[newTab].hostFilter)
895  {
896  auto items = lwHost->findItems(host, Qt::MatchExactly);
897  if (items.size() > 0)
898  {
899  items[0]->setSelected(true);
900  }
901  }
902  for (auto app : msgFilters_[newTab].appFilter)
903  {
904  auto items = lwApplication->findItems(app, Qt::MatchExactly);
905  if (items.size() > 0)
906  {
907  items[0]->setSelected(true);
908  }
909  }
910  for (auto cat : msgFilters_[newTab].catFilter)
911  {
912  auto items = lwCategory->findItems(cat, Qt::MatchExactly);
913  if (items.size() > 0)
914  {
915  items[0]->setSelected(true);
916  }
917  }
918 }
919 
920 void msgViewerDlg::tabCloseRequested(int tabIndex)
921 {
922  if (tabIndex == 0 || static_cast<size_t>(tabIndex) >= msgFilters_.size()) return;
923 
924  auto widget = tabWidget->widget(tabIndex);
925  tabWidget->removeTab(tabIndex);
926  delete widget;
927 
928  msgFilters_.erase(msgFilters_.begin() + tabIndex);
929 }
930 
931 void msgViewerDlg::closeEvent(QCloseEvent* event)
932 {
933  event->accept();
934 }
935 
936 QStringList msgViewerDlg::toQStringList(QList<QListWidgetItem *> in)
937 {
938  QStringList out;
939 
940  for (auto i = 0; i < in.size(); ++i)
941  {
942  out << in[i]->text();
943  }
944 
945  return out;
946 }
QString const & app() const
Get the application of the message
Definition: qt_mf_msg.hh:79
timeval time() const
Get the message timestamp
Definition: qt_mf_msg.hh:84
Qt wrapper around MessageFacility message
Definition: qt_mf_msg.hh:37
Suppress messages based on a regular expression
Definition: suppress.hh:13
QString const & host() const
Get the host from which the message came
Definition: qt_mf_msg.hh:69
void use(bool flag)
Set whether the suppression is active
Definition: suppress.hh:33
Throttle messages based on name and time limits. Separate from MessageFacility limiting.
Definition: throttle.hh:17
QString const & cat() const
Get the category of the message
Definition: qt_mf_msg.hh:74