Allow per pilot loadouts and properties.

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/3092.
This commit is contained in:
Dan Albert
2023-07-20 21:49:21 -07:00
committed by Raffson
parent 8e670e1a3c
commit 485229b92f
27 changed files with 475 additions and 115 deletions

13
qt_ui/blocksignals.py Normal file
View File

@@ -0,0 +1,13 @@
from collections.abc import Iterator
from contextlib import contextmanager
from PySide6.QtWidgets import QWidget
@contextmanager
def block_signals(widget: QWidget) -> Iterator[None]:
blocked = widget.blockSignals(True)
try:
yield
finally:
widget.blockSignals(blocked)

View File

@@ -121,7 +121,7 @@ class AircraftInventoryData:
flight_type = flight.flight_type.value
target = flight.package.target.name
for idx in range(0, num_units):
pilot = flight.roster.pilots[idx]
pilot = flight.roster.pilot_at(idx)
if pilot is None:
pilot_name = "Unassigned"
player = ""

View File

@@ -89,9 +89,10 @@ class QFlightCreator(QDialog):
roster = None
else:
roster = FlightRoster(
squadron, initial_size=self.flight_size_spinner.value()
squadron,
initial_size=self.flight_size_spinner.value(),
)
self.roster_editor = FlightRosterEditor(roster)
self.roster_editor = FlightRosterEditor(squadron, roster)
self.flight_size_spinner.valueChanged.connect(self.roster_editor.resize)
self.squadron_selector.currentIndexChanged.connect(self.on_squadron_changed)
roster_layout = QHBoxLayout()
@@ -232,7 +233,7 @@ class QFlightCreator(QDialog):
self.roster_editor.replace(None)
if squadron is not None:
self.roster_editor.replace(
FlightRoster(squadron, self.flight_size_spinner.value())
squadron, FlightRoster(squadron, self.flight_size_spinner.value())
)
self.on_departure_changed(squadron.location)

View File

@@ -19,6 +19,11 @@ class QFlightPlanner(QTabWidget):
self.general_settings_tab = QGeneralFlightSettingsTab(
gm, package_model, flight, self.waypoint_tab.flight_waypoint_list
)
self.payload_tab = QFlightPayloadTab(flight, gm.game)
self.general_settings_tab.flight_size_changed.connect(
self.payload_tab.resize_for_flight
)
self.waypoint_tab = QFlightWaypointTab(gm.game, package_model.package, flight)
self.waypoint_tab.loadout_changed.connect(self.payload_tab.reload_from_flight)
self.addTab(self.general_settings_tab, "General Flight settings")
self.addTab(self.payload_tab, "Payload")

View File

