/[svn]/qsampler/trunk/src/qsamplerMessages.cpp
ViewVC logotype

Diff of /qsampler/trunk/src/qsamplerMessages.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1465 by capela, Thu Nov 1 17:49:27 2007 UTC revision 3788 by capela, Thu Jun 11 16:59:09 2020 UTC
# Line 1  Line 1 
1  // qsamplerMessages.cpp  // qsamplerMessages.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2020, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
# Line 24  Line 24 
24  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
25    
26  #include <QSocketNotifier>  #include <QSocketNotifier>
27  #include <QTextEdit>  
28    #include <QFile>
29    #include <QTextBrowser>
30  #include <QTextCursor>  #include <QTextCursor>
31    #include <QTextStream>
32  #include <QTextBlock>  #include <QTextBlock>
 #include <QScrollBar>  
33  #include <QDateTime>  #include <QDateTime>
34  #include <QIcon>  #include <QIcon>
35    
36  #if !defined(WIN32)  #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
37  #include <unistd.h>  #include <unistd.h>
38    #include <fcntl.h>
39    #endif
40    
41    
42    // Deprecated QTextStreamFunctions/Qt namespaces workaround.
43    #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
44    #define endl    Qt::endl
45  #endif  #endif
46    
47    
48    namespace QSampler {
49    
50  // The default maximum number of message lines.  // The default maximum number of message lines.
51  #define QSAMPLER_MESSAGES_MAXLINES  1000  #define QSAMPLER_MESSAGES_MAXLINES  1000
52    
# Line 45  Line 57 
57    
58    
59  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
60  // qsamplerMessages - Messages log dockable window.  // QSampler::Messages - Messages log dockable window.
61  //  //
62    
63  // Constructor.  // Constructor.
64  qsamplerMessages::qsamplerMessages ( QWidget *pParent )  Messages::Messages ( QWidget *pParent )
65      : QDockWidget(pParent)          : QDockWidget(pParent)
66  {  {
67          // Surely a name is crucial (e.g.for storing geometry settings)          // Surely a name is crucial (e.g.for storing geometry settings)
68          QDockWidget::setObjectName("qsamplerMessages");          QDockWidget::setObjectName("qsamplerMessages");
69    
70      // Intialize stdout capture stuff.          // Intialize stdout capture stuff.
71      m_pStdoutNotifier = NULL;          m_pStdoutNotifier = nullptr;
72      m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;          m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;
73      m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL;          m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL;
74    
75          // Create local text view widget.          // Create local text view widget.
76          m_pTextView = new QTextEdit(this);          m_pMessagesTextView = new QTextBrowser(this);
77  //  QFont font(m_pTextView->font());  //  QFont font(m_pMessagesTextView->font());
78  //  font.setFamily("Fixed");  //  font.setFamily("Fixed");
79  //  m_pTextView->setFont(font);  //  m_pMessagesTextView->setFont(font);
80          m_pTextView->setLineWrapMode(QTextEdit::NoWrap);          m_pMessagesTextView->setLineWrapMode(QTextEdit::NoWrap);
81          m_pTextView->setReadOnly(true);  //      m_pMessagesTextView->setReadOnly(true);
82          m_pTextView->setUndoRedoEnabled(false);  //      m_pMessagesTextView->setUndoRedoEnabled(false);
83  //      m_pTextView->setTextFormat(Qt::LogText);  //      m_pMessagesTextView->setTextFormat(Qt::LogText);
84    
85          // Initialize default message limit.          // Initialize default message limit.
86          m_iMessagesLines = 0;          m_iMessagesLines = 0;
87          setMessagesLimit(QSAMPLER_MESSAGES_MAXLINES);          setMessagesLimit(QSAMPLER_MESSAGES_MAXLINES);
88    
89            m_pMessagesLog = nullptr;
90    
91          // Prepare the dockable window stuff.          // Prepare the dockable window stuff.
92          QDockWidget::setWidget(m_pTextView);          QDockWidget::setWidget(m_pMessagesTextView);
93          QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);          QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
94          QDockWidget::setAllowedAreas(          QDockWidget::setAllowedAreas(
95                  Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);                  Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
# Line 91  qsamplerMessages::qsamplerMessages ( QWi Line 105  qsamplerMessages::qsamplerMessages ( QWi
105    
106    
107  // Destructor.  // Destructor.
108  qsamplerMessages::~qsamplerMessages (void)  Messages::~Messages (void)
109  {  {
110      // No more notifications.          // Turn off and close logging.
111      if (m_pStdoutNotifier)          setLogging(false);
112          delete m_pStdoutNotifier;  
113            // No more notifications.
114            if (m_pStdoutNotifier)
115                    delete m_pStdoutNotifier;
116    
117      // No need to delete child widgets, Qt does it all for us.          // No need to delete child widgets, Qt does it all for us.
118    }
119    
120    
121    // Set stdout/stderr blocking mode.
122    bool Messages::stdoutBlock ( int fd, bool bBlock ) const
123    {
124    #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
125            const int iFlags = ::fcntl(fd, F_GETFL, 0);
126            const bool bNonBlock = bool(iFlags & O_NONBLOCK);
127            if (bBlock && bNonBlock)
128                    bBlock = (::fcntl(fd, F_SETFL, iFlags & ~O_NONBLOCK) == 0);
129            else
130            if (!bBlock && !bNonBlock)
131                    bBlock = (::fcntl(fd, F_SETFL, iFlags |  O_NONBLOCK) != 0);
132    #endif
133            return bBlock;
134  }  }
135    
136    
137  // Own stdout/stderr socket notifier slot.  // Own stdout/stderr socket notifier slot.
138  void qsamplerMessages::stdoutNotify ( int fd )  void Messages::stdoutNotify ( int fd )
139  {  {
140  #if !defined(WIN32)  #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
141      char achBuffer[1024];          // Set non-blocking reads, if not already...
142      int  cchBuffer = ::read(fd, achBuffer, sizeof(achBuffer) - 1);          const bool bBlock = stdoutBlock(fd, false);
143      if (cchBuffer > 0) {          // Read as much as is available...
144          achBuffer[cchBuffer] = (char) 0;          QString sTemp;
145          appendStdoutBuffer(achBuffer);          char achBuffer[1024];
146      }          const int cchBuffer = sizeof(achBuffer) - 1;
147            int cchRead = ::read(fd, achBuffer, cchBuffer);
148            while (cchRead > 0) {
149                    achBuffer[cchRead] = (char) 0;
150                    sTemp.append(achBuffer);
151                    cchRead = (bBlock ? 0 : ::read(fd, achBuffer, cchBuffer));
152            }
153            // Needs to be non-empty...
154            if (!sTemp.isEmpty())
155                    appendStdoutBuffer(sTemp);
156  #endif  #endif
157  }  }
158    
159    
160  // Stdout buffer handler -- now splitted by complete new-lines...  // Stdout buffer handler -- now splitted by complete new-lines...
161  void qsamplerMessages::appendStdoutBuffer ( const QString& s )  void Messages::appendStdoutBuffer ( const QString& s )
162  {  {
163          m_sStdoutBuffer.append(s);          m_sStdoutBuffer.append(s);
164    
165          int iLength = m_sStdoutBuffer.lastIndexOf('\n') + 1;          processStdoutBuffer();
166    }
167    
168    void Messages::processStdoutBuffer (void)
169    {
170            const int iLength = m_sStdoutBuffer.lastIndexOf('\n');
171          if (iLength > 0) {          if (iLength > 0) {
172                  QString sTemp = m_sStdoutBuffer.left(iLength);                  const QString& sTemp = m_sStdoutBuffer.left(iLength);
173                  m_sStdoutBuffer.remove(0, iLength);                  m_sStdoutBuffer.remove(0, iLength + 1);
174                  QStringList list = sTemp.split('\n');                  QStringList list = sTemp.split('\n');
175                  QStringListIterator iter(list);                  QStringListIterator iter(list);
176                  while (iter.hasNext())                  while (iter.hasNext())
# Line 133  void qsamplerMessages::appendStdoutBuffe Line 180  void qsamplerMessages::appendStdoutBuffe
180    
181    
182  // Stdout flusher -- show up any unfinished line...  // Stdout flusher -- show up any unfinished line...
183  void qsamplerMessages::flushStdoutBuffer (void)  void Messages::flushStdoutBuffer (void)
184  {  {
185      if (!m_sStdoutBuffer.isEmpty()) {          if (!m_sStdoutBuffer.isEmpty()) {
186          appendMessagesText(m_sStdoutBuffer);                  processStdoutBuffer();
187          m_sStdoutBuffer.truncate(0);                  m_sStdoutBuffer.clear();
188      }          }
189  }  }
190    
191    
192  // Stdout capture accessors.  // Stdout capture accessors.
193  bool qsamplerMessages::isCaptureEnabled (void)  bool Messages::isCaptureEnabled (void)
194  {  {
195      return (bool) (m_pStdoutNotifier != NULL);          return (m_pStdoutNotifier != nullptr);
196  }  }
197    
198  void qsamplerMessages::setCaptureEnabled ( bool bCapture )  void Messages::setCaptureEnabled ( bool bCapture )
199  {  {
200      // Flush current buffer.          // Flush current buffer.
201      flushStdoutBuffer();          flushStdoutBuffer();
202    
203  #if !defined(WIN32)  #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
204          // Destroy if already enabled.          // Destroy if already enabled.
205          if (!bCapture && m_pStdoutNotifier) {          if (!bCapture && m_pStdoutNotifier) {
206                  delete m_pStdoutNotifier;                  delete m_pStdoutNotifier;
207                  m_pStdoutNotifier = NULL;                  m_pStdoutNotifier = nullptr;
208                  // Close the notification pipes.                  // Close the notification pipes.
209                  if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {                  if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {
210                          ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);                          ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);
211                          m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;                          m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;
212                  }                  }
                 if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {  
                         ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);  
                         m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;  
                 }  
213          }          }
214          // Are we going to make up the capture?          // Are we going to make up the capture?
215          if (bCapture && m_pStdoutNotifier == NULL && ::pipe(m_fdStdout) == 0) {          if (bCapture && m_pStdoutNotifier == nullptr && ::pipe(m_fdStdout) == 0) {
216                  ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO);                  ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO);
217                  ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO);                  ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO);
218                  m_pStdoutNotifier = new QSocketNotifier(                  m_pStdoutNotifier = new QSocketNotifier(
# Line 183  void qsamplerMessages::setCaptureEnabled Line 226  void qsamplerMessages::setCaptureEnabled
226    
227    
228  // Message font accessors.  // Message font accessors.
229  QFont qsamplerMessages::messagesFont (void)  QFont Messages::messagesFont (void)
230  {  {
231      return m_pTextView->font();          return m_pMessagesTextView->font();
232  }  }
233    
234  void qsamplerMessages::setMessagesFont( const QFont& font )  void Messages::setMessagesFont ( const QFont& font )
235  {  {
236      m_pTextView->setFont(font);          m_pMessagesTextView->setFont(font);
237  }  }
238    
239    
240  // Maximum number of message lines accessors.  // Maximum number of message lines accessors.
241  int qsamplerMessages::messagesLimit (void)  int Messages::messagesLimit (void)
242  {  {
243      return m_iMessagesLimit;          return m_iMessagesLimit;
244  }  }
245    
246  void qsamplerMessages::setMessagesLimit ( int iMessagesLimit )  void Messages::setMessagesLimit ( int iMessagesLimit )
247  {  {
248      m_iMessagesLimit = iMessagesLimit;          m_iMessagesLimit = iMessagesLimit;
249      m_iMessagesHigh  = iMessagesLimit + (iMessagesLimit / 3);          m_iMessagesHigh  = iMessagesLimit + (iMessagesLimit / 3);
250  }  }
251    
252    // Messages logging stuff.
253    bool Messages::isLogging (void) const
254    {
255            return (m_pMessagesLog != nullptr);
256    }
257    
258  // The main utility methods.  void Messages::setLogging ( bool bEnabled, const QString& sFilename )
 void qsamplerMessages::appendMessages ( const QString& s )  
259  {  {
260      appendMessagesColor(s, "#999999");          if (m_pMessagesLog) {
261                    appendMessages(tr("Logging stopped --- %1 ---")
262                            .arg(QDateTime::currentDateTime().toString()));
263                    m_pMessagesLog->close();
264                    delete m_pMessagesLog;
265                    m_pMessagesLog = nullptr;
266            }
267    
268            if (bEnabled) {
269                    m_pMessagesLog = new QFile(sFilename);
270                    if (m_pMessagesLog->open(QIODevice::Text | QIODevice::Append)) {
271                            appendMessages(tr("Logging started --- %1 ---")
272                                    .arg(QDateTime::currentDateTime().toString()));
273                    } else {
274                            delete m_pMessagesLog;
275                            m_pMessagesLog = nullptr;
276                    }
277            }
278  }  }
279    
280  void qsamplerMessages::appendMessagesColor ( const QString& s, const QString &c )  
281    // Messages log output method.
282    void Messages::appendMessagesLog ( const QString& s )
283  {  {
284          appendMessagesText("<font color=\"" + c + "\">"          if (m_pMessagesLog) {
285                  + QTime::currentTime().toString("hh:mm:ss.zzz")                  QTextStream(m_pMessagesLog)
286                  + ' ' + s + "</font>");                          << QTime::currentTime().toString("hh:mm:ss.zzz")
287                            << ' ' << s << endl;
288                    m_pMessagesLog->flush();
289            }
290  }  }
291    
292  void qsamplerMessages::appendMessagesText ( const QString& s )  // Messages widget output method.
293    void Messages::appendMessagesLine ( const QString& s )
294  {  {
295      // Check for message line limit...          // Check for message line limit...
296      if (m_iMessagesLines > m_iMessagesHigh) {          if (m_iMessagesLines > m_iMessagesHigh) {
297                  m_pTextView->setUpdatesEnabled(false);                  m_pMessagesTextView->setUpdatesEnabled(false);
298                  QTextCursor textCursor(m_pTextView->document()->begin());                  QTextCursor textCursor(m_pMessagesTextView->document()->begin());
299                  while (m_iMessagesLines > m_iMessagesLimit) {                  while (m_iMessagesLines > m_iMessagesLimit) {
300                          // Move cursor extending selection                          // Move cursor extending selection
301                          // from start to next line-block...                          // from start to next line-block...
# Line 235  void qsamplerMessages::appendMessagesTex Line 305  void qsamplerMessages::appendMessagesTex
305                  }                  }
306                  // Remove the excessive line-blocks...                  // Remove the excessive line-blocks...
307                  textCursor.removeSelectedText();                  textCursor.removeSelectedText();
308                  m_pTextView->setUpdatesEnabled(true);                  m_pMessagesTextView->setUpdatesEnabled(true);
309      }          }
310    
311          // Count always as a new line out there...          m_pMessagesTextView->append(s);
         m_pTextView->append(s);  
312          m_iMessagesLines++;          m_iMessagesLines++;
313  }  }
314    
315    
316    // The main utility methods.
317    void Messages::appendMessages ( const QString& s )
318    {
319            appendMessagesColor(s, Qt::gray);
320    }
321    
322    void Messages::appendMessagesColor ( const QString& s, const QColor& rgb )
323    {
324            appendMessagesLine("<font color=\"" + rgb.name() + "\">" + s + "</font>");
325            appendMessagesLog(s);
326    }
327    
328    void Messages::appendMessagesText ( const QString& s )
329    {
330            appendMessagesLine(s);
331            appendMessagesLog(s);
332    }
333    
334    
335  // History reset.  // History reset.
336  void qsamplerMessages::clear (void)  void Messages::clear (void)
337  {  {
338          m_iMessagesLines = 0;          m_iMessagesLines = 0;
339          m_pTextView->clear();          m_pMessagesTextView->clear();
340  }  }
341    
342    } // namespace QSampler
343    
344    
345  // end of qsamplerMessages.cpp  // end of qsamplerMessages.cpp

Legend:
Removed from v.1465  
changed lines
  Added in v.3788

  ViewVC Help
Powered by ViewVC