/[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 115 by capela, Mon Jun 7 21:41:43 2004 UTC revision 3357 by capela, Tue Oct 17 21:44:20 2017 UTC
# Line 1  Line 1 
1  // qsamplerMessages.cpp  // qsamplerMessages.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2003-2004, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2017, rncbc aka Rui Nuno Capela. All rights reserved.
5       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
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 13  Line 14 
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License along
18     along with this program; if not, write to the Free Software     with this program; if not, write to the Free Software Foundation, Inc.,
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include "qsamplerAbout.h"
24  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
25    
26  #include <qsocketnotifier.h>  #include <QSocketNotifier>
 #include <qstringlist.h>  
 #include <qtextedit.h>  
 #include <qdatetime.h>  
 #include <qtooltip.h>  
 #include <qpixmap.h>  
27    
28  #include "config.h"  #include <QFile>
29    #include <QTextEdit>
30    #include <QTextCursor>
31    #include <QTextStream>
32    #include <QTextBlock>
33    #include <QScrollBar>
34    #include <QDateTime>
35    #include <QIcon>
36    
37  #if !defined(WIN32)  #if !defined(_WIN32)
38  #include <unistd.h>  #include <unistd.h>
39    #include <fcntl.h>
40  #endif  #endif
41    
42    
43    namespace QSampler {
44    
45  // The default maximum number of message lines.  // The default maximum number of message lines.
46  #define QSAMPLER_MESSAGES_MAXLINES  1000  #define QSAMPLER_MESSAGES_MAXLINES  1000
47    
# Line 44  Line 52 
52    
53    
54  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
55  // qsamplerMessages - Messages log dockable window.  // QSampler::Messages - Messages log dockable window.
56  //  //
57    
58  // Constructor.  // Constructor.
59  qsamplerMessages::qsamplerMessages ( QWidget *pParent, const char *pszName )  Messages::Messages ( QWidget *pParent )
60      : QDockWindow(pParent, pszName)          : QDockWidget(pParent)
61  {  {
62      // Initialize default message limit.          // Surely a name is crucial (e.g.for storing geometry settings)
63      m_iMessagesLimit = QSAMPLER_MESSAGES_MAXLINES;          QDockWidget::setObjectName("qsamplerMessages");
64    
65      // Intialize stdout capture stuff.          // Intialize stdout capture stuff.
66      m_pStdoutNotifier = NULL;          m_pStdoutNotifier = NULL;
67      m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;          m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;
68      m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL;          m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL;
69    
70      // Surely a name is crucial (e.g.for storing geometry settings)          // Create local text view widget.
71      if (pszName == 0)          m_pMessagesTextView = new QTextEdit(this);
72          QDockWindow::setName("qsamplerMessages");  //  QFont font(m_pMessagesTextView->font());
   
     // Create local text view widget.  
     m_pTextView = new QTextEdit(this);  
 //  QFont font(m_pTextView->font());  
73  //  font.setFamily("Fixed");  //  font.setFamily("Fixed");
74  //  m_pTextView->setFont(font);  //  m_pMessagesTextView->setFont(font);
75      m_pTextView->setWordWrap(QTextEdit::NoWrap);          m_pMessagesTextView->setLineWrapMode(QTextEdit::NoWrap);
76      m_pTextView->setReadOnly(true);          m_pMessagesTextView->setReadOnly(true);
77      m_pTextView->setUndoRedoEnabled(false);          m_pMessagesTextView->setUndoRedoEnabled(false);
78    //      m_pMessagesTextView->setTextFormat(Qt::LogText);
79      // Prepare the dockable window stuff.  
80      QDockWindow::setWidget(m_pTextView);          // Initialize default message limit.
81      QDockWindow::setOrientation(Qt::Horizontal);          m_iMessagesLines = 0;
82      QDockWindow::setCloseMode(QDockWindow::Always);          setMessagesLimit(QSAMPLER_MESSAGES_MAXLINES);
83      QDockWindow::setResizeEnabled(true);  
84            m_pMessagesLog = NULL;
85      // Finally set the default caption and tooltip.  
86      QString sCaption = tr("Messages");          // Prepare the dockable window stuff.
87      QToolTip::add(this, sCaption);          QDockWidget::setWidget(m_pMessagesTextView);
88      QDockWindow::setCaption(sCaption);          QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
89            QDockWidget::setAllowedAreas(
90                    Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
91            // Some specialties to this kind of dock window...
92            QDockWidget::setMinimumHeight(120);
93    
94            // Finally set the default caption and tooltip.
95            const QString& sCaption = tr("Messages");
96            QDockWidget::setWindowTitle(sCaption);
97    //      QDockWidget::setWindowIcon(QIcon(":/icons/qsamplerMessages.png"));
98            QDockWidget::setToolTip(sCaption);
99  }  }
100    
101    
102  // Destructor.  // Destructor.
103  qsamplerMessages::~qsamplerMessages (void)  Messages::~Messages (void)
104  {  {
105      // No more notifications.          // Turn off and close logging.
106      if (m_pStdoutNotifier)          setLogging(false);
107          delete m_pStdoutNotifier;  
108            // No more notifications.
109            if (m_pStdoutNotifier)
110                    delete m_pStdoutNotifier;
111    
112            // No need to delete child widgets, Qt does it all for us.
113    }
114    
115    
116      // No need to delete child widgets, Qt does it all for us.  // Set stdout/stderr blocking mode.
117    bool Messages::stdoutBlock ( int fd, bool bBlock ) const
118    {
119    #if !defined(_WIN32)
120            const int iFlags = ::fcntl(fd, F_GETFL, 0);
121            const bool bNonBlock = bool(iFlags & O_NONBLOCK);
122            if (bBlock && bNonBlock)
123                    bBlock = (::fcntl(fd, F_SETFL, iFlags & ~O_NONBLOCK) == 0);
124            else
125            if (!bBlock && !bNonBlock)
126                    bBlock = (::fcntl(fd, F_SETFL, iFlags |  O_NONBLOCK) != 0);
127    #endif
128            return bBlock;
129  }  }
130    
131    
132  // Own stdout/stderr socket notifier slot.  // Own stdout/stderr socket notifier slot.
133  void qsamplerMessages::stdoutNotify ( int fd )  void Messages::stdoutNotify ( int fd )
134  {  {
135  #if !defined(WIN32)  #if !defined(_WIN32)
136      char achBuffer[1024];          // Set non-blocking reads, if not already...
137      int  cchBuffer = ::read(fd, achBuffer, sizeof(achBuffer) - 1);          const bool bBlock = stdoutBlock(fd, false);
138      if (cchBuffer > 0) {          // Read as much as is available...
139          achBuffer[cchBuffer] = (char) 0;          QString sTemp;
140          appendStdoutBuffer(achBuffer);          char achBuffer[1024];
141      }          const int cchBuffer = sizeof(achBuffer) - 1;
142            int cchRead = ::read(fd, achBuffer, cchBuffer);
143            while (cchRead > 0) {
144                    achBuffer[cchRead] = (char) 0;
145                    sTemp.append(achBuffer);
146                    cchRead = (bBlock ? 0 : ::read(fd, achBuffer, cchBuffer));
147            }
148            // Needs to be non-empty...
149            if (!sTemp.isEmpty())
150                    appendStdoutBuffer(sTemp);
151  #endif  #endif
152  }  }
153    
154    
155  // Stdout buffer handler -- now splitted by complete new-lines...  // Stdout buffer handler -- now splitted by complete new-lines...
156  void qsamplerMessages::appendStdoutBuffer ( const QString& s )  void Messages::appendStdoutBuffer ( const QString& s )
157  {  {
158      m_sStdoutBuffer.append(s);          m_sStdoutBuffer.append(s);
159    
160      int iLength = m_sStdoutBuffer.findRev('\n') + 1;          const int iLength = m_sStdoutBuffer.lastIndexOf('\n');
161      if (iLength > 0) {          if (iLength > 0) {
162          QString sTemp = m_sStdoutBuffer.left(iLength);                  const QString& sTemp = m_sStdoutBuffer.left(iLength);
163          m_sStdoutBuffer.remove(0, iLength);                  m_sStdoutBuffer.remove(0, iLength + 1);
164          QStringList list = QStringList::split('\n', sTemp, true);                  QStringList list = sTemp.split('\n');
165          for (QStringList::Iterator iter = list.begin(); iter != list.end(); iter++)                  QStringListIterator iter(list);
166              appendMessagesText(*iter);                  while (iter.hasNext())
167      }                          appendMessagesText(iter.next());
168            }
169  }  }
170    
171    
172  // Stdout flusher -- show up any unfinished line...  // Stdout flusher -- show up any unfinished line...
173  void qsamplerMessages::flushStdoutBuffer (void)  void Messages::flushStdoutBuffer (void)
174  {  {
175      if (!m_sStdoutBuffer.isEmpty()) {          if (!m_sStdoutBuffer.isEmpty()) {
176          appendMessagesText(m_sStdoutBuffer);                  appendMessagesText(m_sStdoutBuffer);
177          m_sStdoutBuffer.truncate(0);                  m_sStdoutBuffer.clear();
178      }          }
179  }  }
180    
181    
182  // Stdout capture accessors.  // Stdout capture accessors.
183  bool qsamplerMessages::isCaptureEnabled (void)  bool Messages::isCaptureEnabled (void)
184  {  {
185      return (bool) (m_pStdoutNotifier != NULL);          return (m_pStdoutNotifier != NULL);
186  }  }
187    
188  void qsamplerMessages::setCaptureEnabled ( bool bCapture )  void Messages::setCaptureEnabled ( bool bCapture )
189  {  {
190      // Flush current buffer.          // Flush current buffer.
191      flushStdoutBuffer();          flushStdoutBuffer();
192    
193  #if !defined(WIN32)  #if !defined(_WIN32)
194      // Destroy if already enabled.          // Destroy if already enabled.
195      if (!bCapture && m_pStdoutNotifier) {          if (!bCapture && m_pStdoutNotifier) {
196          delete m_pStdoutNotifier;                  delete m_pStdoutNotifier;
197          m_pStdoutNotifier = NULL;                  m_pStdoutNotifier = NULL;
198          // Close the notification pipes.                  // Close the notification pipes.
199          if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {                  if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {
200              ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);                          ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);
201              m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;                          m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;
202          }                  }
203          if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {          }
204              ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);          // Are we going to make up the capture?
205              m_fdStdout[QSAMPLER_MESSAGES_FDREAD]  = QSAMPLER_MESSAGES_FDNIL;          if (bCapture && m_pStdoutNotifier == NULL && ::pipe(m_fdStdout) == 0) {
206          }                  ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO);
207      }                  ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO);
208      // Are we going to make up the capture?                  m_pStdoutNotifier = new QSocketNotifier(
209      if (bCapture && m_pStdoutNotifier == NULL && ::pipe(m_fdStdout) == 0) {                          m_fdStdout[QSAMPLER_MESSAGES_FDREAD], QSocketNotifier::Read, this);
210          ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO);                  QObject::connect(m_pStdoutNotifier,
211          ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO);                          SIGNAL(activated(int)),
212          m_pStdoutNotifier = new QSocketNotifier(m_fdStdout[QSAMPLER_MESSAGES_FDREAD], QSocketNotifier::Read, this);                          SLOT(stdoutNotify(int)));
213          QObject::connect(m_pStdoutNotifier, SIGNAL(activated(int)), this, SLOT(stdoutNotify(int)));          }
     }  
