18class QColorOutputPrivate
23 m_coloringEnabled = isColoringPossible();
24 m_hyperLinkSupport = m_coloringEnabled;
27 ~QColorOutputPrivate() { fflush(stderr); }
29 static const char *
const foregrounds[];
30 static const char *
const backgrounds[];
32 inline void write(
const QString &msg)
34 m_buffer.append(msg.toLocal8Bit());
37 static QString escapeCode(
const QString &in)
39 const ushort escapeChar = 0x1B;
41 result.append(QChar(escapeChar));
42 result.append(QLatin1Char(
'['));
44 result.append(QLatin1Char(
'm'));
48 void insertColor(
int id, QColorOutput::ColorCode code) { m_colorMapping.insert(id, code); }
49 QColorOutput::ColorCode color(
int id)
const {
return m_colorMapping.value(id); }
50 bool containsColor(
int id)
const {
return m_colorMapping.contains(id); }
52 void setSilent(
bool silent) { m_silent = silent; }
53 bool isSilent()
const {
return m_silent; }
55 void setCurrentColorID(
int colorId) { m_currentColorID = colorId; }
57 bool coloringEnabled()
const {
return m_coloringEnabled; }
58 bool hasHyperLinkSupport()
const {
return m_hyperLinkSupport; }
59 void setHyperLinkSupport(
bool v) { m_hyperLinkSupport = v; }
63 fwrite(m_buffer.constData(), size_t(1), size_t(m_buffer.size()), stderr);
67 qsizetype bufferSize()
const {
return m_buffer.size(); }
69 void truncateBuffer(qsizetype size) { m_buffer.truncate(size); }
73 QColorOutput::ColorMapping m_colorMapping;
74 int m_currentColorID = -1;
75 bool m_coloringEnabled =
false;
76 bool m_hyperLinkSupport =
false;
77 bool m_silent =
false;
80
81
82 inline bool isColoringPossible()
const
84 static std::optional<
bool> canColor;
85 if (canColor.has_value())
86 return canColor.value();
89 HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
92 if (GetConsoleMode(hErr, &mode))
93 canColor = SetConsoleMode(hErr, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
98
99
100 canColor = isatty(fileno(stderr));
102 return canColor.value();
256void QColorOutput::writePrefixedMessage(
const QString &message, QtMsgType type,
257 const QString &prefix)
259 static const QHash<QtMsgType, QString> prefixes = {
260 {QtMsgType::QtCriticalMsg, QStringLiteral(
"Error")},
261 {QtMsgType::QtWarningMsg, QStringLiteral(
"Warning")},
262 {QtMsgType::QtInfoMsg, QStringLiteral(
"Info")},
263 {QtMsgType::QtDebugMsg, QStringLiteral(
"Hint")}
266 Q_ASSERT(prefixes.contains(type));
267 Q_ASSERT(prefix.isEmpty() || prefix.front().isUpper());
268 write((prefix.isEmpty() ? prefixes[type] : prefix) + QStringLiteral(
": "), type);
269 writeUncolored(message);
317QString QColorOutput::colorify(
const QStringView message,
int colorID)
const
319 Q_ASSERT_X(colorID == -1 || d->containsColor(colorID), Q_FUNC_INFO,
320 qPrintable(QString::fromLatin1(
"There is no color registered by id %1")
322 Q_ASSERT_X(!message.isEmpty(), Q_FUNC_INFO,
323 "It makes no sense to attempt to print an empty string.");
326 d->setCurrentColorID(colorID);
328 if (d->coloringEnabled() && colorID != -1) {
329 const int color = d->color(colorID);
332 if (color & DefaultColor)
333 return message.toString();
335 const int foregroundCode = (color & ForegroundMask) >> ForegroundShift;
336 const int backgroundCode = (color & BackgroundMask) >> BackgroundShift;
337 QString finalMessage;
338 bool closureNeeded =
false;
340 if (foregroundCode > 0) {
342 QColorOutputPrivate::escapeCode(
343 QLatin1String(QColorOutputPrivate::foregrounds[foregroundCode - 1])));
344 closureNeeded =
true;
347 if (backgroundCode > 0) {
349 QColorOutputPrivate::escapeCode(
350 QLatin1String(QColorOutputPrivate::backgrounds[backgroundCode - 1])));
351 closureNeeded =
true;
354 finalMessage.append(message);
357 finalMessage.append(QColorOutputPrivate::escapeCode(QLatin1String(
"0")));
362 return message.toString();