diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py index 26cdefc920dd9f81877c561d792eda2595d7f655..36fca25f6302e63a11f75c083f9d9b29ed0c5482 100644 --- a/src/Model/Geometry/Reach.py +++ b/src/Model/Geometry/Reach.py @@ -106,6 +106,9 @@ class Reach(SQLSubModel): return self._parent.name + def __len__(self): + return len(self._profiles) + @property def profiles(self): return self._profiles.copy() diff --git a/src/View/Geometry/PlotAC.py b/src/View/Geometry/PlotAC.py index e43f39e962d0170c2f029840388f2b941af77f4e..974706aa20419210ddf59089ad71b39343ba3ec6 100644 --- a/src/View/Geometry/PlotAC.py +++ b/src/View/Geometry/PlotAC.py @@ -19,7 +19,7 @@ import logging from tools import timer -from View.Plot.APlot import APlot +from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtCore import ( QCoreApplication @@ -29,12 +29,15 @@ _translate = QCoreApplication.translate logger = logging.getLogger() -class PlotAC(APlot): - def __init__(self, canvas=None, data=None, toolbar=None, plot_xy=None): +class PlotAC(PamhyrPlot): + def __init__(self, canvas=None, trad=None, data=None, toolbar=None, + plot_xy=None, parent=None): super(PlotAC, self).__init__( - canvas=canvas, - data=data, - toolbar=toolbar + canvas = canvas, + trad = trad, + data = data, + toolbar = toolbar, + parent = parent ) self.plot_xy = plot_xy diff --git a/src/View/Geometry/PlotKPZ.py b/src/View/Geometry/PlotKPZ.py index eb7d5e28b8660bf62ef11874522ad3c646290784..f216443c411dcbb8196d169b7776b0b3db07251a 100644 --- a/src/View/Geometry/PlotKPZ.py +++ b/src/View/Geometry/PlotKPZ.py @@ -19,7 +19,7 @@ import logging from tools import timer -from View.Plot.APlot import APlot +from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtCore import ( QCoreApplication @@ -29,13 +29,15 @@ _translate = QCoreApplication.translate logger = logging.getLogger() -class PlotKPZ(APlot): - def __init__(self, canvas=None, data=None, toolbar=None, - display_current=True): +class PlotKPZ(PamhyrPlot): + def __init__(self, canvas=None, trad=None, data=None, toolbar=None, + display_current=True, parent=None): super(PlotKPZ, self).__init__( - canvas=canvas, - data=data, - toolbar=toolbar + canvas = canvas, + trad = trad, + data = data, + toolbar = toolbar, + parent = parent ) self.display_current = display_current diff --git a/src/View/Geometry/PlotXY.py b/src/View/Geometry/PlotXY.py index 54e056a910050ab661e472685ce1fd7eb107de4b..ce93fa24ba52f68ede41a70fc61c9dd367a5e29d 100644 --- a/src/View/Geometry/PlotXY.py +++ b/src/View/Geometry/PlotXY.py @@ -17,7 +17,7 @@ # -*- coding: utf-8 -*- from tools import timer, trace -from View.Plot.APlot import APlot +from View.Tools.PamhyrPlot import PamhyrPlot from PyQt5.QtCore import ( QCoreApplication @@ -25,12 +25,15 @@ from PyQt5.QtCore import ( _translate = QCoreApplication.translate -class PlotXY(APlot): - def __init__(self, canvas=None, data=None, toolbar=None, display_current=True): +class PlotXY(PamhyrPlot): + def __init__(self, canvas=None, trad=None, data=None, toolbar=None, + display_current=True, parent=None): super(PlotXY, self).__init__( - canvas=canvas, - data=data, - toolbar=toolbar + canvas = canvas, + trad = trad, + data = data, + toolbar = toolbar, + parent = parent ) self.display_current = display_current @@ -60,11 +63,11 @@ class PlotXY(APlot): # Axes self.canvas.axes.set_xlabel( - _translate("MainWindow_reach", "X (m)"), + _translate("Geometry", "X (m)"), color='green', fontsize=12 ) self.canvas.axes.set_ylabel( - _translate("MainWindow_reach", "Y (m)"), + _translate("Geometry", "Y (m)"), color='green', fontsize=12 ) self.canvas.axes.axis("equal") diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py index 1b055209d9fb4feeadd26d6ab40ea381f7acf24c..0ff5e0c871a6edda6104beb9c4681181b168d482 100644 --- a/src/View/Geometry/Table.py +++ b/src/View/Geometry/Table.py @@ -35,6 +35,8 @@ from PyQt5.QtWidgets import ( QComboBox, ) +from View.Tools.PamhyrTable import PamhyrTableModel + from Model.Geometry import Reach from Model.Geometry.ProfileXYZ import ProfileXYZ from View.Geometry.UndoCommand import * @@ -44,53 +46,26 @@ logger = logging.getLogger() _translate = QCoreApplication.translate -class TableEditableModel(QAbstractTableModel): - def __init__(self, reach, headers=None, undo=None): - QAbstractTableModel.__init__(self) - data_list = [] - - self._undo_stack = undo - self._reach = reach - - # Hack for qtlinguist - _ = _translate("Geometry", "Name") - _ = _translate("Geometry", "Kp (m)") - _ = _translate("Geometry", "Type") - - if headers is None: - self.headers = [ - "Name", - "Kp (m)", - "Type" - ] - else: - self.headers = headers - - def rowCount(self, parent=QModelIndex()): - return self._reach.number_profiles - - def columnCount(self, parent=QModelIndex()): - return len(self.headers) - +class TableEditableModel(PamhyrTableModel): def data(self, index, role=Qt.DisplayRole): if not index.isValid(): return QVariant() if role == Qt.DisplayRole and index.column() == 0: - return self._reach.profile(index.row()).name + return self._data.profile(index.row()).name if role == Qt.DisplayRole and index.column() == 1: - kp = self._reach.profile(index.row()).kp + kp = self._data.profile(index.row()).kp return f"{kp:.4f}" if role == Qt.DisplayRole and index.column() == 2: - return self._reach.profile(index.row()).profile_type + return self._data.profile(index.row()).profile_type if role == Qt.TextAlignmentRole: return Qt.AlignHCenter | Qt.AlignVCenter if role == Qt.ForegroundRole and index.column() == 0: - name = self._reach.profile(index.row()).name\ + name = self._data.profile(index.row()).name\ .strip()\ .lower() if (name == "upstream" or name == "up" or @@ -102,16 +77,6 @@ class TableEditableModel(QAbstractTableModel): return QVariant() - def headerData(self, section, orientation, role=Qt.DisplayRole): - if role == Qt.DisplayRole: - if orientation == Qt.Horizontal: - if section < len(self.headers): - return _translate("Geometry", self.headers[section]) - else: - return str(section + 1) - - return QVariant() - def setData(self, index, value, role=Qt.EditRole): row = index.row() column = index.column() @@ -119,19 +84,19 @@ class TableEditableModel(QAbstractTableModel): if role == Qt.EditRole and index.column() != 2: try: if index.column() == 0: - self._undo_stack.push( + self._undo.push( SetNameCommand( - self._reach, index.row(), - self._reach.profile(index.row()).name, + self._data, index.row(), + self._data.profile(index.row()).name, value ) ) if index.column() == 1: - self._undo_stack.push( + self._undo.push( SetKPCommand( - self._reach, index.row(), - self._reach.profile(index.row()).kp, + self._data, index.row(), + self._data.profile(index.row()).kp, value ) ) @@ -149,27 +114,13 @@ class TableEditableModel(QAbstractTableModel): return False - def index(self, row, column, parent=QModelIndex()): - if not self.hasIndex(row, column, parent): - return QModelIndex() - - return self.createIndex(row, column, QModelIndex()) - - def flags(self, index): - flg = Qt.ItemIsEnabled | Qt.ItemIsSelectable - - if index.column() == 2: - return flg - else: - return Qt.ItemIsEditable | flg - # @QtCore.pyqtSlot() def insert_row(self, row, parent=QModelIndex()): self.beginInsertRows(parent, row, row - 1) - self._undo_stack.push( + self._undo.push( AddCommand( - self._reach, row + self._data, row ) ) @@ -179,9 +130,9 @@ class TableEditableModel(QAbstractTableModel): def remove_rows(self, rows, parent=QModelIndex()): self.beginRemoveRows(parent, rows[0], rows[-1]) - self._undo_stack.push( + self._undo.push( DelCommand( - self._reach, rows + self._data, rows ) ) @@ -191,9 +142,9 @@ class TableEditableModel(QAbstractTableModel): def sort_profiles(self, _reverse): self.layoutAboutToBeChanged.emit() - self._undo_stack.push( + self._undo.push( SortCommand( - self._reach, _reverse + self._data, _reverse ) ) @@ -209,9 +160,9 @@ class TableEditableModel(QAbstractTableModel): self.beginMoveRows(parent, row - 1, row - 1, parent, target) - self._undo_stack.push( + self._undo.push( MoveCommand( - self._reach, "up", row + self._data, "up", row ) ) @@ -219,16 +170,16 @@ class TableEditableModel(QAbstractTableModel): self.layoutChanged.emit() def move_row_down(self, row, parent=QModelIndex()): - if row > self._reach.number_profiles: + if row > self._data.number_profiles: return target = row self.beginMoveRows(parent, row + 1, row + 1, parent, target) - self._undo_stack.push( + self._undo.push( MoveCommand( - self._reach, "down", row + self._data, "down", row ) ) @@ -238,9 +189,9 @@ class TableEditableModel(QAbstractTableModel): def duplicate(self, rows, profiles): self.layoutAboutToBeChanged.emit() - self._undo_stack.push( + self._undo.push( DuplicateCommand( - self._reach, rows, + self._data, rows, profiles ) ) @@ -250,7 +201,7 @@ class TableEditableModel(QAbstractTableModel): def paste(self, row, header, data): - if row > self._reach.number_profiles: + if row > self._data.number_profiles: return if len(data) == 0: @@ -258,9 +209,9 @@ class TableEditableModel(QAbstractTableModel): self.layoutAboutToBeChanged.emit() - self._undo_stack.push( + self._undo.push( PasteCommand( - self._reach, row, + self._data, row, list( map( lambda d: ProfileXYZ.from_data(header, d), @@ -273,16 +224,7 @@ class TableEditableModel(QAbstractTableModel): self.layoutAboutToBeChanged.emit() self.layoutChanged.emit() - - def undo(self): - self._undo_stack.undo() - self.layoutChanged.emit() - - def redo(self): - self._undo_stack.redo() - self.layoutChanged.emit() - - +# TODO: Delete useless delegate class Delegate(QStyledItemDelegate): def __init__(self, parent=None, setModelDataEvent=None): super(Delegate, self).__init__(parent) diff --git a/src/View/Geometry/Translate.py b/src/View/Geometry/Translate.py new file mode 100644 index 0000000000000000000000000000000000000000..c583732db9d1b8b0ac4ccc408215a8e64eac567d --- /dev/null +++ b/src/View/Geometry/Translate.py @@ -0,0 +1,45 @@ +# Translate.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# -*- coding: utf-8 -*- + +from PyQt5.QtCore import QCoreApplication + +from View.Tools.PamhyrTranslate import PamhyrTranslate + +_translate = QCoreApplication.translate + +class GeometryTranslate(PamhyrTranslate): + def __init__(self): + super(GeometryTranslate, self).__init__() + + self._dict["open_file"] = _translate("Geometry", "Open a file") + self._dict["file_st"] = _translate("Geometry", "File mage geometry (*.ST)") + self._dict["file_m"] = _translate("Geometry", "File mage meshed geometry (*.M)") + self._dict["file_all"] = _translate("Geometry", "All file (*)") + + self._dict["reach"] = _translate("Geometry", "reach") + self._dict["reachs"] = _translate("Geometry", "reachs") + + self._dict["cross_section"] = _translate("Geometry", "cross-section") + self._dict["cross_sections"] = _translate("Geometry", "cross-sections") + self._dict["profile"] = _translate("Geometry", "cross-section") + self._dict["profiles"] = _translate("Geometry", "cross-sections") + + self._sub_dict["table_headers"] = { + "name": _translate("Geometry", "Name"), + "kp": _translate("Geometry", "KP"), + } diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index a66ed7812225cd52e8b7514814d0d80bb84602a8..1b334bb724f024ec5fef0e3f979cdc08a15b2ca1 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -34,118 +34,168 @@ from PyQt5.QtCore import ( ) from PyQt5.QtWidgets import ( QApplication, QMainWindow, QFileDialog, QCheckBox, - QUndoStack, QShortcut, + QUndoStack, QShortcut, QTableView, QHeaderView, + QAction, QSlider, QPushButton, QVBoxLayout, + QLabel, ) from View.Geometry.PlotXY import PlotXY from View.Geometry.PlotKPZ import PlotKPZ from View.Geometry.PlotAC import PlotAC -from View.Tools.ASubWindow import ASubMainWindow, WindowToolKit -from View.Tools.ListedSubWindow import ListedSubWindow +from View.Tools.PamhyrWindow import PamhyrWindow +from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar +from View.Tools.Plot.PamhyrCanvas import MplCanvas -from View.Geometry.mainwindow_ui_reach import Ui_MainWindow from View.Geometry.Table import * -from View.Geometry.Profile.Window import ProfileWindow +from View.Geometry.Translate import GeometryTranslate +# from View.Geometry.Profile.Window import ProfileWindow _translate = QCoreApplication.translate -class GeometryWindow(ASubMainWindow, ListedSubWindow): - def __init__(self, model=None, title="Geometry", parent=None): - self._title = title - self.parent = parent - super(GeometryWindow, self).__init__( - name=self._title, - parent=parent - ) +class GeometryWindow(PamhyrWindow): + _pamhyr_ui = "GeometryReach" + _pamhyr_name = "Geometry" - self._model = model - self._reach = model.river.current_reach().reach + def __init__(self, reach=None, study=None, config=None, parent=None): + if reach is None: + self._reach = study.river.current_reach().reach + else: + self._reach = reach - self.ui = Ui_MainWindow() - self.ui.setupUi(self) + name = f"{self._pamhyr_name} - {self._reach.name}" - self.tableView = self.ui.tableView - self.tableView_header = self.ui.tableView_header + super(GeometryWindow, self).__init__( + title = name, + study = study, + config = config, + trad = GeometryTranslate(), + parent = parent + ) self._tablemodel = None self._profile_window = [] - self._clipboard = None - self.setup_window() - self.setup_sc() - self.setup_model() + self.setup_table() self.setup_plots() + self.setup_statusbar() self.setup_connections() self.changed_slider_value() - def setup_window(self): - self._title = f"{self.ui.mainwindow_title} - {self._reach.name}" - self.setWindowTitle(self._title) - - def setup_sc(self): - self._undo_stack = QUndoStack() + def setup_table(self): + table_headers = self._trad.get_dict("table_headers") - self.undo_sc = QShortcut(QKeySequence.Undo, self) - self.redo_sc = QShortcut(QKeySequence.Redo, self) - self.copy_sc = QShortcut(QKeySequence.Copy, self) - self.paste_sc = QShortcut(QKeySequence.Paste, self) - - def setup_model(self): + table = self.find(QTableView, "tableView") self._tablemodel = TableEditableModel( - headers = self.ui.tableView_header, - reach = self._reach, + table_view = table, + table_headers = table_headers, + editable_headers = ["name", "kp"], + data = self._reach, undo = self._undo_stack ) - self.tableView.setModel(self._tablemodel) - self.tableView.setItemDelegate(Delegate()) + table.setModel(self._tablemodel) + table.setSelectionBehavior(QAbstractItemView.SelectRows) + table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + table.setAlternatingRowColors(True) def setup_plots(self): + self._canvas_xy = MplCanvas(width=3, height=4, dpi=100) + self._canvas_xy.setObjectName("canvas_xy") + self._toolbar_xy = PamhyrPlotToolbar( + self._canvas_xy, self, + items = ["home", "zoom", "save", "iso", "back/forward", "move"] + ) + self._plot_layout_xy = self.find(QVBoxLayout, "verticalLayout") + self._plot_layout_xy.addWidget(self._toolbar_xy) + self._plot_layout_xy.addWidget(self._canvas_xy) self.plot_xy() + + self._canvas_kpc = MplCanvas(width=6, height=4, dpi=100) + self._canvas_kpc.setObjectName("canvas_kpc") + self._toolbar_kpc = PamhyrPlotToolbar( + self._canvas_kpc, self, + items = ["home", "zoom", "save", "iso", "back/forward", "move"] + ) + self._plot_layout_kpc = self.find(QVBoxLayout, "verticalLayout_2") + self._plot_layout_kpc.addWidget(self._toolbar_kpc) + self._plot_layout_kpc.addWidget(self._canvas_kpc) self.plot_kpc() + + self._canvas_ac = MplCanvas(width=9, height=4, dpi=100) + self._canvas_ac.setObjectName("canvas_ac") + self._toolbar_ac = PamhyrPlotToolbar( + self._canvas_ac, self, + items = ["home", "zoom", "save", "iso", "back/forward", "move"] + ) + self._plot_layout_ac = self.find(QVBoxLayout, "verticalLayout_3") + self._plot_layout_ac.addWidget(self._toolbar_ac) + self._plot_layout_ac.addWidget(self._canvas_ac) self.plot_ac() + def _compute_status_label(self): + row = self.index_selected_row() + profile = self._reach.profile(row) + + name = profile.name + " " + str(profile.kp) + + return ( + f"<font color=\"Grey\">{self._trad['reach']}: {self._reach.name}" + " - " + f"{self._trad['cross_section']}:</font> {name}" + ) + + def setup_statusbar(self): + txt = "" + self._status_label = QLabel(txt) + self.statusbar.addPermanentWidget(self._status_label) + + def update_statusbar(self): + txt = self._compute_status_label() + self._status_label.setText(txt) + def setup_connections(self): - self.ui.btn_open.triggered.connect(self.open_file_dialog) - self.ui.btn_sort_asc.triggered.connect(self.sort_ascending) - self.ui.btn_sort_desc.triggered.connect(self.sort_descending) - self.ui.btn_move_up.triggered.connect(self.move_row_up) - self.ui.btn_move_down.triggered.connect(self.move_row_down) - # self.ui.btn_end_editing.triggered.connect(self.handleSave) - self.ui.btn_add.triggered.connect(self.insert_row) - self.ui.btn_delete.triggered.connect(self.delete_rows) - self.ui.btn_edit.triggered.connect(self.edit_profile) - self.ui.verticalSlider.valueChanged.connect(self.changed_slider_value) - - self.ui.btn_slider_up.clicked.connect(self.decrement_value_slider) - self.ui.btn_slider_down.clicked.connect(self.increment_value_slider) - self.ui.btn_move_up.triggered.connect(self.changed_profile_slot) - - self.undo_sc.activated.connect(self.undo) - self.redo_sc.activated.connect(self.redo) - self.copy_sc.activated.connect(self.copy) - self.paste_sc.activated.connect(self.paste) + actions = { + "action_import": self.import_from_file, + # "action_export": self.export_to_file, + "action_sort_asc": self.sort_ascending, + "action_sort_des": self.sort_descending, + "action_up": self.move_up, + "action_down": self.move_down, + "action_add": self.add, + "action_delete": self.delete, + "action_edit": self.edit_profile, + } + + for action in actions: + self.find(QAction, action)\ + .triggered.connect(actions[action]) + + self.find(QSlider, "verticalSlider").valueChanged.connect(self.changed_slider_value) + self.find(QPushButton, "pushButton_up").clicked.connect(self.decrement_value_slider) + self.find(QPushButton, "pushButton_down").clicked.connect(self.increment_value_slider) # Profile selection when line change in table - self.tableView.selectionModel()\ - .selectionChanged\ - .connect(self.select_current_profile) + self.find(QTableView, "tableView").selectionModel()\ + .selectionChanged\ + .connect(self.select_current_profile) - def open_file_dialog(self): + + def import_from_file(self): options = QFileDialog.Options() settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', ) options |= QFileDialog.DontUseNativeDialog + file_types = [ + self._trad["file_st"], + self._trad["file_m"], + self._trad["file_all"], + ] + filename, _ = QtWidgets.QFileDialog.getOpenFileName( self, - _translate("MainWindow_reach", "Ouvrir un fichier"), + self._trad["open_file"], "", - _translate("MainWindow_reach", "Fichiers .ST (*.ST)") + - ";; " + - _translate("MainWindow_reach", "Fichiers .M (*.M)") + - ";; " + - _translate("MainWindow_reach", "Tous les fichiers (*)"), + ";; ".join(file_types), options=options ) @@ -159,20 +209,6 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.plot_kpc() self.plot_ac() - def messagebox_profile_editing(self): - msg_box = QtWidgets.QMessageBox() - msg_box.setIcon(QtWidgets.QMessageBox.Information) - msg_box.setWindowTitle(_translate("MainWindow_reach", - "Édition des profils sélectionnés")) - msg_box.setText(_translate("MainWindow_reach", - "Vous avez sélectionné plus de 5 profils." - " \nSeuls les 5 premiers seront édités.")) - msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok) - - return_value = msg_box.exec() - # if return_value == QtWidgets.QMessageBox.Ok: - # print('OK clicked') - def edit_profile(self): self.tableView.model().blockSignals(True) @@ -215,9 +251,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.tableView.model().blockSignals(True) self._plot_xy = PlotXY( - canvas = self.ui.canvas_1, + canvas = self._canvas_xy, data = self._reach, - toolbar = self.ui.toolbar_1 + toolbar = self._toolbar_xy ) self._plot_xy.draw() @@ -232,9 +268,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.tableView.model().blockSignals(True) self._plot_kpc = PlotKPZ( - canvas = self.ui.canvas_2, + canvas = self._canvas_kpc, data = self._reach, - toolbar = self.ui.toolbar_2 + toolbar = self._toolbar_kpc ) self._plot_kpc.draw() @@ -249,9 +285,9 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.tableView.model().blockSignals(True) self._plot_ac = PlotAC( - canvas = self.ui.canvas_3, + canvas = self._canvas_ac, data = self._reach, - toolbar = self.ui.toolbar_3, + toolbar = self._toolbar_ac, plot_xy = self._plot_xy ) self._plot_ac.draw() @@ -304,7 +340,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): if len(self.tableView.selectedIndexes()) > 0: row = self.index_selected_row() - self.ui.verticalSlider.setValue(row) + self.find(QSlider, "verticalSlider").setValue(row) self.select_plot_xy(row) self.select_plot_kpc(row) self.select_plot_ac(row) @@ -315,41 +351,37 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.tableView.model().blockSignals(True) if self._tablemodel.rowCount() != 0: - self.ui.verticalSlider.setMaximum(self._tablemodel.rowCount() - 1) + slider = self.find(QSlider, "verticalSlider") + slider.setMaximum(self._tablemodel.rowCount() - 1) - slider_value = self.ui.verticalSlider.value() + slider_value = slider.value() kp = self._reach.profile(slider_value).kp - self.ui.vertical_slider_label.setText( - _translate("MainWindow_reach", "Kp : ") + - f"{kp}" + "\n" + - _translate("MainWindow_reach", - "Profil N° : ") + - f"{slider_value + 1}" - ) - self.select_plot_xy(slider_value) self.select_plot_kpc(slider_value) self.select_row_profile_slider(slider_value) + self.update_statusbar() self.tableView.model().blockSignals(False) def increment_value_slider(self): - if 0 <= self.ui.verticalSlider.value() < self._tablemodel.rowCount() - 1: - self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1) + slider = self.find(QSlider, "verticalSlider") + if 0 <= slider.value() < self._tablemodel.rowCount() - 1: + slider.setValue(slider.value() + 1) def decrement_value_slider(self): - if 0 < self.ui.verticalSlider.value() < self._tablemodel.rowCount(): - self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1) + slider = self.find(QSlider, "verticalSlider") + if 0 < slider.value() < self._tablemodel.rowCount(): + slider.setValue(slider.value() - 1) - def insert_row(self): + def add(self): if len(self.tableView.selectedIndexes()) == 0: - self._tablemodel.insert_row(self._tablemodel.rowCount()) + self._tablemodel.add(self._tablemodel.rowCount()) else: row = self.index_selected_row() - self._tablemodel.insert_row(row + 1) + self._tablemodel.add(row + 1) - def delete_rows(self): + def delete(self): rows = sorted( list( set( @@ -384,14 +416,14 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.select_current_profile() self.changed_slider_value() - def move_row_up(self): + def move_up(self): row = self.index_selected_row() - self._tablemodel.move_row_up(row) + self._tablemodel.move_up(row) self.select_current_profile() - def move_row_down(self): + def move_down(self): row = self.index_selected_row() - self._tablemodel.move_row_down(row) + self._tablemodel.move_down(row) self.select_current_profile() def duplicate(self): @@ -412,7 +444,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self._tablemodel.duplicate(rows, profiles) self.select_current_profile() - def copy(self): + def _copy(self): rows = self.tableView\ .selectionModel()\ .selectedRows() @@ -428,7 +460,7 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self.copyTableIntoClipboard(table) - def paste(self): + def _paste(self): header, data = self.parseClipboardTable() if len(data) == 0: @@ -443,19 +475,19 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): self._tablemodel.paste(row, header, data) self.select_current_profile() - def undo(self): + def _undo(self): self._tablemodel.undo() self.select_current_profile() self.update_plot_xy() self.update_plot_kpc() - def redo(self): + def _redo(self): self._tablemodel.redo() self.select_current_profile() self.update_plot_xy() self.update_plot_kpc() - def handleSave(self): + def export_to_file(self): options = QFileDialog.Options() DEFAULT_DIRECTORY = '/home/' settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', ) @@ -464,32 +496,11 @@ class GeometryWindow(ASubMainWindow, ListedSubWindow): filename, filters = QFileDialog.getSaveFileName( self, - filter=_translate("MainWindow_reach", - "Files .ST(*.ST or *.st)") - + ";; " + - _translate("MainWindow_reach", "All files " - "(*)"), - options=options + filter = self._trad["file_st"] + ";; " + self._trad["file_all"], + options = options ) current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY if filename != '': self._tablemodel.export_reach(filename) - - def handleOpen(self): - filename, filterName = QFileDialog.getOpenFileName(self) - - if filename != '': - with open(filename, 'r') as f: - reader = csv.reader(f, delimiter='\t') - header = next(reader) - buf = [] - for row in reader: - row[0] = QCheckBox("-") - buf.append(row) - - self._tablemodel = None - self._tablemodel = TableEditableModel(buf) - self.tableView.setModel(self._tablemodel) - filename = '' diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 58a2a031c0d2e9fbf0ccb6b217c41408635a2950..8162807e377723ad1bafeb207883f18644eb92b1 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -44,7 +44,7 @@ from View.Configure.Window import ConfigureWindow from View.Study.Window import NewStudyWindow from View.About.Window import AboutWindow from View.Network.Window import NetworkWindow -# from View.Geometry.Window import GeometryWindow +from View.Geometry.Window import GeometryWindow # from View.BoundaryCondition.Window import BoundaryConditionWindow # from View.LateralContribution.Window import LateralContributionWindow # from View.InitialConditions.Window import InitialConditionsWindow @@ -534,7 +534,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ) if geometry is None: - geometry = GeometryWindow(model=self._study, parent=self) + geometry = GeometryWindow(study=self._study, config=self.conf, parent=self) geometry.show() else: geometry.activateWindow() diff --git a/src/View/Tools/PamhyrTable.py b/src/View/Tools/PamhyrTable.py index 08e36c8430e5e225b5e43ce70ba78035b57b3957..65cd7687a0ce3eee14824f72748580227985a699 100644 --- a/src/View/Tools/PamhyrTable.py +++ b/src/View/Tools/PamhyrTable.py @@ -115,10 +115,10 @@ class PamhyrTableModel(QAbstractTableModel): return options - def rowCount(self, parent): + def rowCount(self, parent=QModelIndex()): return len(self._lst) - def columnCount(self, parent): + def columnCount(self, parent=QModelIndex()): return len(self._headers) def headerData(self, section, orientation, role): diff --git a/src/View/ui/GeometryCrossSection.ui b/src/View/ui/GeometryCrossSection.ui new file mode 100644 index 0000000000000000000000000000000000000000..b0c12393d47714d27691d2701903f2d6b82374d0 --- /dev/null +++ b/src/View/ui/GeometryCrossSection.ui @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1120</width> + <height>630</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTableView" name="tableView"/> + <widget class="QWidget" name="verticalLayoutWidget"> + <layout class="QVBoxLayout" name="verticalLayout"/> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1120</width> + <height>22</height> + </rect> + </property> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <widget class="QToolBar" name="toolBar"> + <property name="windowTitle"> + <string>toolBar</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="action_add"/> + <addaction name="action_delete"/> + <addaction name="action_sort"/> + <addaction name="action_resort"/> + <addaction name="action_up"/> + <addaction name="action_down"/> + </widget> + <action name="action_add"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset> + </property> + <property name="text"> + <string>add</string> + </property> + <property name="toolTip"> + <string>Add a point on cross-section</string> + </property> + </action> + <action name="action_delete"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset> + </property> + <property name="text"> + <string>delete</string> + </property> + <property name="toolTip"> + <string>Delete selected point(s)</string> + </property> + </action> + <action name="action_up"> + <property name="icon"> + <iconset> + <normaloff>ressources/up.png</normaloff>ressources/up.png</iconset> + </property> + <property name="text"> + <string>up</string> + </property> + <property name="toolTip"> + <string>Move up selected point(s)</string> + </property> + </action> + <action name="action_down"> + <property name="icon"> + <iconset> + <normaloff>ressources/down.png</normaloff>ressources/down.png</iconset> + </property> + <property name="text"> + <string>down</string> + </property> + <property name="toolTip"> + <string>Mode down selected point(s)</string> + </property> + </action> + <action name="action_sort"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-sort-ascending.png</normaloff>ressources/gtk-sort-ascending.png</iconset> + </property> + <property name="text"> + <string>sort</string> + </property> + <property name="toolTip"> + <string>Sort points by nearest neighbor</string> + </property> + </action> + <action name="action_resort"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-sort-descending.png</normaloff>ressources/gtk-sort-descending.png</iconset> + </property> + <property name="text"> + <string>resort</string> + </property> + <property name="toolTip"> + <string>Sort reversed points by nearest neighbor</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui new file mode 100644 index 0000000000000000000000000000000000000000..e09d9d359ac1e163f710498e2a1f2214c1e17ff9 --- /dev/null +++ b/src/View/ui/GeometryReach.ui @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1280</width> + <height>720</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <property name="locale"> + <locale language="English" country="Europe"/> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QSplitter" name="splitter_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTableView" name="tableView"/> + <widget class="QSplitter" name="splitter_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QWidget" name="verticalLayoutWidget"> + <layout class="QVBoxLayout" name="verticalLayout"/> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_2"> + <layout class="QVBoxLayout" name="verticalLayout_2"/> + </widget> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_3"> + <layout class="QVBoxLayout" name="verticalLayout_3"/> + </widget> + </widget> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QSlider" name="verticalSlider"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="invertedAppearance"> + <bool>true</bool> + </property> + <property name="invertedControls"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPushButton" name="pushButton_up"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>ressources/go-up2.png</normaloff>ressources/go-up2.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_down"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>ressources/go-down1.png</normaloff>ressources/go-down1.png</iconset> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1280</width> + <height>22</height> + </rect> + </property> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <widget class="QToolBar" name="toolBar"> + <property name="windowTitle"> + <string>toolBar</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="action_import"/> + <addaction name="action_add"/> + <addaction name="action_delete"/> + <addaction name="action_edit"/> + <addaction name="action_sort_asc"/> + <addaction name="action_sort_des"/> + <addaction name="action_up"/> + <addaction name="action_down"/> + <addaction name="action_export"/> + </widget> + <action name="action_import"> + <property name="text"> + <string>import</string> + </property> + <property name="toolTip"> + <string>Import geometry</string> + </property> + </action> + <action name="action_export"> + <property name="text"> + <string>export</string> + </property> + <property name="toolTip"> + <string>Export geometry</string> + </property> + </action> + <action name="action_add"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset> + </property> + <property name="text"> + <string>add</string> + </property> + <property name="toolTip"> + <string>Add a cross-section</string> + </property> + </action> + <action name="action_delete"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset> + </property> + <property name="text"> + <string>delete</string> + </property> + <property name="toolTip"> + <string>Delete selected cross-section(s)</string> + </property> + </action> + <action name="action_edit"> + <property name="icon"> + <iconset> + <normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset> + </property> + <property name="text"> + <string>edit</string> + </property> + <property name="toolTip"> + <string>Edit selected cross section(s)</string> + </property> + </action> + <action name="action_sort_asc"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-sort-ascending.png</normaloff>ressources/gtk-sort-ascending.png</iconset> + </property> + <property name="text"> + <string>sort_asc</string> + </property> + <property name="toolTip"> + <string>Sort cross-sections by ascending KP</string> + </property> + </action> + <action name="action_sort_des"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-sort-descending.png</normaloff>ressources/gtk-sort-descending.png</iconset> + </property> + <property name="text"> + <string>sort_des</string> + </property> + <property name="toolTip"> + <string>Sort cross-sections by descending KP</string> + </property> + </action> + <action name="action_up"> + <property name="icon"> + <iconset> + <normaloff>ressources/up.png</normaloff>ressources/up.png</iconset> + </property> + <property name="text"> + <string>up</string> + </property> + <property name="toolTip"> + <string>Move up selected cross-section(s)</string> + </property> + </action> + <action name="action_down"> + <property name="icon"> + <iconset> + <normaloff>ressources/down.png</normaloff>ressources/down.png</iconset> + </property> + <property name="text"> + <string>down</string> + </property> + <property name="toolTip"> + <string>Move down selected cross-section(s)</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui>