log_panel.cpp
Go to the documentation of this file.
1 
29 
30 #include <log_view/utils.h>
31 
32 namespace log_view {
33 
35  int64_t cursor = getCursor();
36 
37  bool new_logs = last_content_size_ != getContentSize();
38 
39  if (following() && (cleared_ || new_logs)) {
40  max_length_ = 0;
41 
42  if (!cleared_) {
43  werase(window_);
44  }
45  cleared_ = false;
46 
47  const auto& logs = logs_->logs();
48  if (getContentSize() < getContentHeight()) {
49  for (size_t i = 0; i < getContentSize(); i++) {
50  auto entry = filter_.indices()[i];
51  printEntry(i, logs[entry.index], entry.line, i);
52  }
53  }
54  else {
55  size_t start_idx = getContentSize() - getContentHeight();
56  for (size_t i = 0; i < height_; i++) {
57  auto entry = filter_.indices()[i + start_idx];
58  printEntry(i, logs[entry.index], entry.line, i + start_idx);
59  }
60  }
61  }
62  else if (!following() && (cleared_ || last_cursor_ != cursor || (!filled_ && new_logs))) {
63  filled_ = false;
64  max_length_ = 0;
65  if (!cleared_) {
66  werase(window_);
67  }
68  cleared_ = false;
69 
70  int64_t start_idx = cursor;
71  if (cursor >= getContentHeight()) {
72  start_idx -= getContentHeight();
73  }
74  else {
75  start_idx = 0;
76  }
77 
78  const auto& logs = logs_->logs();
79  for (size_t i = 0; i < getContentHeight() && i + start_idx < getContentSize(); i++) {
80  auto entry = filter_.indices()[i + start_idx];
81  printEntry(i, logs[entry.index], entry.line, i + start_idx);
82  }
83  filled_ = start_idx + getContentHeight() < getContentSize();
84  }
85 
87  last_cursor_ = cursor;
88 
90 }
91 
92 bool LogPanel::handleKey(int key) {
93  if (hidden()) {
94  return false;
95  }
96 
97  if (key == ctrl('a')) {
98  selectAll();
99 
100  return true;
101  }
102 
103  return false;
104 }
105 
106 
107 bool LogPanel::handleMouse(const MEVENT& event) {
108  if (hidden() || !encloses(event.y, event.x)) {
109  return false;
110  }
111 
112  if (event.bstate & BUTTON1_PRESSED) {
113  mouse_down_ = true;
114  startSelect(event.y - y_);
115  forceRefresh();
116  return true;
117  }
118  else if (mouse_down_ && (event.bstate & REPORT_MOUSE_POSITION)) {
119  endSelect(event.y - y_);
120  forceRefresh();
121  return true;
122  }
123  else if (event.bstate & BUTTON1_RELEASED) {
124  mouse_down_ = false;
125  copyToClipboard();
126  return true;
127  }
128  else if (!mouse_down_ && (event.bstate & BUTTON3_PRESSED)) {
130  forceRefresh();
131  return true;
132  }
133 
134  return false;
135 }
136 
137 void LogPanel::resize(int height, int width, int y, int x) {
138  PanelInterface::resize(height, width, y, x);
140 }
141 
143  if (getContentSize() > 0) {
146  copyToClipboard();
147  forceRefresh();
148  }
149 }
150 
152  int64_t select_start = filter_.getSelectStart();
153  int64_t select_end = filter_.getSelectEnd();
154  if (select_start >=0 && select_end >= 0) {
155  int start = std::min(select_start, select_end);
156  int end = std::max(select_start, select_end);
157  const auto& logs = logs_->logs();
158  std::string data;
159  for (size_t i = start; i <= end && i < getContentSize(); i++) {
160  auto entry = filter_.indices()[i];
161  std::string prefix = getPrefix(logs[entry.index], entry.line);
162  data += prefix + logs[entry.index].text[entry.line] + "\n";
163  }
164  toClipboard(data);
165  }
166 }
167 
168 void LogPanel::startSelect(int row) {
169  follow(false);
170 
171  size_t start_idx = filter_.getCursor();
172  if (start_idx >= getContentHeight()) {
173  start_idx -= getContentHeight();
174  }
175  else {
176  start_idx = 0;
177  }
178 
179  filter_.setSelectStart(start_idx + row);
180 }
181 
182 void LogPanel::endSelect(int row) {
183  size_t start_idx = filter_.getCursor();
184  if (start_idx >= getContentHeight()) {
185  start_idx -= getContentHeight();
186  }
187  else {
188  start_idx = 0;
189  }
190 
191  filter_.setSelectEnd(start_idx + row);
192 }
193 
195  int width = width_;
196  if (getContentSize() >= getContentHeight()) {
197  width--;
198  }
199  return width;
200 }
201 
202 std::string LogPanel::getPrefix(const LogEntry& entry, size_t line) const {
203  std::string text = toString(entry.stamp.toSec(), 4) + " [";
204  if (entry.level == rosgraph_msgs::Log::DEBUG) {
205  text += "DEBUG";
206  }
207  else if (entry.level == rosgraph_msgs::Log::INFO) {
208  text += "INFO";
209  }
210  else if (entry.level == rosgraph_msgs::Log::WARN) {
211  text += "WARN";
212  }
213  else if (entry.level == rosgraph_msgs::Log::ERROR) {
214  text += "ERROR";
215  }
216  else if (entry.level == rosgraph_msgs::Log::FATAL) {
217  text += "FATAL";
218  }
219  else {
220  text += std::to_string(entry.level);
221  }
222  text += "] ";
223  if (line > 0) {
224  text = std::string(text.size(), ' ');
225  }
226 
227  return text;
228 }
229 
230 void LogPanel::printEntry(size_t row, const LogEntry& entry, size_t line, size_t idx) {
231  bool selected = false;
232  int64_t select_start = filter_.getSelectStart();
233  int64_t select_end = filter_.getSelectEnd();
234  if (select_start != -1) {
235  int start = std::min(select_start, select_end);
236  int end = std::max(select_start, select_end);
237  selected = idx >= start && idx <= end;
238  }
239 
240  if (selected) {
241  wattron(window_, A_REVERSE);
242  }
243 
244  if (entry.level == rosgraph_msgs::Log::DEBUG) {
245  wattron(window_, A_DIM);
246  }
247  else if (entry.level == rosgraph_msgs::Log::ERROR) {
248  wattron(window_, COLOR_PAIR(CP_RED));
249  }
250  else if (entry.level == rosgraph_msgs::Log::FATAL) {
251  wattron(window_, A_BOLD);
252  wattron(window_, COLOR_PAIR(CP_RED));
253  }
254  else if (entry.level == rosgraph_msgs::Log::WARN) {
255 
256  wattron(window_, COLOR_PAIR(CP_YELLOW));
257  }
258 
259  std::string prefix = getPrefix(entry, line);
260  std::string text = prefix + entry.text[line];
261  max_length_ = std::max(max_length_, text.size());
262 
263  std::string match = filter_.getSearch();
264  size_t match_size = match.size();
265  std::vector<size_t> match_indices;
266  bool matched = false;
267  if (!match.empty()) {
268  match_indices = find(entry.text[line], match, true);
269  matched = !match_indices.empty();
270  }
271 
272  if (shift_ >= text.size()) {
273  text.clear();
274  }
275  else if (shift_ > 0) {
276  text.erase(0, shift_);
277  }
278  if (text.size() > width_) {
279  text.resize(width_);
280  }
281 
282  mvwprintw(window_, row, 0, text.c_str());
283 
284  if (matched) {
285  wattron(window_, COLOR_PAIR(CP_DEFAULT_CYAN));
286 
287  if (text.empty()) {
288  mvwprintw(window_, row, 0, " ");
289  }
290  else {
291  for (const auto& match_index: match_indices) {
292  int64_t start_idx = match_index + prefix.length() - shift_;
293  int64_t end_idx = start_idx + match_size;
294 
295  start_idx = std::min(static_cast<int64_t>(text.size()) - 2, std::max(static_cast<int64_t>(0), start_idx));
296  end_idx = std::min(static_cast<int64_t>(text.size()) - 2, std::max(static_cast<int64_t>(0), end_idx));
297 
298  int64_t substr_len = std::max(static_cast<int64_t>(1), end_idx - start_idx);
299 
300  mvwprintw(window_, row, start_idx, text.substr(start_idx, substr_len).c_str());
301  }
302  }
303  wattroff(window_, COLOR_PAIR(CP_DEFAULT_CYAN));
304  }
305 
306  if (entry.level == rosgraph_msgs::Log::DEBUG) {
307  wattroff(window_, A_DIM);
308  }
309  else if (entry.level == rosgraph_msgs::Log::ERROR) {
310  wattroff(window_, COLOR_PAIR(CP_RED));
311  }
312  if (entry.level == rosgraph_msgs::Log::FATAL) {
313  wattroff(window_, COLOR_PAIR(CP_RED));
314  wattroff(window_, A_BOLD);
315  }
316  else if (entry.level == rosgraph_msgs::Log::WARN) {
317  wattroff(window_, COLOR_PAIR(CP_YELLOW));
318  }
319 
320  if (selected) {
321  wattroff(window_, A_REVERSE);
322  }
323 }
324 
325 } // namespace log_view
virtual void resize(int height, int width, int y, int x)
Definition: log_panel.cpp:137
LogFilter & filter_
Definition: log_panel.h:60
virtual int getContentHeight() const
ROSCPP_DECL void start()
virtual bool encloses(int y, int x)
virtual size_t getContentSize() const
Definition: log_panel.h:51
virtual bool handleKey(int key)
Definition: log_panel.cpp:92
virtual int width() const
virtual void resize(int height, int width, int y, int x)
void printEntry(size_t row, const LogEntry &entry, size_t line, size_t index)
Definition: log_panel.cpp:230
std::vector< size_t > find(const std::string &text, const std::string &substr, bool case_insensitive)
Definition: utils.cpp:85
virtual int getContentWidth() const
Definition: log_panel.cpp:194
virtual void endSelect(int row)
Definition: log_panel.cpp:182
const std::deque< LogLine > & indices() const
Definition: log_filter.h:88
virtual void startSelect(int row)
Definition: log_panel.cpp:168
virtual void selectAll()
Definition: log_panel.cpp:142
virtual int y() const
std::string toString(double val, int precision)
Definition: utils.cpp:37
int64_t getSelectEnd()
Definition: log_filter.cpp:255
virtual bool hidden() const
void setSelectStart(int64_t index)
Definition: log_filter.cpp:242
virtual void refresh()
Definition: log_panel.cpp:34
std::string getPrefix(const LogEntry &entry, size_t line) const
Definition: log_panel.cpp:202
void setCursorOffset(int64_t offset)
Definition: log_filter.h:45
void toClipboard(const std::string &text)
Definition: utils.cpp:125
std::string getSearch() const
Definition: log_filter.h:86
ros::Time stamp
Definition: datatypes.h:57
virtual int x() const
virtual int64_t getCursor() const
Definition: log_panel.h:54
int64_t getSelectStart()
Definition: log_filter.cpp:247
virtual void copyToClipboard()
Definition: log_panel.cpp:151
std::vector< std::string > text
Definition: datatypes.h:64
int ctrl(char key)
Definition: utils.cpp:121
void setSelectEnd(int64_t index)
Definition: log_filter.cpp:251
virtual bool handleMouse(const MEVENT &event)
Definition: log_panel.cpp:107
LogStorePtr logs_
Definition: log_panel.h:59
virtual int height() const
virtual void drawScrollBar(size_t count, int height, int y, int x)
virtual void follow(bool enable)


log_view
Author(s): Marc Alban
autogenerated on Thu Mar 4 2021 03:21:52