18class QColorOutputPrivate
23 m_coloringEnabled = isColoringPossible();
26 ~QColorOutputPrivate() { fflush(stderr); }
28 static const char *
const foregrounds[];
29 static const char *
const backgrounds[];
31 inline void write(
const QString &msg)
33 m_buffer.append(msg.toLocal8Bit());
36 static QString escapeCode(
const QString &in)
38 const ushort escapeChar = 0x1B;
40 result.append(QChar(escapeChar));
41 result.append(QLatin1Char(
'['));
43 result.append(QLatin1Char(
'm'));
47 void insertColor(
int id, QColorOutput::ColorCode code) { m_colorMapping.insert(id, code); }
48 QColorOutput::ColorCode color(
int id)
const {
return m_colorMapping.value(id); }
49 bool containsColor(
int id)
const {
return m_colorMapping.contains(id); }
51 void setSilent(
bool silent) { m_silent = silent; }
52 bool isSilent()
const {
return m_silent; }
54 void setCurrentColorID(
int colorId) { m_currentColorID = colorId; }
56 bool coloringEnabled()
const {
return m_coloringEnabled; }
60 fwrite(m_buffer.constData(), size_t(1), size_t(m_buffer.size()), stderr);
71 QColorOutput::ColorMapping m_colorMapping;
72 int m_currentColorID = -1;
73 bool m_coloringEnabled =
false;
74 bool m_silent =
false;
77
78
79 inline bool isColoringPossible()
const
81 static std::optional<
bool> canColor;
82 if (canColor.has_value())
83 return canColor.value();
86 HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
89 if (GetConsoleMode(hErr, &mode))
90 canColor = SetConsoleMode(hErr, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
95
96
97 canColor = isatty(fileno(stderr));
99 return canColor.value();
253void QColorOutput::writePrefixedMessage(
const QString &message, QtMsgType type,
254 const QString &prefix)
256 static const QHash<QtMsgType, QString> prefixes = {
257 {QtMsgType::QtCriticalMsg, QStringLiteral(
"Error")},
258 {QtMsgType::QtWarningMsg, QStringLiteral(
"Warning")},
259 {QtMsgType::QtInfoMsg, QStringLiteral(
"Info")},
260 {QtMsgType::QtDebugMsg, QStringLiteral(
"Hint")}
263 Q_ASSERT(prefixes.contains(type));
264 Q_ASSERT(prefix.isEmpty() || prefix.front().isUpper());
265 write((prefix.isEmpty() ? prefixes[type] : prefix) + QStringLiteral(
": "), type);
266 writeUncolored(message);
291QString QColorOutput::colorify(
const QStringView message,
int colorID)
const
293 Q_ASSERT_X(colorID == -1 || d->containsColor(colorID), Q_FUNC_INFO,
294 qPrintable(QString::fromLatin1(
"There is no color registered by id %1")
296 Q_ASSERT_X(!message.isEmpty(), Q_FUNC_INFO,
297 "It makes no sense to attempt to print an empty string.");
300 d->setCurrentColorID(colorID);
302 if (d->coloringEnabled() && colorID != -1) {
303 const int color = d->color(colorID);
306 if (color & DefaultColor)
307 return message.toString();
309 const int foregroundCode = (color & ForegroundMask) >> ForegroundShift;
310 const int backgroundCode = (color & BackgroundMask) >> BackgroundShift;
311 QString finalMessage;
312 bool closureNeeded =
false;
314 if (foregroundCode > 0) {
316 QColorOutputPrivate::escapeCode(
317 QLatin1String(QColorOutputPrivate::foregrounds[foregroundCode - 1])));
318 closureNeeded =
true;
321 if (backgroundCode > 0) {
323 QColorOutputPrivate::escapeCode(
324 QLatin1String(QColorOutputPrivate::backgrounds[backgroundCode - 1])));
325 closureNeeded =
true;
328 finalMessage.append(message);
331 finalMessage.append(QColorOutputPrivate::escapeCode(QLatin1String(
"0")));
336 return message.toString();