Commit Graph
2400 Commits
Author SHA1 Message Date
Magne Sjaastad ea719c41b3 #14112 Contour map: guard null legend config in defineUiOrdering
Selecting a contour map projection in the tree could crash when the
associated legend config was null. RimContourMapProjection::defineUiOrdering
called legendConfig()->uiOrdering() unguarded. Because PdmUiObjectHandle::uiOrdering
is non-virtual, the call entered with a null this and then crashed on the
virtual defineUiOrdering dispatch.

Guard the legendConfig() dereference, matching the existing null checks
elsewhere in the file. Apply the same guard to RimEclipseCellColors::defineUiOrdering.
2026-06-04 16:06:50 +02:00
Kristian Bendiksen dae3fc7cfd Data Filters: add "go to" button. 2026-06-01 16:41:21 +02:00
Kristian Bendiksen e37b20afb1 #14074 CellFilters: Hide empty case Data Filters node, add Filters submenu
The case-level Data Filters node (RimDataFilterCollection) was always shown under
RimEclipseCase, cluttering the tree when empty. Gate it in
RimEclipseCase::defineUiTreeOrdering on a new shouldBeVisibleInTree() check, and
refresh the owner case from onItemsChanged/onChildDeleted so the node appears and
disappears as the collection crosses the empty boundary.

Because a hidden node cannot be right-clicked to create the first filter, add a
RimEclipseCase::appendMenuItems override that exposes the filter-creation
commands as a Filters submenu on the case node. A shared
RicCellFilterFeatureTools::selectedDataFilterCollection() resolves a selected
RimEclipseCase to its data filter collection, so the cell, property and combined
filter create features target the case-level collection.
2026-06-01 16:41:21 +02:00
Kristian Bendiksen 78a6d0a8e5 #14074 CellFilters: Notify filter facade from all property-filter mutations
The view filter nodes were unified under a read-only RimFilterInViewCollection
facade, and the source collections are now tree-hidden. As a result, the
existing collection->updateConnectedEditors() calls no longer refresh the tree:
the filters are shown under the facade, which only refreshes when a source emits
filtersChanged/wrappersChanged.

Several property-filter mutations changed the child array without emitting that
signal (insertAt/push_back/erase do not auto-fire onChildAdded/onChildDeleted),
so newly created or removed filters did not appear under the Filters node:
property filter insert, new combined filter, add linked filter, undo of a
property-filter creation, and Show Contributing Wells.

Emit the change signal from these paths (via the existing onChildAdded hook, or
filtersChanged on removal) so the single facade handler refreshes the tree. The
cell-filter, paste, property-add and data-filter paths already emit the signal
and are unchanged.
2026-06-01 16:41:21 +02:00
Kristian Bendiksen a0e502f75e Move OSDU well logs and undo/redo view to experimental features
Gate the OSDU well log import menu item and the command undo/redo history view
behind the discoverable experimental features registry instead of
RiaApplication::enableDevelopmentFeatures(), so they can be toggled from
Preferences -> System without setting the RESINSIGHT_DEVEL environment variable.

Register the 'osdu-well-logs' and 'undo-redo-view' features in
RiaExperimentalFeatures and gate the code paths via
RiaPreferencesSystem::isFeatureEnabled().
2026-06-01 16:41:00 +02:00
Kristian Bendiksen 19c547cc2e Well Event: Add opt-in column-aligned schedule output
Add an align_columns option to schedule generation. When enabled, each
keyword is serialized with a '--'-prefixed column-header comment and data
rows right-aligned into fixed-width columns, instead of the compact default
form. The default output is unchanged.

A new RimKeywordFactory::deckKeywordToAlignedString introspects the OPM deck
model and renders each item in its own column (consecutive defaults are not
collapsed into 'N*'). The flag is threaded through RicScheduleDataGenerator
and exposed on the GenerateSchedule scriptable method as align_columns in the
Python generate_schedule_text wrapper.
2026-06-01 15:45:03 +02:00
Kristian Bendiksen 187addb1d0 #13890 Faults: Provide FAULTDIST menu via appendMenuItems() 2026-06-01 11:28:46 +02:00
Kristian Bendiksen 31c1271034 #13890 Faults: Move fault distance results collection to the view
Reparent RimFaultDistanceResultCollection so it is owned directly by
RimEclipseView instead of RimFaultInViewCollection, and show it as a
top-level node next to the Faults node in the project tree.