214  #endif  #endif
215  }  }
216    
217    
218  // Message font accessors.  // Message font accessors.
219  QFont qsamplerMessages::messagesFont (void)  QFont Messages::messagesFont (void)
220  {  {
221      return m_pTextView->font();          return m_pMessagesTextView->font();
222  }  }
223    
224  void qsamplerMessages::setMessagesFont( const QFont& font )  void Messages::setMessagesFont ( const QFont& font )
225  {  {
226      m_pTextView->setFont(font);          m_pMessagesTextView->setFont(font);
227  }  }
228    
229    
230  // Maximum number of message lines accessors.  // Maximum number of message lines accessors.
231  int qsamplerMessages::messagesLimit (void)  int Messages::messagesLimit (void)
232    {
233            return m_iMessagesLimit;
234    }
235    
236    void Messages::setMessagesLimit ( int iMessagesLimit )
237    {
238            m_iMessagesLimit = iMessagesLimit;
239            m_iMessagesHigh  = iMessagesLimit + (iMessagesLimit / 3);
240    }
241    
242    // Messages logging stuff.
243    bool Messages::isLogging (void) const
244    {
245            return (m_pMessagesLog != NULL);
246    }
247    
248    void Messages::setLogging ( bool bEnabled, const QString& sFilename )
249    {
250            if (m_pMessagesLog) {
251                    appendMessages(tr("Logging stopped --- %1 ---")
252                            .arg(QDateTime::currentDateTime().toString()));
253                    m_pMessagesLog->close();
254                    delete m_pMessagesLog;
255                    m_pMessagesLog = NULL;
256            }
257    
258            if (bEnabled) {
259                    m_pMessagesLog = new QFile(sFilename);
260                    if (m_pMessagesLog->open(QIODevice::Text | QIODevice::Append)) {
261                            appendMessages(tr("Logging started --- %1 ---")
262                                    .arg(QDateTime::currentDateTime().toString()));
263                    } else {
264                            delete m_pMessagesLog;
265                            m_pMessagesLog = NULL;
266                    }
267            }
268    }
269    
270    
271    // Messages log output method.
272    void Messages::appendMessagesLog ( const QString& s )
273  {  {
274      return m_iMessagesLimit;          if (m_pMessagesLog) {
275                    QTextStream(m_pMessagesLog) << s << endl;
276                    m_pMessagesLog->flush();
277            }
278  }  }
279    
280  void qsamplerMessages::setMessagesLimit ( int iMessagesLimit )  // Messages widget output method.
281    void Messages::appendMessagesLine ( const QString& s )
282  {  {
283      m_iMessagesLimit = iMessagesLimit;          // Check for message line limit...
284            if (m_iMessagesLines > m_iMessagesHigh) {
285                    m_pMessagesTextView->setUpdatesEnabled(false);
286                    QTextCursor textCursor(m_pMessagesTextView->document()->begin());
287                    while (m_iMessagesLines > m_iMessagesLimit) {
288                            // Move cursor extending selection
289                            // from start to next line-block...
290                            textCursor.movePosition(
291                                    QTextCursor::NextBlock, QTextCursor::KeepAnchor);
292                            m_iMessagesLines--;
293                    }
294                    // Remove the excessive line-blocks...
295                    textCursor.removeSelectedText();
296                    m_pMessagesTextView->setUpdatesEnabled(true);
297            }
298    
299            m_pMessagesTextView->append(s);
300            m_iMessagesLines++;
301  }  }
302    
303    
304  // The main utility methods.  // The main utility methods.
305  void qsamplerMessages::appendMessages ( const QString& s )  void Messages::appendMessages ( const QString& s )
306  {  {
307      appendMessagesColor(s, "#999999");          appendMessagesColor(s, "#999999");
308  }  }
309    
310  void qsamplerMessages::appendMessagesColor ( const QString& s, const QString &c )  void Messages::appendMessagesColor ( const QString& s, const QString &c )
311  {  {
312      appendMessagesText("<font color=\"" + c + "\">" + QTime::currentTime().toString("hh:mm:ss.zzz") + " " + s + "</font>");          const QString& sText
313                    = QTime::currentTime().toString("hh:mm:ss.zzz") + ' ' + s;
314            appendMessagesLine("<font color=\"" + c + "\">" + sText + "</font>");
315            appendMessagesLog(sText);
316  }  }
317    
318  void qsamplerMessages::appendMessagesText ( const QString& s )  void Messages::appendMessagesText ( const QString& s )
319  {  {
320      // Check for message line limit...          appendMessagesLine(s);
321      if (m_iMessagesLimit > 0) {          appendMessagesLog(s);
         int iParagraphs = m_pTextView->paragraphs();  
         if (iParagraphs > m_iMessagesLimit) {  
             m_pTextView->setUpdatesEnabled(false);  
             while (iParagraphs > m_iMessagesLimit) {  
                 m_pTextView->removeParagraph(0);  
                 iParagraphs--;  
             }  
             m_pTextView->scrollToBottom();  
             m_pTextView->setUpdatesEnabled(true);  
         }  
     }  
     m_pTextView->append(s);  
322  }  }
323    
324    
325  // One time scroll to the most recent message.  // History reset.
326  void qsamplerMessages::scrollToBottom (void)  void Messages::clear (void)
327  {  {
328      flushStdoutBuffer();          m_iMessagesLines = 0;
329      m_pTextView->scrollToBottom();          m_pMessagesTextView->clear();
330  }  }
331    
332    } // namespace QSampler
333    
334    
335  // end of qsamplerMessages.cpp  // end of qsamplerMessages.cpp

Legend:
Removed from v.115  
changed lines
  Added in v.3357

  ViewVC Help
Powered by ViewVC