/*===========================================================================*\ * * * OpenFlipper * * Copyright (C) 2001-2010 by Computer Graphics Group, RWTH Aachen * * www.openflipper.org * * * *--------------------------------------------------------------------------- * * This file is part of OpenFlipper. * * * * OpenFlipper is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * If other files instantiate templates or use macros * * or inline functions from this file, or you compile this file and * * link it with other files to produce an executable, this file does * * not by itself cause the resulting executable to be covered by the * * GNU Lesser General Public License. This exception does not however * * invalidate any other reasons why the executable file might be * * covered by the GNU Lesser General Public License. * * * * OpenFlipper is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenFlipper. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $LastChangedBy$ * * $Date$ * * * \*===========================================================================*/ #include "loggerWidget.hh" #include #include #include #include LoggerWidget::LoggerWidget( QWidget *parent) : QWidget(parent), newData_(true) { QVBoxLayout* vlayout = new QVBoxLayout(); QHBoxLayout* hlayout = new QHBoxLayout(); QHBoxLayout* hlayout2 = new QHBoxLayout(); list_ = new QListWidget(); list_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); list_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); list_->setFocusPolicy(Qt::NoFocus); list_->setSelectionMode(QAbstractItemView::ExtendedSelection); QString path = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator(); // ============================ // Context Menu // ============================ context_ = new QMenu(tr("Log Viewer")); QAction* copyAction = new QAction(QIcon(path + "edit-copy.png"), tr("Copy"),0); copyAction->setShortcut( QKeySequence("Ctrl+C") ); QAction* selectAction = new QAction(tr("Select All"),0); selectAction->setShortcut( QKeySequence("Ctrl+A") ); connect (copyAction, SIGNAL(triggered()), this, SLOT(copySelected())); connect (selectAction, SIGNAL(triggered()), list_, SLOT(selectAll())); context_->addAction(copyAction); context_->addSeparator(); context_->addAction(selectAction); // ============================ // Filters Menu // ============================ filterMenu_ = new QMenu(tr("Log Viewer")); QAction* openMeshFilterAction = new QAction(QIcon(path + "edit-copy.png"), tr("Enable OpenMesh error messages"),0); openMeshFilterAction->setCheckable(true); if ( OpenFlipperSettings().value("Core/Gui/LogWindow/OpenMeshErrors",true).toBool() ) { openMeshFilterAction->setChecked( true ); omerr().enable(); } else { openMeshFilterAction->setChecked( false ); omerr().disable(); } filterMenu_->addAction(openMeshFilterAction); connect (openMeshFilterAction, SIGNAL(toggled(bool)), this, SLOT(slotOpenMeshERR(bool))); // ============================ // Scrollbar // ============================ scrollBar_ = new QScrollBar(Qt::Vertical); blockNext_ = false; connect (scrollBar_, SIGNAL(valueChanged(int)), this, SLOT(scrollTo(int))); connect (list_->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(mapScrollPosition(int))); connect (&loggerUpdateTimer_, SIGNAL(timeout ()), this, SLOT(slotScrollUpdate())); // Single shot timer every 500 msecs loggerUpdateTimer_.setSingleShot(true); loggerUpdateTimer_.setInterval(500); hlayout2->addWidget(list_); hlayout2->addWidget(scrollBar_); allButton_ = new QPushButton(QIcon(path + "status_all.png"),tr("All Messages")); allButton_->setCheckable(true); allButton_->setAutoExclusive(true); infoButton_ = new QPushButton(QIcon(path + "status_green.png"),tr("Informations")); infoButton_->setCheckable(true); infoButton_->setAutoExclusive(true); warnButton_ = new QPushButton(QIcon(path + "status_yellow.png"),tr("Warnings")); warnButton_->setCheckable(true); warnButton_->setAutoExclusive(true); errorButton_ = new QPushButton(QIcon(path + "status_red.png"),tr("Errors")); errorButton_->setCheckable(true); errorButton_->setAutoExclusive(true); filterButton_ = new QPushButton(QIcon(path + "status_red.png"),tr("Filters")); filterButton_->setCheckable(true); allButton_->setChecked(true); connect(allButton_, SIGNAL(clicked()), this, SLOT(updateList())); connect(infoButton_, SIGNAL(clicked()), this, SLOT(updateList())); connect(warnButton_, SIGNAL(clicked()), this, SLOT(updateList())); connect(errorButton_, SIGNAL(clicked()), this, SLOT(updateList())); connect(filterButton_,SIGNAL(clicked()), this, SLOT(slotFilterMenu())); clearButton_ = new QPushButton(QIcon(path + "edit-clear.png"),tr("Clear Messages")); connect(clearButton_, SIGNAL(clicked()), list_, SLOT(clear())); hlayout->addWidget( allButton_ ); hlayout->addWidget( infoButton_ ); hlayout->addWidget( warnButton_ ); hlayout->addWidget( errorButton_ ); hlayout->addStretch(); hlayout->addWidget( filterButton_ ); hlayout->addStretch(); hlayout->addWidget( clearButton_ ); hlayout->setSpacing(0); hlayout->setContentsMargins (0,0,0,0); vlayout->setSpacing(0); vlayout->setContentsMargins (0,0,0,0); vlayout->addLayout( hlayout2 ); vlayout->addLayout( hlayout ); setLayout( vlayout ); } LoggerWidget::~LoggerWidget() { delete clearButton_; delete errorButton_; delete warnButton_; delete infoButton_; delete allButton_; delete scrollBar_; delete context_; delete list_; } //------------------------------------------------------------------------------------- /// workaround for scrolling void LoggerWidget::mapScrollPosition(int _pos){ //map list_'s internal scrollbar position to our own scrollBar position blockNext_ = true; scrollBar_->setValue( floor( 100 * _pos / (double) list_->verticalScrollBar()->maximum() ) ); } //------------------------------------------------------------------------------------- /// workaround for scrolling void LoggerWidget::scrollTo(int _pos){ //if the scrollEvent was triggered by list_ ignore it if (blockNext_){ blockNext_ = false; return; } // now it gets ugly ;) if (_pos < 5) list_->scrollToTop(); else if (_pos > 95) list_->scrollToBottom(); else list_->scrollToItem( list_->item( floor((list_->count()-1) * (_pos / 100.0)) ) ); list_->hide(); list_->show(); } //------------------------------------------------------------------------------------- /// Append a new logmessage to log viewer void LoggerWidget::append(QString _text, Logtype _type){ list_->addItem(_text); QListWidgetItem* item = list_->item( list_->count()-1 ); if ( allButton_->isChecked() ) item->setHidden(false); else item->setHidden(true); switch (_type) { case LOGINFO: item->setForeground( QBrush(QColor(Qt::darkGreen)) ); item->setBackground( QBrush(QColor(225,255,225), Qt::Dense4Pattern) ); if ( infoButton_->isChecked() ) item->setHidden(false); break; case LOGOUT: item->setForeground( QBrush(QColor(Qt::black)) ); break; case LOGWARN: item->setForeground( QBrush(QColor(160,160,0)) ); item->setBackground( QBrush(QColor(255,240,200),Qt::Dense4Pattern) ); if ( warnButton_->isChecked() ) item->setHidden(false); break; case LOGERR: item->setForeground( QBrush(QColor(Qt::red)) ); item->setBackground( QBrush(QColor(255,225,225),Qt::Dense4Pattern) ); if ( errorButton_->isChecked() ) item->setHidden(false); break; } // If the logger is hidden, we just ignore the update ... done by showEvent later if ( isHidden() ) return; // Remember that we have new logs to show newData_ = true; // Check if we already have a running timer. // If so, the timeout of that timer will trigger the redraw. // Otherwise, we redraw and start the timer to block concurrent redraws. // Only if new data is available, the redraw at the timers timeout will be done. if ( ! loggerUpdateTimer_.isActive() ) { // Update the logger list_->scrollToBottom(); // Remember that there is no new data now. // This might change again on a call to this function, while the timer is active. newData_ = false; // start the timer loggerUpdateTimer_.start(); } } //------------------------------------------------------------------------------------- void LoggerWidget::slotScrollUpdate() { // If there is data to show, do it. if ( newData_ ) { list_->scrollToBottom(); newData_ = false; } } //------------------------------------------------------------------------------------- /// update the list if a button was pressed void LoggerWidget::updateList(){ QColor color; if ( infoButton_->isChecked() ) color = QColor(Qt::darkGreen); else if ( warnButton_->isChecked() ) color = QColor(160,160,0); else if ( errorButton_->isChecked() ) color = QColor(Qt::red); else color = QColor(Qt::black); if (color == QColor(Qt::black)){ for (int i=0; i < list_->count(); i++) list_->item( i )->setHidden(false); } else { for (int i=0; i < list_->count(); i++) if ( list_->item(i)->foreground().color() == color ) list_->item( i )->setHidden(false); else list_->item( i )->setHidden(true); } list_->scrollToBottom(); } //------------------------------------------------------------------------------------- void LoggerWidget::showEvent ( QShowEvent * /*event*/ ) { list_->scrollToBottom(); } //------------------------------------------------------------------------------------- /// handle keyPressEvents void LoggerWidget::keyPressEvent (QKeyEvent * _event ) { // Return key event to parent if not one of the standard key combinations ( ... Core ) if ( (_event->modifiers() & Qt::ControlModifier ) && ( _event->key() == Qt::Key_C ) ) copySelected(); else if ( (_event->modifiers() & Qt::ControlModifier ) && ( _event->key() == Qt::Key_A ) ) list_->selectAll(); else _event->ignore(); } //------------------------------------------------------------------------------------- /// show context menu void LoggerWidget::contextMenuEvent ( QContextMenuEvent * event ){ QPoint p = list_->mapToGlobal( event->pos() ); context_->popup( p ); } //------------------------------------------------------------------------------------- ///copy Selected rows to clipboard void LoggerWidget::copySelected (){ QString str = ""; for (int i=0; i < list_->selectedItems().count(); i++) str += (list_->selectedItems()[i])->text() + "\n"; QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(str); } //------------------------------------------------------------------------------------- void LoggerWidget::slotFilterMenu() { filterMenu_->popup( list_->mapToGlobal(filterButton_->pos()) ); } //------------------------------------------------------------------------------------- void LoggerWidget::slotOpenMeshERR(bool _state) { if ( _state ) { omerr().enable(); } else { omerr().disable(); } OpenFlipperSettings().setValue("Core/Gui/LogWindow/OpenMeshErrors",_state); }