RimFaultDistanceResult::calculateValueOptions now reaches the fault list
through the view (the fault collection is a sibling rather than an
ancestor after the move). RicNewFaultDistanceResultFeature resolves the
view from the selection and takes both the distance collection and the
all-faults fallback from it.

The scriptable API moves with the collection: add_fault_distance_result
is now exposed on RimEclipseView (view.add_fault_distance_result(...))
via the new RimcEclipseView, replacing RimcFaultInViewCollection.
2026-06-01 11:28:46 +02:00
Kristian Bendiksen b78ef0d0a1 #13890 Python: Add scriptable API for selected-fault FAULTDIST
Expose the new RimFaultDistanceResult facility to Python by marking the
relevant PDM classes and fields scriptable. RimEclipseView's
m_faultCollection, RimFaultInViewCollection, RimFaultInView,
RimFaultDistanceResult, and RimFaultDistanceResultCollection are now
scriptable, so faults can be enumerated from Python via
view.fault_collection().faults().

A new Rimc method add_fault_distance_result on RimFaultInViewCollection
takes a name and a list of fault objects, creates the result
(auto-numbered FAULTDIST<n> when the name is empty), and returns the
new RimFaultDistanceResult. An empty fault list falls back to every
fault in the view, matching the static-native FAULTDIST behaviour.

Add a Python test exercising both a subset call and a parity check
that asserts the all-faults result matches the existing static-native
FAULTDIST cell-for-cell.
2026-06-01 11:28:46 +02:00
Kristian Bendiksen b51dc28854 #13890 Faults: Add FAULTDIST result for a user-selected subset of faults
The existing FAULTDIST result always considered every fault in the main
grid. Users with many faults need to compute distance fields against a
named subset, so this adds a Fault Distance Results collection under
each view's Faults node. Each entry holds a multiselect of faults and a
name (FAULTDIST1, FAULTDIST2, ...) and publishes the result into the
Generated cell-result category.

The per-cell BVH-based distance loop was extracted from
RigFaultDistanceResultCalculator into a reusable utility that accepts
the subset of faults to include; the original all-faults entry point
delegates to the same utility and keeps the static-native FAULTDIST
behavior unchanged.
2026-06-01 11:28:46 +02:00
Kristian Bendiksen 8f082fc969 #14083 Well Disks: Show disks on project load without toggling wells
On project reload the simulation well disks were not drawn until the user
toggled the Simulation Wells visibility. Two load-ordering issues caused this:

scaleWellDisks() ran before synchronizeWellsWithResults() had populated the
wells list, so it iterated an empty collection. It also bailed out early on the
transient m_showWellDisks aggregate (disableIO), which is only synced from the
restored per-well states when the property panel is built.

Move scaleWellDisks() after synchronizeWellsWithResults(), and sync the
visibility checkbox state at the start of scaleWellDisks() so the disks are
scaled and marked valid before the first display-model build.
2026-06-01 08:19:44 +02:00
Kristian Bendiksen bd9172f33f #14083 Well Disks: Keep disk radius stable when toggling well visibility
Normalize disk radius over all wells instead of only the currently
visible ones. Computing the min/max range over visible wells only made
one well's disk radius depend on whether unrelated wells were filtered
out, so toggling a range filter on one well changed another well's disk.

Fixes #14083.
2026-06-01 08:19:44 +02:00
Kristian Bendiksen 9515e6c277 #13273 Well Event: Support completion number on perforation events for COMPLUMP
Add a completion_number parameter to the add_perf_event Python API
(AddPerfEvent scriptable method) and a matching field on
RimWellEventPerf. When a timeline perforation event is materialised into
a RimPerforationInterval, a non-zero completion number is copied across,
so it flows through the existing completion-data path onto
RigCompletionData.

