Valid Qt column indices are 0..columnCount()-1, but the bottom-right
model index was constructed with column columnCount(). Since
QAbstractItemModel::index() validates its arguments, this produced an
invalid QModelIndex(-1,-1) passed to dataChanged(), causing a console
warning on every table row update, e.g. when adding or moving 3D well
path pick targets. Fix the same off-by-one in modelIndexFromPdmObject().
Fixes#14274.
The tree view in PdmUiTreeSelectionEditor is deleted using deleteLater(),
while the models are children of the editor and are deleted immediately.
Detach the view from the models in the destructor, otherwise pending events
in the view may operate on a selection model whose model has been destroyed.
Driving caf::ProgressInfo from worker threads inside the OpenMP loop in
loadFileSummaryCaseData() marshaled setProgress() to the GUI thread via a
queued connection. These updates could be delivered after the ProgressInfo
scope had ended and the progress stacks were popped, accessing an empty stack
and resurrecting the just-closed dialog stuck at 0% with no way to close it.
Only update the progress dialog from the master thread, using an atomic
counter for a monotonic progress value, and guard the ProgressInfo mutators
against stale updates delivered after the stacks are empty.
The GUI thread deadlocked on a non-recursive QMutex during OSDU well
import. The download-completion slots and DataLoadController::onTaskFinished
held a mutex while triggering progress updates, which call
QApplication::processEvents(). That re-enters the event loop and dispatches
another queued parquet-download-complete event for a different well, whose
handler then blocks trying to lock the same mutex.
Release the mutex before emitting taskDone in the OSDU well path and well
log data loaders, and before calling incrementProgress() in onTaskFinished.
The map access that the mutex protects stays inside the locked scope; the
captured ProgressInfo outlives the call (kept alive by blockUntilDone) and
incrementProgress() is thread-safe via self-marshaling to the GUI thread.
Fixes#14230.
The table model shares one field editor handle per column across all rows.
When an edit ends, the view schedules the editor widget for deletion with
deleteLater(), but the handle's QPointer stays valid until the deferred
deletion runs. Clicking a cell in the same column of another row reused that
doomed widget as the new cell editor, so it was destroyed right after
opening and the user had to click again. Moving horizontally was unaffected
since a different column uses a different editor handle.
Cancel the pending deferred deletion before handing the widget out again,
and guard against a null editor widget.
The boundary conditions table required several clicks in each cell before
a value could be changed, because the table view used Qt's default edit
triggers. Add an opt-in editOnSingleClick attribute to the table view
editor that starts editing on a single click and opens combo box popups
immediately, and enable it for the BCPROP keywords table.
The bounding box tree is destroyed by deleteInternalNodesBottomUp, which
recursed once per tree level. For deep or unbalanced trees this overflowed
the call stack during project close (RigMainGrid destruction).
Replace the recursion with an explicit stack. Deleting an internal node does
not touch its children, so the child pointers are read before the node is
deleted and the deletion order is irrelevant. Leaf nodes remain pooled and
are not deleted individually.
The integer slider editor cross-updated the spin box and slider without blocking signals, so a single user interaction wrote to the PDM field twice. The first (nested) write could trigger a field-changed callback that rebuilt the property panel and destroyed the spin box internal line edit, after which the second write dereferenced the dangling line edit in QAbstractSpinBox::text() and crashed.
Block the other widget signals while programmatically syncing in slotSliderValueChanged and updateSliderPosition, restoring the previous blocked state so it nests safely with configureAndUpdateUi. Add null guards in updateSliderPosition and writeValueToField.
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 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.
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.
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*.
* 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
Consolidate the hand-written PropertyType / NNCPropertyType enums in
enums.py into the auto-generated StrEnum classes that already exist in
generated_classes.py. enums.py and all its imports are removed.
The auto-generated class for caf::AppEnum<RiaDefines::ResultCatType>
was named "ResultType" because the existing scriptable m_resultType
fields used keyword "ResultType". Switch those fields to
CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault, keeping the XML
keyword "ResultType" (so project files still load) but exposing the
script keyword as "PropertyType". The generator now emits a single
PropertyType StrEnum that:
- matches the proto PropertyType for setters (FLOAT/INTEGER aside, the
members callers actually use are identical),
- gains ALLAN_DIAGRAMS that the C++ side already knew about,
- loses the proto-only REMOVED/UNDEFINED sentinels (unused in any
Python caller).
rips.NNCPropertyType was exported but unreferenced anywhere — dropped.
Updated Python callers:
- rips.ResultType.X -> rips.PropertyType.X across examples and tests.
- result_type= kwarg / .result_type attribute -> property_type /
.property_type (the script keyword change renamed those everywhere
the affected PdmObject fields are accessed from Python).
- view.apply_cell_result's hand-written wrapper now takes property_type
instead of result_type and forwards via cell_result.property_type.
All 271 Python tests pass, ruff and clang-format clean.
Replace the hand-written PropertyDataType wrapper with first-class enum
return support in the code generator. Scriptable methods that derive
from the new caf::PdmEnumObjectMethod<T> template return a typed enum
value across the gRPC boundary; the Python generator emits a StrEnum
class with the texts pulled from the underlying caf::AppEnum<T> and
wraps the call site so callers receive `EnumClass(value)` directly.
caf::PdmDataContainerEnum is the small PdmObject the framework uses to
carry the enum text on the wire (single scriptable QString field).
RimcEclipseCase_propertyDataType becomes declarative: implement
executeEnum() returning the typed RiaDefines::ResultDataType and pick a
returnEnumScriptName() — the base handles serialization and reports
the four AppEnum members (UNKNOWN, FLOAT, DOUBLE, INTEGER) to the
generator.
Drop the hand-written PropertyDataType in enums.py — the generated one
in resinsight_classes is wire-equivalent and now the single source of
truth.
IconProvider::operator= copied a new resource-string but never cleared
the existing m_pixmap. icon() prefers the pixmap when present, so a
pixmap-based default stamped earlier (e.g. by a base class) would
silently shadow a later resource-string-only assignment in a derived
class.
Reset m_pixmap in operator= so resource-string-only assignments fully
replace pixmap-based ones, and cover the replacement semantics with a
caf::IconProvider regression test: default-overwriting-pixmap,
resource-string-overwriting-pixmap and pixmap-overwriting-pixmap.
Needed for the upcoming nested-collection migration where a base class
stamps a folder pixmap and the topmost instance applies a branded
resource-string icon on top.
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.
Auto-generate enum.StrEnum classes from cafPdmPythonGenerator for every
caf::AppEnum-backed scriptable field, deduplicated by C++ AppEnum type.
Generated PdmObject attributes and method arguments now reference the
typed enum (e.g. self.depth_type: DepthType = DepthType.MEASURED_DEPTH)
instead of bare str. Member names are sanitized against Python keywords
and identifier rules (None -> None_, R-G -> R_G).
Existing scripts that pass plain strings keep working because StrEnum
members are strings; the wire format is unchanged.
Bumps python_requires to >=3.11 (StrEnum). Adds an Enum branch in
PdmObjectBase.__convert_to_grpc_value so future IntEnum use is also
handled.
Replace the class-level static_assert with a DerivedFromPdmObject concept
checked inside the constructor body. The constructor is lazily instantiated,
so T can be forward-declared at the point PdmObjectCollection<T> is used
as a base class.
The bare "// Overrides" comment is now redundant since the override keyword on
each method already conveys the same information. Qualified comments like
"// Overrides from BaseClass" carry additional information and are kept.
Remove the hard floor against m_defaultPerspectiveNearPlaneDistance
(0.05) when computing the perspective near plane from the closest
bounding-box corner. For very small models the closest corner can sit
within that distance, and clamping pushed the near plane past the
model so it was clipped entirely; parallel projection was unaffected
because its near plane scales directly with the bbox.
The zero/negative guard at the end of the block is the actual safety
net, and the maxFarNearRatio constraint still protects depth-buffer
precision when geometry spans both very close and very distant
corners.
Move the loops, lookups, and QString machinery out of
AppEnum<T>::EnumMapper into a new non-template AppEnumMapperBase defined
in cafAppEnum.cpp. Each member is now compiled once for the whole
program rather than once per enum type, cutting build time and binary
size for a class template instantiated across hundreds of enums.
AppEnum<T> becomes a thin static_cast shim around the base methods.
Enum values are stored as int in the mapping; a static_assert rejects
enum types whose underlying type is wider than int. The widest
underlying type currently in use in ResInsight is short, so all current
instantiations are unaffected.
Use std::optional<int> for the mapper default value, and assert against
an empty mapping in defaultValue() (the prior code returned m_mapping[0]
unconditionally, which is undefined behavior on empty).
Document why mapper() uses an explicit init flag rather than
std::call_once or a magic-static lambda: setUp() re-enters mapper() via
addItem, so anything that locks on first init would deadlock.
First-access must therefore be single-threaded, as already exercised by
BaseTest.CreateObjectInMultipleThreads.
Add AppEnumTest.MappingRoundTrip covering text <-> enum, index <-> enum,
isValid, and the failure paths of setFromText / setFromIndex (resets to
default, returns false).
Camera::computeViewFrustum() returns an empty Frustum if the projection
matrix is degenerate (e.g., on the first paint after project open, before
a valid near/far has been set). The per-model culling introduced by
82c7172c1 calls Frustum::isOutside() unconditionally, which asserts when
the frustum has fewer than 6 planes. Skip culling when the frustum is
not fully populated; all valid models then contribute to the near/far
calculation, matching the pre-82c7172c1 behaviour.
The Python class generator previously emitted cvf::Color3f defaults using
the raw QTextStream operator ("r g b" floats), which is not valid Python
and does not match the hex-string form that scriptable color fields
expect on writeToField.
Convert Color3f defaults to their QColor::name() hex representation and
quote any non-QString value mapped to "str" (e.g. Color3f, caf::FilePath)
so the generated Python is syntactically valid.
* Remove unnecessary message parameter from PdmFieldScriptingCapabilityIOHandler readFromField calls
* Add checks for QFile open operations in BaseTest ReadWrite tests
* Fix integer size assertions in AppEnum and PdmLogging tests
* #11371 Remove GLEW dependency and use Qt's QOpenGLFunctions
Replace embedded GLEW library with Qt's native OpenGL function loading
(QOpenGLFunctions/QOpenGLExtraFunctions) to resolve Qt 6 compatibility
warnings about GLEW conflicts with qopenglfunctions.h.
- Update CVF_CALLSITE_OPENGL macro to provide QOpenGLExtraFunctions pointer
- Replace GLEW initialization with Qt OpenGL context validation
- Keep direct calls for fixed-function GL (glBegin, glEnd, glMatrixMode, etc.)
- Remove glew/ directory containing embedded GLEW source
* #11371 Remove GLU dependency to fix Windows build error
GL/glu.h conflicts with Qt's OpenGL headers on Windows due to APIENTRY
redefinition. Replace gluBuild2DMipmaps with glTexImage2D + glGenerateMipmap,
and gluOrtho2D with glOrtho.
Move pdmToVariant/pdmFromVariant overloads for cvf::Color3f, Vec3d, Mat4d, and
Mat3d from namespace caf to namespace cvf. Templates in
cafInternalPdmFieldTypeSpecializations.h use "using caf::pdmToVariant" followed
by an unqualified call, so ADL searches the argument's namespace (cvf). With the
overloads only in caf, the default template was selected, causing cvf::Color3f to
be stored raw in a QVariant instead of as QColor — breaking color field editing
and producing QVariant::save warnings.
All call sites now use the unqualified "using caf::pdmXxx; pdmXxx(value)" pattern
so ADL finds the correct overload without depending on cvf:: as a visible prefix.
Add AdlVariantTest to cafPdmCoreColor3fTest.cpp that exercises this exact pattern.
Adds caf::toVariant<T> and caf::fromVariant<T> to cafPdmFieldTraits.h as
thin wrappers that encapsulate the ADL two-step internally. Client code can
now call caf::toVariant(x) directly instead of requiring a using-declaration
at every call site.
Introduce cafPdmFieldTraits.h with ADL-based pdmToVariant/pdmFromVariant/pdmVariantEqual
as a replacement for PdmValueFieldSpecialization. Migrate all types (AppEnum, FilePath,
PdmPointer, cvf types) and all call sites (PdmDataValueField, PdmProxyValueField, UI
framework, ApplicationLibCode). Delete cafInternalPdmValueFieldSpecializations.h.
Add cafPdmFieldTraits unit tests and fix std::optional support.
Adds an OBJECT library with UNITY_BUILD OFF to measure per-file compile
cost of PDM field types in isolation. Wired into both Fwk/CMakeLists.txt
and the main CMakeLists.txt (under RESINSIGHT_INCLUDE_APPFWK_TESTS).
Also adds build-bench to .gitignore.
Remove the unused non-template PdmObjectCollection class from cafPdmObjectGroup.h/.cpp.
This class conflicted with the template caf::PdmObjectCollection<T> in cafPdmObjectCollection.h,
causing MSVC redefinition errors in Unity builds. The class was dead code with no usages
in application code.
Also correct forward declarations in test MainWindow headers from PdmObjectCollection
to PdmObjectGroup, matching actual usage in the .cpp files.
Registers a ConsoleLogger to handle PDM logging output and removes manual std::cout calls from test PDM objects in favor of the framework's logging system.
Add createDerivedObjectsRecursively() which traverses the object tree using
direct recursion and calls the virtual createDerivedObjects() on each node.
Called between the two resolveReferencesRecursively() passes in RiaApplication,
allowing objects to create child objects based on already-resolved ptr fields.
The second resolve pass then handles references in the newly created children.
Use CAF_PDM_LOG_ERROR and qFatal to notify the developer with an actionable
message when a command feature ID is not registered in the factory. This
replaces the silent CAF_ASSERT and makes it clear that the feature may have
been deleted without removing all references in appendMenuItems().
Iterate per-model bounding boxes and skip models outside the camera frustum to prevent distant off-screen objects from inflating the far plane. This improves depth buffer precision and reduces z-fighting.
Enforce a maximum far/near ratio of 3000.0 by pushing the near plane forward if necessary. Additionally, refine the near plane adjustment when zooming into a point of interest to prevent geometry clipping.