mirror of https://gitlab.com/pamhyr/pamhyr2
Refactoring: Use ui file in Geometry profile edit window.
parent
44ccf99d48
commit
11a7486a9c
|
|
@ -56,6 +56,9 @@ class Profile(object):
|
|||
|
||||
self._profile_type = _type
|
||||
|
||||
def __len__(self):
|
||||
return len(self._points)
|
||||
|
||||
@property
|
||||
def number_points(self):
|
||||
return len(self._points)
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
import logging
|
||||
|
||||
from tools import timer, trace
|
||||
from View.Plot.APlot import APlot
|
||||
from View.Plot.mpl_canvas_onpick_event import OnpickEvent
|
||||
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||
from View.Tools.Plot.OnPickEvent import OnpickEvent
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QCoreApplication
|
||||
|
|
@ -30,12 +30,15 @@ _translate = QCoreApplication.translate
|
|||
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Plot(APlot):
|
||||
def __init__(self, canvas=None, data=None, toolbar=None, table=None):
|
||||
class Plot(PamhyrPlot):
|
||||
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
|
||||
table=None, parent=None):
|
||||
super(Plot, self).__init__(
|
||||
canvas=canvas,
|
||||
data=data,
|
||||
toolbar=toolbar
|
||||
canvas = canvas,
|
||||
trad = trad,
|
||||
data = data,
|
||||
toolbar = toolbar,
|
||||
parent = parent
|
||||
)
|
||||
|
||||
self._table = table
|
||||
|
|
|
|||
|
|
@ -29,10 +29,11 @@ from PyQt5.QtWidgets import (
|
|||
QMessageBox, QStyledItemDelegate, QLineEdit
|
||||
)
|
||||
from PyQt5.QtCore import (
|
||||
QModelIndex, Qt, QAbstractTableModel,
|
||||
QVariant, QCoreApplication
|
||||
QModelIndex, Qt, QVariant, QCoreApplication
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
||||
from Model.Geometry.PointXYZ import PointXYZ
|
||||
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||
|
||||
|
|
@ -43,43 +44,22 @@ logger = logging.getLogger()
|
|||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class TableEditableModel(QAbstractTableModel):
|
||||
def __init__(self, profile: ProfileXYZ, header=None, undo=None):
|
||||
QAbstractTableModel.__init__(self)
|
||||
|
||||
self._undo_stack = undo
|
||||
self._profile = profile
|
||||
|
||||
if header is None:
|
||||
self._header = [
|
||||
"X (m)", "Y (m)", "Z (m)",
|
||||
_translate("MainWindowProfile", "Nom"),
|
||||
_translate("MainWindowProfile", "Abs en travers (m)")
|
||||
]
|
||||
else:
|
||||
self._header = header
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
return self._profile.number_points
|
||||
|
||||
def columnCount(self, parent=QModelIndex()):
|
||||
return len(self._header)
|
||||
|
||||
class GeometryProfileTableModel(PamhyrTableModel):
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
if index.isValid():
|
||||
if role == Qt.DisplayRole:
|
||||
value = ""
|
||||
|
||||
if index.column() == 0:
|
||||
value = self._profile.point(index.row()).x
|
||||
value = self._data.point(index.row()).x
|
||||
elif index.column() == 1:
|
||||
value = self._profile.point(index.row()).y
|
||||
value = self._data.point(index.row()).y
|
||||
elif index.column() == 2:
|
||||
value = self._profile.point(index.row()).z
|
||||
value = self._data.point(index.row()).z
|
||||
elif index.column() == 3:
|
||||
value = self._profile.point(index.row()).name
|
||||
value = self._data.point(index.row()).name
|
||||
elif index.column() == 4:
|
||||
station = self._profile.get_station()
|
||||
station = self._data.get_station()
|
||||
if station is None:
|
||||
return "-"
|
||||
else:
|
||||
|
|
@ -95,25 +75,25 @@ class TableEditableModel(QAbstractTableModel):
|
|||
return Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
if index.column() == 2:
|
||||
value = self._profile.point(index.row()).z
|
||||
value = self._data.point(index.row()).z
|
||||
if role == Qt.ForegroundRole:
|
||||
if value == self._profile.z_min():
|
||||
if value == self._data.z_min():
|
||||
return QColor("red")
|
||||
elif value == self._profile.z_max():
|
||||
elif value == self._data.z_max():
|
||||
return QColor("blue")
|
||||
|
||||
if role == Qt.ToolTipRole:
|
||||
if value == self._profile.z_min():
|
||||
if value == self._data.z_min():
|
||||
return _translate("MainWindowProfile",
|
||||
"La cote du fond",
|
||||
"Z minimale")
|
||||
elif value == self._profile.z_max():
|
||||
elif value == self._data.z_max():
|
||||
return _translate("MainWindowProfile",
|
||||
"La cote maximale",
|
||||
"Z maximale")
|
||||
|
||||
if index.column() == 3:
|
||||
value = self._profile.point(index.row()).name
|
||||
value = self._data.point(index.row()).name
|
||||
|
||||
if value.strip().upper() in ["RG", "RD"]:
|
||||
if role == Qt.FontRole:
|
||||
|
|
@ -132,21 +112,6 @@ class TableEditableModel(QAbstractTableModel):
|
|||
|
||||
return QVariant()
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return self._header[section]
|
||||
elif orientation == Qt.Vertical and role == Qt.DisplayRole:
|
||||
return str(section + 1)
|
||||
|
||||
if role == Qt.ToolTipRole and section == 4:
|
||||
return _translate(
|
||||
"MainWindowProfile",
|
||||
"Abscisse en travers calculée en projétant les points"
|
||||
" \nsur le plan défini par les deux points nommés extrêmes "
|
||||
)
|
||||
|
||||
return QVariant()
|
||||
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
|
|
@ -154,34 +119,34 @@ class TableEditableModel(QAbstractTableModel):
|
|||
if role == Qt.EditRole:
|
||||
try:
|
||||
if column == 0:
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
SetXCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).x,
|
||||
self._data, row,
|
||||
self._data.point(row).x,
|
||||
value
|
||||
)
|
||||
)
|
||||
elif column == 1:
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
SetYCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).y,
|
||||
self._data, row,
|
||||
self._data.point(row).y,
|
||||
value
|
||||
)
|
||||
)
|
||||
elif column == 2:
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
SetZCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).z,
|
||||
self._data, row,
|
||||
self._data.point(row).z,
|
||||
value
|
||||
)
|
||||
)
|
||||
elif column == 3:
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
SetNameCommand(
|
||||
self._profile, row,
|
||||
self._profile.point(row).name,
|
||||
self._data, row,
|
||||
self._data.point(row).name,
|
||||
value
|
||||
)
|
||||
)
|
||||
|
|
@ -213,9 +178,9 @@ class TableEditableModel(QAbstractTableModel):
|
|||
def insert_row(self, row, parent=QModelIndex()):
|
||||
self.beginInsertRows(parent, row, row - 1)
|
||||
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
AddCommand(
|
||||
self._profile, row
|
||||
self._data, row
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -225,9 +190,9 @@ class TableEditableModel(QAbstractTableModel):
|
|||
def remove_rows(self, rows, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, rows[0], rows[-1])
|
||||
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
DelCommand(
|
||||
self._profile, rows
|
||||
self._data, rows
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -239,15 +204,15 @@ class TableEditableModel(QAbstractTableModel):
|
|||
|
||||
reverse = (order != Qt.AscendingOrder)
|
||||
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
SortCommand(
|
||||
self._profile, column, reverse
|
||||
self._data, column, reverse
|
||||
)
|
||||
)
|
||||
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def move_row_up(self, row, parent=QModelIndex()):
|
||||
def move_up(self, row, parent=QModelIndex()):
|
||||
if row <= 0:
|
||||
return
|
||||
|
||||
|
|
@ -255,26 +220,26 @@ class TableEditableModel(QAbstractTableModel):
|
|||
|
||||
self.beginMoveRows(parent, row - 1, row - 1, parent, target)
|
||||
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
MoveCommand(
|
||||
self._profile, "up", row
|
||||
self._data, "up", row
|
||||
)
|
||||
)
|
||||
|
||||
self.endMoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def move_row_down(self, row_to_move, parent=QModelIndex()):
|
||||
if row > self._profile.number_points:
|
||||
def move_down(self, row_to_move, parent=QModelIndex()):
|
||||
if row > self._data.number_points:
|
||||
return
|
||||
|
||||
target = row
|
||||
|
||||
self.beginMoveRows(parent, row + 1, row + 1, parent, target)
|
||||
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
MoveCommand(
|
||||
self._profile, "down", row
|
||||
self._data, "down", row
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -282,7 +247,7 @@ class TableEditableModel(QAbstractTableModel):
|
|||
self.layoutChanged.emit()
|
||||
|
||||
def paste(self, row, header, data):
|
||||
if row > self._profile.number_points:
|
||||
if row > self._data.number_points:
|
||||
return
|
||||
|
||||
if len(data) == 0:
|
||||
|
|
@ -290,12 +255,12 @@ class TableEditableModel(QAbstractTableModel):
|
|||
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
|
||||
self._undo_stack.push(
|
||||
self._undo.push(
|
||||
PasteCommand(
|
||||
self._profile, row,
|
||||
self._data, row,
|
||||
list(
|
||||
map(
|
||||
lambda d: self._profile.point_from_data(header, d),
|
||||
lambda d: self._data.point_from_data(header, d),
|
||||
data
|
||||
)
|
||||
)
|
||||
|
|
@ -306,32 +271,9 @@ class TableEditableModel(QAbstractTableModel):
|
|||
self.layoutChanged.emit()
|
||||
|
||||
def undo(self):
|
||||
self._undo_stack.undo()
|
||||
self._undo.undo()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def redo(self):
|
||||
self._undo_stack.redo()
|
||||
self._undo.redo()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
|
||||
class Delegate(QStyledItemDelegate):
|
||||
def __init__(self, parent=None, setModelDataEvent=None):
|
||||
super(Delegate, self).__init__(parent)
|
||||
self.setModelDataEvent = setModelDataEvent
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
index.model().data(index, Qt.DisplayRole)
|
||||
return QLineEdit(parent)
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
value = index.model().data(index, Qt.DisplayRole)
|
||||
editor.setText(str(value))
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
model.setData(index, editor.text())
|
||||
|
||||
if not self.setModelDataEvent is None:
|
||||
self.setModelDataEvent()
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
editor.setGeometry(option.rect)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
# Translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 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 PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from View.Tools.PamhyrTranslate import PamhyrTranslate
|
||||
from View.Geometry.Translate import GeometryTranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class GeometryProfileTranslate(GeometryTranslate):
|
||||
def __init__(self):
|
||||
super(GeometryProfileTranslate, self).__init__()
|
||||
|
||||
self._sub_dict["table_headers"] = {
|
||||
"x": _translate("Geometry", "X (m)"),
|
||||
"y": _translate("Geometry", "Y (m)"),
|
||||
"z": _translate("Geometry", "Z (m)"),
|
||||
"name": _translate("Geometry", "Name"),
|
||||
"abs": _translate("Geometry", "Traversal abs (m)"),
|
||||
}
|
||||
|
|
@ -31,206 +31,184 @@ from PyQt5.QtCore import (
|
|||
)
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication, QMainWindow, QFileDialog, QCheckBox,
|
||||
QUndoStack, QShortcut,
|
||||
QUndoStack, QShortcut, QTableView, QAbstractItemView,
|
||||
QHeaderView, QVBoxLayout, QAction,
|
||||
)
|
||||
|
||||
from Model.Geometry.Reach import Reach
|
||||
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||
|
||||
from View.Tools.ASubWindow import ASubMainWindow
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||
|
||||
from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow
|
||||
from View.Geometry.Profile.Plot import Plot
|
||||
from View.Geometry.Profile.Table import *
|
||||
from View.Geometry.Profile.Table import GeometryProfileTableModel
|
||||
from View.Geometry.Profile.Translate import GeometryProfileTranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class ProfileWindow(ASubMainWindow):
|
||||
def __init__(self, profile=None, title="Profile", parent=None):
|
||||
self._title = title
|
||||
self.parent = parent
|
||||
super(ProfileWindow, self).__init__(
|
||||
name=self._title,
|
||||
parent=self.parent
|
||||
)
|
||||
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
class ProfileWindow(PamhyrWindow):
|
||||
_pamhyr_ui = "GeometryCrossSection"
|
||||
_pamhyr_name = "Geometry cross-section"
|
||||
|
||||
def __init__(self, profile=None, study=None, config=None, parent=None):
|
||||
self._profile = profile
|
||||
self._model = None
|
||||
|
||||
self.setup_window()
|
||||
self.setup_sc()
|
||||
self.setup_model()
|
||||
self.setup_connections()
|
||||
self.plot()
|
||||
|
||||
self._model.dataChanged.connect(self.update_plot)
|
||||
self.fileName = None
|
||||
|
||||
# self.ui.tableView.installEventFilter(self)
|
||||
# self._model.dataChanged.connect(self.tableview_is_modified)
|
||||
|
||||
# self.ui.btn_go_back.setEnabled(False)
|
||||
# self.ui.btn_check.setEnabled(False)
|
||||
# self._model.dataChanged.connect(self.set_enable_cancel_btn)
|
||||
# self._model.dataChanged.connect(self.set_enable_validate_changes_btn)
|
||||
# self.ui.btn_reset.setEnabled(False)
|
||||
# self._model.dataChanged.connect(self.set_enable_go_back_initial_state_btn)
|
||||
|
||||
def setup_window(self):
|
||||
header = _translate("MainWindowProfile", "Profile")
|
||||
|
||||
name = self._profile.name
|
||||
if (name is None) or (name == ""):
|
||||
name = _translate("MainWindowProfile", "(no name)")
|
||||
|
||||
self._title = (
|
||||
header + " - " +
|
||||
f"{self._profile.reach.name}" + " - " +
|
||||
f"{name} ({self._profile.kp})"
|
||||
name = f"{self._pamhyr_name} - {self._profile.name} {self._profile.kp}"
|
||||
super(ProfileWindow, self).__init__(
|
||||
title = name,
|
||||
study = study,
|
||||
config = config,
|
||||
trad = GeometryProfileTranslate(),
|
||||
parent = parent
|
||||
)
|
||||
|
||||
self.setWindowTitle(self._title)
|
||||
self.setup_table()
|
||||
self.setup_plot()
|
||||
self.setup_connections()
|
||||
|
||||
def setup_sc(self):
|
||||
self._undo_stack = QUndoStack()
|
||||
def setup_table(self):
|
||||
table_headers = self._trad.get_dict("table_headers")
|
||||
|
||||
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 = TableEditableModel(
|
||||
profile = self._profile,
|
||||
table = self.find(QTableView, "tableView")
|
||||
self._tablemodel = GeometryProfileTableModel(
|
||||
table_view = table,
|
||||
table_headers = table_headers,
|
||||
editable_headers = ["name", "x", "y", "z"],
|
||||
data = self._profile,
|
||||
undo = self._undo_stack
|
||||
)
|
||||
table.setModel(self._tablemodel)
|
||||
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||
table.setAlternatingRowColors(True)
|
||||
|
||||
self.ui.tableView.setModel(self._model)
|
||||
self.ui.tableView.setItemDelegate(Delegate())
|
||||
def setup_plot(self):
|
||||
self._tablemodel.blockSignals(True)
|
||||
|
||||
def setup_connections(self):
|
||||
self.ui.btn_sort_asc_x.triggered.connect(self.sort_X_ascending)
|
||||
self.ui.btn_sort_desc_x.triggered.connect(self.sort_X_descending)
|
||||
self.ui.btn_sort_asc_y.triggered.connect(self.sort_Y_ascending)
|
||||
self.ui.btn_sort_desc_y.triggered.connect(self.sort_Y_descending)
|
||||
self.ui.btn_move_up.triggered.connect(self.move_row_up)
|
||||
self.ui.btn_move_down.triggered.connect(self.move_row_down)
|
||||
self.ui.btn_export.triggered.connect(self.handleSave)
|
||||
self.ui.btn_add.triggered.connect(self.insert_row)
|
||||
self.ui.btn_delete.triggered.connect(self.delete_row)
|
||||
# self.ui.btn_copy.clicked.connect(self.copyTable)
|
||||
# self.ui.btn_paste.clicked.connect(self.pasteTable)
|
||||
# self.ui.btn_check.clicked.connect(self.validate_changes)
|
||||
# self.ui.btn_go_back.clicked.connect(self.cancel_validate_changes)
|
||||
# self.ui.btn_reset.clicked.connect(self.go_back_to_initial_state)
|
||||
|
||||
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)
|
||||
self._canvas = MplCanvas(width=3, height=4, dpi=100)
|
||||
self._canvas.setObjectName("canvas")
|
||||
self._toolbar = PamhyrPlotToolbar(
|
||||
self._canvas, self,
|
||||
items = ["home", "zoom", "save", "iso", "back/forward", "move"]
|
||||
)
|
||||
self._plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||
self._plot_layout.addWidget(self._toolbar)
|
||||
self._plot_layout.addWidget(self._canvas)
|
||||
|
||||
self._plot = Plot(
|
||||
canvas = self.ui.canvas,
|
||||
canvas = self._canvas,
|
||||
data = self._profile,
|
||||
toolbar = None,
|
||||
table = self.ui.tableView,
|
||||
toolbar = self._toolbar,
|
||||
table = self.find(QTableView, "tableView")
|
||||
)
|
||||
self._plot.draw()
|
||||
|
||||
self.ui.tableView.model().blockSignals(False)
|
||||
self._tablemodel.blockSignals(False)
|
||||
|
||||
def setup_connections(self):
|
||||
actions = {
|
||||
"action_sort_asc": self.sort_X_ascending,
|
||||
"action_sort_des": self.sort_X_descending,
|
||||
"action_up": self.move_up,
|
||||
"action_down": self.move_down,
|
||||
"action_add": self.add,
|
||||
"action_delete": self.delete,
|
||||
}
|
||||
|
||||
for action in actions:
|
||||
self.find(QAction, action)\
|
||||
.triggered.connect(actions[action])
|
||||
|
||||
self._tablemodel.dataChanged.connect(self.update_plot)
|
||||
|
||||
def update_plot(self):
|
||||
self.ui.tableView.model().blockSignals(True)
|
||||
self._tablemodel.blockSignals(True)
|
||||
|
||||
# TODO: Do not rebuild all graph
|
||||
self._plot.update()
|
||||
|
||||
self.ui.tableView.model().blockSignals(False)
|
||||
self._tablemodel.blockSignals(False)
|
||||
|
||||
def index_selected_row(self):
|
||||
rows = self.ui.tableView\
|
||||
rows = self._tablemodel\
|
||||
.selectionModel()\
|
||||
.selectedRows()
|
||||
if len(rows) == 0:
|
||||
return 0
|
||||
|
||||
return self.ui.tableView\
|
||||
return self._tablemodel\
|
||||
.selectionModel()\
|
||||
.selectedRows()[0]\
|
||||
.row()
|
||||
|
||||
def insert_row(self):
|
||||
if len(self.ui.tableView.selectedIndexes()) == 0:
|
||||
self._model.insert_row(self._model.rowCount())
|
||||
def add(self):
|
||||
if len(self._tablemodel.selectedIndexes()) == 0:
|
||||
self._tablemodel.insert_row(self._tablemodel.rowCount())
|
||||
else:
|
||||
row = self.index_selected_row()
|
||||
self._model.insert_row(row + 1)
|
||||
self._tablemodel.insert_row(row + 1)
|
||||
self.update_plot()
|
||||
|
||||
def delete_row(self):
|
||||
def delete(self):
|
||||
rows = sorted(
|
||||
list(
|
||||
set(
|
||||
[index.row() for index in self.ui.tableView.selectedIndexes()]
|
||||
[index.row() for index in self._tablemodel.selectedIndexes()]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if len(rows) > 0:
|
||||
self._model.remove_rows(rows)
|
||||
self._tablemodel.remove_rows(rows)
|
||||
self.update_plot()
|
||||
|
||||
def sort_X_ascending(self):
|
||||
self._model.sort('x', order=Qt.AscendingOrder)
|
||||
self._tablemodel.sort('x', order=Qt.AscendingOrder)
|
||||
self.update_plot()
|
||||
|
||||
def sort_X_descending(self):
|
||||
self._model.sort('x', order=Qt.DescendingOrder)
|
||||
self._tablemodel.sort('x', order=Qt.DescendingOrder)
|
||||
self.update_plot()
|
||||
|
||||
def sort_Y_ascending(self):
|
||||
self._model.sort('y', order=Qt.AscendingOrder)
|
||||
self._tablemodel.sort('y', order=Qt.AscendingOrder)
|
||||
self.update_plot()
|
||||
|
||||
def sort_Y_descending(self):
|
||||
self._model.sort('y', order=Qt.DescendingOrder)
|
||||
self._tablemodel.sort('y', order=Qt.DescendingOrder)
|
||||
self.update_plot()
|
||||
|
||||
def move_row_down(self):
|
||||
def move_down(self):
|
||||
rows = list(
|
||||
set(
|
||||
[index.row() for index in self.ui.tableView.selectedIndexes()]
|
||||
[index.row() for index in self._tablemodel.selectedIndexes()]
|
||||
)
|
||||
)
|
||||
|
||||
for row in rows:
|
||||
if row < self._model.rowCount() - 1:
|
||||
self._model.move_row_down(row)
|
||||
if row < self._tablemodel.rowCount() - 1:
|
||||
self._tablemodel.move_down(row)
|
||||
|
||||
self.update_plot()
|
||||
|
||||
def move_row_up(self):
|
||||
def move_up(self):
|
||||
rows = list(
|
||||
set(
|
||||
[index.row() for index in self.ui.tableView.selectedIndexes()]
|
||||
[index.row() for index in self._tablemodel.selectedIndexes()]
|
||||
)
|
||||
)
|
||||
|
||||
for row in rows:
|
||||
if 0 < row:
|
||||
self._model.move_row_up(row)
|
||||
self._tablemodel.move_up(row)
|
||||
|
||||
self.update_plot()
|
||||
|
||||
def copy(self):
|
||||
rows = self.ui.tableView\
|
||||
rows = self._tablemodel\
|
||||
.selectionModel()\
|
||||
.selectedRows()
|
||||
table = []
|
||||
|
|
@ -258,136 +236,13 @@ class ProfileWindow(ASubMainWindow):
|
|||
row.append(self._profile)
|
||||
|
||||
row = self.index_selected_row()
|
||||
self._model.paste(row, header, data)
|
||||
self._tablemodel.paste(row, header, data)
|
||||
self.update_plot()
|
||||
|
||||
def undo(self):
|
||||
self._model.undo()
|
||||
self._tablemodel.undo()
|
||||
self.update_plot()
|
||||
|
||||
def redo(self):
|
||||
self._model.redo()
|
||||
self._tablemodel.redo()
|
||||
self.update_plot()
|
||||
|
||||
def handleSave(self):
|
||||
if self.fileName is None or self.fileName == '':
|
||||
self.fileName, self.filters = QFileDialog.getSaveFileName(
|
||||
self, filter="CSV files (*.csv)"
|
||||
)
|
||||
|
||||
if self.fileName != '':
|
||||
with open(self.fileName, 'w') as stream:
|
||||
csvout = csv.writer(stream, delimiter='\t', quotechar=' ',
|
||||
escapechar=None,
|
||||
quoting=csv.QUOTE_NONNUMERIC,
|
||||
lineterminator='\n')
|
||||
|
||||
for row in range(self._model.rowCount(QModelIndex())):
|
||||
rowdata = []
|
||||
for column in range(self._model.columnCount(QModelIndex())):
|
||||
item = self._model.index(
|
||||
row, column, QModelIndex()
|
||||
).data(Qt.DisplayRole)
|
||||
|
||||
if item is not None:
|
||||
rowdata.append(item)
|
||||
|
||||
if item == 'nan':
|
||||
rowdata.remove(item)
|
||||
|
||||
csvout.writerow(rowdata)
|
||||
|
||||
def handleOpen(self):
|
||||
self.fileName, self.filterName = QFileDialog.getOpenFileName(self)
|
||||
|
||||
if self.fileName != '':
|
||||
with open(self.fileName, 'r') as f:
|
||||
reader = csv.reader(f, delimiter='\t')
|
||||
header = next(reader)
|
||||
|
||||
buf = []
|
||||
for row in reader:
|
||||
row[0] = QCheckBox("-")
|
||||
buf.append(row)
|
||||
|
||||
self._model = None
|
||||
self._model = TableEditableModel(buf)
|
||||
self.ui.tableView.setModel(self._model)
|
||||
self.fileName = ''
|
||||
|
||||
def set_enable_validate_changes_btn(self):
|
||||
self.ui.btn_check.setEnabled(True)
|
||||
|
||||
def set_enable_cancel_btn(self):
|
||||
self.ui.btn_go_back.setEnabled(True)
|
||||
|
||||
def set_enable_go_back_initial_state_btn(self):
|
||||
self.ui.btn_reset.setEnabled(True)
|
||||
|
||||
def delete_empty_rows(self):
|
||||
if self._model.data_contains_nan():
|
||||
buttonReply = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
_translate("MainWindowProfile",
|
||||
"Suppression les lignes incomplètes"),
|
||||
_translate("MainWindowProfile",
|
||||
"Supprimer les lignes des cellules"
|
||||
" non renseignées ?"),
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
|
||||
)
|
||||
|
||||
if buttonReply == QtWidgets.QMessageBox.Yes:
|
||||
self._model.delete_empty_rows()
|
||||
|
||||
if buttonReply == QtWidgets.QMessageBox.No:
|
||||
pass
|
||||
|
||||
def remove_duplicates_point_names(self):
|
||||
counter_list = []
|
||||
list_deleted_names = []
|
||||
|
||||
for ind, name_point in enumerate(self._model.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:
|
||||
if name_point not in list_deleted_names:
|
||||
list_deleted_names.append(name_point)
|
||||
|
||||
if list_deleted_names:
|
||||
self.msg_box_check_duplication_names(list_deleted_names)
|
||||
|
||||
def msg_box_check_duplication_names(self, list_deleted_names):
|
||||
if len(list_deleted_names) == 1:
|
||||
text = _translate("MainWindowProfile",
|
||||
"Le nom ''{}'' est dupliqué."
|
||||
" \n\nYes : Ne garder que la première occurrence. \nNo :"
|
||||
" Annuler la suppression.".format(list_deleted_names[0]))
|
||||
else:
|
||||
text = _translate("MainWindowProfile",
|
||||
"Les noms suivants : \n{} sont dupliqués"
|
||||
" \n\nYes : Ne garder que la première occurrence de "
|
||||
"chaque nom. \nNo :"
|
||||
" Annuler la suppression.".format(list_deleted_names))
|
||||
|
||||
buttonReply = QtWidgets.QMessageBox.question(
|
||||
self, _translate("MainWindowProfile",
|
||||
"Suppression des noms répétés"),
|
||||
text,
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
|
||||
)
|
||||
|
||||
if buttonReply == QtWidgets.QMessageBox.Yes:
|
||||
self._model.remove_duplicates_names()
|
||||
|
||||
def ask_quit(self):
|
||||
choice = QtWidgets.QMessageBox.question(
|
||||
self,
|
||||
_translate("MainWindowProfile", "Quittez ?"),
|
||||
_translate("MainWindowProfile",
|
||||
"Etes-vous sûr de vouloir quitter ?"),
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
|
||||
)
|
||||
return choice == QtWidgets.QMessageBox.Yes
|
||||
|
||||
def initial_state_model(self, profile_initial_state):
|
||||
return profile_initial_state
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ logger = logging.getLogger()
|
|||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class TableEditableModel(PamhyrTableModel):
|
||||
class GeometryReachTableModel(PamhyrTableModel):
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
if not index.isValid():
|
||||
return QVariant()
|
||||
|
|
@ -223,62 +223,3 @@ class TableEditableModel(PamhyrTableModel):
|
|||
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
# TODO: Delete useless delegate
|
||||
class Delegate(QStyledItemDelegate):
|
||||
def __init__(self, parent=None, setModelDataEvent=None):
|
||||
super(Delegate, self).__init__(parent)
|
||||
self.setModelDataEvent = setModelDataEvent
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
index.model().data(index, Qt.DisplayRole)
|
||||
return QLineEdit(parent)
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
value = index.model().data(index, Qt.DisplayRole)
|
||||
editor.setText(str(value))
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
model.setData(index, editor.text())
|
||||
|
||||
if not self.setModelDataEvent is None:
|
||||
self.setModelDataEvent()
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
editor.setGeometry(option.rect)
|
||||
|
||||
class Delegate1(QStyledItemDelegate):
|
||||
def __init__(self, owner, choices):
|
||||
super().__init__(owner)
|
||||
self.items = choices
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
if isinstance(self.parent(), QAbstractItemView):
|
||||
self.parent().openPersistentEditor(index)
|
||||
super(Delegate1, self).paint(painter, option, index)
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
editor = QComboBox(parent)
|
||||
# editor.currentIndexChanged.connect(self.commit_editor)
|
||||
editor.addItems(self.items)
|
||||
return editor
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
editor.blockSignals(True)
|
||||
text = index.model().data(index, Qt.DisplayRole)
|
||||
try:
|
||||
i = self.items.index(text)
|
||||
except ValueError:
|
||||
i = 0
|
||||
editor.setCurrentIndex(i)
|
||||
editor.blockSignals(False)
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
model.setData(index, editor.currentText(), Qt.DisplayRole)
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
editor.setGeometry(option.rect)
|
||||
|
||||
@pyqtSlot()
|
||||
def currentIndexChanged(self):
|
||||
self.commitData.emit(self.sender())
|
||||
|
|
|
|||
|
|
@ -39,17 +39,16 @@ from PyQt5.QtWidgets import (
|
|||
QLabel,
|
||||
)
|
||||
|
||||
from View.Geometry.PlotXY import PlotXY
|
||||
from View.Geometry.PlotKPZ import PlotKPZ
|
||||
from View.Geometry.PlotAC import PlotAC
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||
|
||||
from View.Geometry.Table import *
|
||||
from View.Geometry.Table import GeometryReachTableModel
|
||||
from View.Geometry.PlotXY import PlotXY
|
||||
from View.Geometry.PlotAC import PlotAC
|
||||
from View.Geometry.PlotKPZ import PlotKPZ
|
||||
from View.Geometry.Translate import GeometryTranslate
|
||||
# from View.Geometry.Profile.Window import ProfileWindow
|
||||
from View.Geometry.Profile.Window import ProfileWindow
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
|
@ -87,7 +86,7 @@ class GeometryWindow(PamhyrWindow):
|
|||
table_headers = self._trad.get_dict("table_headers")
|
||||
|
||||
table = self.find(QTableView, "tableView")
|
||||
self._tablemodel = TableEditableModel(
|
||||
self._tablemodel = GeometryReachTableModel(
|
||||
table_view = table,
|
||||
table_headers = table_headers,
|
||||
editable_headers = ["name", "kp"],
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@
|
|||
</attribute>
|
||||
<addaction name="action_add"/>
|
||||
<addaction name="action_delete"/>
|
||||
<addaction name="action_sort"/>
|
||||
<addaction name="action_resort"/>
|
||||
<addaction name="action_sort_asc"/>
|
||||
<addaction name="action_sort_des"/>
|
||||
<addaction name="action_up"/>
|
||||
<addaction name="action_down"/>
|
||||
</widget>
|
||||
|
|
@ -104,25 +104,25 @@
|
|||
<string>Mode down selected point(s)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_sort">
|
||||
<action name="action_sort_asc">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>ressources/gtk-sort-ascending.png</normaloff>ressources/gtk-sort-ascending.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>sort</string>
|
||||
<string>sort_asc</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Sort points by nearest neighbor</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_resort">
|
||||
<action name="action_sort_des">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>ressources/gtk-sort-descending.png</normaloff>ressources/gtk-sort-descending.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>resort</string>
|
||||
<string>sort_des</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Sort reversed points by nearest neighbor</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue