mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Merge remote-tracking branch 'khopa/develop' into helipads
# Conflicts: # changelog.md
This commit is contained in:
17
qt_ui/errorreporter.py
Normal file
17
qt_ui/errorreporter.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import logging
|
||||
from collections import Iterator
|
||||
from contextlib import contextmanager
|
||||
from typing import Type
|
||||
|
||||
from PySide2.QtWidgets import QDialog, QMessageBox
|
||||
|
||||
|
||||
@contextmanager
|
||||
def report_errors(
|
||||
title: str, parent: QDialog, error_type: Type[Exception] = Exception
|
||||
) -> Iterator[None]:
|
||||
try:
|
||||
yield
|
||||
except error_type as ex:
|
||||
logging.exception(title)
|
||||
QMessageBox().critical(parent, title, str(ex), QMessageBox.Ok)
|
||||
@@ -13,6 +13,7 @@ from PySide2.QtWidgets import QApplication, QSplashScreen
|
||||
from dcs.payloads import PayloadDirectories
|
||||
|
||||
from game import Game, VERSION, persistency
|
||||
from game.campaignloader.campaign import Campaign
|
||||
from game.data.weapons import WeaponGroup, Pylon, Weapon
|
||||
from game.db import FACTIONS
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
@@ -27,7 +28,6 @@ from qt_ui import (
|
||||
)
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from qt_ui.windows.QLiberationWindow import QLiberationWindow
|
||||
from game.campaignloader.campaign import Campaign
|
||||
from qt_ui.windows.newgame.QNewGameWizard import DEFAULT_BUDGET
|
||||
from qt_ui.windows.preferences.QLiberationFirstStartWindow import (
|
||||
QLiberationFirstStartWindow,
|
||||
@@ -252,7 +252,6 @@ def create_game(
|
||||
start_date=start_date,
|
||||
player_budget=DEFAULT_BUDGET,
|
||||
enemy_budget=DEFAULT_BUDGET,
|
||||
midgame=False,
|
||||
inverted=inverted,
|
||||
no_carrier=False,
|
||||
no_lha=False,
|
||||
|
||||
42
qt_ui/uncaughtexceptionhandler.py
Normal file
42
qt_ui/uncaughtexceptionhandler.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# From https://timlehr.com/python-exception-hooks-with-qt-message-box/
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from PySide2.QtCore import Signal, QObject
|
||||
from PySide2.QtWidgets import QMessageBox, QApplication
|
||||
|
||||
|
||||
class UncaughtExceptionHandler(QObject):
|
||||
_exception_caught = Signal(str, str)
|
||||
|
||||
def __init__(self, parent: QObject):
|
||||
super().__init__(parent)
|
||||
sys.excepthook = self.exception_hook
|
||||
# Use a signal so that the message box always comes from the main thread.
|
||||
self._exception_caught.connect(self.show_exception_box)
|
||||
|
||||
def exception_hook(self, exc_type, exc_value, exc_traceback):
|
||||
if issubclass(exc_type, KeyboardInterrupt):
|
||||
# Ignore keyboard interrupt to support console applications.
|
||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||
return
|
||||
|
||||
logging.exception(
|
||||
"Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)
|
||||
)
|
||||
self._exception_caught.emit(
|
||||
str(exc_value),
|
||||
"".join(traceback.format_exception(exc_type, exc_value, exc_traceback)),
|
||||
)
|
||||
|
||||
def show_exception_box(self, message: str, exception: str) -> None:
|
||||
if QApplication.instance() is not None:
|
||||
QMessageBox().critical(
|
||||
self.parent(),
|
||||
"An unexpected error occurred",
|
||||
"\n".join([message, "", exception]),
|
||||
QMessageBox.Ok,
|
||||
)
|
||||
else:
|
||||
logging.critical("No QApplication instance available.")
|
||||
@@ -10,7 +10,6 @@ from PySide2.QtCore import (
|
||||
)
|
||||
from PySide2.QtGui import QStandardItemModel, QStandardItem, QIcon
|
||||
from PySide2.QtWidgets import (
|
||||
QAbstractItemView,
|
||||
QDialog,
|
||||
QListView,
|
||||
QVBoxLayout,
|
||||
@@ -32,38 +31,7 @@ from game.dcs.aircrafttype import AircraftType
|
||||
from game.squadrons import AirWing, Pilot, Squadron
|
||||
from game.theater import ControlPoint, ConflictTheater
|
||||
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
|
||||
|
||||
|
||||
class SquadronList(QListView):
|
||||
"""List view for displaying the air wing's squadrons."""
|
||||
|
||||
def __init__(self, air_wing_model: AirWingModel) -> None:
|
||||
super().__init__()
|
||||
self.air_wing_model = air_wing_model
|
||||
self.dialog: Optional[SquadronDialog] = None
|
||||
|
||||
self.setIconSize(QSize(91, 24))
|
||||
self.setItemDelegate(SquadronDelegate(self.air_wing_model))
|
||||
self.setModel(self.air_wing_model)
|
||||
self.selectionModel().setCurrentIndex(
|
||||
self.air_wing_model.index(0, 0, QModelIndex()), QItemSelectionModel.Select
|
||||
)
|
||||
|
||||
# self.setIconSize(QSize(91, 24))
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectItems)
|
||||
self.doubleClicked.connect(self.on_double_click)
|
||||
|
||||
def on_double_click(self, index: QModelIndex) -> None:
|
||||
if not index.isValid():
|
||||
return
|
||||
self.dialog = SquadronDialog(
|
||||
SquadronModel(self.air_wing_model.squadron_at_index(index)), self
|
||||
)
|
||||
self.dialog.show()
|
||||
|
||||
|
||||
class AllowedMissionTypeControls(QVBoxLayout):
|
||||
|
||||
@@ -14,12 +14,14 @@ from PySide2.QtWidgets import (
|
||||
QTableWidget,
|
||||
QTableWidgetItem,
|
||||
QWidget,
|
||||
QHBoxLayout,
|
||||
)
|
||||
|
||||
from game.squadrons import Squadron
|
||||
from game.theater import ConflictTheater
|
||||
from gen.flights.flight import Flight
|
||||
from qt_ui.delegates import TwoColumnRowDelegate
|
||||
from qt_ui.models import GameModel, AirWingModel, SquadronModel
|
||||
from qt_ui.models import GameModel, AirWingModel, SquadronModel, AtoModel
|
||||
from qt_ui.windows.SquadronDialog import SquadronDialog
|
||||
|
||||
|
||||
@@ -56,9 +58,16 @@ class SquadronDelegate(TwoColumnRowDelegate):
|
||||
class SquadronList(QListView):
|
||||
"""List view for displaying the air wing's squadrons."""
|
||||
|
||||
def __init__(self, air_wing_model: AirWingModel) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
ato_model: AtoModel,
|
||||
air_wing_model: AirWingModel,
|
||||
theater: ConflictTheater,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.ato_model = ato_model
|
||||
self.air_wing_model = air_wing_model
|
||||
self.theater = theater
|
||||
self.dialog: Optional[SquadronDialog] = None
|
||||
|
||||
self.setIconSize(QSize(91, 24))
|
||||
@@ -76,7 +85,10 @@ class SquadronList(QListView):
|
||||
if not index.isValid():
|
||||
return
|
||||
self.dialog = SquadronDialog(
|
||||
SquadronModel(self.air_wing_model.squadron_at_index(index)), self
|
||||
self.ato_model,
|
||||
SquadronModel(self.air_wing_model.squadron_at_index(index)),
|
||||
self.theater,
|
||||
self,
|
||||
)
|
||||
self.dialog.show()
|
||||
|
||||
@@ -138,30 +150,47 @@ class AircraftInventoryData:
|
||||
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)
|
||||
|
||||
self.only_unallocated = False
|
||||
self.enemy_info = False
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
|
||||
self.only_unallocated_cb = QCheckBox("Unallocated Only?")
|
||||
self.only_unallocated_cb.toggled.connect(self.update_table)
|
||||
checkbox_row = QHBoxLayout()
|
||||
layout.addLayout(checkbox_row)
|
||||
|
||||
layout.addWidget(self.only_unallocated_cb)
|
||||
self.only_unallocated_cb = QCheckBox("Unallocated only")
|
||||
self.only_unallocated_cb.toggled.connect(self.set_only_unallocated)
|
||||
checkbox_row.addWidget(self.only_unallocated_cb)
|
||||
|
||||
self.enemy_info_cb = QCheckBox("Show enemy info")
|
||||
self.enemy_info_cb.toggled.connect(self.set_enemy_info)
|
||||
checkbox_row.addWidget(self.enemy_info_cb)
|
||||
|
||||
checkbox_row.addStretch()
|
||||
|
||||
self.table = QTableWidget()
|
||||
layout.addWidget(self.table)
|
||||
|
||||
self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.table.verticalHeader().setVisible(False)
|
||||
self.update_table(False)
|
||||
self.set_only_unallocated(False)
|
||||
|
||||
def update_table(self, only_unallocated: bool) -> None:
|
||||
def set_only_unallocated(self, value: bool) -> None:
|
||||
self.only_unallocated = value
|
||||
self.update_table()
|
||||
|
||||
def set_enemy_info(self, value: bool) -> None:
|
||||
self.enemy_info = value
|
||||
self.update_table()
|
||||
|
||||
def update_table(self) -> None:
|
||||
self.table.setSortingEnabled(False)
|
||||
self.table.clear()
|
||||
|
||||
inventory_rows = list(self.get_data(only_unallocated))
|
||||
inventory_rows = list(self.get_data())
|
||||
self.table.setRowCount(len(inventory_rows))
|
||||
headers = AircraftInventoryData.headers()
|
||||
self.table.setColumnCount(len(headers))
|
||||
@@ -175,18 +204,19 @@ class AirInventoryView(QWidget):
|
||||
self.table.setSortingEnabled(True)
|
||||
|
||||
def iter_allocated_aircraft(self) -> Iterator[AircraftInventoryData]:
|
||||
for package in self.game_model.game.blue.ato.packages:
|
||||
coalition = self.game_model.game.coalition_for(not self.enemy_info)
|
||||
for package in coalition.ato.packages:
|
||||
for flight in package.flights:
|
||||
yield from AircraftInventoryData.from_flight(flight)
|
||||
|
||||
def iter_unallocated_aircraft(self) -> Iterator[AircraftInventoryData]:
|
||||
game = self.game_model.game
|
||||
for squadron in game.blue.air_wing.iter_squadrons():
|
||||
coalition = self.game_model.game.coalition_for(not self.enemy_info)
|
||||
for squadron in coalition.air_wing.iter_squadrons():
|
||||
yield from AircraftInventoryData.each_untasked_from_squadron(squadron)
|
||||
|
||||
def get_data(self, only_unallocated: bool) -> Iterator[AircraftInventoryData]:
|
||||
def get_data(self) -> Iterator[AircraftInventoryData]:
|
||||
yield from self.iter_unallocated_aircraft()
|
||||
if not only_unallocated:
|
||||
if not self.only_unallocated:
|
||||
yield from self.iter_allocated_aircraft()
|
||||
|
||||
|
||||
@@ -194,7 +224,14 @@ class AirWingTabs(QTabWidget):
|
||||
def __init__(self, game_model: GameModel) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.addTab(SquadronList(game_model.blue_air_wing_model), "Squadrons")
|
||||
self.addTab(
|
||||
SquadronList(
|
||||
game_model.ato_model,
|
||||
game_model.blue_air_wing_model,
|
||||
game_model.game.theater,
|
||||
),
|
||||
"Squadrons",
|
||||
)
|
||||
self.addTab(AirInventoryView(game_model), "Inventory")
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from qt_ui import liberation_install
|
||||
from qt_ui.dialogs import Dialog
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.uiconstants import URLS
|
||||
from qt_ui.uncaughtexceptionhandler import UncaughtExceptionHandler
|
||||
from qt_ui.widgets.QTopPanel import QTopPanel
|
||||
from qt_ui.widgets.ato import QAirTaskingOrderPanel
|
||||
from qt_ui.widgets.map.QLiberationMap import QLiberationMap
|
||||
@@ -42,7 +43,9 @@ from qt_ui.windows.logs.QLogsWindow import QLogsWindow
|
||||
|
||||
class QLiberationWindow(QMainWindow):
|
||||
def __init__(self, game: Optional[Game]) -> None:
|
||||
super(QLiberationWindow, self).__init__()
|
||||
super().__init__()
|
||||
|
||||
self._uncaught_exception_handler = UncaughtExceptionHandler(self)
|
||||
|
||||
self.game = game
|
||||
self.game_model = GameModel(game)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import logging
|
||||
from typing import Callable
|
||||
from typing import Callable, Iterator, Optional
|
||||
|
||||
from PySide2.QtCore import (
|
||||
QItemSelectionModel,
|
||||
@@ -16,12 +16,15 @@ from PySide2.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QCheckBox,
|
||||
QComboBox,
|
||||
)
|
||||
|
||||
from game.squadrons import Pilot
|
||||
from game.squadrons import Pilot, Squadron
|
||||
from game.theater import ControlPoint, ConflictTheater
|
||||
from gen.flights.flight import FlightType
|
||||
from qt_ui.delegates import TwoColumnRowDelegate
|
||||
from qt_ui.models import SquadronModel
|
||||
from qt_ui.errorreporter import report_errors
|
||||
from qt_ui.models import SquadronModel, AtoModel
|
||||
|
||||
|
||||
class PilotDelegate(TwoColumnRowDelegate):
|
||||
@@ -90,12 +93,58 @@ class AutoAssignedTaskControls(QVBoxLayout):
|
||||
self.squadron_model.set_auto_assignable(task, checked)
|
||||
|
||||
|
||||
class SquadronDestinationComboBox(QComboBox):
|
||||
def __init__(self, squadron: Squadron, theater: ConflictTheater) -> None:
|
||||
super().__init__()
|
||||
self.squadron = squadron
|
||||
self.theater = theater
|
||||
|
||||
room = squadron.location.unclaimed_parking()
|
||||
self.addItem(
|
||||
f"Remain at {squadron.location} (room for {room} more aircraft)", None
|
||||
)
|
||||
selected_index: Optional[int] = None
|
||||
for idx, destination in enumerate(sorted(self.iter_destinations(), key=str), 1):
|
||||
if destination == squadron.destination:
|
||||
selected_index = idx
|
||||
room = destination.unclaimed_parking()
|
||||
self.addItem(
|
||||
f"Transfer to {destination} (room for {room} more aircraft)",
|
||||
destination,
|
||||
)
|
||||
|
||||
if squadron.destination is None:
|
||||
selected_index = 0
|
||||
|
||||
if selected_index is not None:
|
||||
self.setCurrentIndex(selected_index)
|
||||
|
||||
def iter_destinations(self) -> Iterator[ControlPoint]:
|
||||
size = self.squadron.expected_size_next_turn
|
||||
for control_point in self.theater.control_points_for(self.squadron.player):
|
||||
if control_point == self:
|
||||
continue
|
||||
if not control_point.can_operate(self.squadron.aircraft):
|
||||
continue
|
||||
if control_point.unclaimed_parking() < size:
|
||||
continue
|
||||
yield control_point
|
||||
|
||||
|
||||
class SquadronDialog(QDialog):
|
||||
"""Dialog window showing a squadron."""
|
||||
|
||||
def __init__(self, squadron_model: SquadronModel, parent) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
ato_model: AtoModel,
|
||||
squadron_model: SquadronModel,
|
||||
theater: ConflictTheater,
|
||||
parent,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self.ato_model = ato_model
|
||||
self.squadron_model = squadron_model
|
||||
self.theater = theater
|
||||
|
||||
self.setMinimumSize(1000, 440)
|
||||
self.setWindowTitle(str(squadron_model.squadron))
|
||||
@@ -117,6 +166,15 @@ class SquadronDialog(QDialog):
|
||||
columns.addWidget(self.pilot_list)
|
||||
|
||||
button_panel = QHBoxLayout()
|
||||
|
||||
self.transfer_destination = SquadronDestinationComboBox(
|
||||
squadron_model.squadron, theater
|
||||
)
|
||||
self.transfer_destination.currentIndexChanged.connect(
|
||||
self.on_destination_changed
|
||||
)
|
||||
button_panel.addWidget(self.transfer_destination)
|
||||
|
||||
button_panel.addStretch()
|
||||
layout.addLayout(button_panel)
|
||||
|
||||
@@ -132,6 +190,19 @@ class SquadronDialog(QDialog):
|
||||
self.toggle_leave_button.clicked.connect(self.toggle_leave)
|
||||
button_panel.addWidget(self.toggle_leave_button, alignment=Qt.AlignRight)
|
||||
|
||||
@property
|
||||
def squadron(self) -> Squadron:
|
||||
return self.squadron_model.squadron
|
||||
|
||||
def on_destination_changed(self, index: int) -> None:
|
||||
with report_errors("Could not change squadron destination", self):
|
||||
destination = self.transfer_destination.itemData(index)
|
||||
if destination is None:
|
||||
self.squadron.cancel_relocation()
|
||||
else:
|
||||
self.squadron.plan_relocation(destination, self.theater)
|
||||
self.ato_model.replace_from_game(player=True)
|
||||
|
||||
def check_disabled_button_states(
|
||||
self, button: QPushButton, index: QModelIndex
|
||||
) -> bool:
|
||||
|
||||
@@ -190,7 +190,7 @@ class QBaseMenu2(QDialog):
|
||||
self.repair_button.setDisabled(True)
|
||||
|
||||
def update_intel_summary(self) -> None:
|
||||
aircraft = self.cp.allocated_aircraft(self.game_model.game).total_present
|
||||
aircraft = self.cp.allocated_aircraft().total_present
|
||||
parking = self.cp.total_aircraft_parking
|
||||
ground_unit_limit = self.cp.frontline_unit_count_limit
|
||||
deployable_unit_info = ""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from PySide2.QtWidgets import QTabWidget
|
||||
|
||||
from game.theater import ControlPoint, OffMapSpawn, Fob
|
||||
from game.theater import ControlPoint, Fob
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.windows.basemenu.DepartingConvoysMenu import DepartingConvoysMenu
|
||||
from qt_ui.windows.basemenu.airfield.QAirfieldCommand import QAirfieldCommand
|
||||
@@ -13,7 +13,7 @@ class QBaseMenuTabs(QTabWidget):
|
||||
super(QBaseMenuTabs, self).__init__()
|
||||
|
||||
if not cp.captured:
|
||||
self.intel = QIntelInfo(cp, game_model.game)
|
||||
self.intel = QIntelInfo(cp)
|
||||
self.addTab(self.intel, "Intel")
|
||||
|
||||
self.departing_convoys = DepartingConvoysMenu(cp, game_model)
|
||||
|
||||
@@ -273,6 +273,8 @@ class UnitTransactionFrame(QFrame, Generic[TransactionItemType]):
|
||||
else:
|
||||
return "Unit can not be sold."
|
||||
|
||||
def info(self, unit_type: UnitType) -> None:
|
||||
self.info_window = QUnitInfoWindow(self.game_model.game, unit_type)
|
||||
def info(self, item: TransactionItemType) -> None:
|
||||
self.info_window = QUnitInfoWindow(
|
||||
self.game_model.game, self.purchase_adapter.unit_type_of(item)
|
||||
)
|
||||
self.info_window.show()
|
||||
|
||||
@@ -21,12 +21,7 @@ from game.purchaseadapter import AircraftPurchaseAdapter
|
||||
|
||||
class QAircraftRecruitmentMenu(UnitTransactionFrame[Squadron]):
|
||||
def __init__(self, cp: ControlPoint, game_model: GameModel) -> None:
|
||||
super().__init__(
|
||||
game_model,
|
||||
AircraftPurchaseAdapter(
|
||||
cp, game_model.game.coalition_for(cp.captured), game_model.game
|
||||
),
|
||||
)
|
||||
super().__init__(game_model, AircraftPurchaseAdapter(cp))
|
||||
self.cp = cp
|
||||
self.game_model = game_model
|
||||
self.purchase_groups = {}
|
||||
@@ -98,7 +93,7 @@ class QHangarStatus(QHBoxLayout):
|
||||
self.setAlignment(Qt.AlignLeft)
|
||||
|
||||
def update_label(self) -> None:
|
||||
next_turn = self.control_point.allocated_aircraft(self.game_model.game)
|
||||
next_turn = self.control_point.allocated_aircraft()
|
||||
max_amount = self.control_point.total_aircraft_parking
|
||||
|
||||
components = [f"{next_turn.total_present} present"]
|
||||
|
||||
@@ -11,22 +11,20 @@ from PySide2.QtWidgets import (
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game import Game
|
||||
from game.theater import ControlPoint
|
||||
|
||||
|
||||
class QIntelInfo(QFrame):
|
||||
def __init__(self, cp: ControlPoint, game: Game):
|
||||
def __init__(self, cp: ControlPoint):
|
||||
super(QIntelInfo, self).__init__()
|
||||
self.cp = cp
|
||||
self.game = game
|
||||
|
||||
layout = QVBoxLayout()
|
||||
scroll_content = QWidget()
|
||||
intel_layout = QVBoxLayout()
|
||||
|
||||
units_by_task: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
|
||||
for unit_type, count in self.cp.allocated_aircraft(game).present.items():
|
||||
for unit_type, count in self.cp.allocated_aircraft().present.items():
|
||||
if count:
|
||||
task_type = unit_type.dcs_unit_type.task_default.name
|
||||
units_by_task[task_type][unit_type.name] += count
|
||||
|
||||
@@ -77,7 +77,7 @@ class AircraftIntelLayout(IntelTableLayout):
|
||||
|
||||
total = 0
|
||||
for control_point in game.theater.control_points_for(player):
|
||||
allocation = control_point.allocated_aircraft(game)
|
||||
allocation = control_point.allocated_aircraft()
|
||||
base_total = allocation.total_present
|
||||
total += base_total
|
||||
if not base_total:
|
||||
|
||||
@@ -85,7 +85,7 @@ class QFlightCreator(QDialog):
|
||||
squadron, initial_size=self.flight_size_spinner.value()
|
||||
)
|
||||
self.roster_editor = FlightRosterEditor(roster)
|
||||
self.flight_size_spinner.valueChanged.connect(self.resize_roster)
|
||||
self.flight_size_spinner.valueChanged.connect(self.roster_editor.resize)
|
||||
self.squadron_selector.currentIndexChanged.connect(self.on_squadron_changed)
|
||||
roster_layout = QHBoxLayout()
|
||||
layout.addLayout(roster_layout)
|
||||
@@ -136,10 +136,6 @@ class QFlightCreator(QDialog):
|
||||
def set_custom_name_text(self, text: str):
|
||||
self.custom_name_text = text
|
||||
|
||||
def resize_roster(self, new_size: int) -> None:
|
||||
self.roster_editor.roster.resize(new_size)
|
||||
self.roster_editor.resize(new_size)
|
||||
|
||||
def verify_form(self) -> Optional[str]:
|
||||
aircraft: Optional[Type[FlyingType]] = self.aircraft_selector.currentData()
|
||||
squadron: Optional[Squadron] = self.squadron_selector.currentData()
|
||||
@@ -182,8 +178,6 @@ class QFlightCreator(QDialog):
|
||||
roster.max_size,
|
||||
task,
|
||||
self.start_type.currentText(),
|
||||
squadron.location,
|
||||
squadron.location,
|
||||
divert,
|
||||
custom_name=self.custom_name_text,
|
||||
roster=roster,
|
||||
@@ -198,7 +192,6 @@ class QFlightCreator(QDialog):
|
||||
self.squadron_selector.update_items(
|
||||
self.task_selector.currentData(), new_aircraft
|
||||
)
|
||||
self.departure.change_aircraft(new_aircraft)
|
||||
self.divert.change_aircraft(new_aircraft)
|
||||
|
||||
def on_departure_changed(self, departure: ControlPoint) -> None:
|
||||
@@ -223,6 +216,7 @@ class QFlightCreator(QDialog):
|
||||
|
||||
def on_squadron_changed(self, index: int) -> None:
|
||||
squadron: Optional[Squadron] = self.squadron_selector.itemData(index)
|
||||
self.update_max_size(self.squadron_selector.aircraft_available)
|
||||
# Clear the roster first so we return the pilots to the pool. This way if we end
|
||||
# up repopulating from the same squadron we'll get the same pilots back.
|
||||
self.roster_editor.replace(None)
|
||||
@@ -230,7 +224,7 @@ class QFlightCreator(QDialog):
|
||||
self.roster_editor.replace(
|
||||
FlightRoster(squadron, self.flight_size_spinner.value())
|
||||
)
|
||||
self.on_departure_changed(squadron.location)
|
||||
self.on_departure_changed(squadron.location)
|
||||
|
||||
def update_max_size(self, available: int) -> None:
|
||||
aircraft = self.aircraft_selector.currentData()
|
||||
|
||||
@@ -176,6 +176,8 @@ class FlightRosterEditor(QVBoxLayout):
|
||||
def resize(self, new_size: int) -> None:
|
||||
if new_size > self.MAX_PILOTS:
|
||||
raise ValueError("A flight may not have more than four pilots.")
|
||||
if self.roster is not None:
|
||||
self.roster.resize(new_size)
|
||||
for controls in self.pilot_controls[:new_size]:
|
||||
controls.enable_and_reset()
|
||||
for controls in self.pilot_controls[new_size:]:
|
||||
|
||||
@@ -65,6 +65,8 @@ class NewGameWizard(QtWidgets.QWizard):
|
||||
logging.info("======================")
|
||||
|
||||
campaign = self.field("selectedCampaign")
|
||||
if campaign is None:
|
||||
campaign = self.theater_page.campaignList.selected_campaign
|
||||
if campaign is None:
|
||||
campaign = self.campaigns[0]
|
||||
|
||||
@@ -94,7 +96,6 @@ class NewGameWizard(QtWidgets.QWizard):
|
||||
enemy_budget=int(self.field("enemy_starting_money")),
|
||||
# QSlider forces integers, so we use 1 to 50 and divide by 10 to
|
||||
# give 0.1 to 5.0.
|
||||
midgame=False,
|
||||
inverted=self.field("invertMap"),
|
||||
no_carrier=self.field("no_carrier"),
|
||||
no_lha=self.field("no_lha"),
|
||||
@@ -300,13 +301,13 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
text="Show incompatible campaigns"
|
||||
)
|
||||
show_incompatible_campaigns_checkbox.setChecked(False)
|
||||
campaignList = QCampaignList(
|
||||
self.campaignList = QCampaignList(
|
||||
campaigns, show_incompatible_campaigns_checkbox.isChecked()
|
||||
)
|
||||
show_incompatible_campaigns_checkbox.toggled.connect(
|
||||
lambda checked: campaignList.setup_content(show_incompatible=checked)
|
||||
lambda checked: self.campaignList.setup_content(show_incompatible=checked)
|
||||
)
|
||||
self.registerField("selectedCampaign", campaignList)
|
||||
self.registerField("selectedCampaign", self.campaignList)
|
||||
|
||||
# Faction description
|
||||
self.campaignMapDescription = QTextEdit("")
|
||||
@@ -366,7 +367,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
template_perf = jinja_env.get_template(
|
||||
"campaign_performance_template_EN.j2"
|
||||
)
|
||||
campaign = campaignList.selected_campaign
|
||||
campaign = self.campaignList.selected_campaign
|
||||
self.setField("selectedCampaign", campaign)
|
||||
if campaign is None:
|
||||
self.campaignMapDescription.setText("No campaign selected")
|
||||
@@ -379,11 +380,13 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
template_perf.render({"performance": campaign.performance})
|
||||
)
|
||||
|
||||
campaignList.selectionModel().setCurrentIndex(
|
||||
campaignList.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows
|
||||
self.campaignList.selectionModel().setCurrentIndex(
|
||||
self.campaignList.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows
|
||||
)
|
||||
|
||||
campaignList.selectionModel().selectionChanged.connect(on_campaign_selected)
|
||||
self.campaignList.selectionModel().selectionChanged.connect(
|
||||
on_campaign_selected
|
||||
)
|
||||
on_campaign_selected()
|
||||
|
||||
docsText = QtWidgets.QLabel(
|
||||
@@ -410,7 +413,7 @@ class TheaterConfiguration(QtWidgets.QWizardPage):
|
||||
|
||||
layout = QtWidgets.QGridLayout()
|
||||
layout.setColumnMinimumWidth(0, 20)
|
||||
layout.addWidget(campaignList, 0, 0, 5, 1)
|
||||
layout.addWidget(self.campaignList, 0, 0, 5, 1)
|
||||
layout.addWidget(show_incompatible_campaigns_checkbox, 5, 0, 1, 1)
|
||||
layout.addWidget(docsText, 6, 0, 1, 1)
|
||||
layout.addWidget(self.campaignMapDescription, 0, 1, 1, 1)
|
||||
|
||||
@@ -22,7 +22,6 @@ from dcs.forcedoptions import ForcedOptions
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game.game import Game
|
||||
from game.infos.information import Information
|
||||
from game.settings import Settings, AutoAtoBehavior
|
||||
from qt_ui.widgets.QLabeledWidget import QLabeledWidget
|
||||
from qt_ui.widgets.spinsliders import TenthsSpinSlider, TimeInputs
|
||||
@@ -894,18 +893,6 @@ class QSettingsWindow(QDialog):
|
||||
def cheatMoney(self, amount):
|
||||
logging.info("CHEATING FOR AMOUNT : " + str(amount) + "M")
|
||||
self.game.blue.budget += amount
|
||||
if amount > 0:
|
||||
self.game.informations.append(
|
||||
Information(
|
||||
"CHEATER",
|
||||
"You are a cheater and you should feel bad",
|
||||
self.game.turn,
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.game.informations.append(
|
||||
Information("CHEATER", "You are still a cheater !", self.game.turn)
|
||||
)
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
|
||||
def applySettings(self):
|
||||
|
||||
Reference in New Issue
Block a user