diff options
author | Robert Griebl <robert.griebl@pelagicore.com> | 2017-03-06 22:39:33 +0100 |
---|---|---|
committer | Dominik Holland <dominik.holland@pelagicore.com> | 2017-03-07 14:38:50 +0000 |
commit | a9404523588b22fb9f4baab6348832a0f4fce2ad (patch) | |
tree | 7f45a676e808522b30d7e845239d54f622df17b1 | |
parent | 83ffd22608c6a5329d2a982b6b1a58dc17e88762 (diff) | |
download | qtapplicationmanager-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.cpp | 33 | ||||
-rw-r--r-- | src/common-lib/startuptimer.cpp | 26 | ||||
-rw-r--r-- | src/common-lib/utilities.cpp | 121 | ||||
-rw-r--r-- | src/common-lib/utilities.h | 2 |
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); |