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

Legend:
Removed from v.1474  
changed lines
  Added in v.3759

  ViewVC Help
Powered by ViewVC