From 507239552272de6fc8989ea9e1222d8503cad771 Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Sun, 30 Apr 2023 21:03:40 +1000 Subject: [PATCH 1/4] allow altitude changes in waypoint list --- .../flight/waypoints/QFlightWaypointList.py | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py index 880d9b361..77d48eb70 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py @@ -6,9 +6,13 @@ 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 QFlightWaypointList(QTableView): def __init__(self, package: Package, flight: Flight): super().__init__() @@ -16,8 +20,9 @@ def __init__(self, package: Package, flight: Flight): 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) @@ -27,17 +32,21 @@ def __init__(self, package: Package, flight: Flight): self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select ) - def update_list(self): + def update_list(self) -> None: + # disconnect itemChanged signal from handler slot for making altitude changes + # in advance updating waypoint list + self.model.itemChanged.disconnect(self.on_changed) + # 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.model.setHorizontalHeaderLabels(["Name", "Alt", "TOT/DEPART"]) + self.model.setHorizontalHeaderLabels(HEADER_LABELS) waypoints = self.flight.flight_plan.waypoints for row, waypoint in enumerate(waypoints): - self.add_waypoint_row(row, self.flight, waypoint) + self._add_waypoint_row(row, self.flight, waypoint) self.selectionModel().setCurrentIndex( self.model.index(current_index, 0), QItemSelectionModel.Select ) @@ -47,7 +56,10 @@ def update_list(self): total_column_width += self.columnWidth(i) + self.lineWidth() self.setFixedWidth(total_column_width) - def add_waypoint_row( + # reconnect itemChanged signal to handler slot for making altitude changes + self.model.itemChanged.connect(self.on_changed) + + def _add_waypoint_row( self, row: int, flight: Flight, waypoint: FlightWaypoint ) -> None: self.model.insertRow(self.model.rowCount()) @@ -55,15 +67,28 @@ def add_waypoint_row( 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() + try: + altitude_feet = float(altitude) + except: + continue + 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: From 55775a3c13effe9376095637da735bea0e447f8e Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Sat, 10 Jun 2023 11:10:21 +1000 Subject: [PATCH 2/4] update changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 68e7f5c97..5ef75204d 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,7 @@ Saves from 7.x are not compatible with 8.0. ## Features/Improvements * **[UI]** Limited size of overfull airbase display and added scrollbar. +* **[UI]** Waypoint altitudes can be edited in Waypoints tab of Edit Flight window. ## Fixes From 607474b0d52f53c0a449dd397cafba9b3ccb30fa Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Mon, 12 Jun 2023 22:35:12 +1000 Subject: [PATCH 3/4] address review comments --- .../mission/flight/waypoints/QFlightWaypointList.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py index 77d48eb70..8b066ea88 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py @@ -33,9 +33,8 @@ def __init__(self, package: Package, flight: Flight): ) def update_list(self) -> None: - # disconnect itemChanged signal from handler slot for making altitude changes - # in advance updating waypoint list - self.model.itemChanged.disconnect(self.on_changed) + # ignore signals when updating list so on_changed does not fire + self.model.blockSignals(True) # We need to keep just the row and rebuild the index later because the # QModelIndex will not be valid after the model is cleared. @@ -56,8 +55,8 @@ def update_list(self) -> None: total_column_width += self.columnWidth(i) + self.lineWidth() self.setFixedWidth(total_column_width) - # reconnect itemChanged signal to handler slot for making altitude changes - self.model.itemChanged.connect(self.on_changed) + # stop ignoring signals + self.model.blockSignals(False) def _add_waypoint_row( self, row: int, flight: Flight, waypoint: FlightWaypoint @@ -86,7 +85,7 @@ def on_changed(self) -> None: altitude = self.model.item(i, 1).text() try: altitude_feet = float(altitude) - except: + except ValueError: # ignore any user inputs that can't be parsed as float continue self.flight.flight_plan.waypoints[i].alt = Distance.from_feet(altitude_feet) From de465da7567cfb1d1f1ab0a02feee8dbf16bd3b3 Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Thu, 15 Jun 2023 22:02:57 +1000 Subject: [PATCH 4/4] address review comments --- .../flight/waypoints/QFlightWaypointList.py | 73 ++++++++++++------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py index 8b066ea88..91fd6ca4b 100644 --- a/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py +++ b/qt_ui/windows/mission/flight/waypoints/QFlightWaypointList.py @@ -1,6 +1,13 @@ -from PySide6.QtCore import QItemSelectionModel, QPoint +from PySide6.QtCore import QItemSelectionModel, QPoint, QModelIndex from PySide6.QtGui import QStandardItem, QStandardItemModel -from PySide6.QtWidgets import QHeaderView, QTableView +from PySide6.QtWidgets import ( + QHeaderView, + QTableView, + QStyledItemDelegate, + QDoubleSpinBox, + QWidget, + QStyleOptionViewItem, +) from game.ato.flight import Flight from game.ato.flightwaypoint import FlightWaypoint @@ -13,6 +20,16 @@ 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): super().__init__() @@ -32,31 +49,34 @@ def __init__(self, package: Package, flight: Flight): self.indexAt(QPoint(1, 1)), QItemSelectionModel.Select ) + self.altitude_editor_delegate = AltitudeEditorDelegate(self) + self.setItemDelegateForColumn(1, self.altitude_editor_delegate) + def update_list(self) -> None: # ignore signals when updating list so on_changed does not fire self.model.blockSignals(True) - - # 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.model.setHorizontalHeaderLabels(HEADER_LABELS) - - 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) - - # stop ignoring signals - self.model.blockSignals(False) + 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() + + self.model.setHorizontalHeaderLabels(HEADER_LABELS) + + 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 @@ -83,10 +103,7 @@ def _add_waypoint_row( def on_changed(self) -> None: for i in range(self.model.rowCount()): altitude = self.model.item(i, 1).text() - try: - altitude_feet = float(altitude) - except ValueError: # ignore any user inputs that can't be parsed as float - continue + 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: