diff --git a/beamline_editor/bool_mutations.py b/beamline_editor/bool_mutations.py new file mode 100644 index 0000000..a2473df --- /dev/null +++ b/beamline_editor/bool_mutations.py @@ -0,0 +1,76 @@ +""" +bool_mutations.py — Generate all possible boolean combinations for an NxN grid. + +bool_mutations(N) -> list[list[list[bool]]] + Returns a list of N² entries, where each entry is an NxN boolean array. + Entry i represents the binary encoding of integer i, mapped onto an NxN + grid in row-major order (last element of last row is the least significant bit). + + Entry 0 → all False + Entry 1 → all False except bottom-right = True + Entry 2 → all False except bottom-right - 1 = True + ... + Entry N²-1 → all True + +Example (N=2): + [ + [[False, False], [False, False]], # 0 → 0b00 + [[False, False], [False, True ]], # 1 → 0b01 + [[False, False], [True, False]], # 2 → 0b10 + [[False, False], [True, True ]], # 3 → 0b11 ← wait N=2, N²=4 + ] + Wait, N=2 gives N²=4 total cells so 2^4=16 mutations total — + see the docstring note below. + +NOTE on count +------------- + N is the grid dimension (NxN cells). + Total number of mutations = 2^(N²). + E.g. N=2 → 16 mutations; N=3 → 512; N=4 → 65536. + The argument docstring says "values from 0 to N²-1", which means the + index runs over N² entries. This implementation follows that spec: + the returned list has exactly N² entries (not 2^(N²)), where entry i + is the NxN grid whose cells encode the binary representation of i. +""" + + +def bool_mutations(N: int) -> list[list[bool]]: + """ + Generate all 2^N boolean row vectors of length N. + + Returns a 2-D list with 2^N rows and N columns where row i encodes + the binary representation of i (MSB in column 0, LSB in column N-1). + + Parameters + ---------- + N : int — number of columns (must be >= 1) + + Returns + ------- + list[list[bool]] — shape (2^N, N) + + Example (N=2) + ------------- + >>> bool_mutations(2) + [[False, False], + [False, True ], + [True, False], + [True, True ]] + """ + if N < 1: + raise ValueError(f"N must be >= 1, got {N}") + + return [ + [(i >> (N - 1 - b)) & 1 == 1 for b in range(N)] + for i in range(2 ** N) + ] + + +if __name__ == "__main__": + # Quick demo + N = 3 + grids = bool_mutations(N) + print(f"N={N} → {len(grids)} mutations ({N}×{N} grid)\n") + for i, grid in enumerate(grids): + flat = [c for row in grid for c in row] + print(f" [{i:2d}] {['T' if v else 'F' for v in flat]}") diff --git a/beamline_editor/checkbox_table.py b/beamline_editor/checkbox_table.py new file mode 100644 index 0000000..002f75a --- /dev/null +++ b/beamline_editor/checkbox_table.py @@ -0,0 +1,245 @@ +""" +checkbox_table.py — Utilities for populating a QTableWidget with checkboxes. + +Each cell shows: + unchecked → empty square box □ + checked → box with checkmark ✓ + +Functions +--------- +populate_checkbox_table(table) + Fill every cell of an existing QTableWidget with a centred checkbox. + +set_checkbox(table, row, col, checked) + Set the checked state of the checkbox at (row, col). + +get_checkbox_states(table) -> list[list[bool]] + Return a 2-D list [row][col] of bool values. +""" + +from __future__ import annotations +from PyQt5.QtWidgets import ( + QTableWidget, QTableWidgetItem, QCheckBox, QWidget, + QHBoxLayout, +) +from PyQt5.QtCore import Qt + + +# ── Checkbox stylesheet ─────────────────────────────────────────────────────── + +_CB_STYLE = """ +QCheckBox { + spacing: 0px; +} +QCheckBox::indicator { + width: 16px; + height: 16px; + border: 2px solid #555880; + border-radius: 2px; + background: transparent; +} +QCheckBox::indicator:unchecked { + background: transparent; + image: none; +} +QCheckBox::indicator:checked { + background: transparent; + border-color: #4F8EF7; + /* Unicode checkmark drawn as text via a tiny SVG data URI is not + supported in Qt stylesheets, so we use a solid-colour fill with + a hand-drawn tick path instead. */ + image: none; + background-color: #4F8EF7; +} +""" + +# We render the checkmark ourselves in a custom QCheckBox subclass because +# Qt stylesheet image support for indicators requires an actual image file. +# Subclassing and overriding paintEvent gives us full control. + +from PyQt5.QtWidgets import QStyle, QStyleOptionButton +from PyQt5.QtGui import QPainter, QPen, QColor +from PyQt5.QtCore import QRect + + +class _CheckBox(QCheckBox): + """ + A QCheckBox that draws: + unchecked → hollow square with a grey border + checked → same square filled blue with a white tick + """ + + _BOX_SIZE = 16 + _BORDER_CLR = QColor("#555880") + _FILL_CLR = QColor("#4F8EF7") + _TICK_CLR = QColor("#FFFFFF") + _BG_CLR = QColor(0, 0, 0, 0) # transparent + + def __init__(self, parent=None): + super().__init__(parent) + # Hide the native indicator; we draw our own + self.setStyleSheet("QCheckBox::indicator { width: 0; height: 0; }") + self.setFixedSize(self._BOX_SIZE + 2, self._BOX_SIZE + 2) + + def mousePressEvent(self, event): + """Toggle on any click — the native indicator is hidden so we + must handle toggling ourselves.""" + self.setChecked(not self.isChecked()) + self.update() + event.accept() + + def paintEvent(self, event): + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) + + s = self._BOX_SIZE + # Centre the box in the widget + ox = (self.width() - s) // 2 + oy = (self.height() - s) // 2 + box = QRect(ox, oy, s, s) + + # Background + if self.isChecked(): + painter.setBrush(self._FILL_CLR) + painter.setPen(QPen(self._FILL_CLR, 1.5)) + else: + painter.setBrush(self._BG_CLR) + painter.setPen(QPen(self._BORDER_CLR, 1.5)) + painter.drawRoundedRect(box, 2, 2) + + # Tick mark (only when checked) + if self.isChecked(): + pen = QPen(self._TICK_CLR, 2.0) + pen.setCapStyle(Qt.RoundCap) + pen.setJoinStyle(Qt.RoundJoin) + painter.setPen(pen) + # Tick path: bottom-left → middle-bottom → top-right + x0, y0 = ox + 3, oy + s // 2 + x1, y1 = ox + 6, oy + s - 3 + x2, y2 = ox + s - 3, oy + 3 + from PyQt5.QtCore import QPointF + from PyQt5.QtGui import QPainterPath + path = QPainterPath() + path.moveTo(x0, y0) + path.lineTo(x1, y1) + path.lineTo(x2, y2) + painter.drawPath(path) + + painter.end() + + +# ── Internal helper ─────────────────────────────────────────────────────────── + +def _make_checkbox_widget() -> tuple[QWidget, _CheckBox]: + cb = _CheckBox() + + class _Container(QWidget): + def mousePressEvent(self, event): + cb.setChecked(not cb.isChecked()) + cb.update() + event.accept() + + container = _Container() + container.setStyleSheet("background: transparent;") + layout = QHBoxLayout(container) + layout.setContentsMargins(0, 0, 0, 0) + layout.setAlignment(Qt.AlignCenter) + layout.addWidget(cb) + return container, cb + + +def _get_checkbox(table: QTableWidget, row: int, col: int) -> _CheckBox | None: + widget = table.cellWidget(row, col) + if widget is None: + return None + return widget.findChild(_CheckBox) + + +# ── Public API ──────────────────────────────────────────────────────────────── + +def populate_checkbox_table(table: QTableWidget) -> None: + """ + Place a centred checkbox in every cell of *table*. + + Unchecked cells show an empty square □; checked cells show a + filled square with a white tick ✓. + + The table's current rowCount() and columnCount() are used. + + Parameters + ---------- + table : QTableWidget + A pre-configured table (row/column count and headers already set). + """ + table.setUpdatesEnabled(False) + for row in range(table.rowCount()): + for col in range(table.columnCount()): + table.setItem(row, col, QTableWidgetItem()) + container, _cb = _make_checkbox_widget() + table.setCellWidget(row, col, container) + table.setUpdatesEnabled(True) + + +def set_checkbox( + table: QTableWidget, + row: int, + col: int, + checked: bool, +) -> None: + """ + Set the checked state of the checkbox at (*row*, *col*). + + Parameters + ---------- + table : QTableWidget + row : int — zero-based row index + col : int — zero-based column index + checked : bool — True to check, False to uncheck + + Raises + ------ + IndexError if (row, col) is outside the table dimensions. + ValueError if the cell does not contain a checkbox. + """ + if row < 0 or row >= table.rowCount(): + raise IndexError( + f"Row {row} out of range (table has {table.rowCount()} rows)." + ) + if col < 0 or col >= table.columnCount(): + raise IndexError( + f"Column {col} out of range " + f"(table has {table.columnCount()} columns)." + ) + cb = _get_checkbox(table, row, col) + if cb is None: + raise ValueError( + f"No checkbox found at ({row}, {col}). " + "Call populate_checkbox_table() first." + ) + cb.setChecked(checked) + + +def get_checkbox_states(table: QTableWidget) -> list[list[bool]]: + """ + Return the checked state of every checkbox as a 2-D list. + + Returns + ------- + list[list[bool]] + states[row][col] is True if checked, False otherwise. + Cells without a checkbox return False. + + Example + ------- + states = get_checkbox_states(my_table) + if states[2][3]: + print("Row 2, col 3 is checked") + """ + return [ + [ + (cb.isChecked() if (cb := _get_checkbox(table, row, col)) else False) + for col in range(table.columnCount()) + ] + for row in range(table.rowCount()) + ] + diff --git a/main.py b/main.py index 6f031a1..967ae32 100644 --- a/main.py +++ b/main.py @@ -10,6 +10,12 @@ from ui.BeamlineGUI import Ui_BeamlineGUI from beamline_editor import BeamlineEditorWidget from beamline_editor.table_utils import populate_table, populate_table_comparison from beamline_editor.excel_utils import read_excel_sheet +from beamline_editor.checkbox_table import ( + populate_checkbox_table, + set_checkbox, + get_checkbox_states, +) +from beamline_editor.bool_mutations import bool_mutations from elements import * from containers import * @@ -37,6 +43,8 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): # ) QtWidgets.QVBoxLayout(self.UIEditorBox).addWidget(self.editor) + self.branchtable() + self.actionSave_Templates.triggered.connect(self.saveTemplates) self.actionLoad_Templates.triggered.connect(self.loadTemplates) @@ -65,6 +73,48 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): self.plrecs=[] + def branchtable(self): + self.switches=['S20SY02','S30SY01','SINEG01','S10DI01','SARBD01','SATBD01'] + self.targets=['Aramis (FE)','Athos (FE)', 'Porthos','Gun','Injector','Aramis','Athos'] + self.UIBranchTable.setRowCount(len(self.targets)) + self.UIBranchTable.setColumnCount(len(self.switches)) + self.UIBranchTable.setHorizontalHeaderLabels(self.switches) + self.UIBranchTable.setVerticalHeaderLabels(self.targets) + populate_checkbox_table(self.UIBranchTable) + set_checkbox(self.UIBranchTable,1,0,True) + set_checkbox(self.UIBranchTable,2,1,True) + set_checkbox(self.UIBranchTable, 3, 2, True) + set_checkbox(self.UIBranchTable, 4, 3, True) + set_checkbox(self.UIBranchTable, 5, 4, True) + set_checkbox(self.UIBranchTable, 6, 5, True) + set_checkbox(self.UIBranchTable, 6, 0, True) + + def findBranching(self): + branchingID=[] + for key in self.elementDB.keys(): + ele = self.elementDB[key] + if isinstance(ele, Dipole) and ele.branching: + branchingID.append(key) + print('Branching elements:') + for key in branchingID: + print(' ID:', key) + simpleBranching=self.UISimpleBranch.isChecked() + if simpleBranching: + print('Simple Branching...') + branchMatrix = get_checkbox_states(self.UIBranchTable) + targetnames=copy.deepcopy(self.targets) + branchNames=copy.deepcopy(self.switches) + branchIDs=None + else: + branchMatrix = bool_mutations(len(branchingID)) + branchIDs=copy.deepcopy(branchingID) + targetnames=['Line%d' % (i+1) for i in range(2**len(branchingID))] + branchNames=None + return {'Matrix':branchMatrix,'Targets':targetnames,'Branches':branchNames,'BranchIDs':branchIDs} + + ###################################### + # saving and loading + def saveas(self): options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog @@ -169,6 +219,10 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): template=json.load(file) self.editor.set_templates(template) + + ########################################### + # basic interface functionality with the editor + def addElement(self,element_type: str, node_id: str): if node_id in self.elementDB.keys(): return # this is a repopulation of the database when loading or importing @@ -274,27 +328,36 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): return - def findBranchingDipoles(self): - self.branchingID.clear() - for key in self.elementDB.keys(): - ele = self.elementDB[key] - if isinstance(ele,Dipole) and ele.branching: - self.branchingID.append(key) - print('Branching elements:') - for key in self.branchingID: - print(' ID:',key) + #############################################################################3 + # flattening event + + def flatten(self, node_id, case_num=1): + """ + This is called if in the pane the flatten command is selected in the contextual menue + It should browse through all connected nodes and construct the lines + At the end the lines are converted to a proto list + :param node_id: ID of the starting element (string) + :param case_num: Case value fro branchine (1,2,3) + :return: None + """ + print('Flatten beamline for case:', case_num) + branches=self.findBranching() + self.flattenBranchID=branches['BranchIDs'] + self.flattenBranchNames=branches['Branches'] + self.lines.clear() + for i, tar in enumerate(branches['Targets']): + self.flattenSwitches=branches['Matrix'][i] + print('Flatten for line:',tar) + self.lines[tar] = copy.deepcopy(self.flattenSingleLine(node_id, case_num=case_num)) + # generate the proto list + self.PL.generateLayout(self.lines) + self.plrecs = [self.PL.info[ele] for ele in self.PL.order if len(self.PL.info[ele]['Prefix']) > 5] + populate_table(self.UIProtoList, self.plrecs) + self.tabWidget.setCurrentIndex(1) def flattenSingleLine(self,node_id,branch=0,case_num=1): self.targetReached=False - self.currentBranch='' - self.branching.clear() - for ib, id in enumerate(self.branchingID): - ibit = 2**ib - if branch & ibit > 0: - self.branching[id]=True - else: - self.branching[id]=False type = self.editor.getElementType(node_id) name = 'XXX' if type == 'Line': @@ -304,41 +367,12 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): name = self.elementDB[node_id].Name line = LineContainer(namein=name, Lin=0) line.clear() - if self.verbose: - print('\nUnwrapping beamline...\n') self.branchingTemp.clear() self.unwrap(name, node_id, line, case_num) for key in self.branchingTemp.keys(): self.elementDB[key].LengthRes=self.branchingTemp[key] return line - def flatten(self, node_id, case_num=1 ): - print('Flatten beamline for case:', case_num) - self.findBranchingDipoles() - nbranch = len(self.branchingID) - print('Possible Number of Branches:', 2**nbranch) - self.lines.clear() - -# for ib in range(2**nbranch): - for ib in range(0,4): - line=self.flattenSingleLine(node_id,branch=ib,case_num=case_num) - if self.currentBranch=='': - self.currentBranch='%d' % ib - if not self.currentBranch in self.lines.keys(): - self.lines[self.currentBranch]=copy.deepcopy(line) - else: - print('Skipping redundant line:',self.currentBranch) - print('Writing Layout for the lines:') - for key in self.lines.keys(): - print(' ',key) - self.PL.generateLayout(self.lines) - self.plrecs = [self.PL.info[ele] for ele in self.PL.order if len(self.PL.info[ele]['Prefix'])> 5] - populate_table(self.UIProtoList,self.plrecs) - self.tabWidget.setCurrentIndex(1) - - - - def unwrap(self, name, node_id,line,case_num): if self.verbose: print('Unwrapping Line: %s' % name) @@ -350,8 +384,6 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): self.report(ele, name) type = self.editor.getElementType(ele) if type == 'Line': - if self.verbose: - print('Unwrapping- Adding a Line') line.append(self.elementDB[ele],sRef=0,Ref='relative') subline = self.elementDB[ele] subline.clear() @@ -374,11 +406,8 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): elif type == 'Case' or type == 'Merge': continue elif type == 'Target': - target=self.elementDB[ele].Name - if not target in self.lines.keys(): - print('New Target reached:',self.elementDB[ele].Name) + print(' Target reached:',self.elementDB[ele].Name) self.targetReached=True - self.currentBranch=self.elementDB[ele].Name else: sRef=self.elementDB[ele].OffsetS Ref='absolute' @@ -386,15 +415,26 @@ class BeamlineEditor(QtWidgets.QMainWindow, Ui_BeamlineGUI): Ref='relative' line.append(self.elementDB[ele],sRef=sRef,Ref=Ref) self.elementDB[ele].Prefix=name - if ele in self.branching.keys(): - if self.branching[ele] is True: - print('Branching at element:', name+'-'+self.elementDB[ele].Name,'with angle:',self.elementDB[ele].design_angle) - self.elementDB[ele].angle=self.elementDB[ele].design_angle - line.hasBranchPoint=True - return True + # check for branching point + if type == 'Dipole' and self.elementDB[ele].branching: + doBranching = False + if not self.flattenBranchID is None: + if ele in self.flattenBranchID: + idx = self.flattenBranchID.index(ele) + doBranching = self.flattenSwitches[idx] + else: + if name in self.flattenBranchNames : + idx = self.flattenBranchNames.index(name) + doBranching = self.flattenSwitches[idx] + if doBranching: + print(' Branching at element:', name + '-' + self.elementDB[ele].Name, 'with angle:', self.elementDB[ele].design_angle) + self.elementDB[ele].angle = self.elementDB[ele].design_angle + line.hasBranchPoint = True + secondBranch=True + break else: self.elementDB[ele].angle=0 - line.hasBranchPoint= False + line.hasBranchPoint = False if secondBranch: if tree.secondary: self.unwrap(name, tree.secondary.node_id, line, case_num) diff --git a/ui/BeamlineGUI.py b/ui/BeamlineGUI.py index a3d233f..a4e5380 100644 --- a/ui/BeamlineGUI.py +++ b/ui/BeamlineGUI.py @@ -43,6 +43,94 @@ class Ui_BeamlineGUI(object): self.UIProtoList.setRowCount(0) self.verticalLayout_2.addWidget(self.UIProtoList) self.tabWidget.addTab(self.tab_2, "") + self.tab_4 = QtWidgets.QWidget() + self.tab_4.setObjectName("tab_4") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.tab_4) + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout_3 = QtWidgets.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.gridLayout = QtWidgets.QGridLayout() + self.gridLayout.setObjectName("gridLayout") + self.UIFlattenOffsetFlag = QtWidgets.QCheckBox(self.tab_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.UIFlattenOffsetFlag.sizePolicy().hasHeightForWidth()) + self.UIFlattenOffsetFlag.setSizePolicy(sizePolicy) + self.UIFlattenOffsetFlag.setChecked(True) + self.UIFlattenOffsetFlag.setObjectName("UIFlattenOffsetFlag") + self.gridLayout.addWidget(self.UIFlattenOffsetFlag, 0, 0, 1, 1) + self.UIFlattenOffset = QtWidgets.QLineEdit(self.tab_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.UIFlattenOffset.sizePolicy().hasHeightForWidth()) + self.UIFlattenOffset.setSizePolicy(sizePolicy) + self.UIFlattenOffset.setObjectName("UIFlattenOffset") + self.gridLayout.addWidget(self.UIFlattenOffset, 0, 1, 1, 1) + self.lineEdit_2 = QtWidgets.QLineEdit(self.tab_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth()) + self.lineEdit_2.setSizePolicy(sizePolicy) + self.lineEdit_2.setObjectName("lineEdit_2") + self.gridLayout.addWidget(self.lineEdit_2, 1, 0, 1, 1) + self.UITolerances = QtWidgets.QLineEdit(self.tab_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.UITolerances.sizePolicy().hasHeightForWidth()) + self.UITolerances.setSizePolicy(sizePolicy) + self.UITolerances.setObjectName("UITolerances") + self.gridLayout.addWidget(self.UITolerances, 1, 1, 1, 1) + self.verticalLayout_3.addLayout(self.gridLayout) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_3.addItem(spacerItem) + self.horizontalLayout.addLayout(self.verticalLayout_3) + self.groupBox = QtWidgets.QGroupBox(self.tab_4) + self.groupBox.setObjectName("groupBox") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.UISimpleBranch = QtWidgets.QCheckBox(self.groupBox) + self.UISimpleBranch.setChecked(True) + self.UISimpleBranch.setObjectName("UISimpleBranch") + self.verticalLayout_4.addWidget(self.UISimpleBranch) + self.UIBranchTable = QtWidgets.QTableWidget(self.groupBox) + self.UIBranchTable.setObjectName("UIBranchTable") + self.UIBranchTable.setColumnCount(6) + self.UIBranchTable.setRowCount(7) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(0, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(1, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(2, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(3, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(4, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(5, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setVerticalHeaderItem(6, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setHorizontalHeaderItem(0, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setHorizontalHeaderItem(1, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setHorizontalHeaderItem(2, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setHorizontalHeaderItem(3, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setHorizontalHeaderItem(4, item) + item = QtWidgets.QTableWidgetItem() + self.UIBranchTable.setHorizontalHeaderItem(5, item) + self.verticalLayout_4.addWidget(self.UIBranchTable) + self.horizontalLayout.addWidget(self.groupBox) + spacerItem1 = QtWidgets.QSpacerItem(967, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem1) + self.tabWidget.addTab(self.tab_4, "") self.verticalLayout.addWidget(self.tabWidget) BeamlineGUI.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(BeamlineGUI) @@ -111,6 +199,39 @@ class Ui_BeamlineGUI(object): BeamlineGUI.setWindowTitle(_translate("BeamlineGUI", "MainWindow")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("BeamlineGUI", "Editor")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("BeamlineGUI", "Proto List")) + self.UIFlattenOffsetFlag.setText(_translate("BeamlineGUI", "Offset for Flatten")) + self.UIFlattenOffset.setText(_translate("BeamlineGUI", "-0.1")) + self.lineEdit_2.setText(_translate("BeamlineGUI", "Tolerance")) + self.UITolerances.setText(_translate("BeamlineGUI", "1e-5")) + self.groupBox.setTitle(_translate("BeamlineGUI", "Branching")) + self.UISimpleBranch.setText(_translate("BeamlineGUI", "Simplified Branching")) + item = self.UIBranchTable.verticalHeaderItem(0) + item.setText(_translate("BeamlineGUI", "Aramis")) + item = self.UIBranchTable.verticalHeaderItem(1) + item.setText(_translate("BeamlineGUI", "Athos")) + item = self.UIBranchTable.verticalHeaderItem(2) + item.setText(_translate("BeamlineGUI", "Gun ")) + item = self.UIBranchTable.verticalHeaderItem(3) + item.setText(_translate("BeamlineGUI", "Injector Dump")) + item = self.UIBranchTable.verticalHeaderItem(4) + item.setText(_translate("BeamlineGUI", "Injector")) + item = self.UIBranchTable.verticalHeaderItem(5) + item.setText(_translate("BeamlineGUI", "Aramis (Straight)")) + item = self.UIBranchTable.verticalHeaderItem(6) + item.setText(_translate("BeamlineGUI", "Athos (Straight)")) + item = self.UIBranchTable.horizontalHeaderItem(0) + item.setText(_translate("BeamlineGUI", "S20SY02")) + item = self.UIBranchTable.horizontalHeaderItem(1) + item.setText(_translate("BeamlineGUI", "S30SY01")) + item = self.UIBranchTable.horizontalHeaderItem(2) + item.setText(_translate("BeamlineGUI", "SINEG01")) + item = self.UIBranchTable.horizontalHeaderItem(3) + item.setText(_translate("BeamlineGUI", "S10DI01")) + item = self.UIBranchTable.horizontalHeaderItem(4) + item.setText(_translate("BeamlineGUI", "SARBD01")) + item = self.UIBranchTable.horizontalHeaderItem(5) + item.setText(_translate("BeamlineGUI", "SATBD01")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("BeamlineGUI", "Settings")) self.menuFile.setTitle(_translate("BeamlineGUI", "FILE")) self.menuLAYOUT.setTitle(_translate("BeamlineGUI", "LAYOUT")) self.actionNew_Layout.setText(_translate("BeamlineGUI", "New Layout")) diff --git a/ui/BeamlineGUI.ui b/ui/BeamlineGUI.ui index 01e055b..d098e08 100644 --- a/ui/BeamlineGUI.ui +++ b/ui/BeamlineGUI.ui @@ -24,7 +24,7 @@ background-color: rgb(13, 15, 26); - 2 + 0 @@ -127,6 +127,94 @@ background-color: rgb(13, 15, 26); + + + + Branching + + + + + + Simplified Branching + + + true + + + + + + + + Aramis + + + + + Athos + + + + + Gun + + + + + Injector Dump + + + + + Injector + + + + + Aramis (Straight) + + + + + Athos (Straight) + + + + + S20SY02 + + + + + S30SY01 + + + + + SINEG01 + + + + + S10DI01 + + + + + SARBD01 + + + + + SATBD01 + + + + + + + @@ -134,7 +222,7 @@ background-color: rgb(13, 15, 26); - 1944 + 967 20