--- qsampler/trunk/src/qsamplerMessages.cpp 2005/01/12 11:05:44 339 +++ qsampler/trunk/src/qsamplerMessages.cpp 2014/05/30 20:58:26 2582 @@ -1,7 +1,8 @@ // qsamplerMessages.cpp // /**************************************************************************** - Copyright (C) 2003-2005, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2004-2014, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2007, Christian Schoenebeck This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -13,27 +14,33 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ +#include "qsamplerAbout.h" #include "qsamplerMessages.h" -#include -#include -#include -#include -#include -#include +#include -#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include #if !defined(WIN32) #include #endif + +namespace QSampler { + // The default maximum number of message lines. #define QSAMPLER_MESSAGES_MAXLINES 1000 @@ -44,203 +51,258 @@ //------------------------------------------------------------------------- -// qsamplerMessages - Messages log dockable window. +// QSampler::Messages - Messages log dockable window. // // Constructor. -qsamplerMessages::qsamplerMessages ( QWidget *pParent, const char *pszName ) - : QDockWindow(pParent, pszName) +Messages::Messages ( QWidget *pParent ) + : QDockWidget(pParent) { - // Intialize stdout capture stuff. - m_pStdoutNotifier = NULL; - m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL; - m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL; - - // Surely a name is crucial (e.g.for storing geometry settings) - if (pszName == 0) - QDockWindow::setName("qsamplerMessages"); - - // Create local text view widget. - m_pTextView = new QTextEdit(this); -// QFont font(m_pTextView->font()); -// font.setFamily("Fixed"); -// m_pTextView->setFont(font); - m_pTextView->setWordWrap(QTextEdit::NoWrap); - m_pTextView->setReadOnly(true); - m_pTextView->setUndoRedoEnabled(false); -#if QT_VERSION >= 0x030200 - m_pTextView->setTextFormat(Qt::LogText); -#endif - // Initialize default message limit. - setMessagesLimit(QSAMPLER_MESSAGES_MAXLINES); + // Surely a name is crucial (e.g.for storing geometry settings) + QDockWidget::setObjectName("qsamplerMessages"); - // Prepare the dockable window stuff. - QDockWindow::setWidget(m_pTextView); - QDockWindow::setOrientation(Qt::Horizontal); - QDockWindow::setCloseMode(QDockWindow::Always); - QDockWindow::setResizeEnabled(true); - - // Finally set the default caption and tooltip. - QString sCaption = tr("Messages"); - QToolTip::add(this, sCaption); - QDockWindow::setCaption(sCaption); + // Intialize stdout capture stuff. + m_pStdoutNotifier = NULL; + m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL; + m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL; + + // Create local text view widget. + m_pMessagesTextView = new QTextEdit(this); +// QFont font(m_pMessagesTextView->font()); +// font.setFamily("Fixed"); +// m_pMessagesTextView->setFont(font); + m_pMessagesTextView->setLineWrapMode(QTextEdit::NoWrap); + m_pMessagesTextView->setReadOnly(true); + m_pMessagesTextView->setUndoRedoEnabled(false); +// m_pMessagesTextView->setTextFormat(Qt::LogText); + + // Initialize default message limit. + m_iMessagesLines = 0; + setMessagesLimit(QSAMPLER_MESSAGES_MAXLINES); + + m_pMessagesLog = NULL; + + // Prepare the dockable window stuff. + QDockWidget::setWidget(m_pMessagesTextView); + QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); + QDockWidget::setAllowedAreas( + Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); + // Some specialties to this kind of dock window... + QDockWidget::setMinimumHeight(120); + + // Finally set the default caption and tooltip. + const QString& sCaption = tr("Messages"); + QDockWidget::setWindowTitle(sCaption); +// QDockWidget::setWindowIcon(QIcon(":/icons/qsamplerMessages.png")); + QDockWidget::setToolTip(sCaption); } // Destructor. -qsamplerMessages::~qsamplerMessages (void) +Messages::~Messages (void) { - // No more notifications. - if (m_pStdoutNotifier) - delete m_pStdoutNotifier; + // Turn off and close logging. + setLogging(false); + + // No more notifications. + if (m_pStdoutNotifier) + delete m_pStdoutNotifier; - // No need to delete child widgets, Qt does it all for us. + // No need to delete child widgets, Qt does it all for us. } // Own stdout/stderr socket notifier slot. -void qsamplerMessages::stdoutNotify ( int fd ) +void Messages::stdoutNotify ( int fd ) { #if !defined(WIN32) - char achBuffer[1024]; - int cchBuffer = ::read(fd, achBuffer, sizeof(achBuffer) - 1); - if (cchBuffer > 0) { - achBuffer[cchBuffer] = (char) 0; - appendStdoutBuffer(achBuffer); - } + char achBuffer[1024]; + const int cchBuffer = ::read(fd, achBuffer, sizeof(achBuffer) - 1); + if (cchBuffer > 0) { + achBuffer[cchBuffer] = (char) 0; + appendStdoutBuffer(achBuffer); + } #endif } // Stdout buffer handler -- now splitted by complete new-lines... -void qsamplerMessages::appendStdoutBuffer ( const QString& s ) +void Messages::appendStdoutBuffer ( const QString& s ) { - m_sStdoutBuffer.append(s); + m_sStdoutBuffer.append(s); - int iLength = m_sStdoutBuffer.findRev('\n') + 1; - if (iLength > 0) { - QString sTemp = m_sStdoutBuffer.left(iLength); - m_sStdoutBuffer.remove(0, iLength); - QStringList list = QStringList::split('\n', sTemp, true); - for (QStringList::Iterator iter = list.begin(); iter != list.end(); iter++) - appendMessagesText(*iter); - } + const int iLength = m_sStdoutBuffer.lastIndexOf('\n'); + if (iLength > 0) { + const QString& sTemp = m_sStdoutBuffer.left(iLength); + m_sStdoutBuffer.remove(0, iLength + 1); + QStringList list = sTemp.split('\n'); + QStringListIterator iter(list); + while (iter.hasNext()) + appendMessagesText(iter.next()); + } } // Stdout flusher -- show up any unfinished line... -void qsamplerMessages::flushStdoutBuffer (void) +void Messages::flushStdoutBuffer (void) { - if (!m_sStdoutBuffer.isEmpty()) { - appendMessagesText(m_sStdoutBuffer); - m_sStdoutBuffer.truncate(0); - } + if (!m_sStdoutBuffer.isEmpty()) { + appendMessagesText(m_sStdoutBuffer); + m_sStdoutBuffer.truncate(0); + } } // Stdout capture accessors. -bool qsamplerMessages::isCaptureEnabled (void) +bool Messages::isCaptureEnabled (void) { - return (bool) (m_pStdoutNotifier != NULL); + return (m_pStdoutNotifier != NULL); } -void qsamplerMessages::setCaptureEnabled ( bool bCapture ) +void Messages::setCaptureEnabled ( bool bCapture ) { - // Flush current buffer. - flushStdoutBuffer(); + // Flush current buffer. + flushStdoutBuffer(); #if !defined(WIN32) - // Destroy if already enabled. - if (!bCapture && m_pStdoutNotifier) { - delete m_pStdoutNotifier; - m_pStdoutNotifier = NULL; - // Close the notification pipes. - if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) { - ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]); - m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL; - } - if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) { - ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]); - m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL; - } - } - // Are we going to make up the capture? - if (bCapture && m_pStdoutNotifier == NULL && ::pipe(m_fdStdout) == 0) { - ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO); - ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO); - m_pStdoutNotifier = new QSocketNotifier(m_fdStdout[QSAMPLER_MESSAGES_FDREAD], QSocketNotifier::Read, this); - QObject::connect(m_pStdoutNotifier, SIGNAL(activated(int)), this, SLOT(stdoutNotify(int))); - } + // Destroy if already enabled. + if (!bCapture && m_pStdoutNotifier) { + delete m_pStdoutNotifier; + m_pStdoutNotifier = NULL; + // Close the notification pipes. + if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) { + ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]); + m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL; + } + } + // Are we going to make up the capture? + if (bCapture && m_pStdoutNotifier == NULL && ::pipe(m_fdStdout) == 0) { + ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO); + ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO); + m_pStdoutNotifier = new QSocketNotifier( + m_fdStdout[QSAMPLER_MESSAGES_FDREAD], QSocketNotifier::Read, this); + QObject::connect(m_pStdoutNotifier, + SIGNAL(activated(int)), + SLOT(stdoutNotify(int))); + } #endif } // Message font accessors. -QFont qsamplerMessages::messagesFont (void) +QFont Messages::messagesFont (void) { - return m_pTextView->font(); + return m_pMessagesTextView->font(); } -void qsamplerMessages::setMessagesFont( const QFont& font ) +void Messages::setMessagesFont ( const QFont& font ) { - m_pTextView->setFont(font); + m_pMessagesTextView->setFont(font); } // Maximum number of message lines accessors. -int qsamplerMessages::messagesLimit (void) +int Messages::messagesLimit (void) { - return m_iMessagesLimit; + return m_iMessagesLimit; } -void qsamplerMessages::setMessagesLimit ( int iMessagesLimit ) +void Messages::setMessagesLimit ( int iMessagesLimit ) { - m_iMessagesLimit = iMessagesLimit; - m_iMessagesHigh = iMessagesLimit + (iMessagesLimit / 3); -#if QT_VERSION >= 0x030200 - m_pTextView->setMaxLogLines(iMessagesLimit); -#endif + m_iMessagesLimit = iMessagesLimit; + m_iMessagesHigh = iMessagesLimit + (iMessagesLimit / 3); +} + +// Messages logging stuff. +bool Messages::isLogging (void) const +{ + return (m_pMessagesLog != NULL); +} + +void Messages::setLogging ( bool bEnabled, const QString& sFilename ) +{ + if (m_pMessagesLog) { + appendMessages(tr("Logging stopped --- %1 ---") + .arg(QDateTime::currentDateTime().toString())); + m_pMessagesLog->close(); + delete m_pMessagesLog; + m_pMessagesLog = NULL; + } + + if (bEnabled) { + m_pMessagesLog = new QFile(sFilename); + if (m_pMessagesLog->open(QIODevice::Text | QIODevice::Append)) { + appendMessages(tr("Logging started --- %1 ---") + .arg(QDateTime::currentDateTime().toString())); + } else { + delete m_pMessagesLog; + m_pMessagesLog = NULL; + } + } +} + + +// Messages log output method. +void Messages::appendMessagesLog ( const QString& s ) +{ + if (m_pMessagesLog) { + QTextStream(m_pMessagesLog) << s << endl; + m_pMessagesLog->flush(); + } +} + +// Messages widget output method. +void Messages::appendMessagesLine ( const QString& s ) +{ + // Check for message line limit... + if (m_iMessagesLines > m_iMessagesHigh) { + m_pMessagesTextView->setUpdatesEnabled(false); + QTextCursor textCursor(m_pMessagesTextView->document()->begin()); + while (m_iMessagesLines > m_iMessagesLimit) { + // Move cursor extending selection + // from start to next line-block... + textCursor.movePosition( + QTextCursor::NextBlock, QTextCursor::KeepAnchor); + m_iMessagesLines--; + } + // Remove the excessive line-blocks... + textCursor.removeSelectedText(); + m_pMessagesTextView->setUpdatesEnabled(true); + } + + m_pMessagesTextView->append(s); + m_iMessagesLines++; } // The main utility methods. -void qsamplerMessages::appendMessages ( const QString& s ) +void Messages::appendMessages ( const QString& s ) { - appendMessagesColor(s, "#999999"); + appendMessagesColor(s, "#999999"); } -void qsamplerMessages::appendMessagesColor ( const QString& s, const QString &c ) +void Messages::appendMessagesColor ( const QString& s, const QString &c ) { - appendMessagesText("" + QTime::currentTime().toString("hh:mm:ss.zzz") + " " + s + ""); + const QString& sText = QTime::currentTime().toString("hh:mm:ss.zzz") + ' ' + s; + appendMessagesLine("" + sText + ""); + appendMessagesLog(sText); } -void qsamplerMessages::appendMessagesText ( const QString& s ) +void Messages::appendMessagesText ( const QString& s ) { -#if QT_VERSION < 0x030200 - // Check for message line limit... - if (m_iMessagesLimit > 0) { - int iParagraphs = m_pTextView->paragraphs(); - if (iParagraphs > m_iMessagesHigh) { - m_pTextView->setUpdatesEnabled(false); - while (iParagraphs > m_iMessagesLimit) { - m_pTextView->removeParagraph(0); - iParagraphs--; - } - m_pTextView->scrollToBottom(); - m_pTextView->setUpdatesEnabled(true); - } - } -#endif - m_pTextView->append(s); + appendMessagesLine(s); + appendMessagesLog(s); } -// One time scroll to the most recent message. -void qsamplerMessages::scrollToBottom (void) +// History reset. +void Messages::clear (void) { - flushStdoutBuffer(); - m_pTextView->scrollToBottom(); + m_iMessagesLines = 0; + m_pMessagesTextView->clear(); } +} // namespace QSampler + // end of qsamplerMessages.cpp