dirty work on BHS

This commit is contained in:
Theophile Terraz committed 2023-12-11 15:44:31 +01:00
commit f302e18d71
35 files changed
+682 -120

No files matched your search

+1 -1
View File
@@ -160,7 +160,7 @@ class EditBoundaryConditionWindow(PamhyrWindow):
table_headers=headers,
editable_headers=self._data.header,
delegates={
#"time": self._delegate_time,
# "time": self._delegate_time,
},
data=self._data,
undo=self._undo_stack,
+2 -2
View File
@@ -115,13 +115,13 @@ class ComboBoxDelegate(QItemDelegate):
class TableModel(PamhyrTableModel):
def __init__(self, trad = None, **kwargs):
def __init__(self, trad=None, **kwargs):
self._trad = trad
self._long_types = {}
if self._trad is not None:
self._long_types = self._trad.get_dict("long_types")
super(TableModel, self).__init__(trad = trad, **kwargs)
super(TableModel, self).__init__(trad=trad, **kwargs)
def _setup_lst(self):
self._lst = self._data.boundary_condition
@@ -18,3 +18,160 @@
import logging
import traceback
from tools import trace, timer
from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel,
QCoreApplication, QModelIndex, pyqtSlot,
QRect,
)
from PyQt5.QtWidgets import (
QDialogButtonBox, QPushButton, QLineEdit,
QFileDialog, QTableView, QAbstractItemView,
QUndoStack, QShortcut, QAction, QItemDelegate,
QComboBox,
)
from View.Tools.PamhyrTable import PamhyrTableModel
from View.HydraulicStructures.BasicHydraulicStructures.UndoCommand import (
SetNameCommand, SetTypeCommand,
AddCommand, DelCommand,
)
from Model.HydraulicStructures.Basic.Types import BHS_types
logger = logging.getLogger()
_translate = QCoreApplication.translate
class ComboBoxDelegate(QItemDelegate):
def __init__(self, data=None, trad=None, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self._data = data
self._trad = trad
self._long_types = {}
if self._trad is not None:
self._long_types = self._trad.get_dict("long_types")
def createEditor(self, parent, option, index):
self.editor = QComboBox(parent)
lst = list(
map(
lambda k: self._long_types[k], BHS_types.keys()
)
)
self.editor.addItems(
lst
)
self.editor.setCurrentText(index.data(Qt.DisplayRole))
return self.editor
def setEditorData(self, editor, index):
value = index.data(Qt.DisplayRole)
self.editor.currentTextChanged.connect(self.currentItemChanged)
def setModelData(self, editor, model, index):
text = str(editor.currentText())
model.setData(index, text)
editor.close()
editor.deleteLater()
def updateEditorGeometry(self, editor, option, index):
r = QRect(option.rect)
if self.editor.windowFlags() & Qt.Popup:
if editor.parent() is not None:
r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft()))
editor.setGeometry(r)
@pyqtSlot()
def currentItemChanged(self):
self.commitData.emit(self.sender())
class TableModel(PamhyrTableModel):
def _setup_lst(self):
self._lst = self._data.basic_structures
def rowCount(self, parent):
return len(self._lst)
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
row = index.row()
column = index.column()
if self._headers[column] == "name":
return self._lst[row].name
elif self._headers[column] == "type":
n = self._lst[row].type
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
if not index.isValid() or role != Qt.EditRole:
return False
row = index.row()
column = index.column()
try:
if self._headers[column] == "name":
self._undo.push(
SetNameCommand(
self._data, row, value
)
)
elif self._headers[column] == "type":
self._undo.push(
SetTypeCommand(
self._data, row, type
)
)
except Exception as e:
logger.info(e)
logger.debug(traceback.format_exc())
self.dataChanged.emit(index, index)
return True
def add(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1)
self._undo.push(
AddCommand(
self._data, row
)
)
self.endInsertRows()
self.layoutChanged.emit()
def delete(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1])
self._undo.push(
DelCommand(
self._data, rows
)
)
self.endRemoveRows()
self.layoutChanged.emit()
def undo(self):
self._undo.undo()
self.layoutChanged.emit()
def redo(self):
self._undo.redo()
self.layoutChanged.emit()
@@ -21,3 +21,17 @@ from PyQt5.QtCore import QCoreApplication
from View.Tools.PamhyrTranslate import PamhyrTranslate
_translate = QCoreApplication.translate
class BasicHydraulicStructuresTranslate(PamhyrTranslate):
def __init__(self):
super(BasicHydraulicStructuresTranslate, self).__init__()
self._sub_dict["long_types"] = {
"ND": _translate("BasicHydraulicStructures", "Not defined"),
}
self._sub_dict["table_headers"] = {
"name": _translate("BasicHydraulicStructures", "Name"),
"type": _translate("BasicHydraulicStructures", "Type"),
}
@@ -15,3 +15,104 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from copy import deepcopy
from tools import trace, timer
from PyQt5.QtWidgets import (
QMessageBox, QUndoCommand, QUndoStack,
)
class SetNameCommand(QUndoCommand):
def __init__(self, hs, index, new_value):
QUndoCommand.__init__(self)
self._hs = hs
self._index = index
self._old = self._hs.basic_structure(self._index).name
self._new = str(new_value)
def undo(self):
self._hs.basic_structure(self._index).name = self._old
def redo(self):
self._hs.basic_structure(self._index).name = self._new
class SetTypeCommand(QUndoCommand):
def __init__(self, hs, index, reach):
QUndoCommand.__init__(self)
self._hs = hs
self._index = index
self._type = _type
self._old = self._hs.basic_structure(self._index)
self._new = self._hs.basic_structure(self._index)\
.convert(self._type)
def undo(self):
self._hs.basic_structure(self._index).convert(self._old)
def redo(self):
self._hs.basic_structure(self._index).convert(self._new)
class AddCommand(QUndoCommand):
def __init__(self, hs, index):
QUndoCommand.__init__(self)
self._hs = hs
self._index = index
self._new = None
def undo(self):
self._hs.delete_i([self._index])
def redo(self):
if self._new is None:
self._new = self._hs.add(self._index)
else:
self._hs.insert(self._index, self._new)
class DelCommand(QUndoCommand):
def __init__(self, hs, rows):
QUndoCommand.__init__(self)
self._hs = hs
self._rows = rows
self._bhs = []
for row in rows:
self._bhs.append((row, self._hs.basic_structure(row)))
def undo(self):
for row, el in self._bhs:
self._hs.insert(row, el)
def redo(self):
self._hs.delete_i(self._rows)
class PasteCommand(QUndoCommand):
def __init__(self, hs, row, h_s):
QUndoCommand.__init__(self)
self._hs = hs
self._row = row
self._bhs = deepcopy(h_s)
self._bhs.reverse()
def undo(self):
self._hs.delete_i(
self._tab,
range(self._row, self._row + len(self._bhs))
)
def redo(self):
for r in self._bhs:
self._hs.insert(self._row, r)
@@ -15,3 +15,207 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import logging
from tools import timer, trace
from View.Tools.PamhyrWindow import PamhyrWindow
from PyQt5 import QtCore
from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel, QCoreApplication,
pyqtSlot, pyqtSignal, QItemSelectionModel,
)
from PyQt5.QtWidgets import (
QDialogButtonBox, QPushButton, QLineEdit,
QFileDialog, QTableView, QAbstractItemView,
QUndoStack, QShortcut, QAction, QItemDelegate,
QHeaderView, QDoubleSpinBox, QVBoxLayout, QCheckBox
)
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.HydraulicStructures.PlotAC import PlotAC
from View.HydraulicStructures.BasicHydraulicStructures.Table import (
TableModel, ComboBoxDelegate
)
from View.Network.GraphWidget import GraphWidget
from View.HydraulicStructures.BasicHydraulicStructures.Translate import BasicHydraulicStructuresTranslate
_translate = QCoreApplication.translate
logger = logging.getLogger()
class BasicHydraulicStructuresWindow(PamhyrWindow):
_pamhyr_ui = "BasicHydraulicStructures"
_pamhyr_name = "Basic Hydraulic Structures"
def __init__(self, data=None, study=None, config=None, parent=None):
name = self._pamhyr_name + " - " + study.name
super(BasicHydraulicStructuresWindow, self).__init__(
title=name,
study=study,
config=config,
trad=BasicHydraulicStructuresTranslate(),
parent=parent
)
self._hash_data.append(data)
self._hs = data
self.setup_table()
self.setup_checkbox()
self.setup_plot()
self.setup_connections()
def setup_table(self):
self._table = None
self._delegate_type = ComboBoxDelegate(
trad=self._trad,
parent=self
)
table = self.find(QTableView, f"tableView")
self._table = TableModel(
table_view=table,
table_headers=self._trad.get_dict("table_headers"),
editable_headers=["name", "type"],
delegates={
"type": self._delegate_type,
},
trad=self._trad,
data=self._hs,
undo=self._undo_stack,
)
selectionModel = table.selectionModel()
index = table.model().index(0, 0)
selectionModel.select(
index,
QItemSelectionModel.Rows |
QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Select
)
table.scrollTo(index)
def setup_checkbox(self):
self._checkbox = self.find(QCheckBox, f"checkBox")
self._set_checkbox_state()
def setup_plot(self):
self.canvas = MplCanvas(width=5, height=4, dpi=100)
self.canvas.setObjectName("canvas")
self.toolbar = PamhyrPlotToolbar(
self.canvas, self
)
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
self.plot_layout.addWidget(self.toolbar)
self.plot_layout.addWidget(self.canvas)
self.plot_ac = PlotAC(
canvas=self.canvas,
river=self._study.river,
reach=None,
profile=None,
toolbar=self.toolbar
)
self.plot_ac.draw()
def setup_connections(self):
self.find(QAction, "action_add").triggered.connect(self.add)
self.find(QAction, "action_delete").triggered.connect(self.delete)
self._checkbox.stateChanged.connect(self._set_basic_structure_state)
table = self.find(QTableView, "tableView")
table.selectionModel()\
.selectionChanged\
.connect(self.update)
def index_selected(self):
table = self.find(QTableView, "tableView")
r = table.selectionModel()\
.selectedRows()
if len(r)>0:
return r[0]
else:
return None
def index_selected_row(self):
table = self.find(QTableView, "tableView")
r = table.selectionModel()\
.selectedRows()
if len(r)>0:
return r[0].row()
else:
return None
def index_selected_rows(self):
table = self.find(QTableView, "tableView")
return list(
# Delete duplicate
set(
map(
lambda i: i.row(),
table.selectedIndexes()
)
)
)
def add(self):
rows = self.index_selected_rows()
if len(self._hs) == 0 or len(rows) == 0:
self._table.add(0)
else:
self._table.add(rows[0])
def delete(self):
rows = self.index_selected_rows()
if len(rows) == 0:
return
self._table.delete(rows)
def _copy(self):
logger.info("TODO: copy")
def _paste(self):
logger.info("TODO: paste")
def _undo(self):
self._table.undo()
def _redo(self):
self._table.redo()
def _set_checkbox_state(self):
row = self.index_selected_row()
if row is None:
self._checkbox.setEnabled(False)
self._checkbox.setChecked(True)
else:
self._checkbox.setEnabled(True)
self._checkbox.setChecked(self._hs.basic_structure(row).enabled)
def _set_basic_structure_state(self):
row = self.index_selected_row()
if row is None:
self._checkbox.setEnabled(False)
else:
self._hs.basic_structure(row).enabled = self._checkbox.isChecked()
def update(self):
self._set_checkbox_state()
self._update_clear_plot()
def _update_clear_plot(self):
rows = self.index_selected_rows()
+1 -1
View File
@@ -126,5 +126,5 @@ class PlotAC(PamhyrPlot):
def clear(self):
if self.line_kp is not None:
self.line_kp.set_data([],[])
self.line_kp.set_data([], [])
self.canvas.figure.canvas.draw_idle()
+3 -5
View File
@@ -110,7 +110,6 @@ class PlotKPC(PamhyrPlot):
color='red', lw=1.
)
self.canvas.figure.tight_layout()
self.canvas.figure.canvas.draw_idle()
if self.toolbar is not None:
@@ -144,16 +143,15 @@ class PlotKPC(PamhyrPlot):
def clear(self):
if self.profile is not None:
self.profile.set_data([],[])
self.profile.set_data([], [])
if self.line_kp_zmin_zmax is not None:
self.line_kp_zmin_zmax.remove()
self.line_kp_zmin_zmax = None
if self.line_kp_zmin is not None:
self.line_kp_zmin.set_data([],[])
self.line_kp_zmin.set_data([], [])
self.canvas.figure.canvas.draw_idle()
def clear_profile(self):
if self.profile is not None:
self.profile.set_data([],[])
self.profile.set_data([], [])
self.canvas.figure.canvas.draw_idle()
+10 -1
View File
@@ -59,7 +59,9 @@ class ComboBoxDelegate(QItemDelegate):
val = []
if self._mode == "kp":
reach = self._data.hydraulic_structures.get(index.row()).input_reach
reach = self._data.hydraulic_structures\
.get(index.row())\
.input_reach
if reach is not None:
val = list(
map(
@@ -138,6 +140,7 @@ class TableModel(PamhyrTableModel):
row = index.row()
column = index.column()
na = _translate("Hydraulic structure", "Not associated")
try:
if self._headers[column] == "name":
@@ -147,12 +150,18 @@ class TableModel(PamhyrTableModel):
)
)
elif self._headers[column] == "reach":
if value == na:
value = None
self._undo.push(
SetReachCommand(
self._lst, row, self._data.edge(value)
)
)
elif self._headers[column] == "kp":
if value == na:
value = None
self._undo.push(
SetKpCommand(
self._lst, row, value
@@ -99,6 +99,7 @@ class SetEnabledCommand(QUndoCommand):
logger.info(f"Undo {self._old} -> {self._new}")
self._h_s_lst.get(self._index).enabled = self._new
class AddCommand(QUndoCommand):
def __init__(self, h_s_lst, index):
QUndoCommand.__init__(self)
+36 -29
View File
@@ -84,13 +84,13 @@ class HydraulicStructuresWindow(PamhyrWindow):
trad=self._trad,
data=self._study.river,
parent=self,
mode = "reaches"
mode="reaches"
)
self._delegate_kp = ComboBoxDelegate(
trad=self._trad,
data=self._study.river,
parent=self,
mode = "kp"
mode="kp"
)
table = self.find(QTableView, f"tableView")
@@ -177,7 +177,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
table = self.find(QTableView, "tableView")
r = table.selectionModel().selectedRows()
if len(r)>0:
if len(r) > 0:
return r[0]
else:
return None
@@ -186,7 +186,7 @@ class HydraulicStructuresWindow(PamhyrWindow):
table = self.find(QTableView, "tableView")
r = table.selectionModel().selectedRows()
if len(r)>0:
if len(r) > 0:
return r[0].row()
else:
return None
@@ -233,7 +233,8 @@ class HydraulicStructuresWindow(PamhyrWindow):
rows = self.index_selected_rows()
for row in rows:
data = self._hs_lst.get(row)
print(row)
print(data)
if self.sub_window_exists(
BasicHydraulicStructuresWindow,
data=[self._study, None, data]
@@ -266,37 +267,43 @@ class HydraulicStructuresWindow(PamhyrWindow):
def update(self):
self._set_checkbox_state()
self._update_clear_plot()
def _update_clear_plot(self):
rows = self.index_selected_rows()
if len(rows) > 0 and len(self._hs_lst) > 0:
reach = self._hs_lst.get(rows[0]).input_reach
else:
reach=None
self.plot_kpc.clear()
self.plot_ac.clear()
if len(rows) == 0 or len(self._hs_lst) == 0:
self._update_clear_all()
return
profile_kp = self._hs_lst.get(rows[0]).input_kp
if profile_kp is None or profile_kp == "Not associated":
profile = None
self.plot_ac.clear()
self.plot_kpc.clear_profile()
else:
profile = reach.reach.get_profiles_from_kp(float(profile_kp))
if reach is not None and reach != "Not associated":
reach = self._hs_lst.get(rows[0]).input_reach
if reach is not None:
self.plot_kpc.set_reach(reach)
self.plot_ac.set_reach(reach)
else:
self.plot_kpc.clear()
self.plot_ac.clear()
return
profile_kp = self._hs_lst.get(rows[0]).input_kp
if profile_kp is not None:
profiles = reach.reach\
.get_profiles_from_kp(
float(profile_kp)
)
if profile is not None:
self.plot_kpc.set_profile(profile[0])
self.plot_ac.set_profile(profile[0])
if profiles is not None:
profile = profiles[0]
self.plot_kpc.set_profile(profile)
self.plot_ac.set_profile(profile)
else:
self._update_clear_profile()
else:
self._update_clear_profile()
else:
self.plot_ac.clear()
self.plot_kpc.clear_profile()
self._update_clear_all()
def _update_clear_all(self):
self.plot_kpc.clear()
self.plot_ac.clear()
def _update_clear_profile(self):
self.plot_ac.clear()
self.plot_kpc.clear_profile()
+1 -1
View File
@@ -101,7 +101,7 @@ class EditLateralContributionWindow(PamhyrWindow):
table_headers=headers,
editable_headers=self._data.header,
delegates={
#"time": self._delegate_time,
# "time": self._delegate_time,
},
data=self._data,
undo=self._undo_stack,
+11 -5
View File
@@ -195,7 +195,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_edit_geometry": self.open_geometry,
"action_menu_boundary_conditions": self.open_boundary_cond,
"action_menu_edit_reservoirs": self.open_reservoir,
"action_menu_edit_hydraulic_structures": self.open_hydraulic_structures,
"action_menu_edit_hydraulic_structures":
self.open_hydraulic_structures,
"action_menu_initial_conditions": self.open_initial_conditions,
"action_menu_edit_friction": self.open_frictions,
"action_menu_edit_lateral_contribution": self.open_lateral_contrib,
@@ -282,8 +283,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
Nothing
"""
self.update_enable_action()
# Maximise window
#self.showMaximized()
# self.showMaximized()
def set_debug_lvl(self, debug=True):
if debug:
@@ -638,7 +638,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
):
return
hydraulic_structures = HydraulicStructuresWindow(study=self._study, parent=self)
hydraulic_structures = HydraulicStructuresWindow(
study=self._study,
parent=self
)
hydraulic_structures.show()
def open_lateral_contrib(self):
@@ -648,7 +651,10 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
):
return
lateral = LateralContributionWindow(study=self._study, parent=self)
lateral = LateralContributionWindow(
study=self._study,
parent=self
)
lateral.show()
def open_stricklers(self):
+1 -1
View File
@@ -69,7 +69,7 @@ class Plot(PamhyrPlot):
)
# Plot label
#header = self.data.header
# header = self.data.header
self.canvas.axes.set_xlabel(
self._table_headers["z"], color='black', fontsize=10
)
+2 -7
View File
@@ -88,18 +88,13 @@ class EditReservoirWindow(PamhyrWindow):
def setup_table(self):
headers = {}
table_headers = self._trad.get_dict("table_headers")
#for h in self._data.header:
#headers[h] = table_headers[h]
table = self.find(QTableView, "tableView")
self._table = TableModel(
table_view=table,
table_headers=table_headers,
editable_headers=table_headers,
#editable_headers=self._data.header,
delegates={
#"time": self._delegate_time,
},
delegates={},
data=self._data,
undo=self._undo_stack,
opt_data=self._study.time_system
@@ -181,7 +176,7 @@ class EditReservoirWindow(PamhyrWindow):
rows = self.index_selected_rows()
table = []
#table.append(self._data.header)
# table.append(self._data.header)
table.append(self._trad.get_dict("table_headers"))
data = self._data.data
+2 -2
View File
@@ -175,12 +175,12 @@ class PlotH(PamhyrPlot):
def set_timestamp(self, timestamp):
self._current_timestamp = timestamp
#self.update()
# self.update()
def update(self):
reach = self.results.river.reach(self._current_reach_id)
profile = reach.profile(self._current_profile_id)
x = self.ts
y = profile.get_key("Q")
self._line.set_data(x,y)
self._line.set_data(x, y)
self.canvas.figure.canvas.draw_idle()
+16 -4
View File
@@ -105,8 +105,14 @@ class PlotKPC(PamhyrPlot):
)
self.profile, = self.canvas.axes.plot(
[kp[self._current_profile_id], kp[self._current_profile_id]],
[z_max[self._current_profile_id],z_min[self._current_profile_id]],
[
kp[self._current_profile_id],
kp[self._current_profile_id]
],
[
z_max[self._current_profile_id],
z_min[self._current_profile_id]
],
color='red', lw=1.
)
@@ -137,7 +143,13 @@ class PlotKPC(PamhyrPlot):
z_min = reach.geometry.get_z_min()
z_max = reach.geometry.get_z_max()
self.profile.set_data(
[kp[self._current_profile_id], kp[self._current_profile_id]],
[z_max[self._current_profile_id],z_min[self._current_profile_id]]
[
kp[self._current_profile_id],
kp[self._current_profile_id]
],
[
z_max[self._current_profile_id],
z_min[self._current_profile_id]
]
)
self.canvas.figure.canvas.draw_idle()
+14 -10
View File
@@ -136,10 +136,14 @@ class PlotXY(PamhyrPlot):
poly_x = [0]
poly_y = [0]
self.fill = self.canvas.axes.fill(poly_x, poly_y, color='skyblue', alpha=0.7)
self.fill = self.canvas.axes.fill(
poly_x, poly_y,
color='skyblue',
alpha=0.7
)
#self.canvas.axes.autoscale_view(True, True, True)
#self.canvas.axes.autoscale()
# self.canvas.axes.autoscale_view(True, True, True)
# self.canvas.axes.autoscale()
self.canvas.figure.tight_layout()
self.canvas.figure.canvas.draw_idle()
if self.toolbar is not None:
@@ -166,7 +170,7 @@ class PlotXY(PamhyrPlot):
# Current profile
profile = reach.profile(self._current_profile_id).geometry
self.plot_selected.set_data(profile.x(),profile.y())
self.plot_selected.set_data(profile.x(), profile.y())
self.plot_selected.set_visible(True)
self.canvas.draw_idle()
@@ -196,12 +200,12 @@ class PlotXY(PamhyrPlot):
poly_r_x.append(ptY.x)
poly_r_y.append(ptY.y)
#self.canvas.axes.plot(
#x, y, lw=1.,
#color='b',
#markersize=1,
#marker='o'
#)
# self.canvas.axes.plot(
# x, y, lw=1.,
# color='b',
# markersize=1,
# marker='o'
# )
poly_x = poly_l_x + list(reversed(poly_r_x))
poly_y = poly_l_y + list(reversed(poly_r_y))
+6 -2
View File
@@ -125,9 +125,13 @@ class ResultsWindow(PamhyrWindow):
self._slider_time.setValue(len(self._timestamps) - 1)
self._icon_start = QIcon()
self._icon_start.addPixmap(QPixmap('./src/View/ui/ressources/media-playback-start.png'))
self._icon_start.addPixmap(
QPixmap('./src/View/ui/ressources/media-playback-start.png')
)
self._icon_pause = QIcon()
self._icon_pause.addPixmap(QPixmap('./src/View/ui/ressources/media-playback-pause.png'))
self._icon_pause.addPixmap(
QPixmap('./src/View/ui/ressources/media-playback-pause.png')
)
self._button_play = self.find(QPushButton, f"playButton")
self._button_play.setIcon(self._icon_start)
self._button_back = self.find(QPushButton, f"backButton")