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)