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
49 #include <OpenFlipper/common/GlobalOptions.hh>
50
51 #include <OpenMesh/Core/System/omstream.hh>
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
257 void LoggerWidget::slotScrollUpdate() {
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
270 void LoggerWidget::updateList(){
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
334 void LoggerWidget::copySelected (){
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
348 void LoggerWidget::slotFilterMenu() {
349 filterMenu_->popup( list_->mapToGlobal(filterButton_->pos()) );
350 }
351
LOGERR
Definition: LoggingInterface.hh:96
omstream.hh
LoggerWidget::copySelected
void copySelected()
copy Selected rows to clipboard
Definition: loggerWidget.cc:334
GlobalOptions.hh
Logtype
Logtype
Log types for Message Window.
Definition: LoggingInterface.hh:92
LOGWARN
Definition: LoggingInterface.hh:95
LOGOUT
Definition: LoggingInterface.hh:93
LoggerWidget::keyPressEvent
void keyPressEvent(QKeyEvent *_event)
Grab key events.
Definition: loggerWidget.cc:308
LOGSTATUS
Definition: LoggingInterface.hh:92
LoggerWidget::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *event)
Show context menu.
Definition: loggerWidget.cc:323
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:1038
LoggerWidget::updateList
void updateList()
update the list if a button was pressed
Definition: loggerWidget.cc:270
LoggerWidget::append
void append(const QString &_text, Logtype _type)
Append a new logmessage to log viewer.
Definition: loggerWidget.cc:185
LoggerWidget::slotFilterMenu
void slotFilterMenu()
Called when filter button is pressed.
Definition: loggerWidget.cc:348
LoggerWidget::slotScrollUpdate
void slotScrollUpdate()
Called when we want to scroll to the bottom.
Definition: loggerWidget.cc:257
LoggerWidget::showEvent
void showEvent(QShowEvent *event)
Called when the widget is shown.
Definition: loggerWidget.cc:301
LOGINFO
Definition: LoggingInterface.hh:94