4 #include <QProgressDialog>
6 #include "cetlib/filepath_maker.h"
7 #include "fhiclcpp/make_ParameterSet.h"
8 #include "fhiclcpp/ParameterSet.h"
10 #include "mfextensions/Binaries/mvdlg.hh"
13 #if GCC_VERSION >= 701000 || defined(__clang__)
14 #pragma GCC diagnostic push
15 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
20 #if GCC_VERSION >= 701000 || defined(__clang__)
21 #pragma GCC diagnostic pop
30 process_fname(std::string& fname)
32 size_t sub_start = fname.find(
"${");
33 size_t sub_end = fname.find(
"}");
35 const size_t npos = std::string::npos;
37 if ((sub_start == npos && sub_end != npos)
38 || (sub_start != npos && sub_end == npos)
39 || (sub_start > sub_end))
41 throw std::runtime_error(
"Unrecognized configuration file. Use default configuration instead.");
44 if (sub_start == npos)
return;
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);
52 static fhicl::ParameterSet
53 readConf(std::string
const& fname)
55 if (fname.empty())
return fhicl::ParameterSet();
57 std::string filename = fname;
58 process_fname(filename);
60 std::string env(
"FHICL_FILE_PATH=");
62 if (filename[0] ==
'/')
71 char* mfe_path = getenv(
"MFEXTENSIONS_DIR");
72 if (mfe_path) env.append(
":").append(mfe_path).append(
"/config");
74 putenv((
char *)env.c_str());
78 cet::filepath_lookup policy(
"FHICL_FILE_PATH");
81 fhicl::ParameterSet pset;
82 fhicl::make_ParameterSet(filename, policy, pset);
87 msgViewerDlg::msgViewerDlg(std::string
const& conf, QDialog* parent)
103 , sup_menu(new QMenu(this))
104 , thr_menu(new QMenu(this))
105 , receivers_(readConf(conf).get<fhicl::ParameterSet>(
"receivers", fhicl::ParameterSet()))
113 fhicl::ParameterSet pset = readConf(conf);
119 btnSuppression->setMenu(sup_menu);
120 btnThrottling->setMenu(thr_menu);
123 connect(btnPause, SIGNAL(clicked()),
this, SLOT(pause()));
124 connect(btnExit, SIGNAL(clicked()),
this, SLOT(exit()));
125 connect(btnClear, SIGNAL(clicked()),
this, SLOT(clear()));
127 connect(btnRMode, SIGNAL(clicked()),
this, SLOT(renderMode()));
128 connect(btnDisplayMode, SIGNAL(clicked()),
this, SLOT(shortMode()));
130 connect(btnSearch, SIGNAL(clicked()),
this, SLOT(searchMsg()));
131 connect(btnSearchClear,
132 SIGNAL(clicked()),
this, SLOT(searchClear()));
134 connect(btnFilter, SIGNAL(clicked()),
this, SLOT(setFilter()));
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()));
142 , SIGNAL(triggered(QAction*))
144 , SLOT(setSuppression(QAction*)));
147 , SIGNAL(triggered(QAction*))
149 , SLOT(setThrottling(QAction*)));
152 , SIGNAL(valueChanged(
int))
154 , SLOT(changeSeverity(
int)));
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);
168 QTabBar *tabBar = tabWidget->findChild<QTabBar *>();
169 tabBar->setTabButton(0, QTabBar::RightSide, 0);
170 tabBar->setTabButton(0, QTabBar::LeftSide, 0);
172 if (simpleRender) btnRMode->setChecked(
true);
173 else btnRMode->setChecked(
false);
175 btnRMode->setEnabled(
false);
177 changeSeverity(sevThresh);
179 QTextDocument* doc =
new QTextDocument(txtMessages);
180 txtMessages->setDocument(doc);
185 msgViewerDlg::~msgViewerDlg()
191 static void str_to_suppress(std::vector<std::string>
const& vs, std::vector<suppress>& s, QMenu* menu)
197 act = menu->addAction(
"None");
198 act->setEnabled(
false);
202 s.reserve(vs.size());
204 for (
size_t i = 0; i < vs.size(); ++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]);
215 static void pset_to_throttle(std::vector<fhicl::ParameterSet>
const& ps, std::vector<throttle>& t, QMenu* menu)
221 act = menu->addAction(
"None");
222 act->setEnabled(
false);
226 t.reserve(ps.size());
228 for (
size_t i = 0; i < ps.size(); ++i)
230 std::string name = ps[i].get<std::string>(
"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]);
242 void msgViewerDlg::parseConf(fhicl::ParameterSet
const& conf)
244 fhicl::ParameterSet nulp;
248 fhicl::ParameterSet sup = conf.get<fhicl::ParameterSet>(
"suppress", nulp);
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>());
254 str_to_suppress(sup_host, e_sup_host, sup_menu);
255 sup_menu->addSeparator();
257 str_to_suppress(sup_app, e_sup_app, sup_menu);
258 sup_menu->addSeparator();
260 str_to_suppress(sup_cat, e_sup_cat, sup_menu);
263 auto thr = conf.get<fhicl::ParameterSet>(
"throttle", nulp);
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>());
269 pset_to_throttle(thr_host, e_thr_host, thr_menu);
270 thr_menu->addSeparator();
272 pset_to_throttle(thr_app, e_thr_app, thr_menu);
273 thr_menu->addSeparator();
275 pset_to_throttle(thr_cat, e_thr_cat, thr_menu);
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; }
284 bool msgViewerDlg::msg_throttled(
qt_mf_msg const& mfmsg)
290 for (
size_t i = 0; i < e_sup_host.size(); ++i)
291 if (e_sup_host[i].match(mfmsg.
host().toStdString()))
294 for (
size_t i = 0; i < e_sup_app.size(); ++i)
295 if (e_sup_app[i].match(mfmsg.
app().toStdString()))
298 for (
size_t i = 0; i < e_sup_cat.size(); ++i)
299 if (e_sup_cat[i].match(mfmsg.
cat().toStdString()))
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()))
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()))
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()))
325 void msgViewerDlg::writeSettings()
327 QSettings settings(
"ARTDAQ",
"MsgViewer");
329 settings.beginGroup(
"MainWindow");
330 settings.setValue(
"size", size());
331 settings.setValue(
"pos", pos());
335 void msgViewerDlg::readSettings()
337 QSettings settings(
"ARTDAQ",
"MsgViewer");
339 settings.beginGroup(
"MainWindow");
340 QPoint pos = settings.value(
"pos", QPoint(100, 100)).toPoint();
341 QSize size = settings.value(
"size", QSize(660, 760)).toSize();
347 void msgViewerDlg::onNewMsg(
qt_mf_msg const& mfmsg)
354 lcdMsgs->display(nMsgs);
357 if (msg_throttled(mfmsg))
359 lcdSuppressionCount->display(nSupMsgs);
360 lcdThrottlingCount->display(nThrMsgs);
365 msg_pool_.emplace_back(mfmsg);
366 msgs_t::iterator it = --msg_pool_.end();
369 unsigned int flag = update_index(it);
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_);
376 for (
size_t d = 0; d < msgFilters_.size(); ++d)
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;
383 if (hostMatch && appMatch && catMatch)
385 msgFilters_[d].msgs.push_back(it);
391 unsigned int msgViewerDlg::update_index(msgs_t::iterator it)
393 QString
const& app = it->app();
394 QString
const& cat = it->cat();
395 QString
const& host = it->host();
397 unsigned int update = 0x0;
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;
403 cat_msgs_[cat].push_back(it);
404 host_msgs_[host].push_back(it);
405 app_msgs_[app].push_back(it);
411 void msgViewerDlg::displayMsg(msgs_t::const_iterator it,
int display)
413 if (it->sev() < sevThresh)
return;
415 msgFilters_[display].nDisplayMsgs++;
416 if (display == tabWidget->currentIndex())
418 lcdDisplayedMsgs->display(msgFilters_[display].nDisplayMsgs);
421 auto txt = it->text(shortMode_);
422 msgFilters_[display].txtDisplay->append(txt);
423 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
426 void msgViewerDlg::displayMsg(
int display)
429 msgFilters_[display].txtDisplay->clear();
430 msgFilters_[display].nDisplayMsgs = 0;
432 msg_iters_t::const_iterator it;
434 n = msgFilters_[display].msgs.size();
435 it = msgFilters_[display].msgs.begin();
436 QProgressDialog progress(
"Fetching data...",
"Cancel"
437 , 0, n / 1000,
this);
439 progress.setWindowModality(Qt::WindowModal);
440 progress.setMinimumDuration(2000);
447 for (; it != msgFilters_[display].msgs.end(); ++it, ++i)
449 if (it->get()->sev() >= sevThresh)
451 txt += it->get()->text(shortMode_);
452 ++msgFilters_[display].nDisplayMsgs;
459 progress.setValue(prog);
461 msgFilters_[display].txtDisplay->append(txt);
465 if (progress.wasCanceled())
469 if (display == tabWidget->currentIndex())
471 lcdDisplayedMsgs->display(msgFilters_[display].nDisplayMsgs);
474 msgFilters_[display].txtDisplay->append(txt);
475 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
480 void msgViewerDlg::updateDisplays()
482 for (
size_t ii = 0; ii < msgFilters_.size(); ++ii)
488 template <
typename M>
489 bool msgViewerDlg::updateList(QListWidget* lw, M
const& map)
491 bool nonSelectedBefore = (lw->currentRow() == -1);
492 bool nonSelectedAfter =
true;
494 QString item = nonSelectedBefore ?
"" : lw->currentItem()->text();
498 typename M::const_iterator it = map.begin();
500 while (it != map.end())
502 lw->addItem(it->first);
503 if (!nonSelectedBefore && nonSelectedAfter)
505 if (item == it->first)
507 lw->setCurrentRow(row);
508 nonSelectedAfter =
false;
515 if (!nonSelectedBefore && nonSelectedAfter)
return true;
520 msg_iters_t msgViewerDlg::list_intersect(msg_iters_t
const& l1, msg_iters_t
const& l2)
523 msg_iters_t::const_iterator it1 = l1.begin();
524 msg_iters_t::const_iterator it2 = l2.begin();
526 while (it1 != l1.end() && it2 != l2.end())
528 if (*it1 < *it2) { ++it1; }
529 else if (*it2 < *it1) { ++it2; }
532 output.push_back(*it1);
538 TLOG(10) <<
"list_intersect: output list has " << output.size() <<
" entries";
542 std::string sev_to_string(sev_code_t s)
558 void msgViewerDlg::setFilter()
560 auto hostFilter = toQStringList(lwHost->selectedItems());
561 auto appFilter = toQStringList(lwApplication->selectedItems());
562 auto catFilter = toQStringList(lwCategory->selectedItems());
564 lwHost->setCurrentRow(-1, QItemSelectionModel::Clear);
565 lwApplication->setCurrentRow(-1, QItemSelectionModel::Clear);
566 lwCategory->setCurrentRow(-1, QItemSelectionModel::Clear);
568 if (hostFilter.isEmpty()
569 && appFilter.isEmpty()
570 && catFilter.isEmpty())
576 QString catFilterExpression =
"";
577 QString hostFilterExpression =
"";
578 QString appFilterExpression =
"";
581 for (
auto app = 0; app < appFilter.size(); ++app)
583 msg_iters_map_t::const_iterator it = app_msgs_.find(appFilter[app]);
584 appFilterExpression += QString(first ?
"" :
" || ") + appFilter[app];
586 if (it != app_msgs_.end())
588 msg_iters_t temp(it->second);
589 TLOG(10) <<
"setFilter: app " << appFilter[app].toStdString() <<
" has " << temp.size() <<
" messages";
593 TLOG(10) <<
"setFilter: result contains %zu messages", result.size();
596 if (!hostFilter.isEmpty())
598 msg_iters_t hostResult;
599 for (
auto host = 0; host < hostFilter.size(); ++host)
601 hostFilterExpression += QString(first ?
"" :
" || ") + hostFilter[host];
603 msg_iters_map_t::const_iterator it = host_msgs_.find(hostFilter[host]);
604 if (it != host_msgs_.end())
606 msg_iters_t temp(it->second);
607 TLOG(10) <<
"setFilter: host " << hostFilter[host].toStdString() <<
" has " << temp.size() <<
" messages";
608 hostResult.merge(temp);
611 if (result.empty()) { result = hostResult; }
612 else { result = list_intersect(result, hostResult); }
613 TLOG(10) <<
"setFilter: result contains " << result.size() <<
" messages";
617 if (!catFilter.isEmpty())
619 msg_iters_t catResult;
620 for (
auto cat = 0; cat < catFilter.size(); ++cat)
622 catFilterExpression += QString(first ?
"" :
" || ") + catFilter[cat];
624 msg_iters_map_t::const_iterator it = cat_msgs_.find(catFilter[cat]);
625 if (it != cat_msgs_.end())
627 msg_iters_t temp(it->second);
628 TLOG(10) <<
"setFilter: cat " << catFilter[cat].toStdString() <<
" has " << temp.size() <<
" messages";
629 catResult.merge(temp);
632 if (result.empty()) { result = catResult; }
633 else { result = list_intersect(result, catResult); }
634 TLOG(10) <<
"setFilter: result contains " << result.size() <<
" messages";
638 auto nFilterExpressions = (appFilterExpression !=
"" ? 1 : 0) + (hostFilterExpression !=
"" ? 1 : 0) + (catFilterExpression !=
"" ? 1 : 0);
639 QString filterExpression =
"";
640 if (nFilterExpressions == 1)
642 filterExpression = catFilterExpression + hostFilterExpression + appFilterExpression;
646 filterExpression =
"(" + (catFilterExpression !=
"" ? catFilterExpression +
") && (" :
"")
647 + hostFilterExpression
648 + (hostFilterExpression !=
"" && appFilterExpression !=
"" ?
") && (" :
"")
649 + appFilterExpression +
")";
654 auto newTabTitle = QString(
"Filter ") + QString::number(++nFilters);
655 QWidget* newTab =
new QWidget();
657 QTextEdit* txtDisplay =
new QTextEdit(newTab);
658 QTextDocument* doc =
new QTextDocument(txtDisplay);
659 txtDisplay->setDocument(doc);
661 QVBoxLayout* layout =
new QVBoxLayout();
662 layout->addWidget(txtDisplay);
663 layout->setContentsMargins(0, 0, 0, 0);
664 newTab->setLayout(layout);
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);
675 tabWidget->addTab(newTab, newTabTitle);
676 tabWidget->setTabToolTip(tabWidget->count() - 1, filterExpression);
677 tabWidget->setCurrentIndex(tabWidget->count() - 1);
679 displayMsg(msgFilters_.size() - 1);
682 void msgViewerDlg::pause()
687 btnPause->setText(
"Resume");
693 btnPause->setText(
"Pause");
697 void msgViewerDlg::exit()
702 void msgViewerDlg::clear()
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);
707 case QMessageBox::Yes:
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_)
720 display.txtDisplay->clear();
721 display.msgs.clear();
722 display.nDisplayMsgs = 0;
725 lcdMsgs->display(nMsgs);
726 lcdDisplayedMsgs->display(0);
728 case QMessageBox::No:
734 void msgViewerDlg::shortMode()
739 btnDisplayMode->setText(
"Long View");
744 btnDisplayMode->setText(
"Compact View");
749 void msgViewerDlg::changeSeverity(
int sev)
765 default: setSevDebug();
771 void msgViewerDlg::setSevError()
774 btnError->setChecked(
true);
775 btnWarning->setChecked(
false);
776 btnInfo->setChecked(
false);
777 btnDebug->setChecked(
false);
778 vsSeverity->setValue(sevThresh);
781 void msgViewerDlg::setSevWarning()
783 sevThresh = SWARNING;
784 btnError->setChecked(
false);
785 btnWarning->setChecked(
true);
786 btnInfo->setChecked(
false);
787 btnDebug->setChecked(
false);
788 vsSeverity->setValue(sevThresh);
791 void msgViewerDlg::setSevInfo()
794 btnError->setChecked(
false);
795 btnWarning->setChecked(
false);
796 btnInfo->setChecked(
true);
797 btnDebug->setChecked(
false);
798 vsSeverity->setValue(sevThresh);
801 void msgViewerDlg::setSevDebug()
804 btnError->setChecked(
false);
805 btnWarning->setChecked(
false);
806 btnInfo->setChecked(
false);
807 btnDebug->setChecked(
true);
808 vsSeverity->setValue(sevThresh);
811 void msgViewerDlg::renderMode()
813 simpleRender = !simpleRender;
817 btnRMode->setChecked(
true);
818 for (
auto display : msgFilters_)
820 display.txtDisplay->setPlainText(display.txtDisplay->toPlainText());
825 btnRMode->setChecked(
false);
830 void msgViewerDlg::searchMsg()
832 QString search = editSearch->text();
834 if (search.isEmpty())
837 auto display = tabWidget->currentIndex();
838 if (search != searchStr)
840 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::Start);
841 if (!msgFilters_[display].txtDisplay->find(search))
843 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
851 if (!msgFilters_[display].txtDisplay->find(search))
853 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::Start);
854 if (!msgFilters_[display].txtDisplay->find(search))
856 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
863 void msgViewerDlg::searchClear()
865 auto display = tabWidget->currentIndex();
866 editSearch->setText(
"");
868 msgFilters_[display].txtDisplay->find(
"");
869 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
872 void msgViewerDlg::setSuppression(QAction* act)
874 bool status = act->isChecked();
879 void msgViewerDlg::setThrottling(QAction* act)
881 bool status = act->isChecked();
886 void msgViewerDlg::tabWidgetCurrentChanged(
int newTab)
888 lcdDisplayedMsgs->display(msgFilters_[newTab].nDisplayMsgs);
890 lwHost->setCurrentRow(-1, QItemSelectionModel::Clear);
891 lwApplication->setCurrentRow(-1, QItemSelectionModel::Clear);
892 lwCategory->setCurrentRow(-1, QItemSelectionModel::Clear);
894 for (
auto host : msgFilters_[newTab].hostFilter)
896 auto items = lwHost->findItems(host, Qt::MatchExactly);
897 if (items.size() > 0)
899 items[0]->setSelected(
true);
902 for (
auto app : msgFilters_[newTab].appFilter)
904 auto items = lwApplication->findItems(app, Qt::MatchExactly);
905 if (items.size() > 0)
907 items[0]->setSelected(
true);
910 for (
auto cat : msgFilters_[newTab].catFilter)
912 auto items = lwCategory->findItems(cat, Qt::MatchExactly);
913 if (items.size() > 0)
915 items[0]->setSelected(
true);
920 void msgViewerDlg::tabCloseRequested(
int tabIndex)
922 if (tabIndex == 0 || static_cast<size_t>(tabIndex) >= msgFilters_.size())
return;
924 auto widget = tabWidget->widget(tabIndex);
925 tabWidget->removeTab(tabIndex);
928 msgFilters_.erase(msgFilters_.begin() + tabIndex);
931 void msgViewerDlg::closeEvent(QCloseEvent* event)
936 QStringList msgViewerDlg::toQStringList(QList<QListWidgetItem *> in)
940 for (
auto i = 0; i < in.size(); ++i)
942 out << in[i]->text();
QString const & app() const
Get the application of the message
timeval time() const
Get the message timestamp
Qt wrapper around MessageFacility message
Suppress messages based on a regular expression
QString const & host() const
Get the host from which the message came
void use(bool flag)
Set whether the suppression is active
Throttle messages based on name and time limits. Separate from MessageFacility limiting.
QString const & cat() const
Get the category of the message