diff --git a/activity_browser/__init__.py b/activity_browser/__init__.py index 412adefe4..0dfaf9771 100644 --- a/activity_browser/__init__.py +++ b/activity_browser/__init__.py @@ -2,6 +2,10 @@ import sys from logging import getLogger +try: + import PySide6 +except ImportError: + import PySide2 from .logger import log_file_location, setup_ab_logging from .mod import bw2data diff --git a/activity_browser/actions/__init__.py b/activity_browser/actions/__init__.py index 6ca277e12..d56814f74 100644 --- a/activity_browser/actions/__init__.py +++ b/activity_browser/actions/__init__.py @@ -59,3 +59,4 @@ from .plugin_wizard_open import PluginWizardOpen from .settings_wizard_open import SettingsWizardOpen from .migrations_install import MigrationsInstall +from .pyside_upgrade import PysideUpgrade diff --git a/activity_browser/actions/activity/activity_delete.py b/activity_browser/actions/activity/activity_delete.py index 836a9cc5b..e69698fb2 100644 --- a/activity_browser/actions/activity/activity_delete.py +++ b/activity_browser/actions/activity/activity_delete.py @@ -1,6 +1,6 @@ from typing import List -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/activity/activity_duplicate.py b/activity_browser/actions/activity/activity_duplicate.py index b1c616a41..c52d8aa5f 100644 --- a/activity_browser/actions/activity/activity_duplicate.py +++ b/activity_browser/actions/activity/activity_duplicate.py @@ -1,6 +1,6 @@ from typing import Callable, List, Union -from PySide2 import QtCore +from qtpy import QtCore from activity_browser.actions.base import ABAction, exception_dialogs from activity_browser.bwutils import commontasks diff --git a/activity_browser/actions/activity/activity_duplicate_to_db.py b/activity_browser/actions/activity/activity_duplicate_to_db.py index b6fef79c0..9de268927 100644 --- a/activity_browser/actions/activity/activity_duplicate_to_db.py +++ b/activity_browser/actions/activity/activity_duplicate_to_db.py @@ -1,6 +1,6 @@ from typing import List -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application, project_settings from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/activity/activity_duplicate_to_loc.py b/activity_browser/actions/activity/activity_duplicate_to_loc.py index dd0d45bdc..08b51d1d9 100644 --- a/activity_browser/actions/activity/activity_duplicate_to_loc.py +++ b/activity_browser/actions/activity/activity_duplicate_to_loc.py @@ -1,7 +1,7 @@ from typing import Callable, Optional, Union import pandas as pd -from PySide2 import QtCore +from qtpy import QtCore from activity_browser import application, signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/activity/activity_modify.py b/activity_browser/actions/activity/activity_modify.py index 40b86f371..7e11068e6 100644 --- a/activity_browser/actions/activity/activity_modify.py +++ b/activity_browser/actions/activity/activity_modify.py @@ -1,6 +1,6 @@ from typing import Callable, Union -from PySide2 import QtCore +from qtpy import QtCore from activity_browser.actions.base import ABAction, exception_dialogs from activity_browser.mod.bw2data import get_activity diff --git a/activity_browser/actions/activity/activity_new.py b/activity_browser/actions/activity/activity_new.py index 527086724..10d5f53e1 100644 --- a/activity_browser/actions/activity/activity_new.py +++ b/activity_browser/actions/activity/activity_new.py @@ -1,6 +1,6 @@ from uuid import uuid4 -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/activity/activity_relink.py b/activity_browser/actions/activity/activity_relink.py index 347f0faf4..fbec1a54a 100644 --- a/activity_browser/actions/activity/activity_relink.py +++ b/activity_browser/actions/activity/activity_relink.py @@ -1,6 +1,6 @@ from typing import List -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/base.py b/activity_browser/actions/base.py index 2572e0f64..a7e61bdba 100644 --- a/activity_browser/actions/base.py +++ b/activity_browser/actions/base.py @@ -1,4 +1,4 @@ -from PySide2 import QtCore, QtGui, QtWidgets +from qtpy import QtCore, QtGui, QtWidgets from activity_browser import application diff --git a/activity_browser/actions/biosphere_update.py b/activity_browser/actions/biosphere_update.py index def55d202..acd3bb2ed 100644 --- a/activity_browser/actions/biosphere_update.py +++ b/activity_browser/actions/biosphere_update.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/calculation_setup/cs_delete.py b/activity_browser/actions/calculation_setup/cs_delete.py index a22f32c45..165fdb450 100644 --- a/activity_browser/actions/calculation_setup/cs_delete.py +++ b/activity_browser/actions/calculation_setup/cs_delete.py @@ -1,6 +1,6 @@ from logging import getLogger -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application, signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/calculation_setup/cs_duplicate.py b/activity_browser/actions/calculation_setup/cs_duplicate.py index 597edca85..69a675a2e 100644 --- a/activity_browser/actions/calculation_setup/cs_duplicate.py +++ b/activity_browser/actions/calculation_setup/cs_duplicate.py @@ -1,6 +1,6 @@ from logging import getLogger -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application, signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/calculation_setup/cs_new.py b/activity_browser/actions/calculation_setup/cs_new.py index 105ef1ccf..66ea2e2d0 100644 --- a/activity_browser/actions/calculation_setup/cs_new.py +++ b/activity_browser/actions/calculation_setup/cs_new.py @@ -1,6 +1,6 @@ from logging import getLogger -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application, signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/calculation_setup/cs_rename.py b/activity_browser/actions/calculation_setup/cs_rename.py index 735548f1f..8ca311c1a 100644 --- a/activity_browser/actions/calculation_setup/cs_rename.py +++ b/activity_browser/actions/calculation_setup/cs_rename.py @@ -1,6 +1,6 @@ from logging import getLogger -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application, signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/database/database_delete.py b/activity_browser/actions/database/database_delete.py index 26994a52a..6f85299a1 100644 --- a/activity_browser/actions/database/database_delete.py +++ b/activity_browser/actions/database/database_delete.py @@ -1,5 +1,5 @@ from bw2data.parameters import Group -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser import application, project_settings from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/database/database_duplicate.py b/activity_browser/actions/database/database_duplicate.py index 2aec75cea..411899a85 100644 --- a/activity_browser/actions/database/database_duplicate.py +++ b/activity_browser/actions/database/database_duplicate.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/database/database_export.py b/activity_browser/actions/database/database_export.py index 57810a00c..928710e5a 100644 --- a/activity_browser/actions/database/database_export.py +++ b/activity_browser/actions/database/database_export.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/database/database_new.py b/activity_browser/actions/database/database_new.py index 6f303b321..ec6fbdcfb 100644 --- a/activity_browser/actions/database/database_new.py +++ b/activity_browser/actions/database/database_new.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application, project_settings, signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/database/database_relink.py b/activity_browser/actions/database/database_relink.py index 48548ea46..80270cc89 100644 --- a/activity_browser/actions/database/database_relink.py +++ b/activity_browser/actions/database/database_relink.py @@ -1,4 +1,4 @@ -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/method/cf_new.py b/activity_browser/actions/method/cf_new.py index 4de62c16d..1f4419e8a 100644 --- a/activity_browser/actions/method/cf_new.py +++ b/activity_browser/actions/method/cf_new.py @@ -1,6 +1,6 @@ from typing import List -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/method/cf_remove.py b/activity_browser/actions/method/cf_remove.py index 51d0c5b55..b8300053b 100644 --- a/activity_browser/actions/method/cf_remove.py +++ b/activity_browser/actions/method/cf_remove.py @@ -1,6 +1,6 @@ from typing import List -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/method/method_delete.py b/activity_browser/actions/method/method_delete.py index 2471a86d2..ab47355e9 100644 --- a/activity_browser/actions/method/method_delete.py +++ b/activity_browser/actions/method/method_delete.py @@ -1,7 +1,7 @@ from typing import List from logging import getLogger -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/method/method_open.py b/activity_browser/actions/method/method_open.py index 480fadee7..6b1253232 100644 --- a/activity_browser/actions/method/method_open.py +++ b/activity_browser/actions/method/method_open.py @@ -1,6 +1,6 @@ from typing import List -from PySide2 import QtWidgets, QtCore +from qtpy import QtWidgets, QtCore from activity_browser import signals from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/migrations_install.py b/activity_browser/actions/migrations_install.py index 14d9305c3..d0ac29353 100644 --- a/activity_browser/actions/migrations_install.py +++ b/activity_browser/actions/migrations_install.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/parameter/parameter_new.py b/activity_browser/actions/parameter/parameter_new.py index 2eea4ad79..8fe2745fc 100644 --- a/activity_browser/actions/parameter/parameter_new.py +++ b/activity_browser/actions/parameter/parameter_new.py @@ -1,6 +1,6 @@ from typing import Tuple -from PySide2 import QtCore, QtGui, QtWidgets +from qtpy import QtCore, QtGui, QtWidgets from activity_browser import actions, application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/parameter/parameter_new_automatic.py b/activity_browser/actions/parameter/parameter_new_automatic.py index dc0f90aca..2a19f6dda 100644 --- a/activity_browser/actions/parameter/parameter_new_automatic.py +++ b/activity_browser/actions/parameter/parameter_new_automatic.py @@ -1,7 +1,7 @@ from typing import List, Tuple from peewee import IntegrityError -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/parameter/parameter_rename.py b/activity_browser/actions/parameter/parameter_rename.py index c1eee3147..4dd611e3a 100644 --- a/activity_browser/actions/parameter/parameter_rename.py +++ b/activity_browser/actions/parameter/parameter_rename.py @@ -1,6 +1,6 @@ from typing import Any -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/project/project_delete.py b/activity_browser/actions/project/project_delete.py index 87a96c65d..f5eb44711 100644 --- a/activity_browser/actions/project/project_delete.py +++ b/activity_browser/actions/project/project_delete.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import ab_settings, application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/project/project_duplicate.py b/activity_browser/actions/project/project_duplicate.py index 77d3bbcd4..724d3f30f 100644 --- a/activity_browser/actions/project/project_duplicate.py +++ b/activity_browser/actions/project/project_duplicate.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/project/project_export.py b/activity_browser/actions/project/project_export.py index 2c3f15282..c142e3a11 100644 --- a/activity_browser/actions/project/project_export.py +++ b/activity_browser/actions/project/project_export.py @@ -3,7 +3,7 @@ import tarfile from logging import getLogger -from PySide2 import QtWidgets, QtCore +from qtpy import QtWidgets, QtCore from activity_browser import application from activity_browser.mod import bw2data as bd diff --git a/activity_browser/actions/project/project_import.py b/activity_browser/actions/project/project_import.py index 777cc484a..0851a973d 100644 --- a/activity_browser/actions/project/project_import.py +++ b/activity_browser/actions/project/project_import.py @@ -3,7 +3,7 @@ import tarfile from logging import getLogger -from PySide2 import QtWidgets, QtCore +from qtpy import QtWidgets, QtCore from bw2io import backup from activity_browser import application diff --git a/activity_browser/actions/project/project_new.py b/activity_browser/actions/project/project_new.py index 7b6f7c5bd..f5728bcab 100644 --- a/activity_browser/actions/project/project_new.py +++ b/activity_browser/actions/project/project_new.py @@ -1,4 +1,4 @@ -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import application from activity_browser.actions.base import ABAction, exception_dialogs diff --git a/activity_browser/actions/pyside_upgrade.py b/activity_browser/actions/pyside_upgrade.py new file mode 100644 index 000000000..9be212352 --- /dev/null +++ b/activity_browser/actions/pyside_upgrade.py @@ -0,0 +1,100 @@ +import qtpy +import os +import sys +import subprocess +import time + +from activity_browser import application +from activity_browser.actions.base import ABAction, exception_dialogs +from activity_browser.ui import threading, icons + +from qtpy import QtWidgets +from qtpy.QtCore import Signal, SignalInstance + + +class PysideUpgrade(ABAction): + """ + ABAction to install PySide6 through PyPI/pip. Installs PySide6, sets the environment variable for QtPy to use + PySide6 and then restarts the Activity Browser through a subprocess. + """ + + icon = icons.qicons.forward + text = "Upgrade installation to PySide6" + + @classmethod + @exception_dialogs + def run(cls): + + # slot definition to update the progress dialog with thread updates + def update_dialog_slot(progress: int, label: str): + dialog.setValue(progress) + dialog.setLabelText(label) + + assert not qtpy.PYSIDE6, "Already running PySide6" + assert cls.in_conda(), "Not inside a Conda environment" + + # setup a progress dialog to show the user we're doing something + dialog = QtWidgets.QProgressDialog(application.main_window) + dialog.setWindowTitle("Upgrading GUI back-end") + dialog.setMaximum(0) + dialog.setCancelButton(None) + + # messages can get quite long, so enable word-wrapping + lbl = dialog.findChild(QtWidgets.QLabel) + lbl.setWordWrap(True) + + # initialize thread and connect signals + thread = PySideUpgradeThread(application) + thread.status.connect(update_dialog_slot) + thread.exit.connect(sys.exit) + + thread.start() + dialog.exec_() + + @staticmethod + def in_conda() -> bool: + """Returns true when the current shell is in a Conda environment.""" + return bool(os.environ.get("CONDA_DEFAULT_ENV", False)) + + +class PySideUpgradeThread(threading.ABThread): + exit: SignalInstance = Signal() + + def run_safely(self): + self.pip_installation() + self.restart() + + def pip_installation(self): + """ + Install PySide6 from PyPI using a subprocess.Popen call + """ + self.status.emit(0, "Installing PySide6 through pip") + + # open subprocess that installs PySide6 + process = subprocess.Popen(["pip", "install", "pyside6"], stdout=subprocess.PIPE) + + while process.poll() is None: # block until the subprocess is finished + # format stdout + line = process.stdout.readline().decode().strip() + if not line: + continue + + # redirect stdout to both console and progress dialog + print(line) + self.status.emit(0, line) + + assert process.returncode == 0, "Failed to install PySide6" + + def restart(self): + """ + Restarts the Activity Browser through a subprocess. Sleeps 5 seconds to allow the user to register + the restart. + """ + self.status.emit(0, "Restarting the Activity Browser") + subprocess.Popen(["python", "-c", "import activity_browser; activity_browser.run_activity_browser()"]) + time.sleep(5) + + # signal restart through the exit signal as sys.exit needs to be called in the main thread. + self.exit.emit() + + diff --git a/activity_browser/application.py b/activity_browser/application.py index bfd32f17d..c01120f07 100644 --- a/activity_browser/application.py +++ b/activity_browser/application.py @@ -2,8 +2,9 @@ import os from logging import getLogger -from PySide2.QtCore import QCoreApplication, QObject, QSysInfo, Qt -from PySide2.QtWidgets import QApplication +import qtpy +from qtpy.QtCore import QCoreApplication, QObject, QSysInfo, Qt +from qtpy.QtWidgets import QApplication, QStyleFactory log = getLogger(__name__) @@ -55,3 +56,6 @@ def deleteLater(self): QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts, True) application = ABApplication() + +if qtpy.PYSIDE6: + application.setStyle(QStyleFactory().create("fusion")) diff --git a/activity_browser/bwutils/calculations.py b/activity_browser/bwutils/calculations.py index 479480a7f..e9a42a9a6 100644 --- a/activity_browser/bwutils/calculations.py +++ b/activity_browser/bwutils/calculations.py @@ -2,7 +2,7 @@ from logging import getLogger from bw2calc.errors import BW2CalcError -from PySide2.QtWidgets import QApplication +from qtpy.QtWidgets import QApplication from ..bwutils import (MLCA, Contributions, MonteCarloLCA, SuperstructureContributions, SuperstructureMLCA) diff --git a/activity_browser/bwutils/multilca.py b/activity_browser/bwutils/multilca.py index 759c3da9f..694988064 100644 --- a/activity_browser/bwutils/multilca.py +++ b/activity_browser/bwutils/multilca.py @@ -6,7 +6,7 @@ import bw2calc as bc import numpy as np import pandas as pd -from PySide2.QtWidgets import QApplication, QMessageBox +from qtpy.QtWidgets import QApplication, QMessageBox from activity_browser.mod import bw2data as bd diff --git a/activity_browser/bwutils/superstructure/dataframe.py b/activity_browser/bwutils/superstructure/dataframe.py index 044c8b305..7359be890 100644 --- a/activity_browser/bwutils/superstructure/dataframe.py +++ b/activity_browser/bwutils/superstructure/dataframe.py @@ -5,8 +5,8 @@ import numpy as np import pandas as pd -from PySide2.QtCore import Qt -from PySide2.QtWidgets import QApplication, QPushButton +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QApplication, QPushButton from ..errors import ScenarioDatabaseNotFoundError from ..metadata import AB_metadata diff --git a/activity_browser/bwutils/superstructure/file_dialogs.py b/activity_browser/bwutils/superstructure/file_dialogs.py index 57e4f3897..34bbf6b54 100644 --- a/activity_browser/bwutils/superstructure/file_dialogs.py +++ b/activity_browser/bwutils/superstructure/file_dialogs.py @@ -1,5 +1,5 @@ import pandas as pd -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from ...ui.icons import qicons diff --git a/activity_browser/bwutils/superstructure/manager.py b/activity_browser/bwutils/superstructure/manager.py index dd9cd70e3..bd6ddcfc6 100644 --- a/activity_browser/bwutils/superstructure/manager.py +++ b/activity_browser/bwutils/superstructure/manager.py @@ -6,8 +6,8 @@ import numpy as np import pandas as pd from pandas.api.types import is_numeric_dtype -from PySide2.QtCore import Qt -from PySide2.QtWidgets import QApplication, QPushButton +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QApplication, QPushButton from activity_browser.mod import bw2data as bd diff --git a/activity_browser/bwutils/superstructure/mlca.py b/activity_browser/bwutils/superstructure/mlca.py index 31d6c4117..5f9a65cac 100644 --- a/activity_browser/bwutils/superstructure/mlca.py +++ b/activity_browser/bwutils/superstructure/mlca.py @@ -3,7 +3,7 @@ import numpy as np import pandas as pd -from PySide2.QtWidgets import QPushButton +from qtpy.QtWidgets import QPushButton from activity_browser.mod import bw2data as bd diff --git a/activity_browser/controllers/plugin.py b/activity_browser/controllers/plugin.py index db8342c12..a445eb8fb 100644 --- a/activity_browser/controllers/plugin.py +++ b/activity_browser/controllers/plugin.py @@ -3,7 +3,7 @@ from pkgutil import iter_modules from logging import getLogger -from PySide2.QtCore import QObject +from qtpy.QtCore import QObject from activity_browser import ab_settings, application, project_settings, signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/layouts/main.py b/activity_browser/layouts/main.py index 3fb6e80c8..68c473b25 100644 --- a/activity_browser/layouts/main.py +++ b/activity_browser/layouts/main.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets import activity_browser.mod.bw2data as bd diff --git a/activity_browser/layouts/panels/panel.py b/activity_browser/layouts/panels/panel.py index a6b87d01f..0fab2bdaa 100644 --- a/activity_browser/layouts/panels/panel.py +++ b/activity_browser/layouts/panels/panel.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from logging import getLogger from activity_browser import signals diff --git a/activity_browser/layouts/panels/right.py b/activity_browser/layouts/panels/right.py index 0b8e48525..b399e1014 100644 --- a/activity_browser/layouts/panels/right.py +++ b/activity_browser/layouts/panels/right.py @@ -1,7 +1,7 @@ from pathlib import Path from logging import getLogger -from PySide2.QtWidgets import QVBoxLayout +from qtpy.QtWidgets import QVBoxLayout from activity_browser import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/layouts/tabs/LCA_results_tab.py b/activity_browser/layouts/tabs/LCA_results_tab.py index 10728cfe8..7c914e105 100644 --- a/activity_browser/layouts/tabs/LCA_results_tab.py +++ b/activity_browser/layouts/tabs/LCA_results_tab.py @@ -3,8 +3,8 @@ from logging import getLogger from bw2calc.errors import BW2CalcError -from PySide2.QtCore import Qt, Slot -from PySide2.QtWidgets import QApplication, QMessageBox, QVBoxLayout +from qtpy.QtCore import Qt, Slot +from qtpy.QtWidgets import QApplication, QMessageBox, QVBoxLayout from activity_browser import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/layouts/tabs/LCA_results_tabs.py b/activity_browser/layouts/tabs/LCA_results_tabs.py index 3df4cae44..34938ccd4 100644 --- a/activity_browser/layouts/tabs/LCA_results_tabs.py +++ b/activity_browser/layouts/tabs/LCA_results_tabs.py @@ -9,8 +9,8 @@ from logging import getLogger import pandas as pd -from PySide2 import QtCore, QtGui -from PySide2.QtWidgets import (QApplication, QButtonGroup, QCheckBox, +from qtpy import QtCore, QtGui +from qtpy.QtWidgets import (QApplication, QButtonGroup, QCheckBox, QComboBox, QFileDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QRadioButton, QScrollArea, @@ -893,7 +893,7 @@ def __init__(self, parent, **kwargs): ) self.df = None - self.plot = ContributionPlot() + self.plot = ContributionPlot(self) self.table = ContributionTable(self) self.contribution_fn = None self.has_method, self.has_func = False, False @@ -1045,7 +1045,7 @@ def update_plot(self): # name is already altered by set_filename before update_plot occurs. name = self.plot.plot_name self.plot.deleteLater() - self.plot = ContributionPlot() + self.plot = ContributionPlot(self) self.pt_layout.insertWidget(idx, self.plot) super().update_plot(self.df, unit=self.unit) self.plot.plot_name = name diff --git a/activity_browser/layouts/tabs/LCA_setup.py b/activity_browser/layouts/tabs/LCA_setup.py index 8889e8828..44981c2d0 100644 --- a/activity_browser/layouts/tabs/LCA_setup.py +++ b/activity_browser/layouts/tabs/LCA_setup.py @@ -2,8 +2,8 @@ from logging import getLogger import pandas as pd -from PySide2 import QtWidgets -from PySide2.QtCore import Qt, Slot +from qtpy import QtWidgets +from qtpy.QtCore import Qt, Slot from activity_browser import actions, signals from activity_browser.mod import bw2data as bd @@ -707,7 +707,7 @@ def scenario_db_check(self, df: pd.DataFrame) -> pd.DataFrame: # check for databases in the scenario dataframe that cannot be linked to if unlinkable: dialog = ScenarioDatabaseDialog.construct_dialog(self._parent, relink) - if dialog.exec_() == dialog.Accepted: + if dialog.exec_() == QtWidgets.QDialog.Accepted: # TODO On update to bw2.5 this should be changed to use the bw2data.utils.get_node method return scenario_replace_databases(df, dialog.relink) # generate the required dialog diff --git a/activity_browser/layouts/tabs/activity.py b/activity_browser/layouts/tabs/activity.py index 4c328668e..1b2360d67 100644 --- a/activity_browser/layouts/tabs/activity.py +++ b/activity_browser/layouts/tabs/activity.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from peewee import DoesNotExist -from PySide2 import QtCore, QtWidgets -from PySide2.QtCore import Slot +from qtpy import QtCore, QtWidgets +from qtpy.QtCore import Slot from activity_browser import ab_settings, project_settings, signals from activity_browser.bwutils import commontasks as bc diff --git a/activity_browser/layouts/tabs/base.py b/activity_browser/layouts/tabs/base.py index cd3d8e5c1..0ca28d085 100644 --- a/activity_browser/layouts/tabs/base.py +++ b/activity_browser/layouts/tabs/base.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from PySide2.QtCore import Slot -from PySide2.QtWidgets import QMessageBox, QWidget +from qtpy.QtCore import Slot +from qtpy.QtWidgets import QMessageBox, QWidget class BaseRightTab(QWidget): diff --git a/activity_browser/layouts/tabs/history.py b/activity_browser/layouts/tabs/history.py index b86ff0d37..bbf0c5b39 100644 --- a/activity_browser/layouts/tabs/history.py +++ b/activity_browser/layouts/tabs/history.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from ...ui.style import header, horizontal_line from ...ui.tables import ActivitiesHistoryTable diff --git a/activity_browser/layouts/tabs/impact_categories.py b/activity_browser/layouts/tabs/impact_categories.py index 7270cec29..d7097cbf3 100644 --- a/activity_browser/layouts/tabs/impact_categories.py +++ b/activity_browser/layouts/tabs/impact_categories.py @@ -1,4 +1,4 @@ -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/layouts/tabs/parameters.py b/activity_browser/layouts/tabs/parameters.py index 79b1f38a6..8efbf45c7 100644 --- a/activity_browser/layouts/tabs/parameters.py +++ b/activity_browser/layouts/tabs/parameters.py @@ -2,8 +2,8 @@ from pathlib import Path import pandas as pd -from PySide2.QtCore import QSize, Qt, Slot -from PySide2.QtWidgets import (QAbstractButton, QCheckBox, QFileDialog, +from qtpy.QtCore import QSize, Qt, Slot +from qtpy.QtWidgets import (QAbstractButton, QCheckBox, QFileDialog, QHBoxLayout, QMessageBox, QPushButton, QSplitter, QStyle, QTabWidget, QToolBar, QVBoxLayout, QWidget) diff --git a/activity_browser/layouts/tabs/project_manager.py b/activity_browser/layouts/tabs/project_manager.py index 524518afe..d0f461c34 100644 --- a/activity_browser/layouts/tabs/project_manager.py +++ b/activity_browser/layouts/tabs/project_manager.py @@ -1,4 +1,4 @@ -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser import actions, signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/settings.py b/activity_browser/settings.py index b6aa61c16..cd2521f29 100644 --- a/activity_browser/settings.py +++ b/activity_browser/settings.py @@ -7,7 +7,7 @@ from logging import getLogger import appdirs -from PySide2.QtWidgets import QMessageBox +from qtpy.QtWidgets import QMessageBox from activity_browser.signals import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/signals.py b/activity_browser/signals.py index c2b18e102..4629749d1 100644 --- a/activity_browser/signals.py +++ b/activity_browser/signals.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from bw2data import Method, get_activity from bw2data.parameters import ParameterBase -from PySide2.QtCore import QObject, Qt, QThread, Signal, SignalInstance +from qtpy.QtCore import QObject, Qt, QThread, Signal, SignalInstance from .application import application diff --git a/activity_browser/ui/figures.py b/activity_browser/ui/figures.py index 4d65b9bf0..11dbee8e3 100644 --- a/activity_browser/ui/figures.py +++ b/activity_browser/ui/figures.py @@ -8,7 +8,7 @@ import seaborn as sns from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.figure import Figure -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser.mod.bw2data import methods from activity_browser.utils import savefilepath @@ -34,6 +34,9 @@ def __init__(self, parent=None): self.figure = Figure(constrained_layout=True) self.canvas = FigureCanvasQTAgg(self.figure) self.canvas.setMinimumHeight(0) + + self.canvas.destroyed.connect(self.check) + self.ax = self.figure.add_subplot(111) # create an axis self.plot_name = "Figure" @@ -46,6 +49,9 @@ def __init__(self, parent=None): ) self.updateGeometry() + def check(self): + print("WHY DELETE") + def plot(self, *args, **kwargs): raise NotImplementedError @@ -177,8 +183,8 @@ def plot(self, df: pd.DataFrame, invert_plot: bool = False): class ContributionPlot(Plot): MAX_LEGEND = 30 - def __init__(self): - super().__init__() + def __init__(self, parent=None): + super().__init__(parent) self.plot_name = "Contributions" def plot(self, df: pd.DataFrame, unit: str = None): diff --git a/activity_browser/ui/icons.py b/activity_browser/ui/icons.py index fb8e3916e..2820ea1d4 100644 --- a/activity_browser/ui/icons.py +++ b/activity_browser/ui/icons.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from pathlib import Path -from PySide2.QtGui import QIcon +from qtpy.QtGui import QIcon PACKAGE_DIR = Path(__file__).resolve().parents[1] diff --git a/activity_browser/ui/menu_bar.py b/activity_browser/ui/menu_bar.py index bda2dbcb5..ea59bc040 100644 --- a/activity_browser/ui/menu_bar.py +++ b/activity_browser/ui/menu_bar.py @@ -1,8 +1,8 @@ import os from importlib.metadata import version -from PySide2 import QtGui, QtWidgets -from PySide2.QtCore import QSize, QUrl, Slot +from qtpy import QtGui, QtWidgets +from qtpy.QtCore import QSize, QUrl, Slot from activity_browser import actions, signals, application, info from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/statusbar.py b/activity_browser/ui/statusbar.py index 31f4d56d8..5196b2f7f 100644 --- a/activity_browser/ui/statusbar.py +++ b/activity_browser/ui/statusbar.py @@ -1,7 +1,7 @@ from logging import getLogger -from PySide2.QtCore import Slot -from PySide2.QtWidgets import QLabel, QStatusBar +from qtpy.QtCore import Slot +from qtpy.QtWidgets import QLabel, QStatusBar from activity_browser import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/style.py b/activity_browser/ui/style.py index 07b97405b..12c055579 100644 --- a/activity_browser/ui/style.py +++ b/activity_browser/ui/style.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtGui, QtWidgets +from qtpy import QtGui, QtWidgets from activity_browser import ab_settings default_font = QtGui.QFont("Arial", 8) diff --git a/activity_browser/ui/tables/LCA_setup.py b/activity_browser/ui/tables/LCA_setup.py index 97d55b2d4..022c03519 100644 --- a/activity_browser/ui/tables/LCA_setup.py +++ b/activity_browser/ui/tables/LCA_setup.py @@ -1,7 +1,7 @@ from logging import getLogger -from PySide2 import QtWidgets -from PySide2.QtCore import Qt, Slot +from qtpy import QtWidgets +from qtpy.QtCore import Qt, Slot from activity_browser import signals, actions from activity_browser.mod.bw2data import calculation_setups @@ -20,7 +20,7 @@ class CSList(QtWidgets.QComboBox): def __init__(self, parent=None): super(CSList, self).__init__(parent) # Runs even if selection doesn't change - self.activated["QString"].connect(self.set_cs) + self.activated.connect(self.set_cs) signals.calculation_setup_selected.connect(self.sync) def sync(self, name): @@ -33,8 +33,8 @@ def sync(self, name): self.blockSignals(False) self.setCurrentIndex(keys.index(name)) - @staticmethod - def set_cs(name: str): + def set_cs(self, index: int): + name = self.itemText(index) signals.calculation_setup_selected.emit(name) @property diff --git a/activity_browser/ui/tables/activity.py b/activity_browser/ui/tables/activity.py index f41dcf616..0575672e6 100644 --- a/activity_browser/ui/tables/activity.py +++ b/activity_browser/ui/tables/activity.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from typing import List -from PySide2 import QtWidgets -from PySide2.QtCore import Slot +from qtpy import QtWidgets +from qtpy.QtCore import Slot from activity_browser import actions diff --git a/activity_browser/ui/tables/delegates/checkbox.py b/activity_browser/ui/tables/delegates/checkbox.py index 30559ee6e..ef8761ecf 100644 --- a/activity_browser/ui/tables/delegates/checkbox.py +++ b/activity_browser/ui/tables/delegates/checkbox.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets class CheckboxDelegate(QtWidgets.QStyledItemDelegate): diff --git a/activity_browser/ui/tables/delegates/database.py b/activity_browser/ui/tables/delegates/database.py index 2bd6a7b4c..a80441a05 100644 --- a/activity_browser/ui/tables/delegates/database.py +++ b/activity_browser/ui/tables/delegates/database.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- from bw2data import databases -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets class DatabaseDelegate(QtWidgets.QStyledItemDelegate): diff --git a/activity_browser/ui/tables/delegates/float.py b/activity_browser/ui/tables/delegates/float.py index 16f410c7a..61529c046 100644 --- a/activity_browser/ui/tables/delegates/float.py +++ b/activity_browser/ui/tables/delegates/float.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import math -from PySide2 import QtCore, QtGui, QtWidgets +from qtpy import QtCore, QtGui, QtWidgets class FloatDelegate(QtWidgets.QStyledItemDelegate): diff --git a/activity_browser/ui/tables/delegates/formula.py b/activity_browser/ui/tables/delegates/formula.py index cc036fc7b..f825d0c81 100644 --- a/activity_browser/ui/tables/delegates/formula.py +++ b/activity_browser/ui/tables/delegates/formula.py @@ -2,8 +2,8 @@ from os import devnull from asteval import Interpreter -from PySide2 import QtCore, QtGui, QtWidgets -from PySide2.QtCore import Signal, Slot +from qtpy import QtCore, QtGui, QtWidgets +from qtpy.QtCore import Signal, Slot from activity_browser import actions, signals diff --git a/activity_browser/ui/tables/delegates/list.py b/activity_browser/ui/tables/delegates/list.py index 0dcdc41cf..be7a5c183 100644 --- a/activity_browser/ui/tables/delegates/list.py +++ b/activity_browser/ui/tables/delegates/list.py @@ -2,7 +2,7 @@ from itertools import zip_longest from typing import List -from PySide2 import QtCore, QtGui, QtWidgets +from qtpy import QtCore, QtGui, QtWidgets class OrderedListInputDialog(QtWidgets.QDialog): diff --git a/activity_browser/ui/tables/delegates/string.py b/activity_browser/ui/tables/delegates/string.py index afec04dc5..fb5ce81f8 100644 --- a/activity_browser/ui/tables/delegates/string.py +++ b/activity_browser/ui/tables/delegates/string.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets class StringDelegate(QtWidgets.QStyledItemDelegate): diff --git a/activity_browser/ui/tables/delegates/uncertainty.py b/activity_browser/ui/tables/delegates/uncertainty.py index a6e203ec9..8238dc210 100644 --- a/activity_browser/ui/tables/delegates/uncertainty.py +++ b/activity_browser/ui/tables/delegates/uncertainty.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from stats_arrays import uncertainty_choices as uc from ....signals import signals diff --git a/activity_browser/ui/tables/delegates/viewonly.py b/activity_browser/ui/tables/delegates/viewonly.py index 4efd2d571..f6880b365 100644 --- a/activity_browser/ui/tables/delegates/viewonly.py +++ b/activity_browser/ui/tables/delegates/viewonly.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import math -from PySide2.QtWidgets import QStyledItemDelegate +from qtpy.QtWidgets import QStyledItemDelegate from .float import FloatDelegate from .uncertainty import UncertaintyDelegate diff --git a/activity_browser/ui/tables/history.py b/activity_browser/ui/tables/history.py index 9534fe524..d8fead91b 100644 --- a/activity_browser/ui/tables/history.py +++ b/activity_browser/ui/tables/history.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from PySide2.QtCore import Slot -from PySide2.QtWidgets import QAbstractItemView, QMenu +from qtpy.QtCore import Slot +from qtpy.QtWidgets import QAbstractItemView, QMenu from ..icons import qicons from .models import ActivitiesHistoryModel diff --git a/activity_browser/ui/tables/impact_categories.py b/activity_browser/ui/tables/impact_categories.py index b532c952a..330384829 100644 --- a/activity_browser/ui/tables/impact_categories.py +++ b/activity_browser/ui/tables/impact_categories.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from typing import Iterable -from PySide2 import QtWidgets -from PySide2.QtCore import QModelIndex, Slot, Qt +from qtpy import QtWidgets +from qtpy.QtCore import QModelIndex, Slot, Qt from activity_browser import actions from activity_browser.mod.bw2data import methods diff --git a/activity_browser/ui/tables/inventory.py b/activity_browser/ui/tables/inventory.py index c589ddf66..a4c6e855c 100644 --- a/activity_browser/ui/tables/inventory.py +++ b/activity_browser/ui/tables/inventory.py @@ -1,7 +1,7 @@ from typing import List, Iterable -from PySide2 import QtCore, QtWidgets -from PySide2.QtCore import Slot +from qtpy import QtCore, QtWidgets +from qtpy.QtCore import Slot from activity_browser import actions @@ -104,7 +104,7 @@ def __init__(self, parent=None): self.model = ActivitiesBiosphereListModel(parent=self) self.setDragEnabled(True) self.setDragDropMode(QtWidgets.QTableView.DragOnly) - self.setSelectionBehavior(self.SelectRows) + self.setSelectionBehavior(QtWidgets.QTableView.SelectRows) # context-menu items self.open_activity_action = actions.ActivityOpen.get_QAction(self.selected_keys) diff --git a/activity_browser/ui/tables/models/activity.py b/activity_browser/ui/tables/models/activity.py index 04c257b02..5f5bc0145 100644 --- a/activity_browser/ui/tables/models/activity.py +++ b/activity_browser/ui/tables/models/activity.py @@ -9,7 +9,7 @@ ProjectParameter) from bw2data.proxies import ExchangeProxyBase from peewee import DoesNotExist -from PySide2.QtCore import QModelIndex, Qt, Slot +from qtpy.QtCore import QModelIndex, Qt, Slot from activity_browser import actions, signals from activity_browser.bwutils import PedigreeMatrix diff --git a/activity_browser/ui/tables/models/base.py b/activity_browser/ui/tables/models/base.py index fb9db1bb5..4bc6f89a8 100644 --- a/activity_browser/ui/tables/models/base.py +++ b/activity_browser/ui/tables/models/base.py @@ -6,9 +6,9 @@ import arrow import numpy as np import pandas as pd -from PySide2.QtCore import (QAbstractItemModel, QAbstractTableModel, +from qtpy.QtCore import (QAbstractItemModel, QAbstractTableModel, QModelIndex, QSortFilterProxyModel, Qt, Signal) -from PySide2.QtGui import QBrush +from qtpy.QtGui import QBrush from activity_browser.bwutils import commontasks as bc from activity_browser.ui.style import style_item diff --git a/activity_browser/ui/tables/models/history.py b/activity_browser/ui/tables/models/history.py index af7e37370..bf868db28 100644 --- a/activity_browser/ui/tables/models/history.py +++ b/activity_browser/ui/tables/models/history.py @@ -1,5 +1,5 @@ import pandas as pd -from PySide2.QtCore import QModelIndex, Slot +from qtpy.QtCore import QModelIndex, Slot from activity_browser import signals from activity_browser.bwutils import commontasks as bc diff --git a/activity_browser/ui/tables/models/impact_categories.py b/activity_browser/ui/tables/models/impact_categories.py index 0753303fc..c887d4dff 100644 --- a/activity_browser/ui/tables/models/impact_categories.py +++ b/activity_browser/ui/tables/models/impact_categories.py @@ -4,7 +4,7 @@ import numpy as np import pandas as pd -from PySide2.QtCore import QModelIndex, Qt, Slot +from qtpy.QtCore import QModelIndex, Qt, Slot from activity_browser import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/tables/models/inventory.py b/activity_browser/ui/tables/models/inventory.py index 6624ee7ff..e63b62111 100644 --- a/activity_browser/ui/tables/models/inventory.py +++ b/activity_browser/ui/tables/models/inventory.py @@ -9,8 +9,8 @@ import numpy as np import pandas as pd -from PySide2.QtCore import QModelIndex, Qt, Slot -from PySide2.QtWidgets import QApplication +from qtpy.QtCore import QModelIndex, Qt, Slot +from qtpy.QtWidgets import QApplication import activity_browser from activity_browser import project_settings diff --git a/activity_browser/ui/tables/models/lca_setup.py b/activity_browser/ui/tables/models/lca_setup.py index 90f089f45..e9c1af43a 100644 --- a/activity_browser/ui/tables/models/lca_setup.py +++ b/activity_browser/ui/tables/models/lca_setup.py @@ -3,8 +3,8 @@ import numpy as np import pandas as pd -from PySide2 import QtWidgets -from PySide2.QtCore import QModelIndex, Qt, Slot +from qtpy import QtWidgets +from qtpy.QtCore import QModelIndex, Qt, Slot from activity_browser import signals, application from activity_browser.bwutils import commontasks as bc diff --git a/activity_browser/ui/tables/models/parameters.py b/activity_browser/ui/tables/models/parameters.py index 41b3ed3cf..80b1d0078 100644 --- a/activity_browser/ui/tables/models/parameters.py +++ b/activity_browser/ui/tables/models/parameters.py @@ -6,8 +6,8 @@ import pandas as pd from asteval import Interpreter from peewee import DoesNotExist -from PySide2 import QtWidgets -from PySide2.QtCore import QModelIndex, Slot +from qtpy import QtWidgets +from qtpy.QtCore import QModelIndex, Slot from activity_browser import actions, application from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/tables/models/plugins.py b/activity_browser/ui/tables/models/plugins.py index 67deed6b7..2605705b0 100644 --- a/activity_browser/ui/tables/models/plugins.py +++ b/activity_browser/ui/tables/models/plugins.py @@ -2,7 +2,7 @@ from importlib import metadata import pandas as pd -from PySide2.QtCore import QModelIndex +from qtpy.QtCore import QModelIndex from activity_browser.settings import ab_settings, project_settings from activity_browser.signals import qparameters, qprojects diff --git a/activity_browser/ui/tables/models/scenarios.py b/activity_browser/ui/tables/models/scenarios.py index b68bac909..795d73265 100644 --- a/activity_browser/ui/tables/models/scenarios.py +++ b/activity_browser/ui/tables/models/scenarios.py @@ -3,7 +3,7 @@ import numpy as np import pandas as pd -from PySide2.QtCore import Slot +from qtpy.QtCore import Slot from activity_browser.bwutils.utils import Parameters from activity_browser.mod.bw2data import parameters, projects diff --git a/activity_browser/ui/tables/parameters.py b/activity_browser/ui/tables/parameters.py index 85f604c85..8270ac85f 100644 --- a/activity_browser/ui/tables/parameters.py +++ b/activity_browser/ui/tables/parameters.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from asteval import Interpreter -from PySide2.QtCore import Slot -from PySide2.QtGui import QContextMenuEvent, QDragMoveEvent, QDropEvent -from PySide2.QtWidgets import QAction, QMenu, QMessageBox +from qtpy.QtCore import Slot +from qtpy.QtGui import QContextMenuEvent, QDragMoveEvent, QDropEvent +from qtpy.QtWidgets import QAction, QMenu, QMessageBox from activity_browser import actions, project_settings, signals diff --git a/activity_browser/ui/tables/plugins.py b/activity_browser/ui/tables/plugins.py index 925a43358..cbadcf8c1 100644 --- a/activity_browser/ui/tables/plugins.py +++ b/activity_browser/ui/tables/plugins.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import pandas -from PySide2 import QtCore, QtWidgets -from PySide2.QtWidgets import QMessageBox +from qtpy import QtCore, QtWidgets +from qtpy.QtWidgets import QMessageBox from ...signals import signals from .delegates import CheckboxDelegate diff --git a/activity_browser/ui/tables/projects.py b/activity_browser/ui/tables/projects.py index e6473576c..59e0d6abc 100644 --- a/activity_browser/ui/tables/projects.py +++ b/activity_browser/ui/tables/projects.py @@ -1,7 +1,7 @@ import os -from PySide2.QtCore import Qt -from PySide2.QtWidgets import QComboBox, QSizePolicy +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QComboBox, QSizePolicy from activity_browser import actions from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/tables/scenarios.py b/activity_browser/ui/tables/scenarios.py index 12021148e..3cc88c271 100644 --- a/activity_browser/ui/tables/scenarios.py +++ b/activity_browser/ui/tables/scenarios.py @@ -1,6 +1,6 @@ from typing import Iterable, Tuple -from PySide2.QtCore import Slot +from qtpy.QtCore import Slot from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/tables/views.py b/activity_browser/ui/tables/views.py index 363d43127..7f2aef05c 100644 --- a/activity_browser/ui/tables/views.py +++ b/activity_browser/ui/tables/views.py @@ -2,9 +2,9 @@ from typing import Optional from logging import getLogger -from PySide2 import QtGui, QtWidgets -from PySide2.QtCore import QPoint, QRect, QSize, Qt, QTimer, Signal, Slot -from PySide2.QtWidgets import QApplication, QSizePolicy, QTableView +from qtpy import QtGui, QtWidgets +from qtpy.QtCore import QPoint, QRect, QSize, Qt, QTimer, Signal, Slot +from qtpy.QtWidgets import QApplication, QSizePolicy, QTableView from activity_browser import ab_settings from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/threading.py b/activity_browser/ui/threading.py index 191bc1876..b861c6a6b 100644 --- a/activity_browser/ui/threading.py +++ b/activity_browser/ui/threading.py @@ -5,7 +5,7 @@ from activity_browser.mod import bw2data as bd from activity_browser.logger import exception_hook -from PySide2.QtCore import QThread, SignalInstance, Signal +from qtpy.QtCore import QThread, SignalInstance, Signal class ABThread(QThread): diff --git a/activity_browser/ui/web/base.py b/activity_browser/ui/web/base.py index 9d1ca6c70..e05a43c49 100644 --- a/activity_browser/ui/web/base.py +++ b/activity_browser/ui/web/base.py @@ -5,8 +5,8 @@ from typing import Type from logging import getLogger -from PySide2 import QtWebChannel, QtWebEngineWidgets, QtWidgets -from PySide2.QtCore import QObject, Qt, QUrl, Signal, Slot +from qtpy import QtWebChannel, QtWebEngineWidgets, QtWidgets +from qtpy.QtCore import QObject, Qt, QUrl, Signal, Slot from activity_browser import ab_settings, signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/web/navigator.py b/activity_browser/ui/web/navigator.py index 05417758e..f1ac16927 100644 --- a/activity_browser/ui/web/navigator.py +++ b/activity_browser/ui/web/navigator.py @@ -6,8 +6,8 @@ from logging import getLogger import networkx as nx -from PySide2 import QtWidgets -from PySide2.QtCore import Slot +from qtpy import QtWidgets +from qtpy.QtCore import Slot from activity_browser import signals from activity_browser.mod.bw2data import Database, get_activity diff --git a/activity_browser/ui/web/sankey_navigator.py b/activity_browser/ui/web/sankey_navigator.py index e637ed3cc..07d9ed0f6 100644 --- a/activity_browser/ui/web/sankey_navigator.py +++ b/activity_browser/ui/web/sankey_navigator.py @@ -6,9 +6,9 @@ from logging import getLogger import bw2calc as bc -from PySide2 import QtWidgets -from PySide2.QtCore import Slot -from PySide2.QtWidgets import QComboBox +from qtpy import QtWidgets +from qtpy.QtCore import Slot +from qtpy.QtWidgets import QComboBox from activity_browser import signals from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/web/webutils.py b/activity_browser/ui/web/webutils.py index 072d4d040..3fc0c445e 100644 --- a/activity_browser/ui/web/webutils.py +++ b/activity_browser/ui/web/webutils.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import os -from PySide2 import QtCore, QtGui, QtWebEngineWidgets, QtWidgets +from qtpy import QtCore, QtGui, QtWebEngineWidgets, QtWidgets # type "localhost:3999" in Chrome for DevTools of AB web content from activity_browser.utils import get_base_path diff --git a/activity_browser/ui/widgets/activity.py b/activity_browser/ui/widgets/activity.py index b501795ba..aee09d5ab 100644 --- a/activity_browser/ui/widgets/activity.py +++ b/activity_browser/ui/widgets/activity.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser import actions, project_settings, signals diff --git a/activity_browser/ui/widgets/biosphere_update.py b/activity_browser/ui/widgets/biosphere_update.py index e5b885f39..a933b9683 100644 --- a/activity_browser/ui/widgets/biosphere_update.py +++ b/activity_browser/ui/widgets/biosphere_update.py @@ -1,8 +1,8 @@ from logging import getLogger import bw2io.data as data -from PySide2 import QtWidgets -from PySide2.QtCore import Signal, Slot +from qtpy import QtWidgets +from qtpy.QtCore import Signal, Slot from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/widgets/comparison_switch.py b/activity_browser/ui/widgets/comparison_switch.py index 76193243d..c0a3b34a3 100644 --- a/activity_browser/ui/widgets/comparison_switch.py +++ b/activity_browser/ui/widgets/comparison_switch.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from collections import namedtuple -from PySide2 import QtWidgets +from qtpy import QtWidgets Switches = namedtuple("switches", ("func", "method", "scenario")) diff --git a/activity_browser/ui/widgets/cutoff_menu.py b/activity_browser/ui/widgets/cutoff_menu.py index bf1f45f60..864c47b85 100644 --- a/activity_browser/ui/widgets/cutoff_menu.py +++ b/activity_browser/ui/widgets/cutoff_menu.py @@ -10,10 +10,10 @@ from typing import Union import numpy as np -from PySide2 import QtCore -from PySide2.QtCore import QLocale, Qt, Signal, Slot -from PySide2.QtGui import QDoubleValidator, QIntValidator -from PySide2.QtWidgets import (QButtonGroup, QHBoxLayout, QLabel, QLineEdit, +from qtpy import QtCore +from qtpy.QtCore import QLocale, Qt, Signal, Slot +from qtpy.QtGui import QDoubleValidator, QIntValidator +from qtpy.QtWidgets import (QButtonGroup, QHBoxLayout, QLabel, QLineEdit, QPushButton, QRadioButton, QSlider, QVBoxLayout, QWidget) diff --git a/activity_browser/ui/widgets/dialog.py b/activity_browser/ui/widgets/dialog.py index 95eab30e0..200742913 100644 --- a/activity_browser/ui/widgets/dialog.py +++ b/activity_browser/ui/widgets/dialog.py @@ -2,8 +2,8 @@ from typing import List, Tuple import bw2io as bi -from PySide2 import QtGui, QtWidgets -from PySide2.QtCore import Qt, Signal, Slot +from qtpy import QtGui, QtWidgets +from qtpy.QtCore import Qt, Signal, Slot from activity_browser import project_settings, signals from activity_browser.bwutils.superstructure import get_sheet_names diff --git a/activity_browser/ui/widgets/line_edit.py b/activity_browser/ui/widgets/line_edit.py index 0756cd0ef..4791476c0 100644 --- a/activity_browser/ui/widgets/line_edit.py +++ b/activity_browser/ui/widgets/line_edit.py @@ -1,6 +1,6 @@ -from PySide2 import QtWidgets -from PySide2.QtCore import Slot -from PySide2.QtGui import QTextFormat +from qtpy import QtWidgets +from qtpy.QtCore import Slot +from qtpy.QtGui import QTextFormat from activity_browser import actions diff --git a/activity_browser/ui/widgets/message.py b/activity_browser/ui/widgets/message.py index f53c45f5d..26993941b 100644 --- a/activity_browser/ui/widgets/message.py +++ b/activity_browser/ui/widgets/message.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from PySide2.QtCore import Qt -from PySide2.QtWidgets import QMessageBox +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QMessageBox def parameter_save_errorbox(parent, error) -> int: diff --git a/activity_browser/ui/wizards/db_export_wizard.py b/activity_browser/ui/wizards/db_export_wizard.py index 07e4d3322..bbfe508fb 100644 --- a/activity_browser/ui/wizards/db_export_wizard.py +++ b/activity_browser/ui/wizards/db_export_wizard.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- import os -from PySide2 import QtWidgets -from PySide2.QtCore import Slot +from qtpy import QtWidgets +from qtpy.QtCore import Slot from activity_browser.bwutils import exporters as exp from activity_browser.mod import bw2data as bd diff --git a/activity_browser/ui/wizards/db_import_wizard.py b/activity_browser/ui/wizards/db_import_wizard.py index 8072d7c0f..6e89c2f27 100644 --- a/activity_browser/ui/wizards/db_import_wizard.py +++ b/activity_browser/ui/wizards/db_import_wizard.py @@ -14,8 +14,8 @@ import requests from bw2io import BW2Package, SingleOutputEcospold2Importer from bw2io.extractors import Ecospold2DataExtractor -from PySide2 import QtCore, QtWidgets -from PySide2.QtCore import Signal, Slot +from qtpy import QtCore, QtWidgets +from qtpy.QtCore import Signal, Slot from py7zr import py7zr from activity_browser.bwutils import errors @@ -52,7 +52,7 @@ def __init__(self, parent=None): self.setWindowModality(QtCore.Qt.ApplicationModal) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowFlags(QtCore.Qt.Sheet) - self.setOption(self.NoCancelButton, False) + self.setOption(QtWidgets.QWizard.NoCancelButton, False) # Construct and bind pages. self.import_type_page = ImportTypePage(self) @@ -708,7 +708,7 @@ def fix_db_import(self, missing: set) -> None: options = [(db, list(bd.databases)) for db in missing] linker = DatabaseLinkingDialog.relink_bw2package(options, self) - if linker.exec_() == DatabaseLinkingDialog.Accepted: + if linker.exec_() == QtWidgets.QDialog.Accepted: self.relink_data = linker.links else: # If the user at any point did not accept their choice, fail. @@ -736,7 +736,7 @@ def fix_excel_import(self, exchanges: list, missing: set) -> None: # Iterate through the missing databases, asking user input. options = [(db, list(bd.databases)) for db in missing] linker = DatabaseLinkingDialog.relink_excel(options, self) - if linker.exec_() == DatabaseLinkingDialog.Accepted: + if linker.exec_() == QtWidgets.QDialog.Accepted: self.relink_data = linker.links else: error = ( diff --git a/activity_browser/ui/wizards/plugins_manager_wizard.py b/activity_browser/ui/wizards/plugins_manager_wizard.py index 08788c21e..3f14bc329 100644 --- a/activity_browser/ui/wizards/plugins_manager_wizard.py +++ b/activity_browser/ui/wizards/plugins_manager_wizard.py @@ -1,6 +1,6 @@ import pandas -from PySide2 import QtCore, QtWidgets -from PySide2.QtCore import Qt, Slot +from qtpy import QtCore, QtWidgets +from qtpy.QtCore import Qt, Slot from ...signals import signals from ...ui.style import header diff --git a/activity_browser/ui/wizards/project_setup_wizard.py b/activity_browser/ui/wizards/project_setup_wizard.py index a572f54b1..870514117 100644 --- a/activity_browser/ui/wizards/project_setup_wizard.py +++ b/activity_browser/ui/wizards/project_setup_wizard.py @@ -1,6 +1,6 @@ import ecoinvent_interface as ei import requests -from PySide2 import QtWidgets, QtCore +from qtpy import QtWidgets, QtCore from activity_browser.ui.threading import ABThread from activity_browser.mod.bw2io import ab_bw2setup @@ -20,10 +20,10 @@ def __init__(self, parent=None): super().__init__(parent) # setting wizard options - self.setWizardStyle(self.ModernStyle) - self.setOption(self.NoCancelButtonOnLastPage) - self.setOption(self.NoBackButtonOnLastPage) - self.setOption(self.NoCancelButton, False) + self.setWizardStyle(QtWidgets.QWizard.ModernStyle) + self.setOption(QtWidgets.QWizard.NoCancelButtonOnLastPage) + self.setOption(QtWidgets.QWizard.NoBackButtonOnLastPage) + self.setOption(QtWidgets.QWizard.NoCancelButton, False) # setting window options self.setWindowTitle("Project Setup") diff --git a/activity_browser/ui/wizards/settings_wizard.py b/activity_browser/ui/wizards/settings_wizard.py index 27a4f8ff7..3b63e009e 100644 --- a/activity_browser/ui/wizards/settings_wizard.py +++ b/activity_browser/ui/wizards/settings_wizard.py @@ -3,13 +3,14 @@ from logging import getLogger from peewee import SqliteDatabase -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets, PYSIDE6 -from activity_browser import ab_settings +from activity_browser import ab_settings, actions from activity_browser.mod.bw2data import projects log = getLogger(__name__) + class SettingsWizard(QtWidgets.QWizard): def __init__(self, parent=None): super().__init__(parent) @@ -107,6 +108,10 @@ def __init__(self, parent=None): self.layout = QtWidgets.QVBoxLayout() self.layout.addWidget(self.startup_groupbox) + + if not PYSIDE6: + self.layout.addWidget(PySide6Switch(self)) + self.layout.addStretch() self.layout.addWidget(self.restore_defaults_button) self.setLayout(self.layout) @@ -304,3 +309,14 @@ def changed(self): def isComplete(self): return self.complete + + +class PySide6Switch(QtWidgets.QGroupBox): + def __init__(self, parent=None): + super().__init__("Upgrade GUI back-end", parent) + self.upgrade_button = actions.PysideUpgrade.get_QButton() + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.upgrade_button) + self.setLayout(layout) + diff --git a/activity_browser/ui/wizards/uncertainty.py b/activity_browser/ui/wizards/uncertainty.py index 854dc5922..1b69a242d 100644 --- a/activity_browser/ui/wizards/uncertainty.py +++ b/activity_browser/ui/wizards/uncertainty.py @@ -1,8 +1,8 @@ from logging import getLogger import numpy as np -from PySide2 import QtCore, QtGui, QtWidgets -from PySide2.QtCore import Signal, Slot +from qtpy import QtCore, QtGui, QtWidgets +from qtpy.QtCore import Signal, Slot from stats_arrays import uncertainty_choices as uncertainty from stats_arrays.distributions import * diff --git a/activity_browser/utils.py b/activity_browser/utils.py index 1f930c2a1..e62ed712e 100644 --- a/activity_browser/utils.py +++ b/activity_browser/utils.py @@ -3,7 +3,7 @@ from typing import Iterable, Tuple import requests -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser.mod import bw2data as bd diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 7baf40e93..ead8f9400 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -33,6 +33,7 @@ requirements: - pint <=0.21 - pyperclip - pyside2 >=5.15.5 + - qtpy - qt-webengine - salib >=1.4 - seaborn diff --git a/tests/actions/test_activity_actions.py b/tests/actions/test_activity_actions.py index 2161eeeb2..b2aeb6559 100644 --- a/tests/actions/test_activity_actions.py +++ b/tests/actions/test_activity_actions.py @@ -1,6 +1,6 @@ import bw2data as bd import pytest -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import actions from activity_browser.mod.bw2data import Database diff --git a/tests/actions/test_calculation_setup_actions.py b/tests/actions/test_calculation_setup_actions.py index 6ea6777d8..944ac97f2 100644 --- a/tests/actions/test_calculation_setup_actions.py +++ b/tests/actions/test_calculation_setup_actions.py @@ -1,5 +1,5 @@ import bw2data as bd -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import actions diff --git a/tests/actions/test_database_actions.py b/tests/actions/test_database_actions.py index 7f173bbb7..42cc58cff 100644 --- a/tests/actions/test_database_actions.py +++ b/tests/actions/test_database_actions.py @@ -1,5 +1,5 @@ import bw2data as bd -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import actions, application from activity_browser.actions.database.database_duplicate import \ diff --git a/tests/actions/test_exchange_actions.py b/tests/actions/test_exchange_actions.py index 750c14908..57d67b67d 100644 --- a/tests/actions/test_exchange_actions.py +++ b/tests/actions/test_exchange_actions.py @@ -2,7 +2,7 @@ import bw2data as bd import pytest -from PySide2 import QtGui +from qtpy import QtGui from stats_arrays.distributions import NormalUncertainty, UndefinedUncertainty from activity_browser import actions, application diff --git a/tests/actions/test_method_actions.py b/tests/actions/test_method_actions.py index 35148928b..e25d90b87 100644 --- a/tests/actions/test_method_actions.py +++ b/tests/actions/test_method_actions.py @@ -1,5 +1,5 @@ import bw2data as bd -from PySide2 import QtWidgets +from qtpy import QtWidgets from stats_arrays.distributions import (NormalUncertainty, UndefinedUncertainty, UniformUncertainty) diff --git a/tests/actions/test_parameter_actions.py b/tests/actions/test_parameter_actions.py index accfbb59a..9c6241f88 100644 --- a/tests/actions/test_parameter_actions.py +++ b/tests/actions/test_parameter_actions.py @@ -1,7 +1,7 @@ import bw2data as bd from bw2data.parameters import (ActivityParameter, DatabaseParameter, ProjectParameter) -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import actions from activity_browser.actions.parameter.parameter_new import ParameterWizard diff --git a/tests/actions/test_project_actions.py b/tests/actions/test_project_actions.py index fae34f7d7..b7282ee3c 100644 --- a/tests/actions/test_project_actions.py +++ b/tests/actions/test_project_actions.py @@ -1,7 +1,7 @@ import os.path import bw2data as bd -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import actions, ab_settings, application from activity_browser.ui.widgets import ProjectDeletionDialog from activity_browser.actions.project.project_export import ExportThread diff --git a/tests/actions/test_various_actions.py b/tests/actions/test_various_actions.py index 31b03cf96..2f2fc8406 100644 --- a/tests/actions/test_various_actions.py +++ b/tests/actions/test_various_actions.py @@ -3,7 +3,7 @@ import bw2data as bd import bw2io as bi import pytest -from PySide2 import QtWidgets +from qtpy import QtWidgets from activity_browser import actions, application from activity_browser.mod.bw2data import Database diff --git a/tests/legacy/test_widgets.py b/tests/legacy/test_widgets.py index 2524e6174..408ee6964 100644 --- a/tests/legacy/test_widgets.py +++ b/tests/legacy/test_widgets.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from PySide2.QtCore import Qt -from PySide2.QtWidgets import QDialogButtonBox, QMessageBox, QWidget +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QDialogButtonBox, QMessageBox, QWidget from activity_browser.ui.widgets import (BiosphereUpdater, CutoffMenu, ForceInputDialog, SwitchComboBox, diff --git a/tests/wizards/test_export_wizard.py b/tests/wizards/test_export_wizard.py index 0fc61e7ef..f5b066d81 100644 --- a/tests/wizards/test_export_wizard.py +++ b/tests/wizards/test_export_wizard.py @@ -1,4 +1,4 @@ -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser.ui.wizards.db_export_wizard import DatabaseExportWizard diff --git a/tests/wizards/test_import_wizard.py b/tests/wizards/test_import_wizard.py index 3ead27149..61095f524 100644 --- a/tests/wizards/test_import_wizard.py +++ b/tests/wizards/test_import_wizard.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from PySide2 import QtCore, QtWidgets +from qtpy import QtCore, QtWidgets from activity_browser.ui.wizards.db_import_wizard import DatabaseImportWizard diff --git a/tests/wizards/test_uncertainty_wizard.py b/tests/wizards/test_uncertainty_wizard.py index eac97de48..73a91ed85 100644 --- a/tests/wizards/test_uncertainty_wizard.py +++ b/tests/wizards/test_uncertainty_wizard.py @@ -5,7 +5,7 @@ import numpy as np import pytest from bw2data.parameters import ProjectParameter -from PySide2.QtWidgets import QMessageBox, QWizard +from qtpy.QtWidgets import QMessageBox, QWizard from stats_arrays.distributions import (LognormalUncertainty, TriangularUncertainty, UndefinedUncertainty,