Skip to content
Snippets Groups Projects
Commit 661eb1f5 authored by Oscar Gustafsson's avatar Oscar Gustafsson :bicyclist:
Browse files

Merge branch 'guicleanup' into 'master'

Cleanup GUI code

See merge request !82
parents 1aa3073b 0e75e8e9
No related branches found
No related tags found
1 merge request!82Cleanup GUI code
Pipeline #74833 passed
...@@ -4,17 +4,48 @@ from qtpy.QtCore import Qt ...@@ -4,17 +4,48 @@ from qtpy.QtCore import Qt
QUESTIONS = { QUESTIONS = {
"Adding operations": "Select an operation under 'Special operations' or 'Core operations' to add it to the workspace.", "Adding operations":
"Moving operations": "To drag an operation, select the operation on the workspace and drag it around.", "Select an operation under 'Special operations' or 'Core operations' "
"Selecting operations": "To select one operation just press it once, it will then turn grey.", "to add it to the workspace.",
"Selecting multiple operations using dragging": "To select multiple operations using your mouse, \ndrag the mouse while pressing left mouse button, any operation under the selection box will then be selected.", "Moving operations":
"Selecting multiple operations using without dragging": "To select mutliple operations using without dragging, \npress 'Ctrl+LMouseButton' on any operation.", "To drag an operation, select the operation on the workspace and drag "
"Remove operations": "To remove an operation, select the operation to be deleted, \nfinally press RMouseButton to bring up the context menu, then press 'Delete'.", "it around.",
"Remove multiple operations": "To remove multiple operations, \nselect all operations to be deleted and press 'Delete' on your keyboard.", "Selecting operations":
"Connecting operations": "To connect operations, select the ports on the operation to connect from, \nthen select the next port by pressing 'Ctrl+LMouseButton' on the destination port. Tip: You can chain connection by selecting the ports in the order they should be connected.", "To select one operation just press it once, it will then turn grey.",
"Creating a signal-flow-graph": "To create a signal-flow-graph (SFG), \ncouple together the operations you wish to create a sfg from, then select all operations you wish to include in the sfg, \nfinally press 'Create SFG' in the upper left corner and enter the name of the sfg.", "Selecting multiple operations using dragging":
"Simulating a signal-flow-graph": "To simulate a signal-flow-graph (SFG), press the run button in the toolbar, \nthen press 'Simulate SFG' and enter the properties of the simulation.", "To select multiple operations using your mouse, \n"
"Properties of simulation": "The properties of the simulation are, 'Iteration Count': The number of iterations to run the simulation for, \n'Plot Results': Open a plot over the output in matplotlib, \n'Get All Results': Print the detailed output from simulating the sfg in the terminal, \n'Input Values': The input values to the SFG by index of the port." "drag the mouse while pressing left mouse button, any operation under "
"the selection box will then be selected.",
"Selecting multiple operations using without dragging":
"To select mutliple operations using without dragging, \n"
"press 'Ctrl+LMouseButton' on any operation.",
"Remove operations":
"To remove an operation, select the operation to be deleted, \n"
"finally press RMouseButton to bring up the context menu, then press "
"'Delete'.",
"Remove multiple operations":
"To remove multiple operations, \nselect all operations to be deleted "
"and press 'Delete' on your keyboard.",
"Connecting operations":
"To connect operations, select the ports on the operation to connect "
"from, \nthen select the next port by pressing 'Ctrl+LMouseButton' on "
"the destination port. Tip: You can chain connection by selecting the "
"ports in the order they should be connected.",
"Creating a signal-flow-graph":
"To create a signal-flow-graph (SFG), \ncouple together the "
"operations you wish to create a sfg from, then select all operations "
"you wish to include in the sfg, \nfinally press 'Create SFG' in the "
"upper left corner and enter the name of the sfg.",
"Simulating a signal-flow-graph":
"To simulate a signal-flow-graph (SFG), press the run button in the "
"toolbar, \nthen press 'Simulate SFG' and enter the properties of the "
"simulation.",
"Properties of simulation":
"The properties of the simulation are, 'Iteration Count': The number "
"of iterations to run the simulation for, \n'Plot Results': Open a "
"plot over the output in matplotlib, \n'Get All Results': Print the "
"detailed output from simulating the sfg in the terminal, \n"
"'Input Values': The input values to the SFG by index of the port."
} }
...@@ -42,9 +73,11 @@ class KeybindsWindow(QDialog): ...@@ -42,9 +73,11 @@ class KeybindsWindow(QDialog):
self.dialog_layout.addWidget(frame) self.dialog_layout.addWidget(frame)
keybinds_label = QLabel( keybinds_label = QLabel(
"'Ctrl+R' - Reload the operation list to add any new operations created.\n" "'Ctrl+R' - Reload the operation list to add any new operations "
"created.\n"
"'Ctrl+Q' - Quit the application.\n" "'Ctrl+Q' - Quit the application.\n"
"'Ctrl+LMouseButton' - On a operation will select the operation, without deselecting the other operations.\n" "'Ctrl+LMouseButton' - On a operation will select the operation, "
"without deselecting the other operations.\n"
"'Ctrl+S' (Plot) - Save the plot if a plot is visible.\n" "'Ctrl+S' (Plot) - Save the plot if a plot is visible.\n"
"'Ctrl+?' - Open the FAQ section." "'Ctrl+?' - Open the FAQ section."
) )
...@@ -74,7 +107,8 @@ class AboutWindow(QDialog): ...@@ -74,7 +107,8 @@ class AboutWindow(QDialog):
information_layout = QVBoxLayout() information_layout = QVBoxLayout()
title_label = QLabel("B-ASIC / Better ASIC Toolbox") title_label = QLabel("B-ASIC / Better ASIC Toolbox")
subtitle_label = QLabel("Construct, simulate and analyze components of an ASIC.") subtitle_label = QLabel(
"Construct, simulate and analyze components of an ASIC.")
frame = QFrame() frame = QFrame()
frame.setFrameShape(QFrame.HLine) frame.setFrameShape(QFrame.HLine)
...@@ -82,9 +116,12 @@ class AboutWindow(QDialog): ...@@ -82,9 +116,12 @@ class AboutWindow(QDialog):
self.dialog_layout.addWidget(frame) self.dialog_layout.addWidget(frame)
about_label = QLabel( about_label = QLabel(
"B-ASIC is a open source tool using the B-ASIC library to construct, simulate and analyze ASICs.\n" "B-ASIC is an open source tool using the B-ASIC library to "
"B-ASIC is developed under the MIT-license and any extension to the program should follow that same license.\n" "construct, simulate and analyze ASICs.\n"
"To read more about how the GUI works please refer to the FAQ under 'Help'." "B-ASIC is developed under the MIT-license and any extension to "
"the program should follow that same license.\n"
"To read more about how the GUI works please refer to the FAQ "
"under 'Help'."
) )
information_layout.addWidget(title_label) information_layout.addWidget(title_label)
......
from qtpy.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QAction,\ from qtpy.QtWidgets import QMenu, QGraphicsLineItem
QStatusBar, QMenuBar, QLineEdit, QPushButton, QSlider, QScrollArea, QVBoxLayout,\ from qtpy.QtCore import Qt, QLineF
QHBoxLayout, QDockWidget, QToolBar, QMenu, QLayout, QSizePolicy, QListWidget, QListWidgetItem,\ from qtpy.QtGui import QPen
QGraphicsLineItem, QGraphicsWidget
from qtpy.QtCore import Qt, QSize, QLineF, QPoint, QRectF
from qtpy.QtGui import QIcon, QFont, QPainter, QPen
from b_asic.signal import Signal from b_asic.signal import Signal
class Arrow(QGraphicsLineItem): class Arrow(QGraphicsLineItem):
def __init__(self, source, destination, window, signal=None, parent=None): def __init__(self, source, destination, window, signal=None, parent=None):
super().__init__(parent) super().__init__(parent)
self.source = source self.source = source
self.signal = Signal(source.port, destination.port) if signal is None else signal if signal is None:
signal = Signal(source.port, destination.port)
self.signal = signal
self.destination = destination self.destination = destination
self._window = window self._window = window
self.moveLine() self.moveLine()
...@@ -37,13 +37,16 @@ class Arrow(QGraphicsLineItem): ...@@ -37,13 +37,16 @@ class Arrow(QGraphicsLineItem):
if (port1 in operation_ports or port2 in operation_ports) and operation in self._window.opToSFG: if (port1 in operation_ports or port2 in operation_ports) and operation in self._window.opToSFG:
self._window.logger.info(f"Operation detected in existing SFG, removing SFG with name: {self._window.opToSFG[operation].name}.") self._window.logger.info(f"Operation detected in existing SFG, removing SFG with name: {self._window.opToSFG[operation].name}.")
del self._window.sfg_dict[self._window.opToSFG[operation].name] del self._window.sfg_dict[self._window.opToSFG[operation].name]
self._window.opToSFG = {op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is not self._window.opToSFG[operation]} self._window.opToSFG = {
op: self._window.opToSFG[op] for op in self._window.opToSFG
if self._window.opToSFG[op] is not self._window.opToSFG[operation]}
del self._window.signalPortDict[self] del self._window.signalPortDict[self]
def moveLine(self): def moveLine(self):
self.setPen(QPen(Qt.black, 3)) self.setPen(QPen(Qt.black, 3))
self.setLine(QLineF(self.source.operation.x()+self.source.x()+14,\ self.setLine(QLineF(
self.source.operation.y()+self.source.y()+7.5,\ self.source.operation.x() + self.source.x() + 14,
self.destination.operation.x()+self.destination.x(),\ self.source.operation.y() + self.source.y() + 7.5,
self.destination.operation.y()+self.destination.y()+7.5)) self.destination.operation.x() + self.destination.x(),
self.destination.operation.y() + self.destination.y() + 7.5))
...@@ -143,7 +143,8 @@ class DragButton(QPushButton): ...@@ -143,7 +143,8 @@ class DragButton(QPushButton):
f"Operation detected in existing SFG, removing SFG with name: {self._window.opToSFG[self].name}.") f"Operation detected in existing SFG, removing SFG with name: {self._window.opToSFG[self].name}.")
del self._window.sfg_dict[self._window.opToSFG[self].name] del self._window.sfg_dict[self._window.opToSFG[self].name]
self._window.opToSFG = { self._window.opToSFG = {
op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is not self._window.opToSFG[self]} op: self._window.opToSFG[op] for op in self._window.opToSFG
if self._window.opToSFG[op] is not self._window.opToSFG[self]}
for port in self._window.portDict[self]: for port in self._window.portDict[self]:
if port in self._window.pressed_ports: if port in self._window.pressed_ports:
......
...@@ -32,7 +32,9 @@ class Ui_main_window(object): ...@@ -32,7 +32,9 @@ class Ui_main_window(object):
" left: 10px;\n" " left: 10px;\n"
" padding: 0 3px 0 3px;\n" " padding: 0 3px 0 3px;\n"
"}") "}")
self.operation_box.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.operation_box.setAlignment(QtCore.Qt.AlignLeading|
QtCore.Qt.AlignLeft|
QtCore.Qt.AlignVCenter)
self.operation_box.setFlat(False) self.operation_box.setFlat(False)
self.operation_box.setCheckable(False) self.operation_box.setCheckable(False)
self.operation_box.setObjectName("operation_box") self.operation_box.setObjectName("operation_box")
......
...@@ -281,7 +281,7 @@ class MainWindow(QMainWindow): ...@@ -281,7 +281,7 @@ class MainWindow(QMainWindow):
return return
if name == "": if name == "":
self.logger.warning(f"Failed to initialize SFG with empty name.") self.logger.warning("Failed to initialize SFG with empty name.")
return return
self.logger.info( self.logger.info(
...@@ -396,7 +396,8 @@ class MainWindow(QMainWindow): ...@@ -396,7 +396,8 @@ class MainWindow(QMainWindow):
def get_operations_from_namespace(self, namespace): def get_operations_from_namespace(self, namespace):
self.logger.info( self.logger.info(
f"Fetching operations from namespace: {namespace.__name__}.") f"Fetching operations from namespace: {namespace.__name__}.")
return [comp for comp in dir(namespace) if hasattr(getattr(namespace, comp), "type_name")] return [comp for comp in dir(namespace)
if hasattr(getattr(namespace, comp), "type_name")]
def add_operations_from_namespace(self, namespace, _list): def add_operations_from_namespace(self, namespace, _list):
for attr_name in self.get_operations_from_namespace(namespace): for attr_name in self.get_operations_from_namespace(namespace):
...@@ -435,8 +436,9 @@ class MainWindow(QMainWindow): ...@@ -435,8 +436,9 @@ class MainWindow(QMainWindow):
attr_button.move(*position) attr_button.move(*position)
attr_button.setFixedSize(55, 55) attr_button.setFixedSize(55, 55)
attr_button.setStyleSheet("background-color: white; border-style: solid;\ attr_button.setStyleSheet(
border-color: black; border-width: 2px") "background-color: white; border-style: solid;"
"border-color: black; border-width: 2px")
self.add_ports(attr_button) self.add_ports(attr_button)
icon_path = os.path.join(os.path.dirname( icon_path = os.path.join(os.path.dirname(
...@@ -502,14 +504,15 @@ class MainWindow(QMainWindow): ...@@ -502,14 +504,15 @@ class MainWindow(QMainWindow):
def _connect_button(self, *event): def _connect_button(self, *event):
if len(self.pressed_ports) < 2: if len(self.pressed_ports) < 2:
self.logger.warning( self.logger.warning(
"Cannot connect less than two ports. Please select at least two.") "Cannot connect less than two ports. "
"Please select at least two.")
return return
for i in range(len(self.pressed_ports) - 1): for i in range(len(self.pressed_ports) - 1):
source = self.pressed_ports[i] if isinstance( source = self.pressed_ports[i] if isinstance(
self.pressed_ports[i].port, OutputPort) else self.pressed_ports[i + 1] self.pressed_ports[i].port, OutputPort) else self.pressed_ports[i + 1]
destination = self.pressed_ports[i + destination = self.pressed_ports[
1] if source is not self.pressed_ports[i + 1] else self.pressed_ports[i] i + 1] if source is not self.pressed_ports[i + 1] else self.pressed_ports[i]
if source.port.operation is destination.port.operation: if source.port.operation is destination.port.operation:
self.logger.warning("Cannot connect to the same port") self.logger.warning("Cannot connect to the same port")
continue continue
...@@ -526,9 +529,11 @@ class MainWindow(QMainWindow): ...@@ -526,9 +529,11 @@ class MainWindow(QMainWindow):
def connect_button(self, source, destination): def connect_button(self, source, destination):
signal_exists = ( signal_exists = (
signal for signal in source.port.signals if signal.destination is destination.port) signal for signal in source.port.signals
if signal.destination is destination.port)
self.logger.info( self.logger.info(
f"Connecting: {source.operation.operation.type_name()} -> {destination.operation.operation.type_name()}.") f"Connecting: {source.operation.operation.type_name()} "
f"-> {destination.operation.operation.type_name()}.")
try: try:
line = Arrow(source, destination, self, signal=next(signal_exists)) line = Arrow(source, destination, self, signal=next(signal_exists))
except StopIteration: except StopIteration:
...@@ -564,7 +569,8 @@ class MainWindow(QMainWindow): ...@@ -564,7 +569,8 @@ class MainWindow(QMainWindow):
simulation = FastSimulation( simulation = FastSimulation(
sfg, input_providers=properties["input_values"]) sfg, input_providers=properties["input_values"])
l_result = simulation.run_for( l_result = simulation.run_for(
properties["iteration_count"], save_results=properties["all_results"]) properties["iteration_count"],
save_results=properties["all_results"])
print(f"{'=' * 10} {sfg.name} {'=' * 10}") print(f"{'=' * 10} {sfg.name} {'=' * 10}")
pprint( pprint(
...@@ -587,7 +593,8 @@ class MainWindow(QMainWindow): ...@@ -587,7 +593,8 @@ class MainWindow(QMainWindow):
self.dialog.show() self.dialog.show()
# Wait for input to dialog. Kinda buggy because of the separate window in the same thread. # Wait for input to dialog.
# Kinda buggy because of the separate window in the same thread.
self.dialog.simulate.connect(self._simulate_sfg) self.dialog.simulate.connect(self._simulate_sfg)
def display_faq_page(self): def display_faq_page(self):
......
import sys
from qtpy.QtWidgets import QPushButton, QMenu from qtpy.QtWidgets import QPushButton, QMenu
from qtpy.QtCore import Qt, Signal from qtpy.QtCore import Qt, Signal
...@@ -37,7 +34,8 @@ class PortButton(QPushButton): ...@@ -37,7 +34,8 @@ class PortButton(QPushButton):
def _toggle_port(self, pressed=False): def _toggle_port(self, pressed=False):
self.pressed = not pressed self.pressed = not pressed
self.setStyleSheet(f"background-color: {'white' if not self.pressed else 'grey'}") self.setStyleSheet(
f"background-color: {'white' if not self.pressed else 'grey'}")
def select_port(self, modifiers=None): def select_port(self, modifiers=None):
if modifiers != Qt.ControlModifier: if modifiers != Qt.ControlModifier:
......
from qtpy.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout,\ from qtpy.QtWidgets import (
QLabel, QCheckBox, QGridLayout QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel,
QCheckBox, QGridLayout)
from qtpy.QtCore import Qt from qtpy.QtCore import Qt
from qtpy.QtGui import QDoubleValidator from qtpy.QtGui import QDoubleValidator
...@@ -23,14 +24,17 @@ class PropertiesWindow(QDialog): ...@@ -23,14 +24,17 @@ class PropertiesWindow(QDialog):
self.vertical_layout = QVBoxLayout() self.vertical_layout = QVBoxLayout()
self.vertical_layout.addLayout(self.name_layout) self.vertical_layout.addLayout(self.name_layout)
if hasattr(self.operation.operation, "value") or hasattr(self.operation.operation, "initial_value"): if (hasattr(self.operation.operation, "value") or
hasattr(self.operation.operation, "initial_value")):
self.constant_layout = QHBoxLayout() self.constant_layout = QHBoxLayout()
self.constant_layout.setSpacing(50) self.constant_layout.setSpacing(50)
self.constant_value = QLabel("Value:") self.constant_value = QLabel("Value:")
if hasattr(self.operation.operation, "value"): if hasattr(self.operation.operation, "value"):
self.edit_constant = QLineEdit(str(self.operation.operation.value)) self.edit_constant = QLineEdit(
str(self.operation.operation.value))
else: else:
self.edit_constant = QLineEdit(str(self.operation.operation.initial_value)) self.edit_constant = QLineEdit(
str(self.operation.operation.initial_value))
self.only_accept_float = QDoubleValidator() self.only_accept_float = QDoubleValidator()
self.edit_constant.setValidator(self.only_accept_float) self.edit_constant.setValidator(self.only_accept_float)
...@@ -51,7 +55,8 @@ class PropertiesWindow(QDialog): ...@@ -51,7 +55,8 @@ class PropertiesWindow(QDialog):
if self.operation.operation.input_count > 0: if self.operation.operation.input_count > 0:
self.latency_layout = QHBoxLayout() self.latency_layout = QHBoxLayout()
self.latency_label = QLabel("Set latency for input ports (-1 for None):") self.latency_label = QLabel(
"Set latency for input ports (-1 for None):")
self.latency_layout.addWidget(self.latency_label) self.latency_layout.addWidget(self.latency_label)
self.vertical_layout.addLayout(self.latency_layout) self.vertical_layout.addLayout(self.latency_layout)
...@@ -68,7 +73,8 @@ class PropertiesWindow(QDialog): ...@@ -68,7 +73,8 @@ class PropertiesWindow(QDialog):
input_layout.addWidget(input_label) input_layout.addWidget(input_label)
input_value = QLineEdit() input_value = QLineEdit()
try: try:
input_value.setPlaceholderText(str(self.operation.operation.latency)) input_value.setPlaceholderText(
str(self.operation.operation.latency))
except ValueError: except ValueError:
input_value.setPlaceholderText("-1") input_value.setPlaceholderText("-1")
int_valid = QDoubleValidator() int_valid = QDoubleValidator()
...@@ -86,7 +92,8 @@ class PropertiesWindow(QDialog): ...@@ -86,7 +92,8 @@ class PropertiesWindow(QDialog):
if self.operation.operation.output_count > 0: if self.operation.operation.output_count > 0:
self.latency_layout = QHBoxLayout() self.latency_layout = QHBoxLayout()
self.latency_label = QLabel("Set latency for output ports (-1 for None):") self.latency_label = QLabel(
"Set latency for output ports (-1 for None):")
self.latency_layout.addWidget(self.latency_label) self.latency_layout.addWidget(self.latency_label)
self.vertical_layout.addLayout(self.latency_layout) self.vertical_layout.addLayout(self.latency_layout)
...@@ -103,7 +110,8 @@ class PropertiesWindow(QDialog): ...@@ -103,7 +110,8 @@ class PropertiesWindow(QDialog):
input_layout.addWidget(input_label) input_layout.addWidget(input_label)
input_value = QLineEdit() input_value = QLineEdit()
try: try:
input_value.setPlaceholderText(str(self.operation.operation.latency)) input_value.setPlaceholderText(
str(self.operation.operation.latency))
except ValueError: except ValueError:
input_value.setPlaceholderText("-1") input_value.setPlaceholderText("-1")
int_valid = QDoubleValidator() int_valid = QDoubleValidator()
...@@ -125,7 +133,8 @@ class PropertiesWindow(QDialog): ...@@ -125,7 +133,8 @@ class PropertiesWindow(QDialog):
self.setLayout(self.vertical_layout) self.setLayout(self.vertical_layout)
def save_properties(self): def save_properties(self):
self._window.logger.info(f"Saving properties of operation: {self.operation.name}.") self._window.logger.info(
f"Saving properties of operation: {self.operation.name}.")
self.operation.name = self.edit_name.text() self.operation.name = self.edit_name.text()
self.operation.operation.name = self.edit_name.text() self.operation.operation.name = self.edit_name.text()
self.operation.label.setPlainText(self.operation.name) self.operation.label.setPlainText(self.operation.name)
...@@ -141,6 +150,10 @@ class PropertiesWindow(QDialog): ...@@ -141,6 +150,10 @@ class PropertiesWindow(QDialog):
self.operation.label.setOpacity(0) self.operation.label.setOpacity(0)
self.operation.is_show_name = False self.operation.is_show_name = False
self.operation.operation.set_latency_offsets({port: float(self.latency_fields[port].text().replace(",", ".")) if self.latency_fields[port].text() and float(self.latency_fields[port].text().replace(",", ".")) > 0 else None for port in self.latency_fields}) self.operation.operation.set_latency_offsets(
{port: float(self.latency_fields[port].text().replace(",", "."))
if self.latency_fields[port].text() and float(self.latency_fields[port].text().replace(",", ".")) > 0
else None
for port in self.latency_fields})
self.reject() self.reject()
from qtpy.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout,\ from qtpy.QtWidgets import QDialog, QPushButton, QVBoxLayout, QComboBox
QLabel, QCheckBox, QSpinBox, QGroupBox, QFrame, QFormLayout, QGridLayout, QSizePolicy, QFileDialog, QShortcut, QComboBox
from qtpy.QtCore import Qt, Signal from qtpy.QtCore import Qt, Signal
from qtpy.QtGui import QIntValidator, QKeySequence
from matplotlib.backends import qt_compat
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class SelectSFGWindow(QDialog): class SelectSFGWindow(QDialog):
......
from b_asic.signal_flow_graph import SFG from b_asic.signal_flow_graph import SFG
from qtpy.QtWidgets import QDialog, QPushButton, QVBoxLayout, QCheckBox,\ from qtpy.QtWidgets import (
QFrame, QFormLayout QDialog, QPushButton, QVBoxLayout, QCheckBox, QFrame, QFormLayout)
from qtpy.QtCore import Qt, Signal from qtpy.QtCore import Qt, Signal
...@@ -42,7 +42,8 @@ class ShowPCWindow(QDialog): ...@@ -42,7 +42,8 @@ class ShowPCWindow(QDialog):
def show_precedence_graph(self): def show_precedence_graph(self):
for check_box, sfg in self.check_box_dict.items(): for check_box, sfg in self.check_box_dict.items():
if check_box.isChecked(): if check_box.isChecked():
self._window.logger.info(f"Creating a precedence graph from SFG with name: {sfg}.") self._window.logger.info(
f"Creating a precedence graph from SFG with name: {sfg}.")
self._window.sfg_dict[sfg].show_precedence_graph() self._window.sfg_dict[sfg].show_precedence_graph()
self.accept() self.accept()
......
from qtpy.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout,\ from qtpy.QtWidgets import (
QLabel, QCheckBox, QSpinBox, QGroupBox, QFrame, QFormLayout, QGridLayout, QSizePolicy, QFileDialog, QShortcut QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel,
QCheckBox, QSpinBox, QFrame, QFormLayout, QGridLayout, QSizePolicy,
QFileDialog, QShortcut)
from qtpy.QtCore import Qt, Signal from qtpy.QtCore import Qt, Signal
from qtpy.QtGui import QDoubleValidator, QKeySequence from qtpy.QtGui import QKeySequence
from matplotlib.backends import qt_compat
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure from matplotlib.figure import Figure
...@@ -91,7 +92,7 @@ class SimulateSFGWindow(QDialog): ...@@ -91,7 +92,7 @@ class SimulateSFGWindow(QDialog):
def parse_input_values(self, input_values): def parse_input_values(self, input_values):
_input_values = [] _input_values = []
for _list in list(input_values): for _list in input_values:
_list_values = [] _list_values = []
for val in _list: for val in _list:
val = val.strip() val = val.strip()
...@@ -110,33 +111,48 @@ class SimulateSFGWindow(QDialog): ...@@ -110,33 +111,48 @@ class SimulateSFGWindow(QDialog):
def save_properties(self): def save_properties(self):
for sfg, _properties in self.input_fields.items(): for sfg, _properties in self.input_fields.items():
input_values = self.parse_input_values(widget.text().split(",") if widget.text() else [0] for widget in self.input_fields[sfg]["input_values"]) input_values = self.parse_input_values(
if max(len(list_) for list_ in input_values) != min(len(list_) for list_ in input_values): [widget.text().split(",") if widget.text() else [0]
self._window.logger.error(f"Minimum length of input lists are not equal to maximum length of input lists: {max(len(list_) for list_ in input_values)} != {min(len(list_) for list_ in input_values)}.") for widget in self.input_fields[sfg]["input_values"]])
elif self.input_fields[sfg]["iteration_count"].value() > min(len(list_) for list_ in input_values): max_len = max(len(list_) for list_ in input_values)
self._window.logger.error(f"Minimum length of input lists are less than the iteration count: {self.input_fields[sfg]['iteration_count'].value()} > {min(len(list_) for list_ in input_values)}.") min_len = min(len(list_) for list_ in input_values)
ic_value = self.input_fields[sfg]["iteration_count"].value()
if max_len != min_len:
self._window.logger.error(
f"Minimum length of input lists are not equal to maximum "
f"length of input lists: {max_len} != {min_len}.")
elif ic_value > min_len:
self._window.logger.error(
f"Minimum length of input lists are less than the "
f"iteration count: {ic_value} > {min_len}.")
else: else:
self.properties[sfg] = { self.properties[sfg] = {
"iteration_count": self.input_fields[sfg]["iteration_count"].value(), "iteration_count": ic_value,
"show_plot": self.input_fields[sfg]["show_plot"].isChecked(), "show_plot":
"all_results": self.input_fields[sfg]["all_results"].isChecked(), self.input_fields[sfg]["show_plot"].isChecked(),
"all_results":
self.input_fields[sfg]["all_results"].isChecked(),
"input_values": input_values "input_values": input_values
} }
# If we plot we should also print the entire data, since you cannot really interact with the graph. # If we plot we should also print the entire data,
# since you cannot really interact with the graph.
if self.properties[sfg]["show_plot"]: if self.properties[sfg]["show_plot"]:
self.properties[sfg]["all_results"] = True self.properties[sfg]["all_results"] = True
continue continue
self._window.logger.info(f"Skipping simulation of SFG with name: {sfg.name}, due to previous errors.") self._window.logger.info(
f"Skipping simulation of SFG with name: {sfg.name}, "
"due to previous errors.")
self.accept() self.accept()
self.simulate.emit() self.simulate.emit()
class Plot(FigureCanvas): class Plot(FigureCanvas):
def __init__(self, simulation, sfg, window, parent=None, width=5, height=4, dpi=100): def __init__(self, simulation, sfg, window, parent=None, width=5, height=4,
dpi=100):
self.simulation = simulation self.simulation = simulation
self.sfg = sfg self.sfg = sfg
self.dpi = dpi self.dpi = dpi
...@@ -149,7 +165,8 @@ class Plot(FigureCanvas): ...@@ -149,7 +165,8 @@ class Plot(FigureCanvas):
FigureCanvas.__init__(self, fig) FigureCanvas.__init__(self, fig)
self.setParent(parent) self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding,
QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self) FigureCanvas.updateGeometry(self)
self.save_figure = QShortcut(QKeySequence("Ctrl+S"), self) self.save_figure = QShortcut(QKeySequence("Ctrl+S"), self)
self.save_figure.activated.connect(self._save_plot_figure) self.save_figure.activated.connect(self._save_plot_figure)
...@@ -158,14 +175,16 @@ class Plot(FigureCanvas): ...@@ -158,14 +175,16 @@ class Plot(FigureCanvas):
def _save_plot_figure(self): def _save_plot_figure(self):
self._window.logger.info(f"Saving plot of figure: {self.sfg.name}.") self._window.logger.info(f"Saving plot of figure: {self.sfg.name}.")
file_choices = "PNG (*.png)|*.png" file_choices = "PNG (*.png)|*.png"
path, ext = QFileDialog.getSaveFileName(self, "Save file", "", file_choices) path, ext = QFileDialog.getSaveFileName(self, "Save file", "",
file_choices)
path = path.encode("utf-8") path = path.encode("utf-8")
if not path[-4:] == file_choices[-4:].encode("utf-8"): if not path[-4:] == file_choices[-4:].encode("utf-8"):
path += file_choices[-4:].encode("utf-8") path += file_choices[-4:].encode("utf-8")
if path: if path:
self.print_figure(path.decode(), dpi=self.dpi) self.print_figure(path.decode(), dpi=self.dpi)
self._window.logger.info(f"Saved plot: {self.sfg.name} to path: {path}.") self._window.logger.info(
f"Saved plot: {self.sfg.name} to path: {path}.")
def _plot_values_sfg(self): def _plot_values_sfg(self):
x_axis = list(range(len(self.simulation.results["0"]))) x_axis = list(range(len(self.simulation.results["0"])))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment