summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@pelagicore.com>2017-03-06 22:39:33 +0100
committerDominik Holland <dominik.holland@pelagicore.com>2017-03-07 14:38:50 +0000
commita9404523588b22fb9f4baab6348832a0f4fce2ad (patch)
tree7f45a676e808522b30d7e845239d54f622df17b1
parent83ffd22608c6a5329d2a982b6b1a58dc17e88762 (diff)
downloadqtapplicationmanager-a9404523588b22fb9f4baab6348832a0f4fce2ad.tar.gz
Further cleanup/improvement of the color output handler
* getOutputInformation does all the low-level handling now * getOutputInformation is for stderr only - this was very confusing and ultimately unnecessary before * console resizing is now also supported on Windows * made the variable naming a bit more meaningful Change-Id: Ice432f6a148a855e7f7085fe1fbf31aa1bd6576d Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r--src/common-lib/global.cpp33
-rw-r--r--src/common-lib/startuptimer.cpp26
-rw-r--r--src/common-lib/utilities.cpp121
-rw-r--r--src/common-lib/utilities.h2
4 files changed, 101 insertions, 81 deletions
diff --git a/src/common-lib/global.cpp b/src/common-lib/global.cpp
index c6123ee3..653e3d9b 100644
--- a/src/common-lib/global.cpp
+++ b/src/common-lib/global.cpp
@@ -46,7 +46,6 @@
#include "global.h"
#include "utilities.h"
-#include "unixsignalhandler.h"
#include <stdio.h>
#if defined(Q_OS_WIN)
@@ -122,21 +121,10 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
out.reserve(512);
out.resize(0);
- static int windowWidth = -1;
- static bool useAnsiColors = false;
- static QAtomicInteger<int> windowSizeCached(0);
-
-#if defined(Q_OS_UNIX) && defined(SIGWINCH)
- UnixSignalHandler::instance()->install(UnixSignalHandler::RawSignalHandler, SIGWINCH, [](int) {
- windowSizeCached = 0;
- });
-#endif
- // This while loop is needed, since SIGWINCH could arrive while getOutputInformation is running.
- // In reality this should never happen, short of the user resizing his console like a madman.
- while (!windowSizeCached) {
- windowSizeCached = 1;
- getOutputInformation(&useAnsiColors, nullptr, &windowWidth);
- }
+ int consoleWidth = -1;
+ bool ansiColorSupport = false;
+ bool runningInCreator = false;
+ getOutputInformation(&ansiColorSupport, &runningInCreator, &consoleWidth);
// Find out, if we have a valid code location and prepare the output strings
const char *filename = nullptr;
@@ -166,7 +154,7 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
enum ConsoleColor { Off = 0, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, BrightFlag = 0x80 };
// helper function to append ANSI color codes to a string
- static auto color = [](QByteArray &out, int consoleColor) -> void {
+ static auto color = [ansiColorSupport](QByteArray &out, int consoleColor) -> void {
static const char *ansiColors[] = {
"\x1b[1m", // bright
"\x1b[0m", // off
@@ -180,7 +168,7 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
"\x1b[37m" // gray
};
- if (!useAnsiColors)
+ if (!ansiColorSupport)
return;
if (consoleColor & BrightFlag)
out.append(ansiColors[0]);
@@ -221,9 +209,9 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
if (filenameLength && linenumberLength) {
int spacing = 1;
- if (windowWidth > 0) {
+ if (consoleWidth > 0) {
// right-align the location mark
- spacing = windowWidth - outLength - linenumberLength - filenameLength - 4; // 4 == strlen(" [:]")
+ spacing = consoleWidth - outLength - linenumberLength - filenameLength - 4; // 4 == strlen(" [:]")
// keep the location mark right-aligned, even if the message contains newlines
int lastNewline = msg.lastIndexOf('\n');
@@ -232,7 +220,7 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
// keep the location mark right-aligned, even if the message is longer than the window width
while (spacing < 0)
- spacing += windowWidth;
+ spacing += consoleWidth;
}
out.append(spacing, ' ');
out.append('[');
@@ -252,7 +240,7 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
out.append('\n');
}
- if (windowWidth <= 0) {
+ if (consoleWidth <= 0) {
#if defined(Q_OS_WIN)
// do not use QMutex to avoid possible recursions
static CRITICAL_SECTION cs;
@@ -282,7 +270,6 @@ static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &contex
#endif
}
fputs(out.constData(), stderr);
- fflush(stderr);
}
#if defined(QT_GENIVIEXTRAS_LIB)
diff --git a/src/common-lib/startuptimer.cpp b/src/common-lib/startuptimer.cpp
index a999bb40..8cccca6e 100644
--- a/src/common-lib/startuptimer.cpp
+++ b/src/common-lib/startuptimer.cpp
@@ -283,15 +283,15 @@ void StartupTimer::checkpoint(const QString &name)
void StartupTimer::createReport(const QString &title)
{
if (m_output) {
- bool useAnsiColors;
- getOutputInformation(&useAnsiColors, nullptr, nullptr, fileno(m_output));
+ bool ansiColorSupport = false;
+ if (m_output == stderr)
+ getOutputInformation(&ansiColorSupport, nullptr, nullptr);
if (!m_reportCreated) {
- if (useAnsiColors) {
- fprintf(m_output, "\n\033[33m== STARTUP TIMING REPORT: %s ==\033[0m\n", title.toLocal8Bit().data());
- } else {
- fprintf(m_output, "\n== STARTUP TIMING REPORT: %s ==\n", title.toLocal8Bit().data());
- }
+ const char *format = "\n== STARTUP TIMING REPORT: %s ==\n";
+ if (ansiColorSupport)
+ format = "\n\033[33m== STARTUP TIMING REPORT: %s ==\033[0m\n";
+ fprintf(m_output, format, title.toLocal8Bit().data());
}
static const int barCols = 60;
@@ -311,7 +311,7 @@ void StartupTimer::createReport(const QString &title)
const QByteArray text = m_checkpoints.at(i).second;
int sec = 0;
int cells = usec / usecPerCell;
- QByteArray bar(cells, useAnsiColors ? ' ' : '#');
+ QByteArray bar(cells, ansiColorSupport ? ' ' : '#');
QByteArray spacing(maxTextLen - text.length(), ' ');
if (usec > 1000*1000) {
@@ -321,11 +321,11 @@ void StartupTimer::createReport(const QString &title)
int msec = usec / 1000;
usec %= 1000;
- if (useAnsiColors) {
- fprintf(m_output, "\033[32m%d'%03d.%03d\033[0m %s %s\033[44m %s\033[0m\n", sec, msec, int(usec), text.constData(), spacing.constData(), bar.constData());
- } else {
- fprintf(m_output, "%d'%03d.%03d %s %s#%s\n", sec, msec, int(usec), text.constData(), spacing.constData(), bar.constData());
- }
+ const char *format = "%d'%03d.%03d %s %s#%s\n";
+ if (ansiColorSupport)
+ format = "\033[32m%d'%03d.%03d\033[0m %s %s\033[44m %s\033[0m\n";
+
+ fprintf(m_output, format, sec, msec, int(usec), text.constData(), spacing.constData(), bar.constData());
}
fflush(m_output);
diff --git a/src/common-lib/utilities.cpp b/src/common-lib/utilities.cpp
index 47bf8e20..4f6b18e3 100644
--- a/src/common-lib/utilities.cpp
+++ b/src/common-lib/utilities.cpp
@@ -51,6 +51,7 @@
#include "utilities.h"
#include "exception.h"
+#include "unixsignalhandler.h"
#include <errno.h>
@@ -58,8 +59,10 @@
# include <unistd.h>
# include <sys/ioctl.h>
# include <termios.h>
+# include <signal.h>
#endif
#if defined(Q_OS_WIN)
+# include <QThread>
# include <windows.h>
# include <io.h>
# include <tlhelp32.h>
@@ -435,7 +438,6 @@ QString findOnSDCard(const QString &file)
QT_END_NAMESPACE_AM
-#include <unixsignalhandler.h>
#include <cxxabi.h>
#include <execinfo.h>
#include <setjmp.h>
@@ -704,37 +706,16 @@ void setCrashActionConfiguration(const QVariantMap &config)
#endif // !Q_OS_LINUX
-void getOutputInformation(bool *useAnsiColors, bool *runningInCreator, int *windowWidth, int consoleFd)
+void getOutputInformation(bool *ansiColorSupport, bool *runningInCreator, int *consoleWidth)
{
- static enum { ColorAuto, ColorOff, ColorOn } forceColor = ColorAuto;
- static bool consoleSupportsAnsiColors = false;
- static bool detectedRunningInCreator = false;
+ static bool ansiColorSupportDetected = false;
+ static bool runningInCreatorDetected = false;
+ static QAtomicInteger<int> consoleWidthCached(0);
+ static int consoleWidthCalculated = -1;
static bool once = false;
- static auto calculateWindowWidth = [](int fd) -> int {
- int windowWidth = -1;
-#if defined(Q_OS_UNIX)
- if (fd < 0)
- fd = STDERR_FILENO;
- if (::isatty(fd)) {
- struct ::winsize ws;
- if ((::ioctl(fd, TIOCGWINSZ, &ws) == 0) && (ws.ws_col > 0))
- windowWidth = ws.ws_col;
- }
-#elif defined(Q_OS_WIN)
- HANDLE h = (fd >= 0) ? (HANDLE) _get_osfhandle(fd) : GetStdHandle(STD_ERROR_HANDLE);
- if (h != INVALID_HANDLE_VALUE && h != NULL) {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (GetConsoleScreenBufferInfo(h, &csbi))
- windowWidth = csbi.dwSize.X;
- }
-#endif
- return windowWidth;
- };
-
- bool forStderr = (consoleFd < 0) || (consoleFd == 2);
-
if (!once) {
+ enum { ColorAuto, ColorOff, ColorOn } forceColor = ColorAuto;
QByteArray forceColorOutput = qgetenv("AM_FORCE_COLOR_OUTPUT");
if (forceColorOutput == "off" || forceColorOutput == "0")
forceColor = ColorOff;
@@ -743,7 +724,7 @@ void getOutputInformation(bool *useAnsiColors, bool *runningInCreator, int *wind
#if defined(Q_OS_UNIX)
if (::isatty(STDERR_FILENO))
- consoleSupportsAnsiColors = true;
+ ansiColorSupportDetected = true;
#elif defined(Q_OS_WIN)
HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
@@ -754,7 +735,7 @@ void getOutputInformation(bool *useAnsiColors, bool *runningInCreator, int *wind
if (GetConsoleMode(h, &mode)) {
mode |= 0x04;
if (SetConsoleMode(h, mode))
- consoleSupportsAnsiColors = true;
+ ansiColorSupportDetected = true;
}
}
}
@@ -770,14 +751,14 @@ void getOutputInformation(bool *useAnsiColors, bool *runningInCreator, int *wind
static QString checkCreator = qSL("/proc/%1/exe");
QFileInfo fi(checkCreator.arg(pid));
if (fi.readLink().contains(qSL("qtcreator"))) {
- detectedRunningInCreator = true;
+ runningInCreatorDetected = true;
break;
}
#elif defined(Q_OS_OSX)
static char buffer[PROC_PIDPATHINFO_MAXSIZE + 1];
int len = proc_pidpath(pid, buffer, sizeof(buffer) - 1);
if ((len > 0) && QByteArray::fromRawData(buffer, len).contains("Qt Creator")) {
- detectedRunningInCreator = true;
+ runningInCreatorDetected = true;
break;
}
#elif defined(Q_OS_WIN)
@@ -787,26 +768,78 @@ void getOutputInformation(bool *useAnsiColors, bool *runningInCreator, int *wind
DWORD exeNameSize = sizeof(exeName) - 1;
if (QueryFullProcessImageNameW(hProcess, 0, exeName, &exeNameSize)) {
if (QString::fromWCharArray(exeName, exeNameSize).contains(qSL("qtcreator.exe")))
- detectedRunningInCreator = true;
+ runningInCreatorDetected = true;
}
}
#endif
}
+
+ if (forceColor != ColorAuto)
+ ansiColorSupportDetected = (forceColor == ColorOn);
+ else if (!ansiColorSupportDetected)
+ ansiColorSupportDetected = runningInCreatorDetected;
+
+#if defined(Q_OS_UNIX) && defined(SIGWINCH)
+ UnixSignalHandler::instance()->install(UnixSignalHandler::RawSignalHandler, SIGWINCH, [](int) {
+ consoleWidthCached = 0;
+ });
+#elif defined(Q_OS_WIN)
+ class ConsoleThread : public QThread
+ {
+ public:
+ ConsoleThread(QObject *parent)
+ : QThread(parent)
+ { }
+ protected:
+ void run() override
+ {
+ HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode = 0;
+ if (!GetConsoleMode(h, &mode))
+ return;
+ if (!SetConsoleMode(h, mode | ENABLE_WINDOW_INPUT))
+ return;
+
+ INPUT_RECORD ir;
+ DWORD irRead = 0;
+ while (ReadConsoleInputW(h, &ir, 1, &irRead)) {
+ if ((irRead == 1) && (ir.EventType == WINDOW_BUFFER_SIZE_EVENT))
+ consoleWidthCached = 0;
+ }
+ }
+ };
+ (new ConsoleThread(qApp))->start();
+#endif // Q_OS_WIN
once = true;
}
- if (useAnsiColors) {
- if (forceColor == ColorAuto)
- *useAnsiColors = forStderr && (consoleSupportsAnsiColors || detectedRunningInCreator);
- else
- *useAnsiColors = forStderr && (forceColor == ColorOn);
- }
+ if (ansiColorSupport)
+ *ansiColorSupport = ansiColorSupportDetected;
if (runningInCreator)
- *runningInCreator = detectedRunningInCreator;
- if (windowWidth) {
- *windowWidth = calculateWindowWidth(consoleFd);
- if ((*windowWidth <= 0) && detectedRunningInCreator)
- *windowWidth = 120;
+ *runningInCreator = runningInCreatorDetected;
+ if (consoleWidth) {
+ if (!consoleWidthCached) {
+ consoleWidthCached = 1;
+ consoleWidthCalculated = -1;
+#if defined(Q_OS_UNIX)
+ if (::isatty(STDERR_FILENO)) {
+ struct ::winsize ws;
+ if ((::ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0) && (ws.ws_col > 0))
+ consoleWidthCalculated = ws.ws_col;
+ }
+#elif defined(Q_OS_WIN)
+ HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
+ if (h != INVALID_HANDLE_VALUE && h != NULL) {
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ if (GetConsoleScreenBufferInfo(h, &csbi))
+ consoleWidthCalculated = csbi.dwSize.X;
+ }
+#endif
+ }
+ if ((consoleWidthCalculated <= 0) && runningInCreatorDetected)
+ *consoleWidth = 120;
+ else
+ *consoleWidth = consoleWidthCalculated;
}
}
diff --git a/src/common-lib/utilities.h b/src/common-lib/utilities.h
index 310e3e41..b9c8cea4 100644
--- a/src/common-lib/utilities.h
+++ b/src/common-lib/utilities.h
@@ -181,7 +181,7 @@ QString findOnSDCard(const QString &file);
void setCrashActionConfiguration(const QVariantMap &config);
-void getOutputInformation(bool *useAnsiColors, bool *runningInCreator, int *windowWidth, int fileHandle = -1);
+void getOutputInformation(bool *ansiColorSupport, bool *runningInCreator, int *consoleWidth);
qint64 getParentPid(qint64 pid);