diff --git a/changelog.md b/changelog.md index 0a345ba0..7365f15e 100644 --- a/changelog.md +++ b/changelog.md @@ -32,6 +32,7 @@ Saves from 2.3 are not compatible with 2.4. * **[UI]** ASAP is now a checkbox rather than a button. Enabling this will disable the TOT selector but changes to the package structure will automatically re-ASAP the package. * **[UI]** Arrival airfield is now shown in the flight list if it differs from the departure airfield. * **[UI]** Start type can now be selected when creating a flight. +* **[UI]** Arrival and divert airfields can be edited after the flight is created. * **[Factions]** Added option for date-based loadout restriction. Active radar homing missiles are handled, patches welcome for the other thousand weapons. * **[Factions]** Added Poland 2010 faction. * **[Factions]** Added Greece 2005 faction. diff --git a/qt_ui/windows/mission/flight/settings/FlightAirfieldDisplay.py b/qt_ui/windows/mission/flight/settings/FlightAirfieldDisplay.py new file mode 100644 index 00000000..4b56cf1b --- /dev/null +++ b/qt_ui/windows/mission/flight/settings/FlightAirfieldDisplay.py @@ -0,0 +1,99 @@ +import logging + +from PySide2.QtWidgets import (QGroupBox, QLabel, QMessageBox, QVBoxLayout) + +from game import Game +from gen.flights.flight import Flight +from gen.flights.flightplan import FlightPlanBuilder, PlanningError +from gen.flights.traveltime import TotEstimator +from qt_ui.models import PackageModel +from qt_ui.widgets.QLabeledWidget import QLabeledWidget +from qt_ui.widgets.combos.QArrivalAirfieldSelector import \ + QArrivalAirfieldSelector + + +class FlightAirfieldDisplay(QGroupBox): + + def __init__(self, game: Game, package_model: PackageModel, + flight: Flight) -> None: + super().__init__("Departure/Arrival") + self.game = game + self.package_model = package_model + self.flight = flight + + layout = QVBoxLayout() + + self.departure_time = QLabel() + layout.addLayout(QLabeledWidget( + f"Departing from {flight.from_cp.name}", + self.departure_time)) + self.package_model.tot_changed.connect(self.update_departure_time) + self.update_departure_time() + + layout.addWidget(QLabel("Determined based on the package TOT. Edit the " + "package to adjust the TOT.")) + + self.arrival = QArrivalAirfieldSelector( + [cp for cp in game.theater.controlpoints if cp.captured], + flight.unit_type, "Same as departure" + ) + self.arrival.currentIndexChanged.connect(self.set_arrival) + if flight.arrival != flight.departure: + self.arrival.setCurrentText(flight.arrival.name) + layout.addLayout(QLabeledWidget("Arrival:", self.arrival)) + + self.divert = QArrivalAirfieldSelector( + [cp for cp in game.theater.controlpoints if cp.captured], + flight.unit_type, "None" + ) + self.divert.currentIndexChanged.connect(self.set_divert) + if flight.divert is not None: + self.divert.setCurrentText(flight.divert.name) + layout.addLayout(QLabeledWidget("Divert:", self.divert)) + + self.setLayout(layout) + + def update_departure_time(self) -> None: + estimator = TotEstimator(self.package_model.package) + delay = estimator.mission_start_time(self.flight) + self.departure_time.setText(f"At T+{delay}") + + def set_arrival(self, index: int) -> None: + old_arrival = self.flight.arrival + arrival = self.arrival.itemData(index) + if arrival == old_arrival: + return + + if arrival is None: + arrival = self.flight.departure + + self.flight.arrival = arrival + try: + self.update_flight_plan() + except PlanningError as ex: + self.flight.arrival = old_arrival + logging.exception("Could not change arrival airfield") + QMessageBox.critical( + self, "Could not update flight plan", str(ex), QMessageBox.Ok + ) + + def set_divert(self, index: int) -> None: + old_divert = self.flight.divert + divert = self.divert.itemData(index) + if divert == old_divert: + return + + self.flight.divert = divert + try: + self.update_flight_plan() + except PlanningError as ex: + self.flight.divert = old_divert + logging.exception("Could not change divert airfield") + QMessageBox.critical( + self, "Could not update flight plan", str(ex), QMessageBox.Ok + ) + + def update_flight_plan(self) -> None: + planner = FlightPlanBuilder(self.game, self.package_model.package, + is_player=True) + planner.populate_flight_plan(self.flight) diff --git a/qt_ui/windows/mission/flight/settings/QFlightDepartureDisplay.py b/qt_ui/windows/mission/flight/settings/QFlightDepartureDisplay.py deleted file mode 100644 index fe1271ca..00000000 --- a/qt_ui/windows/mission/flight/settings/QFlightDepartureDisplay.py +++ /dev/null @@ -1,38 +0,0 @@ -from PySide2.QtWidgets import QLabel, QHBoxLayout, QGroupBox, QVBoxLayout - -from gen.flights.flight import Flight -from gen.flights.traveltime import TotEstimator - - -from qt_ui.models import PackageModel - - -class QFlightDepartureDisplay(QGroupBox): - - def __init__(self, package_model: PackageModel, flight: Flight): - super().__init__("Departure") - self.package_model = package_model - self.flight = flight - - layout = QVBoxLayout() - - departure_row = QHBoxLayout() - layout.addLayout(departure_row) - - departure_row.addWidget(QLabel( - f"Departing from {flight.from_cp.name}" - )) - self.departure_time = QLabel() - self.package_model.tot_changed.connect(self.update_departure_time) - departure_row.addWidget(self.departure_time) - self.update_departure_time() - - layout.addWidget(QLabel("Determined based on the package TOT. Edit the " - "package to adjust the TOT.")) - - self.setLayout(layout) - - def update_departure_time(self) -> None: - estimator = TotEstimator(self.package_model.package) - delay = estimator.mission_start_time(self.flight) - self.departure_time.setText(f"At T+{delay}") diff --git a/qt_ui/windows/mission/flight/settings/QGeneralFlightSettingsTab.py b/qt_ui/windows/mission/flight/settings/QGeneralFlightSettingsTab.py index 05eaf1fa..804fe8dc 100644 --- a/qt_ui/windows/mission/flight/settings/QGeneralFlightSettingsTab.py +++ b/qt_ui/windows/mission/flight/settings/QGeneralFlightSettingsTab.py @@ -4,8 +4,8 @@ from PySide2.QtWidgets import QFrame, QGridLayout, QVBoxLayout from game import Game from gen.flights.flight import Flight from qt_ui.models import PackageModel -from qt_ui.windows.mission.flight.settings.QFlightDepartureDisplay import \ - QFlightDepartureDisplay +from qt_ui.windows.mission.flight.settings.FlightAirfieldDisplay import \ + FlightAirfieldDisplay from qt_ui.windows.mission.flight.settings.QFlightSlotEditor import \ QFlightSlotEditor from qt_ui.windows.mission.flight.settings.QFlightStartType import \ @@ -24,7 +24,8 @@ class QGeneralFlightSettingsTab(QFrame): layout = QGridLayout() layout.addWidget(QFlightTypeTaskInfo(flight), 0, 0) - layout.addWidget(QFlightDepartureDisplay(package_model, flight), 1, 0) + layout.addWidget(FlightAirfieldDisplay(game, package_model, flight), 1, + 0) layout.addWidget(QFlightSlotEditor(package_model, flight, game), 2, 0) layout.addWidget(QFlightStartType(package_model, flight), 3, 0) layout.addWidget(QFlightCustomName(flight), 4, 0)