2022-01-18 09:03:41 +00:00
# ifdef BUILD_WFSERVER
2022-01-17 17:23:55 +00:00
# include <QtCore/QCoreApplication>
2022-04-13 12:55:59 +01:00
# include "keyboard.h"
2022-01-17 17:23:55 +00:00
# else
2018-06-19 12:58:52 -07:00
# include <QApplication>
2024-05-23 09:35:30 -07:00
# include <QTranslator>
2022-01-17 17:23:55 +00:00
# endif
2022-01-26 09:49:52 +00:00
# ifdef Q_OS_WIN
# include <windows.h>
# include <csignal>
2024-08-13 15:39:13 +01:00
# else
# include <fcntl.h>
# include <signal.h>
2025-01-05 17:08:31 +00:00
# include <unistd.h>
2022-01-26 09:49:52 +00:00
# endif
2021-02-02 01:05:59 -08:00
# include <iostream>
2026-04-11 19:08:25 -07:00
# ifdef BUILD_WFSERVER
# include "servermain.h"
2026-04-11 20:12:45 -07:00
# include "serverwizard.h"
2026-04-11 19:08:25 -07:00
# else
2021-02-07 20:07:26 +00:00
# include "wfmain.h"
2026-04-11 19:08:25 -07:00
# endif
2026-03-17 22:52:19 -07:00
# include <QJsonDocument>
# include <QJsonObject>
# include <QSaveFile>
2018-06-19 12:58:52 -07:00
2022-09-14 17:07:23 -07:00
# include "logcategories.h"
2018-06-19 12:58:52 -07:00
2024-08-13 15:39:13 +01:00
bool debugMode = false ;
2022-09-14 17:07:23 -07:00
# ifdef BUILD_WFSERVER
2021-02-07 20:07:26 +00:00
// Smart pointer to log file
QScopedPointer < QFile > m_logFile ;
QMutex logMutex ;
2024-08-13 15:39:13 +01:00
servermain * w = Q_NULLPTR ;
2022-01-26 09:49:52 +00:00
2025-01-01 13:40:58 +00:00
# ifdef Q_OS_WIN
2024-08-13 15:39:13 +01:00
bool __stdcall cleanup ( DWORD sig )
# else
static void cleanup ( int sig )
# endif
{
switch ( sig ) {
2025-01-01 13:40:58 +00:00
# ifndef Q_OS_WIN
2024-08-13 15:39:13 +01:00
case SIGHUP :
qInfo ( ) < < " hangup signal " ;
break ;
2025-01-01 13:40:58 +00:00
# endif
2024-08-13 15:39:13 +01:00
case SIGTERM :
2025-01-01 13:40:58 +00:00
qInfo ( ) < < " terminate signal caught " ;
2022-01-26 09:49:52 +00:00
if ( w ! = Q_NULLPTR ) w - > deleteLater ( ) ;
2022-05-24 10:08:18 +01:00
QCoreApplication : : quit ( ) ;
2024-08-13 15:39:13 +01:00
break ;
default :
break ;
2022-01-26 09:49:52 +00:00
}
2024-08-13 15:39:13 +01:00
# ifdef Q_OS_WIN
return true ;
# else
return ;
# endif
}
# ifndef Q_OS_WIN
void initDaemon ( )
{
int i ;
if ( getppid ( ) = = 1 )
return ; /* already a daemon */
i = fork ( ) ;
if ( i < 0 )
exit ( 1 ) ; /* fork error */
if ( i > 0 )
exit ( 0 ) ; /* parent exits */
setsid ( ) ; /* obtain a new process group */
for ( i = getdtablesize ( ) ; i > = 0 ; - - i )
close ( i ) ; /* close all descriptors */
i = open ( " /dev/null " , O_RDWR ) ; dup ( i ) ; dup ( i ) ;
signal ( SIGCHLD , SIG_IGN ) ;
signal ( SIGTSTP , SIG_IGN ) ;
signal ( SIGTTOU , SIG_IGN ) ;
signal ( SIGTTIN , SIG_IGN ) ;
}
# else
void initDaemon ( ) {
2025-01-01 13:40:58 +00:00
std : : cout < < " Background mode does not currently work in Windows \n " ;
exit ( 1 ) ;
2024-08-13 15:39:13 +01:00
}
# endif
2022-01-26 09:49:52 +00:00
2021-02-07 20:07:26 +00:00
void messageHandler ( QtMsgType type , const QMessageLogContext & context , const QString & msg ) ;
2022-09-14 17:07:23 -07:00
# endif
2018-06-19 12:58:52 -07:00
int main ( int argc , char * argv [ ] )
{
2022-04-13 12:55:59 +01:00
2022-01-18 09:03:41 +00:00
# ifdef BUILD_WFSERVER
2022-01-17 17:23:55 +00:00
QCoreApplication a ( argc , argv ) ;
2022-04-13 12:55:59 +01:00
a . setOrganizationName ( " wfview " ) ;
a . setOrganizationDomain ( " wfview.org " ) ;
a . setApplicationName ( " wfserver " ) ;
2026-04-11 20:12:45 -07:00
keyboard * kb = Q_NULLPTR ;
2022-01-17 17:23:55 +00:00
# else
2025-01-02 16:16:11 +00:00
# if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
2022-04-20 13:35:23 +01:00
QCoreApplication : : setAttribute ( Qt : : AA_EnableHighDpiScaling ) ;
2025-01-02 16:16:11 +00:00
# endif
2018-06-19 12:58:52 -07:00
QApplication a ( argc , argv ) ;
2021-05-01 00:58:30 -07:00
a . setOrganizationName ( " wfview " ) ;
a . setOrganizationDomain ( " wfview.org " ) ;
2020-01-04 17:12:35 -08:00
a . setApplicationName ( " wfview " ) ;
2026-03-17 21:52:58 -07:00
a . setDesktopFileName ( " wfview " ) ;
2022-04-13 12:55:59 +01:00
# endif
2018-11-24 00:10:05 -08:00
2021-05-15 18:53:16 +01:00
# ifdef QT_DEBUG
2022-09-14 17:07:23 -07:00
//debugMode = true;
2021-05-15 18:53:16 +01:00
# endif
2021-02-02 01:05:59 -08:00
2022-09-23 16:46:33 +01:00
QDateTime date = QDateTime : : currentDateTime ( ) ;
QString formattedTime = date . toString ( " dd.MM.yyyy hh:mm:ss " ) ;
QString logFilename = ( QString ( " %1/%2-%3.log " ) . arg ( QStandardPaths : : standardLocations ( QStandardPaths : : TempLocation ) [ 0 ] ) . arg ( a . applicationName ( ) ) . arg ( date . toString ( " yyyyMMddhhmmss " ) ) ) ;
2022-09-23 17:02:06 +01:00
2021-05-20 19:24:40 +01:00
QString settingsFile = NULL ;
2021-02-02 01:05:59 -08:00
QString currentArg ;
2026-04-11 20:12:45 -07:00
# ifdef BUILD_WFSERVER
bool runSetup = false ;
# endif
2021-02-02 01:05:59 -08:00
2021-02-11 19:47:29 +00:00
2026-04-11 20:12:45 -07:00
const QString helpText = QString ( " \n Usage: -l --logfile filename.log, -s --settings filename.ini, -c --clearconfig CONFIRM, -b --background (not Windows), -d --debug, -v --version "
# ifdef BUILD_WFSERVER
" , --setup (interactive config wizard) "
# endif
" \n " ) ; // TODO...
2022-01-18 09:03:41 +00:00
# ifdef BUILD_WFSERVER
2022-01-17 17:23:55 +00:00
const QString version = QString ( " wfserver version: %1 (Git:%2 on %3 at %4 by %5@%6) \n Operating System: %7 (%8) \n Build Qt Version %9. Current Qt Version: %10 \n " )
. arg ( QString ( WFVIEW_VERSION ) )
. arg ( GITSHORT ) . arg ( __DATE__ ) . arg ( __TIME__ ) . arg ( UNAME ) . arg ( HOST )
. arg ( QSysInfo : : prettyProductName ( ) ) . arg ( QSysInfo : : buildCpuArchitecture ( ) )
. arg ( QT_VERSION_STR ) . arg ( qVersion ( ) ) ;
# else
2021-11-19 18:48:15 +00:00
const QString version = QString ( " wfview version: %1 (Git:%2 on %3 at %4 by %5@%6) \n Operating System: %7 (%8) \n Build Qt Version %9. Current Qt Version: %10 \n " )
2022-01-17 17:23:55 +00:00
. arg ( QString ( WFVIEW_VERSION ) )
. arg ( GITSHORT ) . arg ( __DATE__ ) . arg ( __TIME__ ) . arg ( UNAME ) . arg ( HOST )
. arg ( QSysInfo : : prettyProductName ( ) ) . arg ( QSysInfo : : buildCpuArchitecture ( ) )
. arg ( QT_VERSION_STR ) . arg ( qVersion ( ) ) ;
2024-05-23 09:35:30 -07:00
2024-08-13 08:38:55 +01:00
// Translator doesn't really make sense for wfserver right now.
2024-05-23 09:35:30 -07:00
QTranslator myappTranslator ;
qDebug ( ) < < " Current translation language: " < < myappTranslator . language ( ) ;
bool trResult = myappTranslator . load ( QLocale ( ) , QLatin1String ( " wfview " ) , QLatin1String ( " _ " ) , QLatin1String ( " :/translations " ) ) ;
if ( trResult ) {
qDebug ( ) < < " Recognized requested language and loaded the translations (or at least found the /translations resource folder). Installing translator. " ;
a . installTranslator ( & myappTranslator ) ;
} else {
qDebug ( ) < < " Could not load translation. " ;
}
qDebug ( ) < < " Changed to translation language: " < < myappTranslator . language ( ) ;
2024-08-13 08:38:55 +01:00
# endif
2024-05-23 09:35:30 -07:00
2021-02-02 01:05:59 -08:00
for ( int c = 1 ; c < argc ; c + + )
{
2021-05-15 18:53:16 +01:00
//qInfo() << "Argc: " << c << " argument: " << argv[c];
2021-02-02 01:05:59 -08:00
currentArg = QString ( argv [ c ] ) ;
2022-09-23 17:42:36 +01:00
if ( ( currentArg = = " -d " ) | | ( currentArg = = " --debug " ) )
2021-05-15 18:53:16 +01:00
{
debugMode = true ;
2024-08-13 15:39:13 +01:00
}
2021-02-08 10:20:06 +01:00
else if ( ( currentArg = = " -l " ) | | ( currentArg = = " --logfile " ) )
2021-02-07 20:07:26 +00:00
{
if ( argc > c )
{
logFilename = argv [ c + 1 ] ;
c + = 1 ;
2021-02-02 01:05:59 -08:00
}
2021-05-20 19:24:40 +01:00
}
else if ( ( currentArg = = " -s " ) | | ( currentArg = = " --settings " ) )
{
if ( argc > c )
{
settingsFile = argv [ c + 1 ] ;
c + = 1 ;
}
}
2025-01-10 07:49:47 +00:00
else if ( ( currentArg = = " -c " ) | | ( currentArg = = " --clearconfig " ) )
{
if ( argc > c )
{
QString confirm = argv [ c + 1 ] ;
c + = 1 ;
if ( confirm = = " CONFIRM " ) {
QSettings * settings ;
// Clear config
if ( settingsFile . isEmpty ( ) ) {
settings = new QSettings ( ) ;
}
else
{
QString file = settingsFile ;
QFile info ( settingsFile ) ;
QString path = " " ;
if ( ! QFileInfo ( info ) . isAbsolute ( ) )
{
path = QStandardPaths : : writableLocation ( QStandardPaths : : AppDataLocation ) ;
if ( path . isEmpty ( ) )
{
path = QDir : : homePath ( ) ;
}
path = path + " / " ;
file = info . fileName ( ) ;
}
settings = new QSettings ( path + file , QSettings : : Format : : IniFormat ) ;
}
settings - > clear ( ) ;
2026-03-17 22:52:19 -07:00
// Derive the companion .noise profile path the same way wfmain does.
QString noisePath ;
const QString sf = settings - > fileName ( ) ;
const QFileInfo fi ( sf ) ;
if ( ! sf . isEmpty ( ) & & fi . suffix ( ) . length ( ) > = 2 & & fi . suffix ( ) . length ( ) < = 5
& & fi . absoluteDir ( ) . exists ( ) ) {
noisePath = fi . absoluteDir ( ) . absoluteFilePath ( fi . baseName ( ) + " .noise " ) ;
} else {
QString appData = QStandardPaths : : writableLocation (
QStandardPaths : : AppDataLocation ) ;
if ( appData . isEmpty ( ) )
appData = QDir : : homePath ( ) ;
noisePath = appData + " /wfview.noise " ;
}
// Overwrite the noise file with an empty profile store so
// stale profiles from the old configuration are discarded.
QJsonObject emptyRoot ;
emptyRoot [ " version " ] = 1 ;
emptyRoot [ " profiles " ] = QJsonObject ( ) ;
QSaveFile nf ( noisePath ) ;
if ( nf . open ( QIODevice : : WriteOnly ) ) {
nf . write ( QJsonDocument ( emptyRoot ) . toJson ( QJsonDocument : : Compact ) ) ;
if ( nf . commit ( ) )
std : : cout < < QString ( " ANR noise profiles cleared: %1 \n " )
. arg ( noisePath ) . toStdString ( ) ;
else
std : : cout < < QString ( " Warning: could not write noise profile file: %1 \n " )
. arg ( noisePath ) . toStdString ( ) ;
} else {
std : : cout < < QString ( " Warning: could not open noise profile file for writing: %1 \n " )
. arg ( noisePath ) . toStdString ( ) ;
}
2025-01-10 07:49:47 +00:00
delete settings ;
std : : cout < < QString ( " All wfview settings cleared. \n " ) . toStdString ( ) ;
exit ( 0 ) ;
}
}
std : : cout < < QString ( " Error: Clear config not confirmed (please add the word CONFIRM), aborting \n " ) . toStdString ( ) ;
std : : cout < < helpText . toStdString ( ) ;
exit ( - 1 ) ;
}
2024-08-13 15:39:13 +01:00
# ifdef BUILD_WFSERVER
else if ( ( currentArg = = " -b " ) | | ( currentArg = = " --background " ) )
{
initDaemon ( ) ;
}
2026-04-11 20:12:45 -07:00
else if ( currentArg = = " --setup " )
{
runSetup = true ;
}
2024-08-13 15:39:13 +01:00
# endif
2021-11-19 17:52:18 +00:00
else if ( ( currentArg = = " -? " ) | | ( currentArg = = " --help " ) )
2021-02-02 01:05:59 -08:00
{
std : : cout < < helpText . toStdString ( ) ;
2021-11-19 17:52:18 +00:00
return 0 ;
}
else if ( ( currentArg = = " -v " ) | | ( currentArg = = " --version " ) )
{
2021-11-19 18:48:15 +00:00
std : : cout < < version . toStdString ( ) ;
2021-02-02 01:05:59 -08:00
return 0 ;
2024-08-13 15:39:13 +01:00
}
else {
2021-02-02 01:05:59 -08:00
std : : cout < < " Unrecognized option: " < < currentArg . toStdString ( ) ;
std : : cout < < helpText . toStdString ( ) ;
2022-01-17 17:23:55 +00:00
return - 1 ;
2021-02-02 01:05:59 -08:00
}
}
2022-09-14 17:07:23 -07:00
# ifdef BUILD_WFSERVER
2021-02-07 20:07:26 +00:00
// Set the logging file before doing anything else.
2023-01-12 19:47:55 +00:00
m_logFile . reset ( new QFile ( logFilename ) ) ;
2021-02-07 20:07:26 +00:00
// Open the file logging
2023-01-12 19:47:55 +00:00
m_logFile . data ( ) - > open ( QFile : : WriteOnly | QFile : : Truncate | QFile : : Text ) ;
2021-02-07 20:07:26 +00:00
// Set handler
qInstallMessageHandler ( messageHandler ) ;
2021-11-19 18:48:15 +00:00
qInfo ( logSystem ( ) ) < < version ;
2022-09-23 17:42:36 +01:00
2022-09-15 09:49:03 -07:00
# endif
2024-08-13 15:39:13 +01:00
2022-01-18 09:03:41 +00:00
# ifdef BUILD_WFSERVER
2026-04-11 20:12:45 -07:00
if ( runSetup ) {
// Run the wizard before installing signal handlers so Ctrl-C aborts.
int rc = serverwizard : : run ( settingsFile ) ;
return rc ;
}
2024-08-13 15:39:13 +01:00
# ifdef Q_OS_WIN
2022-01-26 09:49:52 +00:00
SetConsoleCtrlHandler ( ( PHANDLER_ROUTINE ) cleanup , TRUE ) ;
2024-08-13 15:39:13 +01:00
# else
2022-01-26 09:49:52 +00:00
signal ( SIGINT , cleanup ) ;
2022-05-24 10:13:44 +01:00
signal ( SIGTERM , cleanup ) ;
signal ( SIGKILL , cleanup ) ;
2024-08-13 15:39:13 +01:00
# endif
2026-04-11 20:12:45 -07:00
kb = new keyboard ( ) ;
kb - > start ( ) ;
2023-01-01 20:28:59 +00:00
w = new servermain ( settingsFile ) ;
2022-01-17 17:23:55 +00:00
# else
2018-11-24 22:21:36 -08:00
a . setWheelScrollLines ( 1 ) ; // one line per wheel click
2022-09-23 17:42:36 +01:00
wfmain w ( settingsFile , logFilename , debugMode ) ;
2018-06-19 12:58:52 -07:00
w . show ( ) ;
2024-08-13 15:39:13 +01:00
2022-01-17 17:23:55 +00:00
# endif
2018-06-19 12:58:52 -07:00
return a . exec ( ) ;
2021-02-07 20:07:26 +00:00
2018-06-19 12:58:52 -07:00
}
2021-02-07 20:07:26 +00:00
2022-09-14 17:07:23 -07:00
# ifdef BUILD_WFSERVER
2021-02-07 20:07:26 +00:00
void messageHandler ( QtMsgType type , const QMessageLogContext & context , const QString & msg )
{
// Open stream file writes
2021-05-15 18:53:16 +01:00
if ( type = = QtDebugMsg & & ! debugMode )
{
return ;
}
2021-02-07 20:07:26 +00:00
QMutexLocker locker ( & logMutex ) ;
QTextStream out ( m_logFile . data ( ) ) ;
2022-09-14 17:07:23 -07:00
QString text ;
2021-02-07 20:07:26 +00:00
// Write the date of recording
out < < QDateTime : : currentDateTime ( ) . toString ( " yyyy-MM-dd hh:mm:ss.zzz " ) ;
// By type determine to what level belongs message
switch ( type )
{
2021-05-15 18:53:16 +01:00
case QtDebugMsg :
out < < " DBG " ;
break ;
case QtInfoMsg :
out < < " INF " ;
break ;
case QtWarningMsg :
out < < " WRN " ;
break ;
case QtCriticalMsg :
out < < " CRT " ;
break ;
case QtFatalMsg :
out < < " FTL " ;
break ;
2021-02-07 20:07:26 +00:00
}
// Write to the output category of the message and the message itself
out < < context . category < < " : " < < msg < < " \n " ;
2022-04-11 11:54:06 +01:00
std : : cout < < QDateTime : : currentDateTime ( ) . toString ( " yyyy-MM-dd hh:mm:ss.zzz " ) . toLocal8Bit ( ) . toStdString ( ) < < msg . toLocal8Bit ( ) . toStdString ( ) < < " \n " ;
2021-02-07 20:07:26 +00:00
out . flush ( ) ; // Clear the buffered data
2021-02-08 10:20:06 +01:00
}
2022-09-14 17:07:23 -07:00
# endif