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 
void copySelected()
copy Selected rows to clipboard
Logtype
Log types for Message Window.
void keyPressEvent(QKeyEvent *_event)
Grab key events.
void contextMenuEvent(QContextMenuEvent *event)
Show context menu.
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
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 slotFilterMenu()
Called when filter button is pressed.
void slotScrollUpdate()
Called when we want to scroll to the bottom.
void showEvent(QShowEvent *event)
Called when the widget is shown.