@@ -9,26 +9,41 @@ from PySide2.QtWidgets import (
QWidget,
QSpinBox,
QSlider,
QCheckBox,
)
from game import Game
from game.ato.flight import Flight
from game.ato.flightmember import FlightMember
from game.ato.loadouts import Loadout
from qt_ui.widgets.QLabeledWidget import QLabeledWidget
from .QLoadoutEditor import QLoadoutEditor
from .propertyeditor import PropertyEditor
class DcsLoadoutSelector(QComboBox):
def __init__(self, flight: Flight) -> None:
def __init__(self, flight: Flight, member: FlightMember) -> None:
super().__init__()
for loadout in Loadout.iter_for(flight):
self.addItem(loadout.name, loadout)
self.model().sort(0)
self.setDisabled(flight.loadout.is_custom)
if flight.loadout.is_custom:
self.setDisabled(member.loadout.is_custom)
if member.loadout.is_custom:
self.setCurrentText(Loadout.default_for(flight).name)
else:
self.setCurrentText(flight.loadout.name)
self.setCurrentText(member.loadout.name)
class FlightMemberSelector(QSpinBox):
def __init__(self, flight: Flight, parent: QWidget | None = None) -> None:
super().__init__(parent)
self.flight = flight
self.setMinimum(0)
self.setMaximum(flight.count - 1)
@property
def selected_member(self) -> FlightMember:
return self.flight.roster.members[self.value()]
class DcsFuelSelector(QHBoxLayout):
@@ -99,12 +114,41 @@ class QFlightPayloadTab(QFrame):
def __init__(self, flight: Flight, game: Game):
super(QFlightPayloadTab, self).__init__()
self.flight = flight
self.payload_editor = QLoadoutEditor(flight, game)
self.payload_editor = QLoadoutEditor(
flight, self.flight.roster.members[0], game
)
self.payload_editor.toggled.connect(self.on_custom_toggled)
self.payload_editor.saved.connect(self.on_saved_payload)
layout = QVBoxLayout()
self.member_selector = FlightMemberSelector(self.flight, self)
self.member_selector.valueChanged.connect(self.rebind_to_selected_member)
layout.addLayout(QLabeledWidget("Flight member:", self.member_selector))
self.same_loadout_for_all_checkbox = QCheckBox(
"Use same loadout for all flight members"
)
self.same_loadout_for_all_checkbox.setChecked(
self.flight.use_same_loadout_for_all_members
)
self.same_loadout_for_all_checkbox.toggled.connect(self.on_same_loadout_toggled)
layout.addWidget(self.same_loadout_for_all_checkbox)
layout.addWidget(
QLabel(
"<strong>Warning: AI flights should use the same loadout for all members.</strong>"
)
)
scroll_content = QWidget()
scrolling_layout = QVBoxLayout()
scroll_content.setLayout(scrolling_layout)
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setWidget(scroll_content)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
layout.addWidget(scroll)
# Docs Link
docsText = QLabel(
'<a href="https://github.com/dcs-retribution/dcs-retribution/wiki/Custom-Loadouts"><span style="color:#FFFFFF;">How to create your own default loadout</span></a>'
@@ -122,6 +166,13 @@ class QFlightPayloadTab(QFrame):
layout.addLayout(self.fuel_selector)
self.loadout_selector = DcsLoadoutSelector(flight)
self.property_editor = PropertyEditor(
self.flight, self.member_selector.selected_member
)
scrolling_layout.addLayout(self.property_editor)
self.loadout_selector = DcsLoadoutSelector(
flight, self.member_selector.selected_member
)
self.loadout_selector.currentIndexChanged.connect(self.on_new_loadout)
layout.addWidget(self.loadout_selector)
layout.addWidget(self.payload_editor, stretch=1)
@@ -129,8 +180,27 @@ class QFlightPayloadTab(QFrame):
self.setLayout(layout)
def resize_for_flight(self) -> None:
self.member_selector.setMaximum(self.flight.count - 1)
def reload_from_flight(self) -> None:
self.loadout_selector.setCurrentText(self.flight.loadout.name)
self.loadout_selector.setCurrentText(
self.member_selector.selected_member.loadout.name
)
def rebind_to_selected_member(self) -> None:
member = self.member_selector.selected_member
self.property_editor.set_flight_member(member)
self.loadout_selector.setCurrentText(member.loadout.name)
self.loadout_selector.setDisabled(member.loadout.is_custom)
self.payload_editor.set_flight_member(member)
if self.member_selector.value() != 0:
self.loadout_selector.setDisabled(
self.flight.use_same_loadout_for_all_members
)
self.payload_editor.setDisabled(
self.flight.use_same_loadout_for_all_members
)
def loadout_at(self, index: int) -> Loadout:
loadout = self.loadout_selector.itemData(index)
@@ -145,18 +215,30 @@ class QFlightPayloadTab(QFrame):
return loadout
def on_new_loadout(self, index: int) -> None:
self.flight.loadout = self.loadout_at(index)
self.member_selector.selected_member.loadout = self.loadout_at(index)
self.payload_editor.reset_pylons()
def on_custom_toggled(self, use_custom: bool) -> None:
self.loadout_selector.setDisabled(use_custom)
member = self.member_selector.selected_member
member.use_custom_loadout = use_custom
if use_custom:
self.flight.loadout = self.flight.loadout.derive_custom("Custom")
member.loadout = member.loadout.derive_custom("Custom")
else:
self.flight.loadout = self.current_loadout()
member.loadout = self.current_loadout()
self.payload_editor.reset_pylons()
def on_saved_payload(self, payload_name: str) -> None:
loadout = self.flight.loadout
self.loadout_selector.addItem(payload_name, loadout)
self.loadout_selector.setCurrentIndex(self.loadout_selector.count() - 1)
def on_same_loadout_toggled(self, checked: bool) -> None:
self.flight.use_same_loadout_for_all_members = checked
if self.member_selector.value():
self.loadout_selector.setDisabled(checked)
self.payload_editor.setDisabled(checked)
if checked:
self.flight.roster.use_same_loadout_for_all_members()
if self.member_selector.value():
self.rebind_to_selected_member()

View File

@@ -1,3 +1,4 @@
from collections.abc import Iterator
from dataclasses import dataclass
from shutil import copyfile
from typing import Dict, Union
@@ -18,20 +19,23 @@ from dcs import lua
from game import Game
from game.ato.flight import Flight
from game.ato.flightmember import FlightMember
from game.data.weapons import Pylon
from game.persistency import payloads_dir
from qt_ui.blocksignals import block_signals
from qt_ui.windows.mission.flight.payload.QPylonEditor import QPylonEditor
class QLoadoutEditor(QGroupBox):
saved = Signal(str)
def __init__(self, flight: Flight, game: Game) -> None:
def __init__(self, flight: Flight, flight_member: FlightMember, game: Game) -> None:
super().__init__("Use custom loadout")
self.flight = flight
self.flight_member = flight_member
self.game = game
self.setCheckable(True)
self.setChecked(flight.loadout.is_custom)
self.setChecked(flight_member.loadout.is_custom)
vbox = QVBoxLayout(self)
layout = QGridLayout(self)
@@ -40,7 +44,7 @@ class QLoadoutEditor(QGroupBox):
label = QLabel(f"<b>{pylon.number}</b>")
label.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
layout.addWidget(label, i, 0)
layout.addWidget(QPylonEditor(game, flight, pylon), i, 1)
layout.addWidget(QPylonEditor(game, flight, flight_member, pylon), i, 1)
vbox.addLayout(layout)
@@ -60,8 +64,18 @@ class QLoadoutEditor(QGroupBox):
self.setLayout(vbox)
for i in self.findChildren(QPylonEditor):
i.set_from(self.flight.loadout)
for pylon_editor in self.iter_pylon_editors():
pylon_editor.set_from(self.flight_member.loadout)
def iter_pylon_editors(self) -> Iterator[QPylonEditor]:
yield from self.findChildren(QPylonEditor)
def set_flight_member(self, flight_member: FlightMember) -> None:
self.flight_member = flight_member
with block_signals(self):
self.setChecked(self.flight_member.use_custom_loadout)
for pylon_editor in self.iter_pylon_editors():
pylon_editor.set_flight_member(flight_member)
def _backup_payloads(self) -> None:
ac_id = self.flight.unit_type.dcs_unit_type.id
@@ -146,10 +160,10 @@ class QLoadoutEditor(QGroupBox):
return payload_name_input
def reset_pylons(self) -> None:
self.flight.use_custom_loadout = self.isChecked()
self.flight_member.use_custom_loadout = self.isChecked()
if not self.isChecked():
for i in self.findChildren(QPylonEditor):
i.set_from(self.flight.loadout)
for pylon_editor in self.iter_pylon_editors():
pylon_editor.set_from(self.flight_member.loadout)
@dataclass

View File

@@ -6,19 +6,23 @@ from PySide2.QtWidgets import QComboBox
from game import Game
from game.ato.flight import Flight
from game.ato.flightmember import FlightMember
from game.ato.loadouts import Loadout
from game.data.weapons import Pylon, Weapon
class QPylonEditor(QComboBox):
def __init__(self, game: Game, flight: Flight, pylon: Pylon) -> None:
def __init__(
self, game: Game, flight: Flight, flight_member: FlightMember, pylon: Pylon
) -> None:
super().__init__()
self.flight = flight
self.flight_member = flight_member
self.pylon = pylon
self.game = game
self.has_added_clean_item = False
current = self.flight.loadout.pylons.get(self.pylon.number)
current = self.flight_member.loadout.pylons.get(self.pylon.number)
self.addItem("None", None)
if self.game.settings.restrict_weapons_by_date:
@@ -35,7 +39,7 @@ class QPylonEditor(QComboBox):
def on_pylon_change(self):
selected: Optional[Weapon] = self.currentData()
self.flight.loadout.pylons[self.pylon.number] = selected
self.flight_member.loadout.pylons[self.pylon.number] = selected
if selected is None:
logging.debug(f"Pylon {self.pylon.number} emptied")
@@ -70,5 +74,9 @@ class QPylonEditor(QComboBox):
return "None"
return weapon.name
def set_flight_member(self, flight_member: FlightMember) -> None:
self.flight_member = flight_member
self.set_from(self.flight_member.loadout)
def set_from(self, loadout: Loadout) -> None:
self.setCurrentText(self.matching_weapon_name(loadout))

View File

@@ -1,21 +1,31 @@
from PySide6.QtWidgets import QCheckBox
from dcs.unitpropertydescription import UnitPropertyDescription
from game.ato import Flight
from game.ato.flightmember import FlightMember
from .missingpropertydataerror import MissingPropertyDataError
class PropertyCheckBox(QCheckBox):
def __init__(self, flight: Flight, prop: UnitPropertyDescription) -> None:
def __init__(
self, flight_member: FlightMember, prop: UnitPropertyDescription
) -> None:
super().__init__()
self.flight = flight
self.flight_member = flight_member
self.prop = prop
if prop.default is None:
raise MissingPropertyDataError("default cannot be None")
self.setChecked(self.flight.props.get(self.prop.identifier, self.prop.default))
self.setChecked(
self.flight_member.properties.get(self.prop.identifier, self.prop.default)
)
self.toggled.connect(self.on_toggle)
def on_toggle(self, checked: bool) -> None:
self.flight.props[self.prop.identifier] = checked
self.flight_member.properties[self.prop.identifier] = checked
def set_flight_member(self, flight_member: FlightMember) -> None:
self.flight_member = flight_member
self.setChecked(
self.flight_member.properties.get(self.prop.identifier, self.prop.default)
)

View File

@@ -1,14 +1,16 @@
from PySide6.QtWidgets import QComboBox
from dcs.unitpropertydescription import UnitPropertyDescription
from game.ato import Flight
from game.ato.flightmember import FlightMember
from .missingpropertydataerror import MissingPropertyDataError
class PropertyComboBox(QComboBox):
def __init__(self, flight: Flight, prop: UnitPropertyDescription) -> None:
def __init__(
self, flight_member: FlightMember, prop: UnitPropertyDescription
) -> None:
super().__init__()
self.flight = flight
self.flight_member = flight_member
self.prop = prop
if prop.values is None:
@@ -16,7 +18,9 @@ class PropertyComboBox(QComboBox):
if prop.default is None:
raise MissingPropertyDataError("default cannot be None")
current_value = self.flight.props.get(self.prop.identifier, self.prop.default)
current_value = self.flight_member.properties.get(
self.prop.identifier, self.prop.default
)
for ident, text in self.prop.values.items():
self.addItem(text, ident)
@@ -26,4 +30,12 @@ class PropertyComboBox(QComboBox):
self.currentIndexChanged.connect(self.on_selection_changed)
def on_selection_changed(self, _index: int) -> None:
self.flight.props[self.prop.identifier] = self.currentData()
self.flight_member.properties[self.prop.identifier] = self.currentData()
def set_flight_member(self, flight_member: FlightMember) -> None:
self.flight_member = flight_member
self.setCurrentText(
self.flight_member.properties.get(
self.prop.identifier, self.prop.values[self.prop.default]
)
)

View File

@@ -1,9 +1,11 @@
import logging
from typing import Callable
from PySide2.QtWidgets import QGridLayout, QLabel
from dcs.unitpropertydescription import UnitPropertyDescription
from game.ato import Flight
from game.ato.flightmember import FlightMember
from .missingpropertydataerror import MissingPropertyDataError
from .propertycheckbox import PropertyCheckBox
from .propertycombobox import PropertyComboBox
@@ -16,9 +18,10 @@ class UnhandledControlTypeError(RuntimeError):
class PropertyEditor(QGridLayout):
def __init__(self, flight: Flight) -> None:
def __init__(self, flight: Flight, flight_member: FlightMember) -> None:
super().__init__()
self.flight = flight
self.flight_member = flight_member
self.flight_member_update_listeners: list[Callable[[FlightMember], None]] = []
for row, prop in enumerate(flight.unit_type.iter_props()):
if prop.label is None:
@@ -56,12 +59,23 @@ class PropertyEditor(QGridLayout):
# "checkbox", "comboList", "groupbox", "label", "slider", "spinbox"
match prop.control:
case "checkbox":
return PropertyCheckBox(self.flight, prop)
widget = PropertyCheckBox(self.flight_member, prop)
self.flight_member_update_listeners.append(widget.set_flight_member)
return widget
case "comboList":
return PropertyComboBox(self.flight, prop)
widget = PropertyComboBox(self.flight_member, prop)
self.flight_member_update_listeners.append(widget.set_flight_member)
return widget
case "groupbox" | "label":
return None
case "slider" | "spinbox":
return PropertySpinBox(self.flight, prop)
widget = PropertySpinBox(self.flight_member, prop)
self.flight_member_update_listeners.append(widget.set_flight_member)
return widget
case _:
raise UnhandledControlTypeError(prop.control)
def set_flight_member(self, flight_member: FlightMember) -> None:
self.flight_member = flight_member
for listener in self.flight_member_update_listeners:
listener(self.flight_member)

View File

@@ -1,14 +1,16 @@
from PySide6.QtWidgets import QSpinBox
from dcs.unitpropertydescription import UnitPropertyDescription
from game.ato import Flight
from game.ato.flightmember import FlightMember
from .missingpropertydataerror import MissingPropertyDataError
class PropertySpinBox(QSpinBox):
def __init__(self, flight: Flight, prop: UnitPropertyDescription) -> None:
def __init__(
self, flight_member: FlightMember, prop: UnitPropertyDescription
) -> None:
super().__init__()
self.flight = flight
self.flight_member = flight_member
self.prop = prop
if prop.minimum is None:
@@ -20,9 +22,17 @@ class PropertySpinBox(QSpinBox):
self.setMinimum(prop.minimum)
self.setMaximum(prop.maximum)
self.setValue(self.flight.props.get(self.prop.identifier, self.prop.default))
self.setValue(
self.flight_member.properties.get(self.prop.identifier, self.prop.default)
)
self.valueChanged.connect(self.on_value_changed)
def on_value_changed(self, value: int) -> None:
self.flight.props[self.prop.identifier] = value
self.flight_member.properties[self.prop.identifier] = value
def set_flight_member(self, flight_member: FlightMember) -> None:
self.flight_member = flight_member
self.setValue(
self.flight_member.properties.get(self.prop.identifier, self.prop.default)
)

View File

@@ -1,5 +1,5 @@
import logging
from typing import Optional, Callable
from typing import Optional, Callable, Union
from PySide2.QtCore import Signal, QModelIndex
from PySide2.QtWidgets import (
@@ -16,6 +16,8 @@ from PySide2.QtWidgets import (
from game import Game
from game.ato.flight import Flight
from game.ato.flightroster import FlightRoster
from game.ato.iflightroster import IFlightRoster
from game.squadrons import Squadron
from game.squadrons.pilot import Pilot
from qt_ui.models import PackageModel
@@ -23,8 +25,11 @@ from qt_ui.models import PackageModel
class PilotSelector(QComboBox):
available_pilots_changed = Signal()
def __init__(self, roster: Optional[FlightRoster], idx: int) -> None:
def __init__(
self, squadron: Union[Squadron, None], roster: Optional[IFlightRoster], idx: int
) -> None:
super().__init__()
self.squadron = squadron
self.roster = roster
self.pilot_index = idx
self.rebuild()
@@ -40,10 +45,13 @@ class PilotSelector(QComboBox):
self.setDisabled(True)
return
if self.squadron is None:
raise RuntimeError("squadron cannot be None if roster is set")
self.setEnabled(True)
self.addItem("Unassigned", None)
choices = list(self.roster.squadron.available_pilots)
current_pilot = self.roster.pilots[self.pilot_index]
choices = list(self.squadron.available_pilots)
current_pilot = self.roster.pilot_at(self.pilot_index)
if current_pilot is not None:
choices.append(current_pilot)
# Put players first, otherwise alphabetically.
@@ -71,23 +79,26 @@ class PilotSelector(QComboBox):
# The roster resize is handled separately, so we have no pilots to remove.
return
pilot = self.itemData(index)
if pilot == self.roster.pilots[self.pilot_index]:
if pilot == self.roster.pilot_at(self.pilot_index):
return
self.roster.set_pilot(self.pilot_index, pilot)
self.available_pilots_changed.emit()
def replace(self, new_roster: Optional[FlightRoster]) -> None:
def replace(self, squadron: Squadron, new_roster: Optional[FlightRoster]) -> None:
self.squadron = squadron
self.roster = new_roster
self.rebuild()
class PilotControls(QHBoxLayout):
def __init__(self, roster: Optional[FlightRoster], idx: int) -> None:
def __init__(
self, squadron: Union[Squadron, None], roster: Optional[FlightRoster], idx: int
) -> None:
super().__init__()
self.roster = roster
self.pilot_index = idx
self.selector = PilotSelector(roster, idx)
self.selector = PilotSelector(squadron, roster, idx)
self.selector.currentIndexChanged.connect(self.on_pilot_changed)
self.addWidget(self.selector)
@@ -95,8 +106,8 @@ class PilotControls(QHBoxLayout):
self.player_checkbox.setToolTip("Checked if this pilot is a player.")
self.on_pilot_changed(self.selector.currentIndex())
enabled = False
if self.roster is not None and self.roster.squadron is not None:
enabled = self.roster.squadron.aircraft.flyable
if self.roster is not None and squadron is not None:
enabled = squadron.aircraft.flyable
self.player_checkbox.setEnabled(enabled)
self.addWidget(self.player_checkbox)
@@ -106,7 +117,7 @@ class PilotControls(QHBoxLayout):
def pilot(self) -> Optional[Pilot]:
if self.roster is None or self.pilot_index >= self.roster.max_size:
return None
return self.roster.pilots[self.pilot_index]
return self.roster.pilot_at(self.pilot_index)
def on_player_toggled(self, checked: bool) -> None:
pilot = self.pilot
@@ -145,19 +156,19 @@ class PilotControls(QHBoxLayout):
finally:
self.player_checkbox.blockSignals(False)
def replace(self, new_roster: Optional[FlightRoster]) -> None:
def replace(self, squadron: Squadron, new_roster: Optional[FlightRoster]) -> None:
self.roster = new_roster
if self.roster is None or self.pilot_index >= self.roster.max_size:
self.disable_and_clear()
else:
self.enable_and_reset()
self.selector.replace(new_roster)
self.selector.replace(squadron, new_roster)
class FlightRosterEditor(QVBoxLayout):
MAX_PILOTS = 4
def __init__(self, roster: Optional[FlightRoster]) -> None:
def __init__(self, squadron: Union[Squadron, None], roster: Union[IFlightRoster, None]) -> None:
super().__init__()
self.roster = roster
@@ -170,7 +181,7 @@ class FlightRosterEditor(QVBoxLayout):
return callback
controls = PilotControls(roster, pilot_idx)
controls = PilotControls(squadron, roster, pilot_idx)
controls.selector.available_pilots_changed.connect(
make_reset_callback(pilot_idx)
)
@@ -193,15 +204,17 @@ class FlightRosterEditor(QVBoxLayout):
for controls in self.pilot_controls[new_size:]:
controls.disable_and_clear()
def replace(self, new_roster: Optional[FlightRoster]) -> None:
def replace(self, squadron: Squadron, new_roster: Optional[FlightRoster]) -> None:
if self.roster is not None:
self.roster.clear()
self.roster = new_roster
for controls in self.pilot_controls:
controls.replace(new_roster)
controls.replace(squadron, new_roster)
class QFlightSlotEditor(QGroupBox):
flight_resized = Signal(int)
def __init__(self, package_model: PackageModel, flight: Flight, game: Game):
super().__init__("Slots")
self.package_model = package_model
@@ -228,7 +241,7 @@ class QFlightSlotEditor(QGroupBox):
layout.addWidget(QLabel(str(self.flight.squadron)), 1, 1)
layout.addWidget(QLabel("Assigned pilots:"), 2, 0)
self.roster_editor = FlightRosterEditor(flight.roster)
self.roster_editor = FlightRosterEditor(flight.squadron, flight.roster)
layout.addLayout(self.roster_editor, 2, 1)
self.setLayout(layout)
@@ -251,3 +264,4 @@ class QFlightSlotEditor(QGroupBox):
self.flight.resize(old_count)
return
self.roster_editor.resize(new_count)
self.flight_resized.emit(new_count)

View File

@@ -19,7 +19,7 @@ from qt_ui.windows.mission.flight.waypoints.QFlightWaypointList import (
class QGeneralFlightSettingsTab(QFrame):
on_flight_settings_changed = Signal()
flight_size_changed = Signal()
def __init__(
self,
@@ -30,13 +30,16 @@ class QGeneralFlightSettingsTab(QFrame):
):
super().__init__()
self.flight_slot_editor = QFlightSlotEditor(package_model, flight, game.game)
self.flight_slot_editor.flight_resized.connect(self.flight_size_changed)
widgets = [
QFlightTypeTaskInfo(flight),
QCommsEditor(flight, game),
FlightPlanPropertiesGroup(
game.game, package_model, flight, flight_wpt_list
),
QFlightSlotEditor(package_model, flight, game.game),
self.flight_slot_editor,
QFlightStartType(package_model, flight),
QFlightCustomName(flight),
]
@@ -45,6 +48,7 @@ class QGeneralFlightSettingsTab(QFrame):
for w in widgets:
layout.addWidget(w, row, 0)
row += 1
vstretch = QVBoxLayout()
vstretch.addStretch()
layout.addLayout(vstretch, row, 0)

View File

@@ -226,9 +226,11 @@ class QFlightWaypointTab(QFrame):
QMessageBox.critical(
self, "Could not recreate flight", str(ex), QMessageBox.Ok
)
if not self.flight.loadout.is_custom:
self.flight.loadout = Loadout.default_for(self.flight)
self.loadout_changed.emit()
for member in self.flight.iter_members():
if not member.loadout.is_custom:
member.loadout = Loadout.default_for(self.flight)
self.loadout_changed.emit()
self.flight_waypoint_list.update_list()
self.on_change()
def on_change(self):