Add per-aircraft tabs to air wing configuration.

This commit is contained in:
Dan Albert 2021-07-18 15:49:58 -07:00
parent c2951e5e41
commit 270f87f193

View File

@ -1,21 +1,20 @@
import itertools from typing import Optional, Callable
import logging
from collections import defaultdict
from typing import Optional, Callable, Iterator
from PySide2.QtCore import ( from PySide2.QtCore import (
QItemSelectionModel, QItemSelectionModel,
QModelIndex, QModelIndex,
QSize, QSize,
Qt, Qt,
QItemSelection,
Signal,
) )
from PySide2.QtGui import QStandardItemModel, QStandardItem, QIcon
from PySide2.QtWidgets import ( from PySide2.QtWidgets import (
QAbstractItemView, QAbstractItemView,
QDialog, QDialog,
QListView, QListView,
QVBoxLayout, QVBoxLayout,
QGroupBox, QGroupBox,
QGridLayout,
QLabel, QLabel,
QWidget, QWidget,
QScrollArea, QScrollArea,
@ -23,12 +22,15 @@ from PySide2.QtWidgets import (
QTextEdit, QTextEdit,
QCheckBox, QCheckBox,
QHBoxLayout, QHBoxLayout,
QStackedLayout,
) )
from game import Game from game import Game
from game.dcs.aircrafttype import AircraftType
from game.squadrons import Squadron, AirWing, Pilot from game.squadrons import Squadron, AirWing, Pilot
from gen.flights.flight import FlightType from gen.flights.flight import FlightType
from qt_ui.models import AirWingModel, SquadronModel 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.AirWingDialog import SquadronDelegate
from qt_ui.windows.SquadronDialog import SquadronDialog from qt_ui.windows.SquadronDialog import SquadronDialog
@ -151,60 +153,33 @@ class SquadronConfigurationBox(QGroupBox):
return self.squadron return self.squadron
class AirWingConfigurationLayout(QVBoxLayout): class SquadronConfigurationLayout(QVBoxLayout):
def __init__(self, air_wing: AirWing) -> None: def __init__(self, squadrons: list[Squadron]) -> None:
super().__init__() super().__init__()
self.air_wing = air_wing
self.squadron_configs = [] self.squadron_configs = []
for squadron in squadrons:
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. <strong>This is your<br />"
"only opportunity to make changes.</strong><br />"
"<br />"
"To accept your changes and continue, close this window.<br />"
"<br />"
"To remove a squadron from the game, uncheck the box in the title. New "
"squadrons cannot<br />"
"be added via the UI at this time. To add a custom squadron, see "
f'<a style="color:#ffffff" href="{doc_url}">the wiki</a>.'
)
doc_label.setOpenExternalLinks(True)
self.addWidget(doc_label)
for squadron in self.air_wing.iter_squadrons():
squadron_config = SquadronConfigurationBox(squadron) squadron_config = SquadronConfigurationBox(squadron)
self.squadron_configs.append(squadron_config) self.squadron_configs.append(squadron_config)
self.addWidget(squadron_config) self.addWidget(squadron_config)
def apply(self) -> None: def apply(self) -> list[Squadron]:
keep_squadrons = defaultdict(list) keep_squadrons = []
for squadron_config in self.squadron_configs: for squadron_config in self.squadron_configs:
if squadron_config.isChecked(): if squadron_config.isChecked():
squadron = squadron_config.apply() keep_squadrons.append(squadron_config.apply())
keep_squadrons[squadron.aircraft].append(squadron) return keep_squadrons
self.air_wing.squadrons = keep_squadrons
class AirWingConfigurationDialog(QDialog): class AircraftSquadronsPage(QWidget):
"""Dialog window for air wing configuration.""" def __init__(self, squadrons: list[Squadron]) -> None:
super().__init__()
layout = QVBoxLayout()
self.setLayout(layout)
def __init__(self, game: Game, parent) -> None: self.squadrons_config = SquadronConfigurationLayout(squadrons)
super().__init__(parent)
self.air_wing = game.blue.air_wing
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 = QWidget()
scrolling_widget.setLayout(self.air_wing_config) scrolling_widget.setLayout(self.squadrons_config)
scrolling_area = QScrollArea() scrolling_area = QScrollArea()
scrolling_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) scrolling_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
@ -212,9 +187,112 @@ class AirWingConfigurationDialog(QDialog):
scrolling_area.setWidgetResizable(True) scrolling_area.setWidgetResizable(True)
scrolling_area.setWidget(scrolling_widget) scrolling_area.setWidget(scrolling_widget)
scrolling_layout.addWidget(scrolling_area) layout.addWidget(scrolling_area)
self.setLayout(scrolling_layout)
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. <strong>This is your only opportunity to make changes.</strong>"
"<br /><br />"
"To accept your changes and continue, close this window.<br />"
"<br />"
"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,<br />"
f'see <a style="color:#ffffff" href="{doc_url}">the wiki</a>.'
)
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: def reject(self) -> None:
self.air_wing_config.apply() self.squadrons_panel.apply()
super().reject() super().reject()
def on_aircraft_changed(self, index: QModelIndex) -> None:
self.squadrons_panel.setCurrentIndex(index)