From c6fd041e0c034a1aa0dbd1c2710d2b7239a47c89 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr> Date: Tue, 25 Apr 2023 13:53:53 +0200 Subject: [PATCH] geometry: Profile: Fix table station display. --- src/Model/Geometry/PointXYZ.py | 8 +-- src/Model/Geometry/ProfileXYZ.py | 11 --- src/View/Geometry/GeometryWindow.py | 8 +-- src/View/Geometry/Profile/ProfileWindow.py | 71 ++++++++++++++++--- .../Geometry/Profile/qtableview_profile.py | 11 +-- 5 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py index e0c29860..7df8123c 100644 --- a/src/Model/Geometry/PointXYZ.py +++ b/src/Model/Geometry/PointXYZ.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from math import dist -from pandas import isna +import numpy as np from Model.Geometry.Point import Point @@ -46,9 +46,9 @@ class PointXYZ(Point): Returns: True if at least one coordinate is as np.nan """ - return (isna(self.x) or - isna(self.y) or - isna(self.z)) + return (np.isnan(self.x) or + np.isnan(self.y) or + np.isnan(self.z)) def dist(self, p2): return PointXYZ.distance(self, p2) diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index fce2bc5c..1118cc00 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -40,17 +40,6 @@ class ProfileXYZ(Profile): data=[[p.x, p.y, p.z, p.name] for p in self._points]) return f"\nProfileXYZ : {self.name}\n{df}" - @property - def header(self): - """ - Returns: - Profile header. - """ - return np.array( - [self._num, self._code1, self._code2, - self.nb_points(), self._kp, self._name] - ) - def x(self): return [point.x for point in self._points] diff --git a/src/View/Geometry/GeometryWindow.py b/src/View/Geometry/GeometryWindow.py index c3325acc..89f3be26 100644 --- a/src/View/Geometry/GeometryWindow.py +++ b/src/View/Geometry/GeometryWindow.py @@ -28,7 +28,7 @@ from View.Geometry.PlotAC import PlotAC from View.ASubWindow import WindowToolKit from View.Geometry.mainwindow_ui_reach import Ui_MainWindow -from View.Geometry import qtableview_reach +from View.Geometry.qtableview_reach import * from View.Geometry.Profile.ProfileWindow import ProfileWindow _translate = QCoreApplication.translate @@ -71,13 +71,13 @@ class GeometryWindow(QMainWindow, WindowToolKit): self.paste_sc = QShortcut(QKeySequence.Paste, self) def setup_model(self): - self._tablemodel = qtableview_reach.PandasModelEditable( + self._tablemodel = PandasModelEditable( headers = self.ui.tableView_header, reach = self._reach, undo = self._undo_stack ) self.tableView.setModel(self._tablemodel) - self.tableView.setItemDelegate(qtableview_reach.Delegate()) + self.tableView.setItemDelegate(Delegate()) def setup_plots(self): if self._reach.number_profiles != 0: @@ -435,6 +435,6 @@ class GeometryWindow(QMainWindow, WindowToolKit): buf.append(row) self._tablemodel = None - self._tablemodel = qtableview_reach.PandasModelEditable(buf) + self._tablemodel = PandasModelEditable(buf) self.tableView.setModel(self._tablemodel) filename = '' diff --git a/src/View/Geometry/Profile/ProfileWindow.py b/src/View/Geometry/Profile/ProfileWindow.py index fb59d7d1..c7f574fa 100644 --- a/src/View/Geometry/Profile/ProfileWindow.py +++ b/src/View/Geometry/Profile/ProfileWindow.py @@ -7,9 +7,16 @@ from time import time from tools import trace, timer -from PyQt5 import QtWidgets, QtGui -from PyQt5.QtCore import QModelIndex, Qt, QEvent, QCoreApplication -from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QCheckBox +from PyQt5.QtGui import ( + QKeySequence, +) +from PyQt5.QtCore import ( + QModelIndex, Qt, QEvent, QCoreApplication +) +from PyQt5.QtWidgets import ( + QApplication, QMainWindow, QFileDialog, QCheckBox, + QUndoStack, QShortcut, +) from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow @@ -34,6 +41,7 @@ class ProfileWindow(QMainWindow): self._model = None self.setup_window() + self.setup_sc() self.setup_model() self.setup_connections() self.plot() @@ -64,6 +72,23 @@ class ProfileWindow(QMainWindow): f"{name} ({self._profile.kp})" ) + def setup_sc(self): + self._undo_stack = QUndoStack() + + 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): + self._model = PandasModelEditable( + profile = self._profile, + undo = self._undo_stack + ) + + self.ui.tableView.setModel(self._model) + self.ui.tableView.setItemDelegate(Delegate()) + def setup_connections(self): self.ui.btn_sort_asc_x.clicked.connect(self.sort_X_ascending) self.ui.btn_sort_desc_x.clicked.connect(self.sort_X_descending) @@ -80,11 +105,10 @@ class ProfileWindow(QMainWindow): # self.ui.btn_go_back.clicked.connect(self.cancel_validate_changes) # self.ui.btn_reset.clicked.connect(self.go_back_to_initial_state) - def setup_model(self): - self._model = PandasModelEditable(self._profile) - - self.ui.tableView.setModel(self._model) - self.ui.tableView.setItemDelegate(Delegate()) + 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) def plot(self): self.ui.tableView.model().blockSignals(True) @@ -169,6 +193,37 @@ class ProfileWindow(QMainWindow): self.update_plot() + def copy(self): + rows = self.tableView\ + .selectionModel()\ + .selectedRows() + + self._clipboard = [] + + for row in rows: + self._clipboard.append( + deepcopy( + self._reach.profile(row.row()) + ) + ) + + def paste(self): + row = self.index_selected_row() + self._tablemodel.paste(row, self._clipboard) + self.select_current_profile() + + def undo(self): + self._tablemodel.undo() + self.select_current_profile() + self.update_plot_xy() + self.update_plot_kpc() + + def redo(self): + self._tablemodel.redo() + self.select_current_profile() + self.update_plot_xy() + self.update_plot_kpc() + def handleSave(self): if self.fileName is None or self.fileName == '': self.fileName, self.filters = QFileDialog.getSaveFileName( diff --git a/src/View/Geometry/Profile/qtableview_profile.py b/src/View/Geometry/Profile/qtableview_profile.py index 7081ad48..f2a25f26 100644 --- a/src/View/Geometry/Profile/qtableview_profile.py +++ b/src/View/Geometry/Profile/qtableview_profile.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import numpy as np -import pandas as pd from PyQt5.QtGui import QFont from PyQt5.QtWidgets import QMessageBox @@ -16,20 +15,20 @@ _translate = QCoreApplication.translate class PandasModelEditable(QAbstractTableModel): - def __init__(self, profile: ProfileXYZ, table_header=None, undo=None): + def __init__(self, profile: ProfileXYZ, header=None, undo=None): QAbstractTableModel.__init__(self) self._undo_stack = undo self._profile = profile - if table_header is None: + if header is None: self._header = [ "X (m)", "Y (m)", "Z (m)", _translate("MainWindowProfile", "Nom"), _translate("MainWindowProfile", "Abs en travers (m)") ] else: - self._header = table_header + self._header = header def rowCount(self, parent=QModelIndex()): return self._profile.number_points @@ -51,11 +50,13 @@ class PandasModelEditable(QAbstractTableModel): elif index.column() == 3: value = self._profile.point(index.row()).name elif index.column() == 4: - value = self._profile.get_station() + value = self._profile.get_station()[index.row()] if 0 <= index.column() < 3: return f"{value:.4f}" elif index.column() == 4: + if np.isnan(value): + return "-" return f"{value:.3f}" return f"{value}" -- GitLab