From a888397beff7916e5b3043c4fe3175c6e9c994be Mon Sep 17 00:00:00 2001 From: bgreman <47828384+bgreman@users.noreply.github.com> Date: Sun, 30 May 2021 16:40:51 -0400 Subject: [PATCH] Add a global air inventory view to air wing dialog. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/428. --- changelog.md | 1 + qt_ui/windows/AirWingDialog.py | 106 +++++++++++++++++++++++++++- resources/stylesheets/style-dcs.css | 5 -- 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/changelog.md b/changelog.md index c05ab8a1..88fc71ab 100644 --- a/changelog.md +++ b/changelog.md @@ -26,6 +26,7 @@ Saves from 2.5 are not compatible with 3.0. * **[UI]** Added new web based map UI. This is mostly functional but many of the old display options are a WIP. Revert to the old map with --old-map. * **[UI]** Campaigns generated for an older or newer version of the game will now be marked as incompatible. They can still be played, but bugs may be present. * **[UI]** DCS loadouts are now selectable in the loadout setup menu. +* **[UI]** Added global aircraft inventory view under Air Wing dialog. * **[UI]** Base menu now shows information about ground unit deployment limits. * **[Modding]** Campaigns now choose locations for factories to spawn. * **[Modding]** Campaigns now use map structures as strike targets. diff --git a/qt_ui/windows/AirWingDialog.py b/qt_ui/windows/AirWingDialog.py index 17e4dcc1..b117cbce 100644 --- a/qt_ui/windows/AirWingDialog.py +++ b/qt_ui/windows/AirWingDialog.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Type from PySide2.QtCore import ( QItemSelectionModel, @@ -8,11 +8,18 @@ from PySide2.QtCore import ( ) from PySide2.QtWidgets import ( QAbstractItemView, + QCheckBox, QDialog, QListView, QVBoxLayout, + QTabWidget, + QTableWidget, + QTableWidgetItem, + QWidget, ) +from dcs.unittype import FlyingType + from game import db from game.squadrons import Squadron from qt_ui.delegates import TwoColumnRowDelegate @@ -75,6 +82,101 @@ class SquadronList(QListView): self.dialog.show() +class AirInventoryView(QWidget): + def __init__(self, game_model: GameModel) -> None: + super().__init__() + + self.game_model = game_model + self.country = self.game_model.game.country_for(player=True) + + layout = QVBoxLayout() + self.setLayout(layout) + + self.only_unallocated_cb = QCheckBox("Unallocated Only?") + self.only_unallocated_cb.toggled.connect(self.update_table) + + layout.addWidget(self.only_unallocated_cb) + + self.table = QTableWidget() + layout.addWidget(self.table) + + self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.table.verticalHeader().setVisible(False) + self.update_table(False) + + def update_table(self, only_unallocated: bool) -> None: + CP_COLUMN = 0 + UNIT_TYPE_COLUMN = 1 + FLIGHT_TYPE_COLUMN = 2 + TARGET_NAME_COLUMN = 3 + + self.table.setSortingEnabled(False) + self.table.clear() + + inventory_rows = self.get_data(only_unallocated) + self.table.setRowCount(len(inventory_rows)) + self.table.setColumnCount(4) + self.table.setHorizontalHeaderLabels(["Base", "Type", "Flight Type", "Target"]) + + for idx, inv_row in enumerate(inventory_rows): + self.table.setItem(idx, CP_COLUMN, QTableWidgetItem(inv_row[CP_COLUMN])) + self.table.setItem( + idx, UNIT_TYPE_COLUMN, QTableWidgetItem(inv_row[UNIT_TYPE_COLUMN]) + ) + self.table.setItem( + idx, FLIGHT_TYPE_COLUMN, QTableWidgetItem(inv_row[FLIGHT_TYPE_COLUMN]) + ) + self.table.setItem( + idx, TARGET_NAME_COLUMN, QTableWidgetItem(inv_row[TARGET_NAME_COLUMN]) + ) + + self.table.resizeColumnsToContents() + self.table.setSortingEnabled(True) + + def get_data(self, only_unallocated: bool) -> list[list[str]]: + game = self.game_model.game + ato = game.blue_ato + inventory_rows = [] + + for cp in game.theater.controlpoints: + if cp.captured: + cp_name = cp.name + + # Allocated aircraft + if not only_unallocated: + for package in ato.packages: + for flight in package.flights: + if flight.from_cp == cp: + unit_type_name = self.format_unit_type(flight.unit_type) + num_units = flight.count + flight_type = flight.flight_type.value + target = flight.package.target.name + for _ in range(0, num_units): + inventory_rows.append( + [cp_name, unit_type_name, flight_type, target] + ) + + # Unallocated aircraft + inventory = game.aircraft_inventory.for_control_point(cp) + for unit_type, num_units in inventory.all_aircraft: + unit_type_name = self.format_unit_type(unit_type) + for _ in range(0, num_units): + inventory_rows.append([cp_name, unit_type_name, "Idle", "None"]) + + return inventory_rows + + def format_unit_type(self, aircraft: Type[FlyingType]) -> str: + return db.unit_get_expanded_info(self.country, aircraft, "name") + + +class AirWingTabs(QTabWidget): + def __init__(self, game_model: GameModel) -> None: + super().__init__() + + self.addTab(SquadronList(game_model.blue_air_wing_model), "Squadrons") + self.addTab(AirInventoryView(game_model), "Inventory") + + class AirWingDialog(QDialog): """Dialog window showing the player's air wing.""" @@ -89,4 +191,4 @@ class AirWingDialog(QDialog): layout = QVBoxLayout() self.setLayout(layout) - layout.addWidget(SquadronList(self.air_wing_model)) + layout.addWidget(AirWingTabs(game_model)) diff --git a/resources/stylesheets/style-dcs.css b/resources/stylesheets/style-dcs.css index 22945244..a68eb866 100644 --- a/resources/stylesheets/style-dcs.css +++ b/resources/stylesheets/style-dcs.css @@ -515,11 +515,6 @@ QHeaderView::section:vertical background: #4B5B74; } -QTableWidget { - gridline-color: red; - background: #4B5B74; -} - QTableView QTableCornerButton::section { background: #4B5B74; }