///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017- Statoil 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 // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RicUserDefinedCalculatorUi.h" #include "RimUserDefinedCalculation.h" #include "RimUserDefinedCalculationCollection.h" #include "cafAssert.h" #include "cafPdmUiListEditor.h" #include "cafPdmUiObjectEditorHandle.h" #include "cafPdmUiPushButtonEditor.h" CAF_PDM_ABSTRACT_SOURCE_INIT( RicUserDefinedCalculatorUi, "RicUserDefinedCalculator" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RicUserDefinedCalculatorUi::RicUserDefinedCalculatorUi() { CAF_PDM_InitObject( "RicUserDefinedCalculator" ); CAF_PDM_InitFieldNoDefault( &m_currentCalculation, "CurrentCalculation", "" ); m_currentCalculation.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); m_currentCalculation.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() ); CAF_PDM_InitFieldNoDefault( &m_newCalculation, "NewCalculation", "New Calculation" ); RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_newCalculation ); CAF_PDM_InitFieldNoDefault( &m_deleteCalculation, "DeleteCalculation", "Delete Calculation" ); RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_deleteCalculation ); CAF_PDM_InitFieldNoDefault( &m_importCalculations, "ImportCalculations", "Import Calculations" ); RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_importCalculations ); CAF_PDM_InitFieldNoDefault( &m_exportCalculations, "ExportCalculations", "Export Calculations" ); RicUserDefinedCalculatorUi::assignPushButtonEditor( &m_exportCalculations ); m_calcContextMenuMgr = std::make_unique(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimUserDefinedCalculation* RicUserDefinedCalculatorUi::currentCalculation() const { return m_currentCalculation(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::setCurrentCalculation( RimUserDefinedCalculation* calculation ) { m_currentCalculation = calculation; connectSignals( m_currentCalculation() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RicUserDefinedCalculatorUi::parseExpression() const { if ( m_currentCalculation() ) { QString previousCurveName = m_currentCalculation->description(); if ( !m_currentCalculation()->parseExpression() ) { return false; } QString currentCurveName = m_currentCalculation->description(); if ( previousCurveName != currentCurveName ) { notifyCalculatedNameChanged( m_currentCalculation()->id(), currentCurveName ); } // Always rebuild the case meta data after parsing the expression. A change in name or change in result type will require rebuild of // case metadata. The rebuild is considered lightweight and should not be a performance issue. calculationCollection()->rebuildCaseMetaData(); } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { if ( changedField == &m_newCalculation ) { m_newCalculation = false; m_currentCalculation = calculationCollection()->addCalculation(); connectSignals( m_currentCalculation ); updateConnectedEditors(); } else if ( changedField == &m_deleteCalculation ) { m_deleteCalculation = false; if ( m_currentCalculation() ) { calculationCollection()->deleteCalculation( m_currentCalculation() ); m_currentCalculation = nullptr; updateConnectedEditors(); caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors(); } } else if ( changedField == &m_currentCalculation && m_currentCalculation() ) { connectSignals( m_currentCalculation() ); } else if ( changedField == &m_importCalculations ) { importCalculations(); m_importCalculations = false; } else if ( changedField == &m_exportCalculations ) { exportCalculations(); m_exportCalculations = false; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { if ( !m_currentCalculation() && !calculationCollection()->calculations().empty() ) { setCurrentCalculation( calculationCollection()->calculations()[0] ); } { caf::PdmUiGroup* group = uiOrdering.addNewGroupWithKeyword( "Calculations", calculationsGroupName() ); group->add( &m_currentCalculation ); group->add( &m_newCalculation ); group->appendToRow( &m_deleteCalculation ); } { caf::PdmUiGroup* group = uiOrdering.addNewGroupWithKeyword( "Calculation Settings", calulationGroupName() ); if ( m_currentCalculation() ) { m_currentCalculation->uiOrdering( uiConfigName, *group ); } } caf::PdmUiGroup* group = uiOrdering.findGroup( calculationsGroupName() ); if ( group ) { group->add( &m_importCalculations ); group->appendToRow( &m_exportCalculations ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QList RicUserDefinedCalculatorUi::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) { QList options; if ( fieldNeedingOptions == &m_currentCalculation ) { for ( auto c : calculationCollection()->calculations() ) { options.push_back( caf::PdmOptionItemInfo( c->description(), c ) ); } } return options; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::assignPushButtonEditor( caf::PdmFieldHandle* fieldHandle ) { CAF_ASSERT( fieldHandle ); CAF_ASSERT( fieldHandle->uiCapability() ); caf::PdmUiPushButtonEditor::configureEditorLabelHidden( fieldHandle ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::assignPushButtonEditorText( caf::PdmUiEditorAttribute* attribute, const QString& text ) { auto* attrib = dynamic_cast( attribute ); if ( attrib ) { attrib->m_buttonText = text; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RicUserDefinedCalculatorUi::calculate() const { if ( m_currentCalculation() ) { if ( !parseExpression() ) return false; if ( !m_currentCalculation()->preCalculate() ) { return false; } if ( !m_currentCalculation()->calculate() ) { return false; } m_currentCalculation()->updateDependentObjects(); caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors(); } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) { if ( &m_newCalculation == field ) { RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "New Calculation" ); } else if ( &m_deleteCalculation == field ) { RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "Delete Calculation" ); } else if ( &m_importCalculations == field ) { RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "Import Calculations" ); } else if ( &m_exportCalculations == field ) { RicUserDefinedCalculatorUi::assignPushButtonEditorText( attribute, "Export Calculations" ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::onEditorWidgetsCreated() { if ( m_currentCalculation() != nullptr ) { m_currentCalculation->attachToWidget(); } for ( const auto& e : m_currentCalculation.uiCapability()->connectedEditors() ) { auto* listEditor = dynamic_cast( e ); if ( !listEditor ) continue; QWidget* widget = listEditor->editorWidget(); if ( !widget ) continue; m_calcContextMenuMgr->attachWidget( widget, this ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::onVariableUpdated( const SignalEmitter* emitter ) { updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicUserDefinedCalculatorUi::connectSignals( RimUserDefinedCalculation* calculation ) { if ( calculation ) { calculation->variableUpdated.connect( this, &RicUserDefinedCalculatorUi::onVariableUpdated ); } }