From 9bb986cff9c9865c5687ac4fc170316a8a035a75 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 18 Jun 2021 20:14:44 -0700 Subject: [PATCH] Update *all* buy/sell buttons, not just the row. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1207 --- changelog.md | 1 + qt_ui/windows/basemenu/QRecruitBehaviour.py | 134 +++++++++--------- .../airfield/QAircraftRecruitmentMenu.py | 13 +- .../ground_forces/QArmorRecruitmentMenu.py | 4 +- 4 files changed, 76 insertions(+), 76 deletions(-) diff --git a/changelog.md b/changelog.md index 8586bb3d..b44b55c5 100644 --- a/changelog.md +++ b/changelog.md @@ -22,6 +22,7 @@ Saves from 3.x are not compatible with 4.0. * **[UI]** Added support for Neutral Dot difficulty label * **[UI]** Clear skies at night no longer described as "Sunny" by the weather widget. * **[UI]** Removed ability to buy (useless) ground units at carriers and LHAs. +* **[UI]** Fixed enable/disable of buy/sell buttons. # 3.0.0 diff --git a/qt_ui/windows/basemenu/QRecruitBehaviour.py b/qt_ui/windows/basemenu/QRecruitBehaviour.py index e471e4f5..7c6bf51c 100644 --- a/qt_ui/windows/basemenu/QRecruitBehaviour.py +++ b/qt_ui/windows/basemenu/QRecruitBehaviour.py @@ -1,13 +1,15 @@ +from __future__ import annotations + import logging from PySide2.QtWidgets import ( QGroupBox, QHBoxLayout, QLabel, - QLayout, QPushButton, QSizePolicy, QSpacerItem, + QGridLayout, ) from game.dcs.unittype import UnitType @@ -18,16 +20,68 @@ from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.QUnitInfoWindow import QUnitInfoWindow +class PurchaseGroup(QGroupBox): + def __init__(self, unit_type: UnitType, recruiter: QRecruitBehaviour) -> None: + super().__init__() + self.unit_type = unit_type + self.recruiter = recruiter + + self.setProperty("style", "buy-box") + self.setMaximumHeight(36) + self.setMinimumHeight(36) + layout = QHBoxLayout() + self.setLayout(layout) + + self.sell_button = QPushButton("-") + self.sell_button.setProperty("style", "btn-sell") + self.sell_button.setDisabled(not recruiter.enable_sale(unit_type)) + self.sell_button.setMinimumSize(16, 16) + self.sell_button.setMaximumSize(16, 16) + self.sell_button.setSizePolicy( + QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + ) + + self.sell_button.clicked.connect(lambda: self.recruiter.sell(self.unit_type)) + + self.amount_bought = QLabel() + self.amount_bought.setSizePolicy( + QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + ) + + self.buy_button = QPushButton("+") + self.buy_button.setProperty("style", "btn-buy") + self.buy_button.setDisabled(not recruiter.enable_purchase(unit_type)) + self.buy_button.setMinimumSize(16, 16) + self.buy_button.setMaximumSize(16, 16) + + self.buy_button.clicked.connect(lambda: self.recruiter.buy(self.unit_type)) + self.buy_button.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) + + layout.addWidget(self.sell_button) + layout.addWidget(self.amount_bought) + layout.addWidget(self.buy_button) + + self.update_state() + + @property + def pending_units(self) -> int: + return self.recruiter.pending_deliveries.units.get(self.unit_type, 0) + + def update_state(self) -> None: + self.buy_button.setEnabled(self.recruiter.enable_purchase(self.unit_type)) + self.sell_button.setEnabled(self.recruiter.enable_sale(self.unit_type)) + self.amount_bought.setText(f"{self.pending_units}") + + class QRecruitBehaviour: game_model: GameModel cp: ControlPoint + purchase_groups: dict[UnitType, PurchaseGroup] = {} existing_units_labels = None - bought_amount_labels = None maximum_units = -1 BUDGET_FORMAT = "Available Budget: ${:.2f}M" def __init__(self) -> None: - self.bought_amount_labels = {} self.existing_units_labels = {} self.update_available_budget() @@ -46,9 +100,9 @@ class QRecruitBehaviour: def add_purchase_row( self, unit_type: UnitType, - layout: QLayout, + layout: QGridLayout, row: int, - ) -> int: + ) -> None: exist = QGroupBox() exist.setProperty("style", "buy-box") exist.setMaximumHeight(36) @@ -57,7 +111,6 @@ class QRecruitBehaviour: exist.setLayout(existLayout) existing_units = self.cp.base.total_units_of_type(unit_type) - scheduled_units = self.pending_deliveries.units.get(unit_type, 0) unitName = QLabel(f"{unit_type.name}") unitName.setSizePolicy( @@ -67,49 +120,13 @@ class QRecruitBehaviour: existing_units = QLabel(str(existing_units)) existing_units.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - amount_bought = QLabel("{}".format(str(scheduled_units))) - amount_bought.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - self.existing_units_labels[unit_type] = existing_units - self.bought_amount_labels[unit_type] = amount_bought price = QLabel(f"$ {unit_type.price} M") price.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - buysell = QGroupBox() - buysell.setProperty("style", "buy-box") - buysell.setMaximumHeight(36) - buysell.setMinimumHeight(36) - buysellayout = QHBoxLayout() - buysell.setLayout(buysellayout) - - buy = QPushButton("+") - buy.setProperty("style", "btn-buy") - buy.setDisabled(not self.enable_purchase(unit_type)) - buy.setMinimumSize(16, 16) - buy.setMaximumSize(16, 16) - - def on_buy(): - self.buy(unit_type) - buy.setDisabled(not self.enable_purchase(unit_type)) - sell.setDisabled(not self.enable_sale(unit_type)) - - buy.clicked.connect(on_buy) - buy.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - - sell = QPushButton("-") - sell.setProperty("style", "btn-sell") - sell.setDisabled(not self.enable_sale(unit_type)) - sell.setMinimumSize(16, 16) - sell.setMaximumSize(16, 16) - sell.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) - - def on_sell(): - self.sell(unit_type) - sell.setDisabled(not self.enable_sale(unit_type)) - buy.setDisabled(not self.enable_purchase(unit_type)) - - sell.clicked.connect(on_sell) + purchase_group = PurchaseGroup(unit_type, self) + self.purchase_groups[unit_type] = purchase_group info = QGroupBox() info.setProperty("style", "buy-box") @@ -135,31 +152,12 @@ class QRecruitBehaviour: ) existLayout.addWidget(price) - buysellayout.addWidget(sell) - buysellayout.addWidget(amount_bought) - buysellayout.addWidget(buy) - infolayout.addWidget(unitInfo) layout.addWidget(exist, row, 1) - layout.addWidget(buysell, row, 2) + layout.addWidget(purchase_group, row, 2) layout.addWidget(info, row, 3) - return row + 1 - - def _update_count_label(self, unit_type: UnitType) -> None: - self.bought_amount_labels[unit_type].setText( - "{}".format( - unit_type in self.pending_deliveries.units - and "{}".format(self.pending_deliveries.units[unit_type]) - or "0" - ) - ) - - self.existing_units_labels[unit_type].setText( - "{}".format(self.cp.base.total_units_of_type(unit_type)) - ) - def update_available_budget(self) -> None: GameUpdateSignal.get_instance().updateBudget(self.game_model.game) @@ -170,7 +168,7 @@ class QRecruitBehaviour: self.pending_deliveries.order({unit_type: 1}) self.budget -= unit_type.price - self._update_count_label(unit_type) + self.update_purchase_controls() self.update_available_budget() def sell(self, unit_type: UnitType) -> None: @@ -179,9 +177,13 @@ class QRecruitBehaviour: self.pending_deliveries.sell({unit_type: 1}) if self.pending_deliveries.units[unit_type] == 0: del self.pending_deliveries.units[unit_type] - self._update_count_label(unit_type) + self.update_purchase_controls() self.update_available_budget() + def update_purchase_controls(self) -> None: + for group in self.purchase_groups.values(): + group.update_state() + def enable_purchase(self, unit_type: UnitType) -> bool: return self.budget >= unit_type.price diff --git a/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py b/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py index 7d6f7e80..f4052c2a 100644 --- a/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py +++ b/qt_ui/windows/basemenu/airfield/QAircraftRecruitmentMenu.py @@ -38,9 +38,6 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour): self.hangar_status = QHangarStatus(game_model, self.cp) - self.init_ui() - - def init_ui(self): main_layout = QVBoxLayout() scroll_content = QWidget() @@ -64,11 +61,11 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour): unit_types, key=lambda u: u.name, ) - for unit_type in sorted_units: - row = self.add_purchase_row(unit_type, task_box_layout, row) - stretch = QVBoxLayout() - stretch.addStretch() - task_box_layout.addLayout(stretch, row, 0) + for row, unit_type in enumerate(sorted_units): + self.add_purchase_row(unit_type, task_box_layout, row) + stretch = QVBoxLayout() + stretch.addStretch() + task_box_layout.addLayout(stretch, row, 0) scroll_content.setLayout(task_box_layout) scroll = QScrollArea() diff --git a/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py b/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py index 544d1623..5c8485b2 100644 --- a/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py +++ b/qt_ui/windows/basemenu/ground_forces/QArmorRecruitmentMenu.py @@ -36,8 +36,8 @@ class QArmorRecruitmentMenu(QFrame, QRecruitBehaviour): set(self.game_model.game.faction_for(player=True).ground_units) ) unit_types.sort(key=lambda u: u.name) - for unit_type in unit_types: - row = self.add_purchase_row(unit_type, task_box_layout, row) + for row, unit_type in enumerate(unit_types): + self.add_purchase_row(unit_type, task_box_layout, row) stretch = QVBoxLayout() stretch.addStretch() task_box_layout.addLayout(stretch, row, 0)