HAL
logger_widget.cpp
Go to the documentation of this file.
5 #include "gui/toolbar/toolbar.h"
9 
10 #include <QHeaderView>
11 #include <QVBoxLayout>
12 #include <QSignalMapper>
13 #include <QPushButton>
14 #include <QLabel>
15 #include <QSpacerItem>
16 #include <QLineEdit>
17 #include <QAction>
18 #include <QDebug>
19 
20 #include <string>
21 #include <QRegularExpression>
22 #include <iostream>
23 
24 namespace hal
25 {
27  {
28  // Active QPropertys
30 
31  mPlainTextEdit = new QPlainTextEdit(this);
32  mPlainTextEdit->setReadOnly(true);
33  mPlainTextEdit->setFrameStyle(QFrame::NoFrame);
34 
35  mPlainTextEditScrollbar = mPlainTextEdit->verticalScrollBar();
36  scrollToBottom();
37  mUserInteractedWithScrollbar = false;
38 
39  mLogMarshall = new LoggerMarshall(mPlainTextEdit);
40  mContentLayout->addWidget(mPlainTextEdit);
41 
43  // Get last severity settings
44  restoreSettings();
45 
46  mSearchbar = new Searchbar(mPlainTextEdit);
47  mSearchbar->hide();
48  mContentLayout->addWidget(mSearchbar);
49  mSearchOptions = 8;
50 
52 
54  connect(model, SIGNAL(updated(spdlog::level::level_enum, std::string, std::string)), this, SLOT(handleChannelUpdated(spdlog::level::level_enum, std::string, std::string)));
55  }
56 
58  {
59 
60  }
61 
63  {
64  // Action button to activate Searchbar
65  mSearchAction = new QAction(this);
66  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
67  toolbar->addAction(mSearchAction);
68 
69  // Show current channel
70  mChannelLabel = new QLabel(this);
71  mChannelLabel->setText("all");
72  toolbar->addWidget(mChannelLabel);
73 
74  // ChannelSelector
75  mSelector = new ChannelSelector(this);
76  mSelector->setEditable(true);
77  connect(mSelector->lineEdit(), SIGNAL(editingFinished()), this, SLOT(handleCustomChannel()));
78  connect(mSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(handleCurrentFilterChanged(int)));
79 // mSelector->setStyleSheet("QCombobox {background-color : rgb(32, 43, 63); border-radius: 2px;}");
81  toolbar->addWidget(mSelector);
82 
83  // Severity buttons
84  mDebugButton = new QPushButton("Debug", this);
85  mDebugButton->setCheckable(true);
86  mDebugButton->setChecked(mDebugSeverity);
87 // mDebugButton->setStyleSheet("QPushButton { border : none; background-color : rgb(26, 26, 26) } QPushButton:hover { background-color : rgb(46, 46, 46) } QPushButton:checked:hover { background-color : rgb(66, 66, 66) } QPushButton:checked { background-color : rgb(89, 89, 89); color : rgb(204, 204, 204)} ");
88  toolbar->addWidget(mDebugButton);
89 
90  mInfoButton = new QPushButton("Info", this);
91  mInfoButton->setCheckable(true);
92  mInfoButton->setChecked(mInfoSeverity);
93 // mInfoButton->setStyleSheet("QPushButton { border : none; background-color : rgb(26, 26, 26) } QPushButton:hover { background-color : rgb(46, 46, 46) } QPushButton:checked:hover { background-color : rgb(66, 66, 66) } QPushButton:checked { background-color : rgb(89, 89, 89); color : rgb(204, 204, 204)} ");
94  toolbar->addWidget(mInfoButton);
95 
96  mWarningButton = new QPushButton("Warning", this);
97  mWarningButton->setCheckable(true);
98  mWarningButton->setChecked(mWarningSeverity);
99 // mWarningButton->setStyleSheet("QPushButton { border : none; background-color : rgb(26, 26, 26) } QPushButton:hover { background-color : rgb(46, 46, 46) } QPushButton:checked:hover { background-color : rgb(66, 66, 66) } QPushButton:checked { background-color : rgb(89, 89, 89); color : rgb(204, 204, 204)} ");
100  toolbar->addWidget(mWarningButton);
101 
102  mErrorButton = new QPushButton("Error", this);
103  mErrorButton->setCheckable(true);
104  mErrorButton->setChecked(mErrorSeverity);
105 // mErrorButton->setStyleSheet("QPushButton { border : none; background-color : rgb(26, 26, 26) } QPushButton:hover { background-color : rgb(46, 46, 46) } QPushButton:checked:hover { background-color : rgb(66, 66, 66) } QPushButton:checked { background-color : rgb(89, 89, 89); color : rgb(204, 204, 204)} ");
106  toolbar->addWidget(mErrorButton);
107 
108  toolbar->addSpacer();
109 
110  mMuteButton = new QPushButton("Mute all", this);
111 // mMuteButton->setStyleSheet("QPushButton { border : none; background-color : rgb(26, 26, 26) } QPushButton:hover { background-color : rgb(46, 46, 46) } QPushButton:pressed { background-color : rgb(89, 89, 89); color : rgb(204, 204, 204)} ");
112  toolbar->addWidget(mMuteButton);
113 
114  mVerboseButton = new QPushButton("Show all", this);
115 // mVerboseButton->setStyleSheet("QPushButton { border : none; background-color : rgb(26, 26, 26) } QPushButton:hover { background-color : rgb(46, 46, 46) } QPushButton:pressed { background-color : rgb(89, 89, 89); color : rgb(204, 204, 204)} ");
116  toolbar->addWidget(mVerboseButton);
117 
118  connect(mSearchAction, SIGNAL(triggered()), this, SLOT(toggleSearchbar()));
119  connect(mSearchbar, SIGNAL(triggerNewSearch(QString, int)), this, SLOT(handleSearchChanged(QString, int)));
120  connect(mDebugButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
121  connect(mInfoButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
122  connect(mWarningButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
123  connect(mErrorButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
124  connect(mMuteButton, SIGNAL(clicked(bool)), this, SLOT(handleSeverityChanged(bool)));
125  connect(mVerboseButton, SIGNAL(clicked(bool)), this, SLOT(handleSeverityChanged(bool)));
126 
127  toolbar->repolish();
128  }
129 
131  {
132  return mPlainTextEdit;
133  }
134 
135  void LoggerWidget::handleCurrentChannelUpdated(spdlog::level::level_enum t, const QString& msg)
136  {
137  mLogMarshall->appendLog(t, msg);
138  }
139 
140  void LoggerWidget::handleChannelUpdated(spdlog::level::level_enum t, const std::string& logger_name, const std::string& msg)
141  {
142  if (mCurrentChannel == "")
143  {
145  }
146  if (logger_name != mCurrentChannel)
147  return;
148 
149 
150  bool filter = false;
151  if ((t == spdlog::level::level_enum::info) && mInfoSeverity) {
152  filter = true;
153  }
154  else if ((t == spdlog::level::level_enum::warn) && mWarningSeverity) {
155  filter = true;
156  }
157  else if ((t == spdlog::level::level_enum::err) && mErrorSeverity) {
158  filter = true;
159  }
160  else if ((t == spdlog::level::level_enum::debug) && mDebugSeverity) {
161  filter = true;
162  }
163  else if (t == spdlog::level::level_enum::critical) {
164  filter = true;
165  }
166 
167  if (filter)
168  {
169  mLogMarshall->appendLog(t, QString::fromStdString(msg));
170  }
171  }
172 
173  bool LoggerWidget::isMatching(QString searchString, QString stringToCheck)
174  {
175  if(!mSearchOptions.isExactMatch() && !mSearchOptions.isRegularExpression()){
176  //check if stringToCheck contains the searchString
177  return stringToCheck.contains(searchString, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
178  }
179  else if(mSearchOptions.isExactMatch()){
180  //check if the stringToCheck is the same as the searchString - also checks CaseSensitivity
181 
182  return 0 == QString::compare(searchString, stringToCheck, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
183  }
184  else if(mSearchOptions.isRegularExpression()){
185  //checks if the stringToCheck matches the regEx given by searchString
187  return regEx.match(stringToCheck).hasMatch();
188  }
189  return false;
190  }
191 
193  {
195 
196  // Channel has been changed or initially set
197  if ((sender() == mSelector) || p == 0) {
198  mCurrentChannelIndex = p;
199  }
200 
201  // Set "all" Channel
202  if (p == -1) {
203  mCurrentChannelIndex = model->rowCount() - 1;
204  }
205 
206  if (mCurrentChannelIndex == -2) {
207  return;
208  }
209 
210  ChannelItem* item = static_cast<ChannelItem*>((model->index(mCurrentChannelIndex, 0, QModelIndex())).internalPointer());
211  mCurrentChannel = item->name().toStdString();
212  mChannelLabel->setText(QString::fromStdString(mCurrentChannel));
213  mSelector->setCurrentText(QString::fromStdString(mCurrentChannel));
214 
215  mPlainTextEdit->clear();
216  QWriteLocker item_locker(item->getLock());
217 
218  // Iterate through every log entry
219  for (ChannelEntry* entry : *(item->getEntries()))
220  {
221  bool filter = false;
222  // If entry msg matches with search string
223  //QRegularExpression re(mSearchFilter);
224  if (isMatching(mSearchFilter, QString::fromStdString(entry->mMsg)))
225  {
226  // If entry severity matches the choosen severitys
227  if ((entry->mMsgType == spdlog::level::level_enum::info) && mInfoSeverity) {
228  filter = true;
229  }
230  else if ((entry->mMsgType == spdlog::level::level_enum::warn) && mWarningSeverity) {
231  filter = true;
232  }
233  else if ((entry->mMsgType == spdlog::level::level_enum::err) && mErrorSeverity) {
234  filter = true;
235  }
236  else if ((entry->mMsgType == spdlog::level::level_enum::debug) && mDebugSeverity) {
237  filter = true;
238  }
239  else if (entry->mMsgType == spdlog::level::level_enum::critical) {
240  filter = true;
241  }
242  }
243 
244  // If log entry should be shown
245  if (filter)
246  {
247  mLogMarshall->appendLog(entry->mMsgType, QString::fromStdString(entry->mMsg));
248  }
249  }
250  }
251 
253  {
254 
255  // change Severitys
256  if (sender() == mDebugButton)
257  {
258  mDebugSeverity = state;
259  }
260  else if (sender() == mInfoButton)
261  {
262  mInfoSeverity = state;
263  }
264  else if (sender() == mWarningButton)
265  {
266  mWarningSeverity = state;
267  }
268  else if (sender() == mErrorButton)
269  {
270  mErrorSeverity = state;
271  }
272  else if (sender() == mMuteButton)
273  {
274  mDebugButton->setChecked(false);
275  mInfoButton->setChecked(false);
276  mWarningButton->setChecked(false);
277  mErrorButton->setChecked(false);
278  }
279  else if (sender() == mVerboseButton)
280  {
281  mDebugButton->setChecked(true);
282  mInfoButton->setChecked(true);
283  mWarningButton->setChecked(true);
284  mErrorButton->setChecked(true);
285  // "all" channel
287  }
288 
289  // Make changes
291 
292  // Save severity settings for next session
293  saveSettings();
294  }
295 
296  void LoggerWidget::handleSearchChanged(QString filter, int searchOptions)
297  {
298  mSearchFilter = filter;
299  std::cout << mSearchFilter.QString::toStdString() << std::endl;
300  mSearchOptions = SearchOptions(searchOptions);
302  }
303 
305  {
306  Q_UNUSED(value);
307 
308  if (!mUserInteractedWithScrollbar)
309  mUserInteractedWithScrollbar = true;
310  }
311 
313  {
314  QString txt = mSelector->lineEdit()->text();
315  if (txt.isEmpty()) return;
316  std::string channel_name = txt.toStdString();
318  model->handleLogmanagerCallback(spdlog::level::level_enum::debug , channel_name, channel_name + " has manually been added to channellist");
319  }
320 
322  {
323  Q_UNUSED(event)
324 
325  if (!mUserInteractedWithScrollbar)
326  scrollToBottom();
327  }
328 
329  void LoggerWidget::scrollToBottom()
330  {
331  mPlainTextEditScrollbar->setValue(mPlainTextEditScrollbar->maximum());
332  }
333 
334  void LoggerWidget::saveSettings()
335  {
336  LoggerSettings settings = { mDebugSeverity, mInfoSeverity, mWarningSeverity, mErrorSeverity };
338  }
339 
340  void LoggerWidget::restoreSettings()
341  {
342  LoggerSettings settings = SettingsManager::instance()->loggerSettings();
343  mDebugSeverity = settings.debugSeverity;
344  mInfoSeverity = settings.infoSeverity;
345  mWarningSeverity = settings.warningSeverity;
346  mErrorSeverity = settings.errorSeverity;
347  }
348 
350  {
351  if(mSearchbar->isHidden())
352  {
353  mSearchbar->show();
354  mSearchbar->setFocus();
355  }
356  else
357  {
358  mSearchbar->hide();
359  setFocus();
360  }
361  }
362 
364  {
365  return mSearchIconPath;
366  }
367 
369  {
370  return mSearchIconStyle;
371  }
372 
374  {
375  mSearchIconPath = path;
376  }
377 
379  {
380  mSearchIconStyle = style;
381  }
382 }
This class represents a channel in the channel model. It primarily holds the channel name and its ent...
Definition: channel_item.h:67
const QString name() const
const QList< ChannelEntry * > * getEntries() const
QReadWriteLock * getLock()
Table model for log channels.
Definition: channel_model.h:48
void handleLogmanagerCallback(const spdlog::level::level_enum &t, const std::string &channel_name, const std::string &msg_text)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
static ChannelModel * instance()
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
A combobox for selecting a logger channel.
Abstract class for Widgets within HAL's ContentArea.
QVBoxLayout * mContentLayout
Appends log messages to the corresponding LoggerWidget.
void appendLog(spdlog::level::level_enum log_type, QString const &msg)
void resizeEvent(QResizeEvent *event) override
virtual void setupToolbar(Toolbar *toolbar) override
void handleCurrentFilterChanged(int p)
~LoggerWidget() override
QString searchIconStyle
Definition: logger_widget.h:60
void handleSearchChanged(QString filter, int SearchOptions)
void setSearchIconStyle(const QString &style)
QString searchIconPath
Definition: logger_widget.h:59
void setSearchIconPath(const QString &path)
QPlainTextEdit * getPlainTextEdit()
void handleFirstUserInteraction(int value)
bool isMatching(QString searchString, QString stringToCheck)
void handleCurrentChannelUpdated(spdlog::level::level_enum t, QString const &msg)
void handleSeverityChanged(bool state)
void handleChannelUpdated(spdlog::level::level_enum t, const std::string &logger_name, std::string const &msg)
LoggerWidget(QWidget *parent=nullptr)
bool isExactMatch() const
bool isCaseSensitive() const
bool isRegularExpression() const
A QFrame with a QLineEdit that can be used to input a substring to search for.
Definition: searchbar.h:48
void saveLoggerSettings(const LoggerSettings &settings)
LoggerSettings loggerSettings() const
static SettingsManager * instance()
Toolbar for all ContentFrames and ContentWidgets.
Definition: toolbar.h:39
void addSpacer()
Definition: toolbar.cpp:11
void repolish()
Definition: toolbar.cpp:19
QIcon getStyledSvgIcon(const QString &from_to_colors_enabled, const QString &svg_path, QString from_to_colors_disabled=QString())
Definition: graphics.cpp:60
void setCheckable(bool)
void setChecked(bool)
QScrollBar * verticalScrollBar() const const
void actionTriggered(int action)
void setValue(int)
void setIcon(const QIcon &icon)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
AdjustToContentsOnFirstShow
void setCurrentText(const QString &text)
void setEditable(bool editable)
QLineEdit * lineEdit() const const
void setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy policy)
void setFrameStyle(int style)
void setText(const QString &)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * sender() const const
void setReadOnly(bool ro)
int compare(const QString &other, Qt::CaseSensitivity cs) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
std::string toStdString() const const
CaseSensitive
CustomContextMenu
QAction * addAction(const QString &text)
QAction * addWidget(QWidget *widget)
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void ensurePolished() const const
virtual bool event(QEvent *event) override
void hide()
bool isHidden() const const
void setFocus()
void show()
QStyle * style() const const
The ChannelEntry struct is used by the ChannelItem class to store a single entry.
Definition: channel_item.h:44