ResInsight/ApplicationLibCode/Application/RiaConsoleApplication.cpp

417 lines
15 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaConsoleApplication.h"
#include "Cloud/RiaConnectorTools.h"
#include "RiaArgumentParser.h"
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RiaPreferencesGrid.h"
#include "RiaProjectModifier.h"
#include "RiaSocketServer.h"
#include "RiaVersionInfo.h"
#include "RicImportGeneralDataFeature.h"
#include "cvfProgramOptions.h"
#include "cvfqtUtils.h"
#include <QFileInfo>
#ifdef WIN32
#include <windows.h>
#endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaConsoleApplication* RiaConsoleApplication::instance()
{
RiaConsoleApplication* currentConsoleApp = dynamic_cast<RiaConsoleApplication*>( RiaApplication::instance() );
CAF_ASSERT( currentConsoleApp && "Should never be called from a method that isn't within the Console context" );
return currentConsoleApp;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaConsoleApplication::RiaConsoleApplication( int& argc, char** argv )
: QCoreApplication( argc, argv )
, RiaApplication()
{
installEventFilter( this );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaConsoleApplication::~RiaConsoleApplication()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaConsoleApplication::initialize()
{
#ifdef _WIN32
#pragma warning( push ) // Saves the current warning state.
#pragma warning( disable : 4996 ) // Temporarily disables warning 4996.
bool isReOpenStdToConsoleNeeded = false;
if ( AttachConsole( ATTACH_PARENT_PROCESS ) )
{
int fileType = GetFileType( GetStdHandle( STD_OUTPUT_HANDLE ) );
// FILE_TYPE_CHAR indicates a windows console buffer.
// FILE_TYPE_PIPE indicates redirection imposed by the starting shell (eg migw shell)
// If we are dealing with a pipe, we do not want to do the reopen, and destroy the connection.
if ( fileType == FILE_TYPE_CHAR )
{
isReOpenStdToConsoleNeeded = true;
}
}
else if ( AllocConsole() )
{
isReOpenStdToConsoleNeeded = true;
}
if ( isReOpenStdToConsoleNeeded )
{
freopen( "conout$", "w", stdout );
freopen( "conout$", "w", stderr );
freopen( "conin$", "r", stdin );
}
#pragma warning( pop )
#endif
RiaApplication::initialize();
auto logger = std::make_unique<RiaStdOutLogger>();
logger->setLevel( int( RiaLogging::logLevelBasedOnPreferences() ) );
RiaLogging::appendLoggerInstance( std::move( logger ) );
m_socketServer = new RiaSocketServer( this );
RiaConnectorTools::readCloudConfigFiles( m_preferences.get() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaApplication::ApplicationStatus RiaConsoleApplication::handleArguments( gsl::not_null<cvf::ProgramOptions*> progOpt )
{
// Handling of the actual command line options
// --------------------------------------------------------
if ( cvf::Option o = progOpt->option( "ignoreArgs" ) )
{
return ApplicationStatus::KEEP_GOING;
}
if ( progOpt->option( "help" ) || progOpt->option( "?" ) )
{
showFormattedTextInMessageBoxOrConsole( "\nThe current command line options in ResInsight are:\n" + commandLineParameterHelp() );
return RiaApplication::ApplicationStatus::EXIT_COMPLETED;
}
if ( progOpt->option( "version" ) )
{
QString text = QString( STRPRODUCTVER ) + "\n";
text += "SHA " + QString( RESINSIGHT_GIT_HASH ) + "\n";
showFormattedTextInMessageBoxOrConsole( text );
return RiaApplication::ApplicationStatus::EXIT_COMPLETED;
}
// Code generation
// -----------------
if ( cvf::Option o = progOpt->option( "generate" ) )
{
CVF_ASSERT( o.valueCount() == 1 );
QString outputFile = cvfqt::Utils::toQString( o.value( 0 ) );
QString errMsg;
if ( !RiaApplication::generateCode( outputFile, &errMsg ) )
{
RiaLogging::error( QString( "Error: %1" ).arg( errMsg ) );
return RiaApplication::ApplicationStatus::EXIT_WITH_ERROR;
}
return RiaApplication::ApplicationStatus::EXIT_COMPLETED;
}
if ( cvf::Option o = progOpt->option( "startdir" ) )
{
CVF_ASSERT( o.valueCount() == 1 );
setStartDir( cvfqt::Utils::toQString( o.value( 0 ) ) );
}
if ( cvf::Option o = progOpt->option( "egridReader" ) )
{
CVF_ASSERT( o.valueCount() == 1 );
std::string readerName = o.value( 0 ).toLower().toStdString();
m_preferences->gridPreferences()->setGridModelReaderOverride( readerName );
}
QString projectFileName;
if ( progOpt->hasOption( "last" ) )
{
projectFileName = preferences()->lastUsedProjectFileName;
}
if ( cvf::Option o = progOpt->option( "project" ) )
{
CVF_ASSERT( o.valueCount() == 1 );
projectFileName = cvfqt::Utils::toQString( o.value( 0 ) );
}
if ( !projectFileName.isEmpty() )
{
cvf::ref<RiaProjectModifier> projectModifier;
RiaApplication::ProjectLoadAction projectLoadAction = RiaApplication::ProjectLoadAction::PLA_NONE;
if ( cvf::Option o = progOpt->option( "replaceCase" ) )
{
if ( projectModifier.isNull() ) projectModifier = new RiaProjectModifier;
if ( o.valueCount() == 1 )
{
// One argument is available, use replace case for first occurrence in the project
QString gridFileName = cvfqt::Utils::toQString( o.safeValue( 0 ) );
projectModifier->setReplaceCaseFirstOccurrence( gridFileName );
}
else
{
size_t optionIdx = 0;
while ( optionIdx < o.valueCount() )
{
const int caseId = o.safeValue( optionIdx++ ).toInt( -1 );
QString gridFileName = cvfqt::Utils::toQString( o.safeValue( optionIdx++ ) );
if ( caseId != -1 && !gridFileName.isEmpty() )
{
projectModifier->setReplaceCase( caseId, gridFileName );
}
}
}
}
if ( cvf::Option o = progOpt->option( "replaceSourceCases" ) )
{
if ( projectModifier.isNull() ) projectModifier = new RiaProjectModifier;
if ( o.valueCount() == 1 )
{
// One argument is available, use replace case for first occurrence in the project
std::vector<QString> gridFileNames = readFileListFromTextFile( cvfqt::Utils::toQString( o.safeValue( 0 ) ) );
projectModifier->setReplaceSourceCasesFirstOccurrence( gridFileNames );
}
else
{
size_t optionIdx = 0;
while ( optionIdx < o.valueCount() )
{
const int groupId = o.safeValue( optionIdx++ ).toInt( -1 );
std::vector<QString> gridFileNames = readFileListFromTextFile( cvfqt::Utils::toQString( o.safeValue( optionIdx++ ) ) );
if ( groupId != -1 && !gridFileNames.empty() )
{
projectModifier->setReplaceSourceCasesById( groupId, gridFileNames );
}
}
}
projectLoadAction = RiaApplication::ProjectLoadAction::PLA_CALCULATE_STATISTICS;
}
if ( cvf::Option o = progOpt->option( "replacePropertiesFolder" ) )
{
if ( projectModifier.isNull() ) projectModifier = new RiaProjectModifier;
if ( o.valueCount() == 1 )
{
QString propertiesFolder = cvfqt::Utils::toQString( o.safeValue( 0 ) );
projectModifier->setReplacePropertiesFolderFirstOccurrence( propertiesFolder );
}
else
{
size_t optionIdx = 0;
while ( optionIdx < o.valueCount() )
{
const int caseId = o.safeValue( optionIdx++ ).toInt( -1 );
QString propertiesFolder = cvfqt::Utils::toQString( o.safeValue( optionIdx++ ) );
if ( caseId != -1 && !propertiesFolder.isEmpty() )
{
projectModifier->setReplacePropertiesFolder( caseId, propertiesFolder );
}
}
}
}
loadProject( projectFileName, projectLoadAction, projectModifier.p() );
}
if ( cvf::Option o = progOpt->option( "case" ) )
{
QStringList fileNames = RicImportGeneralDataFeature::fileNamesFromCaseNames( cvfqt::Utils::toQStringList( o.values() ) );
bool createView = true;
bool createPlot = true;
RicImportGeneralDataFeature::openEclipseFilesFromFileNames( fileNames, createPlot, createView );
}
if ( cvf::Option o = progOpt->option( "commandFile" ) )
{
QString commandFile = cvfqt::Utils::toQString( o.safeValue( 0 ) );
if ( !progOpt->hasOption( "startdir" ) )
{
QFileInfo commandFileInfo( commandFile );
QString commandDir = commandFileInfo.absolutePath();
setStartDir( commandDir );
}
cvf::Option projectOption = progOpt->option( "commandFileProject" );
cvf::Option caseOption = progOpt->option( "commandFileReplaceCases" );
if ( projectOption && caseOption )
{
projectFileName = cvfqt::Utils::toQString( projectOption.value( 0 ) );
std::vector<int> caseIds;
std::vector<QString> caseListFiles;
if ( caseOption.valueCount() == 1 )
{
caseListFiles.push_back( cvfqt::Utils::toQString( caseOption.safeValue( 0 ) ) );
}
else
{
size_t optionIdx = 0;
while ( optionIdx < caseOption.valueCount() )
{
const int caseId = caseOption.safeValue( optionIdx++ ).toInt( -1 );
QString caseListFile = cvfqt::Utils::toQString( caseOption.safeValue( optionIdx++ ) );
if ( caseId != -1 && !caseListFile.isEmpty() )
{
caseIds.push_back( caseId );
caseListFiles.push_back( caseListFile );
}
}
}
if ( caseIds.empty() && !caseListFiles.empty() )
{
QString caseListFile = caseListFiles[0];
std::vector<QString> caseFiles = readFileListFromTextFile( caseListFile );
for ( const QString& caseFile : caseFiles )
{
RiaProjectModifier projectModifier;
projectModifier.setReplaceCaseFirstOccurrence( caseFile );
loadProject( projectFileName, RiaApplication::ProjectLoadAction::PLA_NONE, &projectModifier );
executeCommandFile( commandFile );
}
}
else
{
CVF_ASSERT( caseIds.size() == caseListFiles.size() );
std::vector<std::vector<QString>> allCaseFiles;
size_t maxFiles = 0;
for ( size_t i = 0; i < caseIds.size(); ++i )
{
std::vector<QString> caseFiles = readFileListFromTextFile( caseListFiles[i] );
allCaseFiles.push_back( caseFiles );
maxFiles = std::max( caseFiles.size(), maxFiles );
}
for ( size_t i = 0; i < caseIds.size(); ++i )
{
RiaProjectModifier projectModifier;
for ( size_t j = 0; j < maxFiles; ++j )
{
if ( allCaseFiles[i].size() > j )
{
projectModifier.setReplaceCase( caseIds[i], allCaseFiles[i][j] );
}
}
loadProject( projectFileName, RiaApplication::ProjectLoadAction::PLA_NONE, &projectModifier );
executeCommandFile( commandFile );
}
}
}
else
{
executeCommandFile( commandFile );
}
return ApplicationStatus::EXIT_COMPLETED;
}
return ApplicationStatus::KEEP_GOING;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaConsoleApplication::showFormattedTextInMessageBoxOrConsole( const QString& errMsg )
{
std::cout << errMsg.toStdString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaConsoleApplication::invokeProcessEvents( QEventLoop::ProcessEventsFlags flags /*= QEventLoop::AllEvents*/ )
{
processEvents( flags );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaConsoleApplication::onProjectOpeningError( const QString& errMsg )
{
RiaLogging::error( errMsg );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaConsoleApplication::onProjectOpened()
{
loadAndUpdatePlotData();
processEvents();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaConsoleApplication::onProjectClosed()
{
processEvents();
}