diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py index 83833f283faf53f2251a78a6ca882f3ad82b904c..59d677ea546badc88abd038ab768c300bb0db668 100644 --- a/src/Model/Geometry/Profile.py +++ b/src/Model/Geometry/Profile.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +from Model.Geometry.Point import Point from Model.Except import NotImplementedMethodeError class Profile(object): @@ -20,6 +21,14 @@ class Profile(object): self._profile_type = _type + @property + def number_points(self): + return len(self._points) + + @property + def points(self): + return self._points.copy() + @property def reach(self): return self._reach @@ -100,6 +109,11 @@ class Profile(object): def profile_type(self, value: str): self._profile_type = value + def point(self, i:int): + if i < len(self._points): + return self._points[i] + + return None def named_points(self): """List of named point @@ -110,6 +124,81 @@ class Profile(object): return [point for point in self._points if point.point_is_named()] + + def insert_point(self, index: int, point:Point): + """Insert point at index. + + Args: + index: The index of new profile. + point: The point. + + Returns: + Nothing. + """ + self._points.insert(index, point) + + + def delete(self, index: int): + """Delete the point at index + + Args: + index: Index of point. + + Returns: + Nothing. + """ + try: + self._points.pop(index) + except IndexError: + raise IndexError(f"Invalid point index: {index}") + + # Move + + def move_up_point(self, index: int): + if index < len(self._points): + next = index - 1 + + p = self._points + p[index], p[next] = p[next], p[index] + + def move_down_point(self, index: int): + if index >= 0: + prev = index + 1 + + p = self._points + p[index], p[prev] = p[prev], p[index] + + # Sort + + @timer + def sort(self, column, is_reversed: bool = False): + predicate = lambda p: p.x + if column == 'y': + predicate = lambda p: p.y + elif column == 'z': + predicate = lambda p: p.z + + self._profiles = sorted( + self._points, + key=predicate, + reverse=is_reversed + ) + + @timer + def sort_with_indexes(self, indexes: list): + if len(self._points) != len(indexes): + print("TODO: CRITICAL ERROR!") + + self._points = list( + map( + lambda x: x[1], + sorted( + enumerate(self.points), + key=lambda x: indexes[x[0]] + ) + ) + ) + # Abstract method, must be implemented for in non abstract class def get_station(self): raise NotImplementedMethodeError(self, self.get_station) diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index c9818f3ee458a1b5cbf68c9bd8cf95a7d8d84396..fce2bc5c0d0e63a5dae7cdddaf8bb9bd79a7a4df 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -117,22 +117,8 @@ class ProfileXYZ(Profile): point_xyz = PointXYZ(0., 0., 0.) self._points.append(point_xyz) - def delete(self, index: int): - """Delete the point at index - - Args: - index: Index of point. - - Returns: - Nothing. - """ - try: - self._points.pop(index) - except IndexError: - raise IndexError(f"Invalid point index: {index}") - def insert(self, index: int): - """Insert a new profile at index. + """Insert a new point at index. Args: index: The index of new profile. @@ -140,35 +126,8 @@ class ProfileXYZ(Profile): Returns: Nothing. """ - profile = ProfileXYZ() - self._points.insert(index, profile) - - def delete1(self, list_index: list): - """Delete a list of points - - Args: - list_index: Indexes list. - - Returns: - Nothing. - """ - try: - if list_index: - indices = sorted(list(set(list_index)), reverse=True) - for idx in indices: - # if idx < len(self._list_profiles) : - try: - self._points.pop(idx) - except IndexError: - print("Empty list, nothing to delete") - except TypeError: - if isinstance(list_index, int): - self._points.pop(list_index) - print(f"\n{list_index} is not a list\n") - else: - raise TypeError( - f"{list_index} is instance of unexpected type '{type(list_index)}'" - ) + point = PointXYZ(0., 0., 0.) + self._points.insert(index, point) def filter_isnan(self, lst): """Returns the input list without 'nan' element diff --git a/src/View/Geometry/Profile/ProfileUndoCommand.py b/src/View/Geometry/Profile/ProfileUndoCommand.py new file mode 100644 index 0000000000000000000000000000000000000000..964a870bc7a4d1d0a711ea5b1ac11b0d0e64aafe --- /dev/null +++ b/src/View/Geometry/Profile/ProfileUndoCommand.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- + +from tools import trace, timer + +from PyQt5.QtWidgets import ( + QMessageBox, QUndoCommand, QUndoStack, +) + +from Model.Geometry.Profile import Profile + + +class SetDataCommand(QUndoCommand): + def __init__(self, profile, index, old_value, new_value): + QUndoCommand.__init__(self) + + self._profile = profile + self._index = index + self._old = old_value + self._new = new_value + +class SetXCommand(SetDataCommand): + def undo(self): + self._profile.point(self._index).x = self._old + + def redo(self): + self._profile.point(self._index).x = self._new + +class SetYCommand(SetDataCommand): + def undo(self): + self._profile.point(self._index).y = self._old + + def redo(self): + self._profile.point(self._index).y = self._new + +class SetZCommand(SetDataCommand): + def undo(self): + self._profile.point(self._index).z = self._old + + def redo(self): + self._profile.point(self._index).z = self._new + +class SetNameCommand(SetDataCommand): + def undo(self): + self._profile.point(self._index).name = self._old + + def redo(self): + self._profile.point(self._index).name = self._new + + +class AddCommand(QUndoCommand): + def __init__(self, profile, index): + QUndoCommand.__init__(self) + + self._profile = profile + self._index = index + + def undo(self): + self._profile.delete(self._index) + + def redo(self): + self._profile.insert(self._index) + +class DelCommand(QUndoCommand): + def __init__(self, profile, rows): + QUndoCommand.__init__(self) + + self._profile = profile + self._rows = rows + + self._points = [] + for row in rows: + self._points.append(self._profile.point(row)) + self._points.reverse() + + def undo(self): + row = self._rows[0] + for point in self._points: + self._profile.insert_point(row, point) + + def redo(self): + row = self._rows[0] + for _ in self._rows: + self._profile.delete(row) + +class SortCommand(QUndoCommand): + def __init__(self, profile, column _reverse): + QUndoCommand.__init__(self) + + self._profile = profile + self._column = column + self._reverse = _reverse + + old = self._profile.points + self._profile.sort(self.column, self._reverse) + new = self._profile.points + + self._indexes = list( + map( + lambda p: old.index(p), + new + ) + ) + + def undo(self): + self._profile.sort_with_indexes(self._indexes) + + def redo(self): + self._profile.sort(self.column, self._reverse) + + +class MoveCommand(QUndoCommand): + def __init__(self, profile, up, i): + QUndoCommand.__init__(self) + + self._profile = profile + self._up = up == "up" + self._i = i + + def undo(self): + if self._up: + self._profile.move_up_point(self._i) + else: + self._profile.move_down_point(self._i) + + def redo(self): + if self._up: + self._profile.move_up_point(self._i) + else: + self._profile.move_down_point(self._i) + + +class PasteCommand(QUndoCommand): + def __init__(self, profile, row, points): + QUndoCommand.__init__(self) + + self._profile = profile + self._row = row + self._points = points + + self._points.reverse() + + def undo(self): + for ind in range(len(self._profiles)): + self._profile.delete(self._row) + + def redo(self): + for point in self._points: + self._profile.insert_point(self._row, point) diff --git a/src/View/Geometry/Profile/ProfileWindow.py b/src/View/Geometry/Profile/ProfileWindow.py index 9266f7114007197062a8e6f0a5986193b0fadb58..4bb712333b766bb15612cbbadb1e02b2e52b8fdf 100644 --- a/src/View/Geometry/Profile/ProfileWindow.py +++ b/src/View/Geometry/Profile/ProfileWindow.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import copy import sys import csv @@ -93,7 +95,7 @@ class ProfileWindow(QMainWindow): def graph(self): """ - Returns: Le tracé de la cote z en fonction de l'abscisse (calculée). + Returns: Le tracé de la cote z en fonction de l'abscisse (calculée). """ x = self._model.station # abscisse en travers y = self._model.z # cote z diff --git a/src/View/Geometry/Profile/qtableview_profile.py b/src/View/Geometry/Profile/qtableview_profile.py index b94f59ac89c0b3d1e3598528c98aabe27a994b5d..6e237ac6ccc1f06a5369cff92d8830fd325f288b 100644 --- a/src/View/Geometry/Profile/qtableview_profile.py +++ b/src/View/Geometry/Profile/qtableview_profile.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import numpy as np import pandas as pd from PyQt5.QtGui import QFont @@ -8,66 +10,80 @@ from PyQt5.QtCore import QModelIndex, Qt, QAbstractTableModel, QVariant, QCoreAp from Model.Geometry.ProfileXYZ import ProfileXYZ +from View.Geometry.Profile.ProfileUndoCommand import * + _translate = QCoreApplication.translate class PandasModelEditable(QAbstractTableModel): - def __init__(self, profile: ProfileXYZ, table_header=None): + def __init__(self, profile: ProfileXYZ, table_header=None, undo=None): QAbstractTableModel.__init__(self) + self._undo_stack = undo + self._profile = profile + if table_header is None: - self.header = ["X (m)", "Y (m)", "Z (m)", _translate("MainWindowProfile", "Nom"), - _translate("MainWindowProfile", "Abs en travers (m)")] + self._header = [ + "X (m)", "Y (m)", "Z (m)", + _translate("MainWindowProfile", "Nom"), + _translate("MainWindowProfile", "Abs en travers (m)") + ] else: - self.header = table_header - - self.profile = profile - - data = pd.DataFrame({ - self.header[0]: profile.x(), - self.header[1]: profile.y(), - self.header[2]: profile.z(), - self.header[3]: profile.name(), - self.header[4]: profile.get_station() - }) - self._data = data + self._header = table_header def rowCount(self, parent=QModelIndex()): - return self._data.shape[0] + return self._profile.number_points def columnCount(self, parent=QModelIndex()): - return self._data.shape[1] + return len(self._header) def data(self, index, role=Qt.DisplayRole): - value = self._data.iloc[index.row()][index.column()] if index.isValid(): if role == Qt.DisplayRole: - if index.column() != 4: - if isinstance(value, float): - return "%.4f" % value - else: - if isinstance(value, float): - return "%.3f" % value + value = "" + + if index.column() == 0: + value = self._profile.point(index.row()).x + elif index.column() == 1: + value = self._profile.point(index.row()).y + elif index.column() == 2: + value = self._profile.point(index.row()).z + elif index.column() == 3: + value = self._profile.point(index.row()).name + elif index.column() == 4: + value = self._profile.get_station() - return str(self._data.iloc[index.row(), index.column()]) + if 0 <= index.column() < 3: + return f"{value:.4f}" + elif index.column() == 4: + return f"{value:.3f}" + + return f"{value}" if role == Qt.TextAlignmentRole: return Qt.AlignHCenter | Qt.AlignVCenter - # if index.column() == 2: - # if role == Qt.ForegroundRole: - # if value == min(self._data.iloc[:, index.column()]): - # return QtGui.QColor("red") - # elif value == max(self._data.iloc[:, index.column()]): - # return QtGui.QColor("Blue") + if index.column() == 2: + value = self._profile.point(index.row()).z + if role == Qt.ForegroundRole: + if value == self._profile.z_min(): + return QtGui.QColor("red") + elif value == self._profile.z_max(): + return QtGui.QColor("blue") if role == Qt.ToolTipRole: - if value == min(self._data.iloc[:, index.column()]): - return _translate("MainWindowProfile", "La cote du fond", "Z minimale") - elif value == max(self._data.iloc[:, index.column()]): - return _translate("MainWindowProfile", "La cote maximale", "Z maximale") + if value == self._profile.z_min(): + return _translate("MainWindowProfile", + "La cote du fond", + "Z minimale") + elif value == self._profile.z_max(): + return _translate("MainWindowProfile", + "La cote maximale", + "Z maximale") if index.column() == 3: + value = self._profile.point(index.row()).name + if value.strip().upper() in ["RG", "RD"]: if role == Qt.FontRole: font = QFont() @@ -89,14 +105,13 @@ class PandasModelEditable(QAbstractTableModel): font.setBold(True) return font - # if role == Qt.BackgroundRole: - # return QtGui.QColor("#ededee") - return QVariant() def headerData(self, section, orientation, role=Qt.DisplayRole): if orientation == Qt.Horizontal and role == Qt.DisplayRole: - return self.header[section] + return self._header[section] + elif orientation == Qt.Vertical and role == Qt.DisplayRole: + return return str(section + 1) if role == Qt.ToolTipRole and section == 4: return _translate( @@ -105,268 +120,163 @@ class PandasModelEditable(QAbstractTableModel): " \nsur le plan défini par les deux points nommés extrêmes " ) - if orientation == Qt.Vertical and role == Qt.DisplayRole: - return self._data.index[section] + 1 - - return None + return QVariant() def setData(self, index, value, role=Qt.EditRole): - if role == Qt.EditRole: - try: - if index.column() == 3: - self._data.iat[index.row(), index.column()] = str(value) - elif index.column() == 0: - self._data.iat[index.row(), index.column()] = float(value) - elif index.column() == 1: - self._data.iat[index.row(), index.column()] = float(value) - elif index.column() == 2: - self._data.iat[index.row(), index.column()] = float(value) + row = index.row() + column = index.column() - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() + if role == Qt.EditRole: + if column == 0: + self._undo_stack.push( + SetXCommand( + self._profile, row, + self._profile.profile(row).x, + value + ) + ) + elif column == 1: + self._undo_stack.push( + SetYCommand( + self._profile, row, + self._profile.profile(row).y, + value + ) + ) + elif column == 2: + self._undo_stack.push( + SetZCommand( + self._profile, row, + self._profile.profile(row).z, + value + ) + ) + elif column == 3: + self._undo_stack.push( + SetNameCommand( + self._profile, row, + self._profile.profile(row).name, + value + ) ) - self.dataChanged.emit(index, index) - except: - print('TODO') - self.QMessageBoxCritical(value) + self.dataChanged.emit(index, index) return True self.dataChanged.emit(index, index) self.layoutChanged.emit() - return False - @staticmethod - def QMessageBoxCritical(value): - msg = QMessageBox() - msg.setIcon(QMessageBox.Warning) - msg.setText("{} : Valeur saisie incorrecte ".format(value)) - msg.setInformativeText("Seules les valeurs numériques sont autorisées.") - msg.setWindowTitle("Warning ") - msg.setStyleSheet("QLabel{min-width:150 px; font-size: 13px;} QPushButton{ width:20px; font-size: 12px};" - "background-color: Ligthgray ; color : gray;font-size: 8pt; color: #888a80;") - msg.exec_() - 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): - return Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled - - # @QtCore.pyqtSlot() - def insertRows(self, row, count, parent=QModelIndex()): - self.beginInsertRows(parent, row, row + count - 1) - indexes = [str(self.rowCount() + i) for i in range(count)] - left = self._data[0:row] - mid = pd.DataFrame(index=indexes, columns=self._data.columns) - right = self._data[row + count - 1:self.rowCount()] + flg = Qt.ItemIsSelectable | Qt.ItemIsEnabled - self._data = pd.concat([left, mid, right]) + if index.column() == 4: + return flg - for i in [3]: - self._data.iloc[:, i].replace(np.nan, '', inplace=True) + return Qt.ItemIsEditable | flg - self._data.reset_index(drop=True, inplace=True) + def insert_row(self, row, parent=QModelIndex()): + self.beginInsertRows(parent, row, row - 1) - try: - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() + self._undo_stack.push( + AddCommand( + self._profile, row ) - except: - print("TODO") + ) self.endInsertRows() self.layoutChanged.emit() - # @QtCore.pyqtSlot() - def removeRows(self, row, count, parent=QModelIndex()): - self.beginRemoveRows(parent, row, row + count + 1) - self._data.drop(self._data.index[row], inplace=True) - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() - ) - self.endRemoveRows() - self.layoutChanged.emit() - - def remove_rows1(self, row, count, parent=QModelIndex()): - self.beginRemoveRows(parent, row, row + count - 1) - left = self._data.iloc[0:row] - right = self._data.iloc[row + count:self.rowCount()] - - self._data = pd.concat([left, right], axis=0, ignore_index=True) - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() - ) - self.endRemoveRows() - self.layoutChanged.emit() + def remove_rows(self, rows, parent=QModelIndex()): + self.beginRemoveRows(parent, rows[0], row[-1]) - def remove_rows(self, list_row_selected, parent=QModelIndex()): - self.beginRemoveRows(parent, list_row_selected[0], list_row_selected[-1]) - - try: - self._data.drop(self._data.index[list_row_selected], inplace=True) - self._data.reset_index(drop=True, inplace=True) - except: - print('TODO') - try: - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() + self._undo_stack.push( + DelCommand( + self._profile, rows ) - except: - print("TODO") + ) self.endRemoveRows() self.layoutChanged.emit() - def sort(self, column, order=Qt.AscendingOrder): + def sort(self, column='x', order=Qt.AscendingOrder): self.layoutAboutToBeChanged.emit() - colname = self._data.columns.tolist()[column] - self._data.sort_values(colname, ascending=order == Qt.AscendingOrder, inplace=True) - self._data.reset_index(inplace=True, drop=True) - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() + reverse = (order != Qt.AscendingOrder) + + self._undo_stack.push( + SortCommand( + self._profile, column, reverse + ) ) - self.layoutChanged.emit() - def moveRowDown(self, row_to_move, parent=QModelIndex()): - target = row_to_move + 2 - self.beginMoveRows(parent, row_to_move, row_to_move, parent, target) - block_before_row = self._data.iloc[0:row_to_move] - selected_row = self._data.iloc[row_to_move:row_to_move + 1] - after_selcted_row = self._data.iloc[row_to_move + 1:row_to_move + 2] - block_after_row = self._data.iloc[row_to_move + 2:self.rowCount()] + self.layoutChanged.emit() - self._data = pd.concat([block_before_row, after_selcted_row, selected_row, block_after_row], axis=0) - self._data.reset_index(inplace=True, drop=True) + def move_row_up(self, row, parent=QModelIndex()): + if row <= 0: + return - self.endMoveRows() - self.layoutChanged.emit() + target = row + 2 - def moveRowUp(self, row_to_move, parent=QModelIndex()): - target = row_to_move + 1 - self.beginMoveRows(parent, row_to_move - 1, row_to_move - 1, parent, target) - block_before_row = self._data.iloc[0:row_to_move - 1] - before_selected_row = self._data.iloc[row_to_move - 1:row_to_move] - selected_row = self._data.iloc[row_to_move:row_to_move + 1] - block_after_row = self._data.iloc[row_to_move + 1:self.rowCount()] + self.beginMoveRows(parent, row - 1, row - 1, parent, target) - self._data = pd.concat([block_before_row, selected_row, before_selected_row, block_after_row], axis=0) - self._data.reset_index(inplace=True, drop=True) + self._undo_stack.push( + MoveCommand( + self._profile, "up", row + ) + ) self.endMoveRows() self.layoutChanged.emit() - def copyTable(self, start_selection, end_selection): - end_selection = self.rowCount() - - self._data.loc[start_selection:end_selection]\ - .to_clipboard(header=None, index=False, excel=True, sep='\t') + def move_row_down(self, row_to_move, parent=QModelIndex()): + if row > self._profile.number_points: + return - def insert_df_to_idx(self, idx, df, df_insert): - """ - Args: - idx: is the index position in df where you want to insert new dataframe (df_insert) - df: dataframe - df_insert: dataframe to insert - Returns: - The dataframe df with df_insert inserted at index idx. - """ - return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop=True) + target = row - def pasteTable(self, insertion_index): - self.layoutAboutToBeChanged.emit() - df = pd.read_clipboard(header=None, skip_blank_lines=True, - sep="\t", names=self.header) - self._data = self.insert_df_to_idx(insertion_index, self._data, df) - - for i in [3]: - self._data.iloc[:, i].replace(np.nan, '', inplace=True) + self.beginMoveRows(parent, row + 1, row + 1, parent, target) - self.layoutChanged.emit() - self._data.iloc[:, 4] = projection_pointXYZ.update_station( - self.header, - self._data.values.tolist() + self._undo_stack.push( + MoveCommand( + self._profile, "down", row + ) ) - @property - def model_data(self): - return self._data - - @model_data.setter - def model_data(self, new_data): - self._data = new_data + self.endMoveRows() self.layoutChanged.emit() - @property - def x(self): - return self._data.iloc[:, 0].tolist() - - @property - def y(self): - return self._data.iloc[:, 1].tolist() - - @property - def z(self): - return self._data.iloc[:, 2].tolist() - - @property - def name(self): - return self._data.iloc[:, 3].tolist() - - def get_data(self): - return self._data - - @property - def station(self): - return self._data.iloc[:, 4].tolist() - - def remove_duplicates_names(self): - counter_list = [] - list_deleted_names = [] - ind_ind = [] + def paste(self, row, points): + if row > self._profile.number_points: + return - for ind, name_point in enumerate(self.name): - if name_point not in counter_list: - counter_list.append(name_point) - elif len(name_point.strip()) > 0 and name_point in counter_list: - ind_ind.append(ind) + if len(points) == 0: + return - if name_point not in list_deleted_names: - list_deleted_names.append(name_point) - - for ind in ind_ind: - self._data.iat[ind, 3] = "" + self.layoutAboutToBeChanged.emit() - def data_contains_nan(self) -> bool: - """ - Returns: - Returns True if the QTableView() contains np.nan - """ - return self._data.isnull().values.any() + self._undo_stack.push( + PasteCommand( + self._profile, row, points + ) + ) - def delete_empty_rows(self): self.layoutAboutToBeChanged.emit() + self.layoutChanged.emit() - self._data.dropna(inplace=True) - self._data.reset_index(drop=True, inplace=True) - + def undo(self): + self._undo_stack.undo() self.layoutChanged.emit() - def valide_all_changes(self): - self.profile.x = self._data.iloc[:, 0] - self.profile.y = self._data.iloc[:, 1] - self.profile.z = self._data.iloc[:, 2] - self.profile.ld = self._data.iloc[:, 3] + def redo(self): + self._undo_stack.redo() + self.layoutChanged.emit() class Delegate(QtWidgets.QStyledItemDelegate): @@ -375,48 +285,18 @@ class Delegate(QtWidgets.QStyledItemDelegate): self.setModelDataEvent = setModelDataEvent def createEditor(self, parent, option, index): - """ - Args: - parent: - option: - index: - Returns: - Le widget (éditeur) pour éditer l'item se trouvant à l'index index. - """ index.model().data(index, Qt.DisplayRole) return QtWidgets.QLineEdit(parent) def setEditorData(self, editor, index): - """ - Args: - editor: l'éditeur - index: l'index - Returns: permet de transmettre à l'éditeur editor les données à afficher à partir du modèle se trouvant - à l'index index. - """ value = index.model().data(index, Qt.DisplayRole) editor.setText(str(value)) def setModelData(self, editor, model, index): - """ - Args: - editor: l'éditeur - model: le modèle - index: l'index - Returns: permet de récupérer les données de l'éditeur et de les stocker à l'intérieur du modèle, à l'index - identifié par le paramètre index - """ model.setData(index, editor.text()) if not self.setModelDataEvent is None: self.setModelDataEvent() def updateEditorGeometry(self, editor, option, index): - """ - Args: - editor: l'éditeur - option: - index: l'index - Returns: Permet de redimensionner l'éditeur à la bonne taille lorsque la taille de la vue change - """ editor.setGeometry(option.rect) diff --git a/src/View/Geometry/qtableview_reach.py b/src/View/Geometry/qtableview_reach.py index bb984e83f685f99fbb2731b7011fd8d23fbe1d8c..7f0e498869668c8ff48444a6603330cad34b8307 100644 --- a/src/View/Geometry/qtableview_reach.py +++ b/src/View/Geometry/qtableview_reach.py @@ -178,11 +178,11 @@ class PandasModelEditable(QAbstractTableModel): def move_row_up(self, row, parent=QModelIndex()): - target = row + 2 - if row <= 0: return + target = row + 2 + self.beginMoveRows(parent, row - 1, row - 1, parent, target) self._undo_stack.push( @@ -195,11 +195,11 @@ class PandasModelEditable(QAbstractTableModel): self.layoutChanged.emit() def move_row_down(self, row, parent=QModelIndex()): - target = row - if row > self._reach.number_profiles: return + target = row + self.beginMoveRows(parent, row + 1, row + 1, parent, target) self._undo_stack.push( @@ -249,8 +249,8 @@ class Delegate(QtWidgets.QStyledItemDelegate): return QtWidgets.QLineEdit(parent) def setEditorData(self, editor, index): - value = index.model().data(index, Qt.DisplayRole) # DisplayRole - editor.setText(str(value)) # récupère la valeur de la cellule applique la méthode définie dans setData + value = index.model().data(index, Qt.DisplayRole) + editor.setText(str(value)) def setModelData(self, editor, model, index): model.setData(index, editor.text())