Jpp 19.3.0-rc.3
the software that should make you happy
Loading...
Searching...
No Matches
gui.cpp
Go to the documentation of this file.
1#include "gui.hpp"
2#include "structs.hpp"
3#include "version.hpp"
4
5#include <boost/bind.hpp>
6#include <sys/ioctl.h>
7#include <boost/ref.hpp>
8#include <sstream>
9#include <fstream>
10
11/**
12 * \author cpellegrino
13 */
14
15const static int default_hit_counter_threshold = 850;
16
17std::string mon_channel::mac_address() const
18{
19 /*
20 * The MAC address of a WR node starts with 08:00:30.
21 * The DOMID is defined by the MAC address removing the initial 08:00.
22 */
23
24 std::ostringstream oss("0800", std::ostringstream::ate);
25 oss << std::hex << domid();
26 if (oss.tellp() != 12) {
27 return "undefined";
28 }
29
30 std::ostringstream stream;
31
32 std::string const no = oss.str();
33 std::size_t const s = no.size();
34 for (std::size_t i = 0; i < s; i += 2) {
35 stream << char(toupper(no[i]))
36 << char(toupper(no[i + 1]))
37 << (i != s - 2 ? ":" : "");
38 }
39 return stream.str();
40}
41
42inline
43bool ischar(int key)
44{
45 return
46 key >= std::numeric_limits<char>::min()
47 && key <= std::numeric_limits<char>::max();
48}
49
51 boost::asio::deadline_timer& timer,
52 gui::Screen& screen,
53 boost::system::error_code const& error)
54{
55 if (!error) {
56 screen.commit();
57
58 timer.expires_from_now(boost::posix_time::seconds(1));
59 timer.async_wait(
60 boost::bind(
62 boost::ref(timer),
63 boost::ref(screen),
64 boost::asio::placeholders::error));
65 }
66}
67
69 boost::asio::posix::stream_descriptor& keyb,
70 char& key,
71 gui::Screen& screen,
72 const boost::system::error_code& error,
73 std::size_t bytes_transferred)
74{
75 if (!error) {
76 int k = key;
77
78 if (key == 27) {
79 boost::asio::posix::stream_descriptor::bytes_readable command(true);
80 keyb.io_control(command);
81
82 std::size_t nbytes = command.get();
83
84 while (nbytes--) {
85 boost::system::error_code ec;
86 keyb.read_some(boost::asio::buffer(&key, sizeof(key)), ec);
87 k <<= 8;
88 k += key;
89 }
90 }
91
92 screen.elaborate(k);
93
94 keyb.async_read_some(
95 boost::asio::buffer(&key, sizeof(key)),
96 boost::bind(
98 boost::ref(keyb),
99 boost::ref(key),
100 boost::ref(screen),
101 boost::asio::placeholders::error,
102 boost::asio::placeholders::bytes_transferred));
103 }
104}
105
107 boost::asio::signal_set& window_resize,
108 gui::Screen& screen,
109 boost::system::error_code const& error,
110 int signum)
111{
112 if (!error) {
113 std::pair<int, int> const win_size = window_size();
114
115 screen.resize(win_size.first, win_size.second);
116
117 window_resize.async_wait(
118 boost::bind(
120 boost::ref(window_resize),
121 boost::ref(screen),
122 boost::asio::placeholders::error,
123 boost::asio::placeholders::signal_number));
124 }
125}
126
128{
129 winsize sz;
130
131 ioctl(0, TIOCGWINSZ, &sz);
132
133 return std::make_pair(sz.ws_row, sz.ws_col);
134}
135
136namespace gui {
137
138std::string const Screen::search_prompt = "Search: ";
139std::string const Screen::regex_prompt = "RegEx: ";
140
141void LineEdit::move(LineEdit::movement dir)
142{
143 switch (dir) {
144 case LEFT:
145 m_current_pos -= m_current_pos == 0 ? 0 : 1;
146 break;
147 case RIGHT:
148 m_current_pos += m_current_pos == m_current_line.size() ? 0 : 1;
149 break;
150 case BEGIN:
151 m_current_pos = 0;
152 break;
153 case END:
154 m_current_pos = m_current_line.size();
155 break;
156 case HBACK:
157 if (not m_history.empty()) {
158 if (m_history_pos == m_history.size()) {
159 m_editing_line.swap(m_current_line);
160 }
161
162 if (m_history_pos != 0) {
163 --m_history_pos;
164
165 std::list<std::string>::iterator it = m_history.begin();
166 std::advance(it, m_history_pos);
167
168 m_current_line = *it;
169 m_current_pos = m_current_line.size();
170 }
171 }
172 break;
173 case HFWD:
174 if (not m_history.empty()) {
175 if (m_history_pos == m_history.size() - 1) {
176 m_editing_line.swap(m_current_line);
177 ++m_history_pos;
178 m_current_pos = m_current_line.size();
179 } else if (m_history_pos < m_history.size()) {
180 ++m_history_pos;
181
182 std::list<std::string>::iterator it = m_history.begin();
183 std::advance(it, m_history_pos);
184
185 m_current_line = *it;
186 m_current_pos = m_current_line.size();
187 }
188 }
189 break;
190 }
191}
192
193void LineEdit::load_history(std::string const& path)
194{
195 std::ifstream ifs(path.c_str());
196
197 while (ifs && ifs.peek() != EOF) {
198 std::string line;
199 std::getline(ifs, line);
200
201 m_history.push_back(line);
202 }
203}
204
205void LineEdit::store_history(std::string const& path) const
206{
207 std::ofstream ofs(path.c_str());
209 for (
210 citer it = m_history.begin(), et = m_history.end()
211 ; it != et
212 ; ++it
213 ) {
214 ofs << *it << '\n';
215 }
216}
217
218void Screen::elaborate(int key)
219{
220 if (status != kSEARCH && status != kREGEX) {
221 clear_status_bar();
222
223 if (key == 'q') {
224 m_service.stop();
225 return;
226 }
227 }
228
229 switch (status) {
230 case kNORMAL:
231 if (key == 'h') {
232 show_help();
233 status = kHELP;
234 } else if (key == 'c') {
235 m_list.clear();
236 m_smatched.clear();
237 m_selected = 0;
238 commit();
239 } else if (key == 't') {
240 sort = kLAST_VIEW;
241 commit();
242 } else if (key == 'd') {
243 sort = kDOMID;
244 commit();
245 } else if (key == 'r') {
246 sort = kRATE;
247 commit();
248 } else if (key == 'n') {
249 sort = kRUNNO;
250 commit();
251 } else if (key == 'l') {
252 sort = kNAME;
253 commit();
254 } else if (key == 'i') {
255 m_sort_reverse = !m_sort_reverse;
256 commit();
257 } else if (key == 'g') {
258 if (m_list.size()) {
259 m_selected = 0;
260
261 move_limits();
262
263 move_selection();
264 }
265 } else if (key == 'G') {
266 if (m_list.size()) {
267 m_selected = m_list.size() - 1;
268
269 move_limits();
270
271 move_selection();
272 }
273 } else if (key == '/') {
274 status = kSEARCH;
275 m_search_editor.reset();
276 update_bar(search_prompt, m_search_editor);
277 } else if (key == '%') {
278 status = kREGEX;
279 m_regex_editor.reset();
280 update_bar(regex_prompt, m_regex_editor);
281 } else if (key == 'm') {
282 m_matching_first = ! m_matching_first;
283
284 if (m_matching_first) {
285 write_to_status_bar("Grouping matching CLBs on top");
286 } else {
287 write_to_status_bar("Grouping disabled");
288 }
289 } else if (key == 'w') {
290 go_match = NONE;
291 m_smatched.clear();
292 } else if (key == kKEY_ENTER) {
293 if (m_list.size()) {
294 status = kSINGLE;
295 show_filtered();
296 } else {
297 status_nodoms();
298 }
299 } else if (key == kKEY_DOWN) {
300 if (m_list.size()) {
301 m_selected =
302 m_selected + 1 == static_cast<int>(m_list.size())
303 ? 0
304 : m_selected + 1;
305
306 move_limits();
307
308 move_selection();
309 }
310 } else if (key == kKEY_UP) {
311 if (m_list.size()) {
312 m_selected =
313 m_selected - 1 < 0
314 ? m_list.size() - 1
315 : m_selected - 1;
316
317 move_limits();
318
319 move_selection();
320 }
321 } else if (key == kKEY_LEFT) {
322 if (m_offset != 0) {
323 m_offset -= 5;
324 commit();
325 }
326 } else if (key == kKEY_RIGHT) {
327 if (m_offset + COLS + 1 < max_line_size) {
328 m_offset += 5;
329 commit();
330 }
331 } else {
332 status_unrecognised(key);
333 }
334 break;
335 case kHELP:
336 if (key == kKEY_ESC) {
337 status = kNORMAL;
338 commit();
339 } else {
340 status_unrecognised(key);
341 }
342 break;
343 case kSINGLE:
344 if (key == kKEY_ESC) {
345 status = kNORMAL;
346 commit();
347 } else if (key == kKEY_DOWN) {
348 if (m_list.size()) {
349 m_selected =
350 m_selected + 1 == static_cast<int>(m_list.size())
351 ? 0
352 : m_selected + 1;
353
354 move_limits();
355
356 move_selection();
357 }
358 } else if (key == kKEY_UP) {
359 if (m_list.size()) {
360 m_selected =
361 m_selected - 1 < 0
362 ? m_list.size() - 1
363 : m_selected - 1;
364
365 move_limits();
366
367 move_selection();
368 }
369 } else {
370 status_unrecognised(key);
371 }
372 break;
373 case kSEARCH:
374 if (key == kKEY_ESC) {
375 clear_status_bar();
376
377 if (!m_search_editor.current().empty()) {
378 m_search_editor.add_history();
379 }
380
381 status = kNORMAL;
382 go_match = NONE;
383 m_smatched.clear();
384 return;
385 } else if (key == kKEY_ENTER) {
386 go_match = SEARCH;
387 m_search_editor.add_history();
388 clear_status_bar();
389 status = kNORMAL;
390 return;
391 } else if (key == kKEY_UP) {
392 m_search_editor.move(LineEdit::HBACK);
393 } else if (key == kKEY_DOWN) {
394 m_search_editor.move(LineEdit::HFWD);
395 } else if (key == kKEY_RIGHT) {
396 m_search_editor.move(LineEdit::RIGHT);
397 } else if (key == kKEY_LEFT) {
398 m_search_editor.move(LineEdit::LEFT);
399 } else if (key == kKEY_BACKS) {
400 m_search_editor.remove_bwd();
401 } else if (key == kKEY_DEL) {
402 m_search_editor.remove_fwd();
403 } else if (key == kKEY_HOME || key == kKEY_CTRLA) {
404 m_search_editor.move(LineEdit::BEGIN);
405 } else if (key == kKEY_END || key == kKEY_CTRLE) {
406 m_search_editor.move(LineEdit::END);
407 } else if (key == kKEY_CTRLL) {
408 m_search_editor.reset();
409 } else if (ischar(key) && isprint(key)) {
410 m_search_editor.append(key);
411 } else {
412 return;
413 }
414 update_bar(search_prompt, m_search_editor);
415 go_match = SEARCH;
416 commit();
417 break;
418 case kREGEX:
419 if (key == kKEY_ESC) {
420 clear_status_bar();
421 status = kNORMAL;
422 return;
423 } else if (key == kKEY_ENTER) {
424 if (!m_regex_editor.current().empty()) {
425 m_regex_editor.add_history();
426 }
427
428 std::string const current_line = m_regex_editor.current();
429 m_regex_editor.reset();
430 clear_status_bar();
431 status = kNORMAL;
432
433 try {
434 m_regex.assign(current_line, boost::regex_constants::icase);
435 go_match = REGEX;
436 commit();
437 } catch (...) {
438 write_to_status_bar("Invalid regex");
439 go_match = NONE;
440 m_smatched.clear();
441 }
442 return;
443 } else if (key == kKEY_UP) {
444 m_regex_editor.move(LineEdit::HBACK);
445 } else if (key == kKEY_DOWN) {
446 m_regex_editor.move(LineEdit::HFWD);
447 } else if (key == kKEY_RIGHT) {
448 m_regex_editor.move(LineEdit::RIGHT);
449 } else if (key == kKEY_LEFT) {
450 m_regex_editor.move(LineEdit::LEFT);
451 } else if (key == kKEY_BACKS) {
452 m_regex_editor.remove_bwd();
453 } else if (key == kKEY_DEL) {
454 m_regex_editor.remove_fwd();
455 } else if (key == kKEY_HOME || key == kKEY_CTRLA) {
456 m_regex_editor.move(LineEdit::BEGIN);
457 } else if (key == kKEY_END || key == kKEY_CTRLE) {
458 m_regex_editor.move(LineEdit::END);
459 } else if (key == kKEY_CTRLL) {
460 m_regex_editor.reset();
461 } else if (ischar(key) && isprint(key)) {
462 m_regex_editor.append(key);
463 } else {
464 return;
465 }
466 update_bar(regex_prompt, m_regex_editor);
467 break;
468 default:
469 assert(! "Internal screen error");
470 }
471}
472
473void Screen::update_bar(std::string const& prompt, LineEdit const& le)
474{
475 werase(m_twin);
476 wprintw(m_twin, "%s", prompt.c_str());
477 wprintw(m_twin, "%s", le.current().c_str());
478 wmove(m_twin, 0, le.cursor() + prompt.size());
479 wnoutrefresh(m_twin);
480 doupdate();
481}
482
483void Screen::show_help() const
484{
485 int const col1 = 2;
486 int const col2 = 33;
487
488 int const cols = 70;
489 int const lines = 16;
490 int const x_pos = (COLS - cols) / 2;
491 int const y_pos = (LINES - lines) / 2;
492 WINDOW* help_win = newwin(lines, cols, y_pos, x_pos);
493 box(help_win, 0, 0);
494 wmove(help_win, 0, 6);
495 wprintw(help_win, " Help ");
496 wmove(help_win, 1, col1);
497 wprintw(help_win, "Press the key to activate the corresponding behaviour.");
498 wmove(help_win, 3, col1);
499 wprintw(help_win, "Sort:");
500 wmove(help_win, 4, col1);
501 wprintw(help_win, "- t: sort by last view time");
502 wmove(help_win, 5, col1);
503 wprintw(help_win, "- d: sort by DOM ID");
504 wmove(help_win, 6, col1);
505 wprintw(help_win, "- r: sort by avg hit rate");
506 wmove(help_win, 7, col1);
507 wprintw(help_win, "- n: sort by run number");
508 wmove(help_win, 8, col1);
509 wprintw(help_win, "- l: sort by label (name)");
510 wmove(help_win, 9, col1);
511 wprintw(help_win, "- i: invert sorting");
512 wmove(help_win, 3, col2);
513 wprintw(help_win, "Screen:");
514 wmove(help_win, 4, col2);
515 wprintw(help_win, "- c: clear the screen");
516 wmove(help_win, 5, col2);
517 wprintw(help_win, "- Arrow keys: move selection/view");
518 wmove(help_win, 6, col2);
519 wprintw(help_win, "- g: move selection to top");
520 wmove(help_win, 7, col2);
521 wprintw(help_win, "- G: move selection to bottom");
522 wmove(help_win, 8, col2);
523 wprintw(help_win, "- /: open search prompt");
524 wmove(help_win, 9, col2);
525 wprintw(help_win, "- %%: open regex prompt");
526 wmove(help_win, 10, col2);
527 wprintw(help_win, "- w: wipe the search/regex status");
528 wmove(help_win, 11, col2);
529 wprintw(help_win, "- m: toggle grouping matches on top");
530 wmove(help_win, 13, col1);
531 wprintw(help_win, "Press ESC to dismiss this win");
532 wmove(help_win, 14, col1);
533 wprintw(help_win, "Version %s", clbsk::version::v().c_str());
534
535 wnoutrefresh(help_win);
536 delwin(help_win);
537 reset_cursor();
538}
539
540bool is_problematic(mon_channel const& channel)
541{
542 return
543 ! channel.syncd()
544 || channel.mean() > default_hit_counter_threshold
545 || boost::chrono::duration_cast<boost::chrono::seconds>(channel.last_view())
546 > boost::chrono::seconds(2);
547}
548
549void Screen::write_head() const
550{
551 bool const problematic = std::find_if(
552 m_list.begin()
553 , m_list.end()
555 ) != m_list.end();
556
557 werase(m_hwin);
558 wmove(m_hwin, 0, 0);
559
560 if (m_smatched.empty()) {
561 wprintw(
562 m_hwin
563 , "CLBSK - %s - # CLBs:%c %ld - 'q' to quit, 'h' for help"
564 , m_heading.c_str()
565 , problematic ? '!' : ' '
566 , m_list.size()
567 );
568 } else {
569 wprintw(
570 m_hwin
571 , "CLBSK - %s - # CLBs:%c %ld (%ld) - 'q' to quit, 'h' for help"
572 , m_heading.c_str()
573 , problematic ? '!' : ' '
574 , m_list.size()
575 , m_smatched.size()
576 );
577 }
578
579 wnoutrefresh(m_hwin);
580 reset_cursor();
581}
582
583void Screen::write_page()
584{
585 werase(m_cwin);
586 box(m_cwin, 0, 0);
587 if (m_upper != 0) {
588 mvwaddstr(m_cwin, 0, 3, "^");
589 }
590
591 if (m_lower < static_cast<int>(m_list.size())) {
592 mvwaddstr(m_cwin, LINES - 3, 3, "v");
593 }
594
595 wmove(m_cwin, 1, 2);
596 print_table_head(m_cwin, m_offset);
597
598 int count = 1;
599 typedef ChList::const_iterator citerator;
600
601 citerator it = m_list.begin(), et = m_list.end();
602 std::advance(it, m_upper);
603
604 for (int vcount = m_upper; it != et && vcount < m_lower; ++vcount, ++it) {
605 wmove(m_cwin, ++count, 2);
607 m_cwin
608 , it
609 , m_linebuffer
610 , COLS + m_offset - 3
611 , m_offset
612 , std::find(m_smatched.begin(), m_smatched.end(), it) != m_smatched.end()
613 );
614
615 if (count - 2 == m_selected - m_upper) {
616 mvwaddstr(m_cwin, count, 1, ">");
617 }
618 }
619 wnoutrefresh(m_cwin);
620 reset_cursor();
621}
622
623void Screen::move_limits()
624{
625 if (m_upper > m_selected) {
626 m_upper = m_selected;
627 m_lower = m_upper + LINES - 5;
628 }
629 if (m_lower <= m_selected) {
630 m_lower = m_selected + 1;
631 m_upper = m_lower - LINES + 5;
632 }
633}
634
635void Screen::show_filtered(CLBCommonHeader const* header)
636{
637 ChList::const_iterator it = m_list.begin();
638 std::advance(it, m_selected);
639
640 if (header->domIdentifier() == it->domid()) {
641 werase(m_cwin);
642 box(m_cwin, 0, 0);
643 wmove(m_cwin, 1, 2);
644 wprintw(m_cwin, "Press ESC to return back.");
645
646 wmove(m_cwin, 2, 2);
647 print_table_head(m_cwin, 0);
648 wmove(m_cwin, 3, 2);
649 print_chan(m_cwin, it, m_linebuffer, COLS - 3, 0, false);
650
651 uint32_t const*const data = static_cast<uint32_t const*>(
652 static_cast<void const*>(header + 1));
653
654 wmove(m_cwin, 5, 2);
655
656 bool const valid = validTimeStamp(*header);
657
659 m_cwin,
660 header->timeStamp(),
661 m_linebuffer,
662 COLS - 3,
663 0,
664 valid);
665
666 wmove(m_cwin, 7, 2);
667
668 for (int i = 0; i < 31; ++i) {
669 wprintw(m_cwin, "CH%02d: %5d", i, ntohl(data[i]));
670
671 int y = 0, x = 0;
672 getyx(m_cwin, y, x);
673
674 if (x + 15 > COLS) {
675 wmove(m_cwin, y + 1, 2);
676 } else {
677 wmove(m_cwin, y, x + 2);
678 }
679 }
680
681 int y = 0, x = 0;
682 getyx(m_cwin, y, x);
683
684 char const*const raw_data = static_cast<char const*>(
685 static_cast<void const*>(header));
686
687 SCData const*const scdata = static_cast<SCData const*>(
688 static_cast<void const*>(
689 raw_data + sizeof(*header) + 31 * sizeof(uint32_t)));
690
691 wmove(m_cwin, y + 2, 2);
692 wprintw(m_cwin, "Validity: 0x%x", ntohl(scdata->valid));
693
694 wmove(m_cwin, y + 3, 2);
695 wprintw(
696 m_cwin,
697 "Yaw: %4.4f Pitch: %4.4f Roll: %4.4f deg",
698 ntohl_f(scdata->ahrs.yaw),
699 ntohl_f(scdata->ahrs.pitch),
700 ntohl_f(scdata->ahrs.roll));
701
702 wmove(m_cwin, y + 4, 2);
703 wprintw(
704 m_cwin,
705 "Acceleration: %4.4f, %4.4f, %4.4f g",
706 ntohl_f(scdata->ahrs.ax),
707 ntohl_f(scdata->ahrs.ay),
708 ntohl_f(scdata->ahrs.az));
709
710 wmove(m_cwin, y + 5, 2);
711 wprintw(
712 m_cwin,
713 "Gyroscope: %4.4f, %4.4f, %4.4f deg/sec",
714 ntohl_f(scdata->ahrs.gx),
715 ntohl_f(scdata->ahrs.gy),
716 ntohl_f(scdata->ahrs.gz));
717
718 wmove(m_cwin, y + 6, 2);
719 wprintw(m_cwin,
720 "Compass: %4.4f, %4.4f, %4.4f gauss",
721 ntohl_f(scdata->ahrs.hx),
722 ntohl_f(scdata->ahrs.hy),
723 ntohl_f(scdata->ahrs.hz));
724
725 wmove(m_cwin, y + 7, 2);
726 wprintw(m_cwin, "Temperature: %.2f Celsius", ntohs(scdata->temp) / 100.);
727
728 wmove(m_cwin, y + 8, 2);
729 wprintw(m_cwin, "Humidity: %.2f RH", ntohs(scdata->humidity) / 100.);
730
731 wnoutrefresh(m_cwin);
732 reset_cursor();
733 }
734}
735
736bool matches(mon_channel const& ch, std::string const& pattern)
737{
738 return
739 pattern.size() != 0
740 && (
741 ch.name().find(pattern) != std::string::npos
742 || ch.mac_address().find(pattern) != std::string::npos
743 || boost::lexical_cast<std::string>(ch.domid()).find(pattern) != std::string::npos
744 );
745}
746
747void Screen::search()
748{
749 m_smatched.clear();
750
751 for (
752 ChList::const_iterator it = m_list.begin(), et = m_list.end()
753 ; it != et
754 ; ++it
755 ) {
756 if (matches(*it, m_search_editor.current())) {
757 m_smatched.push_back(it);
758 }
759 }
760}
761
762bool matches(mon_channel const& ch, boost::regex const& regex)
763{
764 return
765 boost::regex_match(ch.name(), regex)
766 || boost::regex_match(ch.mac_address(), regex)
767 || boost::regex_match(boost::lexical_cast<std::string>(ch.domid()), regex);
768}
769
770void Screen::filter()
771{
772 m_smatched.clear();
773
774 for (
775 ChList::const_iterator it = m_list.begin(), et = m_list.end()
776 ; it != et
777 ; ++it
778 ) {
779 if (matches(*it, m_regex)) {
780 m_smatched.push_back(it);
781 }
782 }
783}
784
785bool Screen::is_filter() const
786{
787 return status == kSINGLE;
788}
789
790bool Screen::is_user_input() const
791{
792 return status >= kSEARCH;
793}
794
796{
798
799 public:
800
801 explicit
802 domid_comparator(bool reverse)
803 :
804 m_reverse(reverse)
805 {}
806
807 bool operator ()(mon_channel const& first, mon_channel const& second)
808 {
809 return m_reverse
810 ? first.domid() < second.domid()
811 : first.domid() > second.domid();
812 }
813};
814
816{
818
819 public:
820
821 explicit
823 :
824 m_reverse(reverse)
825 {}
826
827 bool operator ()(mon_channel const& first, mon_channel const& second)
828 {
829 using namespace boost::chrono;
830 return m_reverse
831 ? duration_cast<seconds>(first.last_view()) < duration_cast<seconds>(second.last_view())
832 : duration_cast<seconds>(first.last_view()) > duration_cast<seconds>(second.last_view());
833 }
834};
835
837{
839
840 public:
841
842 explicit
844 :
845 m_reverse(reverse)
846 {}
847
848 bool operator ()(mon_channel const& first, mon_channel const& second)
849 {
850 return m_reverse
851 ? first.mean() < second.mean()
852 : first.mean() > second.mean();
853 }
854};
855
857{
859
860 public:
861
862 explicit
864 :
865 m_reverse(reverse)
866 {}
867
868 bool operator ()(mon_channel const& first, mon_channel const& second)
869 {
870 return m_reverse
871 ? first.run_number() < second.run_number()
872 : first.run_number() > second.run_number();
873 }
874};
875
877{
879
880 public:
881
882 explicit
883 name_comparator(bool reverse)
884 :
885 m_reverse(reverse)
886 {}
887
888 bool operator ()(mon_channel const& first, mon_channel const& second)
889 {
890 return m_reverse
891 ? first.name() < second.name()
892 : first.name() > second.name();
893 }
894};
895
897{
899
900 bool belongs(mon_channel const& ch)
901 {
903 for (
904 citer it = m_matching->begin(), et = m_matching->end()
905 ; it != et
906 ; ++it
907 ) {
908 if ((*(*it)).domid() == ch.domid()) {
909 return true;
910 }
911 }
912
913 return false;
914 }
915
916 public:
917
920 ) : m_matching(&matching)
921 {}
922
923 bool operator ()(mon_channel const& first, mon_channel const& second)
924 {
925 bool const first_matches = belongs(first);
926 bool const second_matches = belongs(second);
927
928 return first_matches || !second_matches;
929 }
930};
931
932void Screen::sort_channels()
933{
934 switch (sort) {
935 case kDOMID:
936 m_list.sort(domid_comparator(m_sort_reverse));
937 break;
938 case kLAST_VIEW:
939 m_list.sort(last_view_comparator(m_sort_reverse));
940 break;
941 case kRATE:
942 m_list.sort(hit_rate_comparator(m_sort_reverse));
943 break;
944 case kRUNNO:
945 m_list.sort(run_number_comparator(m_sort_reverse));
946 break;
947 case kNAME:
948 m_list.sort(name_comparator(m_sort_reverse));
949 break;
950 default:
951 assert(!"Sort internal error");
952 }
953
954 if (m_matching_first && !m_smatched.empty() && go_match != NONE) {
955 m_list.sort(match_comparator(m_smatched));
956 }
957}
958
959void print_table_head(WINDOW* win, int offset)
960{
961 static const char head[] =
962 "DOMID MAC ADDRESS Name Run # Hit rate (min, max, avg) Last viewed S Delta time";
963
964 if (static_cast<int>(strlen(head)) > offset) {
965 int const max_in_string = strlen(head) - offset;
966 int const nchars = std::min(COLS - 4, max_in_string);
967 wprintw(win, "%.*s", nchars, head + offset);
968 }
969}
970
972 WINDOW* win
973 , ChList::const_iterator const& it
974 , std::vector<char>& buffer
975 , int line_size
976 , int offset
977 , bool highlight
978) {
979 assert(offset <= line_size);
980
981 int const last_view = boost::chrono::duration_cast<boost::chrono::seconds>(
982 it->last_view()
983 ).count();
984
985 int const size = snprintf(
986 &buffer.front(),
987 line_size,
988 "%-9d %-17s %-8s %-6u %7.2f, %7.2f, %7.2f kHz %4d sec ago %s %ld ms",
989 it->domid(),
990 it->mac_address().c_str(),
991 it->name().c_str(),
992 it->run_number(),
993 it->min() / 100.,
994 it->max() / 100.,
995 it->mean() / 100.,
996 last_view,
997 it->syncd() ? "*" : " ",
998 it->avg_delta_time());
999
1000 if (offset < std::min(line_size, size)) {
1001 if (highlight) {
1002 wattron(win, A_REVERSE);
1003 } else {
1004 wattroff(win, A_REVERSE);
1005 }
1006
1007 if (!it->syncd()) {
1008 wattron(win, NOSYNC);
1009 }
1010
1011 if (it->mean() > default_hit_counter_threshold) {
1012 wattron(win, HIRATE);
1013 }
1014
1015 if (last_view > 2) {
1016 wattron(win, NODATA);
1017 }
1018
1019 wprintw(win, "%s", &buffer[offset]);
1020
1021 if (size > line_size) {
1022 wprintw(win, "$");
1023 }
1024 }
1025
1026 wattrset(win, GROUND);
1027}
1028
1030 WINDOW* win,
1031 UTCTime const& tstamp,
1032 std::vector<char>& buffer,
1033 int line_size,
1034 int offset,
1035 bool validity)
1036{
1037 assert(offset <= line_size);
1038
1039 std::ostringstream oss;
1040
1041 oss << UTCTime_h(tstamp, validity);
1042
1043 int const size = snprintf(
1044 &buffer.front(),
1045 line_size,
1046 "Sec: %d, Tic: %-8d - %s",
1047 tstamp.sec(),
1048 tstamp.tics(),
1049 oss.str().c_str());
1050
1051 if (offset < std::min(line_size, size)) {
1052 wprintw(win, "%s", &buffer[offset]);
1053
1054 if (size > line_size) {
1055 wprintw(win, "$");
1056 }
1057 }
1058}
1059
1060} // ns gui
bool operator()(mon_channel const &first, mon_channel const &second)
Definition gui.cpp:807
domid_comparator(bool reverse)
Definition gui.cpp:802
hit_rate_comparator(bool reverse)
Definition gui.cpp:843
bool operator()(mon_channel const &first, mon_channel const &second)
Definition gui.cpp:848
last_view_comparator(bool reverse)
Definition gui.cpp:822
bool operator()(mon_channel const &first, mon_channel const &second)
Definition gui.cpp:827
std::list< ChList::const_iterator > const * m_matching
Definition gui.cpp:898
match_comparator(std::list< ChList::const_iterator > const &matching)
Definition gui.cpp:918
bool belongs(mon_channel const &ch)
Definition gui.cpp:900
bool operator()(mon_channel const &first, mon_channel const &second)
Definition gui.cpp:923
name_comparator(bool reverse)
Definition gui.cpp:883
bool operator()(mon_channel const &first, mon_channel const &second)
Definition gui.cpp:888
run_number_comparator(bool reverse)
Definition gui.cpp:863
bool operator()(mon_channel const &first, mon_channel const &second)
Definition gui.cpp:868
bool validTimeStamp(CLBCommonHeader const &header)
bool ischar(int key)
Definition gui.cpp:43
void async_commit(boost::asio::deadline_timer &timer, gui::Screen &screen, boost::system::error_code const &error)
Definition gui.cpp:50
void async_win_resize(boost::asio::signal_set &window_resize, gui::Screen &screen, boost::system::error_code const &error, int signum)
Definition gui.cpp:106
static const int default_hit_counter_threshold
Definition gui.cpp:15
void async_cin(boost::asio::posix::stream_descriptor &keyb, char &key, gui::Screen &screen, const boost::system::error_code &error, std::size_t bytes_transferred)
Definition gui.cpp:68
std::pair< int, int > window_size()
Definition gui.cpp:127
Definition gui.cpp:136
void print_table_head(WINDOW *win, int offset)
Definition gui.cpp:959
void print_timestamp(WINDOW *win, UTCTime const &tstamp, std::vector< char > &buffer, int line_size, int offset, bool validity)
Definition gui.cpp:1029
bool is_problematic(mon_channel const &channel)
Definition gui.cpp:540
bool matches(mon_channel const &ch, std::string const &pattern)
Definition gui.cpp:736
void print_chan(WINDOW *win, ChList::const_iterator const &it, std::vector< char > &buffer, int line_size, int offset, bool highlight)
Definition gui.cpp:971
UTCTime timeStamp() const
uint32_t domIdentifier() const
Auxiliary data structure for alignment of data.
Definition JManip.hh:266
Auxiliary data structure for alignment of data.
Definition JManip.hh:298
uint32_t sec() const
Definition utctime.hh:17
uint32_t tics() const
Definition utctime.hh:22