From 8f67e6ace6cb9e8e55846e9e653406a3dceda447 Mon Sep 17 00:00:00 2001 From: Jon Holba Date: Wed, 18 Dec 2024 13:19:13 +0100 Subject: [PATCH 1/2] Use PySide6 Upgrade from qtpy with pyqt5 to PySide6. Using PySide6 directly should give us better typing. --- .../actions/install_dependencies/action.yml | 5 +- .../install_dependencies_qt/action.yml | 16 +++++ .github/workflows/build_and_test.yml | 4 ++ .github/workflows/codspeed.yml | 3 + .../workflows/run_ert_test_data_setups.yml | 4 ++ .github/workflows/test_ert.yml | 4 ++ .github/workflows/test_ert_with_slurm.yml | 4 ++ .github/workflows/test_everest.yml | 4 ++ .github/workflows/test_semeio.yml | 4 ++ pyproject.toml | 7 +- src/ert/ensemble_evaluator/snapshot.py | 2 +- src/ert/gui/about_dialog.py | 15 ++-- src/ert/gui/ertnotifier.py | 2 +- src/ert/gui/ertwidgets/__init__.py | 6 +- src/ert/gui/ertwidgets/analysismoduleedit.py | 6 +- .../analysismodulevariablespanel.py | 31 ++++---- src/ert/gui/ertwidgets/checklist.py | 10 +-- src/ert/gui/ertwidgets/closabledialog.py | 35 +++++----- src/ert/gui/ertwidgets/copy_button.py | 10 +-- src/ert/gui/ertwidgets/copyablelabel.py | 4 +- .../ertwidgets/create_experiment_dialog.py | 8 +-- src/ert/gui/ertwidgets/customdialog.py | 12 ++-- src/ert/gui/ertwidgets/ensembleselector.py | 8 +-- src/ert/gui/ertwidgets/listeditbox.py | 26 +++---- src/ert/gui/ertwidgets/message_box.py | 6 +- .../models/selectable_list_model.py | 2 +- src/ert/gui/ertwidgets/models/valuemodel.py | 2 +- src/ert/gui/ertwidgets/pathchooser.py | 6 +- src/ert/gui/ertwidgets/searchbox.py | 20 +++--- src/ert/gui/ertwidgets/stringbox.py | 4 +- src/ert/gui/ertwidgets/textbox.py | 4 +- src/ert/gui/ertwidgets/validationsupport.py | 28 ++++---- src/ert/gui/main.py | 10 +-- src/ert/gui/main_window.py | 17 ++--- src/ert/gui/model/fm_step_list.py | 41 +++++++---- src/ert/gui/model/node.py | 2 +- src/ert/gui/model/real_list.py | 38 +++++++--- src/ert/gui/model/snapshot.py | 70 ++++++++++++------- .../simulation/combobox_with_description.py | 12 ++-- .../simulation/ensemble_experiment_panel.py | 6 +- .../gui/simulation/ensemble_smoother_panel.py | 4 +- .../gui/simulation/evaluate_ensemble_panel.py | 4 +- .../gui/simulation/experiment_config_panel.py | 4 +- src/ert/gui/simulation/experiment_panel.py | 41 ++++++----- .../iterated_ensemble_smoother_panel.py | 4 +- src/ert/gui/simulation/manual_update_panel.py | 4 +- .../multiple_data_assimilation_panel.py | 8 +-- src/ert/gui/simulation/queue_emitter.py | 2 +- src/ert/gui/simulation/run_dialog.py | 54 +++++++------- .../gui/simulation/single_test_run_panel.py | 4 +- .../gui/simulation/view/progress_widget.py | 9 ++- src/ert/gui/simulation/view/realization.py | 57 ++++++++------- src/ert/gui/simulation/view/update.py | 20 +++--- src/ert/gui/suggestor/_suggestor_message.py | 18 ++--- src/ert/gui/suggestor/suggestor.py | 14 ++-- src/ert/gui/summarypanel.py | 4 +- .../design_matrix/design_matrix_panel.py | 6 +- src/ert/gui/tools/event_viewer/panel.py | 6 +- src/ert/gui/tools/event_viewer/tool.py | 4 +- src/ert/gui/tools/export/export_panel.py | 2 +- src/ert/gui/tools/export/export_tool.py | 8 +-- src/ert/gui/tools/file/file_dialog.py | 28 ++++---- src/ert/gui/tools/file/file_update_worker.py | 2 +- .../tools/load_results/load_results_panel.py | 4 +- .../tools/load_results/load_results_tool.py | 2 +- .../manage_experiments_panel.py | 14 ++-- .../manage_experiments/storage_info_widget.py | 4 +- .../tools/manage_experiments/storage_model.py | 58 ++++++++++----- .../manage_experiments/storage_widget.py | 19 +++-- .../gui/tools/plot/customize/color_chooser.py | 16 ++--- .../plot/customize/customization_view.py | 6 +- .../plot/customize/customize_plot_dialog.py | 31 ++++---- .../customize/limits_customization_view.py | 46 ++++++------ .../statistics_customization_view.py | 8 ++- .../gui/tools/plot/customize/style_chooser.py | 2 +- .../customize/style_customization_view.py | 8 ++- .../tools/plot/data_type_keys_list_model.py | 37 +++++++--- .../gui/tools/plot/data_type_keys_widget.py | 10 +-- .../gui/tools/plot/data_type_proxy_model.py | 12 +++- .../plot/plot_ensemble_selection_widget.py | 22 +++--- src/ert/gui/tools/plot/plot_widget.py | 6 +- src/ert/gui/tools/plot/plot_window.py | 11 +-- .../tools/plot/widgets/clearable_line_edit.py | 32 ++++----- .../plot/widgets/copy_style_to_dialog.py | 4 +- .../tools/plot/widgets/custom_date_edit.py | 10 +-- .../gui/tools/plot/widgets/filter_popup.py | 10 +-- src/ert/gui/tools/plugins/plugin.py | 2 +- src/ert/gui/tools/plugins/plugin_handler.py | 2 +- src/ert/gui/tools/plugins/plugins_tool.py | 4 +- .../gui/tools/plugins/process_job_dialog.py | 57 +++++++-------- src/ert/gui/tools/search_bar/search_bar.py | 23 +++--- src/ert/gui/tools/tool.py | 11 ++- .../tools/workflows/run_workflow_widget.py | 12 ++-- .../gui/tools/workflows/workflow_dialog.py | 25 +++---- src/ert/gui/tools/workflows/workflows_tool.py | 2 +- .../scripts/gen_data_rft_export.py | 2 +- tests/ert/conftest.py | 4 +- tests/ert/ui_tests/gui/conftest.py | 16 ++--- tests/ert/ui_tests/gui/test_csv_export.py | 6 +- .../gui/test_full_manual_update_workflow.py | 12 ++-- .../gui/test_load_results_manually.py | 4 +- tests/ert/ui_tests/gui/test_main_window.py | 46 ++++++------ .../gui/test_manage_experiments_tool.py | 4 +- .../gui/test_missing_parameters_to_update.py | 4 +- .../ert/ui_tests/gui/test_missing_runpath.py | 4 +- .../gui/test_plotting_of_snake_oil.py | 8 +-- .../gui/test_restart_ensemble_experiment.py | 8 +-- tests/ert/ui_tests/gui/test_restart_esmda.py | 4 +- ...est_restart_no_responses_and_parameters.py | 10 +-- .../ui_tests/gui/test_rft_export_plugin.py | 13 ++-- .../ert/ui_tests/gui/test_single_test_run.py | 6 +- tests/ert/ui_tests/gui/test_workflow_tool.py | 5 +- .../gui/ertwidgets/test_checklist.py | 6 +- .../gui/ertwidgets/test_closabledialog.py | 4 +- .../ertwidgets/test_copy_debug_info_button.py | 2 +- .../gui/ertwidgets/test_copyablelabel.py | 4 +- .../gui/ertwidgets/test_pathchooser.py | 2 +- .../test_plot_case_selection_widget.py | 8 +-- .../gui/ertwidgets/test_search_bar.py | 4 +- .../ert/unit_tests/gui/model/test_job_list.py | 2 +- .../unit_tests/gui/model/test_real_list.py | 2 +- .../ert/unit_tests/gui/model/test_snapshot.py | 4 +- .../gui/run_analysis/test_analysispanel.py | 10 +-- .../gui/run_analysis/test_update_widget.py | 2 +- .../gui/simulation/test_run_dialog.py | 38 +++++----- .../gui/simulation/test_run_path_dialog.py | 19 ++--- .../gui/simulation/view/test_legend.py | 2 +- .../gui/simulation/view/test_realization.py | 6 +- tests/ert/unit_tests/gui/test_suggestor.py | 2 +- .../gui/tools/file/test_filedialog.py | 2 +- .../gui/tools/plot/test_plot_window.py | 4 +- tests/everest/dialogs_mocker.py | 10 +-- 132 files changed, 899 insertions(+), 705 deletions(-) create mode 100644 .github/actions/install_dependencies_qt/action.yml diff --git a/.github/actions/install_dependencies/action.yml b/.github/actions/install_dependencies/action.yml index 14cb4c9cc42..d917bd2e5b4 100644 --- a/.github/actions/install_dependencies/action.yml +++ b/.github/actions/install_dependencies/action.yml @@ -2,9 +2,8 @@ name: install_dependencies description: Installs dependencies for the pip build inputs: - os: - required: true - + os: + required: true runs: using: "composite" diff --git a/.github/actions/install_dependencies_qt/action.yml b/.github/actions/install_dependencies_qt/action.yml new file mode 100644 index 00000000000..55ae7aabc02 --- /dev/null +++ b/.github/actions/install_dependencies_qt/action.yml @@ -0,0 +1,16 @@ +name: install_dependencies_qt +description: Installs dependencies for qt + +inputs: + os: + required: true + +runs: + using: "composite" + steps: + - name: Install Ubuntu dependencies + if: inputs.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install libegl1 + shell: bash diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index c7fef6e5b8c..7de715e1fab 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -155,6 +155,10 @@ jobs: with: os: ${{ matrix.os }} + - uses: ./.github/actions/install_dependencies_qt + with: + os: ${{ matrix.os }} + - name: Install pandoc run: | sudo apt install pandoc diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index 91b8388a9f0..8a6c24157ca 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -20,6 +20,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: ./.github/actions/install_dependencies_qt + with: + os: ubuntu-latest - uses: actions/setup-python@v5 with: python-version: '3.12' diff --git a/.github/workflows/run_ert_test_data_setups.yml b/.github/workflows/run_ert_test_data_setups.yml index b2dcca20b6c..e7d48a76714 100644 --- a/.github/workflows/run_ert_test_data_setups.yml +++ b/.github/workflows/run_ert_test_data_setups.yml @@ -31,6 +31,10 @@ jobs: with: fetch-depth: 0 + - uses: ./.github/actions/install_dependencies_qt + with: + os: ${{ matrix.os }} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: diff --git a/.github/workflows/test_ert.yml b/.github/workflows/test_ert.yml index aa05ff55996..1f4bce5bcce 100644 --- a/.github/workflows/test_ert.yml +++ b/.github/workflows/test_ert.yml @@ -25,6 +25,10 @@ jobs: submodules: true lfs: true + - uses: ./.github/actions/install_dependencies_qt + with: + os: ${{ inputs.os }} + - uses: actions/setup-python@v5 id: setup_python with: diff --git a/.github/workflows/test_ert_with_slurm.yml b/.github/workflows/test_ert_with_slurm.yml index cead32ad1c7..256c6667067 100644 --- a/.github/workflows/test_ert_with_slurm.yml +++ b/.github/workflows/test_ert_with_slurm.yml @@ -18,6 +18,10 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: ./.github/actions/install_dependencies_qt + with: + os: ${{ inputs.os }} + - uses: actions/setup-python@v5 id: setup_python with: diff --git a/.github/workflows/test_everest.yml b/.github/workflows/test_everest.yml index 7983664ae07..5ce1da48e05 100644 --- a/.github/workflows/test_everest.yml +++ b/.github/workflows/test_everest.yml @@ -25,6 +25,10 @@ jobs: with: fetch-depth: 0 + - uses: ./.github/actions/install_dependencies_qt + with: + os: ${{ inputs.os }} + - name: Set up Python ${{ inputs.python-version }} uses: actions/setup-python@v5 with: diff --git a/.github/workflows/test_semeio.yml b/.github/workflows/test_semeio.yml index 2de23376513..54ccf01f72b 100644 --- a/.github/workflows/test_semeio.yml +++ b/.github/workflows/test_semeio.yml @@ -28,6 +28,10 @@ jobs: with: fetch-depth: 0 + - uses: ./.github/actions/install_dependencies_qt + with: + os: ubuntu-latest + - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/pyproject.toml b/pyproject.toml index 7a226b0c46a..03e907fe12f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,7 @@ dependencies = [ "python-dateutil", "python-multipart", # extra dependency for fastapi "pyyaml", - "qtpy", + "PySide6", "requests", "resfo", "scipy >= 1.10.1", @@ -126,6 +126,7 @@ style = [ ] types = [ "mypy", + "pyside6-stubs", "types-lxml", "types-requests", "types-PyYAML", @@ -248,7 +249,7 @@ typeCheckingMode = "standard" pythonVersion = "3.11" [tool.pyright.defineConstant] -PYSIDE6 = false -PYQT5 = true +PYSIDE6 = true +PYQT5 = false PYSIDE2 = false PYQT6 = false diff --git a/src/ert/ensemble_evaluator/snapshot.py b/src/ert/ensemble_evaluator/snapshot.py index 1b4c5ebb6de..c224afa595d 100644 --- a/src/ert/ensemble_evaluator/snapshot.py +++ b/src/ert/ensemble_evaluator/snapshot.py @@ -6,7 +6,7 @@ from datetime import datetime from typing import Any, TypeVar, cast, get_args -from qtpy.QtGui import QColor +from PySide6.QtGui import QColor from typing_extensions import TypedDict from _ert.events import ( diff --git a/src/ert/gui/about_dialog.py b/src/ert/gui/about_dialog.py index 87b96959dc9..1ff50b743c8 100644 --- a/src/ert/gui/about_dialog.py +++ b/src/ert/gui/about_dialog.py @@ -1,6 +1,6 @@ -from qtpy.QtCore import QSize, Qt -from qtpy.QtGui import QFont -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Qt +from PySide6.QtGui import QFont +from PySide6.QtWidgets import ( QDialog, QHBoxLayout, QLabel, @@ -19,13 +19,8 @@ def __init__(self, parent: QWidget | None) -> None: self.setWindowTitle("About") self.setModal(True) self.setFixedSize(QSize(600, 480)) - self.setWindowFlags( - self.windowFlags() - & ~Qt.WindowFlags(Qt.WindowType.WindowContextHelpButtonHint) - ) - self.setWindowFlags( - self.windowFlags() & ~Qt.WindowFlags(Qt.WindowType.WindowCloseButtonHint) - ) + self.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False) + self.setWindowFlag(Qt.WindowType.WindowCloseButtonHint, False) main_layout = QVBoxLayout() diff --git a/src/ert/gui/ertnotifier.py b/src/ert/gui/ertnotifier.py index 274674c8329..1b1d99607cc 100644 --- a/src/ert/gui/ertnotifier.py +++ b/src/ert/gui/ertnotifier.py @@ -1,4 +1,4 @@ -from qtpy.QtCore import QObject, Signal, Slot +from PySide6.QtCore import QObject, Signal, Slot from ert.storage import Ensemble, Storage diff --git a/src/ert/gui/ertwidgets/__init__.py b/src/ert/gui/ertwidgets/__init__.py index cc1bf211dbb..153b5854eeb 100644 --- a/src/ert/gui/ertwidgets/__init__.py +++ b/src/ert/gui/ertwidgets/__init__.py @@ -1,7 +1,7 @@ # isort: skip_file -from qtpy.QtCore import Qt -from qtpy.QtGui import QCursor -from qtpy.QtWidgets import QApplication +from PySide6.QtCore import Qt +from PySide6.QtGui import QCursor +from PySide6.QtWidgets import QApplication from typing import Any from collections.abc import Callable diff --git a/src/ert/gui/ertwidgets/analysismoduleedit.py b/src/ert/gui/ertwidgets/analysismoduleedit.py index 92270bfb0a7..c679d3cef6c 100644 --- a/src/ert/gui/ertwidgets/analysismoduleedit.py +++ b/src/ert/gui/ertwidgets/analysismoduleedit.py @@ -2,9 +2,9 @@ from typing import TYPE_CHECKING -from qtpy.QtCore import QMargins, Qt -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QHBoxLayout, QToolButton, QWidget +from PySide6.QtCore import QMargins, Qt +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QHBoxLayout, QToolButton, QWidget from ert.gui.ertwidgets import ClosableDialog from ert.gui.ertwidgets.analysismodulevariablespanel import AnalysisModuleVariablesPanel diff --git a/src/ert/gui/ertwidgets/analysismodulevariablespanel.py b/src/ert/gui/ertwidgets/analysismodulevariablespanel.py index 0bd78746f0c..acdf544b20b 100644 --- a/src/ert/gui/ertwidgets/analysismodulevariablespanel.py +++ b/src/ert/gui/ertwidgets/analysismodulevariablespanel.py @@ -4,8 +4,8 @@ from typing import cast, get_args from annotated_types import Ge, Gt, Le -from qtpy.QtCore import Qt -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt +from PySide6.QtWidgets import ( QCheckBox, QComboBox, QDoubleSpinBox, @@ -13,7 +13,6 @@ QFrame, QHBoxLayout, QLabel, - QLayout, QWidget, ) @@ -52,7 +51,7 @@ def __init__(self, analysis_module: AnalysisModule, ensemble_size: int): ): metadata = analysis_module.model_fields[variable_name] layout.addRow( - metadata.title, + metadata.title if metadata.title else "", self.createDoubleSpinBox( variable_name, analysis_module.__getattribute__(variable_name), @@ -105,7 +104,8 @@ def __init__(self, analysis_module: AnalysisModule, ensemble_size: int): localization_frame = QFrame() localization_frame.setLayout(QHBoxLayout()) - lf_layout = cast(QLayout, localization_frame.layout()) + lf_layout = localization_frame.layout() + assert lf_layout is not None lf_layout.setContentsMargins(0, 0, 0, 0) metadata = analysis_module.model_fields[ @@ -115,7 +115,7 @@ def __init__(self, analysis_module: AnalysisModule, ensemble_size: int): local_checkbox.setObjectName("localization") local_checkbox.clicked.connect( partial( - self.valueChanged, + self.valueChangedCheckBox, "localization", bool, local_checkbox, @@ -154,8 +154,8 @@ def update_inversion_algorithm( @staticmethod def create_horizontal_line() -> QFrame: hline = QFrame() - hline.setFrameShape(QFrame.HLine) - hline.setFrameShadow(QFrame.Sunken) + hline.setFrameShape(QFrame.Shape.HLine) + hline.setFrameShadow(QFrame.Shadow.Sunken) hline.setFixedHeight(20) return hline @@ -189,14 +189,21 @@ def valueChanged( variable_name: str, variable_type: type[bool] | type[float], variable_control: QWidget, + value: float, ) -> None: - value: bool | float | None = None + if value is not None: + self.analysis_module.__setattr__(variable_name, value) # noqa: PLC2801 + + def valueChangedCheckBox( + self, + variable_name: str, + variable_type: type[bool] | type[float], + variable_control: QWidget, + ) -> None: + value = None if variable_type == bool: assert isinstance(variable_control, QCheckBox) value = variable_control.isChecked() - elif variable_type == float: - assert isinstance(variable_control, QDoubleSpinBox) - value = variable_control.value() if value is not None: self.analysis_module.__setattr__(variable_name, value) # noqa: PLC2801 diff --git a/src/ert/gui/ertwidgets/checklist.py b/src/ert/gui/ertwidgets/checklist.py index 4bf1ecdac04..1dd355cef8f 100644 --- a/src/ert/gui/ertwidgets/checklist.py +++ b/src/ert/gui/ertwidgets/checklist.py @@ -2,9 +2,9 @@ from typing import TYPE_CHECKING -from qtpy.QtCore import QPoint, QSize, Qt -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import ( +from PySide6.QtCore import QPoint, QSize, Qt +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import ( QAbstractItemView, QHBoxLayout, QLabel, @@ -44,7 +44,7 @@ def __init__( self._list = QListWidget() self._list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) - self._list.setSelectionMode(QAbstractItemView.ExtendedSelection) + self._list.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self._search_box = SearchBox() @@ -162,7 +162,7 @@ def uncheckSelected(self) -> None: def showContextMenu(self, point: QPoint) -> None: p = self._list.mapToGlobal(point) - menu = QMenu() + menu = QMenu(self) check_selected = menu.addAction("Check selected") uncheck_selected = menu.addAction("Uncheck selected") menu.addSeparator() diff --git a/src/ert/gui/ertwidgets/closabledialog.py b/src/ert/gui/ertwidgets/closabledialog.py index c6a8cdb5df3..2de22a857e2 100644 --- a/src/ert/gui/ertwidgets/closabledialog.py +++ b/src/ert/gui/ertwidgets/closabledialog.py @@ -1,13 +1,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from collections.abc import Callable +from typing import TYPE_CHECKING, cast -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QDialog, QHBoxLayout, QPushButton, QVBoxLayout, QWidget +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QDialog, QHBoxLayout, QPushButton, QVBoxLayout, QWidget if TYPE_CHECKING: - from qtpy.QtGui import QKeyEvent - from qtpy.QtWidgets import QT_SLOT + from PySide6.QtGui import QKeyEvent class ClosableDialog(QDialog): @@ -15,16 +15,11 @@ def __init__( self, title: str | None, widget: QWidget, parent: QWidget | None = None ) -> None: QDialog.__init__(self, parent) - self.setWindowTitle(title) + self.setWindowTitle(title if title else "") self.setModal(True) - self.setWindowFlags(self.windowFlags() | Qt.WindowType.CustomizeWindowHint) - self.setWindowFlags( - self.windowFlags() - & ~Qt.WindowFlags(Qt.WindowType.WindowContextHelpButtonHint) - ) - self.setWindowFlags( - self.windowFlags() & ~Qt.WindowFlags(Qt.WindowType.WindowCloseButtonHint) - ) + self.setWindowFlag(Qt.WindowType.CustomizeWindowHint, True) + self.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False) + self.setWindowFlag(Qt.WindowType.WindowCloseButtonHint, False) layout = QVBoxLayout() layout.addWidget(widget, stretch=1) @@ -47,11 +42,11 @@ def disableCloseButton(self) -> None: def enableCloseButton(self) -> None: self.close_button.setEnabled(True) - def keyPressEvent(self, a0: QKeyEvent | None) -> None: - if self.close_button.isEnabled() or a0 is None or a0.key() != Qt.Key.Key_Escape: - QDialog.keyPressEvent(self, a0) + def keyPressEvent(self, arg__1: QKeyEvent) -> None: + if self.close_button.isEnabled() or arg__1.key() != Qt.Key.Key_Escape: + QDialog.keyPressEvent(self, arg__1) - def addButton(self, caption: str, listener: QT_SLOT) -> QPushButton: + def addButton(self, caption: str, listener: Callable[..., None]) -> QPushButton: button = QPushButton(caption) button.setObjectName(str(caption).capitalize()) self.__button_layout.insertWidget(1, button) @@ -59,6 +54,8 @@ def addButton(self, caption: str, listener: QT_SLOT) -> QPushButton: return button def toggleButton(self, caption: str, enabled: bool) -> None: - button = self.findChild(QPushButton, str(caption).capitalize()) + button = cast( + QPushButton, self.findChild(QPushButton, str(caption).capitalize()) + ) if button is not None: button.setEnabled(enabled) diff --git a/src/ert/gui/ertwidgets/copy_button.py b/src/ert/gui/ertwidgets/copy_button.py index 5ee953f11a2..ab8c2ee0614 100644 --- a/src/ert/gui/ertwidgets/copy_button.py +++ b/src/ert/gui/ertwidgets/copy_button.py @@ -1,14 +1,14 @@ from abc import abstractmethod -from qtpy.QtCore import QTimer -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QApplication, QMessageBox, QPushButton, QSizePolicy +from PySide6.QtCore import QTimer +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QApplication, QMessageBox, QPushButton, QSizePolicy class CopyButton(QPushButton): def __init__(self) -> None: super().__init__() - self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) self.setIcon(QIcon("img:copy.svg")) self.restore_timer = QTimer(self) @@ -32,7 +32,7 @@ def copy_text(self, text: str) -> None: None, "Error", "Cannot copy text to clipboard because your system does not have a clipboard", - QMessageBox.Ok, + QMessageBox.StandardButton.Ok, ) self.setIcon(QIcon("img:check.svg")) self.restore_timer.start(1000) diff --git a/src/ert/gui/ertwidgets/copyablelabel.py b/src/ert/gui/ertwidgets/copyablelabel.py index 02d1d47dfb8..dd59e8915c3 100644 --- a/src/ert/gui/ertwidgets/copyablelabel.py +++ b/src/ert/gui/ertwidgets/copyablelabel.py @@ -1,7 +1,7 @@ from os import path -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QHBoxLayout, QLabel +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QHBoxLayout, QLabel from .copy_button import CopyButton diff --git a/src/ert/gui/ertwidgets/create_experiment_dialog.py b/src/ert/gui/ertwidgets/create_experiment_dialog.py index ce234ea6005..1a6bbebf91b 100644 --- a/src/ert/gui/ertwidgets/create_experiment_dialog.py +++ b/src/ert/gui/ertwidgets/create_experiment_dialog.py @@ -1,8 +1,8 @@ -from qtpy.QtCore import ( +from PySide6.QtCore import ( Qt, Signal, ) -from qtpy.QtWidgets import ( +from PySide6.QtWidgets import ( QDialog, QDialogButtonBox, QGridLayout, @@ -59,13 +59,13 @@ def __init__( self._iterations_field.setValidator(IntegerArgument(from_value=0)) self._iterations_field.setObjectName("iterations_field_ced") buttons = QDialogButtonBox( - QDialogButtonBox.Ok | QDialogButtonBox.Cancel, + QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, Qt.Orientation.Horizontal, self, ) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) - ok_button = buttons.button(QDialogButtonBox.Ok) + ok_button = buttons.button(QDialogButtonBox.StandardButton.Ok) assert ok_button self._ok_button = ok_button diff --git a/src/ert/gui/ertwidgets/customdialog.py b/src/ert/gui/ertwidgets/customdialog.py index a2d23be78d3..9f278b08876 100644 --- a/src/ert/gui/ertwidgets/customdialog.py +++ b/src/ert/gui/ertwidgets/customdialog.py @@ -1,8 +1,8 @@ from typing import Any -from qtpy.QtCore import QSize, Qt -from qtpy.QtGui import QColor -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Qt +from PySide6.QtGui import QColor +from PySide6.QtWidgets import ( QDialog, QDialogButtonBox, QFormLayout, @@ -93,18 +93,18 @@ def addLabeledOption(self, label: Any, option_widget: QWidget) -> None: self._layout.addRow(f"{label}:", option_widget) - def addWidget(self, widget: QWidget | QLayout | None, label: str = "") -> None: + def addWidget(self, widget: QWidget | QLayout, label: str = "") -> None: if not label.endswith(":"): label = f"{label}:" self._layout.addRow(label, widget) def addButtons(self) -> None: buttons = QDialogButtonBox( - QDialogButtonBox.Ok | QDialogButtonBox.Cancel, + QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, Qt.Orientation.Horizontal, self, ) - self.ok_button = buttons.button(QDialogButtonBox.Ok) + self.ok_button = buttons.button(QDialogButtonBox.StandardButton.Ok) if self.ok_button: self.ok_button.setEnabled(False) diff --git a/src/ert/gui/ertwidgets/ensembleselector.py b/src/ert/gui/ertwidgets/ensembleselector.py index 62926ddf332..a43ab94455b 100644 --- a/src/ert/gui/ertwidgets/ensembleselector.py +++ b/src/ert/gui/ertwidgets/ensembleselector.py @@ -3,8 +3,8 @@ from collections.abc import Iterable from typing import TYPE_CHECKING -from qtpy.QtCore import Qt, Signal -from qtpy.QtWidgets import QComboBox +from PySide6.QtCore import Qt, Signal +from PySide6.QtWidgets import QComboBox from ert.gui.ertnotifier import ErtNotifier from ert.storage.realization_storage_state import RealizationStorageState @@ -36,13 +36,13 @@ def __init__( # if the ensemble has not been used in an update, as that would # invalidate the result self._show_only_no_children = show_only_no_children - self.setSizeAdjustPolicy(QComboBox.AdjustToContents) + self.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContents) self.setEnabled(False) if update_ert: # Update ERT when this combo box is changed - self.currentIndexChanged[int].connect(self._on_current_index_changed) + self.currentIndexChanged.connect(self._on_current_index_changed) # Update this combo box when ERT is changed notifier.current_ensemble_changed.connect( diff --git a/src/ert/gui/ertwidgets/listeditbox.py b/src/ert/gui/ertwidgets/listeditbox.py index 632c0056c00..b2096e6c367 100644 --- a/src/ert/gui/ertwidgets/listeditbox.py +++ b/src/ert/gui/ertwidgets/listeditbox.py @@ -1,9 +1,9 @@ -from collections.abc import Iterable +from collections.abc import Sequence from uuid import UUID -from qtpy.QtCore import QSize, Qt -from qtpy.QtGui import QIcon, QKeyEvent -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Qt +from PySide6.QtGui import QIcon, QKeyEvent +from PySide6.QtWidgets import ( QCompleter, QHBoxLayout, QInputDialog, @@ -18,14 +18,14 @@ class AutoCompleteLineEdit(QLineEdit): # http://blog.elentok.com/2011/08/autocomplete-textbox-for-multiple.html - def __init__(self, items: Iterable[str | None], parent: QWidget | None = None): + def __init__(self, items: Sequence[str], parent: QWidget | None = None): super().__init__(parent) self._separators = [",", " "] self._completer = QCompleter(items, self) self._completer.setWidget(self) - self._completer.activated[str].connect(self.__insertCompletion) + self._completer.activated.connect(self.__insertCompletion) self._completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) self.__keysToIgnore = [ @@ -50,28 +50,28 @@ def textUnderCursor(self) -> str: i -= 1 return text_under_cursor - def keyPressEvent(self, a0: QKeyEvent | None) -> None: + def keyPressEvent(self, arg__1: QKeyEvent) -> None: popup = self._completer.popup() if ( popup is not None and popup.isVisible() - and a0 is not None - and a0.key() in self.__keysToIgnore + and arg__1 is not None + and arg__1.key() in self.__keysToIgnore ): - a0.ignore() + arg__1.ignore() return - super().keyPressEvent(a0) + super().keyPressEvent(arg__1) completion_prefix = self.textUnderCursor() if completion_prefix != self._completer.completionPrefix(): self.__updateCompleterPopupItems(completion_prefix) - if a0 is not None and len(a0.text()) > 0 and len(completion_prefix) > 0: + if arg__1 is not None and len(arg__1.text()) > 0 and len(completion_prefix) > 0: self._completer.complete() if popup is not None and len(completion_prefix) == 0: popup.hide() - def __updateCompleterPopupItems(self, completionPrefix: str | None) -> None: + def __updateCompleterPopupItems(self, completionPrefix: str) -> None: self._completer.setCompletionPrefix(completionPrefix) popup = self._completer.popup() assert popup is not None diff --git a/src/ert/gui/ertwidgets/message_box.py b/src/ert/gui/ertwidgets/message_box.py index 0eebe8c9f82..690a6f023a6 100644 --- a/src/ert/gui/ertwidgets/message_box.py +++ b/src/ert/gui/ertwidgets/message_box.py @@ -1,4 +1,4 @@ -from qtpy.QtWidgets import ( +from PySide6.QtWidgets import ( QDialog, QDialogButtonBox, QGridLayout, @@ -20,12 +20,12 @@ class ErtMessageBox(QDialog): def __init__( self, text: str | None, - detailed_text: str | None, + detailed_text: str, parent: QWidget | None = None, ) -> None: super().__init__(parent) self.box = QDialogButtonBox( - QDialogButtonBox.Ok, + QDialogButtonBox.StandardButton.Ok, ) self.box.setCenterButtons(True) self.box.accepted.connect(self.accept) diff --git a/src/ert/gui/ertwidgets/models/selectable_list_model.py b/src/ert/gui/ertwidgets/models/selectable_list_model.py index 0c78cf71f54..a36dd1c25e4 100644 --- a/src/ert/gui/ertwidgets/models/selectable_list_model.py +++ b/src/ert/gui/ertwidgets/models/selectable_list_model.py @@ -1,4 +1,4 @@ -from qtpy.QtCore import QObject, Signal +from PySide6.QtCore import QObject, Signal class SelectableListModel(QObject): diff --git a/src/ert/gui/ertwidgets/models/valuemodel.py b/src/ert/gui/ertwidgets/models/valuemodel.py index 42ea0087bb3..e54a673603e 100644 --- a/src/ert/gui/ertwidgets/models/valuemodel.py +++ b/src/ert/gui/ertwidgets/models/valuemodel.py @@ -1,4 +1,4 @@ -from qtpy.QtCore import QObject, Signal, Slot +from PySide6.QtCore import QObject, Signal, Slot class ValueModel(QObject): diff --git a/src/ert/gui/ertwidgets/pathchooser.py b/src/ert/gui/ertwidgets/pathchooser.py index 79c9d072f04..071970f9198 100644 --- a/src/ert/gui/ertwidgets/pathchooser.py +++ b/src/ert/gui/ertwidgets/pathchooser.py @@ -4,9 +4,9 @@ import re from typing import TYPE_CHECKING -from qtpy.QtCore import QSize -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QFileDialog, QHBoxLayout, QLineEdit, QToolButton, QWidget +from PySide6.QtCore import QSize +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QFileDialog, QHBoxLayout, QLineEdit, QToolButton, QWidget from .validationsupport import ValidationSupport diff --git a/src/ert/gui/ertwidgets/searchbox.py b/src/ert/gui/ertwidgets/searchbox.py index 473387257f0..6b2afd596f0 100644 --- a/src/ert/gui/ertwidgets/searchbox.py +++ b/src/ert/gui/ertwidgets/searchbox.py @@ -1,8 +1,8 @@ from typing import Any -from qtpy.QtCore import Qt, Signal -from qtpy.QtGui import QColor, QFocusEvent, QKeyEvent -from qtpy.QtWidgets import QLineEdit +from PySide6.QtCore import Qt, Signal +from PySide6.QtGui import QColor, QFocusEvent, QKeyEvent +from PySide6.QtWidgets import QLineEdit class SearchBox(QLineEdit): @@ -54,17 +54,17 @@ def exitSearch(self) -> None: if not self.text(): self.presentSearch() - def focusInEvent(self, a0: QFocusEvent | None) -> None: - QLineEdit.focusInEvent(self, a0) + def focusInEvent(self, arg__1: QFocusEvent) -> None: + QLineEdit.focusInEvent(self, arg__1) self.enterSearch() - def focusOutEvent(self, a0: QFocusEvent | None) -> None: - QLineEdit.focusOutEvent(self, a0) + def focusOutEvent(self, arg__1: QFocusEvent) -> None: + QLineEdit.focusOutEvent(self, arg__1) self.exitSearch() - def keyPressEvent(self, a0: QKeyEvent | None) -> None: - if a0 is not None and a0.key() == Qt.Key.Key_Escape: + def keyPressEvent(self, arg__1: QKeyEvent) -> None: + if arg__1 is not None and arg__1.key() == Qt.Key.Key_Escape: self.clear() self.clearFocus() else: - QLineEdit.keyPressEvent(self, a0) + QLineEdit.keyPressEvent(self, arg__1) diff --git a/src/ert/gui/ertwidgets/stringbox.py b/src/ert/gui/ertwidgets/stringbox.py index 60f56bfc634..6c3ec82f4f2 100644 --- a/src/ert/gui/ertwidgets/stringbox.py +++ b/src/ert/gui/ertwidgets/stringbox.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING, Any -from qtpy.QtGui import QPalette -from qtpy.QtWidgets import QLineEdit +from PySide6.QtGui import QPalette +from PySide6.QtWidgets import QLineEdit from .validationsupport import ValidationSupport diff --git a/src/ert/gui/ertwidgets/textbox.py b/src/ert/gui/ertwidgets/textbox.py index 5362ae4d148..51f75d28164 100644 --- a/src/ert/gui/ertwidgets/textbox.py +++ b/src/ert/gui/ertwidgets/textbox.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING, Any -from qtpy.QtGui import QPalette -from qtpy.QtWidgets import QTextEdit +from PySide6.QtGui import QPalette +from PySide6.QtWidgets import QTextEdit from .validationsupport import ValidationSupport diff --git a/src/ert/gui/ertwidgets/validationsupport.py b/src/ert/gui/ertwidgets/validationsupport.py index 8e7bdeaef03..2c37e0dc843 100644 --- a/src/ert/gui/ertwidgets/validationsupport.py +++ b/src/ert/gui/ertwidgets/validationsupport.py @@ -3,18 +3,18 @@ import html from typing import TYPE_CHECKING -from qtpy.QtCore import ( +from PySide6.QtCore import ( QObject, QPoint, Qt, Signal, ) -from qtpy.QtGui import QColor -from qtpy.QtWidgets import QFrame, QLabel, QSizePolicy, QVBoxLayout, QWidget +from PySide6.QtGui import QColor, QEnterEvent +from PySide6.QtWidgets import QFrame, QLabel, QSizePolicy, QVBoxLayout, QWidget if TYPE_CHECKING: - from qtpy.QtCore import QEvent - from qtpy.QtGui import QHideEvent + from PySide6.QtCore import QEvent + from PySide6.QtGui import QHideEvent class ErrorPopup(QWidget): @@ -36,8 +36,10 @@ def __init__(self) -> None: layout.setContentsMargins(0, 0, 0, 0) self._error_widget = QLabel("") - self._error_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) - self._error_widget.setFrameStyle(QFrame.Box) + self._error_widget.setSizePolicy( + QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum + ) + self._error_widget.setFrameStyle(QFrame.Shape.Box) self._error_widget.setWordWrap(True) self._error_widget.setScaledContents(True) self._error_widget.setTextFormat(Qt.TextFormat.RichText) @@ -84,8 +86,8 @@ def __init__(self, validation_target: QWidget) -> None: self._originalLeaveEvent = validation_target.leaveEvent self._originalHideEvent = validation_target.hideEvent - def enterEvent(a0: QEvent | None) -> None: - self._originalEnterEvent(a0) + def enterEvent(event: QEnterEvent) -> None: + self._originalEnterEvent(event) if not self.isValid(): self._error_popup.presentError( @@ -95,17 +97,17 @@ def enterEvent(a0: QEvent | None) -> None: validation_target.enterEvent = enterEvent # type: ignore[method-assign] - def leaveEvent(a0: QEvent | None) -> None: - self._originalLeaveEvent(a0) + def leaveEvent(event: QEvent) -> None: + self._originalLeaveEvent(event) if self._error_popup is not None: self._error_popup.hide() validation_target.leaveEvent = leaveEvent # type: ignore[method-assign] - def hideEvent(a0: QHideEvent | None) -> None: + def hideEvent(event: QHideEvent) -> None: self._error_popup.hide() - self._originalHideEvent(a0) + self._originalHideEvent(event) validation_target.hideEvent = hideEvent # type: ignore[method-assign] diff --git a/src/ert/gui/main.py b/src/ert/gui/main.py index b4d412bb84a..2d4e461364d 100755 --- a/src/ert/gui/main.py +++ b/src/ert/gui/main.py @@ -6,9 +6,9 @@ from importlib.resources import files from signal import SIG_DFL, SIGINT, signal -from qtpy.QtCore import QDir -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QApplication, QWidget +from PySide6.QtCore import QDir +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QApplication, QWidget from ert.config import ( ErrorInfo, @@ -84,6 +84,8 @@ def _start_initial_gui_window( ert_config = ErtConfig.with_plugins().from_file(args.config) local_storage_set_ert_config(ert_config) + + storage = None if ert_config is not None: try: storage = open_storage(ert_config.ens_path, mode="w") @@ -105,7 +107,6 @@ def _start_initial_gui_window( ), None, ) - assert ert_config is not None counter_fm_steps = Counter(fms.name for fms in ert_config.forward_model_steps) for fm_step_name, count in counter_fm_steps.items(): @@ -118,6 +119,7 @@ def _start_initial_gui_window( for msg in validation_messages.warnings: logger.info(f"Warning shown in gui '{msg}'") + assert storage is not None main_window = _setup_main_window( ert_config, args, log_handler, storage, plugin_manager ) diff --git a/src/ert/gui/main_window.py b/src/ert/gui/main_window.py index ad4106da5c8..eb0d8171928 100644 --- a/src/ert/gui/main_window.py +++ b/src/ert/gui/main_window.py @@ -4,10 +4,9 @@ import functools import webbrowser -from qtpy.QtCore import QSize, Qt, Signal, Slot -from qtpy.QtGui import QCloseEvent, QCursor, QIcon, QMouseEvent -from qtpy.QtWidgets import ( - QAction, +from PySide6.QtCore import QSize, Qt, Signal, Slot +from PySide6.QtGui import QAction, QCloseEvent, QCursor, QIcon, QMouseEvent +from PySide6.QtWidgets import ( QButtonGroup, QFrame, QHBoxLayout, @@ -190,7 +189,7 @@ def select_central_widget(self) -> None: for i, widget in self.central_panels_map.items(): widget.setVisible(i == index_name) - @Slot(object) + @Slot(RunDialog, result=None) def slot_add_widget(self, run_dialog: RunDialog) -> None: for widget in self.central_panels_map.values(): widget.setVisible(False) @@ -219,8 +218,10 @@ def add_sim_run_option(simulation_id: str) -> None: if self.run_dialog_counter == 2: # swap from button to menu selection self.results_button.clicked.disconnect(self.select_central_widget) - self.results_button.setMenu(QMenu()) - self.results_button.setPopupMode(QToolButton.InstantPopup) + self.results_button.setMenu(QMenu(self)) + self.results_button.setPopupMode( + QToolButton.ToolButtonPopupMode.InstantPopup + ) for prev_date_time, widget in self.central_panels_map.items(): if isinstance(widget, RunDialog): @@ -300,7 +301,7 @@ def __add_help_menu(self) -> None: help_link_item = help_menu.addAction(menu_label) assert help_link_item is not None help_link_item.setMenuRole(QAction.MenuRole.ApplicationSpecificRole) - help_link_item.triggered.connect(functools.partial(webbrowser.open, link)) # type: ignore + help_link_item.triggered.connect(functools.partial(webbrowser.open, link)) show_about = help_menu.addAction("About") assert show_about is not None diff --git a/src/ert/gui/model/fm_step_list.py b/src/ert/gui/model/fm_step_list.py index a60c6c9f4ed..13a902851b0 100644 --- a/src/ert/gui/model/fm_step_list.py +++ b/src/ert/gui/model/fm_step_list.py @@ -1,12 +1,12 @@ from typing import Any, overload -from qtpy.QtCore import ( +from PySide6.QtCore import ( QAbstractItemModel, QAbstractProxyModel, QModelIndex, QObject, + QPersistentModelIndex, Qt, - QVariant, Slot, ) from typing_extensions import override @@ -93,13 +93,17 @@ def headerData( return header.capitalize() if orientation == Qt.Orientation.Vertical: return section - return QVariant() + return QObject() @override - def columnCount(self, parent: QModelIndex | None = None) -> int: + def columnCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: return FM_STEP_COLUMN_SIZE - def rowCount(self, parent: QModelIndex | None = None) -> int: + def rowCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: parent = parent if parent else QModelIndex() if not parent.isValid(): source_model = self.sourceModel() @@ -110,16 +114,21 @@ def rowCount(self, parent: QModelIndex | None = None) -> int: return 0 @overload - def parent(self, child: QModelIndex) -> QModelIndex: ... + def parent(self) -> QObject: ... @overload - def parent(self) -> QObject | None: ... + def parent(self, child: QModelIndex | QPersistentModelIndex) -> QModelIndex: ... @override - def parent(self, child: QModelIndex | None = None) -> QObject | None: + def parent( + self, child: QModelIndex | QPersistentModelIndex | None = None + ) -> QObject | QModelIndex: return QModelIndex() @override def index( - self, row: int, column: int, parent: QModelIndex | None = None + self, + row: int, + column: int, + parent: QModelIndex | QPersistentModelIndex | None = None, ) -> QModelIndex: parent = parent if parent else QModelIndex() if not parent.isValid(): @@ -127,7 +136,9 @@ def index( return self.createIndex(row, column, job_index.data(NodeRole)) return QModelIndex() - def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex: + def mapToSource( + self, proxyIndex: QModelIndex | QPersistentModelIndex + ) -> QModelIndex: if proxyIndex.isValid(): sm = self.sourceModel() assert sm is not None @@ -138,10 +149,12 @@ def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex: return sm.index(proxyIndex.row(), proxyIndex.column(), real_index) return QModelIndex() - def mapFromSource(self, src_index: QModelIndex) -> QModelIndex: + def mapFromSource( + self, sourceIndex: QModelIndex | QPersistentModelIndex + ) -> QModelIndex: return ( - self.index(src_index.row(), src_index.column(), QModelIndex()) - if src_index.isValid() and self._accept_index(src_index) + self.index(sourceIndex.row(), sourceIndex.column(), QModelIndex()) + if sourceIndex.isValid() and self._accept_index(sourceIndex) else QModelIndex() ) @@ -154,7 +167,7 @@ def _source_data_changed( if all([proxy_top_left.isValid(), proxy_bottom_right.isValid()]): self.dataChanged.emit(proxy_top_left, proxy_bottom_right, roles) - def _accept_index(self, index: QModelIndex) -> bool: + def _accept_index(self, index: QModelIndex | QPersistentModelIndex) -> bool: if not index.internalPointer() or not index.data(IsFMStepRole): return False diff --git a/src/ert/gui/model/node.py b/src/ert/gui/model/node.py index e8baa8ee5c5..9d02dd220c9 100644 --- a/src/ert/gui/model/node.py +++ b/src/ert/gui/model/node.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, field from typing import cast -from qtpy.QtGui import QColor +from PySide6.QtGui import QColor from ert.ensemble_evaluator.snapshot import FMStepSnapshot diff --git a/src/ert/gui/model/real_list.py b/src/ert/gui/model/real_list.py index eddc60a8f51..71c5d5868e6 100644 --- a/src/ert/gui/model/real_list.py +++ b/src/ert/gui/model/real_list.py @@ -1,10 +1,11 @@ from typing import overload -from qtpy.QtCore import ( +from PySide6.QtCore import ( QAbstractItemModel, QAbstractProxyModel, QModelIndex, QObject, + QPersistentModelIndex, Slot, ) from typing_extensions import override @@ -61,10 +62,14 @@ def setSourceModel(self, sourceModel: QAbstractItemModel | None) -> None: self.endResetModel() @override - def columnCount(self, parent: QModelIndex | None = None) -> int: + def columnCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: return 1 - def rowCount(self, parent: QModelIndex | None = None) -> int: + def rowCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: parent = parent if parent else QModelIndex() if not parent.isValid(): source_model = self.sourceModel() @@ -75,16 +80,21 @@ def rowCount(self, parent: QModelIndex | None = None) -> int: return 0 @overload - def parent(self, child: QModelIndex) -> QModelIndex: ... + def parent(self) -> QObject: ... @overload - def parent(self) -> QObject | None: ... + def parent(self, child: QModelIndex | QPersistentModelIndex) -> QModelIndex: ... @override - def parent(self, child: QModelIndex | None = None) -> QObject | None: + def parent( + self, child: QModelIndex | QPersistentModelIndex | None = None + ) -> QObject | QModelIndex: return QModelIndex() @override def index( - self, row: int, column: int, parent: QModelIndex | None = None + self, + row: int, + column: int, + parent: QModelIndex | QPersistentModelIndex | None = None, ) -> QModelIndex: parent = parent if parent else QModelIndex() if not parent.isValid(): @@ -93,7 +103,9 @@ def index( return QModelIndex() @override - def hasChildren(self, parent: QModelIndex | None = None) -> bool: + def hasChildren( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> bool: # Reimplemented, since in the source model, the realizations have # children (i.e. valid indices.). Realizations do not have children in # this model. @@ -105,7 +117,9 @@ def hasChildren(self, parent: QModelIndex | None = None) -> bool: return False @override - def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex: + def mapToSource( + self, proxyIndex: QModelIndex | QPersistentModelIndex + ) -> QModelIndex: if proxyIndex.isValid(): sm = self.sourceModel() assert sm is not None @@ -115,7 +129,9 @@ def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex: return QModelIndex() @override - def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex: + def mapFromSource( + self, sourceIndex: QModelIndex | QPersistentModelIndex + ) -> QModelIndex: return ( self.index(sourceIndex.row(), sourceIndex.column(), QModelIndex()) if sourceIndex.isValid() and self._accept_index(sourceIndex) @@ -144,7 +160,7 @@ def _source_rows_inserted( if parent.isValid() and self._accept_index(parent): self.endInsertRows() - def _accept_index(self, index: QModelIndex) -> bool: + def _accept_index(self, index: QModelIndex | QPersistentModelIndex) -> bool: # If the index under test isn't a realization, it is of no interest as # this model should only consist of realization indices. if not index.internalPointer() or not index.data(IsRealizationRole): diff --git a/src/ert/gui/model/snapshot.py b/src/ert/gui/model/snapshot.py index 6521d24d101..828cace3e40 100644 --- a/src/ert/gui/model/snapshot.py +++ b/src/ert/gui/model/snapshot.py @@ -5,8 +5,15 @@ from datetime import datetime, timedelta from typing import Any, Final, overload -from qtpy.QtCore import QAbstractItemModel, QModelIndex, QObject, QSize, Qt, QVariant -from qtpy.QtGui import QColor, QFont +from PySide6.QtCore import ( + QAbstractItemModel, + QModelIndex, + QObject, + QPersistentModelIndex, + QSize, + Qt, +) +from PySide6.QtGui import QColor, QFont from typing_extensions import override from ert.ensemble_evaluator import EnsembleSnapshot, state @@ -172,8 +179,8 @@ def _update_snapshot(self, snapshot: EnsembleSnapshot, iter_: str) -> None: if real_id in metadata["real_status_colors"]: data.real_status_color = metadata["real_status_colors"][real_id] reals_changed.append(real_node.row()) - if real.get("message"): - data.message = real["message"] + if msg := real.get("message"): + data.message = msg fm_steps_changed_by_real: dict[str, list[int]] = defaultdict(list) for (real_id, fm_step_id), fm_step in fm_steps.items(): @@ -276,12 +283,16 @@ def _add_snapshot(self, snapshot: EnsembleSnapshot, iter_: str) -> None: self.rowsInserted.emit(parent, snapshot_tree.row(), snapshot_tree.row()) @override - def columnCount(self, parent: QModelIndex | None = None) -> int: + def columnCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: if parent and isinstance(parent.internalPointer(), RealNode): return FM_STEP_COLUMN_SIZE return 1 - def rowCount(self, parent: QModelIndex | None = None) -> int: + def rowCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: if parent is None: parent = QModelIndex() parent_item = self.root if not parent.isValid() else parent.internalPointer() @@ -289,32 +300,38 @@ def rowCount(self, parent: QModelIndex | None = None) -> int: if parent.column() > 0: return 0 - return len(parent_item.children) + return len(parent_item.children) # type: ignore @overload - def parent(self, child: QModelIndex) -> QModelIndex: ... + def parent(self) -> QObject: ... @overload - def parent(self) -> QObject | None: ... + def parent(self, child: QModelIndex | QPersistentModelIndex) -> QModelIndex: ... @override - def parent(self, child: QModelIndex | None = None) -> QObject | None: + def parent( + self, child: QModelIndex | QPersistentModelIndex | None = None + ) -> QObject | QModelIndex: if child is None or not child.isValid(): return QModelIndex() - parent_item = child.internalPointer().parent + parent_item = child.internalPointer().parent # type:ignore if parent_item == self.root: return QModelIndex() return self.createIndex(parent_item.row(), 0, parent_item) @override - def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole) -> Any: + def data( + self, + index: QModelIndex | QPersistentModelIndex, + role: int = Qt.ItemDataRole.DisplayRole, + ) -> Any: if not index.isValid(): - return QVariant() + return None if role == Qt.ItemDataRole.TextAlignmentRole: return Qt.AlignmentFlag.AlignCenter - node: IterNode | RealNode | ForwardModelStepNode = index.internalPointer() + node: IterNode | RealNode | ForwardModelStepNode = index.internalPointer() # type:ignore if role == NodeRole: return node @@ -356,10 +373,12 @@ def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole) -> A }: return QColor() - return QVariant() + return None @staticmethod - def _real_data(_: QModelIndex, node: RealNode, role: int) -> Any: + def _real_data( + _: QModelIndex | QPersistentModelIndex, node: RealNode, role: int + ) -> Any: if role == FMStepColorHint: total_count = len(node.data.fm_step_status_color_by_id) finished_count = sum( @@ -383,11 +402,11 @@ def _real_data(_: QModelIndex, node: RealNode, role: int) -> Any: if role == CallbackStatusMessageRole: return node.data.message - return QVariant() + return None @staticmethod def _fm_step_data( - index: QModelIndex, + index: QModelIndex | QPersistentModelIndex, node: ForwardModelStepNode, role: int, # Qt.ItemDataRole ) -> Any: @@ -427,12 +446,12 @@ def _fm_step_data( if data_name in {ids.STDOUT, ids.STDERR}: if not file_has_content(index.data(FileRole)): return "-" - return "View" if data_name in node.data else QVariant() + return "View" if data_name in node.data else None if data_name in {DURATION}: start_time = node.data.get(ids.START_TIME) if start_time is None: - return QVariant() + return None delta = _estimate_duration( start_time, end_time=node.data.get(ids.END_TIME) ) @@ -445,7 +464,7 @@ def _fm_step_data( if role == FileRole: data_name = FM_STEP_COLUMNS[index.column()] if data_name in {ids.STDOUT, ids.STDERR}: - return node.data.get(data_name, QVariant()) + return node.data.get(data_name, None) if role == RealIens: return node.parent.id_ if node.parent else None @@ -470,11 +489,14 @@ def _fm_step_data( if tt_text is not None: return str(tt_text) - return QVariant() + return None @override def index( - self, row: int, column: int, parent: QModelIndex | None = None + self, + row: int, + column: int, + parent: QModelIndex | QPersistentModelIndex | None = None, ) -> QModelIndex: if parent is None: parent = QModelIndex() @@ -483,7 +505,7 @@ def index( parent_item = self.root if not parent.isValid() else parent.internalPointer() try: - child_item = list(parent_item.children.values())[row] + child_item = list(parent_item.children.values())[row] # type:ignore except KeyError: return QModelIndex() else: diff --git a/src/ert/gui/simulation/combobox_with_description.py b/src/ert/gui/simulation/combobox_with_description.py index de393bdc564..b913baf272a 100644 --- a/src/ert/gui/simulation/combobox_with_description.py +++ b/src/ert/gui/simulation/combobox_with_description.py @@ -1,8 +1,8 @@ from typing import Any -from qtpy.QtCore import QModelIndex, QPoint, QSize -from qtpy.QtGui import QColor, QRegion -from qtpy.QtWidgets import ( +from PySide6.QtCore import QModelIndex, QPersistentModelIndex, QPoint, QSize +from PySide6.QtGui import QColor, QRegion +from PySide6.QtWidgets import ( QComboBox, QLabel, QStyle, @@ -104,7 +104,9 @@ def paint(self, painter: Any, option: Any, index: Any) -> None: widget.render(painter, QPoint(), QRegion(), QWidget.RenderFlag.DrawChildren) painter.restore() - def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize: + def sizeHint( + self, option: QStyleOptionViewItem, index: QModelIndex | QPersistentModelIndex + ) -> QSize: label = index.data(LABEL_ROLE) description = index.data(DESCRIPTION_ROLE) group = index.data(GROUP_TITLE_ROLE) @@ -120,7 +122,7 @@ def __init__(self, parent: QWidget | None = None) -> None: self.setItemDelegate(_ComboBoxWithDescriptionDelegate(self)) def addDescriptionItem( - self, label: str | None, description: Any, group: str | None = None + self, label: str, description: Any, group: str | None = None ) -> None: super().addItem(label) model = self.model() diff --git a/src/ert/gui/simulation/ensemble_experiment_panel.py b/src/ert/gui/simulation/ensemble_experiment_panel.py index 11e59340f26..0d5739b1f40 100644 --- a/src/ert/gui/simulation/ensemble_experiment_panel.py +++ b/src/ert/gui/simulation/ensemble_experiment_panel.py @@ -1,8 +1,8 @@ from dataclasses import dataclass -from qtpy import QtCore -from qtpy.QtCore import Slot -from qtpy.QtWidgets import QFormLayout, QHBoxLayout, QLabel, QPushButton +from PySide6 import QtCore +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QFormLayout, QHBoxLayout, QLabel, QPushButton from ert.config import AnalysisConfig, DesignMatrix from ert.gui.ertnotifier import ErtNotifier diff --git a/src/ert/gui/simulation/ensemble_smoother_panel.py b/src/ert/gui/simulation/ensemble_smoother_panel.py index 8cabfd1daee..fcd4553f5ac 100644 --- a/src/ert/gui/simulation/ensemble_smoother_panel.py +++ b/src/ert/gui/simulation/ensemble_smoother_panel.py @@ -3,8 +3,8 @@ from dataclasses import dataclass from typing import TYPE_CHECKING -from qtpy.QtCore import Slot -from qtpy.QtWidgets import QFormLayout, QLabel +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QFormLayout, QLabel from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import ( diff --git a/src/ert/gui/simulation/evaluate_ensemble_panel.py b/src/ert/gui/simulation/evaluate_ensemble_panel.py index a81b40ad15c..aad8c7d7814 100644 --- a/src/ert/gui/simulation/evaluate_ensemble_panel.py +++ b/src/ert/gui/simulation/evaluate_ensemble_panel.py @@ -1,8 +1,8 @@ from dataclasses import dataclass import numpy as np -from qtpy import QtCore -from qtpy.QtWidgets import QFormLayout, QLabel +from PySide6 import QtCore +from PySide6.QtWidgets import QFormLayout, QLabel from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import ( diff --git a/src/ert/gui/simulation/experiment_config_panel.py b/src/ert/gui/simulation/experiment_config_panel.py index 08e8fe2be52..18c7758bc45 100644 --- a/src/ert/gui/simulation/experiment_config_panel.py +++ b/src/ert/gui/simulation/experiment_config_panel.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING, Any -from qtpy.QtCore import Signal, Slot -from qtpy.QtWidgets import QWidget +from PySide6.QtCore import Signal, Slot +from PySide6.QtWidgets import QWidget if TYPE_CHECKING: from ert.run_models import BaseRunModel diff --git a/src/ert/gui/simulation/experiment_panel.py b/src/ert/gui/simulation/experiment_panel.py index 3e4a494f872..70a6c51a78e 100644 --- a/src/ert/gui/simulation/experiment_panel.py +++ b/src/ert/gui/simulation/experiment_panel.py @@ -9,10 +9,9 @@ from queue import SimpleQueue from typing import TYPE_CHECKING, Any -from qtpy.QtCore import QSize, Qt, Signal -from qtpy.QtGui import QIcon, QStandardItemModel -from qtpy.QtWidgets import ( - QAction, +from PySide6.QtCore import QSize, Qt, Signal +from PySide6.QtGui import QAction, QIcon, QStandardItemModel +from PySide6.QtWidgets import ( QApplication, QCheckBox, QFrame, @@ -134,11 +133,13 @@ def __init__( self._experiment_stack = QStackedWidget() self._experiment_stack.setLineWidth(1) - self._experiment_stack.setFrameStyle(QFrame.StyledPanel) + self._experiment_stack.setFrameStyle(QFrame.Shape.StyledPanel) layout.addWidget(self._experiment_stack) - self._experiment_widgets: dict[type[BaseRunModel], QWidget] = OrderedDict() + self._experiment_widgets: dict[type[BaseRunModel], ExperimentConfigPanel] = ( + OrderedDict() + ) self.addExperimentConfigPanel( SingleTestRunPanel(run_path, notifier), True, @@ -227,8 +228,7 @@ def get_current_experiment_type(self) -> Any: def get_experiment_arguments(self) -> Any: simulation_widget = self._experiment_widgets[self.get_current_experiment_type()] - args = simulation_widget.get_experiment_arguments() - return args + return simulation_widget.get_experiment_arguments() def getExperimentName(self) -> str: """Get the experiment name as provided by the user. Defaults to run mode if not set.""" @@ -248,7 +248,10 @@ def run_experiment(self) -> None: except ValueError as e: QMessageBox.warning( - self, "ERROR: Failed to create experiment", (str(e)), QMessageBox.Ok + self, + "ERROR: Failed to create experiment", + (str(e)), + QMessageBox.StandardButton.Ok, ) return @@ -259,7 +262,7 @@ def run_experiment(self) -> None: msg_box = QMessageBox(self) msg_box.setObjectName("RUN_PATH_WARNING_BOX") - msg_box.setIcon(QMessageBox.Warning) + msg_box.setIcon(QMessageBox.Icon.Warning) msg_box.setText("Run experiments") msg_box.setInformativeText( @@ -278,13 +281,15 @@ def run_experiment(self) -> None: delete_runpath_checkbox.setText("Delete run_path") msg_box.setCheckBox(delete_runpath_checkbox) - msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) - msg_box.setDefaultButton(QMessageBox.No) + msg_box.setStandardButtons( + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No + ) + msg_box.setDefaultButton(QMessageBox.StandardButton.No) msg_box.setWindowModality(Qt.WindowModality.ApplicationModal) msg_box_res = msg_box.exec() - if msg_box_res == QMessageBox.No: + if msg_box_res == QMessageBox.StandardButton.No: return if delete_runpath_checkbox.checkState() == Qt.CheckState.Checked: @@ -295,16 +300,18 @@ def run_experiment(self) -> None: QApplication.restoreOverrideCursor() msg_box = QMessageBox(self) msg_box.setObjectName("RUN_PATH_ERROR_BOX") - msg_box.setIcon(QMessageBox.Warning) + msg_box.setIcon(QMessageBox.Icon.Warning) msg_box.setText("ERT could not delete the existing runpath") msg_box.setInformativeText( f"{e}\n\n" "Continue without deleting the runpath?" ) - msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) - msg_box.setDefaultButton(QMessageBox.No) + msg_box.setStandardButtons( + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No + ) + msg_box.setDefaultButton(QMessageBox.StandardButton.No) msg_box.setWindowModality(Qt.WindowModality.ApplicationModal) msg_box_res = msg_box.exec() - if msg_box_res == QMessageBox.No: + if msg_box_res == QMessageBox.StandardButton.No: return QApplication.restoreOverrideCursor() diff --git a/src/ert/gui/simulation/iterated_ensemble_smoother_panel.py b/src/ert/gui/simulation/iterated_ensemble_smoother_panel.py index 9d4e1138cb4..4c00da14162 100644 --- a/src/ert/gui/simulation/iterated_ensemble_smoother_panel.py +++ b/src/ert/gui/simulation/iterated_ensemble_smoother_panel.py @@ -3,8 +3,8 @@ from dataclasses import dataclass from typing import TYPE_CHECKING -from qtpy.QtCore import Slot -from qtpy.QtWidgets import QFormLayout, QLabel, QSpinBox +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QFormLayout, QLabel, QSpinBox from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import ( diff --git a/src/ert/gui/simulation/manual_update_panel.py b/src/ert/gui/simulation/manual_update_panel.py index 4a7d2a93be5..586b5fdb2ec 100644 --- a/src/ert/gui/simulation/manual_update_panel.py +++ b/src/ert/gui/simulation/manual_update_panel.py @@ -1,8 +1,8 @@ from dataclasses import dataclass import numpy as np -from qtpy import QtCore -from qtpy.QtWidgets import QFormLayout, QLabel +from PySide6 import QtCore +from PySide6.QtWidgets import QFormLayout, QLabel from ert.config import AnalysisConfig from ert.gui.ertnotifier import ErtNotifier diff --git a/src/ert/gui/simulation/multiple_data_assimilation_panel.py b/src/ert/gui/simulation/multiple_data_assimilation_panel.py index a629c77f09a..f4ee622fa17 100644 --- a/src/ert/gui/simulation/multiple_data_assimilation_panel.py +++ b/src/ert/gui/simulation/multiple_data_assimilation_panel.py @@ -3,9 +3,9 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Any -from qtpy.QtCore import Slot -from qtpy.QtGui import QFont -from qtpy.QtWidgets import QCheckBox, QFormLayout, QLabel +from PySide6.QtCore import Slot +from PySide6.QtGui import QFont +from PySide6.QtWidgets import QCheckBox, QFormLayout, QLabel from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import ( @@ -276,7 +276,7 @@ def __init__(self, model: ValueModel) -> None: self._model = model font = self.font() - font.setWeight(QFont.Bold) + font.setWeight(QFont.Weight.Bold) self.setFont(font) self._model.valueChanged.connect(self.updateLabel) diff --git a/src/ert/gui/simulation/queue_emitter.py b/src/ert/gui/simulation/queue_emitter.py index dd07a5ff2fd..9633bb20374 100644 --- a/src/ert/gui/simulation/queue_emitter.py +++ b/src/ert/gui/simulation/queue_emitter.py @@ -5,7 +5,7 @@ from queue import Empty, SimpleQueue from time import sleep -from qtpy.QtCore import QObject, Signal, Slot +from PySide6.QtCore import QObject, Signal, Slot from ert.ensemble_evaluator import EndEvent, FullSnapshotEvent, SnapshotUpdateEvent from ert.gui.model.snapshot import SnapshotModel diff --git a/src/ert/gui/simulation/run_dialog.py b/src/ert/gui/simulation/run_dialog.py index 93908ac2c4d..e49b90fdced 100644 --- a/src/ert/gui/simulation/run_dialog.py +++ b/src/ert/gui/simulation/run_dialog.py @@ -4,15 +4,11 @@ from collections.abc import Callable from pathlib import Path from queue import SimpleQueue +from typing import cast -from qtpy.QtCore import QModelIndex, QSize, Qt, QThread, QTimer, Signal, Slot -from qtpy.QtGui import ( - QMouseEvent, - QMovie, - QTextCursor, - QTextOption, -) -from qtpy.QtWidgets import ( +from PySide6.QtCore import QModelIndex, QSize, Qt, QThread, QTimer, Signal, Slot +from PySide6.QtGui import QMouseEvent, QMovie, QTextCursor, QTextOption +from PySide6.QtWidgets import ( QAbstractItemView, QDialog, QDialogButtonBox, @@ -80,9 +76,9 @@ def __init__(self, snapshot_model: SnapshotModel, parent: QWidget | None) -> Non self._fm_step_model = FMStepListProxyModel(self, 0, 0) self._fm_step_model.setSourceModel(snapshot_model) - self.setVerticalScrollMode(QAbstractItemView.ScrollPerItem) - self.setSelectionBehavior(QAbstractItemView.SelectRows) - self.setSelectionMode(QAbstractItemView.SingleSelection) + self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerItem) + self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) + self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.clicked.connect(self._fm_step_clicked) self.setModel(self._fm_step_model) @@ -98,9 +94,9 @@ def __init__(self, snapshot_model: SnapshotModel, parent: QWidget | None) -> Non # Only last section should be stretch horizontal_header.setSectionResizeMode( section, - QHeaderView.Stretch + QHeaderView.ResizeMode.Stretch if section == horizontal_header.count() - 1 - else QHeaderView.Interactive, + else QHeaderView.ResizeMode.Interactive, ) vertical_header = self.verticalHeader() @@ -119,6 +115,7 @@ def _fm_step_clicked(self, index: QModelIndex) -> None: return selected_file = index.data(FileRole) file_dialog = self.findChild(QDialog, name=selected_file) + file_dialog = cast(QDialog, file_dialog) if file_dialog and file_dialog.isVisible(): file_dialog.raise_() elif selected_file and file_has_content(selected_file): @@ -138,18 +135,18 @@ def _fm_step_clicked(self, index: QModelIndex) -> None: error_textedit = QPlainTextEdit() error_textedit.setReadOnly(True) - error_textedit.setWordWrapMode(QTextOption.NoWrap) + error_textedit.setWordWrapMode(QTextOption.WrapMode.NoWrap) error_textedit.appendPlainText(index.data()) layout.addWidget(error_textedit) - dialog_button = QDialogButtonBox(QDialogButtonBox.Ok) + dialog_button = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) dialog_button.accepted.connect(error_dialog.accept) layout.addWidget(dialog_button) error_dialog.resize(700, 300) - error_textedit.moveCursor(QTextCursor.Start) + error_textedit.moveCursor(QTextCursor.MoveOperation.Start) error_dialog.exec_() - def mouseMoveEvent(self, event: QMouseEvent | None) -> None: + def mouseMoveEvent(self, event: QMouseEvent) -> None: if event: index = self.indexAt(event.pos()) if index.isValid(): @@ -283,7 +280,7 @@ def __init__( self.setLayout(layout) - self.kill_button.clicked.connect(self.killJobs) # type: ignore + self.kill_button.clicked.connect(self.killJobs) self.restart_button.clicked.connect(self.restart_failed_realizations) self.simulation_done.connect(self._on_simulation_done) @@ -307,9 +304,11 @@ def on_snapshot_new_iteration( ) -> None: if not parent.isValid(): index = self._snapshot_model.index(start, 0, parent) + # iteration = index.data(IterNum) + iteration = index.internalPointer().id_ # type: ignore iter_row = start self._iteration_progress_label.setText( - f"Progress for iteration {index.internalPointer().id_}" + f"Progress for iteration {iteration}" ) widget = RealizationWidget(iter_row) @@ -317,7 +316,7 @@ def on_snapshot_new_iteration( widget.itemClicked.connect(self._select_real) self._select_real(widget._real_list_model.index(0, 0)) tab_index = self._tab_widget.addTab( - widget, f"Realizations for iteration {index.internalPointer().id_}" + widget, f"Realizations for iteration {iteration}" ) if self._tab_widget.currentIndex() == self._tab_widget.count() - 2: self._tab_widget.setCurrentIndex(tab_index) @@ -383,10 +382,13 @@ def run() -> None: def killJobs(self) -> QMessageBox.StandardButton: msg = "Are you sure you want to terminate the currently running experiment?" kill_job = QMessageBox.question( - self, "Terminate experiment", msg, QMessageBox.Yes | QMessageBox.No + self, + "Terminate experiment", + msg, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, ) - if kill_job == QMessageBox.Yes: + if kill_job == QMessageBox.StandardButton.Yes: # Normally this slot would be invoked by the signal/slot system, # but the worker is busy tracking the evaluation. self._run_model.cancel() @@ -494,17 +496,19 @@ def update_total_progress( def restart_failed_realizations(self) -> None: msg = QMessageBox(self) - msg.setIcon(QMessageBox.Information) + msg.setIcon(QMessageBox.Icon.Information) msg.setText( "Note that workflows will only be executed on the restarted " "realizations and that this might have unexpected consequences." ) msg.setWindowTitle("Restart failed realizations") - msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) + msg.setStandardButtons( + QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel + ) msg.setObjectName("restart_prompt") result = msg.exec_() - if result == QMessageBox.Ok: + if result == QMessageBox.StandardButton.Ok: self.restart_button.setVisible(False) self.kill_button.setVisible(True) self.run_experiment(restart=True) diff --git a/src/ert/gui/simulation/single_test_run_panel.py b/src/ert/gui/simulation/single_test_run_panel.py index 23ecc40490a..599cab71789 100644 --- a/src/ert/gui/simulation/single_test_run_panel.py +++ b/src/ert/gui/simulation/single_test_run_panel.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from qtpy import QtCore -from qtpy.QtWidgets import QFormLayout, QLabel +from PySide6 import QtCore +from PySide6.QtWidgets import QFormLayout, QLabel from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import CopyableLabel diff --git a/src/ert/gui/simulation/view/progress_widget.py b/src/ert/gui/simulation/view/progress_widget.py index 395ddb77737..bd5508eefa3 100644 --- a/src/ert/gui/simulation/view/progress_widget.py +++ b/src/ert/gui/simulation/view/progress_widget.py @@ -2,14 +2,13 @@ from typing import Any -from qtpy.QtGui import QColor -from qtpy.QtWidgets import ( +from PySide6.QtGui import QColor +from PySide6.QtWidgets import ( QFrame, QHBoxLayout, QLabel, QProgressBar, QVBoxLayout, - QWidget, ) from ert.ensemble_evaluator.state import ENSEMBLE_STATE_FAILED, REAL_STATE_TO_COLOR @@ -17,7 +16,7 @@ class ProgressWidget(QFrame): def __init__(self) -> None: - QWidget.__init__(self) + QFrame.__init__(self) self.setFixedHeight(70) self._vertical_layout = QVBoxLayout(self) @@ -110,5 +109,5 @@ def update_progress(self, status: dict[str, int], realization_count: int) -> Non self.stop_waiting_progress_bar() self.repaint_components() - def resizeEvent(self, a0: Any, event: Any = None) -> None: + def resizeEvent(self, event: Any = None) -> None: self.repaint_components() diff --git a/src/ert/gui/simulation/view/realization.py b/src/ert/gui/simulation/view/realization.py index 00cd593962d..d32488bd7e8 100644 --- a/src/ert/gui/simulation/view/realization.py +++ b/src/ert/gui/simulation/view/realization.py @@ -1,16 +1,19 @@ -from qtpy.QtCore import ( +from typing import cast + +from PySide6.QtCore import ( QAbstractItemModel, QEvent, QItemSelectionModel, QModelIndex, QObject, + QPersistentModelIndex, QPoint, QSize, Qt, Signal, ) -from qtpy.QtGui import QColor, QColorConstants, QPainter, QPalette, QPen -from qtpy.QtWidgets import ( +from PySide6.QtGui import QColor, QMouseEvent, QPainter, QPalette, QPen +from PySide6.QtWidgets import ( QAbstractItemView, QListView, QStyle, @@ -39,18 +42,20 @@ def __init__(self, it: int, parent: QWidget | None = None) -> None: self._delegate_size = QSize(90, 90) self._real_view = QListView(self) - self._real_view.setViewMode(QListView.IconMode) + self._real_view.setViewMode(QListView.ViewMode.IconMode) self._real_view.setGridSize(self._delegate_size) real_delegate = RealizationDelegate(self._delegate_size, self) self._real_view.setMouseTracking(True) self._real_view.setItemDelegate(real_delegate) - self._real_view.setSelectionMode(QAbstractItemView.SingleSelection) - self._real_view.setFlow(QListView.LeftToRight) + self._real_view.setSelectionMode( + QAbstractItemView.SelectionMode.SingleSelection + ) + self._real_view.setFlow(QListView.Flow.LeftToRight) self._real_view.setWrapping(True) - self._real_view.setResizeMode(QListView.Adjust) + self._real_view.setResizeMode(QListView.ResizeMode.Adjust) self._real_view.setUniformItemSizes(True) self._real_view.setStyleSheet( - f"QListView {{ background-color: {self.palette().color(QPalette.Window).name()}; }}" + f"QListView {{ background-color: {self.palette().color(QPalette.ColorRole.Window).name()}; }}" ) self._real_view.clicked.connect(self._item_clicked) @@ -94,14 +99,14 @@ def __init__(self, size: QSize, parent: QObject) -> None: self.adjustment_point_for_job_rect_margin = QPoint(-20, -20) self._color_black = QColor(0, 0, 0, 180) self._color_progress = QColor(50, 173, 230, 200) - self._color_lightgray = QColor(QColorConstants.LightGray).lighter(120) + self._color_lightgray = QColor("LightGray").lighter(120) self._pen_black = QPen(self._color_black, 2, Qt.PenStyle.SolidLine) def paint( self, painter: QPainter | None, option: QStyleOptionViewItem, - index: QModelIndex, + index: QModelIndex | QPersistentModelIndex, ) -> None: if painter is None: return @@ -109,15 +114,15 @@ def paint( selected_color, finished_count, total_count = tuple(index.data(FMStepColorHint)) painter.save() - painter.setRenderHint(QPainter.TextAntialiasing, True) - painter.setRenderHint(QPainter.Antialiasing, True) + painter.setRenderHint(QPainter.RenderHint.TextAntialiasing, True) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) percentage_done = ( 100 if total_count < 1 else int((finished_count * 100.0) / total_count) ) painter.setPen(self._pen_black) - adjusted_rect = option.rect.adjusted(2, 2, -2, -2) + adjusted_rect = option.rect.adjusted(2, 2, -2, -2) # type: ignore[attr-defined] painter.setBrush( self._color_progress if percentage_done == 100 else self._color_lightgray @@ -128,35 +133,37 @@ def paint( painter.setBrush(self._color_progress) painter.drawPie(adjusted_rect, 1440, -int(percentage_done * 57.6)) - if option.state & QStyle.StateFlag.State_Selected: + if option.state & QStyle.StateFlag.State_Selected: # type: ignore[attr-defined] selected_color = selected_color.lighter(125) painter.setBrush(selected_color) - adjusted_rect = option.rect.adjusted(7, 7, -7, -7) + adjusted_rect = option.rect.adjusted(7, 7, -7, -7) # type: ignore[attr-defined] painter.drawEllipse(adjusted_rect) font = painter.font() font.setBold(True) painter.setFont(font) - adj_rect = option.rect.adjusted(0, 20, 0, 0) + adj_rect = option.rect.adjusted(0, 20, 0, 0) # type: ignore[attr-defined] painter.drawText(adj_rect, Qt.AlignmentFlag.AlignHCenter, text) - adj_rect = option.rect.adjusted(0, 45, 0, 0) + adj_rect = option.rect.adjusted(0, 45, 0, 0) # type: ignore[attr-defined] painter.drawText( adj_rect, Qt.AlignmentFlag.AlignHCenter, f"{finished_count} / {total_count}" ) painter.restore() - def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize: + def sizeHint( + self, option: QStyleOptionViewItem, index: QModelIndex | QPersistentModelIndex + ) -> QSize: return self._size - def eventFilter(self, object: QObject | None, event: QEvent | None) -> bool: - if event.type() == QEvent.Type.ToolTip: # type: ignore - mouse_pos = event.pos() + self.adjustment_point_for_job_rect_margin # type: ignore - parent: RealizationWidget = self.parent() # type: ignore + def eventFilter(self, object: QObject, event: QEvent) -> bool: + if event.type() == QEvent.Type.ToolTip and type(event) is QMouseEvent: + mouse_pos = event.position() + self.adjustment_point_for_job_rect_margin + parent: RealizationWidget = cast(RealizationWidget, self.parent()) view = parent._real_view - index = view.indexAt(mouse_pos) + index = view.indexAt(mouse_pos.toPoint()) if index.isValid(): tooltip_text = "" maximum_memory_usage = index.data(MemoryUsageRole) @@ -168,7 +175,9 @@ def eventFilter(self, object: QObject | None, event: QEvent | None) -> bool: if callback_error_msg := index.data(CallbackStatusMessageRole): tooltip_text += callback_error_msg if tooltip_text: - QToolTip.showText(view.mapToGlobal(mouse_pos), tooltip_text) + QToolTip.showText( + view.mapToGlobal(mouse_pos.toPoint()), tooltip_text + ) return True return super().eventFilter(object, event) diff --git a/src/ert/gui/simulation/view/update.py b/src/ert/gui/simulation/view/update.py index 1fe262cafad..4bd93fb3c7c 100644 --- a/src/ert/gui/simulation/view/update.py +++ b/src/ert/gui/simulation/view/update.py @@ -5,9 +5,9 @@ from datetime import timedelta import humanize -from qtpy.QtCore import Qt, Slot -from qtpy.QtGui import QColor, QKeyEvent, QKeySequence -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt, Slot +from PySide6.QtGui import QColor, QKeyEvent, QKeySequence +from PySide6.QtWidgets import ( QAbstractItemView, QApplication, QGridLayout, @@ -46,17 +46,17 @@ def __init__(self, data: DataSection, parent: QWidget | None = None): self.setRowCount(len(data.data)) self.setHorizontalHeaderLabels(data.header) self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) - self.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) horizontal_header = self.horizontalHeader() assert horizontal_header is not None - horizontal_header.setSectionResizeMode(QHeaderView.ResizeToContents) + horizontal_header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) self.setSortingEnabled(True) for i, row in enumerate(data.data): for j, val in enumerate(row): self.setItem(i, j, QTableWidgetItem(str(val))) - def keyPressEvent(self, e: QKeyEvent | None) -> None: - if e is not None and e.matches(QKeySequence.Copy): + def keyPressEvent(self, event: QKeyEvent) -> None: + if event is not None and event.matches(QKeySequence.StandardKey.Copy): stream = "" for i in self.selectedIndexes(): item = self.itemFromIndex(i) @@ -71,10 +71,10 @@ def keyPressEvent(self, e: QKeyEvent | None) -> None: None, "Error", "Cannot copy text to clipboard because your system does not have a clipboard", - QMessageBox.Ok, + QMessageBox.StandardButton.Ok, ) else: - super().keyPressEvent(e) + super().keyPressEvent(event) class UpdateWidget(QWidget): @@ -127,7 +127,7 @@ def iteration(self) -> int: def _insert_status_message(self, message: str) -> None: item = QListWidgetItem() item.setText(message) - item.setFlags(item.flags() & ~Qt.ItemFlags(Qt.ItemFlag.ItemIsEnabled)) + item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEnabled) self._msg_list.addItem(item) def _insert_table_tab( diff --git a/src/ert/gui/suggestor/_suggestor_message.py b/src/ert/gui/suggestor/_suggestor_message.py index cf2831b3dde..5922d1e7baf 100644 --- a/src/ert/gui/suggestor/_suggestor_message.py +++ b/src/ert/gui/suggestor/_suggestor_message.py @@ -2,10 +2,10 @@ from typing import Any, Self -from qtpy import QtSvg -from qtpy.QtCore import Qt -from qtpy.QtGui import QColor -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt +from PySide6.QtGui import QColor +from PySide6.QtSvgWidgets import QSvgWidget +from PySide6.QtWidgets import ( QGraphicsDropShadowEffect, QHBoxLayout, QLabel, @@ -24,9 +24,9 @@ ) -def _svg_icon(image_name: str) -> QtSvg.QSvgWidget: - widget = QtSvg.QSvgWidget(f"img:{image_name}.svg") - widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) +def _svg_icon(image_name: str) -> QSvgWidget: + widget = QSvgWidget(f"img:{image_name}.svg") + widget.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) return widget @@ -73,7 +73,9 @@ def __init__( self.lbl = QLabel(self._collapsed_text()) self.lbl.setOpenExternalLinks(False) - self.lbl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.lbl.setSizePolicy( + QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding + ) self.lbl.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) self.lbl.setWordWrap(True) self._expanded = False diff --git a/src/ert/gui/suggestor/suggestor.py b/src/ert/gui/suggestor/suggestor.py index 99221baf2ab..b7c8359eb24 100644 --- a/src/ert/gui/suggestor/suggestor.py +++ b/src/ert/gui/suggestor/suggestor.py @@ -7,9 +7,9 @@ from collections.abc import Callable, Sequence from typing import TYPE_CHECKING -from qtpy.QtCore import Qt -from qtpy.QtGui import QCursor -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt +from PySide6.QtGui import QCursor +from PySide6.QtWidgets import ( QFrame, QGridLayout, QHBoxLayout, @@ -20,6 +20,8 @@ QWidget, ) +from ert.gui.ertnotifier import ErtNotifier + from ._colors import BLUE_TEXT from ._suggestor_message import SuggestorMessage @@ -111,6 +113,7 @@ def __init__( deprecations: list[WarningInfo], continue_action: Callable[[], None] | None, help_links: dict[str, str] | None = None, + notifier: ErtNotifier | None = None, ) -> None: super().__init__() self._continue_action = continue_action @@ -131,6 +134,7 @@ def __init__( self.setStyleSheet(f"background-color: {LIGHT_GREY}; color: black") self.__layout.setContentsMargins(32, 47, 32, 16) self.__layout.setSpacing(32) + self.notifier = notifier data_layout = QHBoxLayout() data_widget.setLayout(data_layout) @@ -166,7 +170,7 @@ def _help_panel(self, help_links: dict[str, str]) -> QFrame: help_buttons_layout.addWidget(help_header, alignment=Qt.AlignmentFlag.AlignTop) separator = QFrame(parent=self) - separator.setFrameShape(QFrame.HLine) + separator.setFrameShape(QFrame.Shape.HLine) separator.setStyleSheet(f"color: {HEAVY_GREY};") separator.setFixedWidth(388) help_buttons_layout.addWidget(separator) @@ -219,7 +223,7 @@ def run_pressed() -> None: run.setObjectName("run_ert_button") run.pressed.connect(run_pressed) - give_up.pressed.connect(self.close) # type: ignore + give_up.pressed.connect(self.close) buttons = QWidget(parent=self) buttons_layout = QHBoxLayout() buttons_layout.insertStretch(-1, -1) diff --git a/src/ert/gui/summarypanel.py b/src/ert/gui/summarypanel.py index 3eebbae6578..0258b3ca1b4 100644 --- a/src/ert/gui/summarypanel.py +++ b/src/ert/gui/summarypanel.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING, Any -from qtpy.QtCore import Qt -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt +from PySide6.QtWidgets import ( QFrame, QGridLayout, QHBoxLayout, diff --git a/src/ert/gui/tools/design_matrix/design_matrix_panel.py b/src/ert/gui/tools/design_matrix/design_matrix_panel.py index e92e81063c6..81e79203441 100644 --- a/src/ert/gui/tools/design_matrix/design_matrix_panel.py +++ b/src/ert/gui/tools/design_matrix/design_matrix_panel.py @@ -1,6 +1,6 @@ import pandas as pd -from qtpy.QtGui import QStandardItem, QStandardItemModel -from qtpy.QtWidgets import QDialog, QTableView, QVBoxLayout, QWidget +from PySide6.QtGui import QStandardItem, QStandardItemModel +from PySide6.QtWidgets import QDialog, QTableView, QVBoxLayout, QWidget class DesignMatrixPanel(QDialog): @@ -15,7 +15,7 @@ def __init__( self.setWindowTitle(f"Design matrix parameters from {filename}") table_view = QTableView(self) - table_view.setEditTriggers(QTableView.NoEditTriggers) + table_view.setEditTriggers(QTableView.EditTrigger.NoEditTriggers) self.model = self.create_model(design_matrix_df) table_view.setModel(self.model) diff --git a/src/ert/gui/tools/event_viewer/panel.py b/src/ert/gui/tools/event_viewer/panel.py index 3dfd06fb654..017f5c38458 100644 --- a/src/ert/gui/tools/event_viewer/panel.py +++ b/src/ert/gui/tools/event_viewer/panel.py @@ -2,9 +2,9 @@ from collections.abc import Iterator from contextlib import contextmanager -from qtpy import QtCore -from qtpy.QtCore import QObject -from qtpy.QtWidgets import QPlainTextEdit, QVBoxLayout +from PySide6 import QtCore +from PySide6.QtCore import QObject +from PySide6.QtWidgets import QPlainTextEdit, QVBoxLayout from ert.gui.tools.search_bar import SearchBar diff --git a/src/ert/gui/tools/event_viewer/tool.py b/src/ert/gui/tools/event_viewer/tool.py index c083b06a79d..de581d58494 100644 --- a/src/ert/gui/tools/event_viewer/tool.py +++ b/src/ert/gui/tools/event_viewer/tool.py @@ -1,5 +1,5 @@ -from qtpy.QtCore import QObject, Slot -from qtpy.QtGui import QIcon +from PySide6.QtCore import QObject, Slot +from PySide6.QtGui import QIcon from ert.gui.tools import Tool diff --git a/src/ert/gui/tools/export/export_panel.py b/src/ert/gui/tools/export/export_panel.py index 1086f5ae66e..4cf62f5ecc0 100644 --- a/src/ert/gui/tools/export/export_panel.py +++ b/src/ert/gui/tools/export/export_panel.py @@ -3,7 +3,7 @@ import json from typing import TYPE_CHECKING -from qtpy.QtWidgets import QCheckBox, QWidget +from PySide6.QtWidgets import QCheckBox, QWidget from ert.gui.ertwidgets import CustomDialog, ListEditBox, PathChooser, PathModel diff --git a/src/ert/gui/tools/export/export_tool.py b/src/ert/gui/tools/export/export_tool.py index ad277b756fb..01f96e3061f 100644 --- a/src/ert/gui/tools/export/export_tool.py +++ b/src/ert/gui/tools/export/export_tool.py @@ -3,8 +3,8 @@ import logging from typing import TYPE_CHECKING, Any, cast, no_type_check -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QMessageBox, QWidget +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QMessageBox, QWidget if TYPE_CHECKING: from ert.config import ErtConfig @@ -54,7 +54,7 @@ def _run_export(self, params: list[Any]) -> None: cast(QWidget, self.parent()), "Success", """Export completed!""", - QMessageBox.Ok, + QMessageBox.StandardButton.Ok, ) except UserWarning as usrwarning: logger.error(str(usrwarning)) @@ -62,5 +62,5 @@ def _run_export(self, params: list[Any]) -> None: cast(QWidget, self.parent()), "Failure", f"Export failed with the following message:\n{usrwarning}", - QMessageBox.Ok, + QMessageBox.StandardButton.Ok, ) diff --git a/src/ert/gui/tools/file/file_dialog.py b/src/ert/gui/tools/file/file_dialog.py index 8ab5d21d60b..a45641a85a5 100644 --- a/src/ert/gui/tools/file/file_dialog.py +++ b/src/ert/gui/tools/file/file_dialog.py @@ -1,8 +1,8 @@ from math import floor -from qtpy.QtCore import QSize, Qt, QThread -from qtpy.QtGui import QClipboard, QFontDatabase, QTextCursor, QTextOption -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Qt, QThread +from PySide6.QtGui import QClipboard, QFontDatabase, QTextCursor, QTextOption +from PySide6.QtWidgets import ( QApplication, QDialog, QDialogButtonBox, @@ -60,10 +60,10 @@ def __init__( self._file = open(file_name, encoding="utf-8") # noqa: SIM115 except OSError as error: self._mb = QMessageBox( - QMessageBox.Critical, + QMessageBox.Icon.Critical, "Error opening file", - error.strerror, - QMessageBox.Ok, + error.strerror if error.strerror else "", + QMessageBox.StandardButton.Ok, self, ) self._mb.finished.connect(self.accept) @@ -72,7 +72,7 @@ def __init__( self._view = QPlainTextEdit() self._view.setReadOnly(True) - self._view.setWordWrapMode(QTextOption.NoWrap) + self._view.setWordWrapMode(QTextOption.WrapMode.NoWrap) # for moving the actual slider scroll_bar = self._view.verticalScrollBar() assert scroll_bar is not None @@ -80,7 +80,7 @@ def __init__( # for mouse wheel and keyboard arrows scroll_bar.valueChanged.connect(self._update_cursor) - self._view.setFont(QFontDatabase.systemFont(QFontDatabase.FixedFont)) + self._view.setFont(QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)) self._search_bar = SearchBar(self._view) self._follow_mode = False @@ -95,19 +95,19 @@ def _quit_thread(self) -> None: self._file.close() def _init_layout(self) -> None: - dialog_buttons = QDialogButtonBox(QDialogButtonBox.Ok) + dialog_buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) dialog_buttons.accepted.connect(self.accept) self._copy_all_button = dialog_buttons.addButton( "Copy all", - QDialogButtonBox.ActionRole, + QDialogButtonBox.ButtonRole.ActionRole, ) assert self._copy_all_button is not None self._copy_all_button.clicked.connect(self._copy_all) self._follow_button = dialog_buttons.addButton( "Follow", - QDialogButtonBox.ActionRole, + QDialogButtonBox.ButtonRole.ActionRole, ) assert self._follow_button is not None self._follow_button.setCheckable(True) @@ -151,13 +151,13 @@ def _enable_follow_mode(self, enable: bool) -> None: vertical_scroll_bar.setDisabled(enable) self._follow_mode = enable if enable: - self._view.moveCursor(QTextCursor.End) + self._view.moveCursor(QTextCursor.MoveOperation.End) self._view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self._view.setTextInteractionFlags(Qt.TextInteractionFlag.NoTextInteraction) else: self._view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self._view.setTextInteractionFlags( - Qt.TextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) + Qt.TextInteractionFlag.TextSelectableByMouse | Qt.TextInteractionFlag.TextSelectableByKeyboard ) @@ -166,7 +166,7 @@ def _append_text(self, text: str) -> None: if text[-1:] == "\n": text = text[:-1] if self._follow_mode: - self._view.moveCursor(QTextCursor.End) + self._view.moveCursor(QTextCursor.MoveOperation.End) self._view.appendPlainText(text) self.adjustSize() diff --git a/src/ert/gui/tools/file/file_update_worker.py b/src/ert/gui/tools/file/file_update_worker.py index 25b9343853d..c1b489422dc 100644 --- a/src/ert/gui/tools/file/file_update_worker.py +++ b/src/ert/gui/tools/file/file_update_worker.py @@ -1,6 +1,6 @@ from io import TextIOWrapper -from qtpy.QtCore import QObject, QTimer, Signal, Slot +from PySide6.QtCore import QObject, QTimer, Signal, Slot class FileUpdateWorker(QObject): diff --git a/src/ert/gui/tools/load_results/load_results_panel.py b/src/ert/gui/tools/load_results/load_results_panel.py index a0cb44e0936..3322db8519f 100644 --- a/src/ert/gui/tools/load_results/load_results_panel.py +++ b/src/ert/gui/tools/load_results/load_results_panel.py @@ -1,7 +1,7 @@ from __future__ import annotations -from qtpy.QtCore import Qt, Signal -from qtpy.QtWidgets import QFormLayout, QLabel, QMessageBox, QWidget +from PySide6.QtCore import Qt, Signal +from PySide6.QtWidgets import QFormLayout, QLabel, QMessageBox, QWidget from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import ( diff --git a/src/ert/gui/tools/load_results/load_results_tool.py b/src/ert/gui/tools/load_results/load_results_tool.py index faf5a4b58bd..10a8d3ae048 100644 --- a/src/ert/gui/tools/load_results/load_results_tool.py +++ b/src/ert/gui/tools/load_results/load_results_tool.py @@ -1,6 +1,6 @@ from typing import Any -from qtpy.QtGui import QIcon +from PySide6.QtGui import QIcon from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import ClosableDialog diff --git a/src/ert/gui/tools/manage_experiments/manage_experiments_panel.py b/src/ert/gui/tools/manage_experiments/manage_experiments_panel.py index 4fe9d8b34bb..4ceb5c1c0d4 100644 --- a/src/ert/gui/tools/manage_experiments/manage_experiments_panel.py +++ b/src/ert/gui/tools/manage_experiments/manage_experiments_panel.py @@ -1,9 +1,9 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING -from qtpy.QtCore import QEvent, QObject, Qt -from qtpy.QtWidgets import ( +from PySide6.QtCore import QEvent, QObject, Qt +from PySide6.QtWidgets import ( QHBoxLayout, QLabel, QPushButton, @@ -110,7 +110,7 @@ def _add_initialize_from_scratch_tab(self) -> None: initialize_button.setMaximumWidth(150) @showWaitCursorWhileWaiting - def initialize_from_scratch(_: Any) -> None: + def initialize_from_scratch() -> None: parameters = parameter_model.getSelectedItems() sample_prior( ensemble=ensemble_selector.currentData(), @@ -138,7 +138,7 @@ def update_button_state() -> None: self.addTab(panel, "Initialize from scratch") - def eventFilter(self, a0: QObject | None, a1: QEvent | None) -> bool: - if a1 is not None and a1.type() == QEvent.Type.Close: + def eventFilter(self, watched: QObject, event: QEvent) -> bool: + if event is not None and event.type() == QEvent.Type.Close: self.notifier.emitErtChange() - return super().eventFilter(a0, a1) + return super().eventFilter(watched, event) diff --git a/src/ert/gui/tools/manage_experiments/storage_info_widget.py b/src/ert/gui/tools/manage_experiments/storage_info_widget.py index 2d845312f4f..652eb805b39 100644 --- a/src/ert/gui/tools/manage_experiments/storage_info_widget.py +++ b/src/ert/gui/tools/manage_experiments/storage_info_widget.py @@ -6,8 +6,8 @@ import yaml from matplotlib.backends.backend_qt5agg import FigureCanvas # type: ignore from matplotlib.figure import Figure -from qtpy.QtCore import Qt, Slot -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt, Slot +from PySide6.QtWidgets import ( QFrame, QHBoxLayout, QLabel, diff --git a/src/ert/gui/tools/manage_experiments/storage_model.py b/src/ert/gui/tools/manage_experiments/storage_model.py index 54ac392adfa..24462969cf1 100644 --- a/src/ert/gui/tools/manage_experiments/storage_model.py +++ b/src/ert/gui/tools/manage_experiments/storage_model.py @@ -3,8 +3,15 @@ from uuid import UUID import humanize -from qtpy.QtCore import QAbstractItemModel, QModelIndex, QObject, Qt, Slot -from qtpy.QtWidgets import QApplication +from PySide6.QtCore import ( + QAbstractItemModel, + QModelIndex, + QObject, + QPersistentModelIndex, + Qt, + Slot, +) +from PySide6.QtWidgets import QApplication from typing_extensions import override from ert.storage import Ensemble, Experiment, Storage @@ -164,31 +171,37 @@ def _load_storage(self, storage: Storage) -> None: self._children.append(ex) @override - def columnCount(self, parent: QModelIndex | None = None) -> int: + def columnCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: return _NUM_COLUMNS @override - def rowCount(self, parent: QModelIndex | None = None) -> int: + def rowCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: if parent is None: parent = QModelIndex() if parent.isValid(): if isinstance(parent.internalPointer(), RealizationModel): return 0 - return len(parent.internalPointer()._children) + return len(parent.internalPointer()._children) # type: ignore else: return len(self._children) @overload - def parent(self, child: QModelIndex) -> QModelIndex: ... + def parent(self) -> QObject: ... @overload - def parent(self) -> QObject | None: ... + def parent(self, child: QModelIndex | QPersistentModelIndex) -> QModelIndex: ... @override - def parent(self, child: QModelIndex | None = None) -> QObject | None: + def parent( + self, child: QModelIndex | QPersistentModelIndex | None = None + ) -> QObject | QModelIndex: if child is None or not child.isValid(): return QModelIndex() child_item = child.internalPointer() - parentItem = child_item._parent + parentItem = child_item._parent # type: ignore if parentItem == self: return QModelIndex() @@ -208,23 +221,30 @@ def headerData( return _COLUMN_TEXT[_Column(section)] @override - def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole) -> Any: + def data( + self, + index: QModelIndex | QPersistentModelIndex, + role: int = Qt.ItemDataRole.DisplayRole, + ) -> Any: if not index.isValid(): return None - return index.internalPointer().data(index, role) + return index.internalPointer().data(index, role) # type:ignore @override def index( - self, row: int, column: int, parent: QModelIndex | None = None + self, + row: int, + column: int, + parent: QModelIndex | QPersistentModelIndex | None = None, ) -> QModelIndex: if parent is None: parent = QModelIndex() - parentItem = parent.internalPointer() if parent.isValid() else self - try: - childItem = parentItem._children[row] - except KeyError: - childItem = None - if childItem: - return self.createIndex(row, column, childItem) + + model = cast(ChildModel, parent.internalPointer()) if parent.isValid() else self + if type(model) is not RealizationModel: + model = cast(StorageModel | EnsembleModel | ExperimentModel, model) + if len(model._children) > row: + childItem = model._children[row] + return self.createIndex(row, column, childItem) return QModelIndex() diff --git a/src/ert/gui/tools/manage_experiments/storage_widget.py b/src/ert/gui/tools/manage_experiments/storage_widget.py index a062254607a..5dcafa640b0 100644 --- a/src/ert/gui/tools/manage_experiments/storage_widget.py +++ b/src/ert/gui/tools/manage_experiments/storage_widget.py @@ -1,16 +1,17 @@ from collections.abc import Callable -from qtpy.QtCore import ( +from PySide6.QtCore import ( QAbstractItemModel, QItemSelectionModel, QModelIndex, + QPersistentModelIndex, QSize, QSortFilterProxyModel, Qt, Signal, ) -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import ( +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import ( QHBoxLayout, QLineEdit, QToolButton, @@ -64,9 +65,13 @@ def __init__(self, model: QAbstractItemModel): super().__init__() self.setSourceModel(model) - def lessThan(self, left: QModelIndex, right: QModelIndex) -> bool: - left_data = left.data() - right_data = right.data() + def lessThan( + self, + source_left: QModelIndex | QPersistentModelIndex, + source_right: QModelIndex | QPersistentModelIndex, + ) -> bool: + left_data = source_left.data() + right_data = source_right.data() if ( isinstance(left_data, str) @@ -79,7 +84,7 @@ def lessThan(self, left: QModelIndex, right: QModelIndex) -> bool: return left_realization_number < right_realization_number - return super().lessThan(left, right) + return super().lessThan(source_left, source_right) class StorageWidget(QWidget): diff --git a/src/ert/gui/tools/plot/customize/color_chooser.py b/src/ert/gui/tools/plot/customize/color_chooser.py index de8f7495915..6bce641b20b 100644 --- a/src/ert/gui/tools/plot/customize/color_chooser.py +++ b/src/ert/gui/tools/plot/customize/color_chooser.py @@ -1,6 +1,6 @@ -from qtpy.QtCore import QRect, QSize, Signal, Slot -from qtpy.QtGui import QColor, QMouseEvent, QPainter, QPaintEvent -from qtpy.QtWidgets import QColorDialog, QFrame +from PySide6.QtCore import QRect, QSize, Signal, Slot +from PySide6.QtGui import QColor, QMouseEvent, QPainter, QPaintEvent +from PySide6.QtWidgets import QColorDialog, QFrame class ColorBox(QFrame): @@ -11,7 +11,7 @@ class ColorBox(QFrame): def __init__(self, size: int = 15) -> None: QFrame.__init__(self) - self.setFrameStyle(QFrame.Panel | QFrame.Sunken) + self.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Sunken) self.setMaximumSize(QSize(size, size)) self.setMinimumSize(QSize(size, size)) @@ -30,7 +30,7 @@ def update_color(self, color: QColor) -> None: def show_color_dialog(self) -> None: color_dialog = QColorDialog(self._color, self) color_dialog.setWindowTitle("Select color") - color_dialog.setOption(QColorDialog.ShowAlphaChannel) + color_dialog.setOption(QColorDialog.ColorDialogOption.ShowAlphaChannel) color_dialog.accepted.connect( lambda: self.colorChanged.emit(color_dialog.selectedColor()) ) @@ -47,7 +47,7 @@ def color(self, color: tuple[str, float]) -> None: self._color = new_color self.update() - def paintEvent(self, event: QPaintEvent | None) -> None: + def paintEvent(self, arg__1: QPaintEvent) -> None: """Paints the box""" painter = QPainter(self) rect = self.contentsRect() @@ -65,9 +65,9 @@ def paintEvent(self, event: QPaintEvent | None) -> None: painter.restore() painter.fillRect(rect, self._color) - QFrame.paintEvent(self, event) + QFrame.paintEvent(self, arg__1) - def mouseReleaseEvent(self, event: QMouseEvent | None) -> None: + def mouseReleaseEvent(self, event: QMouseEvent) -> None: if event: self.mouseRelease.emit() return super().mouseReleaseEvent(event) diff --git a/src/ert/gui/tools/plot/customize/customization_view.py b/src/ert/gui/tools/plot/customize/customization_view.py index 24dd5530e00..e8f2829e532 100644 --- a/src/ert/gui/tools/plot/customize/customization_view.py +++ b/src/ert/gui/tools/plot/customize/customization_view.py @@ -3,7 +3,7 @@ from collections.abc import Callable from typing import TYPE_CHECKING, Any -from qtpy.QtWidgets import ( +from PySide6.QtWidgets import ( QCheckBox, QFormLayout, QHBoxLayout, @@ -28,7 +28,7 @@ def __init__(self) -> None: self.setLayout(self._layout) self._widgets: dict[str, QWidget] = {} - def addRow(self, title: str | None, widget: QWidget | None) -> None: + def addRow(self, title: str, widget: QWidget) -> None: self._layout.addRow(title, widget) def addLineEdit( @@ -142,7 +142,7 @@ def addSpacing(self, pixels: int = 10) -> None: def addHeading(self, title: str) -> None: self.addSpacing(10) - self._layout.addRow(title, None) + self._layout.addRow(title, None) # type: ignore self.addSpacing(1) def __getitem__(self, item: str) -> QWidget: diff --git a/src/ert/gui/tools/plot/customize/customize_plot_dialog.py b/src/ert/gui/tools/plot/customize/customize_plot_dialog.py index ca4bbf520a4..7e6c8239530 100644 --- a/src/ert/gui/tools/plot/customize/customize_plot_dialog.py +++ b/src/ert/gui/tools/plot/customize/customize_plot_dialog.py @@ -3,9 +3,9 @@ from collections.abc import Iterable, Iterator from typing import TYPE_CHECKING -from qtpy.QtCore import QObject, Qt, Signal -from qtpy.QtGui import QIcon, QKeyEvent -from qtpy.QtWidgets import ( +from PySide6.QtCore import QObject, Qt, Signal +from PySide6.QtGui import QIcon, QKeyEvent +from PySide6.QtWidgets import ( QDialog, QHBoxLayout, QLayout, @@ -197,7 +197,8 @@ def __init__( key: str | None = "", ) -> None: QDialog.__init__(self, parent) - self.setWindowTitle(title) + if title is not None: + self.setWindowTitle(title) self.current_key = key self._key_defs = key_defs @@ -205,7 +206,7 @@ def __init__( self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # type: ignore self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) # type: ignore - self._tab_map: dict[str, QWidget] = {} + self._tab_map: dict[str, CustomizationView] = {} self._tab_order: list[str] = [] layout = QVBoxLayout() @@ -235,13 +236,15 @@ def __init__( self._copy_from_button = QToolButton() self._copy_from_button.setIcon(QIcon("img:download.svg")) self._copy_from_button.setToolTip("Copy settings from another key") - self._copy_from_button.setPopupMode(QToolButton.InstantPopup) + self._copy_from_button.setPopupMode( + QToolButton.ToolButtonPopupMode.InstantPopup + ) self._copy_from_button.setEnabled(False) self._copy_to_button = QToolButton() self._copy_to_button.setIcon(QIcon("img:upload.svg")) self._copy_to_button.setToolTip("Copy current plot settings to other keys") - self._copy_to_button.setPopupMode(QToolButton.InstantPopup) + self._copy_to_button.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) self._copy_to_button.clicked.connect(self.initiateCopyStyleToDialog) self._copy_to_button.setEnabled(True) @@ -283,7 +286,7 @@ def initiateCopyStyleToDialog(self) -> None: if dialog.exec_(): self.copySettingsToOthers.emit(dialog.getSelectedKeys()) - def addCopyableKey(self, key: str | QListWidgetItem | None) -> None: + def addCopyableKey(self, key: str | QListWidgetItem) -> None: self._popup_list.addItem(key) def keySelected(self, list_widget_item: QListWidgetItem) -> None: @@ -292,15 +295,17 @@ def keySelected(self, list_widget_item: QListWidgetItem) -> None: def currentPlotKeyChanged(self, new_key: str | None) -> None: self.current_key = new_key - def keyPressEvent(self, a0: QKeyEvent | None) -> None: + def keyPressEvent(self, arg__1: QKeyEvent | None) -> None: # Hide when pressing Escape instead of QDialog.keyPressEvent(KeyEscape) # which closes the dialog - if a0 is not None and a0.key() == Qt.Key.Key_Escape: + if arg__1 is not None and arg__1.key() == Qt.Key.Key_Escape: self.hide() else: - QDialog.keyPressEvent(self, a0) + QDialog.keyPressEvent(self, arg__1) # type: ignore[arg-type] - def addTab(self, attribute_name: str, title: str, widget: QWidget) -> None: + def addTab( + self, attribute_name: str, title: str, widget: CustomizationView + ) -> None: self._tabs.addTab(widget, title) self._tab_map[attribute_name] = widget self._tab_order.append(attribute_name) @@ -308,7 +313,7 @@ def addTab(self, attribute_name: str, title: str, widget: QWidget) -> None: def __getitem__(self, item: str) -> CustomizationView: return self._tab_map[item] - def __iter__(self) -> Iterator[QWidget]: + def __iter__(self) -> Iterator[CustomizationView]: for attribute_name in self._tab_order: yield self._tab_map[attribute_name] diff --git a/src/ert/gui/tools/plot/customize/limits_customization_view.py b/src/ert/gui/tools/plot/customize/limits_customization_view.py index fec3e58cccf..b730a433310 100644 --- a/src/ert/gui/tools/plot/customize/limits_customization_view.py +++ b/src/ert/gui/tools/plot/customize/limits_customization_view.py @@ -4,8 +4,8 @@ from datetime import date from typing import TYPE_CHECKING, Any, ClassVar -from qtpy.QtGui import QDoubleValidator, QIntValidator -from qtpy.QtWidgets import QLabel, QStackedWidget, QWidget +from PySide6.QtGui import QDoubleValidator, QIntValidator +from PySide6.QtWidgets import QLabel, QLineEdit, QStackedWidget from ert.gui.tools.plot.plottery import PlotContext, PlotLimits from ert.gui.tools.plot.widgets import ClearableLineEdit, CustomDateEdit @@ -19,12 +19,14 @@ class StackedInput(QStackedWidget): def __init__(self) -> None: QStackedWidget.__init__(self) - self._inputs: dict[str | None, QWidget] = {} + self._inputs: dict[str | None, QLineEdit | QLabel | CustomDateEdit] = {} self._index_map: dict[str | None, int] = {} self.addInput(PlotContext.UNKNOWN_AXIS, QLabel("Fixed")) self._current_name: str | None = PlotContext.UNKNOWN_AXIS - def addInput(self, name: str | None, widget: QWidget) -> None: + def addInput( + self, name: str | None, widget: QLineEdit | QLabel | CustomDateEdit + ) -> None: index = self.addWidget(widget) self._inputs[name] = widget self._index_map[name] = index @@ -102,28 +104,28 @@ def createIntegerLineEdit( def setValue(self, axis_name: str | None, value: Any) -> None: input_ = self._inputs[axis_name] - if axis_name in LimitsStack.NUMBER_AXIS: - if value is None: - input_.setText("") - else: - input_.setText(str(value)) - elif axis_name == PlotContext.DATE_AXIS: + if axis_name in LimitsStack.NUMBER_AXIS and ( + type(input_) is QLineEdit or type(input_) is QLabel + ): + input_.setText(str(value) if value is not None else "") + elif axis_name == PlotContext.DATE_AXIS and type(input_) is CustomDateEdit: input_.setDate(value) def getValue(self, axis_name: str | None) -> float | int | date | None: input_ = self._inputs[axis_name] - result = None - if axis_name in LimitsStack.FLOAT_AXIS: - try: - result = float(input_.text()) - except ValueError: - result = None - elif axis_name in LimitsStack.INT_AXIS: - try: - result = int(input_.text()) - except ValueError: - result = None - elif axis_name == PlotContext.DATE_AXIS: + result: float | int | date | None = None + if type(input_) is QLineEdit or type(input_) is QLabel: + if axis_name in LimitsStack.FLOAT_AXIS: + try: + result = float(input_.text()) + except ValueError: + result = None + elif axis_name in LimitsStack.INT_AXIS: + try: + result = int(input_.text()) + except ValueError: + result = None + elif axis_name == PlotContext.DATE_AXIS and type(input_) is CustomDateEdit: result = input_.date() return result diff --git a/src/ert/gui/tools/plot/customize/statistics_customization_view.py b/src/ert/gui/tools/plot/customize/statistics_customization_view.py index 9fbd4c991db..dcd8df8cf2e 100644 --- a/src/ert/gui/tools/plot/customize/statistics_customization_view.py +++ b/src/ert/gui/tools/plot/customize/statistics_customization_view.py @@ -2,10 +2,10 @@ from typing import TYPE_CHECKING -from qtpy.QtWidgets import QComboBox, QHBoxLayout +from PySide6.QtWidgets import QComboBox, QHBoxLayout from .customization_view import CustomizationView, WidgetProperty -from .style_chooser import STYLESET_AREA +from .style_chooser import STYLESET_AREA, StyleChooser if TYPE_CHECKING: from ert.gui.tools.plot.plottery import PlotConfig @@ -80,7 +80,9 @@ def __init__(self) -> None: "Toggle distribution connection lines visibility.", ) - self["mean_style"].createLabelLayout(layout) + style = self["mean_style"] + assert type(style) is StyleChooser + style.createLabelLayout(layout) def createPresets(self) -> QComboBox: preset_combo = QComboBox() diff --git a/src/ert/gui/tools/plot/customize/style_chooser.py b/src/ert/gui/tools/plot/customize/style_chooser.py index 46bd7a0fa9b..c8a14d00c4b 100644 --- a/src/ert/gui/tools/plot/customize/style_chooser.py +++ b/src/ert/gui/tools/plot/customize/style_chooser.py @@ -1,6 +1,6 @@ from collections.abc import Iterator -from qtpy.QtWidgets import ( +from PySide6.QtWidgets import ( QComboBox, QDoubleSpinBox, QHBoxLayout, diff --git a/src/ert/gui/tools/plot/customize/style_customization_view.py b/src/ert/gui/tools/plot/customize/style_customization_view.py index db611287f8e..0719c8ddb01 100644 --- a/src/ert/gui/tools/plot/customize/style_customization_view.py +++ b/src/ert/gui/tools/plot/customize/style_customization_view.py @@ -1,10 +1,10 @@ from typing import TYPE_CHECKING -from qtpy.QtWidgets import QHBoxLayout +from PySide6.QtWidgets import QHBoxLayout from .color_chooser import ColorBox from .customization_view import CustomizationView, WidgetProperty -from .style_chooser import STYLESET_TOGGLE +from .style_chooser import STYLESET_TOGGLE, StyleChooser if TYPE_CHECKING: from ert.gui.tools.plot.plottery import PlotConfig @@ -36,7 +36,9 @@ def __init__(self) -> None: line_style_set=STYLESET_TOGGLE, ) - self["default_style"].createLabelLayout(layout) + style = self["default_style"] + assert type(style) is StyleChooser + style.createLabelLayout(layout) self.addSpacing(10) diff --git a/src/ert/gui/tools/plot/data_type_keys_list_model.py b/src/ert/gui/tools/plot/data_type_keys_list_model.py index cc7aae62b75..66fc874fee9 100644 --- a/src/ert/gui/tools/plot/data_type_keys_list_model.py +++ b/src/ert/gui/tools/plot/data_type_keys_list_model.py @@ -1,7 +1,13 @@ from typing import Any, overload -from qtpy.QtCore import QAbstractItemModel, QModelIndex, QObject, Qt -from qtpy.QtGui import QColor, QIcon +from PySide6.QtCore import ( + QAbstractItemModel, + QModelIndex, + QObject, + QPersistentModelIndex, + Qt, +) +from PySide6.QtGui import QColor, QIcon from typing_extensions import override from .plot_api import PlotApiKeyDefinition @@ -19,28 +25,41 @@ def __init__(self, keys: list[PlotApiKeyDefinition]): @override def index( - self, row: int, column: int, parent: QModelIndex | None = None + self, + row: int, + column: int, + parent: QModelIndex | QPersistentModelIndex | None = None, ) -> QModelIndex: return self.createIndex(row, column) @overload - def parent(self, child: QModelIndex) -> QModelIndex: ... + def parent(self) -> QObject: ... @overload - def parent(self) -> QObject | None: ... + def parent(self, child: QModelIndex | QPersistentModelIndex) -> QModelIndex: ... @override - def parent(self, child: QModelIndex | None = None) -> QObject | None: + def parent( + self, child: QModelIndex | QPersistentModelIndex | None = None + ) -> QObject | QModelIndex: return QModelIndex() @override - def rowCount(self, parent: QModelIndex | None = None) -> int: + def rowCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: return len(self._keys) @override - def columnCount(self, parent: QModelIndex | None = None) -> int: + def columnCount( + self, parent: QModelIndex | QPersistentModelIndex | None = None + ) -> int: return 1 @override - def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole) -> Any: + def data( + self, + index: QModelIndex | QPersistentModelIndex, + role: int = Qt.ItemDataRole.DisplayRole, + ) -> Any: assert isinstance(index, QModelIndex) if index.isValid(): diff --git a/src/ert/gui/tools/plot/data_type_keys_widget.py b/src/ert/gui/tools/plot/data_type_keys_widget.py index 31e9dc26671..c21421cea91 100644 --- a/src/ert/gui/tools/plot/data_type_keys_widget.py +++ b/src/ert/gui/tools/plot/data_type_keys_widget.py @@ -1,6 +1,6 @@ -from qtpy.QtCore import QSize, Signal -from qtpy.QtGui import QColor, QIcon, QPainter, QPaintEvent -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Signal +from PySide6.QtGui import QColor, QIcon, QPainter, QPaintEvent +from PySide6.QtWidgets import ( QHBoxLayout, QLabel, QListView, @@ -56,7 +56,7 @@ def __init__(self, legend: str | None, color: QColor): layout.setContentsMargins(0, 0, 0, 0) self.legend_marker = _LegendMarker(color) - self.legend_marker.setToolTip(legend) + self.legend_marker.setToolTip(legend if legend else "") layout.addWidget(self.legend_marker) self.legend_label = QLabel(legend) @@ -127,7 +127,7 @@ def selectDefault(self) -> None: self.data_type_keys_widget.setCurrentIndex(self.filter_model.index(0, 0)) def setSearchString(self, filter_: str | None) -> None: - self.filter_model.setFilterFixedString(filter_) + self.filter_model.setFilterFixedString(filter_ if filter_ else "") def showFilterPopup(self) -> None: self.__filter_popup.show() diff --git a/src/ert/gui/tools/plot/data_type_proxy_model.py b/src/ert/gui/tools/plot/data_type_proxy_model.py index 09a18b77d76..e6d98852835 100644 --- a/src/ert/gui/tools/plot/data_type_proxy_model.py +++ b/src/ert/gui/tools/plot/data_type_proxy_model.py @@ -2,7 +2,13 @@ from typing import TYPE_CHECKING -from qtpy.QtCore import QModelIndex, QObject, QSortFilterProxyModel, Qt +from PySide6.QtCore import ( + QModelIndex, + QObject, + QPersistentModelIndex, + QSortFilterProxyModel, + Qt, +) if TYPE_CHECKING: from .data_type_keys_list_model import DataTypeKeysListModel @@ -21,7 +27,9 @@ def __init__(self, parent: QObject | None, model: DataTypeKeysListModel) -> None self.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) self.setSourceModel(model) - def filterAcceptsRow(self, source_row: int, source_parent: QModelIndex) -> bool: + def filterAcceptsRow( + self, source_row: int, source_parent: QModelIndex | QPersistentModelIndex + ) -> bool: show = QSortFilterProxyModel.filterAcceptsRow(self, source_row, source_parent) if show: diff --git a/src/ert/gui/tools/plot/plot_ensemble_selection_widget.py b/src/ert/gui/tools/plot/plot_ensemble_selection_widget.py index e72147d93ff..f698d3a942d 100644 --- a/src/ert/gui/tools/plot/plot_ensemble_selection_widget.py +++ b/src/ert/gui/tools/plot/plot_ensemble_selection_widget.py @@ -1,8 +1,8 @@ from collections.abc import Iterator from typing import Any -from qtpy.QtCore import QModelIndex, QSize, Qt, Signal -from qtpy.QtGui import ( +from PySide6.QtCore import QModelIndex, QPersistentModelIndex, QSize, Qt, Signal +from PySide6.QtGui import ( QBrush, QColor, QCursor, @@ -12,7 +12,7 @@ QPainter, QPen, ) -from qtpy.QtWidgets import ( +from PySide6.QtWidgets import ( QAbstractItemView, QListWidget, QListWidgetItem, @@ -67,7 +67,7 @@ def __init__(self, ensembles: list[EnsembleObject]): if (viewport := self.viewport()) is not None: viewport.setMouseTracking(True) - self.setDragDropMode(QAbstractItemView.InternalMove) + self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) self.setItemDelegate(CustomItemDelegate()) self.itemClicked.connect(self.slot_toggle_plot) @@ -81,14 +81,14 @@ def _iter() -> Iterator[EnsembleObject]: return list(_iter()) - def mouseMoveEvent(self, e: QMouseEvent | None) -> None: + def mouseMoveEvent(self, e: QMouseEvent) -> None: super().mouseMoveEvent(e) if e is not None and self.itemAt(e.pos()): self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) else: self.setCursor(QCursor(Qt.CursorShape.ArrowCursor)) - def dropEvent(self, event: QDropEvent | None) -> None: + def dropEvent(self, event: QDropEvent) -> None: super().dropEvent(event) self.ensembleSelectionListChanged.emit() @@ -116,17 +116,17 @@ def paint( self, painter: QPainter | None, option: QStyleOptionViewItem, - index: QModelIndex, + index: QModelIndex | QPersistentModelIndex, ) -> None: if painter is None: return - painter.setRenderHint(QPainter.Antialiasing) + painter.setRenderHint(QPainter.RenderHint.Antialiasing) pen_color = QColor("black") background_color = QColor("lightgray") selected_background_color = QColor("lightblue") - rect = option.rect.adjusted(2, 2, -2, -2) + rect = option.rect.adjusted(2, 2, -2, -2) # type:ignore[attr-defined] painter.setPen(QPen(pen_color)) if index.data(Qt.ItemDataRole.CheckStateRole): @@ -139,6 +139,6 @@ def paint( text_rect = rect.adjusted(self.swap_pixmap.width() + 4, 4, -4, -4) painter.drawText(text_rect, Qt.AlignmentFlag.AlignLeft, index.data()) - cursor_x = option.rect.left() + self.swap_pixmap.width() - 14 - cursor_y = int(option.rect.center().y() - (self.swap_pixmap.height() / 2)) + cursor_x = option.rect.left() + self.swap_pixmap.width() - 14 # type:ignore[attr-defined] + cursor_y = int(option.rect.center().y() - (self.swap_pixmap.height() / 2)) # type:ignore[attr-defined] painter.drawPixmap(cursor_x, cursor_y, self.swap_pixmap) diff --git a/src/ert/gui/tools/plot/plot_widget.py b/src/ert/gui/tools/plot/plot_widget.py index a94e5f60633..e5aa3b656b0 100644 --- a/src/ert/gui/tools/plot/plot_widget.py +++ b/src/ert/gui/tools/plot/plot_widget.py @@ -10,9 +10,9 @@ NavigationToolbar2QT, ) from matplotlib.figure import Figure -from qtpy.QtCore import QStringListModel, Qt, Signal, Slot -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QAction, QComboBox, QVBoxLayout, QWidget, QWidgetAction +from PySide6.QtCore import QStringListModel, Qt, Signal, Slot +from PySide6.QtGui import QAction, QIcon +from PySide6.QtWidgets import QComboBox, QVBoxLayout, QWidget, QWidgetAction from .plot_api import EnsembleObject diff --git a/src/ert/gui/tools/plot/plot_window.py b/src/ert/gui/tools/plot/plot_window.py index 469fd503d7a..02d46968fee 100644 --- a/src/ert/gui/tools/plot/plot_window.py +++ b/src/ert/gui/tools/plot/plot_window.py @@ -6,8 +6,8 @@ import pandas as pd from httpx import RequestError from pandas import DataFrame -from qtpy.QtCore import Qt, Slot -from qtpy.QtWidgets import QDockWidget, QMainWindow, QTabWidget, QWidget +from PySide6.QtCore import Qt, Slot +from PySide6.QtWidgets import QDockWidget, QMainWindow, QTabWidget, QWidget from ert.gui.ertwidgets import showWaitCursorWhileWaiting @@ -37,7 +37,7 @@ logger = logging.getLogger(__name__) -from qtpy.QtWidgets import ( +from PySide6.QtWidgets import ( QApplication, QDialog, QHBoxLayout, @@ -179,7 +179,7 @@ def updatePlot(self, layer: int | None = None) -> None: key = key_def.key plot_widget = self._central_tab.currentWidget() - assert plot_widget is not None + assert type(plot_widget) is PlotWidget if plot_widget._plotter.dimensionality == key_def.dimensionality: selected_ensembles = ( @@ -316,7 +316,8 @@ def addDock( dock_widget.setWidget(widget) dock_widget.setAllowedAreas(allowed_areas) dock_widget.setFeatures( - QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable + QDockWidget.DockWidgetFeature.DockWidgetFloatable + | QDockWidget.DockWidgetFeature.DockWidgetMovable ) self.addDockWidget(area, dock_widget) diff --git a/src/ert/gui/tools/plot/widgets/clearable_line_edit.py b/src/ert/gui/tools/plot/widgets/clearable_line_edit.py index 63cfb1120be..7f79a890758 100644 --- a/src/ert/gui/tools/plot/widgets/clearable_line_edit.py +++ b/src/ert/gui/tools/plot/widgets/clearable_line_edit.py @@ -1,6 +1,6 @@ -from qtpy.QtCore import QSize, Qt -from qtpy.QtGui import QColor, QFocusEvent, QIcon, QKeyEvent, QResizeEvent -from qtpy.QtWidgets import QLineEdit, QPushButton, QStyle +from PySide6.QtCore import QSize, Qt +from PySide6.QtGui import QColor, QFocusEvent, QIcon, QKeyEvent, QResizeEvent +from PySide6.QtWidgets import QLineEdit, QPushButton, QStyle class ClearableLineEdit(QLineEdit): @@ -40,7 +40,7 @@ def minimumSizeHint(self) -> QSize: size = QLineEdit.minimumSizeHint(self) return QSize(size.width() + self._clear_button.width() + 3, size.height()) - def resizeEvent(self, a0: QResizeEvent | None) -> None: + def resizeEvent(self, event: QResizeEvent) -> None: right = self.rect().right() style = self.style() assert style is not None @@ -49,7 +49,7 @@ def resizeEvent(self, a0: QResizeEvent | None) -> None: right - frame_width - self._clear_button.width(), int((self.height() - self._clear_button.height()) / 2), ) - QLineEdit.resizeEvent(self, a0) + QLineEdit.resizeEvent(self, event) def clearButtonClicked(self) -> None: self.setText("") @@ -70,29 +70,29 @@ def hidePlaceHolder(self) -> None: palette.setColor(self.foregroundRole(), self._active_color) self.setPalette(palette) - def focusInEvent(self, a0: QFocusEvent | None) -> None: - QLineEdit.focusInEvent(self, a0) + def focusInEvent(self, arg__1: QFocusEvent) -> None: + QLineEdit.focusInEvent(self, arg__1) self.hidePlaceHolder() - def focusOutEvent(self, a0: QFocusEvent | None) -> None: - QLineEdit.focusOutEvent(self, a0) + def focusOutEvent(self, arg__1: QFocusEvent) -> None: + QLineEdit.focusOutEvent(self, arg__1) if not QLineEdit.text(self): self.showPlaceholder() - def keyPressEvent(self, a0: QKeyEvent | None) -> None: - if a0 is not None and a0.key() == Qt.Key.Key_Escape: + def keyPressEvent(self, arg__1: QKeyEvent) -> None: + if arg__1 is not None and arg__1.key() == Qt.Key.Key_Escape: self.clear() self.clearFocus() - a0.accept() + arg__1.accept() - QLineEdit.keyPressEvent(self, a0) + QLineEdit.keyPressEvent(self, arg__1) - def setText(self, a0: str | None) -> None: + def setText(self, arg__1: str | None) -> None: self.hidePlaceHolder() - QLineEdit.setText(self, a0) + QLineEdit.setText(self, arg__1) - if len(str(a0)) == 0 and not self.hasFocus(): + if len(str(arg__1)) == 0 and not self.hasFocus(): self.showPlaceholder() def text(self) -> str: diff --git a/src/ert/gui/tools/plot/widgets/copy_style_to_dialog.py b/src/ert/gui/tools/plot/widgets/copy_style_to_dialog.py index 059a5500566..7721aea19e0 100644 --- a/src/ert/gui/tools/plot/widgets/copy_style_to_dialog.py +++ b/src/ert/gui/tools/plot/widgets/copy_style_to_dialog.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING, Any -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import ( +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import ( QDialog, QFormLayout, QHBoxLayout, diff --git a/src/ert/gui/tools/plot/widgets/custom_date_edit.py b/src/ert/gui/tools/plot/widgets/custom_date_edit.py index 27779469f46..4c1346322b2 100644 --- a/src/ert/gui/tools/plot/widgets/custom_date_edit.py +++ b/src/ert/gui/tools/plot/widgets/custom_date_edit.py @@ -1,8 +1,8 @@ import datetime -from qtpy.QtCore import QDate -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import ( +from PySide6.QtCore import QDate +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import ( QCalendarWidget, QHBoxLayout, QMenu, @@ -20,7 +20,7 @@ def __init__(self) -> None: self._line_edit = ClearableLineEdit() self._calendar_button = QToolButton() - self._calendar_button.setPopupMode(QToolButton.InstantPopup) + self._calendar_button.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) self._calendar_button.setFixedSize(26, 26) self._calendar_button.setAutoRaise(True) self._calendar_button.setIcon(QIcon("img:calendar_date_range.svg")) @@ -45,7 +45,7 @@ def __init__(self) -> None: def setDate(self, date: datetime.date | QDate) -> None: if isinstance(date, datetime.date): - date = QDate(date.year, date.month, date.day) # type: ignore + date = QDate(date.year, date.month, date.day) if date is not None and date.isValid(): self._line_edit.setText(str(date.toString("yyyy-MM-dd"))) diff --git a/src/ert/gui/tools/plot/widgets/filter_popup.py b/src/ert/gui/tools/plot/widgets/filter_popup.py index fb4a0a91fce..e245626312a 100644 --- a/src/ert/gui/tools/plot/widgets/filter_popup.py +++ b/src/ert/gui/tools/plot/widgets/filter_popup.py @@ -2,9 +2,9 @@ from typing import TYPE_CHECKING -from qtpy.QtCore import QEvent, Qt, Signal -from qtpy.QtGui import QCursor -from qtpy.QtWidgets import ( +from PySide6.QtCore import QEvent, Qt, Signal +from PySide6.QtGui import QCursor +from PySide6.QtWidgets import ( QCheckBox, QDialog, QFrame, @@ -38,7 +38,7 @@ def __init__( layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) frame = QFrame() - frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) + frame.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Raised) layout.addWidget(frame) self.__layout = QVBoxLayout() @@ -69,7 +69,7 @@ def toggleItem(checked: bool) -> None: self.__layout.addWidget(check_box) - def leaveEvent(self, event: QEvent | None) -> None: + def leaveEvent(self, event: QEvent) -> None: self.hide() QWidget.leaveEvent(self, event) diff --git a/src/ert/gui/tools/plugins/plugin.py b/src/ert/gui/tools/plugins/plugin.py index c3407720d29..ab6f954a14e 100644 --- a/src/ert/gui/tools/plugins/plugin.py +++ b/src/ert/gui/tools/plugins/plugin.py @@ -6,7 +6,7 @@ from ert import ErtScript if TYPE_CHECKING: - from qtpy.QtWidgets import QWidget + from PySide6.QtWidgets import QWidget from ert.config import ErtPlugin, WorkflowJob from ert.gui.ertnotifier import ErtNotifier diff --git a/src/ert/gui/tools/plugins/plugin_handler.py b/src/ert/gui/tools/plugins/plugin_handler.py index fbced1ad385..d7715dfa4f2 100644 --- a/src/ert/gui/tools/plugins/plugin_handler.py +++ b/src/ert/gui/tools/plugins/plugin_handler.py @@ -6,7 +6,7 @@ from .plugin import Plugin if TYPE_CHECKING: - from qtpy.QtWidgets import QWidget + from PySide6.QtWidgets import QWidget from ert.config import WorkflowJob from ert.gui.ertnotifier import ErtNotifier diff --git a/src/ert/gui/tools/plugins/plugins_tool.py b/src/ert/gui/tools/plugins/plugins_tool.py index 519d120d959..7ebb36507af 100644 --- a/src/ert/gui/tools/plugins/plugins_tool.py +++ b/src/ert/gui/tools/plugins/plugins_tool.py @@ -2,8 +2,8 @@ from typing import TYPE_CHECKING -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QMenu +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QMenu from ert.gui.tools import Tool diff --git a/src/ert/gui/tools/plugins/process_job_dialog.py b/src/ert/gui/tools/plugins/process_job_dialog.py index 38198f8cb89..933b40e591b 100644 --- a/src/ert/gui/tools/plugins/process_job_dialog.py +++ b/src/ert/gui/tools/plugins/process_job_dialog.py @@ -1,8 +1,8 @@ from typing import cast -from qtpy.QtCore import QSize, Qt, Signal -from qtpy.QtGui import QCloseEvent, QKeyEvent, QMovie -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Qt, Signal +from PySide6.QtGui import QCloseEvent, QKeyEvent, QMovie +from PySide6.QtWidgets import ( QDialog, QGridLayout, QHBoxLayout, @@ -31,13 +31,8 @@ def __init__(self, title: str, parent: QWidget | None = None) -> None: self.__parent = parent self.setWindowTitle(title) self.setModal(True) - self.setWindowFlags( - self.windowFlags() - & ~Qt.WindowFlags(Qt.WindowType.WindowContextHelpButtonHint) - ) - self.setWindowFlags( - self.windowFlags() & ~Qt.WindowFlags(Qt.WindowType.WindowCloseButtonHint) - ) + self.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False) + self.setWindowFlag(Qt.WindowType.WindowCloseButtonHint, False) layout = QVBoxLayout() layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize) @@ -88,24 +83,22 @@ def disableCloseButton(self) -> None: def enableCloseButton(self) -> None: self.close_button.setEnabled(True) - def keyPressEvent(self, a0: QKeyEvent | None) -> None: + def keyPressEvent(self, arg__1: QKeyEvent) -> None: # disallow pressing escape to close # when close button is not enabled if ( - self._close_button.isEnabled() - or a0 is None - or a0.key() != Qt.Key.Key_Escape + self.close_button.isEnabled() + or arg__1 is None + or arg__1.key() != Qt.Key.Key_Escape ): - QDialog.keyPressEvent(self, a0) + QDialog.keyPressEvent(self, arg__1) - def closeEvent(self, a0: QCloseEvent | None) -> None: - if a0 is not None: - a0.ignore() + def closeEvent(self, arg__1: QCloseEvent | None) -> None: + if arg__1 is not None: + arg__1.ignore() self.closeButtonPressed.emit() - def __createMsgBox( - self, title: str | None, message: str | None, details: str - ) -> QMessageBox: + def __createMsgBox(self, title: str, message: str, details: str) -> QMessageBox: msg_box = QMessageBox(cast(QWidget | None, self.parent())) msg_box.setText(title) msg_box.setInformativeText(message) @@ -114,26 +107,22 @@ def __createMsgBox( msg_box.setDetailedText(details) horizontal_spacer = QSpacerItem( - 500, 0, QSizePolicy.MinimumExpanding, QSizePolicy.Expanding + 500, 0, QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding ) layout = cast(QGridLayout, msg_box.layout()) layout.addItem(horizontal_spacer, layout.rowCount(), 0, 1, layout.columnCount()) return msg_box - def __presentInformation( - self, title: str | None, message: str | None, details: str - ) -> None: + def __presentInformation(self, title: str, message: str, details: str) -> None: self._msg_box = self.__createMsgBox(title, message, details) - self._msg_box.setIcon(QMessageBox.Information) + self._msg_box.setIcon(QMessageBox.Icon.Information) self._msg_box.exec_() - def __presentError( - self, title: str | None, message: str | None, details: str - ) -> None: + def __presentError(self, title: str, message: str, details: str) -> None: self._msg_box = self.__createMsgBox(title, message, details) - self._msg_box.setIcon(QMessageBox.Critical) + self._msg_box.setIcon(QMessageBox.Icon.Critical) self._msg_box.exec_() @@ -141,11 +130,13 @@ def __confirmCancel(self) -> None: cancel_box = self.__createMsgBox( "Confirm cancel", "Are you sure you want to cancel the running job?", "" ) - cancel_box.setIcon(QMessageBox.Question) - cancel_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + cancel_box.setIcon(QMessageBox.Icon.Question) + cancel_box.setStandardButtons( + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No + ) cancel_box.exec_() cancel = cancel_box.result() - if cancel == QMessageBox.Yes: + if cancel == QMessageBox.StandardButton.Yes: self.cancelConfirmed.emit() diff --git a/src/ert/gui/tools/search_bar/search_bar.py b/src/ert/gui/tools/search_bar/search_bar.py index 59bb5ad6547..f089e5fe5cf 100644 --- a/src/ert/gui/tools/search_bar/search_bar.py +++ b/src/ert/gui/tools/search_bar/search_bar.py @@ -1,6 +1,6 @@ -from qtpy import QtCore -from qtpy.QtGui import QBrush, QColor, QTextCharFormat, QTextCursor -from qtpy.QtWidgets import QBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPlainTextEdit +from PySide6 import QtCore +from PySide6.QtGui import QBrush, QColor, QTextCharFormat, QTextCursor +from PySide6.QtWidgets import QBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPlainTextEdit class SearchBar(QLineEdit): @@ -33,11 +33,14 @@ def search_bar_changed(self, value: str) -> None: ): # Check if the entire term matches self._cursor.movePosition( - QTextCursor.Right, QTextCursor.KeepAnchor, len(value) + QTextCursor.MoveOperation.Right, + QTextCursor.MoveMode.KeepAnchor, + len(value), ) self._cursor.mergeCharFormat(text_format) self._cursor.movePosition( - QTextCursor.NextCharacter, QTextCursor.MoveAnchor + QTextCursor.MoveOperation.NextCharacter, + QTextCursor.MoveMode.MoveAnchor, ) def get_layout(self) -> QBoxLayout: @@ -48,13 +51,17 @@ def get_layout(self) -> QBoxLayout: def select_text(self, start: int, length: int) -> None: self._cursor.setPosition(start) - self._cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, length) + self._cursor.movePosition( + QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, length + ) self._text_box.setTextCursor(self._cursor) def clear_selection(self) -> None: text_format = QTextCharFormat() - self._cursor.setPosition(QTextCursor.Start) - self._cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) + self._cursor.setPosition(0, QTextCursor.MoveMode.MoveAnchor) + self._cursor.movePosition( + QTextCursor.MoveOperation.End, QTextCursor.MoveMode.KeepAnchor + ) text_format.setBackground(QBrush(QColor("white"))) self._cursor.mergeCharFormat(text_format) self._cursor.clearSelection() diff --git a/src/ert/gui/tools/tool.py b/src/ert/gui/tools/tool.py index fc24e4c6f07..564a6b0c333 100644 --- a/src/ert/gui/tools/tool.py +++ b/src/ert/gui/tools/tool.py @@ -1,6 +1,5 @@ -from qtpy.QtCore import QObject -from qtpy.QtGui import QIcon -from qtpy.QtWidgets import QAction +from PySide6.QtCore import QObject +from PySide6.QtGui import QAction, QIcon class Tool: @@ -37,10 +36,10 @@ def trigger(self) -> None: def setParent(self, parent: QObject | None) -> None: self.__parent = parent - self.__action.setParent(parent) + self.__action.setParent(parent) # type: ignore[arg-type] - def parent(self) -> QObject | None: - return self.__parent + def parent(self) -> QObject: + return self.__parent if self.__parent else QObject() def isEnabled(self) -> bool: return self.__enabled diff --git a/src/ert/gui/tools/workflows/run_workflow_widget.py b/src/ert/gui/tools/workflows/run_workflow_widget.py index a258b45afbb..85d0f28a9fe 100644 --- a/src/ert/gui/tools/workflows/run_workflow_widget.py +++ b/src/ert/gui/tools/workflows/run_workflow_widget.py @@ -4,9 +4,9 @@ from collections.abc import Iterable from typing import TYPE_CHECKING -from qtpy.QtCore import QSize, Qt, Signal -from qtpy.QtGui import QIcon, QMovie -from qtpy.QtWidgets import ( +from PySide6.QtCore import QSize, Qt, Signal +from PySide6.QtGui import QIcon, QMovie +from PySide6.QtWidgets import ( QComboBox, QFormLayout, QHBoxLayout, @@ -40,7 +40,7 @@ def __init__(self, config: ErtConfig, notifier: ErtNotifier): layout = QFormLayout() self._workflow_combo = QComboBox() - self._workflow_combo.addItems(sorted(config.workflows.keys(), key=str.lower)) # type: ignore + self._workflow_combo.addItems(sorted(config.workflows.keys(), key=str.lower)) layout.addRow("Workflow", self._workflow_combo) @@ -97,10 +97,10 @@ def cancelWorkflow(self) -> None: self, "Confirm cancel", "Are you sure you want to cancel the running workflow?", - QMessageBox.Yes | QMessageBox.No, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, ) - if cancel == QMessageBox.Yes: + if cancel == QMessageBox.StandardButton.Yes: self._workflow_runner.cancel() if self._running_workflow_dialog is not None: self._running_workflow_dialog.disableCloseButton() diff --git a/src/ert/gui/tools/workflows/workflow_dialog.py b/src/ert/gui/tools/workflows/workflow_dialog.py index 0927b922f4c..5e09bb2766c 100644 --- a/src/ert/gui/tools/workflows/workflow_dialog.py +++ b/src/ert/gui/tools/workflows/workflow_dialog.py @@ -1,6 +1,6 @@ -from qtpy.QtCore import Qt, Signal -from qtpy.QtGui import QKeyEvent -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt, Signal +from PySide6.QtGui import QKeyEvent +from PySide6.QtWidgets import ( QDialog, QHBoxLayout, QLayout, @@ -20,13 +20,8 @@ def __init__( self.setWindowTitle(title) self.setModal(True) - self.setWindowFlags( - self.windowFlags() - & ~Qt.WindowFlags(Qt.WindowType.WindowContextHelpButtonHint) - ) - self.setWindowFlags( - self.windowFlags() & ~Qt.WindowFlags(Qt.WindowType.WindowCloseButtonHint) - ) + self.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False) + self.setWindowFlag(Qt.WindowType.WindowCloseButtonHint, False) layout = QVBoxLayout() layout.setSizeConstraint( @@ -51,12 +46,12 @@ def disableCloseButton(self) -> None: def enableCloseButton(self) -> None: self.close_button.setEnabled(True) - def keyPressEvent(self, a0: QKeyEvent | None) -> None: + def keyPressEvent(self, arg__1: QKeyEvent) -> None: # disallow pressing escape to close # when close button is not enabled if ( - self._close_button.isEnabled() - or a0 is None - or a0.key() != Qt.Key.Key_Escape + self.close_button.isEnabled() + or arg__1 is None + or arg__1.key() != Qt.Key.Key_Escape ): - QDialog.keyPressEvent(self, a0) + QDialog.keyPressEvent(self, arg__1) diff --git a/src/ert/gui/tools/workflows/workflows_tool.py b/src/ert/gui/tools/workflows/workflows_tool.py index 5cc87f44d5f..4512221489f 100644 --- a/src/ert/gui/tools/workflows/workflows_tool.py +++ b/src/ert/gui/tools/workflows/workflows_tool.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING -from qtpy.QtGui import QIcon +from PySide6.QtGui import QIcon from ert.gui.ertwidgets import ClosableDialog from ert.gui.tools import Tool diff --git a/src/ert/resources/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py b/src/ert/resources/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py index 0b603d9b413..a8c0a81e905 100644 --- a/src/ert/resources/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py +++ b/src/ert/resources/workflows/jobs/internal-gui/scripts/gen_data_rft_export.py @@ -7,7 +7,7 @@ import numpy import pandas as pd import polars -from qtpy.QtWidgets import QCheckBox, QWidget +from PySide6.QtWidgets import QCheckBox, QWidget from ert.config import CancelPluginException, ErtPlugin from ert.storage import Storage diff --git a/tests/ert/conftest.py b/tests/ert/conftest.py index 07b847a52de..c69f78d790d 100644 --- a/tests/ert/conftest.py +++ b/tests/ert/conftest.py @@ -13,8 +13,8 @@ import pytest from hypothesis import HealthCheck, settings from hypothesis import strategies as st -from qtpy.QtCore import QDir -from qtpy.QtWidgets import QApplication +from PySide6.QtCore import QDir +from PySide6.QtWidgets import QApplication import _ert.forward_model_runner.cli from _ert.threading import set_signal_handler diff --git a/tests/ert/ui_tests/gui/conftest.py b/tests/ert/ui_tests/gui/conftest.py index bfdddf77a97..e05e288ca0d 100644 --- a/tests/ert/ui_tests/gui/conftest.py +++ b/tests/ert/ui_tests/gui/conftest.py @@ -13,9 +13,8 @@ from unittest.mock import MagicMock, Mock import pytest -from pytestqt.qtbot import QtBot -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import ( +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import ( QApplication, QComboBox, QMessageBox, @@ -23,6 +22,7 @@ QToolButton, QWidget, ) +from pytestqt.qtbot import QtBot from ert.config import ErtConfig from ert.gui.ertwidgets import ClosableDialog @@ -260,7 +260,7 @@ def handle_dialog(): "Evaluate ensemble", }: QTimer.singleShot(500, handle_dialog) - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) if click_done: # The Run dialog opens, click show details and wait until done appears @@ -348,11 +348,11 @@ def handle_popup_dialog(): messagebox = QApplication.activeModalWidget() assert isinstance(messagebox, QMessageBox) assert messagebox.text() == "Successfully loaded all realisations" - ok_button = messagebox.button(QMessageBox.Ok) - qtbot.mouseClick(ok_button, Qt.LeftButton) + ok_button = messagebox.button(QMessageBox.StandardButton.Ok) + qtbot.mouseClick(ok_button, Qt.MouseButton.LeftButton) QTimer.singleShot(2000, handle_popup_dialog) - qtbot.mouseClick(load_button, Qt.LeftButton) + qtbot.mouseClick(load_button, Qt.MouseButton.LeftButton) dialog.close() QTimer.singleShot(1000, handle_load_results_dialog) @@ -364,7 +364,7 @@ def add_experiment_manually( ): button_manage_experiments = gui.findChild(QToolButton, "button_Manage_experiments") assert button_manage_experiments - qtbot.mouseClick(button_manage_experiments, Qt.LeftButton) + qtbot.mouseClick(button_manage_experiments, Qt.MouseButton.LeftButton) experiments_panel = gui.findChild(ManageExperimentsPanel) # Open the create new experiment tab diff --git a/tests/ert/ui_tests/gui/test_csv_export.py b/tests/ert/ui_tests/gui/test_csv_export.py index 7d53cd9a0a5..74694414c67 100644 --- a/tests/ert/ui_tests/gui/test_csv_export.py +++ b/tests/ert/ui_tests/gui/test_csv_export.py @@ -5,8 +5,8 @@ import pandas as pd import pytest -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import QComboBox, QMessageBox, QWidget +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import QComboBox, QMessageBox, QWidget from ert.gui.ertwidgets.listeditbox import ListEditBox from ert.gui.ertwidgets.pathchooser import PathChooser @@ -98,7 +98,7 @@ def run_experiment_via_gui(gui, qtbot): shutil.rmtree("poly_out") run_experiment = get_child(experiment_panel, QWidget, name="run_experiment") - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) run_dialog = wait_for_child(gui, qtbot, RunDialog) qtbot.waitUntil(lambda: run_dialog.is_simulation_done() == True, timeout=20000) diff --git a/tests/ert/ui_tests/gui/test_full_manual_update_workflow.py b/tests/ert/ui_tests/gui/test_full_manual_update_workflow.py index d1784c5ee46..b49bc7440a5 100644 --- a/tests/ert/ui_tests/gui/test_full_manual_update_workflow.py +++ b/tests/ert/ui_tests/gui/test_full_manual_update_workflow.py @@ -2,8 +2,8 @@ import shutil import numpy as np -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QComboBox, QToolButton, QTreeView, QWidget +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QComboBox, QToolButton, QTreeView, QWidget from ert.data import MeasuredData from ert.gui.simulation.evaluate_ensemble_panel import EvaluateEnsemblePanel @@ -37,7 +37,7 @@ def test_manual_analysis_workflow(ensemble_experiment_has_run, qtbot): # Click start simulation and agree to the message run_experiment = get_child(experiment_panel, QWidget, name="run_experiment") - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) # The Run dialog opens, wait until done appears, then click done run_dialog = wait_for_child(gui, qtbot, RunDialog) qtbot.waitUntil(lambda: run_dialog.is_simulation_done() == True, timeout=10000) @@ -45,7 +45,7 @@ def test_manual_analysis_workflow(ensemble_experiment_has_run, qtbot): button_manage_experiments = gui.findChild(QToolButton, "button_Manage_experiments") assert button_manage_experiments - qtbot.mouseClick(button_manage_experiments, Qt.LeftButton) + qtbot.mouseClick(button_manage_experiments, Qt.MouseButton.LeftButton) experiments_panel = gui.findChild(ManageExperimentsPanel) assert experiments_panel @@ -69,7 +69,9 @@ def test_manual_analysis_workflow(ensemble_experiment_has_run, qtbot): simulation_mode_combo.setCurrentText(EvaluateEnsemble.name()) idx = simulation_settings._ensemble_selector.findData( - "ensemble_experiment : iter-0_1", Qt.MatchStartsWith + "ensemble_experiment : iter-0_1", + Qt.ItemDataRole.DisplayRole, + Qt.MatchFlag.MatchStartsWith, ) assert idx != -1 simulation_settings._ensemble_selector.setCurrentIndex(idx) diff --git a/tests/ert/ui_tests/gui/test_load_results_manually.py b/tests/ert/ui_tests/gui/test_load_results_manually.py index 8b72648fb61..49aa3697ad0 100644 --- a/tests/ert/ui_tests/gui/test_load_results_manually.py +++ b/tests/ert/ui_tests/gui/test_load_results_manually.py @@ -1,5 +1,5 @@ -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import QPushButton +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import QPushButton from ert.gui.ertwidgets import ClosableDialog, StringBox, TextBox from ert.gui.ertwidgets.ensembleselector import EnsembleSelector diff --git a/tests/ert/ui_tests/gui/test_main_window.py b/tests/ert/ui_tests/gui/test_main_window.py index daabc9047c0..959534663c0 100644 --- a/tests/ert/ui_tests/gui/test_main_window.py +++ b/tests/ert/ui_tests/gui/test_main_window.py @@ -8,10 +8,9 @@ import numpy as np import pytest -from qtpy.QtCore import Qt, QTimer -from qtpy.QtGui import QWindow -from qtpy.QtWidgets import ( - QAction, +from PySide6.QtCore import Qt, QTimer +from PySide6.QtGui import QAction, QWindow +from PySide6.QtWidgets import ( QApplication, QCheckBox, QComboBox, @@ -189,7 +188,7 @@ def test_help_buttons_in_suggester_dialog(tmp_path, qtbot): with patch("webbrowser.open", MagicMock(return_value=True)) as browser_open: github_button = get_child(gui, QWidget, name="GitHub page") - qtbot.mouseClick(github_button, Qt.LeftButton) + qtbot.mouseClick(github_button, Qt.MouseButton.LeftButton) assert browser_open.called @@ -297,7 +296,7 @@ def test_that_the_plot_window_contains_the_expected_elements( # Click on Create plot after esmda has run button_plot_tool = gui.findChild(QToolButton, "button_Create_plot") assert button_plot_tool - qtbot.mouseClick(button_plot_tool, Qt.LeftButton) + qtbot.mouseClick(button_plot_tool, Qt.MouseButton.LeftButton) plot_window = wait_for_child(gui, qtbot, PlotWindow) data_types = get_child(plot_window, DataTypeKeysWidget) @@ -316,7 +315,7 @@ def test_that_the_plot_window_contains_the_expected_elements( data_keys = data_types.data_type_keys_widget for i in range(data_keys.model().rowCount()): index = data_keys.model().index(i, 0) - data_names.append(str(index.data(Qt.DisplayRole))) + data_names.append(str(index.data(Qt.ItemDataRole.DisplayRole))) expected_data_names = [ "POLY_RES@0", @@ -349,7 +348,7 @@ def test_that_the_plot_window_contains_the_expected_elements( index = model.index(i, 0) qtbot.mouseClick( data_types.data_type_keys_widget, - Qt.LeftButton, + Qt.MouseButton.LeftButton, pos=data_types.data_type_keys_widget.visualRect(index).center(), ) for tab_index in range(plot_window._central_tab.count()): @@ -364,7 +363,7 @@ def test_that_the_manage_experiments_tool_can_be_used(esmda_has_run, qtbot): button_manage_experiments = gui.findChild(QToolButton, "button_Manage_experiments") assert button_manage_experiments - qtbot.mouseClick(button_manage_experiments, Qt.LeftButton) + qtbot.mouseClick(button_manage_experiments, Qt.MouseButton.LeftButton) experiments_panel = wait_for_child(gui, qtbot, ManageExperimentsPanel) # Open the tab @@ -403,7 +402,7 @@ def handle_add_dialog(): QTimer.singleShot(1000, handle_add_dialog) create_widget = get_child(storage_widget, AddWidget) - qtbot.mouseClick(create_widget.addButton, Qt.LeftButton) + qtbot.mouseClick(create_widget.addButton, Qt.MouseButton.LeftButton) assert experiments_panel.notifier.current_ensemble.iteration == 42 @@ -418,14 +417,14 @@ def handle_add_dialog(): QPushButton, name="initialize_from_scratch_button", ) - qtbot.mouseClick(initialize_button, Qt.LeftButton) + qtbot.mouseClick(initialize_button, Qt.MouseButton.LeftButton) def test_that_inversion_type_can_be_set_from_gui(qtbot, opened_main_window_poly): gui = opened_main_window_poly sim_mode = get_child(gui, QWidget, name="experiment_type") - qtbot.keyClick(sim_mode, Qt.Key_Down) + qtbot.keyClick(sim_mode, Qt.Key.Key_Down) es_panel = get_child(gui, QWidget, name="ensemble_smoother_panel") es_edit = get_child(es_panel, QWidget, name="ensemble_smoother_edit") @@ -447,7 +446,9 @@ def handle_analysis_module_panel(): var_panel.parent().close() QTimer.singleShot(500, handle_analysis_module_panel) - qtbot.mouseClick(get_child(es_edit, QToolButton), Qt.LeftButton, delay=1) + qtbot.mouseClick( + get_child(es_edit, QToolButton), Qt.MouseButton.LeftButton, delay=1 + ) def test_that_the_manage_experiments_tool_can_be_used_with_clean_storage( @@ -457,7 +458,7 @@ def test_that_the_manage_experiments_tool_can_be_used_with_clean_storage( button_manage_experiments = gui.findChild(QToolButton, "button_Manage_experiments") assert button_manage_experiments - qtbot.mouseClick(button_manage_experiments, Qt.LeftButton) + qtbot.mouseClick(button_manage_experiments, Qt.MouseButton.LeftButton) experiments_panel = wait_for_child(gui, qtbot, ManageExperimentsPanel) # Open the create new ensembles tab @@ -499,7 +500,7 @@ def handle_add_dialog(): initialize_button = get_child( current_tab, QPushButton, name="initialize_from_scratch_button" ) - qtbot.mouseClick(initialize_button, Qt.LeftButton) + qtbot.mouseClick(initialize_button, Qt.MouseButton.LeftButton) @pytest.mark.usefixtures("use_tmpdir") @@ -561,7 +562,7 @@ def handle_error_dialog(run_dialog): assert substring in text error_dialog.accept() - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) run_dialog = wait_for_child(gui, qtbot, RunDialog) @@ -586,7 +587,7 @@ def test_that_gui_plotter_works_when_no_data(qtbot, storage, monkeypatch): button_plot_tool = gui.findChild(QToolButton, "button_Create_plot") assert button_plot_tool - qtbot.mouseClick(button_plot_tool, Qt.LeftButton) + qtbot.mouseClick(button_plot_tool, Qt.MouseButton.LeftButton) plot_window = wait_for_child(gui, qtbot, PlotWindow) ensemble_plot_names = get_child( @@ -623,7 +624,7 @@ def top_level_plotter_windows() -> list[QWindow]: def right_click_plotter_button() -> None: top_level_windows = len(top_level_plotter_windows()) - qtbot.mouseClick(button_plot_tool, Qt.RightButton) + qtbot.mouseClick(button_plot_tool, Qt.MouseButton.RightButton) qtbot.wait_until( lambda: len(top_level_plotter_windows()) > top_level_windows, timeout=5000, @@ -641,7 +642,7 @@ def right_click_plotter_button() -> None: qtbot.wait_until(lambda: not top_level_plotter_windows(), timeout=5000) - qtbot.mouseClick(button_plot_tool, Qt.LeftButton) + qtbot.mouseClick(button_plot_tool, Qt.MouseButton.LeftButton) plot_window = wait_for_child(gui, qtbot, PlotWindow) assert plot_window assert "Plotting" in plot_window.windowTitle() @@ -702,7 +703,8 @@ def test_help_menu(qtbot): about_dialog = wait_for_child(gui, qtbot, AboutDialog) assert about_dialog.windowTitle() == "About" qtbot.mouseClick( - get_child(about_dialog, QPushButton, name="close_button"), Qt.LeftButton + get_child(about_dialog, QPushButton, name="close_button"), + Qt.MouseButton.LeftButton, ) @@ -749,13 +751,13 @@ def find_and_click_button( assert button assert button.isEnabled() == expected_enabled_state if should_click: - qtbot.mouseClick(button, Qt.LeftButton) + qtbot.mouseClick(button, Qt.MouseButton.LeftButton) def run_experiment(): run_experiment_panel = wait_for_child(gui, qtbot, ExperimentPanel) qtbot.wait_until(lambda: not run_experiment_panel.isHidden(), timeout=5000) assert run_experiment_panel.run_button.isEnabled() - qtbot.mouseClick(run_experiment_panel.run_button, Qt.LeftButton) + qtbot.mouseClick(run_experiment_panel.run_button, Qt.MouseButton.LeftButton) def wait_for_simulation_completed(): run_dialogs = get_children(gui, RunDialog) diff --git a/tests/ert/ui_tests/gui/test_manage_experiments_tool.py b/tests/ert/ui_tests/gui/test_manage_experiments_tool.py index 9e6994c3aa3..a08bba19173 100644 --- a/tests/ert/ui_tests/gui/test_manage_experiments_tool.py +++ b/tests/ert/ui_tests/gui/test_manage_experiments_tool.py @@ -3,8 +3,8 @@ import polars import pytest -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QPushButton, QTextEdit +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QPushButton, QTextEdit from ert.config import ErtConfig, SummaryConfig from ert.gui.ertnotifier import ErtNotifier diff --git a/tests/ert/ui_tests/gui/test_missing_parameters_to_update.py b/tests/ert/ui_tests/gui/test_missing_parameters_to_update.py index 02fc047604a..ff8443e644d 100644 --- a/tests/ert/ui_tests/gui/test_missing_parameters_to_update.py +++ b/tests/ert/ui_tests/gui/test_missing_parameters_to_update.py @@ -1,8 +1,8 @@ import fileinput import pytest -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QComboBox +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QComboBox from ert.gui.simulation.experiment_panel import ExperimentPanel from tests.ert.ui_tests.gui.conftest import get_child, open_gui_with_config diff --git a/tests/ert/ui_tests/gui/test_missing_runpath.py b/tests/ert/ui_tests/gui/test_missing_runpath.py index e6118037a85..1319b279a2d 100644 --- a/tests/ert/ui_tests/gui/test_missing_runpath.py +++ b/tests/ert/ui_tests/gui/test_missing_runpath.py @@ -1,8 +1,8 @@ import stat from contextlib import suppress -from qtpy.QtCore import QTimer -from qtpy.QtWidgets import QLabel +from PySide6.QtCore import QTimer +from PySide6.QtWidgets import QLabel from ert.ensemble_evaluator.state import ENSEMBLE_STATE_FAILED from ert.gui.simulation.run_dialog import RunDialog diff --git a/tests/ert/ui_tests/gui/test_plotting_of_snake_oil.py b/tests/ert/ui_tests/gui/test_plotting_of_snake_oil.py index 617acceb206..87279de4155 100644 --- a/tests/ert/ui_tests/gui/test_plotting_of_snake_oil.py +++ b/tests/ert/ui_tests/gui/test_plotting_of_snake_oil.py @@ -1,8 +1,8 @@ from unittest.mock import Mock import pytest -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QCheckBox, QToolButton +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QCheckBox, QToolButton from ert.gui.main import GUILogHandler, _setup_main_window from ert.gui.tools.plot.data_type_keys_widget import DataTypeKeysWidget @@ -64,7 +64,7 @@ def plot_figure(qtbot, heat_equation_storage, snake_oil_case_storage, request): button_plot_tool = gui.findChild(QToolButton, "button_Create_plot") assert button_plot_tool - qtbot.mouseClick(button_plot_tool, Qt.LeftButton) + qtbot.mouseClick(button_plot_tool, Qt.MouseButton.LeftButton) plot_window = wait_for_child(gui, qtbot, PlotWindow) central_tab = plot_window._central_tab @@ -146,7 +146,7 @@ def test_that_all_plotter_filter_boxes_yield_expected_filter_results( button_plot_tool = gui.findChild(QToolButton, "button_Create_plot") assert button_plot_tool - qtbot.mouseClick(button_plot_tool, Qt.LeftButton) + qtbot.mouseClick(button_plot_tool, Qt.MouseButton.LeftButton) plot_window = wait_for_child(gui, qtbot, PlotWindow) key_list = plot_window.findChild(DataTypeKeysWidget).data_type_keys_widget diff --git a/tests/ert/ui_tests/gui/test_restart_ensemble_experiment.py b/tests/ert/ui_tests/gui/test_restart_ensemble_experiment.py index 04910bb8890..9ad17c57a17 100644 --- a/tests/ert/ui_tests/gui/test_restart_ensemble_experiment.py +++ b/tests/ert/ui_tests/gui/test_restart_ensemble_experiment.py @@ -3,8 +3,8 @@ import stat from textwrap import dedent -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import QComboBox, QMessageBox, QWidget +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import QComboBox, QMessageBox, QWidget from ert.gui.simulation.experiment_panel import ExperimentPanel from ert.gui.simulation.run_dialog import RunDialog @@ -99,12 +99,12 @@ def _evaluate(coeffs, x): assert set(failed_realizations) == failing_reals_first_try def handle_dialog(): - message_box = wait_for_child(gui, qtbot, QMessageBox, name="restart_prompt") + message_box = gui.findChildren(QMessageBox, name="restart_prompt")[-1] qtbot.mouseClick(message_box.buttons()[0], Qt.MouseButton.LeftButton) - QTimer.singleShot(500, handle_dialog) failing_reals_second_try = {*random.sample(list(failing_reals_first_try), 5)} write_poly_eval(failing_reals=failing_reals_second_try) + QTimer.singleShot(500, handle_dialog) qtbot.mouseClick(run_dialog.restart_button, Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: run_dialog.is_simulation_done() == True, timeout=60000) diff --git a/tests/ert/ui_tests/gui/test_restart_esmda.py b/tests/ert/ui_tests/gui/test_restart_esmda.py index 6c7c8e312ed..641380087f1 100644 --- a/tests/ert/ui_tests/gui/test_restart_esmda.py +++ b/tests/ert/ui_tests/gui/test_restart_esmda.py @@ -1,5 +1,5 @@ -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QCheckBox, QComboBox, QWidget +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QCheckBox, QComboBox, QWidget from ert.gui.ertwidgets import StringBox from ert.gui.simulation.experiment_panel import ExperimentPanel diff --git a/tests/ert/ui_tests/gui/test_restart_no_responses_and_parameters.py b/tests/ert/ui_tests/gui/test_restart_no_responses_and_parameters.py index 0cc9cc1cc37..fa8435d2b5d 100644 --- a/tests/ert/ui_tests/gui/test_restart_no_responses_and_parameters.py +++ b/tests/ert/ui_tests/gui/test_restart_no_responses_and_parameters.py @@ -6,10 +6,8 @@ from unittest.mock import Mock import pytest -from qtpy.QtCore import Qt -from qtpy.QtWidgets import ( - QComboBox, -) +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QComboBox from ert.config import ErtConfig from ert.gui.main import _setup_main_window @@ -107,7 +105,9 @@ def test_sensitivity_restart(open_gui, qtbot, run_experiment): simulation_mode_combo.setCurrentText(EvaluateEnsemble.name()) idx = simulation_settings._ensemble_selector.findData( - "ensemble_experiment : iter-0", Qt.MatchStartsWith + "ensemble_experiment : iter-0", + Qt.ItemDataRole.DisplayRole, + Qt.MatchFlag.MatchStartsWith, ) assert idx != -1 simulation_settings._ensemble_selector.setCurrentIndex(idx) diff --git a/tests/ert/ui_tests/gui/test_rft_export_plugin.py b/tests/ert/ui_tests/gui/test_rft_export_plugin.py index 8540c8caa55..011066a81da 100644 --- a/tests/ert/ui_tests/gui/test_rft_export_plugin.py +++ b/tests/ert/ui_tests/gui/test_rft_export_plugin.py @@ -4,8 +4,8 @@ from unittest.mock import Mock import pytest -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import QCheckBox, QMessageBox +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import QCheckBox, QMessageBox from ert.config import ErtConfig from ert.gui.ertwidgets import CustomDialog, ListEditBox, PathChooser @@ -93,11 +93,14 @@ def test_rft_csv_export_plugin_exports_rft_data( def handle_finished_box(): """ - Click on the plugin finised dialog once it pops up + Click on the plugin finished dialog once it pops up """ finished_message = wait_for_child(gui, qtbot, QMessageBox) assert "completed" in finished_message.text() - qtbot.mouseClick(finished_message.button(QMessageBox.Ok), Qt.LeftButton) + qtbot.mouseClick( + finished_message.button(QMessageBox.StandardButton.Ok), + Qt.MouseButton.LeftButton, + ) def handle_rft_plugin_dialog(): dialog = wait_for_child(gui, qtbot, CustomDialog) @@ -109,7 +112,7 @@ def handle_rft_plugin_dialog(): dialog, QCheckBox, name="drop_const_columns_check" ) drop_constant.setChecked(True) - qtbot.mouseClick(dialog.ok_button, Qt.LeftButton) + qtbot.mouseClick(dialog.ok_button, Qt.MouseButton.LeftButton) plugin_tool = gui.plugins_tool plugin_actions = plugin_tool.menu.actions() diff --git a/tests/ert/ui_tests/gui/test_single_test_run.py b/tests/ert/ui_tests/gui/test_single_test_run.py index 536808c355e..00cc9db3f9a 100644 --- a/tests/ert/ui_tests/gui/test_single_test_run.py +++ b/tests/ert/ui_tests/gui/test_single_test_run.py @@ -1,8 +1,8 @@ import contextlib import shutil -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QComboBox, QWidget +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QComboBox, QWidget from ert.gui.simulation.experiment_panel import ExperimentPanel from ert.gui.simulation.run_dialog import RunDialog @@ -28,7 +28,7 @@ def test_single_test_run_after_ensemble_experiment( simulation_mode_combo.setCurrentText("Single realization test-run") run_experiment = get_child(experiment_panel, QWidget, name="run_experiment") - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) run_dialog = wait_for_child(gui, qtbot, RunDialog) qtbot.waitUntil(lambda: run_dialog.is_simulation_done() == True, timeout=100000) qtbot.waitUntil(lambda: run_dialog._tab_widget.currentWidget() is not None) diff --git a/tests/ert/ui_tests/gui/test_workflow_tool.py b/tests/ert/ui_tests/gui/test_workflow_tool.py index dc348b6e02b..fd178e13664 100644 --- a/tests/ert/ui_tests/gui/test_workflow_tool.py +++ b/tests/ert/ui_tests/gui/test_workflow_tool.py @@ -5,7 +5,7 @@ from unittest.mock import Mock import pytest -from qtpy.QtCore import Qt, QTimer +from PySide6.QtCore import Qt, QTimer from ert.config import ErtConfig from ert.gui.ertwidgets import ClosableDialog @@ -75,7 +75,8 @@ def handle_run_workflow_tool(): workflow_widget = get_child(dialog, RunWorkflowWidget) def close_all(): - workflow_widget._running_workflow_dialog.accept() + if running_dlg := workflow_widget._running_workflow_dialog: + running_dlg.accept() dialog.close() workflow_widget.workflowSucceeded.disconnect() diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_checklist.py b/tests/ert/unit_tests/gui/ertwidgets/test_checklist.py index 89e21160f0b..4c814f03b17 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_checklist.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_checklist.py @@ -1,4 +1,4 @@ -from qtpy.QtCore import Qt +from PySide6.QtCore import Qt from ert.gui.ertwidgets.checklist import CheckList from ert.gui.ertwidgets.models.selectable_list_model import SelectableListModel @@ -8,12 +8,12 @@ def test_checklist(qtbot): checklist = CheckList(SelectableListModel(items=["1", "2", "3"])) qtbot.addWidget(checklist) - qtbot.mouseClick(checklist._checkAllButton, Qt.LeftButton) + qtbot.mouseClick(checklist._checkAllButton, Qt.MouseButton.LeftButton) for item in checklist._model.getList(): assert checklist._model.isValueSelected(item) - qtbot.mouseClick(checklist._uncheckAllButton, Qt.LeftButton) + qtbot.mouseClick(checklist._uncheckAllButton, Qt.MouseButton.LeftButton) for item in checklist._model.getList(): assert not checklist._model.isValueSelected(item) diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_closabledialog.py b/tests/ert/unit_tests/gui/ertwidgets/test_closabledialog.py index 47e22506868..15fdd0332c0 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_closabledialog.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_closabledialog.py @@ -1,6 +1,6 @@ +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QPushButton from pytestqt.qtbot import QtBot -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QPushButton from ert.gui.ertwidgets import ClosableDialog diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_copy_debug_info_button.py b/tests/ert/unit_tests/gui/ertwidgets/test_copy_debug_info_button.py index d85d68e9592..38163e833fa 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_copy_debug_info_button.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_copy_debug_info_button.py @@ -1,5 +1,5 @@ +from PySide6.QtCore import Qt from pytestqt.qtbot import QtBot -from qtpy.QtCore import Qt from ert.gui.simulation.run_dialog import CopyDebugInfoButton diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_copyablelabel.py b/tests/ert/unit_tests/gui/ertwidgets/test_copyablelabel.py index 2dbc36c9ab8..f6f003b5c66 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_copyablelabel.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_copyablelabel.py @@ -1,6 +1,6 @@ import pytest -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QApplication, QWidget +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QApplication, QWidget from ert.gui.ertwidgets.copyablelabel import ( CopyableLabel, diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_pathchooser.py b/tests/ert/unit_tests/gui/ertwidgets/test_pathchooser.py index b051533ff6a..740681dc1cc 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_pathchooser.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_pathchooser.py @@ -1,4 +1,4 @@ -from qtpy.QtWidgets import QFileDialog +from PySide6.QtWidgets import QFileDialog from ert.gui.ertwidgets.models.path_model import PathModel from ert.gui.ertwidgets.pathchooser import PathChooser diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_plot_case_selection_widget.py b/tests/ert/unit_tests/gui/ertwidgets/test_plot_case_selection_widget.py index 938741ac4cc..cee15fbc399 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_plot_case_selection_widget.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_plot_case_selection_widget.py @@ -1,5 +1,5 @@ +from PySide6.QtCore import Qt from pytestqt.qtbot import QtBot -from qtpy.QtCore import Qt from ert.gui.tools.plot.plot_api import EnsembleObject from ert.gui.tools.plot.plot_ensemble_selection_widget import ( @@ -24,7 +24,7 @@ def test_ensemble_selection_widget_max_min_selection(qtbot: QtBot): qtbot.mouseClick( list_widget.viewport(), - Qt.LeftButton, + Qt.MouseButton.LeftButton, pos=list_widget.visualItemRect(list_widget.item(0)).center(), ) # deselect the only item selected @@ -36,7 +36,7 @@ def test_ensemble_selection_widget_max_min_selection(qtbot: QtBot): it = list_widget.item(index) qtbot.mouseClick( list_widget.viewport(), - Qt.LeftButton, + Qt.MouseButton.LeftButton, pos=list_widget.visualItemRect(it).center(), ) @@ -46,7 +46,7 @@ def test_ensemble_selection_widget_max_min_selection(qtbot: QtBot): it = list_widget.item(index) qtbot.mouseClick( list_widget.viewport(), - Qt.LeftButton, + Qt.MouseButton.LeftButton, pos=list_widget.visualItemRect(it).center(), ) diff --git a/tests/ert/unit_tests/gui/ertwidgets/test_search_bar.py b/tests/ert/unit_tests/gui/ertwidgets/test_search_bar.py index ce6181ab907..df6c35e8442 100644 --- a/tests/ert/unit_tests/gui/ertwidgets/test_search_bar.py +++ b/tests/ert/unit_tests/gui/ertwidgets/test_search_bar.py @@ -1,7 +1,7 @@ import pytest +from PySide6.QtGui import QColor +from PySide6.QtWidgets import QPlainTextEdit from pytestqt.qtbot import QtBot -from qtpy.QtGui import QColor -from qtpy.QtWidgets import QPlainTextEdit from ert.gui.tools.search_bar import SearchBar diff --git a/tests/ert/unit_tests/gui/model/test_job_list.py b/tests/ert/unit_tests/gui/model/test_job_list.py index d50aa7995aa..d14b39a17ff 100644 --- a/tests/ert/unit_tests/gui/model/test_job_list.py +++ b/tests/ert/unit_tests/gui/model/test_job_list.py @@ -3,8 +3,8 @@ import pytest from dateutil import tz +from PySide6.QtCore import QModelIndex from pytestqt.qt_compat import qt_api -from qtpy.QtCore import QModelIndex from ert.ensemble_evaluator import identifiers as ids from ert.ensemble_evaluator.snapshot import FMStepSnapshot diff --git a/tests/ert/unit_tests/gui/model/test_real_list.py b/tests/ert/unit_tests/gui/model/test_real_list.py index d0f6c304b6b..6e6d309c499 100644 --- a/tests/ert/unit_tests/gui/model/test_real_list.py +++ b/tests/ert/unit_tests/gui/model/test_real_list.py @@ -1,5 +1,5 @@ +from PySide6.QtCore import QModelIndex from pytestqt.qt_compat import qt_api -from qtpy.QtCore import QModelIndex from ert.ensemble_evaluator.state import ( REALIZATION_STATE_FINISHED, diff --git a/tests/ert/unit_tests/gui/model/test_snapshot.py b/tests/ert/unit_tests/gui/model/test_snapshot.py index b8a369bbd68..a3b167a2fdf 100644 --- a/tests/ert/unit_tests/gui/model/test_snapshot.py +++ b/tests/ert/unit_tests/gui/model/test_snapshot.py @@ -1,7 +1,7 @@ import pytest +from PySide6.QtCore import QModelIndex +from PySide6.QtGui import QColor from pytestqt.qt_compat import qt_api -from qtpy.QtCore import QModelIndex -from qtpy.QtGui import QColor from ert.ensemble_evaluator.state import COLOR_FAILED from ert.gui.model.snapshot import FMStepColorHint, SnapshotModel diff --git a/tests/ert/unit_tests/gui/run_analysis/test_analysispanel.py b/tests/ert/unit_tests/gui/run_analysis/test_analysispanel.py index 03896f2655d..aceb5d6773a 100644 --- a/tests/ert/unit_tests/gui/run_analysis/test_analysispanel.py +++ b/tests/ert/unit_tests/gui/run_analysis/test_analysispanel.py @@ -1,20 +1,22 @@ import math import pytest -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QCheckBox, QDoubleSpinBox +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QCheckBox, QDoubleSpinBox +from pytestqt.qtbot import QtBot from ert.config import ESSettings from ert.gui.ertwidgets.analysismodulevariablespanel import AnalysisModuleVariablesPanel @pytest.fixture -def panel_with_localization_on(qtbot): +def panel_with_localization_on(qtbot: QtBot): def func(settings, ensemble_size): widget = AnalysisModuleVariablesPanel(settings, ensemble_size) qtbot.addWidget(widget) + widget.show() check_box = widget.findChild(QCheckBox, name="localization") - qtbot.mouseClick(check_box, Qt.LeftButton) + qtbot.mouseClick(check_box, Qt.MouseButton.LeftButton) return settings, widget yield func diff --git a/tests/ert/unit_tests/gui/run_analysis/test_update_widget.py b/tests/ert/unit_tests/gui/run_analysis/test_update_widget.py index f8176643fd6..266e11c45b0 100644 --- a/tests/ert/unit_tests/gui/run_analysis/test_update_widget.py +++ b/tests/ert/unit_tests/gui/run_analysis/test_update_widget.py @@ -1,8 +1,8 @@ from uuid import uuid4 import numpy as np +from PySide6.QtWidgets import QTableWidget from pytestqt.qtbot import QtBot -from qtpy.QtWidgets import QTableWidget from ert.analysis.event import DataSection from ert.gui.simulation.view import UpdateWidget diff --git a/tests/ert/unit_tests/gui/simulation/test_run_dialog.py b/tests/ert/unit_tests/gui/simulation/test_run_dialog.py index 686939f032a..fcd13e0b748 100644 --- a/tests/ert/unit_tests/gui/simulation/test_run_dialog.py +++ b/tests/ert/unit_tests/gui/simulation/test_run_dialog.py @@ -4,10 +4,9 @@ import pandas as pd import pytest -from pytestqt.qtbot import QtBot -from qtpy import QtWidgets -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import ( +from PySide6 import QtWidgets +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import ( QApplication, QComboBox, QLabel, @@ -15,6 +14,7 @@ QToolButton, QWidget, ) +from pytestqt.qtbot import QtBot import ert from ert.config import ErtConfig @@ -68,9 +68,7 @@ def run_dialog(qtbot: QtBot, run_model, event_queue, notifier): run_dialog = RunDialog("mock.ert", run_model, event_queue, notifier) qtbot.addWidget(run_dialog) - # Teardown yield run_dialog - run_dialog.close() def test_terminating_experiment_shows_a_confirmation_dialog( @@ -89,10 +87,10 @@ def handle_dialog(): QtWidgets.QDialogButtonBox ).buttons() yes_button = next(b for b in dialog_buttons if "Yes" in b.text()) - qtbot.mouseClick(yes_button, Qt.LeftButton) + qtbot.mouseClick(yes_button, Qt.MouseButton.LeftButton) QTimer.singleShot(100, handle_dialog) - qtbot.mouseClick(run_dialog.kill_button, Qt.LeftButton) + qtbot.mouseClick(run_dialog.kill_button, Qt.MouseButton.LeftButton) @pytest.mark.integration_test @@ -431,7 +429,7 @@ def test_run_dialog_memory_usage_showing( realization_box = run_dialog._tab_widget.widget(0) assert type(realization_box) == RealizationWidget # Click the first realization box - qtbot.mouseClick(realization_box, Qt.LeftButton) + qtbot.mouseClick(realization_box, Qt.MouseButton.LeftButton) fm_step_model = run_dialog._fm_step_overview.model() assert fm_step_model._real == 0 @@ -441,7 +439,9 @@ def test_run_dialog_memory_usage_showing( max_memory_column_proxy_index = fm_step_model.index( fm_step_number, max_memory_column_index ) - max_memory_value = fm_step_model.data(max_memory_column_proxy_index, Qt.DisplayRole) + max_memory_value = fm_step_model.data( + max_memory_column_proxy_index, Qt.ItemDataRole.DisplayRole + ) assert max_memory_value == "60.00 KB" @@ -534,7 +534,7 @@ def test_run_dialog_fm_label_show_correct_info( realization_box = run_dialog._tab_widget.widget(0) assert type(realization_box) == RealizationWidget # Click the first realization box - qtbot.mouseClick(realization_box, Qt.LeftButton) + qtbot.mouseClick(realization_box, Qt.MouseButton.LeftButton) fm_step_model = run_dialog._fm_step_overview.model() assert fm_step_model._real == 0 @@ -583,11 +583,11 @@ def handle_error_dialog(run_dialog): assert error_dialog text = error_dialog.details_text.toPlainText() assert "I failed :(" in text - qtbot.mouseClick(error_dialog.box.buttons()[0], Qt.LeftButton) + qtbot.mouseClick(error_dialog.box.buttons()[0], Qt.MouseButton.LeftButton) simulation_mode_combo = gui.findChild(QComboBox) simulation_mode_combo.setCurrentText("Single realization test-run") - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) run_dialog = wait_for_child(gui, qtbot, RunDialog) QTimer.singleShot(100, lambda: handle_error_dialog(run_dialog)) @@ -615,7 +615,7 @@ def test_that_debug_info_button_provides_data_in_clipboard(qtbot: QtBot, storage assert run_experiment assert isinstance(run_experiment, QToolButton) - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None, timeout=5000) run_dialog = gui.findChild(RunDialog) assert run_dialog is not None @@ -623,7 +623,7 @@ def test_that_debug_info_button_provides_data_in_clipboard(qtbot: QtBot, storage copy_debug_info_button = gui.findChild(QPushButton, "copy_debug_info_button") assert copy_debug_info_button assert isinstance(copy_debug_info_button, QPushButton) - qtbot.mouseClick(copy_debug_info_button, Qt.LeftButton) + qtbot.mouseClick(copy_debug_info_button, Qt.MouseButton.LeftButton) clipboard_text = QApplication.clipboard().text() @@ -667,7 +667,7 @@ def test_that_stdout_and_stderr_buttons_react_to_file_content( QTimer.singleShot( 1000, lambda: handle_run_path_dialog(gui, qtbot, delete_run_path=True) ) - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None, timeout=5000) run_dialog = gui.findChild(RunDialog) @@ -684,7 +684,7 @@ def test_that_stdout_and_stderr_buttons_react_to_file_content( with qtbot.waitSignal(realization_widget.itemClicked, timeout=30000): qtbot.mouseClick( realization_widget._real_view.viewport(), - Qt.LeftButton, + Qt.MouseButton.LeftButton, pos=click_pos, ) @@ -701,7 +701,9 @@ def test_that_stdout_and_stderr_buttons_react_to_file_content( assert fm_step_stderr.data(Qt.ItemDataRole.FontRole) is None click_pos = fm_step_overview.visualRect(fm_step_stdout).center() - qtbot.mouseClick(fm_step_overview.viewport(), Qt.LeftButton, pos=click_pos) + qtbot.mouseClick( + fm_step_overview.viewport(), Qt.MouseButton.LeftButton, pos=click_pos + ) file_dialog = run_dialog.findChild(FileDialog) qtbot.waitUntil(file_dialog.isVisible, timeout=10000) file_dialog.close() diff --git a/tests/ert/unit_tests/gui/simulation/test_run_path_dialog.py b/tests/ert/unit_tests/gui/simulation/test_run_path_dialog.py index ad4fde67f3c..42f055efad9 100644 --- a/tests/ert/unit_tests/gui/simulation/test_run_path_dialog.py +++ b/tests/ert/unit_tests/gui/simulation/test_run_path_dialog.py @@ -3,9 +3,9 @@ from unittest.mock import Mock, patch import pytest +from PySide6.QtCore import Qt, QTimer +from PySide6.QtWidgets import QComboBox, QMessageBox, QToolButton, QWidget from pytestqt.qtbot import QtBot -from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import QComboBox, QMessageBox, QToolButton, QWidget from ert.config import ErtConfig from ert.gui.main import _setup_main_window @@ -25,16 +25,17 @@ def handle_run_path_dialog( delete_run_path: bool = True, expect_error: bool = False, ): - mb = gui.findChild(QMessageBox, "RUN_PATH_WARNING_BOX") + mb = gui.findChildren(QMessageBox, "RUN_PATH_WARNING_BOX") + mb = mb[-1] if mb else None if mb is not None: assert mb assert isinstance(mb, QMessageBox) if delete_run_path: - qtbot.mouseClick(mb.checkBox(), Qt.LeftButton) + qtbot.mouseClick(mb.checkBox(), Qt.MouseButton.LeftButton) - qtbot.mouseClick(mb.buttons()[0], Qt.LeftButton) + qtbot.mouseClick(mb.buttons()[0], Qt.MouseButton.LeftButton) if expect_error: QTimer.singleShot(1000, lambda: handle_run_path_error_dialog(gui, qtbot)) @@ -46,7 +47,7 @@ def handle_run_path_error_dialog(gui: ErtMainWindow, qtbot: QtBot): assert mb assert isinstance(mb, QMessageBox) # Continue without deleting the runpath - qtbot.mouseClick(mb.buttons()[0], Qt.LeftButton) + qtbot.mouseClick(mb.buttons()[0], Qt.MouseButton.LeftButton) @pytest.mark.integration_test @@ -91,7 +92,7 @@ def test_run_path_deleted_error( 1000, lambda: handle_run_path_dialog(gui, qtbot, expect_error=True) ) with patch("shutil.rmtree", side_effect=PermissionError("Not allowed!")): - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None) run_dialog = gui.findChild(RunDialog) @@ -138,7 +139,7 @@ def test_run_path_is_deleted(snake_oil_case_storage: ErtConfig, qtbot: QtBot): QTimer.singleShot( 1000, lambda: handle_run_path_dialog(gui, qtbot, delete_run_path=True) ) - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None) run_dialog = gui.findChild(RunDialog) @@ -183,7 +184,7 @@ def test_run_path_is_not_deleted(snake_oil_case_storage: ErtConfig, qtbot: QtBot QTimer.singleShot( 500, lambda: handle_run_path_dialog(gui, qtbot, delete_run_path=False) ) - qtbot.mouseClick(run_experiment, Qt.LeftButton) + qtbot.mouseClick(run_experiment, Qt.MouseButton.LeftButton) qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None, timeout=10000) run_dialog = gui.findChild(RunDialog) diff --git a/tests/ert/unit_tests/gui/simulation/view/test_legend.py b/tests/ert/unit_tests/gui/simulation/view/test_legend.py index 40730621c2f..75decbcc41e 100644 --- a/tests/ert/unit_tests/gui/simulation/view/test_legend.py +++ b/tests/ert/unit_tests/gui/simulation/view/test_legend.py @@ -1,7 +1,7 @@ import hypothesis.strategies as st import pytest from hypothesis import HealthCheck, given, settings -from qtpy.QtWidgets import QLabel +from PySide6.QtWidgets import QLabel from ert.ensemble_evaluator.state import REAL_STATE_TO_COLOR from ert.gui.simulation.view import ProgressWidget diff --git a/tests/ert/unit_tests/gui/simulation/view/test_realization.py b/tests/ert/unit_tests/gui/simulation/view/test_realization.py index 4de9ecab378..8f35c5e25e2 100644 --- a/tests/ert/unit_tests/gui/simulation/view/test_realization.py +++ b/tests/ert/unit_tests/gui/simulation/view/test_realization.py @@ -1,9 +1,9 @@ from datetime import datetime as dt import pytest -from qtpy import QtCore -from qtpy.QtCore import QModelIndex, QSize -from qtpy.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem +from PySide6 import QtCore +from PySide6.QtCore import QModelIndex, QSize +from PySide6.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem from ert.ensemble_evaluator.snapshot import ( EnsembleSnapshot, diff --git a/tests/ert/unit_tests/gui/test_suggestor.py b/tests/ert/unit_tests/gui/test_suggestor.py index a04366e07cc..eaa71aadc4c 100644 --- a/tests/ert/unit_tests/gui/test_suggestor.py +++ b/tests/ert/unit_tests/gui/test_suggestor.py @@ -1,5 +1,5 @@ import pytest -from qtpy.QtWidgets import QWidget +from PySide6.QtWidgets import QWidget from ert.config import ErrorInfo from ert.gui.suggestor import Suggestor diff --git a/tests/ert/unit_tests/gui/tools/file/test_filedialog.py b/tests/ert/unit_tests/gui/tools/file/test_filedialog.py index fcb8d4dec2a..7feb8eb6a1e 100644 --- a/tests/ert/unit_tests/gui/tools/file/test_filedialog.py +++ b/tests/ert/unit_tests/gui/tools/file/test_filedialog.py @@ -2,7 +2,7 @@ from os import path import pytest -from qtpy.QtWidgets import QApplication +from PySide6.QtWidgets import QApplication from ert.gui.tools.file.file_dialog import FileDialog diff --git a/tests/ert/unit_tests/gui/tools/plot/test_plot_window.py b/tests/ert/unit_tests/gui/tools/plot/test_plot_window.py index 0d23a9d4dcb..7fbd3497fb1 100644 --- a/tests/ert/unit_tests/gui/tools/plot/test_plot_window.py +++ b/tests/ert/unit_tests/gui/tools/plot/test_plot_window.py @@ -1,6 +1,6 @@ +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QApplication, QPushButton from pytestqt.qtbot import QtBot -from qtpy.QtCore import Qt -from qtpy.QtWidgets import QApplication, QPushButton from ert.gui.tools.plot.plot_window import create_error_dialog diff --git a/tests/everest/dialogs_mocker.py b/tests/everest/dialogs_mocker.py index 5361465ab3d..d573b5d28df 100644 --- a/tests/everest/dialogs_mocker.py +++ b/tests/everest/dialogs_mocker.py @@ -1,4 +1,4 @@ -from qtpy.QtWidgets import QFileDialog, QMessageBox +from PySide6.QtWidgets import QFileDialog, QMessageBox def mock_dialogs( @@ -57,10 +57,10 @@ def mock_dialogs_all( open_file_name="", open_file_names="", save_file_name="", - information_button=QMessageBox.Ok, - warning_button=QMessageBox.Ok, - critical_button=QMessageBox.Ok, - question_button=QMessageBox.Ok | QMessageBox.Yes, + information_button=QMessageBox.StandardButton.Ok, + warning_button=QMessageBox.StandardButton.Ok, + critical_button=QMessageBox.StandardButton.Ok, + question_button=QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Yes, ): """Same as mock_dialog but with some acceptable default""" mock_dialogs( From fcb1ddcd472555bf3ae46cab40b8393d6ad3a704 Mon Sep 17 00:00:00 2001 From: Jon Holba Date: Thu, 19 Dec 2024 11:30:20 +0100 Subject: [PATCH 2/2] Add additional typing to qt components --- src/ert/gui/model/node.py | 20 +++++------ src/ert/gui/simulation/run_dialog.py | 11 +++--- .../tools/manage_experiments/storage_model.py | 34 ++++++++++++------- .../gui/simulation/view/test_realization.py | 4 +-- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/ert/gui/model/node.py b/src/ert/gui/model/node.py index 9d02dd220c9..90e051fb642 100644 --- a/src/ert/gui/model/node.py +++ b/src/ert/gui/model/node.py @@ -10,7 +10,7 @@ @dataclass -class _Node(ABC): +class Node(ABC): id_: str parent: RootNode | IterNode | RealNode | None = None children: ( @@ -24,7 +24,7 @@ def __repr__(self) -> str: return f"Node<{type(self).__name__}>@{self.id_} with {parent}parent and {children}children" @abstractmethod - def add_child(self, node: _Node) -> None: + def add_child(self, node: Node) -> None: pass def row(self) -> int: @@ -37,12 +37,12 @@ def row(self) -> int: @dataclass -class RootNode(_Node): +class RootNode(Node): parent: None = field(default=None, init=False) children: dict[str, IterNode] = field(default_factory=dict) max_memory_usage: int | None = None - def add_child(self, node: _Node) -> None: + def add_child(self, node: Node) -> None: node = cast(IterNode, node) node.parent = self self.children[node.id_] = node @@ -55,12 +55,12 @@ class IterNodeData: @dataclass -class IterNode(_Node): +class IterNode(Node): parent: RootNode | None = None data: IterNodeData = field(default_factory=IterNodeData) children: dict[str, RealNode] = field(default_factory=dict) - def add_child(self, node: _Node) -> None: + def add_child(self, node: Node) -> None: node = cast(RealNode, node) node.parent = self self.children[node.id_] = node @@ -80,21 +80,21 @@ class RealNodeData: @dataclass -class RealNode(_Node): +class RealNode(Node): parent: IterNode | None = None data: RealNodeData = field(default_factory=RealNodeData) children: dict[str, ForwardModelStepNode] = field(default_factory=dict) - def add_child(self, node: _Node) -> None: + def add_child(self, node: Node) -> None: node = cast(ForwardModelStepNode, node) node.parent = self self.children[node.id_] = node @dataclass -class ForwardModelStepNode(_Node): +class ForwardModelStepNode(Node): parent: RealNode | None data: FMStepSnapshot = field(default_factory=lambda: FMStepSnapshot()) # noqa: PLW0108 - def add_child(self, node: _Node) -> None: + def add_child(self, node: Node) -> None: pass diff --git a/src/ert/gui/simulation/run_dialog.py b/src/ert/gui/simulation/run_dialog.py index e49b90fdced..787140311fa 100644 --- a/src/ert/gui/simulation/run_dialog.py +++ b/src/ert/gui/simulation/run_dialog.py @@ -39,6 +39,8 @@ from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets.message_box import ErtMessageBox from ert.gui.model.fm_step_list import FMStepListProxyModel +from ert.gui.model.node import Node +from ert.gui.model.real_list import RealListModel from ert.gui.model.snapshot import ( FM_STEP_COLUMNS, FileRole, @@ -179,8 +181,8 @@ def __init__( QFrame.__init__(self, parent) self.output_path = output_path self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) - self.setWindowFlags(Qt.WindowType.Window) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # type: ignore + self.setWindowFlag(Qt.WindowType.Window, True) + self.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False) self.setWindowTitle(f"Experiment - {config_file} {find_ert_info()}") self._snapshot_model = SnapshotModel(self) @@ -304,8 +306,7 @@ def on_snapshot_new_iteration( ) -> None: if not parent.isValid(): index = self._snapshot_model.index(start, 0, parent) - # iteration = index.data(IterNum) - iteration = index.internalPointer().id_ # type: ignore + iteration = cast(Node, index.internalPointer()).id_ iter_row = start self._iteration_progress_label.setText( f"Progress for iteration {iteration}" @@ -325,7 +326,7 @@ def on_snapshot_new_iteration( def _select_real(self, index: QModelIndex) -> None: if index.isValid(): real = index.row() - iter_ = index.model().get_iter() # type: ignore + iter_ = cast(RealListModel, index.model()).get_iter() exec_hosts = None iter_node = self._snapshot_model.root.children.get(str(iter_), None) diff --git a/src/ert/gui/tools/manage_experiments/storage_model.py b/src/ert/gui/tools/manage_experiments/storage_model.py index 24462969cf1..80bdfbbe572 100644 --- a/src/ert/gui/tools/manage_experiments/storage_model.py +++ b/src/ert/gui/tools/manage_experiments/storage_model.py @@ -1,5 +1,5 @@ from enum import IntEnum -from typing import Any, overload +from typing import Any, cast, overload from uuid import UUID import humanize @@ -52,7 +52,9 @@ def row(self) -> int: return self._parent._children.index(self) return 0 - def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> Any: + def data( + self, index: QModelIndex | QPersistentModelIndex, role: Qt.ItemDataRole + ) -> Any: if not index.isValid(): return None @@ -79,7 +81,9 @@ def row(self) -> int: return self._parent._children.index(self) return 0 - def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> Any: + def data( + self, index: QModelIndex | QPersistentModelIndex, role: Qt.ItemDataRole + ) -> Any: if not index.isValid(): return None @@ -113,7 +117,9 @@ def row(self) -> int: return 0 def data( - self, index: QModelIndex, role: Qt.ItemDataRole = Qt.ItemDataRole.DisplayRole + self, + index: QModelIndex | QPersistentModelIndex, + role: Qt.ItemDataRole = Qt.ItemDataRole.DisplayRole, ) -> Any: if not index.isValid(): return None @@ -139,6 +145,9 @@ def data( return None +ChildModel = ExperimentModel | EnsembleModel | RealizationModel + + class StorageModel(QAbstractItemModel): def __init__(self, storage: Storage): super().__init__(None) @@ -180,12 +189,9 @@ def columnCount( def rowCount( self, parent: QModelIndex | QPersistentModelIndex | None = None ) -> int: - if parent is None: - parent = QModelIndex() - if parent.isValid(): - if isinstance(parent.internalPointer(), RealizationModel): - return 0 - return len(parent.internalPointer()._children) # type: ignore + if parent is not None and parent.isValid(): + data = cast(ChildModel | StorageModel, parent.internalPointer()) + return 0 if isinstance(data, RealizationModel) else len(data._children) else: return len(self._children) @@ -200,8 +206,8 @@ def parent( if child is None or not child.isValid(): return QModelIndex() - child_item = child.internalPointer() - parentItem = child_item._parent # type: ignore + child_item = cast(ChildModel, child.internalPointer()) + parentItem = child_item._parent if parentItem == self: return QModelIndex() @@ -229,7 +235,9 @@ def data( if not index.isValid(): return None - return index.internalPointer().data(index, role) # type:ignore + return cast(ChildModel | StorageModel, index.internalPointer()).data( + index, cast(Qt.ItemDataRole, role) + ) @override def index( diff --git a/tests/ert/unit_tests/gui/simulation/view/test_realization.py b/tests/ert/unit_tests/gui/simulation/view/test_realization.py index 8f35c5e25e2..015fb83f578 100644 --- a/tests/ert/unit_tests/gui/simulation/view/test_realization.py +++ b/tests/ert/unit_tests/gui/simulation/view/test_realization.py @@ -12,7 +12,7 @@ FORWARD_MODEL_STATE_START, REALIZATION_STATE_UNKNOWN, ) -from ert.gui.model.node import _Node +from ert.gui.model.node import Node from ert.gui.model.snapshot import SnapshotModel from ert.gui.simulation.view.realization import RealizationWidget from tests.ert import SnapshotBuilder @@ -104,7 +104,7 @@ def test_selection_success(large_snapshot, qtbot): def check_selection_cb(index): node = index.internalPointer() - return isinstance(node, _Node) and str(node.id_) == str(selection_id) + return isinstance(node, Node) and str(node.id_) == str(selection_id) with qtbot.waitSignal( widget.itemClicked, timeout=30000, check_params_cb=check_selection_cb