PulseView  unreleased development snapshot
A Qt-based sigrok GUI
logging.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2018 Soeren Apel <soeren@apelpie.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "logging.hpp"
21 #include "globalsettings.hpp"
22 
23 #include <iostream>
24 
25 #ifdef ENABLE_DECODE
26 #include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */
27 #endif
28 
29 #include <libsigrokcxx/libsigrokcxx.hpp>
30 
31 #include <QApplication>
32 
33 using std::cout;
34 using std::endl;
35 using std::lock_guard;
36 
37 namespace pv {
38 
40 
41 const int Logging::MIN_BUFFER_SIZE = 10;
42 const int Logging::MAX_BUFFER_SIZE = 50000;
43 
44 static sr_log_callback prev_sr_log_cb;
45 static void *prev_sr_log_cb_data;
46 
47 #ifdef ENABLE_DECODE
48 static srd_log_callback prev_srd_log_cb;
49 static void *prev_srd_log_cb_data;
50 #endif
51 
53 {
54  qInstallMessageHandler(nullptr);
55  if (prev_sr_log_cb)
56  sr_log_callback_set(prev_sr_log_cb, prev_sr_log_cb_data);
57  prev_sr_log_cb = nullptr;
58  prev_sr_log_cb_data = nullptr;
59 #ifdef ENABLE_DECODE
60  if (prev_srd_log_cb)
61  srd_log_callback_set(prev_srd_log_cb, prev_srd_log_cb_data);
62  prev_srd_log_cb = nullptr;
63  prev_srd_log_cb_data = nullptr;
64 #endif
65 
67 }
68 
70 {
71  GlobalSettings settings;
72 
73  buffer_size_ =
74  settings.value(GlobalSettings::Key_Log_BufferSize).toInt();
75 
76  buffer_.reserve(buffer_size_);
77 
78  qInstallMessageHandler(log_pv);
79  sr_log_callback_get(&prev_sr_log_cb, &prev_sr_log_cb_data);
80  sr_log_callback_set(log_sr, nullptr);
81 #ifdef ENABLE_DECODE
82  srd_log_callback_get(&prev_srd_log_cb, &prev_srd_log_cb_data);
83  srd_log_callback_set(log_srd, nullptr);
84 #endif
85 
87 }
88 
90 {
91  // We assume that libsigrok and libsrd always have the same log level
92  return sr_log_loglevel_get();
93 }
94 
95 void Logging::set_log_level(int level)
96 {
97  sr_log_loglevel_set(level);
98 #ifdef ENABLE_DECODE
99  srd_log_loglevel_set(level);
100 #endif
101 }
102 
103 QString Logging::get_log() const
104 {
105  return buffer_.join("<br />\n");
106 }
107 
108 void Logging::log(const QString &text, int source)
109 {
110  lock_guard<mutex> log_lock(log_mutex_);
111 
112  if (buffer_.size() >= buffer_size_)
113  buffer_.removeFirst();
114 
115  QString s;
116 
117  if (text.contains("warning", Qt::CaseInsensitive)) {
118  s = QString("<font color=\"darkorange\">%1</font>").arg(text);
119  goto out;
120  }
121 
122  if (text.contains("error", Qt::CaseInsensitive)) {
123  s = QString("<font color=\"darkred\">%1</font>").arg(text);
124  goto out;
125  }
126 
127  switch (source) {
128  case LogSource_pv:
129  s = QString("<font color=\"darkMagenta\">pv: %1</font>").arg(text);
130  break;
131  case LogSource_sr:
132  s = QString("<font color=\"darkGreen\">sr: %1</font>").arg(text);
133  break;
134  case LogSource_srd:
135  s = QString("<font color=\"olive\">srd: %1</font>").arg(text);
136  break;
137  default:
138  s = text;
139  break;
140  }
141 
142 out:
143  buffer_.append(s);
144 
145  // If we're tearing down the program, sending out notifications to UI
146  // elements that can no longer function properly is a bad idea
147  if (!QApplication::closingDown())
148  logged_text(s);
149 }
150 
151 void Logging::log_pv(QtMsgType type, const QMessageLogContext &context, const QString &msg)
152 {
153  (void)type;
154  (void)context;
155 
156  logging.log(msg, LogSource_pv);
157 
158  cout << msg.toUtf8().data() << endl;
159 }
160 
161 int Logging::log_sr(void *cb_data, int loglevel, const char *format, va_list args)
162 {
163  va_list args2;
164 
165  (void)cb_data;
166 
167  va_copy(args2, args);
168  if (prev_sr_log_cb)
169  prev_sr_log_cb(prev_sr_log_cb_data, loglevel, format, args2);
170  va_end(args2);
171 
172  char *text = g_strdup_vprintf(format, args);
173  logging.log(QString::fromUtf8(text), LogSource_sr);
174  g_free(text);
175 
176  return SR_OK;
177 }
178 
179 #ifdef ENABLE_DECODE
180 int Logging::log_srd(void *cb_data, int loglevel, const char *format, va_list args)
181 {
182  va_list args2;
183 
184  (void)cb_data;
185 
186  va_copy(args2, args);
187  if (prev_srd_log_cb)
188  prev_srd_log_cb(prev_srd_log_cb_data, loglevel, format, args2);
189  va_end(args2);
190 
191  char *text = g_strdup_vprintf(format, args);
192 
193  QString s = QString::fromUtf8(text);
194 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
195  for (QString& substring : s.split("\n", Qt::SkipEmptyParts))
196  logging.log(substring, LogSource_srd);
197 #else
198  for (QString& substring : s.split("\n", QString::SkipEmptyParts))
199  logging.log(substring, LogSource_srd);
200 #endif
201  g_free(text);
202 
203  return SR_OK;
204 }
205 #endif
206 
207 void Logging::on_setting_changed(const QString &key, const QVariant &value)
208 {
210  // Truncate buffer if needed
211  const int delta = buffer_.size() - value.toInt();
212  if (delta > 0)
213  buffer_.erase(buffer_.begin(), buffer_.begin() + delta);
214 
215  buffer_size_ = value.toInt();
216  buffer_.reserve(buffer_size_);
217  }
218 }
219 
220 } // namespace pv
libsigrok allows users to import and export data from files in various formats some of them as generic as others very specific For a list and make sure to check not so common and outright exotic ways to represent data and sigrok tries to suit as many needs as it can To see which formats your version of PulseView just click on the small arrow next to the _Open_ PulseView will ask for the file name to open Once you picked the you may be asked to specify the details of the format
Logging logging
Definition: logging.cpp:39
static const QString Key_Log_BufferSize
static const int MAX_BUFFER_SIZE
Definition: logging.hpp:48
static int log_sr(void *cb_data, int loglevel, const char *format, va_list args)
Definition: logging.cpp:161
T value(details::expression_node< T > *n)
Definition: exprtk.hpp:12358
static void * prev_sr_log_cb_data
Definition: loghandler.cpp:34
static sr_log_callback prev_sr_log_cb
Definition: loghandler.cpp:33
void set_log_level(int level)
Definition: logging.cpp:95
mutex log_mutex_
Definition: logging.hpp:78
int get_log_level() const
Definition: logging.cpp:89
QString get_log() const
Definition: logging.cpp:103
static void remove_change_handler(GlobalSettingsInterface *cb)
static const int MIN_BUFFER_SIZE
Definition: logging.hpp:47
static void log_pv(QtMsgType type, const QMessageLogContext &context, const QString &msg)
Definition: logging.cpp:151
void init()
Definition: logging.cpp:69
void logged_text(QString s)
void on_setting_changed(const QString &key, const QVariant &value)
Definition: logging.cpp:207
QStringList buffer_
Definition: logging.hpp:77
static void add_change_handler(GlobalSettingsInterface *cb)
int buffer_size_
Definition: logging.hpp:76
void log(const QString &text, int source)
Definition: logging.cpp:108