Source code for pyomo.contrib.viewer.qt

# ____________________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2026 National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and Engineering
# Solutions of Sandia, LLC, the U.S. Government retains certain rights in this
# software.  This software is distributed under the 3-clause BSD License.
# ____________________________________________________________________________________
#
# This module was originally developed as part of the IDAES PSE Framework
#
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018-2019, by the
# software owners: The Regents of the University of California, through
# Lawrence Berkeley National Laboratory,  National Technology & Engineering
# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia
# University Research Corporation, et al. All rights reserved.
#
# This software is distributed under the 3-clause BSD License.
# ____________________________________________________________________________________

"""
Try to import PySide6, which is the current official Qt 6 Python interface. Then,
try PyQt5 if that doesn't work. If no compatible Qt Python interface is found,
use some dummy classes to allow some testing.
"""

__author__ = "John Eslick"
import sys
import enum
import importlib

from pyomo.common.collections import Bunch
from pyomo.common.flags import building_documentation

# Supported Qt wrappers in preferred order
supported = ["PySide6", "PyQt6", "PyQt5"]
# Import errors encountered, delay logging for testing reasons
import_errors = []
# Set this to the Qt wrapper module is available
available = False

# You can only have one Qt interface loaded at a time.  If something
# like IPython has already loaded an interface, then we will use that
# one.
_loaded = list(filter(sys.modules.__contains__, supported))
if _loaded:
    supported = _loaded

for module_str in supported:
    try:
        qt_package = importlib.import_module(module_str)
        QtWidgets = importlib.import_module(f"{module_str}.QtWidgets")
        QtCore = importlib.import_module(f"{module_str}.QtCore")
        QtGui = importlib.import_module(f"{module_str}.QtGui")
        available = module_str
        break
    except Exception as e:
        qt_package = QtWidgets = QtCore = QtGui = None
        import_errors.append(f"{e}")

if not available:
    # If Qt is not available, we still want to be able to test as much
    # as we can, so add some dummy classes that allow for testing
[docs] class Qt:
[docs] class ItemDataRole(enum.Enum): EditRole = 1 DisplayRole = 2 ToolTipRole = 3 ForegroundRole = 4
[docs] class QtCore: """ A dummy QtCore class to allow some testing without PyQt """ class QModelIndex: pass Qt = Qt
class QAbstractItemModel: """ A dummy QAbstractItemModel class to allow some testing without PyQt """
[docs] def __init__(*args, **kwargs): pass
class QAbstractTableModel: """ A dummy QAbstractTableModel class to allow some testing without PyQt """
[docs] def __init__(*args, **kwargs): pass
[docs] class QItemEditorCreatorBase: """ A dummy QItemEditorCreatorBase class to allow some testing without PyQt """ pass
[docs] class QItemDelegate: """ A dummy QItemDelegate class to allow some testing without PyQt """ pass
else: QAbstractItemView = QtWidgets.QAbstractItemView QFileDialog = QtWidgets.QFileDialog QMainWindow = QtWidgets.QMainWindow QMdiArea = QtWidgets.QMdiArea QApplication = QtWidgets.QApplication QTableWidgetItem = QtWidgets.QTableWidgetItem QStatusBar = QtWidgets.QStatusBar QLineEdit = QtWidgets.QLineEdit QItemEditorFactory = QtWidgets.QItemEditorFactory QItemEditorCreatorBase = QtWidgets.QItemEditorCreatorBase QStyledItemDelegate = QtWidgets.QStyledItemDelegate QItemDelegate = QtWidgets.QItemDelegate QComboBox = QtWidgets.QComboBox QMessageBox = QtWidgets.QMessageBox QColor = QtGui.QColor QAbstractItemModel = QtCore.QAbstractItemModel QAbstractTableModel = QtCore.QAbstractTableModel Qt = QtCore.Qt QMetaType = Bunch() if available == "PySide6": from PySide6.QtGui import QAction from PySide6.QtCore import Signal from PySide6 import QtUiTools as uic QMetaType.Int = QtCore.QMetaType.Type.Int.value QMetaType.Double = QtCore.QMetaType.Type.Double.value elif available == "PyQt6": from PyQt6.QtGui import QAction from PyQt6.QtCore import pyqtSignal as Signal from PyQt6 import uic QMetaType.Int = QtCore.QMetaType.Type.Int.value QMetaType.Double = QtCore.QMetaType.Type.Double.value elif available == "PyQt5": from PyQt5.QtWidgets import QAction from PyQt5.QtCore import pyqtSignal as Signal from PyQt5 import uic QMetaType.Int = QtCore.QMetaType.Type.Int QMetaType.Double = QtCore.QMetaType.Type.Double else: raise RuntimeError(f"Unknown Qt engine: {available}") # Note that QAbstractTableModel and QAbstractItemModel have # signatures that are not parsable by Sphinx, so we will hide them # if we are building the API documentation. if building_documentation():
[docs] class QAbstractItemModel: pass
[docs] class QAbstractTableModel: pass