ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
log_widget.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #include "ui/log_widget.h"
33 
34 namespace colmap {
35 
36 LogWidget::LogWidget(QWidget* parent, const int max_num_blocks) {
37  setWindowFlags(Qt::Window);
38  setWindowTitle("Log");
39  resize(320, parent->height());
40 
41  QGridLayout* grid = new QGridLayout(this);
42  grid->setContentsMargins(5, 10, 5, 5);
43 
44  qRegisterMetaType<QTextCursor>("QTextCursor");
45  qRegisterMetaType<QTextBlock>("QTextBlock");
46 
47  QTimer* timer = new QTimer(this);
48  connect(timer, &QTimer::timeout, this, &LogWidget::Flush);
49  timer->start(100);
50 
51  // Comment these lines if debugging, otherwise debug messages won't appear
52  // on the console and the output is lost in the log widget when crashing
54  std::cout, LogWidget::Update, this);
56  std::cerr, LogWidget::Update, this);
58  std::clog, LogWidget::Update, this);
59 
60  QHBoxLayout* left_button_layout = new QHBoxLayout();
61 
62  QPushButton* save_log_button = new QPushButton(tr("Save"), this);
63  connect(save_log_button, &QPushButton::released, this, &LogWidget::SaveLog);
64  left_button_layout->addWidget(save_log_button);
65 
66  QPushButton* clear_button = new QPushButton(tr("Clear"), this);
67  connect(clear_button, &QPushButton::released, this, &LogWidget::Clear);
68  left_button_layout->addWidget(clear_button);
69 
70  grid->addLayout(left_button_layout, 0, 0, Qt::AlignLeft);
71 
72  QHBoxLayout* right_button_layout = new QHBoxLayout();
73 
74  grid->addLayout(right_button_layout, 0, 1, Qt::AlignRight);
75 
76  text_box_ = new QPlainTextEdit(this);
77  text_box_->setReadOnly(true);
78  text_box_->setMaximumBlockCount(max_num_blocks);
79  text_box_->setWordWrapMode(QTextOption::NoWrap);
80  text_box_->setFont(QFont("Courier", 10));
81  grid->addWidget(text_box_, 1, 0, 1, 2);
82 }
83 
85  if (log_file_.is_open()) {
86  log_file_.close();
87  }
88 
89  delete cout_redirector_;
90  delete cerr_redirector_;
91  delete clog_redirector_;
92 }
93 
94 void LogWidget::Append(const std::string& text) {
95  QMutexLocker locker(&mutex_);
96  text_queue_ += text;
97 
98  // Dump to log file
99  if (log_file_.is_open()) {
100  log_file_ << text;
101  }
102 }
103 
105  QMutexLocker locker(&mutex_);
106 
107  if (text_queue_.size() > 0) {
108  // Write to log widget
109  text_box_->moveCursor(QTextCursor::End);
110  text_box_->insertPlainText(QString::fromStdString(text_queue_));
111  text_box_->moveCursor(QTextCursor::End);
112  text_queue_.clear();
113  }
114 }
115 
117  QMutexLocker locker(&mutex_);
118  text_queue_.clear();
119  text_box_->clear();
120 }
121 
122 void LogWidget::Update(const char* text, std::streamsize count,
123  void* log_widget_ptr) {
124  std::string text_str;
125  for (std::streamsize i = 0; i < count; ++i) {
126  if (text[i] == '\n') {
127  text_str += "\n";
128  } else {
129  text_str += text[i];
130  }
131  }
132 
133  LogWidget* log_widget = static_cast<LogWidget*>(log_widget_ptr);
134  log_widget->Append(text_str);
135 }
136 
137 void LogWidget::SaveLog() {
138  const std::string log_path =
139  QFileDialog::getSaveFileName(this, tr("Select path to log file"), "",
140  tr("Log (*.log)"))
141  .toUtf8()
142  .constData();
143 
144  if (log_path == "") {
145  return;
146  }
147 
148  std::ofstream file(log_path, std::ios::app);
149  CHECK(file.is_open()) << log_path;
150  file << text_box_->toPlainText().toUtf8().constData();
151 }
152 
153 } // namespace colmap
int count
LogWidget(QWidget *parent, const int max_num_blocks=100000)
Definition: log_widget.cc:36
void Append(const std::string &text)
Definition: log_widget.cc:94