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  mSearchAction = new QAction(this);
57  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
58 
59  mChannelLabel = new QLabel(this);
60  mChannelLabel->setText("all");
61 
62  mSelector = new ChannelSelector(this);
63  mSelector->setEditable(true);
64  }
65 
67  {
68 
69  }
70 
72  {
73  // Action button to activate Searchbar
74  toolbar->addAction(mSearchAction);
75 
76  // Show current channel
77  toolbar->addWidget(mChannelLabel);
78 
79  // ChannelSelector
80  connect(mSelector->lineEdit(), SIGNAL(editingFinished()), this, SLOT(handleCustomChannel()));
81  connect(mSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(handleCurrentFilterChanged(int)));
82 // mSelector->setStyleSheet("QCombobox {background-color : rgb(32, 43, 63); border-radius: 2px;}");
84  toolbar->addWidget(mSelector);
85 
86  // Severity buttons
87  mDebugButton = new QPushButton("Debug", this);
88  mDebugButton->setCheckable(true);
89  mDebugButton->setChecked(mDebugSeverity);
90 // 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)} ");
91  toolbar->addWidget(mDebugButton);
92 
93  mInfoButton = new QPushButton("Info", this);
94  mInfoButton->setCheckable(true);
95  mInfoButton->setChecked(mInfoSeverity);
96 // 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)} ");
97  toolbar->addWidget(mInfoButton);
98 
99  mWarningButton = new QPushButton("Warning", this);
100  mWarningButton->setCheckable(true);
101  mWarningButton->setChecked(mWarningSeverity);
102 // 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)} ");
103  toolbar->addWidget(mWarningButton);
104 
105  mErrorButton = new QPushButton("Error", this);
106  mErrorButton->setCheckable(true);
107  mErrorButton->setChecked(mErrorSeverity);
108 // 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)} ");
109  toolbar->addWidget(mErrorButton);
110 
111  toolbar->addSpacer();
112 
113  mMuteButton = new QPushButton("Mute all", this);
114 // 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)} ");
115  toolbar->addWidget(mMuteButton);
116 
117  mVerboseButton = new QPushButton("Show all", this);
118 // 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)} ");
119  toolbar->addWidget(mVerboseButton);
120 
121  connect(mSearchAction, SIGNAL(triggered()), this, SLOT(toggleSearchbar()));
122  connect(mSearchbar, SIGNAL(triggerNewSearch(QString, int)), this, SLOT(handleSearchChanged(QString, int)));
123  connect(mDebugButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
124  connect(mInfoButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
125  connect(mWarningButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
126  connect(mErrorButton, SIGNAL(toggled(bool)), this, SLOT(handleSeverityChanged(bool)));
127  connect(mMuteButton, SIGNAL(clicked(bool)), this, SLOT(handleSeverityChanged(bool)));
128  connect(mVerboseButton, SIGNAL(clicked(bool)), this, SLOT(handleSeverityChanged(bool)));
129 
130  toolbar->repolish();
131  }
132 
134  {
135  return mPlainTextEdit;
136  }
137 
138  void LoggerWidget::handleCurrentChannelUpdated(spdlog::level::level_enum t, const QString& msg)
139  {
140  mLogMarshall->appendLog(t, msg);
141  }
142 
143  void LoggerWidget::handleChannelUpdated(spdlog::level::level_enum t, const std::string& logger_name, const std::string& msg)
144  {
145  if (mCurrentChannel == "")
146  {
148  }
149  if (logger_name != mCurrentChannel)
150  return;
151 
152 
153  bool filter = false;
154  if ((t == spdlog::level::level_enum::info) && mInfoSeverity) {
155  filter = true;
156  }
157  else if ((t == spdlog::level::level_enum::warn) && mWarningSeverity) {
158  filter = true;
159  }
160  else if ((t == spdlog::level::level_enum::err) && mErrorSeverity) {
161  filter = true;
162  }
163  else if ((t == spdlog::level::level_enum::debug) && mDebugSeverity) {
164  filter = true;
165  }
166  else if (t == spdlog::level::level_enum::critical) {
167  filter = true;
168  }
169 
170  if (filter)
171  {
172  mLogMarshall->appendLog(t, QString::fromStdString(msg));
173  }
174  }
175 
176  bool LoggerWidget::isMatching(QString searchString, QString stringToCheck)
177  {
178  if(!mSearchOptions.isExactMatch() && !mSearchOptions.isRegularExpression()){
179  //check if stringToCheck contains the searchString
180  return stringToCheck.contains(searchString, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
181  }
182  else if(mSearchOptions.isExactMatch()){
183  //check if the stringToCheck is the same as the searchString - also checks CaseSensitivity
184 
185  return 0 == QString::compare(searchString, stringToCheck, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
186  }
187  else if(mSearchOptions.isRegularExpression()){
188  //checks if the stringToCheck matches the regEx given by searchString
190  return regEx.match(stringToCheck).hasMatch();
191  }
192  return false;
193  }
194 
196  {
198 
199  // Channel has been changed or initially set
200  if ((sender() == mSelector) || p == 0) {
201  mCurrentChannelIndex = p;
202  }
203 
204  // Set "all" Channel
205  if (p == -1) {
206  mCurrentChannelIndex = model->rowCount() - 1;
207  }
208 
209  if (mCurrentChannelIndex == -2) {
210  return;
211  }
212 
213  ChannelItem* item = static_cast<ChannelItem*>((model->index(mCurrentChannelIndex, 0, QModelIndex())).internalPointer());
214  mCurrentChannel = item->name().toStdString();
215  mChannelLabel->setText(QString::fromStdString(mCurrentChannel));
216  mSelector->setCurrentText(QString::fromStdString(mCurrentChannel));
217 
218  mPlainTextEdit->clear();
219  QWriteLocker item_locker(item->getLock());
220 
221  // Iterate through every log entry
222  for (ChannelEntry* entry : *(item->getEntries()))
223  {
224  bool filter = false;
225  // If entry msg matches with search string
226  //QRegularExpression re(mSearchFilter);
227  if (isMatching(mSearchFilter, QString::fromStdString(entry->mMsg)))
228  {
229  // If entry severity matches the choosen severitys
230  if ((entry->mMsgType == spdlog::level::level_enum::info) && mInfoSeverity) {
231  filter = true;
232  }
233  else if ((entry->mMsgType == spdlog::level::level_enum::warn) && mWarningSeverity) {
234  filter = true;
235  }
236  else if ((entry->mMsgType == spdlog::level::level_enum::err) && mErrorSeverity) {
237  filter = true;
238  }
239  else if ((entry->mMsgType == spdlog::level::level_enum::debug) && mDebugSeverity) {
240  filter = true;
241  }
242  else if (entry->mMsgType == spdlog::level::level_enum::critical) {
243  filter = true;
244  }
245  }
246 
247  // If log entry should be shown
248  if (filter)
249  {
250  mLogMarshall->appendLog(entry->mMsgType, QString::fromStdString(entry->mMsg));
251  }
252  }
253  }
254 
256  {
257 
258  // change Severitys
259  if (sender() == mDebugButton)
260  {
261  mDebugSeverity = state;
262  }
263  else if (sender() == mInfoButton)
264  {
265  mInfoSeverity = state;
266  }
267  else if (sender() == mWarningButton)
268  {
269  mWarningSeverity = state;
270  }
271  else if (sender() == mErrorButton)
272  {
273  mErrorSeverity = state;
274  }
275  else if (sender() == mMuteButton)
276  {
277  mDebugButton->setChecked(false);
278  mInfoButton->setChecked(false);
279  mWarningButton->setChecked(false);
280  mErrorButton->setChecked(false);
281  }
282  else if (sender() == mVerboseButton)
283  {
284  mDebugButton->setChecked(true);
285  mInfoButton->setChecked(true);
286  mWarningButton->setChecked(true);
287  mErrorButton->setChecked(true);
288  // "all" channel
290  }
291 
292  // Make changes
294 
295  // Save severity settings for next session
296  saveSettings();
297  }
298 
299  void LoggerWidget::handleSearchChanged(QString filter, int searchOptions)
300  {
301  mSearchFilter = filter;
302  std::cout << mSearchFilter.QString::toStdString() << std::endl;
303  mSearchOptions = SearchOptions(searchOptions);
305  }
306 
308  {
309  Q_UNUSED(value);
310 
311  if (!mUserInteractedWithScrollbar)
312  mUserInteractedWithScrollbar = true;
313  }
314 
316  {
317  QString txt = mSelector->lineEdit()->text();
318  if (txt.isEmpty()) return;
319  std::string channel_name = txt.toStdString();
321  model->handleLogmanagerCallback(spdlog::level::level_enum::debug , channel_name, channel_name + " has manually been added to channellist");
322  }
323 
325  {
326  Q_UNUSED(event)
327 
328  if (!mUserInteractedWithScrollbar)
329  scrollToBottom();
330  }
331 
332  void LoggerWidget::scrollToBottom()
333  {
334  mPlainTextEditScrollbar->setValue(mPlainTextEditScrollbar->maximum());
335  }
336 
337  void LoggerWidget::saveSettings()
338  {
339  LoggerSettings settings = { mDebugSeverity, mInfoSeverity, mWarningSeverity, mErrorSeverity };
341  }
342 
343  void LoggerWidget::restoreSettings()
344  {
345  LoggerSettings settings = SettingsManager::instance()->loggerSettings();
346  mDebugSeverity = settings.debugSeverity;
347  mInfoSeverity = settings.infoSeverity;
348  mWarningSeverity = settings.warningSeverity;
349  mErrorSeverity = settings.errorSeverity;
350  }
351 
353  {
354  if(mSearchbar->isHidden())
355  {
356  mSearchbar->show();
357  mSearchbar->setFocus();
358  }
359  else
360  {
361  mSearchbar->hide();
362  setFocus();
363  }
364  }
365 
367  {
368  return mSearchIconPath;
369  }
370 
372  {
373  return mSearchIconStyle;
374  }
375 
377  {
378  mSearchIconPath = path;
379  }
380 
382  {
383  mSearchIconStyle = style;
384  }
385 }
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