From 322b8245f7167a54604241caf1c7e63efa560887 Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Fri, 16 Jun 2023 15:41:49 +1000 Subject: [PATCH] Make waypoint altitudes editable. --- changelog.md | 1 + .../flight/waypoints/QFlightWaypointList.py | 90 +++++++++++++------ 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/changelog.md b/changelog.md index 84753d4d..362be8fc 100644 --- a/changelog.md +++ b/changelog.md @@ -150,6 +150,7 @@ Saves from 7.0.0 are compatible with 7.1.0 * **[Factions]** Replaced Patriot STRs "EWRs" with AN/FPS-117 for blue factions 1980 or newer. * **[Mission Generation]** Added option to prevent scud and V2 sites from firing at the start of the mission. * **[Mission Planning]** Per-flight TOT offsets can now be set in the flight details UI. This allows individual flights to be scheduled ahead of or behind the rest of the package. +* **[UI]** Waypoint altitudes can be edited in Waypoints tab of Edit Flight window. * **[UI]** Parking capacity of each squadron's base is now shown during air wing configuration to avoid overcrowding bases when beginning the game with full squadrons. ## Fixes diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py index 49a417ab..70dbc909 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py @@ -1,15 +1,35 @@ from datetime import timedelta -from PySide2.QtCore import QItemSelectionModel, QPoint +from PySide2.QtCore import QItemSelectionModel, QPoint, QModelIndex from PySide2.QtGui import QStandardItem, QStandardItemModel -from PySide2.QtWidgets import QHeaderView, QTableView +from PySide2.QtWidgets import ( + QHeaderView, + QTableView, + QStyledItemDelegate, + QWidget, + QStyleOptionViewItem, + QDoubleSpinBox, +) from game.ato.flight import Flight from game.ato.flightwaypoint import FlightWaypoint from game.ato.flightwaypointtype import FlightWaypointType from game.ato.package import Package +from game.utils import Distance from qt_ui.windows.mission.flight.waypoints.QFlightWaypointItem import QWaypointItem +HEADER_LABELS = ["Name", "Alt (ft)", "Alt Type", "TOT/DEPART"] + + +class AltitudeEditorDelegate(QStyledItemDelegate): + def createEditor( + self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex + ) -> QDoubleSpinBox: + editor = QDoubleSpinBox(parent) + editor.setMinimum(0) + editor.setMaximum(40000) + return editor + class QFlightWaypointList(QTableView): def __init__(self, package: Package, flight: Flight): @@ -18,8 +38,9 @@ class QFlightWaypointList(QTableView): self.flight = flight self.model = QStandardItemModel(self) + self.model.itemChanged.connect(self.on_changed) self.setModel(self.model) - self.model.setHorizontalHeaderLabels(["Name", "Alt", "TOT/DEPART"]) + self.model.setHorizontalHeaderLabels(HEADER_LABELS) header = self.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.ResizeToContents) @@ -29,27 +50,36 @@ class QFlightWaypointList(QTableView): self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select ) - def update_list(self): - # We need to keep just the row and rebuild the index later because the - # QModelIndex will not be valid after the model is cleared. - current_index = self.currentIndex().row() - self.model.clear() + self.altitude_editor_delegate = AltitudeEditorDelegate(self) + self.setItemDelegateForColumn(1, self.altitude_editor_delegate) - self.model.setHorizontalHeaderLabels(["Name", "Alt", "TOT/DEPART"]) + def update_list(self) -> None: + # ignore signals when updating list so on_changed does not fire + self.model.blockSignals(True) + try: + # We need to keep just the row and rebuild the index later because the + # QModelIndex will not be valid after the model is cleared. + current_index = self.currentIndex().row() + self.model.clear() - waypoints = self.flight.flight_plan.waypoints - for row, waypoint in enumerate(waypoints): - self.add_waypoint_row(row, self.flight, waypoint) - self.selectionModel().setCurrentIndex( - self.model.index(current_index, 0), QItemSelectionModel.Select - ) - self.resizeColumnsToContents() - total_column_width = self.verticalHeader().width() + self.lineWidth() - for i in range(0, self.model.columnCount()): - total_column_width += self.columnWidth(i) + self.lineWidth() - self.setFixedWidth(total_column_width) + self.model.setHorizontalHeaderLabels(HEADER_LABELS) - def add_waypoint_row( + waypoints = self.flight.flight_plan.waypoints + for row, waypoint in enumerate(waypoints): + self._add_waypoint_row(row, self.flight, waypoint) + self.selectionModel().setCurrentIndex( + self.model.index(current_index, 0), QItemSelectionModel.Select + ) + self.resizeColumnsToContents() + total_column_width = self.verticalHeader().width() + self.lineWidth() + for i in range(0, self.model.columnCount()): + total_column_width += self.columnWidth(i) + self.lineWidth() + self.setFixedWidth(total_column_width) + finally: + # stop ignoring signals + self.model.blockSignals(False) + + def _add_waypoint_row( self, row: int, flight: Flight, waypoint: FlightWaypoint ) -> None: self.model.insertRow(self.model.rowCount()) @@ -57,15 +87,25 @@ class QFlightWaypointList(QTableView): self.model.setItem(row, 0, QWaypointItem(waypoint, row)) altitude = int(waypoint.alt.feet) - altitude_type = "AGL" if waypoint.alt_type == "RADIO" else "MSL" - altitude_item = QStandardItem(f"{altitude} ft {altitude_type}") - altitude_item.setEditable(False) + altitude_item = QStandardItem(f"{altitude}") + altitude_item.setEditable(True) self.model.setItem(row, 1, altitude_item) + altitude_type = "AGL" if waypoint.alt_type == "RADIO" else "MSL" + altitude_type_item = QStandardItem(f"{altitude_type}") + altitude_type_item.setEditable(False) + self.model.setItem(row, 2, altitude_type_item) + tot = self.tot_text(flight, waypoint) tot_item = QStandardItem(tot) tot_item.setEditable(False) - self.model.setItem(row, 2, tot_item) + self.model.setItem(row, 3, tot_item) + + def on_changed(self) -> None: + for i in range(self.model.rowCount()): + altitude = self.model.item(i, 1).text() + altitude_feet = float(altitude) + self.flight.flight_plan.waypoints[i].alt = Distance.from_feet(altitude_feet) def tot_text(self, flight: Flight, waypoint: FlightWaypoint) -> str: if waypoint.waypoint_type == FlightWaypointType.TAKEOFF: