Pamhyr2/src/View/Geometry/Profile/Table.py

284 lines
7.7 KiB
Python

# Table.py -- Pamhyr
# Copyright (C) 2023-2025 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 -*-
import numpy as np
import logging
import traceback
from tools import timer, trace
from PyQt5.QtGui import (
QFont, QColor
)
from PyQt5.QtWidgets import (
QMessageBox, QStyledItemDelegate, QLineEdit
)
from PyQt5.QtCore import (
QModelIndex, Qt, QVariant, QCoreApplication
)
from View.Tools.PamhyrTable import PamhyrTableModel
from Model.Geometry.PointXYZ import PointXYZ
from Model.Geometry.ProfileXYZ import ProfileXYZ
from View.Geometry.Profile.UndoCommand import *
logger = logging.getLogger()
_translate = QCoreApplication.translate
class GeometryProfileTableModel(PamhyrTableModel):
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.DisplayRole:
value = ""
if index.column() == 0:
value = self._data.point(index.row()).x
elif index.column() == 1:
value = self._data.point(index.row()).y
elif index.column() == 2:
value = self._data.point(index.row()).z
elif index.column() == 3:
value = self._data.point(index.row()).name
elif index.column() == 4:
station = self._data.get_station()
if station is None:
return "-"
else:
value = station[index.row()]
return f"{value:.3f}"
if 0 <= index.column() < 3:
return f"{value:.4f}"
return f"{value}"
if role == Qt.TextAlignmentRole:
return Qt.AlignHCenter | Qt.AlignVCenter
if index.column() == 2:
value = self._data.point(index.row()).z
if role == Qt.ForegroundRole:
if value == self._data.z_min():
return QColor("red")
elif value == self._data.z_max():
return QColor("blue")
if index.column() == 3:
value = self._data.point(index.row()).name
if value.strip().upper() in ["RG", "RD"]:
if role == Qt.FontRole:
font = QFont()
font.setBold(True)
return font
if role == Qt.ForegroundRole:
return QColor("darkRed")
return QVariant()
def setData(self, index, value, role=Qt.EditRole):
row = index.row()
column = index.column()
if role == Qt.EditRole:
try:
if column == 0:
self._undo.push(
SetXCommand(
self._data, row,
self._data.point(row).x,
value.replace(",", ".")
)
)
elif column == 1:
self._undo.push(
SetYCommand(
self._data, row,
self._data.point(row).y,
value.replace(",", ".")
)
)
elif column == 2:
self._undo.push(
SetZCommand(
self._data, row,
self._data.point(row).z,
value.replace(",", ".")
)
)
elif column == 3:
self._undo.push(
SetNameCommand(
self._data, row,
self._data.point(row).name,
value
)
)
except Exception as e:
logger.info(e)
logger.debug(traceback.format_exc())
self.dataChanged.emit(index, index)
return True
self.dataChanged.emit(index, index)
self.layoutChanged.emit()
return False
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):
flg = Qt.ItemIsSelectable
if index.column() == 4:
return flg
return Qt.ItemIsEditable | Qt.ItemIsEnabled | flg
def insert_row(self, row, parent=QModelIndex()):
self.beginInsertRows(parent, row, row - 1)
self._undo.push(
AddCommand(
self._data, row
)
)
self.endInsertRows()
self.layoutChanged.emit()
def remove_rows(self, rows, parent=QModelIndex()):
self.beginRemoveRows(parent, rows[0], rows[-1])
self._undo.push(
DelCommand(
self._data, rows
)
)
self.endRemoveRows()
self.layoutChanged.emit()
def sort(self, column='x', order=Qt.AscendingOrder):
self.layoutAboutToBeChanged.emit()
reverse = (order != Qt.AscendingOrder)
self._undo.push(
SortCommand(
self._data, column, reverse
)
)
self.layoutChanged.emit()
def move_up(self, row, parent=QModelIndex()):
if row <= 0:
return
target = row + 2
self.beginMoveRows(parent, row - 1, row - 1, parent, target)
self._undo.push(
MoveCommand(
self._data, "up", row
)
)
self.endMoveRows()
self.layoutChanged.emit()
def move_down(self, row, parent=QModelIndex()):
if row > self._data.number_points:
return
target = row
self.beginMoveRows(parent, row + 1, row + 1, parent, target)
self._undo.push(
MoveCommand(
self._data, "down", row
)
)
self.endMoveRows()
self.layoutChanged.emit()
def purge(self, np_purge):
self._undo.push(
PurgeCommand(
self._data, np_purge
)
)
self.layoutChanged.emit()
def reverse(self):
self._undo.push(
ReverseCommand(
self._data
)
)
self.layoutChanged.emit()
def paste(self, row, header, data):
if row > self._data.number_points:
return
if len(data) == 0:
return
self.layoutAboutToBeChanged.emit()
points = list(
map(
lambda d: self._data.point_from_data(header, d),
data
)
)
self._undo.push(
PasteCommand(
self._data, row, points
)
)
self.layoutAboutToBeChanged.emit()
self.layoutChanged.emit()
def undo(self):
self._undo.undo()
self.layoutChanged.emit()
def redo(self):
self._undo.redo()
self.layoutChanged.emit()