Files
ResInsight/ApplicationLibCode/ProjectDataModel/Jobs/RimSingleJob.cpp
T
JJ e0c1f23e6e Support for ensemble jobs (#14773)
Initial support for running well planning opm flow jobs for ensembles
2026-09-17 14:03:54 +02:00

236 lines
8.3 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2026 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 "RimSingleJob.h"
#include "RiaColorTools.h"
#include "RiaGuiApplication.h"
#include "RiaLogging.h"
#include "RiaQStringFormatter.h"
#include "RimJobMonitor.h"
#include "RimProcess.h"
#include "RimProcessQueue.h"
#include "RiuGuiTheme.h"
#include "cafPdmUiTreeAttributes.h"
#include "cafProgressInfo.h"
#include <QMessageBox>
CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimSingleJob, "SingleJob" ); // Do not use. Abstract class
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSingleJob::RimSingleJob()
: m_percentageDone( 0.0 )
, m_errorsDetected( 0 )
, m_warningsDetected( 0 )
, m_process( nullptr )
{
CAF_PDM_InitObject( "Generic Single Job" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSingleJob::~RimSingleJob()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimSingleJob::percentageDone() const
{
return m_percentageDone;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSingleJob::stop()
{
if ( !m_process.isNull() )
{
RimProcessQueue::stopProcess( m_process->ID() );
RiaLogging::info( std::format( "Job \"{}\" stopped by user.", name() ) );
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSingleJob::execute()
{
if ( isRunning() ) return false;
m_errorsDetected = 0;
m_warningsDetected = 0;
m_percentageDone = 0.0;
m_process = nullptr;
setState( JobState::Idle );
onProgress( m_percentageDone );
// job preparations
{
caf::ProgressInfo prepProgress( 1, name(), false );
auto prepRun = prepProgress.task( "Preparing for run, please wait..." );
if ( !onPrepare() )
{
setFinished( false );
return false;
}
}
// check if we should run
if ( !onRun() ) return false;
QStringList cmdLine = command();
if ( cmdLine.isEmpty() )
{
setFinished( false );
return false;
}
// cannot delete job while running
setDeletable( false );
setState( JobState::Queued );
m_process = new RimProcess( true, new RimJobMonitor( this ) );
// build process to run
QString cmd = cmdLine.takeFirst();
m_process->setCommand( cmd );
if ( !cmdLine.isEmpty() ) m_process->addParameters( cmdLine );
m_process->setWorkingDirectory( workingDirectory() );
for ( const auto& [name, value] : environment() )
{
m_process->addEnvironmentVariable( name, value );
}
RimProcessQueue::queueProcess( m_process );
onProgress( m_percentageDone );
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSingleJob::setFinished( bool runOk )
{
setState( runOk ? JobState::Completed : JobState::Failed );
m_percentageDone = 100.0;
onProgress( m_percentageDone );
setDeletable( true );
onCompleted( runOk );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSingleJob::setStarted()
{
setState( RimSingleJob::JobState::Running );
onProgress( m_percentageDone );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSingleJob::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
static auto warnColor = QColor( RiaColorTools::toQColor( cvf::Color3f( cvf::Color3f::DARK_YELLOW ) ) );
static auto contrastWarnColor =
QColor( RiaColorTools::toQColor( RiaColorTools::contrastColor( cvf::Color3f( cvf::Color3f::DARK_YELLOW ) ) ) );
static auto waitColor = QColor( RiaColorTools::toQColor( cvf::Color3f( cvf::Color3f::LIGHT_GRAY ) ) );
static auto contrastWaitColor =
QColor( RiaColorTools::toQColor( RiaColorTools::contrastColor( cvf::Color3f( cvf::Color3f::LIGHT_GRAY ) ) ) );
if ( auto* treeItemAttribute = dynamic_cast<caf::PdmUiTreeViewItemAttribute*>( attribute ) )
{
if ( state() == JobState::Failed )
{
auto txt = m_errorsDetected > 0 ? QString( "[%1]" ).arg( m_errorsDetected ) : "!!!";
auto tag =
caf::PdmUiTreeViewItemAttribute::createTag( QColor( Qt::red ), RiuGuiTheme::getColorByVariableName( "backgroundColor1" ), txt );
treeItemAttribute->tags.push_back( std::move( tag ) );
}
else if ( state() == JobState::Queued )
{
auto tag = caf::PdmUiTreeViewItemAttribute::createTag();
tag->text = "Waiting...";
tag->bgColor = waitColor;
tag->fgColor = contrastWaitColor;
treeItemAttribute->tags.push_back( std::move( tag ) );
}
else if ( ( state() == JobState::Running ) || ( state() == JobState::Completed ) )
{
auto tag = caf::PdmUiTreeViewItemAttribute::createTag();
if ( state() == JobState::Running )
{
tag->text = QString( "%1 %" ).arg( m_percentageDone, 0, 'f', 1 );
}
else
{
tag->text = "Done";
}
double factor = m_percentageDone / 100.0;
cvf::Color3f viewColor = cvf::Color3f( cvf::Color3f::GREEN );
viewColor.set( viewColor.r() * factor, viewColor.g() * factor, viewColor.b() * factor );
cvf::Color3f viewTextColor = RiaColorTools::contrastColor( viewColor );
tag->bgColor = QColor( RiaColorTools::toQColor( viewColor ) );
tag->fgColor = QColor( RiaColorTools::toQColor( viewTextColor ) );
treeItemAttribute->tags.push_back( std::move( tag ) );
}
if ( m_warningsDetected > 0 )
{
auto warnTxt = QString( "[%1]" ).arg( m_warningsDetected );
auto warnTag = caf::PdmUiTreeViewItemAttribute::createTag( warnColor, contrastWarnColor, warnTxt );
treeItemAttribute->tags.push_back( std::move( warnTag ) );
auto iconTag = caf::PdmUiTreeViewItemAttribute::createTag();
iconTag->icon = caf::IconProvider( ":/warning.png" );
treeItemAttribute->tags.push_back( std::move( iconTag ) );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QStringList RimSingleJob::jobLog() const
{
if ( m_process.isNull() ) return QStringList();
return m_process->stdOut();
}