From 12cca24d8b4fe71a35aefca9550e6a497895175a Mon Sep 17 00:00:00 2001 From: Theophile Terraz <theophile.terraz@inrae.fr> Date: Mon, 5 Aug 2024 15:50:22 +0200 Subject: [PATCH] add shift button in geometry window --- src/Model/Geometry/ProfileXYZ.py | 6 + src/View/Geometry/ShiftDialog.py | 60 ++++++++ src/View/Geometry/Table.py | 9 ++ src/View/Geometry/Translate.py | 9 ++ src/View/Geometry/UndoCommand.py | 29 ++++ src/View/Geometry/Window.py | 28 +++- src/View/InitialConditions/Window.py | 2 +- src/View/ui/GeometryReach.ui | 9 ++ src/View/ui/GeometryReachShift.ui | 134 ++++++++++++++++++ ...{UpdateKPOptions.ui => UpdateRKOptions.ui} | 0 10 files changed, 281 insertions(+), 5 deletions(-) create mode 100644 src/View/Geometry/ShiftDialog.py create mode 100644 src/View/ui/GeometryReachShift.ui rename src/View/ui/{UpdateKPOptions.ui => UpdateRKOptions.ui} (100%) diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index d3e98097..0e29c8c3 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -779,3 +779,9 @@ class ProfileXYZ(Profile, SQLSubModel): self.point(i), self.point(i+1) ) + + def shift(self, x, y, z): + for p in self.points: + p.x = p.x + x + p.y = p.y + y + p.z = p.z + z diff --git a/src/View/Geometry/ShiftDialog.py b/src/View/Geometry/ShiftDialog.py new file mode 100644 index 00000000..4953855a --- /dev/null +++ b/src/View/Geometry/ShiftDialog.py @@ -0,0 +1,60 @@ +# ShiftDialog.py -- Pamhyr +# Copyright (C) 2023-2024 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 View.Tools.PamhyrWindow import PamhyrDialog + + +class ShiftDialog(PamhyrDialog): + _pamhyr_ui = "GeometryReachShift" + _pamhyr_name = "Shift" + + def __init__(self, trad=None, parent=None): + super(ShiftDialog, self).__init__( + title=trad[self._pamhyr_name], + trad=trad, + options=[], + parent=parent + ) + + self._init_default_values() + + def _init_default_values(self): + self._dx = 0.0 + self._dy = 0.0 + self._dz = 0.0 + + @property + def dx(self): + return self._dx + + @property + def dy(self): + return self._dy + + @property + def dz(self): + return self._dz + + def accept(self): + self._dx = self.get_double_spin_box("doubleSpinBox_X") + self._dy = self.get_double_spin_box("doubleSpinBox_Y") + self._dz = self.get_double_spin_box("doubleSpinBox_Z") + super().accept() + + def reject(self): + self.close() diff --git a/src/View/Geometry/Table.py b/src/View/Geometry/Table.py index 2676037d..fd91707a 100644 --- a/src/View/Geometry/Table.py +++ b/src/View/Geometry/Table.py @@ -267,3 +267,12 @@ class GeometryReachTableModel(PamhyrTableModel): ) ) self.layoutChanged.emit() + + def shift(self, rows, dx, dy, dz): + + self._undo.push( + ShiftCommand( + self._data, rows, dx, dy, dz + ) + ) + self.layoutChanged.emit() diff --git a/src/View/Geometry/Translate.py b/src/View/Geometry/Translate.py index b2bc2eec..7944d661 100644 --- a/src/View/Geometry/Translate.py +++ b/src/View/Geometry/Translate.py @@ -82,3 +82,12 @@ class GeometryTranslate(MainTranslate): self._dict["Meshing"] = _translate( "Geometry", "Meshing" ) + self._dict["UpdateRK"] = _translate( + "Geometry", "UpdateRK" + ) + self._dict["Purge"] = _translate( + "Geometry", "Purge" + ) + self._dict["Shift"] = _translate( + "Geometry", "Shift" + ) diff --git a/src/View/Geometry/UndoCommand.py b/src/View/Geometry/UndoCommand.py index 772c84e1..d3cc29ef 100644 --- a/src/View/Geometry/UndoCommand.py +++ b/src/View/Geometry/UndoCommand.py @@ -281,3 +281,32 @@ class PurgeCommand(QUndoCommand): def redo(self): for profile in self._reach._profiles: profile.purge(self._np_purge) + + +class ShiftCommand(QUndoCommand): + def __init__(self, reach, rows, dx, dy, dz): + QUndoCommand.__init__(self) + + self._reach = reach + self._rows = rows + self._dx = dx + self._dy = dy + self._dz = dz + + self._old = [] + for profile in self._reach.profiles: + self._old.append(profile.points.copy()) + + def undo(self): + for i in self._rows: + profile = self._reach.profiles[i] + self._reach.profiles[i].shift(-self._dx, + -self._dy, + -self._dz) + + def redo(self): + for i in self._rows: + profile = self._reach.profiles[i] + self._reach.profiles[i].shift(self._dx, + self._dy, + self._dz) diff --git a/src/View/Geometry/Window.py b/src/View/Geometry/Window.py index 20fe4aa2..1a621808 100644 --- a/src/View/Geometry/Window.py +++ b/src/View/Geometry/Window.py @@ -58,6 +58,7 @@ from View.Geometry.PlotRKZ import PlotRKZ from View.Geometry.MeshingDialog import MeshingDialog from View.Geometry.UpdateRKDialog import UpdateRKDialog from View.Geometry.PurgeDialog import PurgeDialog +from View.Geometry.ShiftDialog import ShiftDialog from View.Geometry.Translate import GeometryTranslate from View.Geometry.Profile.Window import ProfileWindow @@ -194,6 +195,7 @@ class GeometryWindow(PamhyrWindow): "action_meshing": self.edit_meshing, "action_update_rk": self.update_rk, "action_purge": self.purge, + "action_shift": self.shift, } for action in actions: @@ -499,10 +501,6 @@ class GeometryWindow(PamhyrWindow): self._table.move_down(row) self.select_current_profile() - def purge(self): - self._table.purge() - self.update_redraw() - def purge(self): try: dlg = PurgeDialog( @@ -515,6 +513,28 @@ class GeometryWindow(PamhyrWindow): logger_exception(e) return + def shift(self): + rows = sorted( + list( + set( + [index.row() for index in self.tableView.selectedIndexes()] + ) + ) + ) + try: + dlg = ShiftDialog( + trad=self._trad, + parent=self + ) + if dlg.exec(): + self._table.shift(rows, + dlg.dx, + dlg.dy, + dlg.dz) + except Exception as e: + logger_exception(e) + return + def duplicate(self): rows = [ row.row() for row in diff --git a/src/View/InitialConditions/Window.py b/src/View/InitialConditions/Window.py index 1113b121..e6563169 100644 --- a/src/View/InitialConditions/Window.py +++ b/src/View/InitialConditions/Window.py @@ -194,7 +194,7 @@ class InitialConditionsWindow(PamhyrWindow): return rows[0].row() def update(self): - self.update(propagate=False) + self._update(propagate=False) def _update(self, propagate=True): self._update_plot() diff --git a/src/View/ui/GeometryReach.ui b/src/View/ui/GeometryReach.ui index 97be0806..2d175bdc 100644 --- a/src/View/ui/GeometryReach.ui +++ b/src/View/ui/GeometryReach.ui @@ -92,6 +92,7 @@ <addaction name="action_meshing"/> <addaction name="action_update_rk"/> <addaction name="action_purge"/> + <addaction name="action_shift"/> </widget> <action name="action_import"> <property name="icon"> @@ -226,6 +227,14 @@ <string>Purge cross-sections to keep a given number of points</string> </property> </action> + <action name="action_shift"> + <property name="text"> + <string>Shift</string> + </property> + <property name="toolTip"> + <string>Shift selected sections coordinates</string> + </property> + </action> </widget> <resources/> <connections/> diff --git a/src/View/ui/GeometryReachShift.ui b/src/View/ui/GeometryReachShift.ui new file mode 100644 index 00000000..575dbb98 --- /dev/null +++ b/src/View/ui/GeometryReachShift.ui @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>381</width> + <height>144</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="3" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Y coordinate</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_1"> + <property name="text"> + <string>X coordinate</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_Y"> + <property name="decimals"> + <number>4</number> + </property> + <property name="minimum"> + <double>-99999999.000000000000000</double> + </property> + <property name="maximum"> + <double>99999999.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_X"> + <property name="decimals"> + <number>4</number> + </property> + <property name="minimum"> + <double>-99999999.000000000000000</double> + </property> + <property name="maximum"> + <double>99999999.000000000000000</double> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Z coordinate</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_Z"> + <property name="decimals"> + <number>4</number> + </property> + <property name="minimum"> + <double>-99999999.000000000000000</double> + </property> + <property name="maximum"> + <double>99999999.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Dialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Dialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/View/ui/UpdateKPOptions.ui b/src/View/ui/UpdateRKOptions.ui similarity index 100% rename from src/View/ui/UpdateKPOptions.ui rename to src/View/ui/UpdateRKOptions.ui -- GitLab