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 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 
52 
53 #include "loggerWidget.hh"
54 
56 
58 
59 LoggerWidget::LoggerWidget( QWidget *parent)
60  : QWidget(parent),
61  newData_(true)
62 {
63  // Don't delete this widget on close actions
64  // since it may be embedded in different widget
65  // containers at the same time
66  setAttribute(Qt::WA_DeleteOnClose, false);
67 
68  QVBoxLayout* vlayout = new QVBoxLayout();
69  QHBoxLayout* hlayout = new QHBoxLayout();
70 
71  list_ = new QListWidget();
72 
73  list_->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
74  list_->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
75  list_->setFocusPolicy(Qt::NoFocus);
76  list_->setSelectionMode(QAbstractItemView::ExtendedSelection);
77  list_->setUniformItemSizes(true);
78 
79  QString path = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator();
80 
81  // ============================
82  // Context Menu
83  // ============================
84  context_ = new QMenu(tr("Log Viewer"));
85 
86  QAction* copyAction = new QAction(QIcon(path + "edit-copy.png"), tr("Copy"),0);
87  copyAction->setShortcut( QKeySequence("Ctrl+C") );
88  QAction* selectAction = new QAction(tr("Select All"),0);
89  selectAction->setShortcut( QKeySequence("Ctrl+A") );
90 
91  connect (copyAction, SIGNAL(triggered()), this, SLOT(copySelected()));
92  connect (selectAction, SIGNAL(triggered()), list_, SLOT(selectAll()));
93 
94  context_->addAction(copyAction);
95  context_->addSeparator();
96  context_->addAction(selectAction);
97 
98 
99  // ============================
100  // Filters Menu
101  // ============================
102  filterMenu_ = new QMenu(tr("Log Viewer"));
103 
104  openMeshFilterAction_ = new QAction(QIcon(path + "edit-copy.png"), tr("Enable OpenMesh error messages"),0);
105  openMeshFilterAction_->setCheckable(true);
106 
107 
108  if ( OpenFlipperSettings().value("Core/Gui/LogWindow/OpenMeshErrors",true).toBool() ) {
109  openMeshFilterAction_->setChecked( true );
110  omerr().enable();
111  } else {
112  openMeshFilterAction_->setChecked( false );
113  omerr().disable();
114  }
115 
116  filterMenu_->addAction(openMeshFilterAction_);
117 
118  // ============================
119  // Scrollbar
120  // ============================
121  blockNext_ = false;
122 
123  connect (&loggerUpdateTimer_, SIGNAL(timeout ()), this, SLOT(slotScrollUpdate()));
124 
125  // Single shot timer every 500 msecs
126  loggerUpdateTimer_.setSingleShot(true);
127  loggerUpdateTimer_.setInterval(500);
128 
129  allButton_ = new QPushButton(QIcon(path + "status_all.png"),tr("All Messages"));
130  allButton_->setCheckable(true);
131  allButton_->setAutoExclusive(true);
132  infoButton_ = new QPushButton(QIcon(path + "status_green.png"),tr("Informations"));
133  infoButton_->setCheckable(true);
134  infoButton_->setAutoExclusive(true);
135  warnButton_ = new QPushButton(QIcon(path + "status_yellow.png"),tr("Warnings"));
136  warnButton_->setCheckable(true);
137  warnButton_->setAutoExclusive(true);
138  errorButton_ = new QPushButton(QIcon(path + "status_red.png"),tr("Errors"));
139  errorButton_->setCheckable(true);
140  errorButton_->setAutoExclusive(true);
141 
142  filterButton_ = new QPushButton(QIcon(path + "status_filter.png"),tr("Set Filters"));
143  filterButton_->setCheckable(false);
144 
145  allButton_->setChecked(true);
146 
147  connect(allButton_, SIGNAL(clicked()), this, SLOT(updateList()));
148  connect(infoButton_, SIGNAL(clicked()), this, SLOT(updateList()));
149  connect(warnButton_, SIGNAL(clicked()), this, SLOT(updateList()));
150  connect(errorButton_, SIGNAL(clicked()), this, SLOT(updateList()));
151  connect(filterButton_,SIGNAL(clicked()), this, SLOT(slotFilterMenu()));
152 
153  clearButton_ = new QPushButton(QIcon(path + "edit-clear.png"),tr("Clear Messages"));
154  connect(clearButton_, SIGNAL(clicked()), list_, SLOT(clear()));
155 
156  hlayout->addWidget( allButton_ );
157  hlayout->addWidget( infoButton_ );
158  hlayout->addWidget( warnButton_ );
159  hlayout->addWidget( errorButton_ );
160  hlayout->addStretch();
161  hlayout->addWidget( filterButton_ );
162  hlayout->addStretch();
163  hlayout->addWidget( clearButton_ );
164 
165  hlayout->setSpacing(0);
166  hlayout->setContentsMargins (0,0,0,0);
167  vlayout->setSpacing(0);
168  vlayout->setContentsMargins (0,0,0,0);
169 
170  vlayout->addWidget(list_);
171  vlayout->addLayout( hlayout );
172 
173  setLayout( vlayout );
174 }
175 
176 LoggerWidget::~LoggerWidget()
177 {
178  delete clearButton_;
179  delete errorButton_;
180  delete warnButton_;
181  delete infoButton_;
182  delete allButton_;
183  delete context_;
184  delete list_;
185 }
186 
187 
188 //-------------------------------------------------------------------------------------
189 
191 void LoggerWidget::append(const QString& _text, Logtype _type){
192 
193  list_->addItem(_text);
194 
195  QListWidgetItem* item = list_->item( list_->count()-1 );
196 
197  if ( allButton_->isChecked() )
198  item->setHidden(false);
199  else
200  item->setHidden(true);
201 
202  switch (_type) {
203  case LOGINFO:
204  item->setForeground( QBrush(QColor(Qt::darkGreen)) );
205  item->setBackground( QBrush(QColor(225,255,225), Qt::Dense4Pattern) );
206 
207  if ( infoButton_->isChecked() )
208  item->setHidden(false);
209  break;
210  case LOGOUT:
211  item->setForeground( QBrush(QColor(Qt::black)) );
212  break;
213  case LOGWARN:
214  item->setForeground( QBrush(QColor(160,160,0)) );
215  item->setBackground( QBrush(QColor(255,240,200),Qt::Dense4Pattern) );
216 
217  if ( warnButton_->isChecked() )
218  item->setHidden(false);
219  break;
220  case LOGERR:
221  item->setForeground( QBrush(QColor(Qt::red)) );
222  item->setBackground( QBrush(QColor(255,225,225),Qt::Dense4Pattern) );
223 
224  if ( errorButton_->isChecked() )
225  item->setHidden(false);
226  break;
227  case LOGSTATUS:
228  item->setForeground( QBrush(QColor(Qt::blue)) );
229  item->setBackground( QBrush(QColor(255,225,225),Qt::Dense4Pattern) );
230 
231  if ( errorButton_->isChecked() )
232  item->setHidden(false);
233  break;
234  }
235 
236  // If the logger is hidden, we just ignore the update ... done by showEvent later
237  if ( isHidden() )
238  return;
239 
240  // Remember that we have new logs to show
241  newData_ = true;
242 
243  // Check if we already have a running timer.
244  // If so, the timeout of that timer will trigger the redraw.
245  // Otherwise, we redraw and start the timer to block concurrent redraws.
246  // Only if new data is available, the redraw at the timers timeout will be done.
247  if ( ! loggerUpdateTimer_.isActive() ) {
248  // Update the logger
249  list_->scrollToBottom();
250 
251  // Remember that there is no new data now.
252  // This might change again on a call to this function, while the timer is active.
253  newData_ = false;
254 
255  // start the timer
256  loggerUpdateTimer_.start();
257  }
258 
259 }
260 
261 //-------------------------------------------------------------------------------------
262 
264 
265  // If there is data to show, do it.
266  if ( newData_ ) {
267  list_->scrollToBottom();
268  newData_ = false;
269  }
270 
271 }
272 
273 //-------------------------------------------------------------------------------------
274 
277 
278  QColor color;
279 
280  if ( infoButton_->isChecked() )
281  color = QColor(Qt::darkGreen);
282  else if ( warnButton_->isChecked() )
283  color = QColor(160,160,0);
284  else if ( errorButton_->isChecked() )
285  color = QColor(Qt::red);
286  else
287  color = QColor(Qt::black);
288 
289  if (color == QColor(Qt::black)){
290 
291  for (int i=0; i < list_->count(); i++)
292  list_->item( i )->setHidden(false);
293 
294  } else {
295 
296  for (int i=0; i < list_->count(); i++)
297  if ( list_->item(i)->foreground().color() == color )
298  list_->item( i )->setHidden(false);
299  else
300  list_->item( i )->setHidden(true);
301  }
302 
303  list_->scrollToBottom();
304 }
305 
306 //-------------------------------------------------------------------------------------
307 void LoggerWidget::showEvent ( QShowEvent * /*event*/ ) {
308  list_->scrollToBottom();
309 }
310 
311 //-------------------------------------------------------------------------------------
312 
314 void LoggerWidget::keyPressEvent (QKeyEvent * _event ) {
315  // Return key event to parent if not one of the standard key combinations ( ... Core )
316  if ( (_event->modifiers() & Qt::ControlModifier ) && ( _event->key() == Qt::Key_C ) )
317  copySelected();
318 
319  else if ( (_event->modifiers() & Qt::ControlModifier ) && ( _event->key() == Qt::Key_A ) )
320  list_->selectAll();
321 
322  else
323  _event->ignore();
324 }
325 
326 //-------------------------------------------------------------------------------------
327 
329 void LoggerWidget::contextMenuEvent ( QContextMenuEvent * event ){
330 
331  QPoint p = list_->mapToGlobal( event->pos() );
332 
333  context_->popup( p );
334 
335 }
336 
337 //-------------------------------------------------------------------------------------
338 
341 
342  QString str = "";
343 
344  for (int i=0; i < list_->selectedItems().count(); i++)
345  str += (list_->selectedItems()[i])->text() + "\n";
346 
347  QClipboard *clipboard = QApplication::clipboard();
348 
349  clipboard->setText(str);
350 }
351 
352 //-------------------------------------------------------------------------------------
353 
355  filterMenu_->popup( list_->mapToGlobal(filterButton_->pos()) );
356 }
357 
void slotFilterMenu()
Called when filter button is pressed.
void slotScrollUpdate()
Called when we want to scroll to the bottom.
Logtype
Log types for Message Window.
void copySelected()
copy Selected rows to clipboard
void append(const QString &_text, Logtype _type)
Append a new logmessage to log viewer.
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void contextMenuEvent(QContextMenuEvent *event)
Show context menu.
void showEvent(QShowEvent *event)
Called when the widget is shown.
void updateList()
update the list if a button was pressed
void keyPressEvent(QKeyEvent *_event)
Grab key events.