Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicfSetExportFolder.h
${CMAKE_CURRENT_LIST_DIR}/RicfSetMainWindowSize.h
${CMAKE_CURRENT_LIST_DIR}/RicfSetPlotWindowSize.h
${CMAKE_CURRENT_LIST_DIR}/RicfSetSnapshotSize.h
${CMAKE_CURRENT_LIST_DIR}/RicfSetStartDir.h
${CMAKE_CURRENT_LIST_DIR}/RicfSetTimeStep.h
${CMAKE_CURRENT_LIST_DIR}/RicfScaleFractureTemplate.h
Expand Down Expand Up @@ -55,6 +56,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicfSetExportFolder.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfSetMainWindowSize.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfSetPlotWindowSize.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfSetSnapshotSize.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfSetStartDir.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfSetTimeStep.cpp
${CMAKE_CURRENT_LIST_DIR}/RicfScaleFractureTemplate.cpp
Expand Down
80 changes: 80 additions & 0 deletions ApplicationLibCode/CommandFileInterface/RicfSetSnapshotSize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2026- Equinor 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////

#include "RicfSetSnapshotSize.h"

#include "RiaGuiApplication.h"
#include "RiuMainWindow.h"
#include "RiuMainWindowTools.h"
#include "RiuPlotMainWindow.h"

#include "cafPdmFieldScriptingCapability.h"

#include <QApplication>

CAF_PDM_SOURCE_INIT( RicfSetSnapshotSize, "setSnapshotSize" );

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicfSetSnapshotSize::RicfSetSnapshotSize()
{
CAF_PDM_InitScriptableField( &m_height, "height", -1, "Height" );
CAF_PDM_InitScriptableField( &m_width, "width", -1, "Width" );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmScriptResponse RicfSetSnapshotSize::execute()
{
if ( m_width() <= 0 || m_height() <= 0 )
{
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, "setSnapshotSize: width and height must both be > 0" );
}

RiaGuiApplication* guiApp = RiaGuiApplication::instance();
if ( !guiApp )
{
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, "Need GUI ResInsight to set snapshot size" );
}

// Resize plot sub-windows so plot snapshots render at the requested size.
// This is the same helper --snapshotsize uses in the CLI dispatch path.
// Note: for the inner plot widget to also be resized (and not just the
// outer multi-plot wrapper), the caller must have invoked
// set_plot_window_size first so the plots are realized inside MDI
// sub-windows. Without that, only the wrapper resizes and the qwt
// canvas stays anchored at its initial geometry.
if ( auto* plotMainWindow = guiApp->mainPlotWindow() )
{
RiuMainWindowTools::setWindowSizeOnWidgetsInMdiWindows( plotMainWindow, m_width(), m_height() );
}

// Mirror --snapshotsize behavior for 3D views as well.
if ( auto* mainWindow = guiApp->mainWindow() )
{
RiuMainWindowTools::setFixedWindowSizeFor3dViews( mainWindow, m_width(), m_height() );
}

// Let the resize events propagate before the caller's next gRPC
// request (typically export_snapshot) renders the widget.
QApplication::processEvents();

return caf::PdmScriptResponse();
}
42 changes: 42 additions & 0 deletions ApplicationLibCode/CommandFileInterface/RicfSetSnapshotSize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2026- Equinor 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "RicfCommandObject.h"

#include "cafPdmField.h"

//==================================================================================================
//
//
//
//==================================================================================================
class RicfSetSnapshotSize : public RicfCommandObject
{
CAF_PDM_HEADER_INIT;

public:
RicfSetSnapshotSize();

caf::PdmScriptResponse execute() override;

private:
caf::PdmField<int> m_height;
caf::PdmField<int> m_width;
};
1 change: 1 addition & 0 deletions GrpcInterface/GrpcProtos/Commands.proto
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ message CommandParams {
SetWindowSizeParams setPlotWindowSize = 37;
ExportContourMapToTextRequest exportContourMapToText = 38;
SaveProjectRequest saveProject = 39;
SetWindowSizeParams setSnapshotSize = 40;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
summary_cases=[summary_case], address="WOPR:A*;WOPR:B*"
)

# Resize the plot sub-windows so the exported PNGs come out at the
# requested resolution. Without this, the offscreen layout engine picks
# its own (typically small) geometry and snapshots ignore the --size
# launch parameter.
resinsight.set_snapshot_size(1200, 1000)

plots = resinsight.project.plots()
for plot in plots:
plot.export_snapshot()
Expand Down
36 changes: 36 additions & 0 deletions GrpcInterface/Python/rips/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,42 @@ def set_plot_window_size(self, width: int, height: int):
)
)

def set_snapshot_size(self, width: int, height: int):
"""
Set the size used for snapshot export of plots and 3D views.

Affects subsequent calls to ``export_snapshot`` /
``export_snapshots``. Equivalent to the ``--snapshotsize`` CLI
flag. Must be called after at least one plot window has been
created (otherwise there is nothing to resize).

Unlike :meth:`set_plot_window_size`, which only resizes the
outer plot main window, this method un-maximizes and resizes
each MDI sub-window so the actual plot widget is rendered at
the requested dimensions.

Recommended call order for a filled snapshot:

1. :meth:`set_plot_window_size` *before* creating plots, so the
plots are realized inside MDI sub-windows.
2. Create the plot(s).
3. ``project.plots()`` to fetch the plot to export. This can
re-tile the MDI sub-windows back to their defaults, so call
``set_snapshot_size`` *after* it, not before.
4. ``set_snapshot_size(width, height)``.
5. ``plot.export_snapshot(...)``.

**Parameters**::

Parameter | Description | Type
--------- | ---------------- | -----
width | Width in pixels | Integer
height | Height in pixels | Integer
"""
return self.__execute_command(
setSnapshotSize=Commands_pb2.SetWindowSizeParams(width=width, height=height)
)

def major_version(self) -> int:
"""Get an integer with the major version number"""
return int(self.__version_message().major_version)
Expand Down
Loading