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)