Skip to content

Commit

Permalink
Add right click capability to open external plot windows
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-el authored Nov 13, 2024
1 parent 648aa27 commit 6f6543f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 5 deletions.
35 changes: 30 additions & 5 deletions src/ert/gui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import datetime
import functools
import webbrowser
from typing import Dict, Optional
from typing import Dict, List, Optional

from qtpy.QtCore import QSize, Qt, Signal, Slot
from qtpy.QtGui import QCloseEvent, QCursor, QIcon
from qtpy.QtGui import QCloseEvent, QCursor, QIcon, QMouseEvent
from qtpy.QtWidgets import (
QAction,
QFrame,
Expand Down Expand Up @@ -62,6 +62,17 @@
)


class SidebarToolButton(QToolButton):
right_clicked = Signal()

def mousePressEvent(self, event: Optional[QMouseEvent]) -> None:
if event:
if event.button() == Qt.MouseButton.RightButton:
self.right_clicked.emit()
else:
super().mousePressEvent(event)


class ErtMainWindow(QMainWindow):
close_signal = Signal()

Expand Down Expand Up @@ -90,6 +101,7 @@ def __init__(
self.central_widget.setLayout(self.central_layout)
self.facade = LibresFacade(self.ert_config)
self.side_frame = QFrame(self)
self._external_plot_windows: List[PlotWindow] = []

if self.is_dark_mode():
self.side_frame.setStyleSheet("background-color: rgb(64, 64, 64);")
Expand All @@ -104,7 +116,8 @@ def __init__(
self._plot_window: Optional[PlotWindow] = None
self._manage_experiments_panel: Optional[ManageExperimentsPanel] = None
self._add_sidebar_button("Start simulation", QIcon("img:library_add.svg"))
self._add_sidebar_button("Create plot", QIcon("img:timeline.svg"))
plot_button = self._add_sidebar_button("Create plot", QIcon("img:timeline.svg"))
plot_button.setToolTip("Right click to open external window")
self._add_sidebar_button("Manage experiments", QIcon("img:build_wrench.svg"))
self.results_button = self._add_sidebar_button(
"Simulation status", QIcon("img:in_progress.svg")
Expand All @@ -125,6 +138,13 @@ def __init__(
def is_dark_mode(self) -> bool:
return self.palette().base().color().value() < 70

def right_clicked(self) -> None:
actor = self.sender()
if actor and actor.property("index") == "Create plot":
pw = PlotWindow(self.config_file, None)
pw.show()
self._external_plot_windows.append(pw)

def select_central_widget(self) -> None:
actor = self.sender()
if actor:
Expand Down Expand Up @@ -234,8 +254,8 @@ def post_init(self) -> None:
self.help_menu.menuAction(), self.plugins_tool.get_menu()
)

def _add_sidebar_button(self, name: str, icon: QIcon) -> QToolButton:
button = QToolButton(self.side_frame)
def _add_sidebar_button(self, name: str, icon: QIcon) -> SidebarToolButton:
button = SidebarToolButton(self.side_frame)
button.setFixedSize(85, 95)
button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))

Expand All @@ -256,6 +276,7 @@ def _add_sidebar_button(self, name: str, icon: QIcon) -> QToolButton:
self.vbox_layout.addWidget(button)

button.clicked.connect(self.select_central_widget)
button.right_clicked.connect(self.right_clicked)
button.setProperty("index", name)
return button

Expand Down Expand Up @@ -308,6 +329,10 @@ def __add_tools_menu(self) -> None:
tools_menu.addAction(self.load_results_tool.getAction())

def closeEvent(self, closeEvent: Optional[QCloseEvent]) -> None:
for plot_window in self._external_plot_windows:
if plot_window:
plot_window.close()

if closeEvent is not None:
if self.notifier.is_simulation_running:
closeEvent.ignore()
Expand Down
42 changes: 42 additions & 0 deletions tests/ert/ui_tests/gui/test_main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from qtpy.QtCore import Qt, QTimer
from qtpy.QtWidgets import (
QAction,
QApplication,
QCheckBox,
QComboBox,
QDoubleSpinBox,
Expand All @@ -30,6 +31,7 @@
from ert.gui.ertwidgets.create_experiment_dialog import CreateExperimentDialog
from ert.gui.ertwidgets.ensembleselector import EnsembleSelector
from ert.gui.main import ErtMainWindow, GUILogHandler, _setup_main_window
from ert.gui.main_window import SidebarToolButton
from ert.gui.simulation.experiment_panel import ExperimentPanel
from ert.gui.simulation.run_dialog import RunDialog
from ert.gui.suggestor import Suggestor
Expand Down Expand Up @@ -592,6 +594,46 @@ def test_that_gui_plotter_works_when_no_data(qtbot, storage, monkeypatch):
assert len(ensemble_plot_names) == 0


@pytest.mark.usefixtures("use_tmpdir", "set_site_config")
def test_right_click_plot_button_opens_external_plotter(qtbot, storage, monkeypatch):
monkeypatch.setattr(PlotApi, "get_all_ensembles", lambda _: [])
config_file = "minimal_config.ert"
with open(config_file, "w", encoding="utf-8") as f:
f.write("NUM_REALIZATIONS 1")
args_mock = Mock()
args_mock.config = config_file
ert_config = ErtConfig.from_file(config_file)
with StorageService.init_service(
project=os.path.abspath(ert_config.ens_path),
):
gui = _setup_main_window(ert_config, args_mock, GUILogHandler(), storage)
qtbot.addWidget(gui)

button_plot_tool = gui.findChild(SidebarToolButton, "button_Create_plot")
assert button_plot_tool

qtbot.mouseClick(button_plot_tool, Qt.LeftButton)
plot_window = wait_for_child(gui, qtbot, PlotWindow)
assert plot_window

prev_open_windows = len(QApplication.topLevelWindows())

def detect_external_plot_widget_open_on_right_click(plot_count: int):
previous_count = plot_count - 1
assert len(QApplication.topLevelWindows()) == previous_count
qtbot.mouseClick(button_plot_tool, Qt.RightButton)
qtbot.wait_until(
lambda: len(QApplication.topLevelWindows()) != previous_count,
timeout=5000,
)
assert len(QApplication.topLevelWindows()) == plot_count

detect_external_plot_widget_open_on_right_click(prev_open_windows + 1)
detect_external_plot_widget_open_on_right_click(prev_open_windows + 2)
detect_external_plot_widget_open_on_right_click(prev_open_windows + 3)
gui.close()


@pytest.mark.usefixtures("copy_poly_case")
def test_that_es_mda_restart_run_box_is_disabled_when_there_are_no_cases(qtbot):
args = Mock()
Expand Down

0 comments on commit 6f6543f

Please sign in to comment.