geometry: Add scheme undo/redo feature.

mesh
Pierre-Antoine Rouby 2023-04-20 10:51:20 +02:00
parent 6fcd0b83af
commit 51b9b3e1e4
4 changed files with 159 additions and 24 deletions

View File

@ -8,7 +8,7 @@ from copy import deepcopy
from operator import itemgetter
from functools import reduce
from tools import flatten, timer
from tools import flatten, timer, trace
from Model.Geometry.Profile import Profile
from Model.Geometry.ProfileXYZ import ProfileXYZ
@ -99,6 +99,19 @@ class Reach:
self._profiles.insert(index, profile)
self._update_profile_numbers()
def insert_profile(self, index: int, profile: Profile):
"""Insert new profile in list
Args:
index: The position of the new profile.
Returns:
Nothing.
"""
self._profiles.insert(index, profile)
self._update_profile_numbers()
def delete(self, list_index: list):
"""Delete some elements in profile list
@ -124,13 +137,6 @@ class Reach:
else:
raise TypeError(f"{list_index} is instance of unexpected type '{type(list_index)}'")
def sort(self, is_reversed: bool = False):
self._profiles = sorted(
self._profiles,
key=lambda profile: profile.kp,
reverse=is_reversed
)
def get_x(self):
return [profile.x() for profile in self.profiles]
@ -270,22 +276,28 @@ class Reach:
# Sort
def sort_ascending(self):
"""Sort profiles by increasing KP
@timer
def sort(self, is_reversed: bool = False):
self._profiles = sorted(
self._profiles,
key=lambda profile: profile.kp,
reverse=is_reversed
)
Returns:
Nothing.
"""
self._sort(is_reversed=False)
def sort_descending(self):
"""Sort profiles by decreasing KP
Returns:
Nothing.
"""
self._sort(is_reversed=True)
@timer
def sort_with_indexes(self, indexes: list):
if len(self._profiles) != len(indexes):
print("TODO: CRITICAL ERROR!")
self._profiles = list(
map(
lambda x: x[1],
sorted(
enumerate(self.profiles),
key=lambda x: indexes[x[0]]
)
)
)
# Copy/Paste

View File

@ -28,6 +28,9 @@ from View.ASubWindow import WindowToolKit
_translate = QCoreApplication.translate
class GeometryWindow(QMainWindow, WindowToolKit):
def __init__(self, model=None, parent=None):
self.parent = parent
@ -47,6 +50,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
self.setup_window()
self.setup_model()
self.setup_plots()
# self.setup_undo()
self.setup_connections()
self.changed_slider_value()
@ -67,6 +71,12 @@ class GeometryWindow(QMainWindow, WindowToolKit):
self.plot_kpc()
self.plot_ac()
# def setup_undo(self):
# self.undoAction = self.undoStack.createUndoAction(self, self.tr("&Undo"))
# self.undoAction.setShortcuts(QKeySequence.Undo)
# self.redoAction = self.undoStack.createRedoAction(self, self.tr("&Redo"))
# self.redoAction.setShortcuts(QKeySequence.Redo)
def setup_connections(self):
self.ui.btn_open.clicked.connect(self.open_file_dialog)
self.ui.btn_sort_asc.clicked.connect(self.sort_ascending)

View File

@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
from tools import trace, timer
from PyQt5.QtWidgets import (
QMessageBox, QUndoCommand, QUndoStack,
)
from Model.Geometry import Reach
class SetDataCommand(QUndoCommand):
def __init__(self, reach, index, old_value, new_value):
QUndoCommand.__init__(self)
self._reach = reach
self._index = index
self._old = old_value
self._new = new_value
class SetNameCommand(SetDataCommand):
def undo(self):
self._reach.profile(self._index).name = self._old
def redo(self):
self._reach.profile(self._index).name = self._new
class SetKPCommand(SetDataCommand):
def undo(self):
self._reach.profile(self._index).kp = self._old
def redo(self):
self._reach.profile(self._index).kp = self._new
class AddCommand(QUndoCommand):
def __init__(self, reach, index):
QUndoCommand.__init__(self)
self._reach = reach
self._index = index
def undo(self):
self._reach.delete([self._index])
def redo(self):
self._reach.insert(self._index)
class DelCommand(QUndoCommand):
def __init__(self, reach, index, profile):
QUndoCommand.__init__(self)
self._reach = reach
self._index = index
self._profile = profile
def undo(self):
self._reach.insert_profile(self._index, self._profile)
def redo(self):
self._reach.delete([self._index])
class SortCommand(QUndoCommand):
@timer
def __init__(self, reach, old, new):
QUndoCommand.__init__(self)
self._reach = reach
self._indexes = list(
map(
lambda p: old.index(p),
new
)
)
self._rindexes = list(
map(
lambda p: new.index(p),
old
)
)
def undo(self):
self._reach.sort_with_indexes(self._indexes)
def redo(self):
self._reach.sort_with_indexes(self._rindexes)

View File

@ -13,21 +13,26 @@ from PyQt5 import (
)
from PyQt5.QtCore import (
Qt, QAbstractTableModel, QModelIndex,
QVariant, pyqtSlot, QCoreApplication
QVariant, pyqtSlot, QCoreApplication,
)
from PyQt5.QtWidgets import (
QMessageBox
QMessageBox, QUndoCommand, QUndoStack,
)
from Model.Geometry import Reach
from View.Geometry.ReachUndoCommand import *
_translate = QCoreApplication.translate
class PandasModelEditable(QAbstractTableModel):
def __init__(self, reach, headers=None):
QAbstractTableModel.__init__(self)
data_list = []
self._undo_stack = QUndoStack()
self._reach = reach
if headers is None:
@ -91,9 +96,23 @@ class PandasModelEditable(QAbstractTableModel):
if role == Qt.EditRole and index.column() != 2:
if index.column() == 0:
self._undo_stack.push(
SetNameCommand(
self._reach, index.row(),
self._reach.profile(index.row()).name,
value
)
)
self._reach.profile(index.row()).name = value
if index.column() == 1:
self._undo_stack.push(
SetKPCommand(
self._reach, index.row(),
self._reach.profile(index.row()).kp,
value
)
)
self._reach.profile(index.row()).kp = value
self.dataChanged.emit(index, index)
@ -167,6 +186,14 @@ class PandasModelEditable(QAbstractTableModel):
self.endMoveRows()
self.layoutChanged.emit()
def undo(self):
self._undo_stack.undo()
self.layoutChanged.emit()
def redo(self):
self._undo_stack.redo()
self.layoutChanged.emit()
class Delegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None, setModelDataEvent=None):