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