diff --git a/b_asic/GUI/drag_button.py b/b_asic/GUI/drag_button.py index 7506caa6533b0096facb6d522fbf4f3cd3475b23..b81ea9d4a6cfcabcaea071154fcaaec452a8e84a 100644 --- a/b_asic/GUI/drag_button.py +++ b/b_asic/GUI/drag_button.py @@ -5,8 +5,10 @@ This class creates a dragbutton which can be clicked, dragged and dropped. import os.path -from PyQt5.QtWidgets import QPushButton -from PyQt5.QtCore import Qt, QSize +from properties_window import PropertiesWindow + +from PyQt5.QtWidgets import QPushButton, QMenu, QAction +from PyQt5.QtCore import Qt, QSize, pyqtSignal from PyQt5.QtGui import QIcon from utils import decorate_class, handle_error @@ -14,8 +16,11 @@ from utils import decorate_class, handle_error @decorate_class(handle_error) class DragButton(QPushButton): - def __init__(self, name, operation, operation_path_name, window, parent = None): + connectionRequested = pyqtSignal(QPushButton) + moved = pyqtSignal() + def __init__(self, name, operation, operation_path_name, is_show_name, window, parent = None): self.name = name + self.is_show_name = is_show_name self._window = window self.operation = operation self.operation_path_name = operation_path_name @@ -25,6 +30,20 @@ class DragButton(QPushButton): self._mouse_move_pos = None super(DragButton, self).__init__(self._window) + def contextMenuEvent(self, event): + menu = QMenu() + properties = QAction("Properties") + menu.addAction(properties) + properties.triggered.connect(self.show_properties_window) + menu.exec_(self.cursor().pos()) + + def show_properties_window(self, event): + self.properties_window = PropertiesWindow(self, self._window) + self.properties_window.show() + + def add_label(self, label): + self.label = label + def mousePressEvent(self, event): if event.button() == Qt.LeftButton: @@ -38,20 +57,20 @@ class DragButton(QPushButton): if self.clicked == 1: self.pressed = True self.setStyleSheet("background-color: grey; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") + border-color: black; border-width: 2px") path_to_image = os.path.join('operation_icons', self.operation_path_name + '_grey.png') self.setIcon(QIcon(path_to_image)) - self.setIconSize(QSize(50, 50)) + self.setIconSize(QSize(55, 55)) self._window.pressed_button.append(self) elif self.clicked == 2: self.clicked = 0 self.pressed = False self.setStyleSheet("background-color: white; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") + border-color: black; border-width: 2px") path_to_image = os.path.join('operation_icons', self.operation_path_name + '.png') self.setIcon(QIcon(path_to_image)) - self.setIconSize(QSize(50, 50)) + self.setIconSize(QSize(55, 55)) self._window.pressed_button.remove(self) super(DragButton, self).mousePressEvent(event) diff --git a/b_asic/GUI/main_window.py b/b_asic/GUI/main_window.py index b65a118438b64ee9b6540bac5177b77cc9c2cf44..aa30dc2a4d913acfbe3398750a105dd8bb9e2c91 100644 --- a/b_asic/GUI/main_window.py +++ b/b_asic/GUI/main_window.py @@ -1,414 +1,215 @@ """@package docstring B-ASIC GUI Module. -This python file is an example of how a GUI can be implemented -using buttons and textboxes. +This python file is the main window of the GUI for B-ASIC. """ +from os import getcwd, path import sys +from drag_button import DragButton +from gui_interface import Ui_main_window +from arrow import Arrow +from port_button import PortButton + +from b_asic import Operation +import b_asic.core_operations as c_oper +import b_asic.special_operations as s_oper +from utils import decorate_class, handle_error + +from numpy import linspace + from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QAction,\ QStatusBar, QMenuBar, QLineEdit, QPushButton, QSlider, QScrollArea, QVBoxLayout,\ -QHBoxLayout, QDockWidget, QToolBar, QMenu -from PyQt5.QtCore import Qt, QSize, pyqtSlot -from PyQt5.QtGui import QIcon, QFont, QPainter, QPen, QColor - -from b_asic.core_operations import Addition - - -class DragButton(QPushButton): - def __init__(self, name, window, parent = None): - self.name = name - self.__menu = None - self.__window = window - self.counter = 0 - self.clicked = 0 - self.pressed = False - print("Constructor" + self.name) - super(DragButton, self).__init__(self.__window) - - self.__window.setContextMenuPolicy(Qt.CustomContextMenu) - self.__window.customContextMenuRequested.connect(self.create_menu) - - - @pyqtSlot(QAction) - def actionClicked(self, action): - print("Triggern "+ self.name, self.__menu.name) - #self.__window.check_for_remove_op(self.name) - - #def show_context_menu(self, point): - # show context menu - - - def create_menu(self, point): - self.counter += 1 - # create context menu - popMenu = MyMenu('Menu' + str(self.counter)) - popMenu.addAction(QAction('Add a signal', self)) - popMenu.addAction(QAction('Remove a signal', self)) - #action = QAction('Remove operation', self) - popMenu.addAction('Remove operation', lambda:self.removeAction(self)) - popMenu.addSeparator() - popMenu.addAction(QAction('Remove all signals', self)) - self.__window.menuList.append(popMenu) - #self.__window.actionList.append(action) - self.__menu = popMenu - self.pressed = False - self.__menu.exec_(self.__window.sender().mapToGlobal(point)) - self.__menu.triggered.connect(self.actionClicked) - - - def removeAction(self, op): - print(op.__menu.name, op.name) - op.remove() - - """This class is made to create a draggable button""" - - def mousePressEvent(self, event): - self._mouse_press_pos = None - self._mouse_move_pos = None - self.clicked += 1 - if self.clicked == 1: - self.pressed = True - self.setStyleSheet("background-color: grey; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") - elif self.clicked == 2: - self.clicked = 0 - self.presseed = False - self.setStyleSheet("background-color: white; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") - - if event.button() == Qt.LeftButton: - self._mouse_press_pos = event.globalPos() - self._mouse_move_pos = event.globalPos() - - super(DragButton, self).mousePressEvent(event) - - def mouseMoveEvent(self, event): - if event.buttons() == Qt.LeftButton: - cur_pos = self.mapToGlobal(self.pos()) - global_pos = event.globalPos() - diff = global_pos - self._mouse_move_pos - new_pos = self.mapFromGlobal(cur_pos + diff) - self.move(new_pos) - self.pressed = False - - self._mouse_move_pos = global_pos - - super(DragButton, self).mouseMoveEvent(event) - - def mouseReleaseEvent(self, event): - if self._mouse_press_pos is not None: - moved = event.globalPos() - self._mouse_press_pos - if moved.manhattanLength() > 3: - event.ignore() - return - - super(DragButton, self).mouseReleaseEvent(event) - - def remove(self): - self.deleteLater() - -class SubWindow(QWidget): - """Creates a sub window """ - def create_window(self, window_width, window_height): - """Creates a window - """ - parent = None - super(SubWindow, self).__init__(parent) - self.setWindowFlags(Qt.WindowStaysOnTopHint) - self.resize(window_width, window_height) +QHBoxLayout, QDockWidget, QToolBar, QMenu, QLayout, QSizePolicy, QListWidget,\ +QListWidgetItem, QGraphicsView, QGraphicsScene, QShortcut, QGraphicsTextItem,\ +QGraphicsProxyWidget +from PyQt5.QtCore import Qt, QSize +from PyQt5.QtGui import QIcon, QFont, QPainter, QPen, QBrush, QKeySequence -class MyMenu(QMenu): - def __init__(self, name, parent = None): - self.name = name - super(MyMenu, self).__init__() - +MIN_WIDTH_SCENE = 600 +MIN_HEIGHT_SCENE = 520 +@decorate_class(handle_error) class MainWindow(QMainWindow): - """Main window for the program""" - # pylint: disable=too-many-instance-attributes - # Eight is reasonable in this case. - def __init__(self, *args, **kwargs): - super(MainWindow, self).__init__(*args, **kwargs) - self.init_ui() - self.counter = 0 - self.operations = [] - self.menuList = [] - self.actionList = [] - - def init_ui(self): + def __init__(self): + super(MainWindow, self).__init__() + self.ui = Ui_main_window() + self.ui.setupUi(self) self.setWindowTitle(" ") self.setWindowIcon(QIcon('small_logo.png')) - self.create_operation_menu() - self.create_menu_bar() - self.setStatusBar(QStatusBar(self)) - - def create_operation_menu(self): - self.operation_box = QDockWidget("Operation Box", self) - self.operation_box.setAllowedAreas(Qt.LeftDockWidgetArea) - self.test = QToolBar(self) - self.operation_list = QMenuBar(self) - self.test.addWidget(self.operation_list) - self.test.setOrientation(Qt.Vertical) - self.operation_list.setStyleSheet("background-color:rgb(222,222,222); vertical") - basic_operations = self.operation_list.addMenu('Basic operations') - special_operations = self.operation_list.addMenu('Special operations') - - self.addition_menu_item = QAction('&Addition', self) - self.addition_menu_item.setStatusTip("Add addition operation to workspace") - self.addition_menu_item.triggered.connect(self.create_addition_operation) - basic_operations.addAction(self.addition_menu_item) - - self.subtraction_menu_item = QAction('&Subtraction', self) - self.subtraction_menu_item.setStatusTip("Add subtraction operation to workspace") - self.subtraction_menu_item.triggered.connect(self.create_subtraction_operation) - basic_operations.addAction(self.subtraction_menu_item) - - self.multiplication_menu_item = QAction('&Multiplication', self) - self.multiplication_menu_item.setStatusTip("Add multiplication operation to workspace") - self.multiplication_menu_item.triggered.connect(self.create_multiplication_operation) - basic_operations.addAction(self.multiplication_menu_item) - - self.division_menu_item = QAction('&Division', self) - self.division_menu_item.setStatusTip("Add division operation to workspace") - #self.division_menu_item.triggered.connect(self.create_division_operation) - basic_operations.addAction(self.division_menu_item) - - self.constant_menu_item = QAction('&Constant', self) - self.constant_menu_item.setStatusTip("Add constant operation to workspace") - #self.constant_menu_item.triggered.connect(self.create_constant_operation) - basic_operations.addAction(self.constant_menu_item) - - self.square_root_menu_item = QAction('&Square root', self) - self.square_root_menu_item.setStatusTip("Add square root operation to workspace") - #self.square_root_menu_item.triggered.connect(self.create_square_root_operation) - basic_operations.addAction(self.square_root_menu_item) - - self.complex_conjugate_menu_item = QAction('&Complex conjugate', self) - self.complex_conjugate_menu_item.setStatusTip("Add complex conjugate operation to workspace") - #self.complex_conjugate_menu_item.triggered.connect(self.create_complex_conjugate_operation) - basic_operations.addAction(self.complex_conjugate_menu_item) - - self.max_menu_item = QAction('&Max', self) - self.max_menu_item.setStatusTip("Add max operation to workspace") - #self.max_menu_item.triggered.connect(self.create_max_operation) - basic_operations.addAction(self.max_menu_item) - - self.min_menu_item = QAction('&Min', self) - self.min_menu_item.setStatusTip("Add min operation to workspace") - #self.min_menu_item.triggered.connect(self.create_min_operation) - basic_operations.addAction(self.min_menu_item) - - self.absolute_menu_item = QAction('&Absolute', self) - self.absolute_menu_item.setStatusTip("Add absolute operation to workspace") - #self.absolute_menu_item.triggered.connect(self.create_absolute_operation) - basic_operations.addAction(self.absolute_menu_item) - - self.constant_addition_menu_item = QAction('&Constant addition', self) - self.constant_addition_menu_item.setStatusTip("Add constant addition operation to workspace") - #self.constant_addition_menu_item.triggered.connect(self.create_constant_addition_operation) - basic_operations.addAction(self.constant_addition_menu_item) - - self.constant_subtraction_menu_item = QAction('&Constant subtraction', self) - self.constant_subtraction_menu_item.setStatusTip("Add constant subtraction operation to workspace") - #self.constant_subtraction_menu_item.triggered.connect(self.create_constant_subtraction_operation) - basic_operations.addAction(self.constant_subtraction_menu_item) - - self.constant_multiplication_menu_item = QAction('&Constant multiplication', self) - self.constant_multiplication_menu_item.setStatusTip("Add constant multiplication operation to workspace") - #self.constant_multiplication_menu_item.triggered.connect(self.create_constant_multiplication_operation) - basic_operations.addAction(self.constant_multiplication_menu_item) - - self.constant_division_menu_item = QAction('&Constant division', self) - self.constant_division_menu_item.setStatusTip("Add constant division operation to workspace") - #self.constant_division_menu_item.triggered.connect(self.create_constant_division_operation) - basic_operations.addAction(self.constant_division_menu_item) - - self.butterfly_menu_item = QAction('&Butterfly', self) - self.butterfly_menu_item.setStatusTip("Add butterfly operation to workspace") - #self.butterfly_menu_item.triggered.connect(self.create_butterfly_operation) - basic_operations.addAction(self.butterfly_menu_item) - - self.operation_box.setWidget(self.operation_list) - self.operation_box.setMaximumSize(240, 400) - self.operation_box.setFeatures(QDockWidget.NoDockWidgetFeatures) - self.operation_box.setFixedSize(300, 500) - self.operation_box.setStyleSheet("background-color: white; border-style: solid;\ - border-color: black; border-width: 2px") - self.addDockWidget(Qt.LeftDockWidgetArea, self.operation_box) - - def create_addition_operation(self): - self.counter += 1 - - # Create drag button - addition_operation = DragButton("OP" + str(self.counter), self) - addition_operation.move(250, 100) - addition_operation.setFixedSize(50, 50) - addition_operation.setStyleSheet("background-color: white; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") - addition_operation.clicked.connect(self.create_sub_window) - #self.addition_operation.setIcon(QIcon("GUI'\'operation_icons'\'plus.png")) - addition_operation.setText("OP" + str(self.counter)) - addition_operation.setIconSize(QSize(50, 50)) - addition_operation.show() - self.operations.append(addition_operation) - - # set context menu policies - #self.addition_operation.setContextMenuPolicy(Qt.CustomContextMenu) - #self.addition_operation.customContextMenuRequested.connect(self.show_context_menu) - - #self.action.triggered.connect(lambda checked: self.remove(self.addition_operation.name)) - - def check_for_remove_op(self, name): - self.remove(name) - - - def remove(self, name): - for op in self.operations: - print(name, op.name) - if op.name == name: - self.operations.remove(op) - op.remove() - - def create_subtraction_operation(self): - self.subtraction_operation = DragButton("sub" + str(self.counter), self) - self.subtraction_operation.move(250, 100) - self.subtraction_operation.setFixedSize(50, 50) - self.subtraction_operation.setStyleSheet("background-color: white; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") - self.subtraction_operation.setIcon(QIcon("GUI'\'operation_icons'\'minus.png")) - self.subtraction_operation.setIconSize(QSize(50, 50)) - self.subtraction_operation.clicked.connect(self.create_sub_window) - self.subtraction_operation.show() - - # set context menu policies - self.subtraction_operation.setContextMenuPolicy(Qt.CustomContextMenu) - self.subtraction_operation.customContextMenuRequested.connect(self.show_context_menu) - - # create context menu - self.button_context_menu = QMenu(self) - self.button_context_menu.addAction(QAction('Add a signal', self)) - self.button_context_menu.addAction(QAction('Remove a signal', self)) - self.button_context_menu.addSeparator() - self.button_context_menu.addAction(QAction('Remove all signals', self)) - - def create_multiplication_operation(self): - self.multiplication_operation = DragButton(self) - self.multiplication_operation.move(250, 100) - self.multiplication_operation.setFixedSize(50, 50) - self.multiplication_operation.setStyleSheet("background-color: white; border-style: solid;\ - border-color: black; border-width: 2px; border-radius: 10px") - self.multiplication_operation.clicked.connect(self.create_sub_window) - self.multiplication_operation.setIcon(QIcon(r"GUI\operation_icons\plus.png")) - self.multiplication_operation.setIconSize(QSize(50, 50)) - self.multiplication_operation.show() - - # set context menu policies - self.multiplication_operation.setContextMenuPolicy(Qt.CustomContextMenu) - self.multiplication_operation.customContextMenuRequested.connect(self.show_context_menu) - - # create context menu - self.button_context_menu = QMenu(self) - self.button_context_menu.addAction(QAction('Add a signal', self)) - self.button_context_menu.addAction(QAction('Remove a signal', self)) - self.button_context_menu.addSeparator() - self.button_context_menu.addAction(QAction('Remove all signals', self)) - - - def create_menu_bar(self): - # Menu buttons - load_button = QAction("Load", self) - save_button = QAction("Save", self) - - exit_button = QAction("Exit", self) - exit_button.setShortcut("Ctrl+Q") - exit_button.triggered.connect(self.exit_app) - - edit_button = QAction("Edit", self) - edit_button.setStatusTip("Open edit menu") - edit_button.triggered.connect(self.on_edit_button_click) - - view_button = QAction("View", self) - view_button.setStatusTip("Open view menu") - view_button.triggered.connect(self.on_view_button_click) - - menu_bar = QMenuBar() - menu_bar.setStyleSheet("background-color:rgb(222, 222, 222)") - self.setMenuBar(menu_bar) - - file_menu = menu_bar.addMenu("&File") - file_menu.addAction(save_button) - file_menu.addSeparator() - file_menu.addAction(exit_button) - - edit_menu = menu_bar.addMenu("&Edit") - edit_menu.addAction(edit_button) - - edit_menu.addSeparator() - - view_menu = menu_bar.addMenu("&View") - view_menu.addAction(view_button) - - - def create_sub_window(self): - """ Example of how to create a sub window - """ - self.sub_window = SubWindow() - self.sub_window.create_window(400, 300) - self.sub_window.setWindowTitle("Properties") - - self.sub_window.properties_label = QLabel(self.sub_window) - self.sub_window.properties_label.setText('Properties') - self.sub_window.properties_label.setFixedWidth(400) - self.sub_window.properties_label.setFont(QFont('SansSerif', 14, QFont.Bold)) - self.sub_window.properties_label.setAlignment(Qt.AlignCenter) + self.scene = None + self._operations_from_name = dict() + self.zoom = 1 + self.operationList = [] + self.signalList = [] + self.pressed_button = [] + self.portList = [] + self.pressed_ports = [] + self.source = None + self._window = self - self.sub_window.name_label = QLabel(self.sub_window) - self.sub_window.name_label.setText('Name:') - self.sub_window.name_label.move(20, 40) - - self.sub_window.name_line = QLineEdit(self.sub_window) - self.sub_window.name_line.setPlaceholderText("Write a name here") - self.sub_window.name_line.move(70, 40) - self.sub_window.name_line.resize(100, 20) - - self.sub_window.id_label = QLabel(self.sub_window) - self.sub_window.id_label.setText('Id:') - self.sub_window.id_label.move(20, 70) - - self.sub_window.id_line = QLineEdit(self.sub_window) - self.sub_window.id_line.setPlaceholderText("Write an id here") - self.sub_window.id_line.move(70, 70) - self.sub_window.id_line.resize(100, 20) + self.init_ui() + 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.sub_window.show() + self.shortcut_core = QShortcut(QKeySequence("Ctrl+R"), self.ui.operation_box) + self.shortcut_core.activated.connect(self._refresh_operations_list_from_namespace) - def keyPressEvent(self, event): - for op in self.operations: - if event.key() == Qt.Key_Delete and op.pressed: - self.operations.remove(op) - op.remove() - - def on_file_button_click(self): - print("File") + self.move_button_index = 0 + self.is_show_names = True - def on_edit_button_click(self): - print("Edit") + self.check_show_names = QAction("Show operation names") + self.check_show_names.triggered.connect(self.view_operation_names) + self.check_show_names.setCheckable(True) + self.check_show_names.setChecked(1) + self.ui.view_menu.addAction(self.check_show_names) - def on_view_button_click(self): - print("View") + def init_ui(self): + self.ui.core_operations_list.itemClicked.connect(self.on_list_widget_item_clicked) + self.ui.special_operations_list.itemClicked.connect(self.on_list_widget_item_clicked) + self.ui.exit_menu.triggered.connect(self.exit_app) + self.create_graphics_view() + + def create_graphics_view(self): + self.scene = QGraphicsScene(self) + self.graphic_view = QGraphicsView(self.scene, self) + self.graphic_view.setRenderHint(QPainter.Antialiasing) + self.graphic_view.setGeometry(self.ui.operation_box.width(), 0, self.width(), self.height()) + self.graphic_view.setDragMode(QGraphicsView.ScrollHandDrag) + + def resizeEvent(self, event): + 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()) + super(MainWindow, self).resizeEvent(event) + + def wheelEvent(self, event): + if event.modifiers() == Qt.ControlModifier: + old_zoom = self.zoom + self.zoom += event.angleDelta().y()/2500 + self.graphic_view.scale(self.zoom, self.zoom) + self.zoom = old_zoom + + def view_operation_names(self, event): + if self.check_show_names.isChecked(): + self.is_show_names = True + else: + self.is_show_names = False + for operation in self.operationList: + operation.label.setOpacity(self.is_show_names) + operation.is_show_name = self.is_show_names def exit_app(self, checked): QApplication.quit() - def clicked(self): - print("Drag button clicked") - + def _determine_port_distance(self, length, ports): + """Determine the distance between each port on the side of an operation. + The method returns the distance that each port should have from 0. + """ + return [length / 2] if ports == 1 else linspace(0, length, ports) + + def _create_port(self, operation, output_port=True): + text = ">" if output_port else "<" + button = PortButton(text, operation, self) + button.setStyleSheet("background-color: white") + button.connectionRequested.connect(self.connectButton) + return button + + def add_ports(self, operation): + _output_ports_dist = self._determine_port_distance(55 - 17, operation.operation.output_count) + _input_ports_dist = self._determine_port_distance(55 - 17, operation.operation.input_count) + + for dist in _input_ports_dist: + port = self._create_port(operation) + port.move(0, dist) + port.show() + + for dist in _output_ports_dist: + port = self._create_port(operation) + port.move(55 - 12, dist) + port.show() + + def get_operations_from_namespace(self, namespace): + return [comp for comp in dir(namespace) if hasattr(getattr(namespace, comp), "type_name")] + + def add_operations_from_namespace(self, namespace, _list): + for attr_name in self.get_operations_from_namespace(namespace): + attr = getattr(namespace, attr_name) + try: + attr.type_name() + item = QListWidgetItem(attr_name) + _list.addItem(item) + self._operations_from_name[attr_name] = attr + except NotImplementedError: + pass + + def _create_operation(self, item): + try: + 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.move(250, 100) + attr_button.setFixedSize(55, 55) + attr_button.setStyleSheet("background-color: white; border-style: solid;\ + border-color: black; border-width: 2px") + self.add_ports(attr_button) + + icon_path = path.join("operation_icons", f"{attr_oper.type_name().lower()}.png") + if not path.exists(icon_path): + icon_path = path.join("operation_icons", f"custom_operation.png") + attr_button.setIcon(QIcon(icon_path)) + attr_button.setIconSize(QSize(55, 55)) + attr_button.setParent(None) + attr_button_scene = self.scene.addWidget(attr_button) + attr_button_scene.moveBy(self.move_button_index * 100, 0) + self.move_button_index += 1 + operation_label = QGraphicsTextItem(attr_oper.type_name(), attr_button_scene) + if not self.is_show_names: + operation_label.setOpacity(0) + operation_label.setTransformOriginPoint(operation_label.boundingRect().center()) + operation_label.moveBy(10, -20) + attr_button.add_label(operation_label) + self.operationList.append(attr_button) + except Exception as e: + print("Unexpected error occured: ", e) + + def _refresh_operations_list_from_namespace(self): + self.ui.core_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(s_oper, self.ui.special_operations_list) + + def on_list_widget_item_clicked(self, item): + self._create_operation(item) + + def keyPressEvent(self, event): + pressed_buttons = [] + for op in self.operationList: + if op.pressed: + pressed_buttons.append(op) + if event.key() == Qt.Key_Delete: + for pressed_op in pressed_buttons: + self.operationList.remove(pressed_op) + pressed_op.remove() + self.move_button_index -= 1 + super().keyPressEvent(event) + + def connectButton(self, button): + if len(self.pressed_ports) < 2: + return + for i in range(len(self.pressed_ports) - 1): + line = Arrow(self.pressed_ports[i], self.pressed_ports[i + 1], self) + self.scene.addItem(line) + self.signalList.append(line) + + self.update() + + def paintEvent(self, event): + for signal in self.signalList: + signal.moveLine() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() - window.resize(960, 720) window.show() - app.exec_() + sys.exit(app.exec_()) diff --git a/b_asic/GUI/properties_window.py b/b_asic/GUI/properties_window.py new file mode 100644 index 0000000000000000000000000000000000000000..5aaee05c820f5d58a9b41d5fee506b176b6826f6 --- /dev/null +++ b/b_asic/GUI/properties_window.py @@ -0,0 +1,62 @@ +from PyQt5.QtWidgets import QDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout,\ +QLabel, QCheckBox +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QIntValidator + +class PropertiesWindow(QDialog): + def __init__(self, operation, main_window): + super(PropertiesWindow, self).__init__() + self.operation = operation + self.main_window = main_window + self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowCloseButtonHint) + self.setWindowTitle("Properties") + + self.name_layout = QHBoxLayout() + self.name_layout.setSpacing(50) + self.name_label = QLabel("Name:") + self.edit_name = QLineEdit(self.operation.operation_path_name) + self.name_layout.addWidget(self.name_label) + self.name_layout.addWidget(self.edit_name) + + self.vertical_layout = QVBoxLayout() + self.vertical_layout.addLayout(self.name_layout) + + if self.operation.operation_path_name == "c": + self.constant_layout = QHBoxLayout() + self.constant_layout.setSpacing(50) + self.constant_value = QLabel("Constant:") + self.edit_constant = QLineEdit(str(self.operation.operation.value)) + self.only_accept_int = QIntValidator() + self.edit_constant.setValidator(self.only_accept_int) + self.constant_layout.addWidget(self.constant_value) + self.constant_layout.addWidget(self.edit_constant) + self.vertical_layout.addLayout(self.constant_layout) + + self.show_name_layout = QHBoxLayout() + self.check_show_name = QCheckBox("Show name?") + if self.operation.is_show_name: + self.check_show_name.setChecked(1) + else: + self.check_show_name.setChecked(0) + self.check_show_name.setLayoutDirection(Qt.RightToLeft) + self.check_show_name.setStyleSheet("spacing: 170px") + self.show_name_layout.addWidget(self.check_show_name) + self.vertical_layout.addLayout(self.show_name_layout) + + self.ok = QPushButton("OK") + self.ok.clicked.connect(self.save_properties) + self.vertical_layout.addWidget(self.ok) + self.setLayout(self.vertical_layout) + + def save_properties(self): + self.operation.name = self.edit_name.text() + self.operation.label.setPlainText(self.operation.name) + if self.operation.operation_path_name == "c": + self.operation.operation.value = self.edit_constant.text() + if self.check_show_name.isChecked(): + self.operation.label.setOpacity(1) + self.operation.is_show_name = True + else: + self.operation.label.setOpacity(0) + self.operation.is_show_name = False + self.reject() \ No newline at end of file