Source code for tools.UI_confComponents
#!/usr/bin/python3
# -*- coding: utf-8 -*-
'''Pychemqt, Chemical Engineering Process simulator
Copyright (C) 2009-2025, Juan José Gómez Romera <jjgomera@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Dialog to define the chemical compounds used in the project, both normal \
fluids and solids
.. image:: images/UI_confComponents.png
:alt: UI_confComponents
The module include all related widget for components configuration:
* :class:`UI_confComponents_widget`: Components list widget, to use in \
whatever need, dialog, wizard...
* :class:`Dialog`: Standalone dialog
API reference
-------------
'''
from ast import literal_eval as eval2
import os
from lib.config import IMAGE_PATH
from tools.qt import QtCore, QtGui, QtWidgets
from tools.UI_databank import UI_databank_widget
[docs]
class UI_confComponents_widget(QtWidgets.QWidget):
"""Component list widget to use in dialor and in wizard"""
componentChanged = QtCore.pyqtSignal("bool")
[docs]
def __init__(self, config=None, solido=True, parent=None):
"""Constructor, opcional config parameter with project config"""
super().__init__(parent)
layout = QtWidgets.QGridLayout(self)
self.databank = UI_databank_widget()
self.databank.BaseDatos.itemSelectionChanged.connect(
self.comprobarBotones)
layout.addWidget(self.databank, 1, 1, 17, 1)
layout.addItem(QtWidgets.QSpacerItem(
30, 30, QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Fixed), 1, 2, 1, 2)
layout.addWidget(QtWidgets.QLabel(self.tr("Components list")), 2, 3)
self.DeleteComponente = QtWidgets.QToolButton()
self.DeleteComponente.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "arrow-left.png"))))
self.DeleteComponente.clicked.connect(self.Delete)
layout.addWidget(self.DeleteComponente, 4, 2)
self.AddComponente = QtWidgets.QToolButton()
self.AddComponente.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "arrow-right.png"))))
self.AddComponente.clicked.connect(self.Add)
layout.addWidget(self.AddComponente, 5, 2)
self.Arriba = QtWidgets.QToolButton()
self.Arriba.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "arrow-up.png"))))
self.Arriba.clicked.connect(self.Up)
layout.addWidget(self.Arriba, 6, 2)
self.Abajo = QtWidgets.QToolButton()
self.Abajo.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "arrow-down.png"))))
self.Abajo.clicked.connect(self.Down)
layout.addWidget(self.Abajo, 7, 2)
self.clearComp = QtWidgets.QToolButton()
self.clearComp.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "clear.png"))))
self.clearComp.clicked.connect(self.clear)
layout.addWidget(self.clearComp, 8, 2)
self.ListaComponentes = QtWidgets.QListWidget()
self.ListaComponentes.setSizePolicy(
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Expanding)
self.ListaComponentes.itemSelectionChanged.connect(
self.comprobarBotones)
layout.addWidget(self.ListaComponentes, 3, 3, 7, 1)
self.DeleteSolido = QtWidgets.QToolButton()
self.DeleteSolido.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "arrow-left.png"))))
self.DeleteSolido.clicked.connect(self.DeleteSolid)
layout.addWidget(self.DeleteSolido, 13, 2)
self.AddSolido = QtWidgets.QToolButton()
self.AddSolido.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "arrow-right.png"))))
self.AddSolido.clicked.connect(self.AddSolid)
layout.addWidget(self.AddSolido, 14, 2)
self.clearSolido = QtWidgets.QToolButton()
self.clearSolido.setIcon(QtGui.QIcon(QtGui.QPixmap(os.path.join(
IMAGE_PATH, "button", "clear.png"))))
self.clearSolido.clicked.connect(self.clearSolids)
layout.addWidget(self.clearSolido, 15, 2)
self.ListaSolidos = QtWidgets.QListWidget()
self.ListaSolidos.setFixedHeight(100)
self.ListaSolidos.itemSelectionChanged.connect(self.comprobarBotones)
layout.addWidget(self.ListaSolidos, 12, 3, 5, 1)
if solido:
layout.addItem(QtWidgets.QSpacerItem(
20, 20, QtWidgets.QSizePolicy.Policy.Fixed,
QtWidgets.QSizePolicy.Policy.Expanding), 10, 4, 1, 1)
layout.addWidget(QtWidgets.QLabel(self.tr("Solids", None)), 11, 3)
else:
self.DeleteSolido.setVisible(False)
self.AddSolido.setVisible(False)
self.clearSolido.setVisible(False)
self.ListaSolidos.setVisible(False)
self.indices = []
self.solidos = []
if config and config.has_section("Components"):
self.indices = eval2(config.get("Components", "Components"))
self.solidos = eval2(config.get("Components", "Solids"))
for indice in self.indices:
name = self.databank.BaseDatos.item(indice-1, 1).text()
self.ListaComponentes.addItem(f"{indice:03} - {name}")
for solido in self.solidos:
name = self.databank.BaseDatos.item(solido-1, 1).text()
self.ListaSolidos.addItem(f"{solido:03} - {name}")
self.comprobarBotones()
[docs]
def Add(self):
"""Add selected component to component list"""
insertar = self.ListaComponentes.currentRow()+1
indice = self.databank.currentRow()+1
if indice not in self.indices + self.solidos:
self.indices.insert(insertar, indice)
name = self.databank.BaseDatos.item(indice-1, 1).text()
self.ListaComponentes.insertItem(insertar, f"{indice:03} - {name}")
self.comprobarBotones()
self.ListaComponentes.setCurrentRow(insertar)
self.componentChanged.emit(bool(self.indices))
[docs]
def Delete(self):
"""Remove component to component list"""
del self.indices[self.ListaComponentes.currentRow()]
self.ListaComponentes.takeItem(self.ListaComponentes.currentRow())
self.comprobarBotones()
self.componentChanged.emit(bool(self.indices))
[docs]
def Up(self):
"""Up selected item in component list"""
indice = self.ListaComponentes.currentRow()
self.ListaComponentes.insertItem(
indice-1, self.ListaComponentes.item(indice).text())
self.ListaComponentes.takeItem(indice+1)
self.ListaComponentes.setCurrentRow(indice-1)
self.indices.insert(indice-1, self.indices.pop(indice))
[docs]
def Down(self):
"""Down selected item in component list"""
indice = self.ListaComponentes.currentRow()
self.ListaComponentes.insertItem(
indice+2, self.ListaComponentes.item(indice).text())
self.ListaComponentes.takeItem(indice)
self.ListaComponentes.setCurrentRow(indice+1)
self.indices.insert(indice+1, self.indices.pop(indice))
[docs]
def AddSolid(self):
"""Add selected component to solid component list"""
insertar = self.ListaSolidos.currentRow()+1
indice = self.databank.currentRow()+1
if indice not in self.indices+self.solidos:
self.solidos.insert(insertar, indice)
name = self.databank.BaseDatos.item(indice-1, 1).text()
self.ListaSolidos.insertItem(insertar, f"{indice:03} - {name}")
self.comprobarBotones()
self.ListaSolidos.setCurrentRow(insertar)
[docs]
def DeleteSolid(self):
"""Remove component to solid component list"""
del self.solidos[self.ListaSolidos.currentRow()]
self.ListaSolidos.takeItem(self.ListaSolidos.currentRow())
self.comprobarBotones()
[docs]
def clear(self):
"""Clear component list"""
self.ListaComponentes.clear()
self.indices = []
self.comprobarBotones()
self.componentChanged.emit(bool(self.indices))
[docs]
def clearSolids(self):
"""Clear solid component list"""
self.ListaSolidos.clear()
self.solidos = []
self.comprobarBotones()
[docs]
def comprobarBotones(self):
"""Check current status of button availibility"""
if self.ListaComponentes.currentRow() == -1:
self.Arriba.setEnabled(False)
self.Abajo.setEnabled(False)
self.DeleteComponente.setEnabled(False)
else:
self.DeleteComponente.setEnabled(True)
if self.ListaComponentes.count() > 1:
if self.ListaComponentes.currentRow() == 0:
self.Arriba.setEnabled(False)
self.Abajo.setEnabled(True)
elif self.ListaComponentes.currentRow() == \
self.ListaComponentes.count()-1:
self.Abajo.setEnabled(False)
self.Arriba.setEnabled(True)
else:
self.Arriba.setEnabled(True)
self.Abajo.setEnabled(True)
else:
self.Arriba.setEnabled(False)
self.Abajo.setEnabled(False)
self.clearComp.setEnabled(bool(self.indices))
self.clearSolido.setEnabled(bool(self.solidos))
if self.databank.currentRow() == -1 or \
self.databank.currentRow() + 1 in self.indices + self.solidos:
self.AddComponente.setEnabled(False)
self.AddSolido.setEnabled(False)
else:
self.AddComponente.setEnabled(True)
self.AddSolido.setEnabled(True)
if self.ListaSolidos.currentRow() == -1:
self.DeleteSolido.setEnabled(False)
else:
self.DeleteSolido.setEnabled(True)
[docs]
def value(self, config):
"""Function to result wizard"""
if not config.has_section("Components"):
config.add_section("Components")
config.set("Components", "Components", str(self.indices))
config.set("Components", "Solids", str(self.solidos))
return config
[docs]
@classmethod
def default(cls, config):
"""Default configuration"""
config.add_section("Components")
config.set("Components", "Components", "[]")
config.set("Components", "Solids", "[]")
return config
[docs]
class Dialog(QtWidgets.QDialog):
"""Component list config dialog"""
[docs]
def __init__(self, config=None, parent=None, **kw):
super().__init__(parent)
self.setWindowTitle(self.tr("Define project Components"))
layout = QtWidgets.QVBoxLayout(self)
self.datos = UI_confComponents_widget(config, **kw)
layout.addWidget(self.datos)
self.buttonBox = QtWidgets.QDialogButtonBox(
QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Ok)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
layout.addWidget(self.buttonBox)
[docs]
def value(self, config):
"""Function to result wizard"""
config = self.datos.value(config)
return config
[docs]
def cmp(self):
"""Direct access to list of compounds selected in widget"""
return self.datos.indices
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = Dialog()
Dialog.show()
sys.exit(app.exec())