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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3759 - (show annotations) (download)
Sat Mar 28 00:28:13 2020 UTC (4 years ago) by capela
File size: 9244 byte(s)
- Early fixing to build for Qt >= 5.15.0. (bis)
1 // qsamplerMessages.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2004-2020, 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
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 *****************************************************************************/
22
23 #include "qsamplerAbout.h"
24 #include "qsamplerMessages.h"
25
26 #include <QSocketNotifier>
27
28 #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__) && !defined(_WIN32) && !defined(WIN32)
38 #include <unistd.h>
39 #include <fcntl.h>
40 #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.
52 #define QSAMPLER_MESSAGES_MAXLINES 1000
53
54 // Notification pipe descriptors
55 #define QSAMPLER_MESSAGES_FDNIL -1
56 #define QSAMPLER_MESSAGES_FDREAD 0
57 #define QSAMPLER_MESSAGES_FDWRITE 1
58
59
60 //-------------------------------------------------------------------------
61 // QSampler::Messages - Messages log dockable window.
62 //
63
64 // Constructor.
65 Messages::Messages ( QWidget *pParent )
66 : QDockWidget(pParent)
67 {
68 // Surely a name is crucial (e.g.for storing geometry settings)
69 QDockWidget::setObjectName("qsamplerMessages");
70
71 // Intialize stdout capture stuff.
72 m_pStdoutNotifier = nullptr;
73 m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL;
74 m_fdStdout[QSAMPLER_MESSAGES_FDWRITE] = QSAMPLER_MESSAGES_FDNIL;
75
76 // Create local text view widget.
77 m_pMessagesTextView = new QTextEdit(this);
78 // QFont font(m_pMessagesTextView->font());
79 // font.setFamily("Fixed");
80 // m_pMessagesTextView->setFont(font);
81 m_pMessagesTextView->setLineWrapMode(QTextEdit::NoWrap);
82 m_pMessagesTextView->setReadOnly(true);
83 m_pMessagesTextView->setUndoRedoEnabled(false);
84 // m_pMessagesTextView->setTextFormat(Qt::LogText);
85
86 // Initialize default message limit.
87 m_iMessagesLines = 0;
88 setMessagesLimit(QSAMPLER_MESSAGES_MAXLINES);
89
90 m_pMessagesLog = nullptr;
91
92 // Prepare the dockable window stuff.
93 QDockWidget::setWidget(m_pMessagesTextView);
94 QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
95 QDockWidget::setAllowedAreas(
96 Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
97 // Some specialties to this kind of dock window...
98 QDockWidget::setMinimumHeight(120);
99
100 // Finally set the default caption and tooltip.
101 const QString& sCaption = tr("Messages");
102 QDockWidget::setWindowTitle(sCaption);
103 // QDockWidget::setWindowIcon(QIcon(":/icons/qsamplerMessages.png"));
104 QDockWidget::setToolTip(sCaption);
105 }
106
107
108 // Destructor.
109 Messages::~Messages (void)
110 {
111 // Turn off and close logging.
112 setLogging(false);
113
114 // 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 // Set stdout/stderr blocking mode.
123 bool Messages::stdoutBlock ( int fd, bool bBlock ) const
124 {
125 #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
126 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.
139 void Messages::stdoutNotify ( int fd )
140 {
141 #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
142 // Set non-blocking reads, if not already...
143 const bool bBlock = stdoutBlock(fd, false);
144 // Read as much as is available...
145 QString sTemp;
146 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
158 }
159
160
161 // Stdout buffer handler -- now splitted by complete new-lines...
162 void Messages::appendStdoutBuffer ( const QString& s )
163 {
164 m_sStdoutBuffer.append(s);
165
166 const int iLength = m_sStdoutBuffer.lastIndexOf('\n');
167 if (iLength > 0) {
168 const QString& sTemp = m_sStdoutBuffer.left(iLength);
169 m_sStdoutBuffer.remove(0, iLength + 1);
170 QStringList list = sTemp.split('\n');
171 QStringListIterator iter(list);
172 while (iter.hasNext())
173 appendMessagesText(iter.next());
174 }
175 }
176
177
178 // Stdout flusher -- show up any unfinished line...
179 void Messages::flushStdoutBuffer (void)
180 {
181 if (!m_sStdoutBuffer.isEmpty()) {
182 appendMessagesText(m_sStdoutBuffer);
183 m_sStdoutBuffer.clear();
184 }
185 }
186
187
188 // Stdout capture accessors.
189 bool Messages::isCaptureEnabled (void)
190 {
191 return (m_pStdoutNotifier != nullptr);
192 }
193
194 void Messages::setCaptureEnabled ( bool bCapture )
195 {
196 // Flush current buffer.
197 flushStdoutBuffer();
198
199 #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32)
200 // Destroy if already enabled.
201 if (!bCapture && m_pStdoutNotifier) {
202 delete m_pStdoutNotifier;
203 m_pStdoutNotifier = nullptr;
204 // Close the notification pipes.
205 if (m_fdStdout[QSAMPLER_MESSAGES_FDREAD] != QSAMPLER_MESSAGES_FDNIL) {
206 ::close(m_fdStdout[QSAMPLER_MESSAGES_FDREAD]);
207 m_fdStdout[QSAMPLER_MESSAGES_FDREAD] = QSAMPLER_MESSAGES_FDNIL;
208 }
209 }
210 // Are we going to make up the capture?
211 if (bCapture && m_pStdoutNotifier == nullptr && ::pipe(m_fdStdout) == 0) {
212 ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDOUT_FILENO);
213 ::dup2(m_fdStdout[QSAMPLER_MESSAGES_FDWRITE], STDERR_FILENO);
214 m_pStdoutNotifier = new QSocketNotifier(
215 m_fdStdout[QSAMPLER_MESSAGES_FDREAD], QSocketNotifier::Read, this);
216 QObject::connect(m_pStdoutNotifier,
217 SIGNAL(activated(int)),
218 SLOT(stdoutNotify(int)));
219 }
220 #endif
221 }
222
223
224 // Message font accessors.
225 QFont Messages::messagesFont (void)
226 {
227 return m_pMessagesTextView->font();
228 }
229
230 void Messages::setMessagesFont ( const QFont& font )
231 {
232 m_pMessagesTextView->setFont(font);
233 }
234
235
236 // Maximum number of message lines accessors.
237 int Messages::messagesLimit (void)
238 {
239 return m_iMessagesLimit;
240 }
241
242 void Messages::setMessagesLimit ( int iMessagesLimit )
243 {
244 m_iMessagesLimit = iMessagesLimit;
245 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 void Messages::setLogging ( bool bEnabled, const QString& sFilename )
255 {
256 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
277 // Messages log output method.
278 void Messages::appendMessagesLog ( const QString& s )
279 {
280 if (m_pMessagesLog) {
281 QTextStream(m_pMessagesLog) << s << endl;
282 m_pMessagesLog->flush();
283 }
284 }
285
286 // Messages widget output method.
287 void Messages::appendMessagesLine ( const QString& s )
288 {
289 // Check for message line limit...
290 if (m_iMessagesLines > m_iMessagesHigh) {
291 m_pMessagesTextView->setUpdatesEnabled(false);
292 QTextCursor textCursor(m_pMessagesTextView->document()->begin());
293 while (m_iMessagesLines > m_iMessagesLimit) {
294 // Move cursor extending selection
295 // from start to next line-block...
296 textCursor.movePosition(
297 QTextCursor::NextBlock, QTextCursor::KeepAnchor);
298 m_iMessagesLines--;
299 }
300 // Remove the excessive line-blocks...
301 textCursor.removeSelectedText();
302 m_pMessagesTextView->setUpdatesEnabled(true);
303 }
304
305 m_pMessagesTextView->append(s);
306 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.
332 void Messages::clear (void)
333 {
334 m_iMessagesLines = 0;
335 m_pMessagesTextView->clear();
336 }
337
338 } // namespace QSampler
339
340
341 // end of qsamplerMessages.cpp

  ViewVC Help
Powered by ViewVC