Skip to content
Snippets Groups Projects
Commit 2769576c authored by Andreas Bolin's avatar Andreas Bolin
Browse files

workspace dump

parent c0b5ff87
No related branches found
No related tags found
1 merge request!78Add scheduler GUI
Pipeline #73055 failed
...@@ -5,7 +5,7 @@ Graphical user interface for B-ASIC scheduler. ...@@ -5,7 +5,7 @@ Graphical user interface for B-ASIC scheduler.
from logger import * from logger import *
from main_window import * from main_window import *
from graphics_scene import * from graphics_graph import *
#__all__ = ['main_window', 'scheduler'] #__all__ = ['main_window', 'scheduler']
__version__ = '0.1' __version__ = '0.1'
......
...@@ -31,30 +31,46 @@ from b_asic.schedule import Schedule ...@@ -31,30 +31,46 @@ from b_asic.schedule import Schedule
# class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem): # class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem):
class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem): class ComponentItem(QGraphicsItemGroup):
# class ComponentItem(QGraphicsLayoutItem, QGraphicsItemGroup): # class ComponentItem(QGraphicsLayoutItem, QGraphicsItemGroup):
# class ComponentItem(QGraphicsLayoutItem, QGraphicsItem): # class ComponentItem(QGraphicsLayoutItem, QGraphicsItem):
_scale: float _scale: float
_height: float
_component_item: QGraphicsPathItem _component_item: QGraphicsPathItem
_execution_time_item: QGraphicsPathItem _execution_time_item: QGraphicsPathItem
_item_group: QGraphicsItemGroup _item_group: QGraphicsItemGroup
def __init__(self, scale: float, parent: QGraphicsWidget = None): def __init__(self, scale: float, height: float = 1.5):
QGraphicsItemGroup.__init__(self) super().__init__()
QGraphicsLayoutItem.__init__(self, parent = parent)
self.setGraphicsItem(self)
self._scale = scale self._scale = scale
self._height = height
self._component_item = QGraphicsPathItem()
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! A') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! A')
self._item_group = QGraphicsItemGroup() self._item_group = QGraphicsItemGroup()
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! B') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! B')
self._populate() self._populate()
self.setFlag(QGraphicsItem.ItemIsMovable)
self.setFlag(QGraphicsItem.ItemIsSelectable)
# print(self.boundingRect().size()) # print(self.boundingRect().size())
def _populate(self): @property
def scale(self) -> float:
return self._scale
@scale.setter
def scale(self, scale: float) -> None:
self._scale = scale()
self.prepareGeometryChange()
self.update()
@property
def height(self) -> float:
return self._height
def _populate(self) -> None:
# brush = QBrush(Qt.lightGray, bs=Qt.SolidPattern) # brush = QBrush(Qt.lightGray, bs=Qt.SolidPattern)
brush = QBrush(Qt.lightGray) brush = QBrush(Qt.lightGray)
# brush.setStyle(Qt.SolidPattern) # brush.setStyle(Qt.SolidPattern)
...@@ -66,20 +82,22 @@ class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem): ...@@ -66,20 +82,22 @@ class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem):
# component path # component path
component_path = QPainterPath(QPoint(0,0)) component_path = QPainterPath(QPoint(0,0))
component_path.lineTo(0, 1) component_path.lineTo(0, self._height/2)
component_path.lineTo(4, 1) component_path.lineTo(0.2, self._height/2)
component_path.lineTo(0.2, self._height)
component_path.lineTo(4, self._height)
component_path.lineTo(4, 0) component_path.lineTo(4, 0)
component_path.closeSubpath() component_path.closeSubpath()
# component item # component item
self._component_item = QGraphicsPathItem(component_path) self._component_item.setPath(component_path)
self._component_item.setPen(pen) self._component_item.setPen(pen)
self._component_item.setBrush(brush) self._component_item.setBrush(brush)
self._component_item.setPos(0.5,0) # in parent (i.e. item_group) coordinates self._component_item.setPos(0.5,0) # in parent (i.e. item_group) coordinates
# execution time square # execution time square
execution_time_path = QPainterPath(QPoint(0,0)) execution_time_path = QPainterPath(QPoint(0,0))
execution_time_path.addRect(0, 0, 1.0, 1.0) execution_time_path.addRect(0, 0, self._height, self._height)
# execution time item # execution time item
green_color = QColor(Qt.magenta) green_color = QColor(Qt.magenta)
...@@ -113,41 +131,7 @@ class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem): ...@@ -113,41 +131,7 @@ class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem):
# reimplement QGraphicsLayoutItem virtual functions
def updateGeometry(self):
print('updateGeometry()')
QGraphicsLayoutItem.updateGeometry(self)
def setGeometry(self, geom: QRectF) -> None:
print(f'setGeometry({geom})')
self.prepareGeometryChange()
QGraphicsLayoutItem.setGeometry(self, geom)
self.setPos(geom.topLeft())
def sizeHint(self, which: Qt.SizeHint, constraint: QSizeF = QSizeF()) -> QSizeF:
print(f'sizeHint(which={which}, constraint={constraint}')
# return QSizeF(1000, 100)
# if self.isEmpty():
# pass
# item = self.graphicsItem()
switch = {
Qt.MinimumSize: self.boundingRect().size(),
Qt.PreferredSize: self.boundingRect().size(),
# Qt.MinimumSize: self.geometry().size(),
# Qt.PreferredSize: self.geometry().size(),
Qt.MaximumSize: QSizeF(float("inf"), float("inf"))
# Qt.MaximumSize: self.parentItem().boundingRect().size()
}
ret = switch.get(which, constraint)
print(f'ret: {ret}')
return switch.get(which, constraint)
def minimumSize(self):
print('minimumSize()')
# # reimplement QGraphicsItem virtual functions # # reimplement QGraphicsItem virtual functions
# def boundingRect(self) -> QRectF: # def boundingRect(self) -> QRectF:
# print('boundingRect()') # print('boundingRect()')
......
import os
import sys
from typing import Any, Optional
from pprint import pprint
from typing import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final
# from typing_extensions import Self, Final, Literal, LiteralString, TypeAlias, final
import numpy as np
from copy import deepcopy
from itertools import combinations
import qtpy
from qtpy import QtCore
from qtpy import QtGui
from qtpy import QtWidgets
# QGraphics and QPainter imports
from qtpy.QtCore import (
Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray)
from qtpy.QtGui import (
QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
QLinearGradient, QTransform)
from qtpy.QtWidgets import (
QGraphicsView, QGraphicsScene, QGraphicsWidget,
QGraphicsLayout, QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayoutItem, QGraphicsAnchorLayout,
QGraphicsItem, QGraphicsItemGroup, QGraphicsPathItem, QGraphicsLineItem, QGraphicsTextItem,
QStyleOptionGraphicsItem, QWidget, QGraphicsObject)
from qtpy.QtCore import (
QPoint, QPointF)
# B-ASIC
import logger
class GraphicsAxis(QGraphicsItemGroup):
_scale: float
_width: float
_height: float
_axis: dict[str: Any]
def __init__(self, scale: float, width: float = 0.0, height: float = 0.0):
super().__init__()
self._scale = scale
self._width = width
self._height = height
self._axis = {}
# self._axis['x'] = QGraphicsItemGroup()
# self._axis['y'] = QGraphicsLineItem()
self._make_axis()
@property
def width(self) -> float:
return self._axis['w']
@width.setter
def width(self, width: float) -> None:
self._axis['w'] = width
self.prepareGeometryChange()
self._axis.clear()
self._make_axis()
@property
def height(self) -> float:
return self._axis['h']
@height.setter
def height(self, height: float) -> None:
self._axis['h'] = height
self.prepareGeometryChange()
self._axis.clear()
self._make_axis()
# def _clear(self) -> None:
# for child in self._axis.values():
# del child
def _make_axis(self) -> None:
pen = QPen()
pen.setWidthF(2/self._scale)
# x-axis
self._axis['x'] = QGraphicsItemGroup()
line1 = QGraphicsLineItem(0, 0, self._width, 0)
line1.setPen(pen)
self._axis['x'].addToGroup(line1)
# x-axis arrow
line2 = QGraphicsLineItem(0, 0, -5/self._scale, -5/self._scale)
line2.setPen(pen)
line2.setPos(self._width, 0)
self._axis['x'].addToGroup(line2)
line3 = QGraphicsLineItem(0, 0, -5/self._scale, 5/self._scale)
line3.setPen(pen)
line3.setPos(self._width, 0)
self._axis['x'].addToGroup(line3)
self._axis['x'].setPos(0, self._height)
# x-axis scale
ticks = [x for x in range(int(self._width) + 1)]
# print('xxxxxxxxxxxxxxxxxxxxxxx', x)
line4 = QGraphicsLineItem(0, -5/self._scale, 0, 5/self._scale)
# for i in range(len(ticks)):
# lines[i] =
# x-axis label
label = QGraphicsTextItem('time')
label.setFlag(QGraphicsItem.ItemIgnoresTransformations)
label.setPos(self._width, self._height + 5/self._scale)
# add x-axis
self.addToGroup(self._axis['x'])
self.addToGroup(label)
# y-axis
self._axis['y'] = QGraphicsLineItem(0, 0, 0, self._height)
self._axis['y'].setPen(pen)
self._axis['y'].setPos(0, 0)
# add y-axis
self.addToGroup(self._axis['y'])
\ No newline at end of file
import os
import sys
from typing import Any, Optional
from pprint import pprint
from typing import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final
# from typing_extensions import Self, Final, Literal, LiteralString, TypeAlias, final
import numpy as np
from copy import deepcopy
from itertools import combinations
import qtpy
from qtpy import QtCore
from qtpy import QtGui
from qtpy import QtWidgets
# QGraphics and QPainter imports
from qtpy.QtCore import (
Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray)
from qtpy.QtGui import (
QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
QLinearGradient, QTransform)
from qtpy.QtWidgets import (
QGraphicsView, QGraphicsScene, QGraphicsWidget,
QGraphicsLayout, QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayoutItem, QGraphicsAnchorLayout,
QGraphicsItem, QGraphicsItemGroup, QGraphicsPathItem, QGraphicsLineItem,
QStyleOptionGraphicsItem, QWidget, QGraphicsObject)
from qtpy.QtCore import (
QPoint, QPointF)
# B-ASIC
import logger
from b_asic.schedule import Schedule
from component_item import ComponentItem
from graphics_axis import GraphicsAxis
class GraphicsGraph(QGraphicsItemGroup):
_schedule: Schedule
_scale: float
_axis: dict[str, QGraphicsLineItem] # {'x': <x-axis>, 'y': y-axis}
_component_group: QGraphicsItemGroup
_axis_group: QGraphicsItemGroup
def __init__(self, schedule: Schedule, scale: float = 100.0, *args, **kwargs):
super().__init__(*args, **kwargs)
self._schedule = deepcopy(schedule)
self._scale = scale
self._axis = {}
self._component_group = QGraphicsItemGroup()
self._axis_group = QGraphicsItemGroup()
# add components
y: float = 0.0
for i in range(3):
component = ComponentItem(self._scale)
component.setPos(0, y)
self._component_group.addToGroup(component)
y += component.height + 0.2
self._component_group.setPos(0.2, 0.1)
self.addToGroup(self._component_group)
y += 0.1
# add x-axis
# self._component_group.boundingRect().width()
axis = GraphicsAxis(self._scale, 5, y)
self.addToGroup(axis)
@property
def scale(self) -> float:
return self._scale
@scale.setter
def scale(self, scale:float) -> None:
self._scale = scale
for component in self._component_group.childItems():
component.scale = scale
@property
def items(self) -> list[ComponentItem]:
return self._component_group.childItems()
\ No newline at end of file
...@@ -45,7 +45,7 @@ from qtpy.QtWidgets import ( ...@@ -45,7 +45,7 @@ from qtpy.QtWidgets import (
# B-ASIC # B-ASIC
import logger import logger
from b_asic.schedule import Schedule from b_asic.schedule import Schedule
from graphics_scene import GraphicsScene from graphics_graph import GraphicsGraph
from component_item import ComponentItem from component_item import ComponentItem
...@@ -109,10 +109,10 @@ QCoreApplication.setApplicationName('B-ASIC Scheduler') ...@@ -109,10 +109,10 @@ QCoreApplication.setApplicationName('B-ASIC Scheduler')
class MainWindow(QMainWindow, Ui_MainWindow): class MainWindow(QMainWindow, Ui_MainWindow):
"""Schedule of an SFG with scheduled Operations.""" """Schedule of an SFG with scheduled Operations."""
# _schedules: dict # _schedules: dict
_scenes: dict[str, GraphicsScene] # _scenes: dict[str, GraphicsScene]
_scene: QGraphicsScene _scene: QGraphicsScene
_diagrams: dict[str, QGraphicsWidget] _graphs: dict[str, QGraphicsWidget]
_diagram_count: int _graph_count: int
_scene_count: int _scene_count: int
_open_file_dialog_opened: bool _open_file_dialog_opened: bool
_scale: float _scale: float
...@@ -121,9 +121,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -121,9 +121,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
"""Initialize Schedule-gui.""" """Initialize Schedule-gui."""
super().__init__() super().__init__()
self._scenes = {} self._scenes = {}
self._diagrams = {} self._graphs = {}
self._scene_count = 0 self._scene_count = 0
self._diagram_count = 0 self._graph_count = 0
self._open_file_dialog_opened = False self._open_file_dialog_opened = False
self._scale = 100.0 self._scale = 100.0
...@@ -270,45 +270,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -270,45 +270,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# self._scene_count += 1 # self._scene_count += 1
# windowLayout = QGraphicsLinearLayout(Qt.Vertical) graph = GraphicsGraph(schedule, self._scale)
vertical = QGraphicsLinearLayout(Qt.Vertical)
# linear1 = QGraphicsLinearLayout(windowLayout) self._scene.addItem(graph)
linear1 = QGraphicsLinearLayout(Qt.Horizontal)
# linear1.setAlignment(Qt.AlignLeft| Qt.AlignTop)
linear2 = QGraphicsLinearLayout(Qt.Horizontal)
linear1.setMaximumSize(linear1.minimumSize())
linear2.setMaximumSize(linear2.minimumSize())
vertical.setMaximumSize(vertical.minimumSize())
linear1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, QSizePolicy.DefaultType)
linear2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, QSizePolicy.DefaultType)
vertical.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, QSizePolicy.DefaultType)
widget = QGraphicsWidget()
item1 = ComponentItem(self._scale)
item2 = ComponentItem(self._scale)
item3 = ComponentItem(self._scale)
linear1.addItem(item1)
linear1.setStretchFactor(item1, 1)
linear1.addItem(item2)
linear2.addItem(item3)
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1')
vertical.addItem(linear1)
vertical.addItem(linear2)
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2')
print(f'boundingRect: {item1.boundingRect()}')
print(f'vertical.getContentsMargins(): {vertical.getContentsMargins()}')
print(f'linear1.getContentsMargins(): {linear1.getContentsMargins()}')
print(f'linear2.getContentsMargins(): {linear2.getContentsMargins()}')
# widget.setLayout(windowLayout)
widget.setLayout(vertical)
widget.setWindowTitle(self.tr("Basic Graphics Layouts Example"))
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3')
self._scene.addItem(widget)
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4')
self._diagrams[self._diagram_count] = widget self._graphs[self._graph_count] = graph
self._diagram_count += 1 self._graph_count += 1
self.update_statusbar(self.tr('Schedule loaded successfully')) self.update_statusbar(self.tr('Schedule loaded successfully'))
@Slot() @Slot()
......
import os
import sys
from typing import Any, Optional
from pprint import pprint
from typing import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final
# from typing_extensions import Self, Final, Literal, LiteralString, TypeAlias, final
import numpy as np
import qtpy
from qtpy import QtCore
from qtpy import QtGui
from qtpy import QtWidgets
# QGraphics and QPainter imports
from qtpy.QtCore import (
Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray)
from qtpy.QtGui import (
QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
QLinearGradient, QTransform)
from qtpy.QtWidgets import (
QGraphicsView, QGraphicsScene, QGraphicsWidget,
QGraphicsLayout, QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayoutItem, QGraphicsAnchorLayout,
QGraphicsItem, QGraphicsItemGroup, QGraphicsPathItem,
QStyleOptionGraphicsItem, QWidget)
from qtpy.QtCore import (
QPoint, QPointF)
# B-ASIC
import logger
from b_asic.schedule import Schedule
# class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem):
class ComponentItem(QGraphicsItemGroup, QGraphicsLayoutItem):
# class ComponentItem(QGraphicsLayoutItem, QGraphicsItemGroup):
# class ComponentItem(QGraphicsLayoutItem, QGraphicsItem):
_scale: float
_component_item: QGraphicsPathItem
_execution_time_item: QGraphicsPathItem
_item_group: QGraphicsItemGroup
def __init__(self, scale: float, parent: QGraphicsWidget = None):
QGraphicsItemGroup.__init__(self)
QGraphicsLayoutItem.__init__(self, parent = parent)
self.setGraphicsItem(self)
self._scale = scale
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! A')
self._item_group = QGraphicsItemGroup()
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! B')
self._populate()
# print(self.boundingRect().size())
def _populate(self):
# brush = QBrush(Qt.lightGray, bs=Qt.SolidPattern)
brush = QBrush(Qt.lightGray)
# brush.setStyle(Qt.SolidPattern)
pen = QPen(Qt.SolidLine)
pen.setWidthF(1/self._scale)
pen.setBrush(Qt.darkGray)
# pen.setCapStyle(Qt.RoundCap) # Qt.FlatCap, Qt.SquareCap (default), Qt.RoundCap
pen.setJoinStyle(Qt.RoundJoin) # Qt.MiterJoin, Qt.BevelJoin (default), Qt.RoundJoin, Qt.SvgMiterJoin
# component path
component_path = QPainterPath(QPoint(0,0))
component_path.lineTo(0, 1)
component_path.lineTo(4, 1)
component_path.lineTo(4, 0)
component_path.closeSubpath()
# component item
self._component_item = QGraphicsPathItem(component_path)
self._component_item.setPen(pen)
self._component_item.setBrush(brush)
self._component_item.setPos(0.5,0) # in parent (i.e. item_group) coordinates
# execution time square
execution_time_path = QPainterPath(QPoint(0,0))
execution_time_path.addRect(0, 0, 1.0, 1.0)
# execution time item
green_color = QColor(Qt.magenta)
green_color.setAlpha(200) # 0-255
pen.setColor(green_color)
self._execution_time_item = QGraphicsPathItem(execution_time_path)
self._execution_time_item.setPen(pen)
# item group, consist of time_item and component_item
# item_group = QGraphicsItemGroup()
# graphics_item = self.graphicsItem()
# print(graphics_item)
# self._item_group = graphics_item.childItems()[0]
# print(self._item_group)
# # item_group.setScale(self._scale)
# print('############################# 1')
# self._item_group.addToGroup(self._component_item)
# print('############################# 2')
# self._item_group.addToGroup(self._execution_time_item)
print('############################# 1')
self.addToGroup(self._component_item)
print('############################# 2')
self.addToGroup(self._execution_time_item)
# self.setGraphicsItem(self)
# QGraphicsItemGroup
# self.setGroup(item_group)
print('Populated!')
# reimplement QGraphicsLayoutItem virtual functions
def updateGeometry(self):
print('updateGeometry()')
QGraphicsLayoutItem.updateGeometry(self)
def setGeometry(self, geom: QRectF) -> None:
print(f'setGeometry({geom})')
self.prepareGeometryChange()
QGraphicsLayoutItem.setGeometry(self, geom)
self.setPos(geom.topLeft())
def sizeHint(self, which: Qt.SizeHint, constraint: QSizeF = QSizeF()) -> QSizeF:
print(f'sizeHint(which={which}, constraint={constraint}')
# return QSizeF(1000, 100)
# if self.isEmpty():
# pass
# item = self.graphicsItem()
switch = {
Qt.MinimumSize: self.boundingRect().size(),
Qt.PreferredSize: self.boundingRect().size(),
# Qt.MinimumSize: self.geometry().size(),
# Qt.PreferredSize: self.geometry().size(),
Qt.MaximumSize: QSizeF(float("inf"), float("inf"))
# Qt.MaximumSize: self.parentItem().boundingRect().size()
}
ret = switch.get(which, constraint)
print(f'ret: {ret}')
return switch.get(which, constraint)
def minimumSize(self):
print('minimumSize()')
# # reimplement QGraphicsItem virtual functions
# def boundingRect(self) -> QRectF:
# print('boundingRect()')
# # return self._item_group.boundingRect()
# return QRectF(QPointF(0,0), self.geometry().size())
# def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: Optional[QWidget]= None) -> None:
# print(f'paint(painter={painter}, option={option}, widget={widget})')
# painter.drawRoundedRect(-10, -10, 20, 20, 5, 5)
# # self._item_group.paint(painter, option, widget)
# print("MRO:")
# pprint(ComponentItem.__mro__)
\ No newline at end of file
# This Python file uses the following encoding: utf-8
"""B-ASIC Scheduler-gui Module.
Contains the scheduler-gui class for scheduling operations in an SFG.
Start main-window with start_gui().
"""
import os
import sys
from pathlib import Path
from types import ModuleType
from typing import Any
from pprint import pprint
#from matplotlib.pyplot import bar
#from diagram import *
from importlib.machinery import SourceFileLoader
import inspect
# Qt/qtpy
import qtpy
from qtpy import uic, QtCore, QtGui, QtWidgets
from qtpy.QtCore import QCoreApplication, Qt, Slot, QSettings, QStandardPaths
from qtpy.QtGui import QCloseEvent
from qtpy.QtWidgets import (
QApplication, QMainWindow, QMessageBox, QFileDialog, QInputDialog, QCheckBox, QAbstractButton,
QTableWidgetItem, QSizePolicy)
# QGraphics and QPainter imports
from qtpy.QtCore import (
QRect, QRectF, QPoint, QSize, QByteArray)
from qtpy.QtGui import (
QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
QLinearGradient)
from qtpy.QtWidgets import (
QGraphicsView, QGraphicsScene, QGraphicsWidget,
QGraphicsLayout, QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayoutItem, QGraphicsAnchorLayout,
QGraphicsItem, QGraphicsItemGroup)
# B-ASIC
import logger
from b_asic.schedule import Schedule
from graphics_scene import GraphicsScene
from component_item import ComponentItem
log = logger.getLogger()
# Debug struff
if __debug__:
log.setLevel('DEBUG')
if __debug__:
# Print some system version information
QT_API = os.environ.get('QT_API')
log.debug('Qt version (runtime): {}'.format(QtCore.qVersion()))
log.debug('Qt version (compiletime): {}'.format(QtCore.__version__))
log.debug('QT_API: {}'.format(QT_API))
if QT_API.lower().startswith('pyside'):
import PySide2
log.debug('PySide version: {}'.format(PySide2.__version__))
if QT_API.lower().startswith('pyqt'):
from qtpy.QtCore import PYQT_VERSION_STR
log.debug('PyQt version: {}'.format(PYQT_VERSION_STR))
log.debug('QtPy version: {}'.format(qtpy.__version__))
# Autocompile the .ui form to a python file.
try: # PyQt5, try autocompile
from qtpy.uic import compileUiDir
uic.compileUiDir('.', map=(lambda dir,file: (dir, 'ui_' + file)))
except:
try: # PySide2, try manual compile
import subprocess
os_ = sys.platform
if os_.startswith('linux'):
cmds = ['pyside2-uic -o ui_main_window.py main_window.ui']
for cmd in cmds:
subprocess.call(cmd.split())
else:
#TODO: Implement (startswith) 'win32', 'darwin' (MacOs)
raise SystemExit
except: # Compile failed, look for pre-compiled file
try:
from ui_main_window import Ui_MainWindow
except: # Everything failed, exit
log.exception("Could not import 'Ui_MainWindow'.")
log.exception("Can't autocompile under", QT_API, "eviroment. Try to manual compile 'main_window.ui' to 'ui/main_window_ui.py'")
os._exit(1)
sys.path.insert(0, 'icons/') # Needed for the compiled '*_rc.py' files in 'ui_*.py' files
from ui_main_window import Ui_MainWindow # Only availible when the form (.ui) is compiled
# The folowing QCoreApplication values is used for QSettings among others
QCoreApplication.setOrganizationName('Linöping University')
QCoreApplication.setOrganizationDomain('liu.se')
QCoreApplication.setApplicationName('B-ASIC Scheduler')
#QCoreApplication.setApplicationVersion(__version__) # TODO: read from packet __version__
class MainWindow(QMainWindow, Ui_MainWindow):
"""Schedule of an SFG with scheduled Operations."""
# _schedules: dict
_scenes: dict[str, GraphicsScene]
_scene: QGraphicsScene
_diagrams: dict[str, QGraphicsWidget]
_diagram_count: int
_scene_count: int
_open_file_dialog_opened: bool
_scale: float
def __init__(self):
"""Initialize Schedule-gui."""
super().__init__()
self._scenes = {}
self._diagrams = {}
self._scene_count = 0
self._diagram_count = 0
self._open_file_dialog_opened = False
self._scale = 100.0
QIcon.setThemeName('breeze')
log.debug('themeName: \'{}\''.format(QIcon.themeName()))
log.debug('themeSearchPaths: {}'.format(QIcon.themeSearchPaths()))
self._init_ui()
self._init_graphics()
self._read_settings()
def _init_ui(self) -> None:
"""Initialize the ui"""
self.setupUi(self)
# Connect signals to slots
self.menu_load_from_file.triggered .connect(self._load_schedule_from_pyfile)
self.menu_save .triggered .connect(self.save)
self.menu_save_as .triggered .connect(self.save_as)
self.menu_quit .triggered .connect(self.close)
self.menu_node_info .triggered .connect(self.toggle_component_info)
self.menu_exit_dialog .triggered .connect(self.toggle_exit_dialog)
self.actionT .triggered .connect(self.actionTbtn)
self.splitter_center .splitterMoved .connect(self._splitter_center_moved)
# Setup event member functions
self.closeEvent = self._close_event
# Setup info table
self.info_table.setHorizontalHeaderLabels(['Property','Value'])
# test = '#b085b2'
# self.info_table.setStyleSheet('alternate-background-color: lightGray;background-color: white;')
self.info_table.setStyleSheet('alternate-background-color: #fadefb;background-color: #ebebeb;')
for i in range(10):
self.info_table.insertRow(i)
item = QTableWidgetItem('this is a very very very very long string that says abolutly nothing')
self.info_table.setItem(i,0, QTableWidgetItem('property {}: '.format(i)))
self.info_table.setItem(i,1,item)
# Init central-widget splitter
self.splitter_center.setStretchFactor(0, 1)
self.splitter_center.setStretchFactor(1, 0)
self.splitter_center.setCollapsible(0, False)
self.splitter_center.setCollapsible(1, True)
def _init_graphics(self) -> None:
"""Initialize the QGraphics framework"""
# scene = GraphicsScene(0, parent=self)
# self.graphic_view.setScene(scene)
# self.graphic_view.setRenderHint(QPainter.Antialiasing)
# self.graphic_view.setGeometry(20, 20, self.width(), self.height())
self.graphics_view.setDragMode(QGraphicsView.RubberBandDrag)
self.graphics_view.scale(self._scale, self._scale)
self._scene = QGraphicsScene()
self.graphics_view.setScene(self._scene)
###############
#### Slots ####
###############
@Slot()
def actionTbtn(self) -> None:
# print('_scene_count:', self._scene_count)
scene = self._scenes[self._scene_count - 1]
sched = scene.schedule
print('From MainWindow:\t\t\t', end='')
pprint(sched)
# print('')
self._scenes[self._scene_count - 1].plot_schedule()
# self.printButtonPressed('callback_pushButton()')
@Slot()
def _load_schedule_from_pyfile(self) -> None:
open_dir = QStandardPaths.standardLocations(QStandardPaths.HomeLocation)[0] if not self._open_file_dialog_opened else ''
abs_path_filename = QFileDialog.getOpenFileName(self, self.tr("Open python file"),
open_dir,
self.tr("Python Files (*.py *.py3)"))
abs_path_filename = abs_path_filename[0]
if not abs_path_filename: # return if empty filename (QFileDialog was canceled)
return
log.debug('abs_path_filename = {}.'.format(abs_path_filename))
self._open_file_dialog_opened = True
module_name = inspect.getmodulename(abs_path_filename)
if not module_name: # return if empty module name
log.error('Could not load module from file \'{}\'.'.format(abs_path_filename))
return
try:
module = SourceFileLoader(module_name, abs_path_filename).load_module()
except:
log.exception('Exception occurred. Could not load module from file \'{}\'.'.format(abs_path_filename))
return
schedule_obj_list = dict(inspect.getmembers(module, (lambda x: type(x) == Schedule)))
if not schedule_obj_list: # return if no Schedule objects in script
QMessageBox.warning(self,
self.tr('File not found'),
self.tr('Could not find any Schedule object in file \'{}\'.')
.format(os.path.basename(abs_path_filename)))
log.info('Could not find any Schedule object in file \'{}\'.'
.format(os.path.basename(abs_path_filename)))
del module
return
ret_tuple = QInputDialog.getItem(self,
self.tr('Load object'),
self.tr('Found the following Schedule object(s) in file.)\n\n'
'Select an object to proceed:'),
schedule_obj_list.keys(),0,False)
if not ret_tuple[1]: # User canceled the operation
log.debug('Load schedule operation: user canceled')
del module
return
self.open(schedule_obj_list[ret_tuple[0]])
del module
#@Slot()
def open(self, schedule: Schedule) -> None:
"""Takes in an Schedule and place it in the schedule list."""
#TODO: all
#TODO: Unique hash keys
#TODO: self.open(schedule_obj_list[ret_tuple[0])
# scene = GraphicsScene(self._scene_count, schedule, self.graphics_view)
# #scene = QGraphicsScene()
# self._scenes[self._scene_count] = scene
# self.graphics_view.setScene(scene)
# self.graphics_view.setRenderHint(QPainter.Antialiasing)
# # self.graphics_view.setGeometry(20, 20, self.width(), self.height())
# self.graphics_view.setDragMode(QGraphicsView.RubberBandDrag)
# # self.graphics_view.scale(10.0, 10.0)
# self._scene_count += 1
# windowLayout = QGraphicsLinearLayout(Qt.Vertical)
vertical = QGraphicsLinearLayout(Qt.Vertical)
# linear1 = QGraphicsLinearLayout(windowLayout)
linear1 = QGraphicsLinearLayout(Qt.Horizontal)
# linear1.setAlignment(Qt.AlignLeft| Qt.AlignTop)
linear2 = QGraphicsLinearLayout(Qt.Horizontal)
linear1.setMaximumSize(linear1.minimumSize())
linear2.setMaximumSize(linear2.minimumSize())
vertical.setMaximumSize(vertical.minimumSize())
linear1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, QSizePolicy.DefaultType)
linear2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, QSizePolicy.DefaultType)
vertical.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, QSizePolicy.DefaultType)
widget = QGraphicsWidget()
item1 = ComponentItem(self._scale)
item2 = ComponentItem(self._scale)
item3 = ComponentItem(self._scale)
linear1.addItem(item1)
linear1.setStretchFactor(item1, 1)
linear1.addItem(item2)
linear2.addItem(item3)
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1')
vertical.addItem(linear1)
vertical.addItem(linear2)
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2')
print(f'boundingRect: {item1.boundingRect()}')
print(f'vertical.getContentsMargins(): {vertical.getContentsMargins()}')
print(f'linear1.getContentsMargins(): {linear1.getContentsMargins()}')
print(f'linear2.getContentsMargins(): {linear2.getContentsMargins()}')
# widget.setLayout(windowLayout)
widget.setLayout(vertical)
widget.setWindowTitle(self.tr("Basic Graphics Layouts Example"))
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3')
self._scene.addItem(widget)
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4')
self._diagrams[self._diagram_count] = widget
self._diagram_count += 1
self.update_statusbar(self.tr('Schedule loaded successfully'))
@Slot()
def save(self) -> None:
"""This method save an schedule."""
#TODO: all
self.printButtonPressed('save_schedule()')
self.update_statusbar(self.tr('Schedule saved successfully'))
@Slot()
def save_as(self) -> None:
"""This method save as an schedule."""
#TODO: all
self.printButtonPressed('save_schedule()')
self.update_statusbar(self.tr('Schedule saved successfully'))
@Slot(bool)
def toggle_component_info(self, checked: bool) -> None:
"""This method toggles the right hand side info window."""
# Note: splitter handler index 0 is a hidden splitter handle far most left, use index 1
settings = QSettings()
range = self.splitter_center.getRange(1) # tuple(min, max)
if checked:
self.splitter_center.restoreState(settings.value("mainwindow/splitter_center/last_state"))
# self.splitter_center.restoreState(settings.value("splitterSizes"))
else:
settings.setValue("mainwindow/splitter_center/last_state", self.splitter_center.saveState())
self.splitter_center.moveSplitter(range[1], 1)
@Slot(bool)
def toggle_exit_dialog(self, checked: bool) -> None:
s = QSettings()
s.setValue("mainwindow/hide_exit_dialog", checked)
@Slot(int, int)
def _splitter_center_moved(self, pos: int, index: int) -> None:
"""Callback method used to check if the right widget (info window)
has collapsed. Update the checkbutton accordingly."""
# TODO: Custom move handler, save state on click-release?
widths: list[int, int] = list(self.splitter_center.sizes())
if widths[1] == 0:
self.menu_node_info.setChecked(False)
else:
self.menu_node_info.setChecked(True)
################
#### Events ####
################
def _close_event(self, event: QCloseEvent) -> None:
"""Replaces QMainWindow default closeEvent(QCloseEvent) event"""
s = QSettings()
hide_dialog = s.value('mainwindow/hide_exit_dialog', False, bool)
ret = QMessageBox.StandardButton.Yes
if not hide_dialog:
box = QMessageBox(self)
box.setWindowTitle(self.tr('Confirm Exit'))
box.setText('<h3>' + self.tr('Confirm Exit') + '</h3><p><br>' +
self.tr('Are you sure you want to exit?') +
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></p>')
box.setIcon(QMessageBox.Question)
box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
buttons: list[QAbstractButton] = box.buttons()
buttons[0].setText(self.tr('&Exit'))
buttons[1].setText(self.tr('&Cancel'))
checkbox = QCheckBox(self.tr('Don\'t ask again'))
box.setCheckBox(checkbox)
ret = box.exec_()
if ret == QMessageBox.StandardButton.Yes:
if not hide_dialog:
s.setValue('mainwindow/hide_exit_dialog', checkbox.isChecked())
self._write_settings()
log.info('Exit: {}'.format(os.path.basename(__file__)))
event.accept()
else:
event.ignore()
#################################
#### Helper member functions ####
#################################
def printButtonPressed(self, func_name: str) -> None:
#TODO: remove
self.label.setText("hello")
alert = QMessageBox(self)
alert.setText("Called from " + func_name + '!')
alert.exec_()
def update_statusbar(self, msg: str) -> None:
"""Write the given str to the statusbar with temporarily policy."""
self.statusbar.showMessage(msg)
def _write_settings(self) -> None:
"""Write settings from MainWindow to Settings."""
s = QSettings()
s.setValue('mainwindow/maximized', self.isMaximized()) # window: maximized, in X11 - alwas False
s.setValue('mainwindow/pos', self.pos()) # window: pos
s.setValue('mainwindow/size', self.size()) # window: size
s.setValue('mainwindow/state', self.saveState()) # toolbars, dockwidgets: pos, size
s.setValue('mainwindow/menu/node_info', self.menu_node_info.isChecked())
s.setValue('mainwindow/splitter/state', self.splitter_center.saveState())
if s.isWritable():
log.debug('Settings written to \'{}\'.'.format(s.fileName()))
else:
log.warning('Settings cant be saved to file, read-only.')
def _read_settings(self) -> None:
"""Read settings from Settings to MainWindow."""
s = QSettings()
if s.value('mainwindow/maximized', defaultValue=False, type=bool):
self.showMaximized()
else:
self.move( s.value('mainwindow/pos', self.pos()))
self.resize( s.value('mainwindow/size', self.size()))
self.restoreState( s.value('mainwindow/state', QByteArray()))
self.menu_node_info.setChecked( s.value('mainwindow/menu/node_info', True, bool))
self.splitter_center.restoreState( s.value('mainwindow/splitter/state', QByteArray()))
self.menu_exit_dialog.setChecked(s.value('mainwindow/hide_exit_dialog', False, bool))
log.debug('Settings read from \'{}\'.'.format(s.fileName()))
def start_gui():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
start_gui()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment