computeFaultDistances faked a nearest-point query with cvf::BoundingBoxTree,
which only supports box overlap: it grew a cell-sized box until it overlapped a
fault face. For cells far from any fault this did many full tree traversals and
then brute-forced the distance to a large, over-collected candidate set, and the
answer was only approximate. This was slow on grids with ~10 million cells.
The metric is the distance from each cell center to the nearest fault face
center, which is exactly a nearest-point search. Replace the bounding-box tree
and the grow-the-box loop with a nanoflann KD-tree built over the fault face
centers and a single nearest-neighbor query per active cell. A zero-copy adaptor
reads the existing std::vector<cvf::Vec3d> directly. The OpenMP loop is retained
since nanoflann queries are read-only. The result is O(F log F) build plus
O(N log F) queries, the full grid-node array copy is gone, and distances are now
exact rather than approximate.
Add nanoflann as a vcpkg dependency, wired in like Clipper2 as an imported
target.
Refs: https://github.com/OPM/ResInsight/issues/14128
The export property dialogs that rely solely on sizeHint() could open collapsed when shown on a screen whose DPI differs from the screen they were built on. Recompute the layout on first show, after the dialog is associated with its destination screen, by calling adjustSize() in showEvent when no stored size is restored. Also give RiuPropertyViewTabWidget a minimum size floor so the inner scroll area's artificially small minimum width cannot collapse the dialog.
Replace the binary QWidget::saveGeometry()/restoreGeometry() encoding used by PdmUiPropertyViewDialog and RiuPropertyViewTabWidget with plain integer width and height values in QSettings, restored with resize(). The stored values are human-readable and not tied to Qt internal geometry-stream version. Only the size is persisted; the window position is left to the window manager to avoid restoring dialogs off-screen or on a disconnected monitor.
The template name resolution built a regular expression per key and used
QString::replace(QRegularExpression, value) to insert the value. When a value
inserted by one key contained an invalid UTF-16 sequence (e.g. a lone
surrogate from a data-derived case or well name), a subsequent key's global
match ran the regex engine over the malformed subject, causing an
out-of-bounds read and a segmentation fault inside PCRE2.
Replace the regex based substitution with a literal indexOf/replace loop that
preserves the existing word-boundary behavior, so values are never fed through
the regex engine. Empty keys are skipped.
ecl_file_iget_named_kw() performs an unchecked vector access and crashes with SIGSEGV when the requested keyword occurrence does not exist in the active file view. Bounds-check the occurrence against ecl_file_get_num_named_kw() in both keywordData() overloads before calling it, and check the previously ignored return value of ecl_file_select_block() in results() so a stale active view is not queried.
A truncated or corrupt restart file could provide a Fortran record-length header larger than the destination buffer, causing fortio_fread_record to fread past the heap allocation and crash. Bound each record read to the remaining buffer capacity and treat an oversized record as a read failure, which propagates up as a normal failed read instead of a segfault.
RimCase::timeStepDates() returns std::vector<QDateTime> by value, so
calling cbegin() and cend() in separate invocations produced iterators
into two different temporary vectors. Passing these mismatched iterators
to std::find is undefined behavior and walked off freed memory, crashing
in setValidTimeStepRangeForCase().
Snapshot timeStepDates() into a single local vector and use its
iterators. The same pattern was fixed in RimWellConnectivityTable.
Reloading an Eclipse grid file destroys and recreates RigEclipseCaseData and its RigCaseCellResultsData. The contour map projection caches raw pointers to this case data in updateGridInformation() and only refreshes them when the projection is rebuilt. Previously the projection was reset on reload only when a GENERATED result was selected, so for any other result type the next scheduled redraw dereferenced the freed RigCaseCellResultsData in generateResults, crashing in hasResultEntry. Reset the grid mapping for all contour map views on reload so fresh case data pointers are captured.
The combined filter node had no Delete entry in its right-click menu. The generic RicDeleteItemFeature only enables when isDeletable() is true, which defaults to false; every other cell filter opts in via setDeletable(true) in its constructor, but RimCombinedFilter omitted it. Add the call so the Delete item is offered, and assert it in the unit test.
RimEclipseView::onLoadDataAndUpdate() can be called again after a failed grid
load has cleared the view's eclipse case (RicNewViewFeature calls
loadDataAndUpdate once more after the view is added). On that second call the
open guard is skipped because eclipseCase() is already null, and the method then
dereferences eclipseCase() directly via dataFilterCollection(), crashing with a
null this pointer.
Return early when eclipseCase() is null after the open block, since there is
nothing to load without a case.
The Completion Type result was registered only as a dynamic result, which
requires simulation time steps. Loading only grid geometry (e.g. a ROFF grid)
therefore made the result unavailable, since there are no time steps to compute
it for.
Register and compute a STATIC_NATIVE variant of Completion Type in addition to
the existing DYNAMIC_NATIVE one, computed as a single time-step-independent
frame. The shared per-frame computation is factored out of
computeCompletionTypeForTimeStep so both variants reuse it. The virtual
perforation transmissibilities already handle the no-restart case by clamping to
a single frame, so the static result can be computed at calc time step 0.
The legend/category predicates and the completion-type result clearing are
broadened to recognise the static variant so it renders with the same discrete
named-category legend as the dynamic one.
RigCombMultResultAccessor::cellFaceScalar called oppositeFace() with the
face passed from the picked selection. A plain cell pick leaves the face
as NO_FACE, which has no opposite and tripped CVF_ASSERT(false) in
oppositeFace, crashing the application.
Guard against a non-directional face and return 1.0, consistent with the
no-change-in-MULT-factor convention already used in nativeMultScalar.
A file-based well path whose source file is missing has a null wellPathGeometry(). Add null checks at the remaining call sites that dereferenced it without one, so operations on such a well path no longer crash:
- RimWellPathGroup: skip geometry merging for a child with no geometry (grouping runs on import and project load).
- RimWellPathFracture::computeFractureDirectionNormal: return undefined when geometry is missing.
- RivWellPathPartMgr: extend the existing well path null checks to also require geometry in the attribute, well measurement, and valve append paths.
- RimCompletionCellIntersectionCalc, RicExportLgrFeature, RicCreateMultipleWellPathLaterals, RigLasFileExporter, RiuWellPathComponentPlotItem: guard the geometry before use.
Sites that were already guarded or only reachable through guarded paths were left unchanged.
When a project references an RMS well path file that no longer exists, the well path geometry is null. The MSW completion export validated the eclipse case, well path, and MSW parameters but not the geometry, so generateCellSegments asserted and crashed when triggering Export Completion Data for Visible Well Paths.
Guard the single MSW export dispatcher extractSingleWellMswData with a well path geometry null check that returns an error, protecting all export callers. Harden generateCellSegments to return empty instead of asserting on null geometry.
Also log a warning on the interactive well path import path when a file cannot be read, matching the existing project-load behavior.
Fixes#14121.
Install a Qt message handler at startup that filters out the cosmetic Qt6
warning "QColorSpace attempted constructed from invalid primaries" seen on
some Linux platforms (e.g. RHEL8). The warning originates in Qt6 when it
validates an empty, all-zero QColorSpacePrimaries and has no functional
impact. All other messages are forwarded to the previous handler unchanged.
The tree selection editor can grow to a large height, which is useful when it is the last field editor in the property dialog. When other field editors are located below, the heightHint is now used as the maximum height instead. The form layout tracks whether an editor occupies the bottom-most row of the form and passes this to the editor. In the Analysis Plot, the time step selection is constrained to its height hint because other input fields are located below it.
The Event Timeline stores event timestamps with full time-of-day precision, but the exported SCHEDULE deck only emitted DAY/MONTH/YEAR in the DATES keyword, dropping any sub-day precision the user had set.
Emit the optional TIME field (HH:MM:SS[.SSS]) in datesKeyword() whenever the timestamp is non-midnight, formatting with millisecond precision when present. Date-only events keep their previous DAY/MONTH/YEAR-only output. The first-date comment in the schedule generator mirrors the same time so it stays consistent with the keyword.
A grid created via the create_corner_point_grid API populated the internal
active cell info but never created an ACTNUM result property, so the grid did
not expose ACTNUM the way a grid loaded from an Eclipse file does. Since the
corner point case has no reader interface, the data cannot be loaded lazily and
is now materialized as a STATIC_NATIVE result sized per active cell, mirroring
native Eclipse ACTNUM.
Select the summary plot as the current item before any menu commands are
created, so every command in the context menu operates on that plot. This is
the root fix for plot-level commands (New Analysis Plot, correlation plots,
etc.) that derive their enablement from the selected plot: previously the
selection could be left on an ensemble realization's summary case, disabling
them.
Because the plot is now selected, the Show Plot Data / Edit Plot / Split / Delete
commands resolve the plot from the selection, so passing it as user data is no
longer needed. The RicShowPlotDataCtxFeature and RicEditSummaryPlotCtxFeature
subclasses existed only to force isCommandEnabled to true for the context menu;
they are now obsolete and removed, and the menu uses the base RicShowPlotData
and RicEditSummaryPlot features directly.
Also highlight the curve under the cursor before showing the menu, giving the
same visual feedback as a left-click. Separate highlighting from selection:
extract the visual-only part of selectClosestPlotItem into
applyHighlightForClosestItem, shared by selectClosestPlotItem (left-click:
highlight + select) and the new highlightClosestPlotItem (highlight only). The
context menu uses the highlight-only path, so it does not change the selection.
Add highlightClosestPlotItemAtPosition that takes widget coordinates and
converts them to canvas coordinates internally, so the caller does not depend
on qwt headers.
Persist the geometry of PdmUiPropertyViewDialog and RiuPropertyViewTabWidget to the application settings on close and restore it on the next show. Restoring is done in showEvent rather than the constructor so it is applied reliably for a modal dialog. The settings key includes the bound object class keyword so distinct dialogs that share a window title do not collide.
This behaviour is gated behind a new "Remember Dialog Size" experimental feature, disabled by default. PdmUiPropertyViewDialog cannot access RiaPreferencesSystem, so the application pushes the current setting via the static enableGeometryPersistence(), following the existing pattern used for class-name display. RiuPropertyViewTabWidget queries the feature directly.
Override sizeHint() and minimumSizeHint() in PdmUiPropertyViewDialog so the dialog cannot open collapsed. The inner scroll area reports an artificially small minimum size hint that some window managers honor literally, shrinking the dialog to an unusable size (issue #14104). The floor is capped by the content's preferred size so intentionally small dialogs are not enlarged.
ecl_grid_alloc can return null for a corrupt or truncated grid file.
When a valid INIT file was present, loadAllGrids dereferenced the null
grid pointer via ecl_grid_dual_grid/ecl_grid_get_global_size before
returning, causing a segfault.
Guard the init-file active cell logic on a non-null grid so the function
returns null cleanly, letting the existing null check in open() report
the error gracefully.
stepListIndexToTimeStepAndDataFrameIndex only guarded against negative indices, relying on a CVF_ASSERT for the upper bound. That assert is compiled out in release builds, so when a GeoMech case has no steps loaded (empty m_stepList) the clamped current time step of 0 caused an out-of-bounds read of m_stepList[0]. Extend the early-return guard to also cover indices past the end, returning the existing (stepIndex, -1) sentinel.
The add() overloads aborted via CAF_ASSERT when passed a null field or
object, forcing every call site that adds an optional child to pre-guard.
Adding an optional node is inherently an "add it if it exists" operation,
so make both overloads a no-op on null instead: the field overload returns,
and the object overload returns nullptr. This removes a class of latent
release crashes and the need for repetitive null checks at call sites.
Also remove a redundant dynamic_cast (and its "// What ???" comment) in
containsField, since child() already returns PdmUiTreeOrdering*.
Guard the remaining unguarded legendConfig() uses so a null legend config
cannot crash: both updateLegend() implementations (eclipse and statistics
projections) now capture the pointer and return early when null, and the
statistics view tree ordering skips a null legend config.
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.
Use a numeric-aware QCollator in RiuGroupedBarChartBuilder::BarEntry::operator< so that tick and legend texts containing numbers (e.g. realization-2 vs realization-10) sort in natural numerical order instead of lexicographically.
Fixes#14105
Revert 380b471. The 'Export Layout to Clipboard' window menu action is a developer-only utility, not an experimental feature. Gate it behind RiaApplication::enableDevelopmentFeatures() again and drop the 'export-dock-layout' experimental feature registration.
Plain pip has no time-based cutoff, so route the workflow's package
installs through uv and set UV_EXCLUDE_NEWER to refuse releases
published within the last week as supply-chain hardening. Mirror the
policy in the rips pyproject for local uv installs.
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.
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.
Promote the experimental feature checkboxes out of the development-only System tab into a dedicated, always-visible Experimental tab so end users can opt into experimental features without enabling development features.
The m_enabledFeatures field stays owned by RiaPreferencesSystem, so its keyword, value options and legacy-keyword migration are unchanged.
Gate the derived oil volume cell result behind the new 'oil-volume-result'
experimental feature instead of RiaApplication::enableDevelopmentFeatures().
In the ROFF file reader, drop the enableDevelopmentFeatures() gates around the
grid dimension, timing and array diagnostics and log them at debug level instead,
so the output is available without RESINSIGHT_DEVEL but stays quiet in normal
runs.
Gate the 'Export Layout to Clipboard' window menu action behind the experimental
features registry instead of RiaApplication::enableDevelopmentFeatures(). Register
the 'export-dock-layout' feature and drop the now-unused RiaApplication include.
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().
Replace the free-text experimental-feature keyword box with a discoverable
registry and a checkbox list in Preferences -> System.
Add RiaExperimentalFeatures as a single, discoverable list of available
experimental features (keyword, display name, description). RiaPreferencesSystem
now stores the enabled features in a tree-selection (checkbox) field populated
from this registry, and isFeatureEnabled() checks that selection. The legacy
semicolon-separated keyword string is migrated in initAfterRead(), preserving
existing preference files and the 'enable-all' keyword.
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.
* Refactor: add MACOSX_BUNDLE option to qt_add_executable in multiple CMakeLists.txt files
* #14045 macOS: Guard std::stacktrace usage and skip ucontext on Apple platforms
* #14045 macOS: Guard std::ispanstream with std::istringstream fallback
* #14045 macOS: Add vcpkg overlay triplets for osx and exclude grpc on osx
* #14045 macOS: CMake macOS build support and openzgy OpenMP-disable patch
* #14045 CI: Add macOS build workflow
* #14045 macOS: Use feature-test macros to detect <stacktrace> and <spanstream>
* #14045 macOS: Make MAX_STIMPLAN_LAYERS constexpr to fix arm64 link error
* #14045 CI: Ship README-macOS.txt with artifact to document Gatekeeper workaround
* #14045 CI: Pin macOS runner to macos-14 and set deployment target to 14.0
* #14045 CI: Move macOS runner to macos-15 and fix README step on configure failure