diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.cpp index 16896fe8e1..fe1071ead2 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.cpp @@ -256,3 +256,14 @@ void RicSummaryCurveCalculator::defineEditorAttribute(const caf::PdmFieldHandle* RicSummaryCurveCalculator::assignPushButtonEditorText(attribute, "Delete Calculation"); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicSummaryCurveCalculator::onEditorWidgetsCreated() +{ + if (m_currentCalculation() != nullptr) + { + m_currentCalculation->attachToWidget(); + } +} diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.h b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.h index 8dc662cedc..3f493a557b 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryCurveCalculator.h @@ -49,6 +49,7 @@ private: virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override; virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; + virtual void onEditorWidgetsCreated(); private: static RimSummaryCalculationCollection* calculationCollection(); diff --git a/ApplicationCode/ProjectDataModel/RimSummaryCalculation.cpp b/ApplicationCode/ProjectDataModel/RimSummaryCalculation.cpp index a16c5f3b68..8d142865e8 100644 --- a/ApplicationCode/ProjectDataModel/RimSummaryCalculation.cpp +++ b/ApplicationCode/ProjectDataModel/RimSummaryCalculation.cpp @@ -30,11 +30,14 @@ #include "RimSummaryPlot.h" #include "RimSummaryPlotCollection.h" +#include "RiuExpressionContextMenuManager.h" + #include "cafPdmUiTextEditor.h" #include #include +#include "QMenu" CAF_PDM_SOURCE_INIT(RimSummaryCalculation, "RimSummaryCalculation"); @@ -46,16 +49,18 @@ RimSummaryCalculation::RimSummaryCalculation() { CAF_PDM_InitObject("RimSummaryCalculation", ":/octave.png", "Calculation", ""); - CAF_PDM_InitFieldNoDefault(&m_description, "Description", "Description", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_description, "Description", "Description", "", "", ""); m_description.uiCapability()->setUiReadOnly(true); - CAF_PDM_InitField(&m_expression, "Expression", QString("variableName := a"), "Expression", "", "", ""); + CAF_PDM_InitField(&m_expression, "Expression", QString("variableName := a"), "Expression", "", "", ""); m_expression.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); - CAF_PDM_InitFieldNoDefault(&m_variables, "Variables", "Variables", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_variables, "Variables", "Variables", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_calculatedValues, "CalculatedValues", "Calculated Values", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_timesteps, "TimeSteps", "Time Steps", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_timesteps, "TimeSteps", "Time Steps", "", "", ""); + + m_exprContextMenuMgr = std::unique_ptr(new RiuExpressionContextMenuManager()); } //-------------------------------------------------------------------------------------------------- @@ -201,7 +206,7 @@ bool RimSummaryCalculation::calculate() variableValues.resize(m_variables.size()); std::vector sourceTimeSteps; - + size_t itemCount = 0; for (size_t i = 0; i < m_variables.size(); i++) @@ -300,6 +305,30 @@ QString RimSummaryCalculation::findLeftHandSide(const QString& expresion) return ""; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryCalculation::attachToWidget() +{ + for (auto e : m_expression.uiCapability()->connectedEditors()) + { + caf::PdmUiTextEditor* textEditor = dynamic_cast(e); + if (!textEditor) continue; + + QWidget* containerWidget = textEditor->editorWidget(); + if (!containerWidget) continue; + + for (auto qObj : containerWidget->children()) + { + QTextEdit* textEdit = dynamic_cast(qObj); + if (textEdit) + { + m_exprContextMenuMgr->attachTextEdit(textEdit); + } + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimSummaryCalculation.h b/ApplicationCode/ProjectDataModel/RimSummaryCalculation.h index 673370f14c..5eb64b80cb 100644 --- a/ApplicationCode/ProjectDataModel/RimSummaryCalculation.h +++ b/ApplicationCode/ProjectDataModel/RimSummaryCalculation.h @@ -18,11 +18,15 @@ #pragma once +#include "RiuExpressionContextMenuManager.h" #include "cafPdmChildArrayField.h" #include "cafPdmObject.h" #include "cafPdmField.h" +#include +#include class RimSummaryCalculationVariable; +class QTextEdit; //================================================================================================== /// @@ -46,10 +50,11 @@ public: bool parseExpression(); bool calculate(); void updateDependentCurvesAndPlots(); - + virtual caf::PdmFieldHandle* userDescriptionField() override; static QString findLeftHandSide(const QString& expresion); + void attachToWidget(); private: RimSummaryCalculationVariable* findByName(const QString& name) const; @@ -66,4 +71,6 @@ private: caf::PdmField> m_calculatedValues; caf::PdmField> m_timesteps; + + std::unique_ptr m_exprContextMenuMgr; }; diff --git a/ApplicationCode/UserInterface/CMakeLists_files.cmake b/ApplicationCode/UserInterface/CMakeLists_files.cmake index 682510a4ae..c091414a6e 100644 --- a/ApplicationCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationCode/UserInterface/CMakeLists_files.cmake @@ -60,6 +60,7 @@ ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelection.h ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelectionDialog.h ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelectionEditor.h ${CEE_CURRENT_LIST_DIR}RiuSummaryVectorDescriptionMap.h +${CEE_CURRENT_LIST_DIR}RiuExpressionContextMenuManager.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -116,6 +117,7 @@ ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelection.cpp ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelectionDialog.cpp ${CEE_CURRENT_LIST_DIR}RiuSummaryCurveDefSelectionEditor.cpp ${CEE_CURRENT_LIST_DIR}RiuSummaryVectorDescriptionMap.cpp +${CEE_CURRENT_LIST_DIR}RiuExpressionContextMenuManager.cpp ) list(APPEND CODE_HEADER_FILES @@ -152,6 +154,7 @@ ${CEE_CURRENT_LIST_DIR}RiuWellPltPlot.h ${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h ${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h ${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h +${CEE_CURRENT_LIST_DIR}RiuExpressionContextMenuManager.h ) list(APPEND QT_UI_FILES diff --git a/ApplicationCode/UserInterface/RiuExpressionContextMenuManager.cpp b/ApplicationCode/UserInterface/RiuExpressionContextMenuManager.cpp new file mode 100644 index 0000000000..e6c03c5b0f --- /dev/null +++ b/ApplicationCode/UserInterface/RiuExpressionContextMenuManager.cpp @@ -0,0 +1,124 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RiuExpressionContextMenuManager.h" +#include +#include + +const std::map> RiuExpressionContextMenuManager::MENU_MAP = +{ + { + "Basic Operators", + { + "+", "-", "*", "/", "%", "^" + } + }, + { + "Assignment Operators", + { + ":=", "+=", "-=", "*=", "/=", "%=" + } + }, + { + "Functions", + { + "abs(x)", "avg(x, y, ...)", "ceil(x)", "clamp(r0, x, r1)", + "floor(x)", "frac(x)", "log(x)", "log10(x)", + "max(x, y, ...)", "min(x, y, ...)", "pow(x, y)", "root(x, y)", + "round(x)", "roundn(x, d)", "sgn(x)", "sqrt(x)", "sum(x, y, ...)", + "trunc(x)" + } + }, + { + "Trigonometry Functions", + { + "acos(x)", "acosh(x)", "asin(x)", "asinh(x)", "atan(x)", "atanh(x)", + "cos(x)", "cosh(x)", "cot(x)", "csc(x)", "sec(x)", "sin(x)", "sinc(x)", "sinh(x)", + "tan(x)", "tanh(x)", "rad2deg(x)", "deg2grad(x)", "deg2rad(x)", "grad2deg(x)" + } + } +}; + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuExpressionContextMenuManager::attachTextEdit(QTextEdit* textEdit) +{ + if (m_textEdit != textEdit) + { + textEdit->setContextMenuPolicy(Qt::CustomContextMenu); + QObject::connect(textEdit, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotMenuItems(QPoint))); + } + + m_textEdit = textEdit; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuExpressionContextMenuManager::slotMenuItems(QPoint point) +{ + QMenu menu; + + for (const std::pair>& subMenuPair : MENU_MAP) + { + QMenu* subMenu = menu.addMenu(subMenuPair.first); + + for (const QString& menuItemText : subMenuPair.second) + { + if (m_actionCache.count(menuItemText) == 0) + { + QAction* action = new QAction(menuItemText, this); + connect(action, SIGNAL(triggered()), SLOT(slotShowText())); + m_actionCache.insert(std::make_pair(menuItemText, std::unique_ptr(action))); + } + + subMenu->addAction(m_actionCache[menuItemText].get()); + } + } + + QPoint globalPoint = point; + if (m_textEdit) + { + globalPoint = m_textEdit->mapToGlobal(point); + + m_textPosition = m_textEdit->textCursor().position(); + } + + menu.exec(globalPoint); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuExpressionContextMenuManager::slotShowText() +{ + if (m_textEdit) + { + QAction* action = qobject_cast(sender()); + if (action) + { + QTextCursor cursor = m_textEdit->textCursor(); + cursor.setPosition(m_textPosition); + + m_textEdit->setTextCursor(cursor); + m_textEdit->insertPlainText(action->text()); + } + } +} diff --git a/ApplicationCode/UserInterface/RiuExpressionContextMenuManager.h b/ApplicationCode/UserInterface/RiuExpressionContextMenuManager.h new file mode 100644 index 0000000000..13721c5256 --- /dev/null +++ b/ApplicationCode/UserInterface/RiuExpressionContextMenuManager.h @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmChildArrayField.h" +#include "cafPdmObject.h" +#include "cafPdmField.h" +#include +#include +#include + +class RimSummaryCalculationVariable; +class QTextEdit; + +//================================================================================================== +/// +/// +//================================================================================================== +class RiuExpressionContextMenuManager : public QObject +{ + Q_OBJECT + + static const std::map> MENU_MAP; + +public: + RiuExpressionContextMenuManager() { } + + void attachTextEdit(QTextEdit* textEdit); + +public slots: + void slotMenuItems(QPoint point); + +private slots: + void slotShowText(); + +private: + QPointer m_textEdit; + int m_textPosition; + std::map> m_actionCache; +};