The schedule generator now emits COMPLUMP alongside COMPDAT: COMPDAT
generation is folded into generateCompletionsForWell, which computes the
completion data once and builds both keywords from it via the existing
RimKeywordFactory::complumpKeyword (added in #13273). COMPLUMP only
produces records for perforations that have a completion number and is
merged across wells like COMPDAT.
2026-05-29 15:43:30 +02:00
Magne Sjaastad a8306ebb81 #14077 Add umbrella Import Simulation Grid feature for GRID/EGRID, GRDECL, and ROFF 2026-05-29 14:00:49 +02:00
Magne Sjaastad 277d8a4da8 #14075 Histogram: Compute percentiles and mean in a single call 2026-05-29 12:34:51 +02:00
Magne Sjaastad 2f8ec77851 #14061 Reorder user interface for summary/grid ensemble import
* Agent docs: Recommend cmake --build over ninja when sharing build/ with Visual Studio
* Disable Create Well Target Mapping for grid ensembles with individual grids
* Move RimSummaryCaseMainCollection context menu items into appendMenuItems override
* Reorganize import menus: split per-window, group submenus, rename actions, add Import/Export icons
* Show icons on "New Statistics Case" and "New Grid Case Group" menu actions
* Rename grid/summary import submenus to "More" and use the import icon
2026-05-28 16:06:39 +02:00
Magne Sjaastad 24700198fb #14069 Indicate grid ensembles with individual grids via info tag and tooltip 2026-05-28 14:04:31 +02:00
Kristian Bendiksen 6ef024cee9 #14063 Well Event: Group records of same keyword across wells
The schedule generator previously concatenated full keyword blocks
(`KEYWORD ... /\n/\n`) — one per well — producing verbose output where
each WELSPECS / COMPDAT / WCONHIST / WELSEGS / COMPSEGS / etc. block
appeared once per contributing well. Eclipse keywords are designed to
hold multiple records under a single header; the per-well repetition is
syntactically valid but bloats the file and obscures intent.

Switch `RicScheduleDataGenerator` to accumulate
`std::map<QString, Opm::DeckKeyword>` instead of raw concatenated text.
Each per-well helper now returns an `Opm::DeckKeyword`, and a new
`mergeKeyword` primitive appends its records into the accumulator entry,
creating the entry from the helper's keyword on first encounter. At
emission time each accumulated keyword is serialised once.

To support this, `RifEventKeywordFormatter` is split: each `format*`
QString function now wraps a corresponding `build*` function that
returns `std::optional<Opm::DeckKeyword>`. `RimWellEventKeyword` and
`RimKeywordEvent` expose a parallel `generateDeckKeyword` accessor.
The text-scraping `extractKeywordName` helper becomes dead code and is
removed.
2026-05-28 08:21:17 +02:00
Kristian Bendiksen d2e7bed6b8 Well Event: Emit RPTRST/RPTSCHED as proper mnemonic lists
Schedule-level keywords whose OPM ParserRecord is a single ALL-sized item
(RPTRST, RPTSCHED, ...) are not positional — they take a free-form list
of mnemonic tokens like `BASIC=2 DEN ROCKC NORST=1`. Previously each
`keyword_data` entry became its own DeckItem, and OPM emitted them
either as truncated positional values or as a quoted, space-collapsed
single string.

Detect that schema shape in `RifEventKeywordFormatter::formatKeyword`
and pack the user's entries into one RawString DeckItem of mnemonic
tokens: `KEY` for FLAG items, `KEY=VALUE` otherwise.

To distinguish flag mnemonics (`DEN`) from `KEY=1`-style entries, add a
new `FLAG` value to `RimWellEventKeywordItem::ItemType` plumbed end to
end (Python -> GRPC -> Rimc -> storage -> formatter). The Python API
now maps `bool True` to FLAG and silently drops `bool False`.

For positional keywords (WCONHIST etc.) FLAG items have no value to
emit and are rendered as default markers ("1*").

A `rawStringItem` helper is added to `RifOpmDeckTools` so the
mnemonic-list path can produce DeckItems whose OPM output is not
quoted.
2026-05-28 08:21:17 +02:00
Kristian Bendiksen 8dad4bd410 #13913 Add "Active Wells Only" visibility toggle for simulation wells
Adds a collection-level checkbox in the simulation well "Visibility"
group that hides wells which are not open at the current time step.
Mirrors the existing "Wells Through Visible Cells Only" sibling toggle
in placement, default (off), and contour-map gating.

The frame-aware predicates isWellPipeVisible, isWellSpheresVisible,
isWellValvesVisible and isWellDiskVisible now short-circuit to false
when the toggle is on and RigSimWellData::isOpen(frameIndex) is false,
placed before the active-intersection bypass so the user's filter is
not overridden.

Fixes #13913
2026-05-28 07:44:18 +02:00
Kristian Bendiksen 09d4e42796 #13992 Hide production disks for wells filtered out by "Wells Through Visible Cells Only"
Production disks were drawn for wells that the visible-cells filter
hides, because RimSimWellInView::isWellDiskVisible() never consulted
the showWellsIntersectingVisibleCells toggle.

Add a frameIndex parameter and the same active-intersection / visible-
cells filter logic that isWellPipeVisible already uses, and update the
two call sites to pass the current frame.
2026-05-27 09:37:42 +02:00
Håkon Hægland be3621a66d Make RimMultiPlot column/row count scriptable via gRPC
* Make RimMultiPlot column/row count scriptable via gRPC
* Add pytest for scriptable multi-plot layout
2026-05-26 18:49:56 +02:00
Magne Sjaastad 071d6cc19e #14050 CMake: Remove dead variable definitions and references
* CMake: Remove dead CODE_HEADER_FILES variable
* CMake: Remove dead COMMAND_CODE_HEADER_FILES and COMMAND_MOC_SOURCE_FILES
* CMake: Remove dead MOC_SOURCE_FILES and FORM_FILES_CPP references
* CMake: Remove dead HEADER_FILES reference
* CMake: Delete unused CustomPCH.cmake superseded by target_precompile_headers
2026-05-26 13:10:20 +02:00
Kristian Bendiksen cc574e7a7b #14006 CorrelationPlot: Guard against empty time steps in fieldChangedByUi
Changing the time step filter combo box crashed when the plot had no
available time steps: filteredTimeStepIndices returned an empty vector
and .back() invoked undefined behaviour. Skip the m_timeStep assignment
when either allDateTimes or filteredTimeStepIndices is empty.

Fixes #14006.
2026-05-20 18:04:01 +02:00
Kristian Bendiksen 37c6892102 #14022 DataFilter: Restore category options for case-level property filters on project load
The case-level RimDataFilterCollection lacked an equivalent of
RimEclipsePropertyFilterCollection::loadAndInitializePropertyFilters, so a
saved FORMATION_NAMES selection had its value preserved on reload but no
category options list to render against. The selection only appeared after
the user toggled the filter, which routes through fieldChangedByUi and
rebuilds the category cache. Add loadAndInitializeFilters and invoke it
from RimEclipseView::onLoadDataAndUpdate, once openReservoirCase has loaded
the grid and active formation names.
2026-05-20 18:03:19 +02:00
Magne Sjaastad 91fed8e48c #14020 Use perforation interval cell filter to limit COMPDAT and MSW export
* Completions: Apply perforation cell filter to COMPDAT and MSW export
* PerforationInterval: Limit Cell Filter dropdown to case-level filters
* PerforationInterval: Prefix Cell Filter entries with case name when multiple cases
* Completions: Use std::format for cell filter suppression log messages
2026-05-20 16:04:40 +02:00
Kristian Bendiksen 20087c6dd9 #13997 3dView: Show active filter name(s) below Z-scale indicator
Adds a new HUD label in the upper-left of the 3D view that reads
"Filter : <name(s)>" whenever a cell, property, or per-view data
filter is active. The label is hidden when nothing is enabled.

Names are joined per the source collection's AND/OR combine mode, and
contributions from different collections are concatenated with ", ".
On Eclipse views the unified RimFilterInViewCollection is used as the
single anchor; GeoMech views aggregate cell and GeoMech property
filters directly.
2026-05-20 14:16:04 +02:00
Kristian Bendiksen 92107da9ed #14011 FlowRateCurve: Guard against null plot curve in updateCurveAppearance
When the user toggles "Show Curve" off, updateCurvePresentation runs
updateCurveVisibility, which detaches and deletes m_plotCurve, before
calling updateCurveAppearance. The override in RimWellFlowRateCurve
dereferenced m_plotCurve unconditionally and crashed. Match the null
guard already present in RimPlotCurve::updateCurveAppearance.

Fixes #14011.
2026-05-18 21:48:13 +02:00
Kristian Bendiksen 44b0df7906 CellFilters: Drop AND/OR count suffix from combined filter name 2026-05-15 08:37:46 +02:00
Kristian Bendiksen 6edc17892f CellFilters: Unify view filter nodes under RimFilterInViewCollection 2026-05-15 08:37:46 +02:00
Kristian Bendiksen b15c8d383c CellFilters: Fix lifetime and notification issues from review
Three fixes from PR review on the data-filters refactor.

RimDataFilterInViewCollection::syncWithSource: avoid double-free on
project load when m_sourceCollection has not yet resolved. The first
pass deletes orphan wrappers but leaves them in the local snapshot;
the null-source branch then deleted them again. Replace the second
deletion with deleteChildren() on the wrapper field.

RimDataFilterInViewCollection::setSourceCollection: disconnect from
the previous source's filtersChanged signal before reassigning, so
edits to a previously-bound case no longer trigger spurious geometry
regen on this view.

RimEclipsePropertyFilter::fieldChangedByUi: always emit
triggerFilterChanged() after updating bounds and related fields.
Otherwise, when the property filter lives inside a combined filter
under a per-view RimEclipsePropertyFilterCollection, the combined
parent's auto-derived display name was never recomputed.
2026-05-15 08:37:46 +02:00
Kristian Bendiksen c9456bba62 Python: Add cell filter reference to perforation intervals
Lets a script attach a cell filter to a RimPerforationInterval as a
typed reference so subsequent work can gate completion-export
connections by the filter's cell mask. Pure metadata in this commit:
no consumer of RimPerforationInterval is modified, the field exists
purely as an API surface.

Add a non-scriptable caf::PdmPtrField<RimCellFilter*> m_cellFilter to
RimPerforationInterval with public cellFilter()/setCellFilter()
accessors and a "Cell Filter" group in the property panel between the
existing geometry/flow group and the Date Settings group. The field is
deliberately non-scriptable: a scriptable PdmPtrField round-trips in
Python as an opaque "ClassName:0xADDR" string rather than a resolved
object, defeating the point. Two CAF object methods on
RimcPerforationInterval expose the relationship:

- AddFilter (perf.add_filter(filter)) sets the pointer; replaces any
  existing filter (single filter per perforation).
- cell_filter (perf.cell_filter()) resolves to the referenced
  RimCellFilter object on read, mirroring the valve.template() pattern.

Composition stays in RimCombinedFilter: a script that wants AND/OR
across multiple filters attaches a combined filter as the single
filter on the perforation.

The Python example in PythonExamples builds a case-level AND combined
filter (PERMX 100..20000 AND K=5..10), creates a modeled well path
with two perforation intervals, and shares the same filter between
them. test_perforation_filter.py covers single-set, replace-on-second-
add, and shared-pointer round-trips.
2026-05-15 08:37:46 +02:00
Kristian Bendiksen 3a1ff7a1e3 CellFilters: Auto-derive combined-filter name from children
Combined filters used to always show whatever literal string the user
passed in (or the default "Combined Filter"). For programmatic creation
without a name, that string never reflected the children, leaving the
case-level "Data Filters" tree row stale when child bounds changed.

Add an m_autoDeriveName flag (default true) to RimCombinedFilter. When
on, the display name is recomputed on every relevant change — addFilter,
removeFilter, onChildAdded, onChildFilterChanged, and combineMode
toggle — by joining children's name() with " AND " / " OR ". The flag
flips to false the first time the user renames the filter via the UI
property panel or via Python (combined.user_description = "..."),
preserving any explicitly typed name verbatim from then on.

Two child-creation paths needed an extra triggerFilterChanged() so the
combined parent recomputes after the child's final name is set:
addPropertyFilterToCombinedFilter (setDefaults updates name without a
signal) and RimcCombinedFilter_addRangeFilter (Rimc applies user
params after addNewFilter).

The Rimc factory passes setAutoDeriveName(false) only when a name is
supplied. The Python example demonstrates both modes side by side, and
test_combined_filter.py adds three cases: named filter preserves its
name, auto-derived filter tracks bound mutations, and Python rename
locks the auto-derived filter.
2026-05-15 08:37:46 +02:00
Kristian Bendiksen 74fde9edef CellFilters: Mirror source filter's name in the per-view wrapper
RimDataFilterInView previously copied the source filter's name once, in
setSourceFilter() and initAfterRead() via syncNameFromSource(). That
left the wrapper showing the default "Combined Filter" when the source
was renamed after the wrapper was created — typical for the Python
add_combined_filter(name=...) flow, where the wrapper is constructed
during addFilter() before the user-supplied name reaches the source.

Replace the wrapper's reliance on its inherited m_name field for
display with a caf::PdmProxyValueField<QString> that delegates the
read to m_sourceFilter()->name() and the write to setName(). Override
userDescriptionField() so the PDM tree label and property panel route
through the proxy — both directions of rename now propagate.

Matches the m_nameProxy pattern already established in RimCellFilter.
The inherited m_name is no longer the display source of truth but is
left in place so RimNamedObject's serialization stays unchanged.
2026-05-15 08:37:46 +02:00
Kristian Bendiksen eb70d32eb1 Python: Add scriptable Data Filters API for combined filters
Expose the case-level RimDataFilterCollection (introduced for
case-shared cell filters) to Python so scripts can build combined
filters with property-filter and IJK-range children without going
through a view.

Scriptable surface:
- RimEclipseCase.m_dataFilterCollection -> case.data_filter_collection()
- RimDataFilterCollection (object + Filters child array) -> filters()
- RimEclipsePropertyFilter (object + m_lowerBound + m_upperBound) ->
  pf.lower_bound, pf.upper_bound
- RimCellRangeFilter (object + start_index_{i,j,k}, cell_count_{i,j,k})

New CAF object methods under ProjectDataModelCommands/:
- RimcDataFilterCollection: add_combined_filter(name, combine_mode)
- RimcCombinedFilter: add_property_filter(result_variable, result_type)
  and add_range_filter(name, start_{i,j,k}, cell_count_{i,j,k}).

Bounds are not part of add_property_filter because the Python class
generator emits a bare nan literal as the default for double fields
initialised to quiet_NaN, which fails to import. Bounds are set via
the now-scriptable lower_bound/upper_bound fields after creation,
matching the update() pattern used elsewhere in the API.

RicEclipsePropertyFilterFeatureImpl::addPropertyFilterToCombinedFilter
now returns the new RimEclipsePropertyFilter* so the CAF method can
hand it back to Python. setDefaults is relaxed to be view-tolerant:
case-level filters have no Rim3dView ancestor and the eclipse case is
already wired by RimEclipsePropertyFilter::setCase via the owning
collection's onItemsChanged hook.

End-to-end coverage in tests/test_combined_filter.py: round-trip
create, mode toggle, property-filter add/mutate, range-filter
add/mutate. Example script in PythonExamples builds an AND combined
filter that gates PERMX between 100 and 20000 against a K=5..10
slice.
2026-05-15 08:37:46 +02:00
Kristian Bendiksen 4ed6d70b73 CellFilters: Add case-level Data Filters with per-view wrappers
Introduce RimDataFilterCollection on RimEclipseCase to hold filter
configuration that is shared across all views of the case. Each
RimEclipseView gets a RimDataFilterInViewCollection of
RimDataFilterInView wrappers that auto-sync with the case-level list
and expose an independent on/off toggle per view. The wrapper's
applyToCellVisibility delegates to the wrapped RimCellFilter via the
existing unified virtual, so property, range, and combined filters all
work uniformly.

RimDataFilterCollection is built on caf::PdmObjectCollection<RimCellFilter>
and emits a filtersChanged signal on add/remove/reorder/child changes.
The wrapper collection mirrors RimSurfaceInViewCollection's sync pattern:
new wrappers default to checked, removed sources drop their wrappers,
and the wrapper list follows the case order. Per-view wrappers feed into
RivReservoirViewPartMgr::computePropertyVisibility after the existing
view-level property-filter loop.

The RicNew*Feature commands now route into a selected RimDataFilterCollection,
and the existing combined-filter path is generalized to allow combined
filters living under either a per-view RimEclipsePropertyFilterCollection
or the new case-level collection. Several Asserted ancestor lookups in
RimEclipsePropertyFilter, RimCellFilter and RimEclipseResultDefinition
that assumed a Rim3dView ancestor were relaxed to the non-asserting
variant with graceful fallbacks, so case-level filters can be created
and edited without a host view.

Backwards compatible: empty Data Filter collection is a no-op,
existing per-view RimEclipsePropertyFilterCollection and
RimCellFilterCollection paths are unchanged. GeoMech parity deferred.
2026-05-15 08:37:46 +02:00
Magne Sjaastad 3375e37ffc #13987 PDM: Make loadData() virtual on RimPolygonContainer
Replace the dynamic_cast dispatch in RimPolygonCollection::loadData() with a
virtual loadData() on RimPolygonContainer. The base recurses through
subCollections; RimPolygonFile overrides to load file data. The folder
RimPolygonCollection no longer needs its own loadData().

Move RimPolygonFile::canAddSubCollection() and RimPolygonInView::sourceItem()
implementations from headers to .cpp.

Simplify std::unexpected calls in RimcNestedCollectionBase by removing
redundant explicit QString construction.
2026-05-13 14:53:00 +02:00
Magne Sjaastad dc20a016f7 #13987 PDM: Migrate Surface and Polygon collections to PdmNestedCollection
Port RimSurfaceCollection, RimPolygonCollection and the polygon-in-view
side onto the new caf::PdmNestedCollection framework, replacing the
per-class folder plumbing (m_subCollections field, topmost-folder flag,
add/remove/find sub-collection, factory, "new folder" command) with the
shared base.

- RimSurfaceCollection and RimPolygonCollection now derive from
  caf::PdmNestedCollection. Each constructor uses the generic folder
  icon and exposes a static createTopmost() that marks the top instance
  and applies the branded domain icon; RimOilField calls the factory.
- RimPolygonInViewCollection uses the new RimNestedMirrorCollectionInView
  helper, and a new RimPolygonContainer carries the source-side polygon
  link.
- RicNewSurfaceCollectionFeature is removed; the generic
  RicNewNestedCollectionFeature drives the "Add Folder" action against
  both collections.
- Update callers (RimAnnotationCollection, RimEnsembleSurface, polygon
  command features) and the scripting wrapper (RimcSurfaceCollection),
  plus the Python add-folder binding and polygon test.
2026-05-13 14:53:00 +02:00
Magne Sjaastad 92da6633bb #13987 PDM: Add caf::PdmNestedCollection framework
Introduce a shared base for tree-shaped folder containers that hold a
list of leaf items together with a list of subcontainers of the same
kind. Replaces the per-class plumbing (subcollections field, top-folder
flag, add/remove/find sub-collection, factory) that is duplicated across
RimSurfaceCollection, RimPolygonCollection and similar candidates.

- caf::PdmNestedCollectionBase: non-templated PdmObject base exposing
  collection-name, add-new-subcollection, leaf-check and topmost-folder
  marking for generic command features and script methods.
- caf::PdmNestedCollection<SelfT, ItemT>: CRTP template that owns the
  typed m_subCollections field and inherits the m_items array from
  PdmObjectCollection<ItemT>. Provides allItems(), find-sub-collection,
  and a typed factory hook.
- RimNestedMirrorCollectionInView: view-side analogue for in-view
  collections that mirror a nested source collection, with orphan-sweep
  + find-or-create + reorder sync.

Design rationale (templated vs non-templated, break-even on derived
class count) lives in docs/pdm-nested-collection-design.md.

No callers migrated in this commit.
2026-05-13 14:53:00 +02:00
Magne Sjaastad eee33cdc8d #13994 QuickAccess: Avoid re-entrant updateConnectedEditors when creating/removing groups 2026-05-12 12:58:25 +02:00
Kristian Bendiksen 2fa7520b3a Refactor: forward-declare element type in collection headers
Move the element-type include from each migrated collection header into
its .cpp, leaving only a forward declaration in the header. Follows the
pattern from 9e4d79159 for RimJobCollection, made possible by the
constructor-time PdmObject base check.
2026-05-11 13:42:13 +02:00
Magne Sjaastad 4feca2b920 RimJobCollection: Forward-declare RimGenericJob in header
Move the RimGenericJob include from the header to the .cpp now that
PdmObjectCollection<T> permits forward-declared template parameters.
2026-05-11 13:42:13 +02:00
Kristian Bendiksen 5e880ffc26 Refactor: migrate fourteen more collections to caf::PdmObjectCollection<T>
Migrated to the templated base, preserving each collection's existing XML
field keyword for project-file backward compatibility:

- RimEnsembleFractureStatisticsCollection
- RimEclipseInputPropertyCollection
- RimPlotDataFilterCollection
- RimGeoMechContourMapViewCollection
- RimIntersectionResultsDefinitionCollection
- RimCustomObjectiveFunctionCollection
- RimStimPlanModelTemplateCollection
- RimEnsembleWellLogsCollection
- RimEclipseContourMapViewCollection
- RimSeismicViewCollection
- RimGridInfoCollection
- RimEclipseStatisticsCaseCollection
- RimWellIASettingsCollection
- RimVfpDataCollection

External callers that accessed the old public/named array fields directly
(RimEclipseInputPropertyCollection::inputProperties,
RimEclipseStatisticsCaseCollection::cases) now use addItem/items() from
the base. RimCustomObjectiveFunction.h replaced its include of the
collection header with a forward declaration to break the new include
cycle introduced by the migration.
2026-05-11 13:42:13 +02:00
Kristian Bendiksen ddd413cb0b Refactor: migrate five collections to caf::PdmObjectCollection<T>
RimEnsembleFileSetCollection, RimJobCollection, RimQuickAccessCollection,
RimRefinementRegionCollection and RimFractureTemplateCollection now inherit
from the templated caf::PdmObjectCollection<T> base, reusing the shared
add/insert/delete/items plumbing introduced for RimValveTemplateCollection.

XML field keywords are preserved on every collection so existing project
files continue to load.
2026-05-11 13:42:13 +02:00
Kristian Bendiksen 8f4008db0f #12106 Polygon: Show coordinates with positive depth in property panel
Bind a PdmProxyValueField that inverts the Z sign to the Points group in
RimPolygon's property panel, mirroring the pattern already used by
RimExtrudedCurveIntersection. The raw m_pointsInDomainCoords field keeps
its XYZ semantics, scriptable keyword, and serialization unchanged.

Fixes #12106.
2026-05-11 13:35:51 +02:00
Kristian Bendiksen 9832fabde7 #5840 RiaEclipseUnitTools: Use barToPascal helper in RimWellIASettings
Replace inline bar-to-Pascal magic constants with RiaEclipseUnitTools::barToPascal
for initial stress and pore pressure parameters passed to the Well Impact Analysis
exporter. Behavior is unchanged; both sites previously multiplied by 100000.0.

Fixes #5840.
2026-05-11 12:44:49 +02:00
Magne Sjaastad b18f676884 #13967 Apply persisted Flip X/Y axis when loading an Eclipse result case
When a project file persisted FlipXAxis or FlipYAxis as true, the flag was
restored to the PdmField but never propagated to the grid nodes during
RimEclipseResultCase::importGridAndResultMetaData. Only the UI change handler
applied the flip, so on reload the grid stayed un-flipped while the checkbox
appeared active.

Mirror the call already present in RimEclipseInputCase and RimRoffCase by
invoking setFlipAxis before computeCachedData.
2026-05-08 10:28:31 +02:00
Magne Sjaastad 7f51676da2 Custom Mock Model: Add extent and offset fields to dialog
Expose XYZ extent and XY UTM offset as user-editable fields in the
Customize Mock Model dialog instead of hard-coding them in
RimEclipseResultCase. Defaults match the previous hard-coded values
(6000/12000/500 extent, 400000/6000000 offset).
2026-05-08 10:28:00 +02:00
Kristian Bendiksen 5ffcb69acc #13126 RiaLogging: Use std::string_view instead of QString for logging 2026-05-08 10:11:09 +02:00
Kristian Bendiksen 4957bf5a8b #13126 RiaLogging: Take std::string_view for logElapsedTime message
Switch the message parameter from const QString& to std::string_view so
callers with std::string in hand no longer need a QString::fromStdString
wrapper. The internal duration formatting still uses QString::arg, fed
from a single QString::fromUtf8 conversion.

Callers passing QString locals are updated with .toStdString() at the
call site.
2026-05-08 10:11:09 +02:00