mirror of https://gitlab.com/pamhyr/pamhyr2
geometry: Add scheme undo/redo feature.
parent
6fcd0b83af
commit
51b9b3e1e4
|
|
@ -8,7 +8,7 @@ from copy import deepcopy
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
from tools import flatten, timer
|
from tools import flatten, timer, trace
|
||||||
|
|
||||||
from Model.Geometry.Profile import Profile
|
from Model.Geometry.Profile import Profile
|
||||||
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||||
|
|
@ -99,6 +99,19 @@ class Reach:
|
||||||
self._profiles.insert(index, profile)
|
self._profiles.insert(index, profile)
|
||||||
self._update_profile_numbers()
|
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):
|
def delete(self, list_index: list):
|
||||||
"""Delete some elements in profile list
|
"""Delete some elements in profile list
|
||||||
|
|
||||||
|
|
@ -124,13 +137,6 @@ class Reach:
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"{list_index} is instance of unexpected type '{type(list_index)}'")
|
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):
|
def get_x(self):
|
||||||
return [profile.x() for profile in self.profiles]
|
return [profile.x() for profile in self.profiles]
|
||||||
|
|
||||||
|
|
@ -270,22 +276,28 @@ class Reach:
|
||||||
|
|
||||||
# Sort
|
# Sort
|
||||||
|
|
||||||
def sort_ascending(self):
|
@timer
|
||||||
"""Sort profiles by increasing KP
|
def sort(self, is_reversed: bool = False):
|
||||||
|
self._profiles = sorted(
|
||||||
|
self._profiles,
|
||||||
|
key=lambda profile: profile.kp,
|
||||||
|
reverse=is_reversed
|
||||||
|
)
|
||||||
|
|
||||||
Returns:
|
@timer
|
||||||
Nothing.
|
def sort_with_indexes(self, indexes: list):
|
||||||
"""
|
if len(self._profiles) != len(indexes):
|
||||||
self._sort(is_reversed=False)
|
print("TODO: CRITICAL ERROR!")
|
||||||
|
|
||||||
def sort_descending(self):
|
|
||||||
"""Sort profiles by decreasing KP
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Nothing.
|
|
||||||
"""
|
|
||||||
self._sort(is_reversed=True)
|
|
||||||
|
|
||||||
|
self._profiles = list(
|
||||||
|
map(
|
||||||
|
lambda x: x[1],
|
||||||
|
sorted(
|
||||||
|
enumerate(self.profiles),
|
||||||
|
key=lambda x: indexes[x[0]]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Copy/Paste
|
# Copy/Paste
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ from View.ASubWindow import WindowToolKit
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GeometryWindow(QMainWindow, WindowToolKit):
|
class GeometryWindow(QMainWindow, WindowToolKit):
|
||||||
def __init__(self, model=None, parent=None):
|
def __init__(self, model=None, parent=None):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
@ -47,6 +50,7 @@ class GeometryWindow(QMainWindow, WindowToolKit):
|
||||||
self.setup_window()
|
self.setup_window()
|
||||||
self.setup_model()
|
self.setup_model()
|
||||||
self.setup_plots()
|
self.setup_plots()
|
||||||
|
# self.setup_undo()
|
||||||
self.setup_connections()
|
self.setup_connections()
|
||||||
self.changed_slider_value()
|
self.changed_slider_value()
|
||||||
|
|
||||||
|
|
@ -67,6 +71,12 @@ class GeometryWindow(QMainWindow, WindowToolKit):
|
||||||
self.plot_kpc()
|
self.plot_kpc()
|
||||||
self.plot_ac()
|
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):
|
def setup_connections(self):
|
||||||
self.ui.btn_open.clicked.connect(self.open_file_dialog)
|
self.ui.btn_open.clicked.connect(self.open_file_dialog)
|
||||||
self.ui.btn_sort_asc.clicked.connect(self.sort_ascending)
|
self.ui.btn_sort_asc.clicked.connect(self.sort_ascending)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -13,21 +13,26 @@ from PyQt5 import (
|
||||||
)
|
)
|
||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, QAbstractTableModel, QModelIndex,
|
Qt, QAbstractTableModel, QModelIndex,
|
||||||
QVariant, pyqtSlot, QCoreApplication
|
QVariant, pyqtSlot, QCoreApplication,
|
||||||
)
|
)
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QMessageBox
|
QMessageBox, QUndoCommand, QUndoStack,
|
||||||
)
|
)
|
||||||
|
|
||||||
from Model.Geometry import Reach
|
from Model.Geometry import Reach
|
||||||
|
from View.Geometry.ReachUndoCommand import *
|
||||||
|
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
class PandasModelEditable(QAbstractTableModel):
|
class PandasModelEditable(QAbstractTableModel):
|
||||||
def __init__(self, reach, headers=None):
|
def __init__(self, reach, headers=None):
|
||||||
QAbstractTableModel.__init__(self)
|
QAbstractTableModel.__init__(self)
|
||||||
data_list = []
|
data_list = []
|
||||||
|
|
||||||
|
self._undo_stack = QUndoStack()
|
||||||
|
|
||||||
self._reach = reach
|
self._reach = reach
|
||||||
|
|
||||||
if headers is None:
|
if headers is None:
|
||||||
|
|
@ -91,9 +96,23 @@ class PandasModelEditable(QAbstractTableModel):
|
||||||
|
|
||||||
if role == Qt.EditRole and index.column() != 2:
|
if role == Qt.EditRole and index.column() != 2:
|
||||||
if index.column() == 0:
|
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
|
self._reach.profile(index.row()).name = value
|
||||||
|
|
||||||
if index.column() == 1:
|
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._reach.profile(index.row()).kp = value
|
||||||
|
|
||||||
self.dataChanged.emit(index, index)
|
self.dataChanged.emit(index, index)
|
||||||
|
|
@ -167,6 +186,14 @@ class PandasModelEditable(QAbstractTableModel):
|
||||||
self.endMoveRows()
|
self.endMoveRows()
|
||||||
self.layoutChanged.emit()
|
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):
|
class Delegate(QtWidgets.QStyledItemDelegate):
|
||||||
def __init__(self, parent=None, setModelDataEvent=None):
|
def __init__(self, parent=None, setModelDataEvent=None):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue