Skip to content
Snippets Groups Projects
Commit 73b45df2 authored by Adam Jakobsson's avatar Adam Jakobsson
Browse files

merge

parents 2527a40e 9eef1a36
No related branches found
No related tags found
1 merge request!55Resolve "Show PC in GUI"
Pipeline #15708 passed
from PySide2.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QDialog, QLabel, QFrame, QScrollArea
from PySide2.QtCore import Qt
QUESTIONS = {
"Adding operations": "Select an operation under 'Special operations' or 'Core operations' to add it to the workspace.",
"Moving operations": "To drag an operation, select the operation on the workspace and drag it around.",
"Selecting operations": "To select one operation just press it once, it will then turn grey.",
"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.",
"Selecting multiple operations using without dragging": "To select mutliple operations using without dragging, \npress 'Ctrl+LMouseButton' on any operation. Alternatively press 'Ctrl+A' to select all operations.",
"Remove operations": "To remove an operation, select the operation to be deleted, \nfinally 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."
}
class KeybindsWindow(QDialog):
def __init__(self, window):
super(KeybindsWindow, self).__init__()
self._window = window
self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
self.setWindowTitle("B-ASIC Keybinds")
self.dialog_layout = QVBoxLayout()
self.setLayout(self.dialog_layout)
self.add_information_to_layout()
def add_information_to_layout(self):
information_layout = QVBoxLayout()
title_label = QLabel("B-ASIC / Better ASIC Toolbox")
subtitle_label = QLabel("Keybinds in the GUI.")
frame = QFrame()
frame.setFrameShape(QFrame.HLine)
frame.setFrameShadow(QFrame.Sunken)
self.dialog_layout.addWidget(frame)
keybinds_label = QLabel(
"'Ctrl+A' - Select all operations on the workspace.\n"
"'Ctrl+R' - Reload the operation list to add any new operations created.\n"
"'Ctrl+Q' - Quit the application.\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+?' - Open the FAQ section."
)
information_layout.addWidget(title_label)
information_layout.addWidget(subtitle_label)
self.dialog_layout.addLayout(information_layout)
self.dialog_layout.addWidget(frame)
self.dialog_layout.addWidget(keybinds_label)
class AboutWindow(QDialog):
def __init__(self, window):
super(AboutWindow, self).__init__()
self._window = window
self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
self.setWindowTitle("About B-ASIC")
self.dialog_layout = QVBoxLayout()
self.setLayout(self.dialog_layout)
self.add_information_to_layout()
def add_information_to_layout(self):
information_layout = QVBoxLayout()
title_label = QLabel("B-ASIC / Better ASIC Toolbox")
subtitle_label = QLabel("Construct, simulate and analyze components of an ASIC.")
frame = QFrame()
frame.setFrameShape(QFrame.HLine)
frame.setFrameShadow(QFrame.Sunken)
self.dialog_layout.addWidget(frame)
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 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(subtitle_label)
self.dialog_layout.addLayout(information_layout)
self.dialog_layout.addWidget(frame)
self.dialog_layout.addWidget(about_label)
class FaqWindow(QDialog):
def __init__(self, window):
super(FaqWindow, self).__init__()
self._window = window
self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
self.setWindowTitle("Frequently Asked Questions")
self.dialog_layout = QVBoxLayout()
self.scroll_area = QScrollArea()
self.setLayout(self.dialog_layout)
for question, answer in QUESTIONS.items():
self.add_question_to_layout(question, answer)
self.scroll_area.setWidget(self)
self.scroll_area.setWidgetResizable(True)
def add_question_to_layout(self, question, answer):
question_layout = QVBoxLayout()
answer_layout = QHBoxLayout()
question_label = QLabel(question)
question_layout.addWidget(question_label)
answer_label = QLabel(answer)
answer_layout.addWidget(answer_label)
frame = QFrame()
frame.setFrameShape(QFrame.HLine)
frame.setFrameShadow(QFrame.Sunken)
self.dialog_layout.addWidget(frame)
question_layout.addLayout(answer_layout)
self.dialog_layout.addLayout(question_layout)
...@@ -115,11 +115,13 @@ class DragButton(QPushButton): ...@@ -115,11 +115,13 @@ class DragButton(QPushButton):
signal.update() signal.update()
def remove(self): def remove(self):
self._window.logger.info(f"Removing operation with name {self.operation.name}.")
self._window.scene.removeItem(self._window.operationDict[self]) self._window.scene.removeItem(self._window.operationDict[self])
_signals = [] _signals = []
for signal, ports in self._window.signalPortDict.items(): for signal, ports in self._window.signalPortDict.items():
if any([port in self._window.portDict[self] for port in ports]): if any([port in self._window.portDict[self] for port in ports]):
self._window.logger.info(f"Removed signal with name: {signal.signal.name} to/from operation: {self.operation.name}.")
signal.remove() signal.remove()
_signals.append(signal) _signals.append(signal)
......
...@@ -225,6 +225,8 @@ class Ui_main_window(object): ...@@ -225,6 +225,8 @@ class Ui_main_window(object):
self.view_menu.setObjectName("view_menu") self.view_menu.setObjectName("view_menu")
self.run_menu = QtWidgets.QMenu(self.menu_bar) self.run_menu = QtWidgets.QMenu(self.menu_bar)
self.run_menu.setObjectName("run_menu") self.run_menu.setObjectName("run_menu")
self.help_menu = QtWidgets.QMenu(self.menu_bar)
self.help_menu.setObjectName("help_menu")
main_window.setMenuBar(self.menu_bar) main_window.setMenuBar(self.menu_bar)
self.status_bar = QtWidgets.QStatusBar(main_window) self.status_bar = QtWidgets.QStatusBar(main_window)
self.status_bar.setObjectName("status_bar") self.status_bar.setObjectName("status_bar")
...@@ -241,6 +243,12 @@ class Ui_main_window(object): ...@@ -241,6 +243,12 @@ class Ui_main_window(object):
self.actionSimulateSFG.setObjectName("actionSimulateSFG") self.actionSimulateSFG.setObjectName("actionSimulateSFG")
self.actionShowPC = QtWidgets.QAction(main_window) self.actionShowPC = QtWidgets.QAction(main_window)
self.actionShowPC.setObjectName("actionShowPC") self.actionShowPC.setObjectName("actionShowPC")
self.aboutBASIC = QtWidgets.QAction(main_window)
self.aboutBASIC.setObjectName("aboutBASIC")
self.faqBASIC = QtWidgets.QAction(main_window)
self.faqBASIC.setObjectName("faqBASIC")
self.keybindsBASIC = QtWidgets.QAction(main_window)
self.keybindsBASIC.setObjectName("keybindsBASIC")
self.actionToolbar = QtWidgets.QAction(main_window) self.actionToolbar = QtWidgets.QAction(main_window)
self.actionToolbar.setCheckable(True) self.actionToolbar.setCheckable(True)
self.actionToolbar.setObjectName("actionToolbar") self.actionToolbar.setObjectName("actionToolbar")
...@@ -252,10 +260,14 @@ class Ui_main_window(object): ...@@ -252,10 +260,14 @@ class Ui_main_window(object):
self.view_menu.addAction(self.actionToolbar) self.view_menu.addAction(self.actionToolbar)
self.run_menu.addAction(self.actionShowPC) self.run_menu.addAction(self.actionShowPC)
self.run_menu.addAction(self.actionSimulateSFG) self.run_menu.addAction(self.actionSimulateSFG)
self.help_menu.addAction(self.aboutBASIC)
self.help_menu.addAction(self.faqBASIC)
self.help_menu.addAction(self.keybindsBASIC)
self.menu_bar.addAction(self.file_menu.menuAction()) self.menu_bar.addAction(self.file_menu.menuAction())
self.menu_bar.addAction(self.edit_menu.menuAction()) self.menu_bar.addAction(self.edit_menu.menuAction())
self.menu_bar.addAction(self.view_menu.menuAction()) self.menu_bar.addAction(self.view_menu.menuAction())
self.menu_bar.addAction(self.run_menu.menuAction()) self.menu_bar.addAction(self.run_menu.menuAction())
self.menu_bar.addAction(self.help_menu.menuAction())
self.retranslateUi(main_window) self.retranslateUi(main_window)
self.operation_list.setCurrentIndex(1) self.operation_list.setCurrentIndex(1)
...@@ -264,7 +276,7 @@ class Ui_main_window(object): ...@@ -264,7 +276,7 @@ class Ui_main_window(object):
def retranslateUi(self, main_window): def retranslateUi(self, main_window):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
main_window.setWindowTitle(_translate("main_window", "MainWindow")) main_window.setWindowTitle(_translate("main_window", "B-ASIC"))
self.operation_box.setTitle(_translate("main_window", "Operations")) self.operation_box.setTitle(_translate("main_window", "Operations"))
self.core_operations_list.setSortingEnabled(False) self.core_operations_list.setSortingEnabled(False)
__sortingEnabled = self.core_operations_list.isSortingEnabled() __sortingEnabled = self.core_operations_list.isSortingEnabled()
...@@ -280,7 +292,11 @@ class Ui_main_window(object): ...@@ -280,7 +292,11 @@ class Ui_main_window(object):
self.view_menu.setTitle(_translate("main_window", "View")) self.view_menu.setTitle(_translate("main_window", "View"))
self.run_menu.setTitle(_translate("main_window", "Run")) self.run_menu.setTitle(_translate("main_window", "Run"))
self.actionShowPC.setText(_translate("main_window", "Show PC")) self.actionShowPC.setText(_translate("main_window", "Show PC"))
self.help_menu.setTitle(_translate("main_window", "Help"))
self.actionSimulateSFG.setText(_translate("main_window", "Simulate SFG")) self.actionSimulateSFG.setText(_translate("main_window", "Simulate SFG"))
self.aboutBASIC.setText(_translate("main_window", "About B-ASIC"))
self.faqBASIC.setText(_translate("main_window", "FAQ"))
self.keybindsBASIC.setText(_translate("main_window", "Keybinds"))
self.save_menu.setText(_translate("main_window", "Save")) self.save_menu.setText(_translate("main_window", "Save"))
self.exit_menu.setText(_translate("main_window", "Exit")) self.exit_menu.setText(_translate("main_window", "Exit"))
self.exit_menu.setShortcut(_translate("main_window", "Ctrl+Q")) self.exit_menu.setShortcut(_translate("main_window", "Ctrl+Q"))
......
...@@ -5,8 +5,11 @@ This python file is the main window of the GUI for B-ASIC. ...@@ -5,8 +5,11 @@ This python file is the main window of the GUI for B-ASIC.
from pprint import pprint from pprint import pprint
from os import getcwd, path from os import getcwd, path
import logging
logging.basicConfig(level=logging.INFO)
import sys import sys
from about_window import AboutWindow, FaqWindow, KeybindsWindow
from drag_button import DragButton from drag_button import DragButton
from gui_interface import Ui_main_window from gui_interface import Ui_main_window
from arrow import Arrow from arrow import Arrow
...@@ -26,7 +29,7 @@ from PySide2.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QActio ...@@ -26,7 +29,7 @@ from PySide2.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QActio
QStatusBar, QMenuBar, QLineEdit, QPushButton, QSlider, QScrollArea, QVBoxLayout,\ QStatusBar, QMenuBar, QLineEdit, QPushButton, QSlider, QScrollArea, QVBoxLayout,\
QHBoxLayout, QDockWidget, QToolBar, QMenu, QLayout, QSizePolicy, QListWidget,\ QHBoxLayout, QDockWidget, QToolBar, QMenu, QLayout, QSizePolicy, QListWidget,\
QListWidgetItem, QGraphicsView, QGraphicsScene, QShortcut, QGraphicsTextItem,\ QListWidgetItem, QGraphicsView, QGraphicsScene, QShortcut, QGraphicsTextItem,\
QGraphicsProxyWidget, QInputDialog QGraphicsProxyWidget, QInputDialog, QTextEdit
from PySide2.QtCore import Qt, QSize from PySide2.QtCore import Qt, QSize
from PySide2.QtGui import QIcon, QFont, QPainter, QPen, QBrush, QKeySequence from PySide2.QtGui import QIcon, QFont, QPainter, QPen, QBrush, QKeySequence
...@@ -39,7 +42,6 @@ class MainWindow(QMainWindow): ...@@ -39,7 +42,6 @@ class MainWindow(QMainWindow):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.ui = Ui_main_window() self.ui = Ui_main_window()
self.ui.setupUi(self) self.ui.setupUi(self)
self.setWindowTitle(" ")
self.setWindowIcon(QIcon('small_logo.png')) self.setWindowIcon(QIcon('small_logo.png'))
self.scene = None self.scene = None
self._operations_from_name = dict() self._operations_from_name = dict()
...@@ -54,6 +56,7 @@ class MainWindow(QMainWindow): ...@@ -54,6 +56,7 @@ class MainWindow(QMainWindow):
self.pressed_ports = [] self.pressed_ports = []
self.sfg_list = [] self.sfg_list = []
self._window = self self._window = self
self.logger = logging.getLogger(__name__)
self.init_ui() self.init_ui()
self.add_operations_from_namespace(c_oper, self.ui.core_operations_list) self.add_operations_from_namespace(c_oper, self.ui.core_operations_list)
self.add_operations_from_namespace(s_oper, self.ui.special_operations_list) self.add_operations_from_namespace(s_oper, self.ui.special_operations_list)
...@@ -75,6 +78,14 @@ class MainWindow(QMainWindow): ...@@ -75,6 +78,14 @@ class MainWindow(QMainWindow):
self.ui.actionShowPC.triggered.connect(self.show_precedence_chart) self.ui.actionShowPC.triggered.connect(self.show_precedence_chart)
self.ui.actionSimulateSFG.triggered.connect(self.simulate_sfg) self.ui.actionSimulateSFG.triggered.connect(self.simulate_sfg)
self.ui.faqBASIC.triggered.connect(self.display_faq_page)
self.ui.aboutBASIC.triggered.connect(self.display_about_page)
self.ui.keybindsBASIC.triggered.connect(self.display_keybinds_page)
self.shortcut_help = QShortcut(QKeySequence("Ctrl+?"), self)
self.shortcut_help.activated.connect(self.display_faq_page)
self.logger.info("Finished setting up GUI")
self.logger.info("For questions please refer to 'Ctrl+?', or visit the 'Help' section on the toolbar.")
def init_ui(self): def init_ui(self):
self.ui.core_operations_list.itemClicked.connect(self.on_list_widget_item_clicked) self.ui.core_operations_list.itemClicked.connect(self.on_list_widget_item_clicked)
...@@ -87,7 +98,7 @@ class MainWindow(QMainWindow): ...@@ -87,7 +98,7 @@ class MainWindow(QMainWindow):
self.scene = QGraphicsScene(self) self.scene = QGraphicsScene(self)
self.graphic_view = QGraphicsView(self.scene, self) self.graphic_view = QGraphicsView(self.scene, self)
self.graphic_view.setRenderHint(QPainter.Antialiasing) self.graphic_view.setRenderHint(QPainter.Antialiasing)
self.graphic_view.setGeometry(self.ui.operation_box.width(), 0, self.width(), self.height()) self.graphic_view.setGeometry(self.ui.operation_box.width(), 20, self.width(), self.height())
self.graphic_view.setDragMode(QGraphicsView.RubberBandDrag) self.graphic_view.setDragMode(QGraphicsView.RubberBandDrag)
def create_toolbar_view(self): def create_toolbar_view(self):
...@@ -96,7 +107,7 @@ class MainWindow(QMainWindow): ...@@ -96,7 +107,7 @@ class MainWindow(QMainWindow):
def resizeEvent(self, event): def resizeEvent(self, event):
self.ui.operation_box.setGeometry(10, 10, self.ui.operation_box.width(), self.height()) self.ui.operation_box.setGeometry(10, 10, self.ui.operation_box.width(), self.height())
self.graphic_view.setGeometry(self.ui.operation_box.width() + 20, 0, self.width() - self.ui.operation_box.width() - 20, self.height()) self.graphic_view.setGeometry(self.ui.operation_box.width() + 20, 30, self.width() - self.ui.operation_box.width() - 20, self.height()-30)
super(MainWindow, self).resizeEvent(event) super(MainWindow, self).resizeEvent(event)
def wheelEvent(self, event): def wheelEvent(self, event):
...@@ -111,11 +122,13 @@ class MainWindow(QMainWindow): ...@@ -111,11 +122,13 @@ class MainWindow(QMainWindow):
self.is_show_names = True self.is_show_names = True
else: else:
self.is_show_names = False self.is_show_names = False
for operation in self.operationDict.keys(): for operation in self.operationDict.keys():
operation.label.setOpacity(self.is_show_names) operation.label.setOpacity(self.is_show_names)
operation.is_show_name = self.is_show_names operation.is_show_name = self.is_show_names
def exit_app(self): def exit_app(self):
self.logger.info("Exiting the application.")
QApplication.quit() QApplication.quit()
def create_SFG_from_toolbar(self): def create_SFG_from_toolbar(self):
...@@ -128,8 +141,11 @@ class MainWindow(QMainWindow): ...@@ -128,8 +141,11 @@ class MainWindow(QMainWindow):
outputs.append(op.operation) outputs.append(op.operation)
name = QInputDialog.getText(self, "Create SFG", "Name: ", QLineEdit.Normal) name = QInputDialog.getText(self, "Create SFG", "Name: ", QLineEdit.Normal)
self.logger.info(f"Creating SFG with name: {name[0]} from selected operations.")
sfg = SFG(inputs=inputs, outputs=outputs, name=name[0]) sfg = SFG(inputs=inputs, outputs=outputs, name=name[0])
self.logger.info(f"Created SFG with name: {name[0]} from selected operations.")
for op in self.pressed_operations: for op in self.pressed_operations:
op.setToolTip(sfg.name) op.setToolTip(sfg.name)
self.sfg_list.append(sfg) self.sfg_list.append(sfg)
...@@ -165,6 +181,7 @@ class MainWindow(QMainWindow): ...@@ -165,6 +181,7 @@ class MainWindow(QMainWindow):
port.show() port.show()
def get_operations_from_namespace(self, namespace): def get_operations_from_namespace(self, namespace):
self.logger.info(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):
...@@ -178,7 +195,10 @@ class MainWindow(QMainWindow): ...@@ -178,7 +195,10 @@ class MainWindow(QMainWindow):
except NotImplementedError: except NotImplementedError:
pass pass
self.logger.info(f"Added operations from namespace: {namespace.__name__}.")
def _create_operation(self, item): def _create_operation(self, item):
self.logger.info(f"Creating operation of type: {item.text()}.")
try: try:
attr_oper = self._operations_from_name[item.text()]() attr_oper = self._operations_from_name[item.text()]()
attr_button = DragButton(attr_oper.graph_id, attr_oper, attr_oper.type_name().lower(), True, self) attr_button = DragButton(attr_oper.graph_id, attr_oper, attr_oper.type_name().lower(), True, self)
...@@ -209,14 +229,16 @@ class MainWindow(QMainWindow): ...@@ -209,14 +229,16 @@ class MainWindow(QMainWindow):
attr_button.add_label(operation_label) attr_button.add_label(operation_label)
self.operationDict[attr_button] = attr_button_scene self.operationDict[attr_button] = attr_button_scene
except Exception as e: except Exception as e:
print("Unexpected error occured: ", e) self.logger.error(f"Unexpected error occured while creating operation: {e}.")
def _refresh_operations_list_from_namespace(self): def _refresh_operations_list_from_namespace(self):
self.logger.info("Refreshing operation list.")
self.ui.core_operations_list.clear() self.ui.core_operations_list.clear()
self.ui.special_operations_list.clear() self.ui.special_operations_list.clear()
self.add_operations_from_namespace(c_oper, self.ui.core_operations_list) self.add_operations_from_namespace(c_oper, self.ui.core_operations_list)
self.add_operations_from_namespace(s_oper, self.ui.special_operations_list) self.add_operations_from_namespace(s_oper, self.ui.special_operations_list)
self.logger.info("Finished refreshing operation list.")
def on_list_widget_item_clicked(self, item): def on_list_widget_item_clicked(self, item):
self._create_operation(item) self._create_operation(item)
...@@ -231,10 +253,13 @@ class MainWindow(QMainWindow): ...@@ -231,10 +253,13 @@ class MainWindow(QMainWindow):
def connectButton(self, button): def connectButton(self, button):
if len(self.pressed_ports) < 2: if len(self.pressed_ports) < 2:
self.logger.warn("Can't connect less than two ports. Please select more.")
return return
for i in range(len(self.pressed_ports) - 1): for i in range(len(self.pressed_ports) - 1):
if isinstance(self.pressed_ports[i].port, OutputPort) and \ if isinstance(self.pressed_ports[i].port, OutputPort) and \
isinstance(self.pressed_ports[i+1].port, InputPort): isinstance(self.pressed_ports[i+1].port, InputPort):
self.logger.info(f"Connecting: {self.pressed_ports[i].operation.operation.type_name()} -> {self.pressed_ports[i + 1].operation.operation.type_name()}")
line = Arrow(self.pressed_ports[i], self.pressed_ports[i + 1], self) line = Arrow(self.pressed_ports[i], self.pressed_ports[i + 1], self)
self.signalPortDict[line] = [self.pressed_ports[i], self.pressed_ports[i + 1]] self.signalPortDict[line] = [self.pressed_ports[i], self.pressed_ports[i + 1]]
...@@ -251,6 +276,7 @@ class MainWindow(QMainWindow): ...@@ -251,6 +276,7 @@ class MainWindow(QMainWindow):
signal.moveLine() signal.moveLine()
def _select_all_operations(self): def _select_all_operations(self):
self.logger.info("Selecting all operations in the workspace.")
self.pressed_operations.clear() self.pressed_operations.clear()
for button in self.operationDict.keys(): for button in self.operationDict.keys():
button._toggle_button(pressed=False) button._toggle_button(pressed=False)
...@@ -269,6 +295,7 @@ class MainWindow(QMainWindow): ...@@ -269,6 +295,7 @@ class MainWindow(QMainWindow):
def _simulate_sfg(self): def _simulate_sfg(self):
for sfg, properties in self.dialog.properties.items(): for sfg, properties in self.dialog.properties.items():
self.logger.info(f"Simulating sfg with name: {sfg.name}.")
simulation = Simulation(sfg, input_providers=properties["input_values"], save_results=properties["all_results"]) simulation = Simulation(sfg, input_providers=properties["input_values"], save_results=properties["all_results"])
l_result = simulation.run_for(properties["iteration_count"]) l_result = simulation.run_for(properties["iteration_count"])
...@@ -278,7 +305,9 @@ class MainWindow(QMainWindow): ...@@ -278,7 +305,9 @@ class MainWindow(QMainWindow):
print(f"{'=' * 10} /{sfg.name} {'=' * 10}") print(f"{'=' * 10} /{sfg.name} {'=' * 10}")
if properties["show_plot"]: if properties["show_plot"]:
self.plot = Plot(simulation, sfg) self.logger.info(f"Opening plot for sfg with name: {sfg.name}.")
self.logger.info("To save the plot press 'Ctrl+S' when the plot is focused.")
self.plot = Plot(simulation, sfg, self)
self.plot.show() self.plot.show()
def simulate_sfg(self): def simulate_sfg(self):
...@@ -292,6 +321,19 @@ class MainWindow(QMainWindow): ...@@ -292,6 +321,19 @@ class MainWindow(QMainWindow):
# 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):
self.faq_page = FaqWindow(self)
self.faq_page.scroll_area.show()
def display_about_page(self):
self.about_page = AboutWindow(self)
self.about_page.show()
def display_keybinds_page(self):
self.keybinds_page = KeybindsWindow(self)
self.keybinds_page.show()
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
window = MainWindow() window = MainWindow()
......
...@@ -7,7 +7,7 @@ class PropertiesWindow(QDialog): ...@@ -7,7 +7,7 @@ class PropertiesWindow(QDialog):
def __init__(self, operation, main_window): def __init__(self, operation, main_window):
super(PropertiesWindow, self).__init__() super(PropertiesWindow, self).__init__()
self.operation = operation self.operation = operation
self.main_window = main_window self._window = main_window
self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint) self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
self.setWindowTitle("Properties") self.setWindowTitle("Properties")
...@@ -49,6 +49,7 @@ class PropertiesWindow(QDialog): ...@@ -49,6 +49,7 @@ 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.operation.name = self.edit_name.text() self.operation.name = self.edit_name.text()
self.operation.label.setPlainText(self.operation.name) self.operation.label.setPlainText(self.operation.name)
if self.operation.operation_path_name == "c": if self.operation.operation_path_name == "c":
......
...@@ -41,6 +41,7 @@ class ShowPCWindow(QDialog): ...@@ -41,6 +41,7 @@ class ShowPCWindow(QDialog):
def show_precedence_graph(self): def show_precedence_graph(self):
for i, check_box in enumerate(self.check_box_list): for i, check_box in enumerate(self.check_box_list):
if check_box.isChecked(): if check_box.isChecked():
self._window.logger.info("Creating a precedence chart from " + self._window.sfg_list[i].name)
self._window.sfg_list[i].show_precedence_graph() self._window.sfg_list[i].show_precedence_graph()
break break
......
from PySide2.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout,\ from PySide2.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout,\
QLabel, QCheckBox, QSpinBox, QGroupBox, QFrame, QFormLayout, QGridLayout, QSizePolicy QLabel, QCheckBox, QSpinBox, QGroupBox, QFrame, QFormLayout, QGridLayout, QSizePolicy, QFileDialog, QShortcut
from PySide2.QtCore import Qt, Signal from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QIntValidator from PySide2.QtGui import QIntValidator, QKeySequence
from matplotlib.backends import qt_compat from matplotlib.backends import qt_compat
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
...@@ -52,10 +52,11 @@ class SimulateSFGWindow(QDialog): ...@@ -52,10 +52,11 @@ class SimulateSFGWindow(QDialog):
x += 1 x += 1
y = 0 y = 0
_input_value = QLineEdit() input_value = QLineEdit()
_input_value.setValidator(QIntValidator()) input_value.setPlaceholderText(str(i))
_input_value.setFixedWidth(50) input_value.setValidator(QIntValidator())
input_grid.addWidget(_input_value, x, y) input_value.setFixedWidth(50)
input_grid.addWidget(input_value, x, y)
y += 1 y += 1
input_layout.addLayout(input_grid) input_layout.addLayout(input_grid)
...@@ -93,9 +94,11 @@ class SimulateSFGWindow(QDialog): ...@@ -93,9 +94,11 @@ class SimulateSFGWindow(QDialog):
class Plot(FigureCanvas): class Plot(FigureCanvas):
def __init__(self, simulation, sfg, 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._window = window
fig = Figure(figsize=(width, height), dpi=dpi) fig = Figure(figsize=(width, height), dpi=dpi)
fig.suptitle(sfg.name, fontsize=20) fig.suptitle(sfg.name, fontsize=20)
...@@ -106,8 +109,22 @@ class Plot(FigureCanvas): ...@@ -106,8 +109,22 @@ class Plot(FigureCanvas):
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.activated.connect(self._save_plot_figure)
self._plot_values_sfg() self._plot_values_sfg()
def _save_plot_figure(self):
self._window.logger.info(f"Saving plot of figure: {self.sfg.name}.")
file_choices = "PNG (*.png)|*.png"
path, ext = QFileDialog.getSaveFileName(self, "Save file", "", file_choices)
path = path.encode("utf-8")
if not path[-4:] == file_choices[-4:].encode("utf-8"):
path += file_choices[-4:].encode("utf-8")
if path:
self.print_figure(path.decode(), dpi=self.dpi)
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.keys()))) x_axis = list(range(len(self.simulation.results.keys())))
for _output in range(self.sfg.output_count): for _output in range(self.sfg.output_count):
......
...@@ -6,6 +6,7 @@ def handle_error(fn): ...@@ -6,6 +6,7 @@ def handle_error(fn):
try: try:
return fn(self, *args, **kwargs) return fn(self, *args, **kwargs)
except Exception as e: except Exception as e:
self._window.logger.error(f"Unexpected error: {format_exc()}")
QErrorMessage(self._window).showMessage(f"Unexpected error: {format_exc()}") QErrorMessage(self._window).showMessage(f"Unexpected error: {format_exc()}")
return wrapper return wrapper
......
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