Developer Documentation
loggerWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 
44 
45 
46 
47 #include "loggerWidget.hh"
48 
50 
52 
53 LoggerWidget::LoggerWidget( QWidget *parent)
54  : QWidget(parent),
55  newData_(true)
56 {
57  // Don't delete this widget on close actions
58  // since it may be embedded in different widget
59  // containers at the same time
60  setAttribute(Qt::WA_DeleteOnClose, false);
61 
62  QVBoxLayout* vlayout = new QVBoxLayout();
63  QHBoxLayout* hlayout = new QHBoxLayout();
64 
65  list_ = new QListWidget();
66 
67  list_->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
68  list_->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
69  list_->setFocusPolicy(Qt::NoFocus);
70  list_->setSelectionMode(QAbstractItemView::ExtendedSelection);
71  list_->setUniformItemSizes(true);
72 
73  QString path = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator();
74 
75  // ============================
76  // Context Menu
77  // ============================
78  context_ = new QMenu(tr("Log Viewer"));
79 
80  QAction* copyAction = new QAction(QIcon(path + "edit-copy.png"), tr("Copy"),0);
81  copyAction->setShortcut( QKeySequence("Ctrl+C") );
82  QAction* selectAction = new QAction(tr("Select All"),0);
83  selectAction->setShortcut( QKeySequence("Ctrl+A") );
84 
85  connect (copyAction, SIGNAL(triggered()), this, SLOT(copySelected()));
86  connect (selectAction, SIGNAL(triggered()), list_, SLOT(selectAll()));
87 
88  context_->addAction(copyAction);
89  context_->addSeparator();
90  context_->addAction(selectAction);
91 
92 
93  // ============================
94  // Filters Menu
95  // ============================
96  filterMenu_ = new QMenu(tr("Log Viewer"));
97 
98  openMeshFilterAction_ = new QAction(QIcon(path + "edit-copy.png"), tr("Enable OpenMesh error messages"),0);
99  openMeshFilterAction_->setCheckable(true);
100 
101 
102  if ( OpenFlipperSettings().value("Core/Gui/LogWindow/OpenMeshErrors",true).toBool() ) {
103  openMeshFilterAction_->setChecked( true );
104  omerr().enable();
105  } else {
106  openMeshFilterAction_->setChecked( false );
107  omerr().disable();
108  }
109 
110  filterMenu_->addAction(openMeshFilterAction_);
111 
112  // ============================
113  // Scrollbar
114  // ============================
115  blockNext_ = false;
116 
117  connect (&loggerUpdateTimer_, SIGNAL(timeout ()), this, SLOT(slotScrollUpdate()));
118 
119  // Single shot timer every 500 msecs
120  loggerUpdateTimer_.setSingleShot(true);
121  loggerUpdateTimer_.setInterval(500);
122 
123  allButton_ = new QPushButton(QIcon(path + "status_all.png"),tr("All Messages"));
124  allButton_->setCheckable(true);
125  allButton_->setAutoExclusive(true);
126  infoButton_ = new QPushButton(QIcon(path + "status_green.png"),tr("Information"));
127  infoButton_->setCheckable(true);
128  infoButton_->setAutoExclusive(true);
129  warnButton_ = new QPushButton(QIcon(path + "status_yellow.png"),tr("Warnings"));
130  warnButton_->setCheckable(true);
131  warnButton_->setAutoExclusive(true);
132  errorButton_ = new QPushButton(QIcon(path + "status_red.png"),tr("Errors"));
133  errorButton_->setCheckable(true);
134  errorButton_->setAutoExclusive(true);
135 
136  filterButton_ = new QPushButton(QIcon(path + "status_filter.png"),tr("Set Filters"));
137  filterButton_->setCheckable(false);
138 
139  allButton_->setChecked(true);
140 
141  connect(allButton_, SIGNAL(clicked()), this, SLOT(updateList()));
142  connect(infoButton_, SIGNAL(clicked()), this, SLOT(updateList()));
143  connect(warnButton_, SIGNAL(clicked()), this, SLOT(updateList()));
144  connect(errorButton_, SIGNAL(clicked()), this, SLOT(updateList()));
145  connect(filterButton_,SIGNAL(clicked()), this, SLOT(slotFilterMenu()));
146 
147  clearButton_ = new QPushButton(QIcon(path + "edit-clear.png"),tr("Clear Messages"));
148  connect(clearButton_, SIGNAL(clicked()), list_, SLOT(clear()));
149 
150  hlayout->addWidget( allButton_ );
151  hlayout->addWidget( infoButton_ );
152  hlayout->addWidget( warnButton_ );
153  hlayout->addWidget( errorButton_ );
154  hlayout->addStretch();
155  hlayout->addWidget( filterButton_ );
156  hlayout->addStretch();
157  hlayout->addWidget( clearButton_ );
158 
159  hlayout->setSpacing(0);
160  hlayout->setContentsMargins (0,0,0,0);
161  vlayout->setSpacing(0);
162  vlayout->setContentsMargins (0,0,0,0);
163 
164  vlayout->addWidget(list_);
165  vlayout->addLayout( hlayout );
166 
167  setLayout( vlayout );
168 }
169 
170 LoggerWidget::~LoggerWidget()
171 {
172  delete clearButton_;
173  delete errorButton_;
174  delete warnButton_;
175  delete infoButton_;
176  delete allButton_;
177  delete context_;
178  delete list_;
179 }
180 
181 
182 //-------------------------------------------------------------------------------------
183 
185 void LoggerWidget::append(const QString& _text, Logtype _type){
186 
187  list_->addItem(_text);
188 
189  QListWidgetItem* item = list_->item( list_->count()-1 );
190 
191  if ( allButton_->isChecked() )
192  item->setHidden(false);
193  else
194  item->setHidden(true);
195 
196  switch (_type) {
197  case LOGINFO:
198  item->setForeground( QBrush(QColor(Qt::darkGreen)) );
199  item->setBackground( QBrush(QColor(225,255,225), Qt::SolidPattern) );
200 
201  if ( infoButton_->isChecked() )
202  item->setHidden(false);
203  break;
204  case LOGOUT:
205  item->setForeground( QPalette{}.windowText() );
206  break;
207  case LOGWARN:
208  item->setForeground( QBrush(QColor(160,160,0)) );
209  item->setBackground( QBrush(QColor(255,240,200),Qt::SolidPattern) );
210 
211  if ( warnButton_->isChecked() )
212  item->setHidden(false);
213  break;
214  case LOGERR:
215  item->setForeground( QBrush(QColor(Qt::red)) );
216  item->setBackground( QBrush(QColor(255,225,225),Qt::SolidPattern) );
217 
218  if ( errorButton_->isChecked() )
219  item->setHidden(false);
220  break;
221  case LOGSTATUS:
222  item->setForeground( QBrush(QColor(Qt::blue)) );
223  item->setBackground( QBrush(QColor(255,225,225),Qt::SolidPattern) );
224 
225  if ( errorButton_->isChecked() )
226  item->setHidden(false);
227  break;
228  }
229 
230  // If the logger is hidden, we just ignore the update ... done by showEvent later
231  if ( isHidden() )
232  return;
233 
234  // Remember that we have new logs to show
235  newData_ = true;
236 
237  // Check if we already have a running timer.
238  // If so, the timeout of that timer will trigger the redraw.
239  // Otherwise, we redraw and start the timer to block concurrent redraws.
240  // Only if new data is available, the redraw at the timers timeout will be done.
241  if ( ! loggerUpdateTimer_.isActive() ) {
242  // Update the logger
243  list_->scrollToBottom();
244 
245  // Remember that there is no new data now.
246  // This might change again on a call to this function, while the timer is active.
247  newData_ = false;
248 
249  // start the timer
250  loggerUpdateTimer_.start();
251  }
252 
253 }
254 
255 //-------------------------------------------------------------------------------------
256 
258 
259  // If there is data to show, do it.
260  if ( newData_ ) {
261  list_->scrollToBottom();
262  newData_ = false;
263  }
264 
265 }
266 
267 //-------------------------------------------------------------------------------------
268 
271 
272  QColor color;
273 
274  if ( infoButton_->isChecked() )
275  color = QColor(Qt::darkGreen);
276  else if ( warnButton_->isChecked() )
277  color = QColor(160,160,0);
278  else if ( errorButton_->isChecked() )
279  color = QColor(Qt::red);
280  else
281  color = QColor(Qt::black);
282 
283  if (color == QColor(Qt::black)){
284 
285  for (int i=0; i < list_->count(); i++)
286  list_->item( i )->setHidden(false);
287 
288  } else {
289 
290  for (int i=0; i < list_->count(); i++)
291  if ( list_->item(i)->foreground().color() == color )
292  list_->item( i )->setHidden(false);
293  else
294  list_->item( i )->setHidden(true);
295  }
296 
297  list_->scrollToBottom();
298 }
299 
300 //-------------------------------------------------------------------------------------
301 void LoggerWidget::showEvent ( QShowEvent * /*event*/ ) {
302  list_->scrollToBottom();
303 }
304 
305 //-------------------------------------------------------------------------------------
306 
308 void LoggerWidget::keyPressEvent (QKeyEvent * _event ) {
309  // Return key event to parent if not one of the standard key combinations ( ... Core )
310  if ( (_event->modifiers() & Qt::ControlModifier ) && ( _event->key() == Qt::Key_C ) )
311  copySelected();
312 
313  else if ( (_event->modifiers() & Qt::ControlModifier ) && ( _event->key() == Qt::Key_A ) )
314  list_->selectAll();
315 
316  else
317  _event->ignore();
318 }
319 
320 //-------------------------------------------------------------------------------------
321 
323 void LoggerWidget::contextMenuEvent ( QContextMenuEvent * event ){
324 
325  QPoint p = list_->mapToGlobal( event->pos() );
326 
327  context_->popup( p );
328 
329 }
330 
331 //-------------------------------------------------------------------------------------
332 
335 
336  QString str = "";
337 
338  for (int i=0; i < list_->selectedItems().count(); i++)
339  str += (list_->selectedItems()[i])->text() + "\n";
340 
341  QClipboard *clipboard = QApplication::clipboard();
342 
343  clipboard->setText(str);
344 }
345 
346 //-------------------------------------------------------------------------------------
347 
349  filterMenu_->popup( list_->mapToGlobal(filterButton_->pos()) );
350 }
351 
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Logtype
Log types for Message Window.
void updateList()
update the list if a button was pressed
void append(const QString &_text, Logtype _type)
Append a new logmessage to log viewer.
void slotScrollUpdate()
Called when we want to scroll to the bottom.
void copySelected()
copy Selected rows to clipboard
void slotFilterMenu()
Called when filter button is pressed.
void showEvent(QShowEvent *event)
Called when the widget is shown.
void contextMenuEvent(QContextMenuEvent *event)
Show context menu.
void keyPressEvent(QKeyEvent *_event)
Grab key events.