296 lines
7.2 KiB
C++
296 lines
7.2 KiB
C++
/* --- logConsoleGUI.cpp ---------------------------------------
|
|
System: Log system for gui applications
|
|
Status: Version 1.0 Release 2
|
|
Language: C++
|
|
|
|
(c) Copyright SD-Innovation 2016
|
|
|
|
Author: Sylvain Schneider
|
|
------------------------------------------------------------- */
|
|
|
|
#include "logConsoleGUI.h"
|
|
|
|
#include <ctime>
|
|
#include <sstream>
|
|
|
|
#ifdef _WIN32
|
|
# include <Windows.h>
|
|
#endif // defined WIN32
|
|
|
|
t_logConsoleGUI logConsole;
|
|
|
|
using namespace std;
|
|
using namespace sdiTools;
|
|
//--------------------------------------------------------------
|
|
logConsoleGUI::logConsoleGUI(const std::string &logFilepath)
|
|
{
|
|
// Constructor
|
|
if (!logFilepath.empty())
|
|
openLogFile(logFilepath);
|
|
}
|
|
//--------------------------------------------------------------
|
|
logConsoleGUI::~logConsoleGUI()
|
|
{
|
|
// Destructor
|
|
releaseConsole();
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::openLogFile(const std::string &logFilepath)
|
|
{
|
|
// Open log file
|
|
m_logFile.open(logFilepath.c_str(), std::ofstream::out | std::ofstream::app);
|
|
if (!m_logFile.is_open())
|
|
throw logic_error("Unable to open log file !");
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::closeLogFile()
|
|
{
|
|
// Close log file
|
|
if (m_logFile.is_open())
|
|
m_logFile.close();
|
|
}
|
|
//--------------------------------------------------------------
|
|
int64_t logConsoleGUI::getLogFileSize()
|
|
{
|
|
// Return opened log file size
|
|
if (!m_logFile.is_open())
|
|
return -1;
|
|
return m_logFile.tellp();
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::initConsole(bool attachOnly)
|
|
{
|
|
// Init application console and attach debug console under MSW
|
|
#ifdef _WIN32
|
|
|
|
if (hasAttachedConsole())
|
|
return;
|
|
|
|
bool hasParentConsole = true;
|
|
if (!AttachConsole(ATTACH_PARENT_PROCESS)) // Attach application to console
|
|
{
|
|
if (attachOnly)
|
|
return;
|
|
|
|
// No console was available
|
|
hasParentConsole = false;
|
|
if (!AllocConsole()) // Create console and attach application to it
|
|
{
|
|
// Error during creating console
|
|
throw logic_error("Unable to attach application to debug console");
|
|
}
|
|
}
|
|
|
|
int err;
|
|
err = freopen_s(&m_stdoutFile, "CONOUT$", "w", stdout);
|
|
if (err != 0)
|
|
{
|
|
// Error during reopen on stdout
|
|
throw logic_error("Unable to reopen stdout");
|
|
}
|
|
err = freopen_s(&m_stderrFile, "CONOUT$", "w", stderr);
|
|
if (err != 0)
|
|
{
|
|
// Error during reopen on stderr
|
|
throw logic_error("Unable to reopen stderr");
|
|
}
|
|
|
|
cout.clear();
|
|
cerr.clear();
|
|
|
|
if (hasParentConsole)
|
|
{
|
|
cout << endl;
|
|
}
|
|
// cout << "logConsoleGUI is ready !" << endl;
|
|
|
|
#endif // defined WIN32
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::releaseConsole()
|
|
{
|
|
// Release application console
|
|
#ifdef _WIN32
|
|
|
|
if (!hasAttachedConsole())
|
|
return;
|
|
|
|
cout << "logConsoleGUI is terminated !" << endl;
|
|
cout.clear();
|
|
cerr.clear();
|
|
|
|
FreeConsole();
|
|
|
|
fclose(m_stdoutFile);
|
|
fclose(m_stderrFile);
|
|
|
|
#endif // defined WIN32
|
|
}
|
|
//--------------------------------------------------------------
|
|
bool logConsoleGUI::hasAttachedConsole()
|
|
{
|
|
// Returns true if console was attached, false otherwise
|
|
#ifdef _WIN32
|
|
|
|
if (GetConsoleWindow())
|
|
return true;
|
|
|
|
return false;
|
|
|
|
#endif // defined WIN32
|
|
return false;
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::disable_quickEditMode()
|
|
{
|
|
#ifdef _WIN32
|
|
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
if (hInput == INVALID_HANDLE_VALUE || hInput == NULL)
|
|
{
|
|
DWORD errorCode = GetLastError();
|
|
throw runtime_error("Unable to get input console handle");
|
|
}
|
|
|
|
BOOL bRet;
|
|
DWORD consoleMode;
|
|
|
|
bRet = GetConsoleMode(hInput, &consoleMode);
|
|
if (bRet == 0)
|
|
{
|
|
DWORD errorCode = GetLastError();
|
|
throw runtime_error("Unable to get console mode");
|
|
}
|
|
|
|
consoleMode = ENABLE_EXTENDED_FLAGS | (consoleMode & ~ENABLE_QUICK_EDIT_MODE);
|
|
|
|
bRet = SetConsoleMode(hInput, consoleMode);
|
|
if (bRet == 0)
|
|
{
|
|
// DWORD errorCode = GetLastError();
|
|
throw runtime_error("Unable to set console mode");
|
|
}
|
|
|
|
// Disable cursor
|
|
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
if (hOutput == INVALID_HANDLE_VALUE || hOutput == NULL)
|
|
{
|
|
DWORD errorCode = GetLastError();
|
|
throw runtime_error("Unable to get output console handle");
|
|
}
|
|
|
|
CONSOLE_CURSOR_INFO cursorInfo;
|
|
bRet = GetConsoleCursorInfo(hOutput, &cursorInfo);
|
|
if (bRet == 0)
|
|
{
|
|
throw runtime_error("Unable to get console cursor info");
|
|
}
|
|
|
|
cursorInfo.bVisible = false; // set the cursor visibility
|
|
bRet = SetConsoleCursorInfo(hOutput, &cursorInfo);
|
|
if (bRet == 0)
|
|
{
|
|
throw runtime_error("Unable to set console cursor info");
|
|
}
|
|
|
|
#endif // defined WIN32
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::alwaysOnTop()
|
|
{
|
|
#ifdef _WIN32
|
|
HWND hWin = GetConsoleWindow();
|
|
if (!hWin)
|
|
throw runtime_error("Unable to get window handle");
|
|
|
|
BOOL bRet;
|
|
|
|
bRet = SetWindowPos(
|
|
hWin, // window handle
|
|
HWND_TOPMOST, // "handle to the window to precede
|
|
// the positioned window in the Z order
|
|
// OR one of the following:"
|
|
// HWND_BOTTOM or HWND_NOTOPMOST or HWND_TOP or HWND_TOPMOST
|
|
0,
|
|
80, // X, Y position of the window (in client coordinates)
|
|
0,
|
|
0, // cx, cy => width & height of the window in pixels
|
|
SWP_DRAWFRAME | /* SWP_NOMOVE | */ SWP_NOSIZE | SWP_SHOWWINDOW // The window sizing and positioning flags.
|
|
);
|
|
if (bRet == 0)
|
|
{
|
|
DWORD errorCode = GetLastError();
|
|
throw runtime_error("Unable to change window mode");
|
|
}
|
|
|
|
#endif // defined WIN32
|
|
}
|
|
//--------------------------------------------------------------
|
|
void logConsoleGUI::log(const std::string &msg, e_logLevel level)
|
|
{
|
|
// Log message into console and log file
|
|
string levelStr = "";
|
|
switch (level)
|
|
{
|
|
case level_DEBUG_COMMUNICATION:
|
|
#ifndef DEBUG
|
|
return;
|
|
#endif
|
|
levelStr = "[DEBUG_COMM] ";
|
|
break;
|
|
case level_DEBUG:
|
|
#ifndef DEBUG
|
|
return;
|
|
#endif
|
|
levelStr = "[DEBUG] ";
|
|
break;
|
|
case level_INFORMATIONS:
|
|
break;
|
|
case level_NOTICE:
|
|
levelStr = "[NOTICE] ";
|
|
break;
|
|
case level_WARNING:
|
|
levelStr = "[WARNING] ";
|
|
break;
|
|
case level_ERROR:
|
|
levelStr = "[ERROR] ";
|
|
break;
|
|
case level_CRITICAL:
|
|
levelStr = "[CRITICAL] ";
|
|
break;
|
|
case level_ALERT:
|
|
levelStr = "[ALERT] ";
|
|
break;
|
|
case level_EMERGENCY:
|
|
levelStr = "[EMERGENCY] ";
|
|
break;
|
|
}
|
|
|
|
string logMsg = header() + levelStr + msg;
|
|
|
|
cout << logMsg << endl;
|
|
if (m_logFile.is_open())
|
|
m_logFile << logMsg << endl;
|
|
}
|
|
//--------------------------------------------------------------
|
|
std::string logConsoleGUI::header()
|
|
{
|
|
// Define header to console log
|
|
char buff[20];
|
|
time_t now = time(nullptr);
|
|
struct tm tm;
|
|
|
|
#ifdef _WIN32
|
|
localtime_s(&tm, &now);
|
|
#elif __linux__
|
|
tm = *localtime(&now);
|
|
#endif
|
|
|
|
strftime(buff, 20, "%Y-%m-%d %H:%M:%S", &tm);
|
|
|
|
ostringstream oss;
|
|
oss << buff << " - ";
|
|
|
|
return oss.str();
|
|
}
|
|
//--------------------------------------------------------------
|