diff --git a/qt_ui/windows/AirWingConfigurationDialog.py b/qt_ui/windows/AirWingConfigurationDialog.py
index fb6bdc8b..87ba13bb 100644
--- a/qt_ui/windows/AirWingConfigurationDialog.py
+++ b/qt_ui/windows/AirWingConfigurationDialog.py
@@ -1,21 +1,20 @@
-import itertools
-import logging
-from collections import defaultdict
-from typing import Optional, Callable, Iterator
+from typing import Optional, Callable
from PySide2.QtCore import (
QItemSelectionModel,
QModelIndex,
QSize,
Qt,
+ QItemSelection,
+ Signal,
)
+from PySide2.QtGui import QStandardItemModel, QStandardItem, QIcon
from PySide2.QtWidgets import (
QAbstractItemView,
QDialog,
QListView,
QVBoxLayout,
QGroupBox,
- QGridLayout,
QLabel,
QWidget,
QScrollArea,
@@ -23,12 +22,15 @@ from PySide2.QtWidgets import (
QTextEdit,
QCheckBox,
QHBoxLayout,
+ QStackedLayout,
)
from game import Game
+from game.dcs.aircrafttype import AircraftType
from game.squadrons import Squadron, AirWing, Pilot
from gen.flights.flight import FlightType
from qt_ui.models import AirWingModel, SquadronModel
+from qt_ui.uiconstants import AIRCRAFT_ICONS
from qt_ui.windows.AirWingDialog import SquadronDelegate
from qt_ui.windows.SquadronDialog import SquadronDialog
@@ -151,60 +153,33 @@ class SquadronConfigurationBox(QGroupBox):
return self.squadron
-class AirWingConfigurationLayout(QVBoxLayout):
- def __init__(self, air_wing: AirWing) -> None:
+class SquadronConfigurationLayout(QVBoxLayout):
+ def __init__(self, squadrons: list[Squadron]) -> None:
super().__init__()
- self.air_wing = air_wing
self.squadron_configs = []
-
- doc_url = (
- "https://github.com/dcs-liberation/dcs_liberation/wiki/Squadrons-and-pilots"
- )
- doc_label = QLabel(
- "Use this opportunity to customize the squadrons available to your "
- "coalition. This is your
"
- "only opportunity to make changes.
"
- "
"
- "To accept your changes and continue, close this window.
"
- "
"
- "To remove a squadron from the game, uncheck the box in the title. New "
- "squadrons cannot
"
- "be added via the UI at this time. To add a custom squadron, see "
- f'the wiki.'
- )
-
- doc_label.setOpenExternalLinks(True)
- self.addWidget(doc_label)
- for squadron in self.air_wing.iter_squadrons():
+ for squadron in squadrons:
squadron_config = SquadronConfigurationBox(squadron)
self.squadron_configs.append(squadron_config)
self.addWidget(squadron_config)
- def apply(self) -> None:
- keep_squadrons = defaultdict(list)
+ def apply(self) -> list[Squadron]:
+ keep_squadrons = []
for squadron_config in self.squadron_configs:
if squadron_config.isChecked():
- squadron = squadron_config.apply()
- keep_squadrons[squadron.aircraft].append(squadron)
- self.air_wing.squadrons = keep_squadrons
+ keep_squadrons.append(squadron_config.apply())
+ return keep_squadrons
-class AirWingConfigurationDialog(QDialog):
- """Dialog window for air wing configuration."""
+class AircraftSquadronsPage(QWidget):
+ def __init__(self, squadrons: list[Squadron]) -> None:
+ super().__init__()
+ layout = QVBoxLayout()
+ self.setLayout(layout)
- def __init__(self, game: Game, parent) -> None:
- super().__init__(parent)
- self.air_wing = game.blue.air_wing
+ self.squadrons_config = SquadronConfigurationLayout(squadrons)
- self.setMinimumSize(500, 800)
- self.setWindowTitle(f"Air Wing Configuration")
- # TODO: self.setWindowIcon()
-
- self.air_wing_config = AirWingConfigurationLayout(self.air_wing)
-
- scrolling_layout = QVBoxLayout()
scrolling_widget = QWidget()
- scrolling_widget.setLayout(self.air_wing_config)
+ scrolling_widget.setLayout(self.squadrons_config)
scrolling_area = QScrollArea()
scrolling_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
@@ -212,9 +187,112 @@ class AirWingConfigurationDialog(QDialog):
scrolling_area.setWidgetResizable(True)
scrolling_area.setWidget(scrolling_widget)
- scrolling_layout.addWidget(scrolling_area)
- self.setLayout(scrolling_layout)
+ layout.addWidget(scrolling_area)
+
+ def apply(self) -> list[Squadron]:
+ return self.squadrons_config.apply()
+
+
+class AircraftSquadronsPanel(QStackedLayout):
+ def __init__(self, air_wing: AirWing) -> None:
+ super().__init__()
+ self.air_wing = air_wing
+ self.squadrons_pages: dict[AircraftType, AircraftSquadronsPage] = {}
+ for aircraft, squadrons in self.air_wing.squadrons.items():
+ page = AircraftSquadronsPage(squadrons)
+ self.addWidget(page)
+ self.squadrons_pages[aircraft] = page
+
+ def apply(self) -> None:
+ for aircraft, page in self.squadrons_pages.items():
+ self.air_wing.squadrons[aircraft] = page.apply()
+
+
+class AircraftTypeList(QListView):
+ page_index_changed = Signal(int)
+
+ def __init__(self, air_wing: AirWing) -> None:
+ super().__init__()
+ self.setIconSize(QSize(91, 24))
+ self.setMinimumWidth(300)
+
+ model = QStandardItemModel(self)
+ self.setModel(model)
+
+ self.selectionModel().setCurrentIndex(
+ model.index(0, 0), QItemSelectionModel.Select
+ )
+ self.selectionModel().selectionChanged.connect(self.on_selection_changed)
+ for aircraft in air_wing.squadrons:
+ aircraft_item = QStandardItem(aircraft.name)
+ icon = self.icon_for(aircraft)
+ if icon is not None:
+ aircraft_item.setIcon(icon)
+ aircraft_item.setEditable(False)
+ aircraft_item.setSelectable(True)
+ model.appendRow(aircraft_item)
+
+ def on_selection_changed(
+ self, selected: QItemSelection, _deselected: QItemSelection
+ ) -> None:
+ indexes = selected.indexes()
+ if len(indexes) > 1:
+ raise RuntimeError("Aircraft list should not allow multi-selection")
+ if not indexes:
+ return
+ self.page_index_changed.emit(indexes[0].row())
+
+ @staticmethod
+ def icon_for(aircraft: AircraftType) -> Optional[QIcon]:
+ name = aircraft.dcs_id
+ if name in AIRCRAFT_ICONS:
+ return QIcon(AIRCRAFT_ICONS[name])
+ return None
+
+
+class AirWingConfigurationDialog(QDialog):
+ """Dialog window for air wing configuration."""
+
+ def __init__(self, game: Game, parent) -> None:
+ super().__init__(parent)
+ self.setMinimumSize(500, 800)
+ self.setWindowTitle(f"Air Wing Configuration")
+ # TODO: self.setWindowIcon()
+
+ layout = QVBoxLayout()
+ self.setLayout(layout)
+
+ doc_url = (
+ "https://github.com/dcs-liberation/dcs_liberation/wiki/Squadrons-and-pilots"
+ )
+ doc_label = QLabel(
+ "Use this opportunity to customize the squadrons available to your "
+ "coalition. This is your only opportunity to make changes."
+ "
"
+ "To accept your changes and continue, close this window.
"
+ "
"
+ "To remove a squadron from the game, uncheck the box in the title. New "
+ "squadrons cannot be added via the UI at this time. To add a custom "
+ "squadron,
"
+ f'see the wiki.'
+ )
+
+ doc_label.setOpenExternalLinks(True)
+ layout.addWidget(doc_label)
+
+ columns = QHBoxLayout()
+ layout.addLayout(columns)
+
+ type_list = AircraftTypeList(game.blue.air_wing)
+ type_list.page_index_changed.connect(self.on_aircraft_changed)
+ columns.addWidget(type_list)
+
+ self.squadrons_panel = AircraftSquadronsPanel(game.blue.air_wing)
+ columns.addLayout(self.squadrons_panel)
def reject(self) -> None:
- self.air_wing_config.apply()
+ self.squadrons_panel.apply()
super().reject()
+
+ def on_aircraft_changed(self, index: QModelIndex) -> None:
+ self.squadrons_panel.setCurrentIndex(index)