mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Merge branch 'develop' of https://github.com/khopa/dcs_liberation into develop
Conflicts: qt_ui/widgets/map/QLiberationMap.py
This commit is contained in:
commit
a0ff78a810
@ -58,7 +58,7 @@ class Dialog:
|
|||||||
flight: Flight) -> None:
|
flight: Flight) -> None:
|
||||||
"""Opens the dialog to edit the given flight."""
|
"""Opens the dialog to edit the given flight."""
|
||||||
cls.edit_flight_dialog = QEditFlightDialog(
|
cls.edit_flight_dialog = QEditFlightDialog(
|
||||||
cls.game_model.game,
|
cls.game_model,
|
||||||
package_model.package,
|
package_model.package,
|
||||||
flight
|
flight
|
||||||
)
|
)
|
||||||
|
|||||||
64
qt_ui/displayoptions.py
Normal file
64
qt_ui/displayoptions.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
"""Visibility options for the game map."""
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Iterator, Optional, Union
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DisplayRule:
|
||||||
|
name: str
|
||||||
|
_value: bool
|
||||||
|
|
||||||
|
@property
|
||||||
|
def menu_text(self) -> str:
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> bool:
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value: bool) -> None:
|
||||||
|
from qt_ui.widgets.map.QLiberationMap import QLiberationMap
|
||||||
|
self._value = value
|
||||||
|
QLiberationMap.instance.reload_scene()
|
||||||
|
QLiberationMap.instance.update()
|
||||||
|
|
||||||
|
def __bool__(self) -> bool:
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayGroup:
|
||||||
|
def __init__(self, name: Optional[str]) -> None:
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __iter__(self) -> Iterator[DisplayRule]:
|
||||||
|
# Python 3.6 enforces that __dict__ is order preserving by default.
|
||||||
|
for value in self.__dict__.values():
|
||||||
|
if isinstance(value, DisplayRule):
|
||||||
|
yield value
|
||||||
|
|
||||||
|
|
||||||
|
class FlightPathOptions(DisplayGroup):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__("Flight Paths")
|
||||||
|
self.hide = DisplayRule("Hide Flight Paths", True)
|
||||||
|
self.only_selected = DisplayRule("Show Selected Flight Path", False)
|
||||||
|
self.all = DisplayRule("Show All Flight Paths", False)
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayOptions:
|
||||||
|
ground_objects = DisplayRule("Ground Objects", True)
|
||||||
|
control_points = DisplayRule("Control Points", True)
|
||||||
|
lines = DisplayRule("Lines", True)
|
||||||
|
events = DisplayRule("Events", True)
|
||||||
|
sam_ranges = DisplayRule("SAM Ranges", True)
|
||||||
|
flight_paths = FlightPathOptions()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def menu_items(cls) -> Iterator[Union[DisplayGroup, DisplayRule]]:
|
||||||
|
# Python 3.6 enforces that __dict__ is order preserving by default.
|
||||||
|
for value in cls.__dict__.values():
|
||||||
|
if isinstance(value, DisplayRule):
|
||||||
|
yield value
|
||||||
|
elif isinstance(value, DisplayGroup):
|
||||||
|
yield value
|
||||||
@ -95,6 +95,8 @@ class NullListModel(QAbstractListModel):
|
|||||||
class PackageModel(QAbstractListModel):
|
class PackageModel(QAbstractListModel):
|
||||||
"""The model for an ATO package."""
|
"""The model for an ATO package."""
|
||||||
|
|
||||||
|
FlightRole = Qt.UserRole
|
||||||
|
|
||||||
#: Emitted when this package is being deleted from the ATO.
|
#: Emitted when this package is being deleted from the ATO.
|
||||||
deleted = Signal()
|
deleted = Signal()
|
||||||
|
|
||||||
@ -113,6 +115,8 @@ class PackageModel(QAbstractListModel):
|
|||||||
return self.text_for_flight(flight)
|
return self.text_for_flight(flight)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
return self.icon_for_flight(flight)
|
return self.icon_for_flight(flight)
|
||||||
|
elif role == PackageModel.FlightRole:
|
||||||
|
return flight
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -185,6 +189,8 @@ class AtoModel(QAbstractListModel):
|
|||||||
|
|
||||||
PackageRole = Qt.UserRole
|
PackageRole = Qt.UserRole
|
||||||
|
|
||||||
|
client_slots_changed = Signal()
|
||||||
|
|
||||||
def __init__(self, game: Optional[Game], ato: AirTaskingOrder) -> None:
|
def __init__(self, game: Optional[Game], ato: AirTaskingOrder) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.game = game
|
self.game = game
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
"""A layout containing a widget with an associated label."""
|
"""A layout containing a widget with an associated label."""
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget
|
from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget
|
||||||
|
|
||||||
@ -10,8 +12,13 @@ class QLabeledWidget(QHBoxLayout):
|
|||||||
label is used to name the input.
|
label is used to name the input.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, text: str, widget: QWidget) -> None:
|
def __init__(self, text: str, widget: QWidget,
|
||||||
|
tooltip: Optional[str]) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.addWidget(QLabel(text))
|
label = QLabel(text)
|
||||||
|
self.addWidget(label)
|
||||||
self.addStretch()
|
self.addStretch()
|
||||||
self.addWidget(widget, alignment=Qt.AlignRight)
|
self.addWidget(widget, alignment=Qt.AlignRight)
|
||||||
|
if tooltip is not None:
|
||||||
|
label.setToolTip(tooltip)
|
||||||
|
widget.setToolTip(tooltip)
|
||||||
|
|||||||
@ -11,9 +11,11 @@ from PySide2.QtWidgets import (
|
|||||||
import qt_ui.uiconstants as CONST
|
import qt_ui.uiconstants as CONST
|
||||||
from game import Game
|
from game import Game
|
||||||
from game.event import CAP, CAS, FrontlineAttackEvent
|
from game.event import CAP, CAS, FrontlineAttackEvent
|
||||||
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
from qt_ui.widgets.QBudgetBox import QBudgetBox
|
||||||
from qt_ui.widgets.QFactionsInfos import QFactionsInfos
|
from qt_ui.widgets.QFactionsInfos import QFactionsInfos
|
||||||
from qt_ui.widgets.QTurnCounter import QTurnCounter
|
from qt_ui.widgets.QTurnCounter import QTurnCounter
|
||||||
|
from qt_ui.widgets.clientslots import MaxPlayerCount
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
from qt_ui.windows.QWaitingForMissionResultWindow import \
|
from qt_ui.windows.QWaitingForMissionResultWindow import \
|
||||||
QWaitingForMissionResultWindow
|
QWaitingForMissionResultWindow
|
||||||
@ -23,14 +25,18 @@ from qt_ui.windows.stats.QStatsWindow import QStatsWindow
|
|||||||
|
|
||||||
class QTopPanel(QFrame):
|
class QTopPanel(QFrame):
|
||||||
|
|
||||||
def __init__(self, game: Game):
|
def __init__(self, game_model: GameModel):
|
||||||
super(QTopPanel, self).__init__()
|
super(QTopPanel, self).__init__()
|
||||||
self.game = game
|
self.game_model = game_model
|
||||||
self.setMaximumHeight(70)
|
self.setMaximumHeight(70)
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
GameUpdateSignal.get_instance().gameupdated.connect(self.setGame)
|
GameUpdateSignal.get_instance().gameupdated.connect(self.setGame)
|
||||||
GameUpdateSignal.get_instance().budgetupdated.connect(self.budget_update)
|
GameUpdateSignal.get_instance().budgetupdated.connect(self.budget_update)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def game(self) -> Optional[Game]:
|
||||||
|
return self.game_model.game
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
|
|
||||||
self.turnCounter = QTurnCounter()
|
self.turnCounter = QTurnCounter()
|
||||||
@ -68,6 +74,8 @@ class QTopPanel(QFrame):
|
|||||||
|
|
||||||
self.proceedBox = QGroupBox("Proceed")
|
self.proceedBox = QGroupBox("Proceed")
|
||||||
self.proceedBoxLayout = QHBoxLayout()
|
self.proceedBoxLayout = QHBoxLayout()
|
||||||
|
self.proceedBoxLayout.addLayout(
|
||||||
|
MaxPlayerCount(self.game_model.ato_model))
|
||||||
self.proceedBoxLayout.addWidget(self.passTurnButton)
|
self.proceedBoxLayout.addWidget(self.passTurnButton)
|
||||||
self.proceedBoxLayout.addWidget(self.proceedButton)
|
self.proceedBoxLayout.addWidget(self.proceedButton)
|
||||||
self.proceedBox.setLayout(self.proceedBoxLayout)
|
self.proceedBox.setLayout(self.proceedBoxLayout)
|
||||||
@ -84,16 +92,17 @@ class QTopPanel(QFrame):
|
|||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def setGame(self, game: Optional[Game]):
|
def setGame(self, game: Optional[Game]):
|
||||||
self.game = game
|
if game is None:
|
||||||
if game is not None:
|
return
|
||||||
self.turnCounter.setCurrentTurn(self.game.turn, self.game.current_day)
|
|
||||||
self.budgetBox.setGame(self.game)
|
|
||||||
self.factionsInfos.setGame(self.game)
|
|
||||||
|
|
||||||
if self.game and self.game.turn == 0:
|
self.turnCounter.setCurrentTurn(self.game.turn, self.game.current_day)
|
||||||
self.proceedButton.setEnabled(False)
|
self.budgetBox.setGame(self.game)
|
||||||
else:
|
self.factionsInfos.setGame(self.game)
|
||||||
self.proceedButton.setEnabled(True)
|
|
||||||
|
if self.game and self.game.turn == 0:
|
||||||
|
self.proceedButton.setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.proceedButton.setEnabled(True)
|
||||||
|
|
||||||
def openSettings(self):
|
def openSettings(self):
|
||||||
self.subwindow = QSettingsWindow(self.game)
|
self.subwindow = QSettingsWindow(self.game)
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from PySide2.QtCore import (
|
|||||||
QSize,
|
QSize,
|
||||||
Qt,
|
Qt,
|
||||||
)
|
)
|
||||||
from PySide2.QtGui import QFont, QFontMetrics, QPainter
|
from PySide2.QtGui import QFont, QFontMetrics, QIcon, QPainter
|
||||||
from PySide2.QtWidgets import (
|
from PySide2.QtWidgets import (
|
||||||
QAbstractItemView,
|
QAbstractItemView,
|
||||||
QGroupBox,
|
QGroupBox,
|
||||||
@ -18,15 +18,109 @@ from PySide2.QtWidgets import (
|
|||||||
QListView,
|
QListView,
|
||||||
QPushButton,
|
QPushButton,
|
||||||
QSplitter,
|
QSplitter,
|
||||||
QStyleOptionViewItem, QStyledItemDelegate, QVBoxLayout,
|
QStyle, QStyleOptionViewItem, QStyledItemDelegate, QVBoxLayout,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from game import db
|
||||||
from gen.ato import Package
|
from gen.ato import Package
|
||||||
from gen.flights.flight import Flight
|
from gen.flights.flight import Flight
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
from ..models import AtoModel, GameModel, NullListModel, PackageModel
|
from ..models import AtoModel, GameModel, NullListModel, PackageModel
|
||||||
|
|
||||||
|
|
||||||
|
class FlightDelegate(QStyledItemDelegate):
|
||||||
|
FONT_SIZE = 10
|
||||||
|
HMARGIN = 4
|
||||||
|
VMARGIN = 4
|
||||||
|
|
||||||
|
def get_font(self, option: QStyleOptionViewItem) -> QFont:
|
||||||
|
font = QFont(option.font)
|
||||||
|
font.setPointSize(self.FONT_SIZE)
|
||||||
|
return font
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def flight(index: QModelIndex) -> Flight:
|
||||||
|
return index.data(PackageModel.FlightRole)
|
||||||
|
|
||||||
|
def first_row_text(self, index: QModelIndex) -> str:
|
||||||
|
flight = self.flight(index)
|
||||||
|
task = flight.flight_type.name
|
||||||
|
count = flight.count
|
||||||
|
name = db.unit_type_name(flight.unit_type)
|
||||||
|
delay = flight.scheduled_in
|
||||||
|
return f"[{task}] {count} x {name} in {delay} minutes"
|
||||||
|
|
||||||
|
def second_row_text(self, index: QModelIndex) -> str:
|
||||||
|
flight = self.flight(index)
|
||||||
|
origin = flight.from_cp.name
|
||||||
|
return f"From {origin}"
|
||||||
|
|
||||||
|
def paint(self, painter: QPainter, option: QStyleOptionViewItem,
|
||||||
|
index: QModelIndex) -> None:
|
||||||
|
# Draw the list item with all the default selection styling, but with an
|
||||||
|
# invalid index so text formatting is left to us.
|
||||||
|
super().paint(painter, option, QModelIndex())
|
||||||
|
|
||||||
|
rect = option.rect.adjusted(self.HMARGIN, self.VMARGIN, -self.HMARGIN,
|
||||||
|
-self.VMARGIN)
|
||||||
|
|
||||||
|
with painter_context(painter):
|
||||||
|
painter.setFont(self.get_font(option))
|
||||||
|
|
||||||
|
icon: Optional[QIcon] = index.data(Qt.DecorationRole)
|
||||||
|
if icon is not None:
|
||||||
|
icon.paint(painter, rect, Qt.AlignLeft | Qt.AlignVCenter,
|
||||||
|
self.icon_mode(option),
|
||||||
|
self.icon_state(option))
|
||||||
|
|
||||||
|
rect = rect.adjusted(self.icon_size(option).width() + self.HMARGIN,
|
||||||
|
0, 0, 0)
|
||||||
|
painter.drawText(rect, Qt.AlignLeft, self.first_row_text(index))
|
||||||
|
line2 = rect.adjusted(0, rect.height() / 2, 0, rect.height() / 2)
|
||||||
|
painter.drawText(line2, Qt.AlignLeft, self.second_row_text(index))
|
||||||
|
|
||||||
|
clients = self.num_clients(index)
|
||||||
|
if clients:
|
||||||
|
painter.drawText(rect, Qt.AlignRight,
|
||||||
|
f"Player Slots: {clients}")
|
||||||
|
|
||||||
|
def num_clients(self, index: QModelIndex) -> int:
|
||||||
|
flight = self.flight(index)
|
||||||
|
return flight.client_count
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def icon_mode(option: QStyleOptionViewItem) -> QIcon.Mode:
|
||||||
|
if not (option.state & QStyle.State_Enabled):
|
||||||
|
return QIcon.Disabled
|
||||||
|
elif option.state & QStyle.State_Selected:
|
||||||
|
return QIcon.Selected
|
||||||
|
elif option.state & QStyle.State_Active:
|
||||||
|
return QIcon.Active
|
||||||
|
return QIcon.Normal
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def icon_state(option: QStyleOptionViewItem) -> QIcon.State:
|
||||||
|
return QIcon.On if option.state & QStyle.State_Open else QIcon.Off
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def icon_size(option: QStyleOptionViewItem) -> QSize:
|
||||||
|
icon_size: Optional[QSize] = option.decorationSize
|
||||||
|
if icon_size is None:
|
||||||
|
return QSize(0, 0)
|
||||||
|
else:
|
||||||
|
return icon_size
|
||||||
|
|
||||||
|
def sizeHint(self, option: QStyleOptionViewItem,
|
||||||
|
index: QModelIndex) -> QSize:
|
||||||
|
left = self.icon_size(option).width() + self.HMARGIN
|
||||||
|
metrics = QFontMetrics(self.get_font(option))
|
||||||
|
first = metrics.size(0, self.first_row_text(index))
|
||||||
|
second = metrics.size(0, self.second_row_text(index))
|
||||||
|
text_width = max(first.width(), second.width())
|
||||||
|
return QSize(left + text_width + 2 * self.HMARGIN,
|
||||||
|
first.height() + second.height() + 2 * self.VMARGIN)
|
||||||
|
|
||||||
|
|
||||||
class QFlightList(QListView):
|
class QFlightList(QListView):
|
||||||
"""List view for displaying the flights of a package."""
|
"""List view for displaying the flights of a package."""
|
||||||
|
|
||||||
@ -34,6 +128,7 @@ class QFlightList(QListView):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.package_model = model
|
self.package_model = model
|
||||||
self.set_package(model)
|
self.set_package(model)
|
||||||
|
self.setItemDelegate(FlightDelegate())
|
||||||
self.setIconSize(QSize(91, 24))
|
self.setIconSize(QSize(91, 24))
|
||||||
self.setSelectionBehavior(QAbstractItemView.SelectItems)
|
self.setSelectionBehavior(QAbstractItemView.SelectItems)
|
||||||
|
|
||||||
@ -109,6 +204,7 @@ class QFlightPanel(QGroupBox):
|
|||||||
"""Sets the package model to display."""
|
"""Sets the package model to display."""
|
||||||
self.package_model = model
|
self.package_model = model
|
||||||
self.flight_list.set_package(model)
|
self.flight_list.set_package(model)
|
||||||
|
self.selection_changed.connect(self.on_selection_changed)
|
||||||
self.on_selection_changed()
|
self.on_selection_changed()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -122,6 +218,15 @@ class QFlightPanel(QGroupBox):
|
|||||||
enabled = index.isValid()
|
enabled = index.isValid()
|
||||||
self.edit_button.setEnabled(enabled)
|
self.edit_button.setEnabled(enabled)
|
||||||
self.delete_button.setEnabled(enabled)
|
self.delete_button.setEnabled(enabled)
|
||||||
|
self.change_map_flight_selection(index)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def change_map_flight_selection(index: QModelIndex) -> None:
|
||||||
|
if not index.isValid():
|
||||||
|
GameUpdateSignal.get_instance().select_flight(None)
|
||||||
|
return
|
||||||
|
|
||||||
|
GameUpdateSignal.get_instance().select_flight(index.row())
|
||||||
|
|
||||||
def on_edit(self) -> None:
|
def on_edit(self) -> None:
|
||||||
"""Opens the flight edit dialog."""
|
"""Opens the flight edit dialog."""
|
||||||
@ -196,6 +301,15 @@ class PackageDelegate(QStyledItemDelegate):
|
|||||||
line2 = rect.adjusted(0, rect.height() / 2, 0, rect.height() / 2)
|
line2 = rect.adjusted(0, rect.height() / 2, 0, rect.height() / 2)
|
||||||
painter.drawText(line2, Qt.AlignLeft, self.right_text(index))
|
painter.drawText(line2, Qt.AlignLeft, self.right_text(index))
|
||||||
|
|
||||||
|
clients = self.num_clients(index)
|
||||||
|
if clients:
|
||||||
|
painter.drawText(rect, Qt.AlignRight,
|
||||||
|
f"Player Slots: {clients}")
|
||||||
|
|
||||||
|
def num_clients(self, index: QModelIndex) -> int:
|
||||||
|
package = self.package(index)
|
||||||
|
return sum(f.client_count for f in package.flights)
|
||||||
|
|
||||||
def sizeHint(self, option: QStyleOptionViewItem,
|
def sizeHint(self, option: QStyleOptionViewItem,
|
||||||
index: QModelIndex) -> QSize:
|
index: QModelIndex) -> QSize:
|
||||||
metrics = QFontMetrics(self.get_font(option))
|
metrics = QFontMetrics(self.get_font(option))
|
||||||
@ -270,6 +384,18 @@ class QPackagePanel(QGroupBox):
|
|||||||
enabled = index.isValid()
|
enabled = index.isValid()
|
||||||
self.edit_button.setEnabled(enabled)
|
self.edit_button.setEnabled(enabled)
|
||||||
self.delete_button.setEnabled(enabled)
|
self.delete_button.setEnabled(enabled)
|
||||||
|
self.change_map_package_selection(index)
|
||||||
|
|
||||||
|
def change_map_package_selection(self, index: QModelIndex) -> None:
|
||||||
|
if not index.isValid():
|
||||||
|
GameUpdateSignal.get_instance().select_package(None)
|
||||||
|
return
|
||||||
|
|
||||||
|
package = self.ato_model.get_package_model(index)
|
||||||
|
if package.rowCount() == 0:
|
||||||
|
GameUpdateSignal.get_instance().select_package(None)
|
||||||
|
else:
|
||||||
|
GameUpdateSignal.get_instance().select_package(index.row())
|
||||||
|
|
||||||
def on_edit(self) -> None:
|
def on_edit(self) -> None:
|
||||||
"""Opens the package edit dialog."""
|
"""Opens the package edit dialog."""
|
||||||
|
|||||||
28
qt_ui/widgets/clientslots.py
Normal file
28
qt_ui/widgets/clientslots.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""Widgets for displaying client slots."""
|
||||||
|
from PySide2.QtWidgets import QLabel
|
||||||
|
|
||||||
|
from qt_ui.models import AtoModel
|
||||||
|
from qt_ui.widgets.QLabeledWidget import QLabeledWidget
|
||||||
|
|
||||||
|
|
||||||
|
class MaxPlayerCount(QLabeledWidget):
|
||||||
|
def __init__(self, ato_model: AtoModel) -> None:
|
||||||
|
self.ato_model = ato_model
|
||||||
|
self.slots_label = QLabel(str(self.count_client_slots))
|
||||||
|
self.ato_model.client_slots_changed.connect(self.update_count)
|
||||||
|
super().__init__(
|
||||||
|
"Max Players:", self.slots_label,
|
||||||
|
("Total number of client slots. To add client slots, edit a flight "
|
||||||
|
"using the panel on the left.")
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def count_client_slots(self) -> int:
|
||||||
|
slots = 0
|
||||||
|
for package in self.ato_model.packages:
|
||||||
|
for flight in package.flights:
|
||||||
|
slots += flight.client_count
|
||||||
|
return slots
|
||||||
|
|
||||||
|
def update_count(self) -> None:
|
||||||
|
self.slots_label.setText(str(self.count_client_slots))
|
||||||
@ -1,5 +1,7 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtGui import QBrush, QColor, QPen, QPixmap, QWheelEvent
|
from PySide2.QtGui import QBrush, QColor, QPen, QPixmap, QWheelEvent
|
||||||
@ -19,11 +21,12 @@ from game.data.aaa_db import AAA_UNITS
|
|||||||
from game.data.radar_db import UNITS_WITH_RADAR
|
from game.data.radar_db import UNITS_WITH_RADAR
|
||||||
from gen import Conflict
|
from gen import Conflict
|
||||||
from gen.flights.flight import Flight
|
from gen.flights.flight import Flight
|
||||||
|
from qt_ui.displayoptions import DisplayOptions
|
||||||
from qt_ui.models import GameModel
|
from qt_ui.models import GameModel
|
||||||
|
from qt_ui.widgets.map.QFrontLine import QFrontLine
|
||||||
from qt_ui.widgets.map.QLiberationScene import QLiberationScene
|
from qt_ui.widgets.map.QLiberationScene import QLiberationScene
|
||||||
from qt_ui.widgets.map.QMapControlPoint import QMapControlPoint
|
from qt_ui.widgets.map.QMapControlPoint import QMapControlPoint
|
||||||
from qt_ui.widgets.map.QMapGroundObject import QMapGroundObject
|
from qt_ui.widgets.map.QMapGroundObject import QMapGroundObject
|
||||||
from qt_ui.widgets.map.QFrontLine import QFrontLine
|
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
from theater import ControlPoint, FrontLine
|
from theater import ControlPoint, FrontLine
|
||||||
|
|
||||||
@ -31,15 +34,7 @@ from theater import ControlPoint, FrontLine
|
|||||||
class QLiberationMap(QGraphicsView):
|
class QLiberationMap(QGraphicsView):
|
||||||
WAYPOINT_SIZE = 4
|
WAYPOINT_SIZE = 4
|
||||||
|
|
||||||
instance = None
|
instance: Optional[QLiberationMap] = None
|
||||||
display_rules: Dict[str, bool] = {
|
|
||||||
"cp": True,
|
|
||||||
"go": True,
|
|
||||||
"lines": True,
|
|
||||||
"events": True,
|
|
||||||
"sam": True,
|
|
||||||
"flight_paths": False
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, game_model: GameModel):
|
def __init__(self, game_model: GameModel):
|
||||||
super(QLiberationMap, self).__init__()
|
super(QLiberationMap, self).__init__()
|
||||||
@ -48,6 +43,8 @@ class QLiberationMap(QGraphicsView):
|
|||||||
self.game: Optional[Game] = game_model.game
|
self.game: Optional[Game] = game_model.game
|
||||||
|
|
||||||
self.flight_path_items: List[QGraphicsItem] = []
|
self.flight_path_items: List[QGraphicsItem] = []
|
||||||
|
# A tuple of (package index, flight index), or none.
|
||||||
|
self.selected_flight: Optional[Tuple[int, int]] = None
|
||||||
|
|
||||||
self.setMinimumSize(800,600)
|
self.setMinimumSize(800,600)
|
||||||
self.setMaximumHeight(2160)
|
self.setMaximumHeight(2160)
|
||||||
@ -62,6 +59,25 @@ class QLiberationMap(QGraphicsView):
|
|||||||
lambda: self.draw_flight_plans(self.scene())
|
lambda: self.draw_flight_plans(self.scene())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def update_package_selection(index: Optional[int]) -> None:
|
||||||
|
self.selected_flight = index, 0
|
||||||
|
self.draw_flight_plans(self.scene())
|
||||||
|
|
||||||
|
GameUpdateSignal.get_instance().package_selection_changed.connect(
|
||||||
|
update_package_selection
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_flight_selection(index: Optional[int]) -> None:
|
||||||
|
if self.selected_flight is None:
|
||||||
|
logging.error("Flight was selected with no package selected")
|
||||||
|
return
|
||||||
|
self.selected_flight = self.selected_flight[0], index
|
||||||
|
self.draw_flight_plans(self.scene())
|
||||||
|
|
||||||
|
GameUpdateSignal.get_instance().flight_selection_changed.connect(
|
||||||
|
update_flight_selection
|
||||||
|
)
|
||||||
|
|
||||||
def init_scene(self):
|
def init_scene(self):
|
||||||
scene = QLiberationScene(self)
|
scene = QLiberationScene(self)
|
||||||
self.setScene(scene)
|
self.setScene(scene)
|
||||||
@ -162,7 +178,8 @@ class QLiberationMap(QGraphicsView):
|
|||||||
buildings = self.game.theater.find_ground_objects_by_obj_name(ground_object.obj_name)
|
buildings = self.game.theater.find_ground_objects_by_obj_name(ground_object.obj_name)
|
||||||
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 14, 12, cp, ground_object, self.game, buildings))
|
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 14, 12, cp, ground_object, self.game, buildings))
|
||||||
|
|
||||||
if ground_object.category == "aa" and self.get_display_rule("sam"):
|
is_aa = ground_object.category == "aa"
|
||||||
|
if is_aa and DisplayOptions.sam_ranges:
|
||||||
threat_range = 0
|
threat_range = 0
|
||||||
detection_range = 0
|
detection_range = 0
|
||||||
can_fire = False
|
can_fire = False
|
||||||
@ -194,11 +211,11 @@ class QLiberationMap(QGraphicsView):
|
|||||||
added_objects.append(ground_object.obj_name)
|
added_objects.append(ground_object.obj_name)
|
||||||
|
|
||||||
for cp in self.game.theater.enemy_points():
|
for cp in self.game.theater.enemy_points():
|
||||||
if self.get_display_rule("lines"):
|
if DisplayOptions.lines:
|
||||||
self.scene_create_lines_for_cp(cp, playerColor, enemyColor)
|
self.scene_create_lines_for_cp(cp, playerColor, enemyColor)
|
||||||
|
|
||||||
for cp in self.game.theater.player_points():
|
for cp in self.game.theater.player_points():
|
||||||
if self.get_display_rule("lines"):
|
if DisplayOptions.lines:
|
||||||
self.scene_create_lines_for_cp(cp, playerColor, enemyColor)
|
self.scene_create_lines_for_cp(cp, playerColor, enemyColor)
|
||||||
|
|
||||||
self.draw_flight_plans(scene)
|
self.draw_flight_plans(scene)
|
||||||
@ -219,37 +236,44 @@ class QLiberationMap(QGraphicsView):
|
|||||||
# Something may have caused those items to already be removed.
|
# Something may have caused those items to already be removed.
|
||||||
pass
|
pass
|
||||||
self.flight_path_items.clear()
|
self.flight_path_items.clear()
|
||||||
if not self.get_display_rule("flight_paths"):
|
if DisplayOptions.flight_paths.hide:
|
||||||
return
|
return
|
||||||
for package in self.game_model.ato_model.packages:
|
for p_idx, package in enumerate(self.game_model.ato_model.packages):
|
||||||
for flight in package.flights:
|
for f_idx, flight in enumerate(package.flights):
|
||||||
self.draw_flight_plan(scene, flight)
|
selected = (p_idx, f_idx) == self.selected_flight
|
||||||
|
if DisplayOptions.flight_paths.only_selected and not selected:
|
||||||
|
continue
|
||||||
|
highlight = selected and DisplayOptions.flight_paths.all
|
||||||
|
self.draw_flight_plan(scene, flight, highlight)
|
||||||
|
|
||||||
def draw_flight_plan(self, scene: QGraphicsScene, flight: Flight) -> None:
|
def draw_flight_plan(self, scene: QGraphicsScene, flight: Flight,
|
||||||
|
highlight: bool) -> None:
|
||||||
is_player = flight.from_cp.captured
|
is_player = flight.from_cp.captured
|
||||||
pos = self._transform_point(flight.from_cp.position)
|
pos = self._transform_point(flight.from_cp.position)
|
||||||
|
|
||||||
self.draw_waypoint(scene, pos, is_player)
|
self.draw_waypoint(scene, pos, is_player, highlight)
|
||||||
prev_pos = tuple(pos)
|
prev_pos = tuple(pos)
|
||||||
for point in flight.points:
|
for point in flight.points:
|
||||||
new_pos = self._transform_point(Point(point.x, point.y))
|
new_pos = self._transform_point(Point(point.x, point.y))
|
||||||
self.draw_flight_path(scene, prev_pos, new_pos, is_player)
|
self.draw_flight_path(scene, prev_pos, new_pos, is_player,
|
||||||
self.draw_waypoint(scene, new_pos, is_player)
|
highlight)
|
||||||
|
self.draw_waypoint(scene, new_pos, is_player, highlight)
|
||||||
prev_pos = tuple(new_pos)
|
prev_pos = tuple(new_pos)
|
||||||
self.draw_flight_path(scene, prev_pos, pos, is_player)
|
self.draw_flight_path(scene, prev_pos, pos, is_player, highlight)
|
||||||
|
|
||||||
def draw_waypoint(self, scene: QGraphicsScene, position: Tuple[int, int],
|
def draw_waypoint(self, scene: QGraphicsScene, position: Tuple[int, int],
|
||||||
player: bool) -> None:
|
player: bool, highlight: bool) -> None:
|
||||||
waypoint_pen = self.waypoint_pen(player)
|
waypoint_pen = self.waypoint_pen(player, highlight)
|
||||||
waypoint_brush = self.waypoint_brush(player)
|
waypoint_brush = self.waypoint_brush(player, highlight)
|
||||||
self.flight_path_items.append(scene.addEllipse(
|
self.flight_path_items.append(scene.addEllipse(
|
||||||
position[0], position[1], self.WAYPOINT_SIZE,
|
position[0], position[1], self.WAYPOINT_SIZE,
|
||||||
self.WAYPOINT_SIZE, waypoint_pen, waypoint_brush
|
self.WAYPOINT_SIZE, waypoint_pen, waypoint_brush
|
||||||
))
|
))
|
||||||
|
|
||||||
def draw_flight_path(self, scene: QGraphicsScene, pos0: Tuple[int, int],
|
def draw_flight_path(self, scene: QGraphicsScene, pos0: Tuple[int, int],
|
||||||
pos1: Tuple[int, int], player: bool):
|
pos1: Tuple[int, int], player: bool,
|
||||||
flight_path_pen = self.flight_path_pen(player)
|
highlight: bool) -> None:
|
||||||
|
flight_path_pen = self.flight_path_pen(player, highlight)
|
||||||
# Draw the line to the *middle* of the waypoint.
|
# Draw the line to the *middle* of the waypoint.
|
||||||
offset = self.WAYPOINT_SIZE // 2
|
offset = self.WAYPOINT_SIZE // 2
|
||||||
self.flight_path_items.append(scene.addLine(
|
self.flight_path_items.append(scene.addLine(
|
||||||
@ -338,17 +362,24 @@ class QLiberationMap(QGraphicsView):
|
|||||||
|
|
||||||
return X > treshold and X or treshold, Y > treshold and Y or treshold
|
return X > treshold and X or treshold, Y > treshold and Y or treshold
|
||||||
|
|
||||||
|
def highlight_color(self, transparent: Optional[bool] = False) -> QColor:
|
||||||
|
return QColor(255, 255, 0, 20 if transparent else 255)
|
||||||
|
|
||||||
def base_faction_color_name(self, player: bool) -> str:
|
def base_faction_color_name(self, player: bool) -> str:
|
||||||
if player:
|
if player:
|
||||||
return self.game.get_player_color()
|
return self.game.get_player_color()
|
||||||
else:
|
else:
|
||||||
return self.game.get_enemy_color()
|
return self.game.get_enemy_color()
|
||||||
|
|
||||||
def waypoint_pen(self, player: bool) -> QPen:
|
def waypoint_pen(self, player: bool, highlight: bool) -> QColor:
|
||||||
|
if highlight:
|
||||||
|
return self.highlight_color()
|
||||||
name = self.base_faction_color_name(player)
|
name = self.base_faction_color_name(player)
|
||||||
return QPen(brush=CONST.COLORS[name])
|
return CONST.COLORS[name]
|
||||||
|
|
||||||
def waypoint_brush(self, player: bool) -> QColor:
|
def waypoint_brush(self, player: bool, highlight: bool) -> QColor:
|
||||||
|
if highlight:
|
||||||
|
return self.highlight_color(transparent=True)
|
||||||
name = self.base_faction_color_name(player)
|
name = self.base_faction_color_name(player)
|
||||||
return CONST.COLORS[f"{name}_transparent"]
|
return CONST.COLORS[f"{name}_transparent"]
|
||||||
|
|
||||||
@ -369,7 +400,10 @@ class QLiberationMap(QGraphicsView):
|
|||||||
qpen.setStyle(Qt.DotLine)
|
qpen.setStyle(Qt.DotLine)
|
||||||
return qpen
|
return qpen
|
||||||
|
|
||||||
def flight_path_pen(self, player: bool) -> QPen:
|
def flight_path_pen(self, player: bool, highlight: bool) -> QPen:
|
||||||
|
if highlight:
|
||||||
|
return self.highlight_color()
|
||||||
|
|
||||||
name = self.base_faction_color_name(player)
|
name = self.base_faction_color_name(player)
|
||||||
color = CONST.COLORS[name]
|
color = CONST.COLORS[name]
|
||||||
pen = QPen(brush=color)
|
pen = QPen(brush=color)
|
||||||
@ -401,18 +435,3 @@ class QLiberationMap(QGraphicsView):
|
|||||||
effect = QGraphicsOpacityEffect()
|
effect = QGraphicsOpacityEffect()
|
||||||
effect.setOpacity(0.3)
|
effect.setOpacity(0.3)
|
||||||
overlay.setGraphicsEffect(effect)
|
overlay.setGraphicsEffect(effect)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def set_display_rule(rule: str, value: bool):
|
|
||||||
QLiberationMap.display_rules[rule] = value
|
|
||||||
QLiberationMap.instance.reload_scene()
|
|
||||||
QLiberationMap.instance.update()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_display_rules() -> Dict[str, bool]:
|
|
||||||
return QLiberationMap.display_rules
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_display_rule(rule) -> bool:
|
|
||||||
return QLiberationMap.display_rules[rule]
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from qt_ui.models import GameModel
|
|||||||
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
|
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
|
||||||
from theater import ControlPoint
|
from theater import ControlPoint
|
||||||
from .QMapObject import QMapObject
|
from .QMapObject import QMapObject
|
||||||
|
from ...displayoptions import DisplayOptions
|
||||||
|
|
||||||
|
|
||||||
class QMapControlPoint(QMapObject):
|
class QMapControlPoint(QMapObject):
|
||||||
@ -21,7 +22,7 @@ class QMapControlPoint(QMapObject):
|
|||||||
self.base_details_dialog: Optional[QBaseMenu2] = None
|
self.base_details_dialog: Optional[QBaseMenu2] = None
|
||||||
|
|
||||||
def paint(self, painter, option, widget=None) -> None:
|
def paint(self, painter, option, widget=None) -> None:
|
||||||
if self.parent.get_display_rule("cp"):
|
if DisplayOptions.control_points:
|
||||||
painter.save()
|
painter.save()
|
||||||
painter.setRenderHint(QPainter.Antialiasing)
|
painter.setRenderHint(QPainter.Antialiasing)
|
||||||
painter.setBrush(self.brush_color)
|
painter.setBrush(self.brush_color)
|
||||||
|
|||||||
@ -8,8 +8,9 @@ import qt_ui.uiconstants as const
|
|||||||
from game import Game
|
from game import Game
|
||||||
from game.data.building_data import FORTIFICATION_BUILDINGS
|
from game.data.building_data import FORTIFICATION_BUILDINGS
|
||||||
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
||||||
from theater import TheaterGroundObject, ControlPoint
|
from theater import ControlPoint, TheaterGroundObject
|
||||||
from .QMapObject import QMapObject
|
from .QMapObject import QMapObject
|
||||||
|
from ...displayoptions import DisplayOptions
|
||||||
|
|
||||||
|
|
||||||
class QMapGroundObject(QMapObject):
|
class QMapGroundObject(QMapObject):
|
||||||
@ -50,7 +51,7 @@ class QMapGroundObject(QMapObject):
|
|||||||
player_icons = "_blue"
|
player_icons = "_blue"
|
||||||
enemy_icons = ""
|
enemy_icons = ""
|
||||||
|
|
||||||
if self.parent.get_display_rule("go"):
|
if DisplayOptions.ground_objects:
|
||||||
painter.save()
|
painter.save()
|
||||||
|
|
||||||
cat = self.ground_object.category
|
cat = self.ground_object.category
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
from PySide2.QtCore import QObject, Signal
|
from PySide2.QtCore import QObject, Signal
|
||||||
|
|
||||||
@ -24,11 +24,21 @@ class GameUpdateSignal(QObject):
|
|||||||
debriefingReceived = Signal(DebriefingSignal)
|
debriefingReceived = Signal(DebriefingSignal)
|
||||||
|
|
||||||
flight_paths_changed = Signal()
|
flight_paths_changed = Signal()
|
||||||
|
package_selection_changed = Signal(int) # Optional[int]
|
||||||
|
flight_selection_changed = Signal(int) # Optional[int]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(GameUpdateSignal, self).__init__()
|
super(GameUpdateSignal, self).__init__()
|
||||||
GameUpdateSignal.instance = self
|
GameUpdateSignal.instance = self
|
||||||
|
|
||||||
|
def select_package(self, index: Optional[int]) -> None:
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
self.package_selection_changed.emit(index)
|
||||||
|
|
||||||
|
def select_flight(self, index: Optional[int]) -> None:
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
self.flight_selection_changed.emit(index)
|
||||||
|
|
||||||
def redraw_flight_paths(self) -> None:
|
def redraw_flight_paths(self) -> None:
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
self.flight_paths_changed.emit()
|
self.flight_paths_changed.emit()
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
|
|
||||||
from PySide2.QtCore import Qt
|
from PySide2.QtCore import Qt
|
||||||
from PySide2.QtGui import QIcon
|
from PySide2.QtGui import QIcon
|
||||||
from PySide2.QtWidgets import (
|
from PySide2.QtWidgets import (
|
||||||
QAction,
|
QAction,
|
||||||
QDesktopWidget,
|
QActionGroup, QDesktopWidget,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
QMainWindow,
|
QMainWindow,
|
||||||
QMessageBox,
|
QMenu, QMessageBox,
|
||||||
QSplitter,
|
QSplitter,
|
||||||
QVBoxLayout,
|
QVBoxLayout,
|
||||||
QWidget,
|
QWidget,
|
||||||
@ -19,6 +19,7 @@ from PySide2.QtWidgets import (
|
|||||||
import qt_ui.uiconstants as CONST
|
import qt_ui.uiconstants as CONST
|
||||||
from game import Game, persistency
|
from game import Game, persistency
|
||||||
from qt_ui.dialogs import Dialog
|
from qt_ui.dialogs import Dialog
|
||||||
|
from qt_ui.displayoptions import DisplayGroup, DisplayOptions, DisplayRule
|
||||||
from qt_ui.models import GameModel
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.uiconstants import URLS
|
from qt_ui.uiconstants import URLS
|
||||||
from qt_ui.widgets.QTopPanel import QTopPanel
|
from qt_ui.widgets.QTopPanel import QTopPanel
|
||||||
@ -76,7 +77,7 @@ class QLiberationWindow(QMainWindow):
|
|||||||
|
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
vbox.setMargin(0)
|
vbox.setMargin(0)
|
||||||
vbox.addWidget(QTopPanel(self.game))
|
vbox.addWidget(QTopPanel(self.game_model))
|
||||||
vbox.addWidget(hbox)
|
vbox.addWidget(hbox)
|
||||||
|
|
||||||
central_widget = QWidget()
|
central_widget = QWidget()
|
||||||
@ -134,48 +135,23 @@ class QLiberationWindow(QMainWindow):
|
|||||||
file_menu.addSeparator()
|
file_menu.addSeparator()
|
||||||
file_menu.addAction(self.showLiberationPrefDialogAction)
|
file_menu.addAction(self.showLiberationPrefDialogAction)
|
||||||
file_menu.addSeparator()
|
file_menu.addSeparator()
|
||||||
#file_menu.addAction("Close Current Game", lambda: self.closeGame()) # Not working
|
|
||||||
file_menu.addAction("E&xit" , lambda: self.exit())
|
file_menu.addAction("E&xit" , lambda: self.exit())
|
||||||
|
|
||||||
displayMenu = self.menu.addMenu("&Display")
|
displayMenu = self.menu.addMenu("&Display")
|
||||||
|
|
||||||
tg_cp_visibility = QAction('&Control Point', displayMenu)
|
last_was_group = True
|
||||||
tg_cp_visibility.setCheckable(True)
|
for item in DisplayOptions.menu_items():
|
||||||
tg_cp_visibility.setChecked(True)
|
if isinstance(item, DisplayRule):
|
||||||
tg_cp_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("cp", tg_cp_visibility.isChecked()))
|
displayMenu.addAction(self.make_display_rule_action(item))
|
||||||
|
last_was_group = False
|
||||||
tg_go_visibility = QAction('&Ground Objects', displayMenu)
|
elif isinstance(item, DisplayGroup):
|
||||||
tg_go_visibility.setCheckable(True)
|
if not last_was_group:
|
||||||
tg_go_visibility.setChecked(True)
|
displayMenu.addSeparator()
|
||||||
tg_go_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("go", tg_go_visibility.isChecked()))
|
group = QActionGroup(displayMenu)
|
||||||
|
for display_rule in item:
|
||||||
tg_line_visibility = QAction('&Lines', displayMenu)
|
displayMenu.addAction(
|
||||||
tg_line_visibility.setCheckable(True)
|
self.make_display_rule_action(display_rule, group))
|
||||||
tg_line_visibility.setChecked(True)
|
last_was_group = True
|
||||||
tg_line_visibility.toggled.connect(
|
|
||||||
lambda: QLiberationMap.set_display_rule("lines", tg_line_visibility.isChecked()))
|
|
||||||
|
|
||||||
tg_event_visibility = QAction('&Events', displayMenu)
|
|
||||||
tg_event_visibility.setCheckable(True)
|
|
||||||
tg_event_visibility.setChecked(True)
|
|
||||||
tg_event_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("events", tg_event_visibility.isChecked()))
|
|
||||||
|
|
||||||
tg_sam_visibility = QAction('&SAM Range', displayMenu)
|
|
||||||
tg_sam_visibility.setCheckable(True)
|
|
||||||
tg_sam_visibility.setChecked(True)
|
|
||||||
tg_sam_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("sam", tg_sam_visibility.isChecked()))
|
|
||||||
|
|
||||||
tg_flight_path_visibility = QAction('&Flight Paths', displayMenu)
|
|
||||||
tg_flight_path_visibility.setCheckable(True)
|
|
||||||
tg_flight_path_visibility.setChecked(False)
|
|
||||||
tg_flight_path_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("flight_paths", tg_flight_path_visibility.isChecked()))
|
|
||||||
|
|
||||||
displayMenu.addAction(tg_go_visibility)
|
|
||||||
displayMenu.addAction(tg_cp_visibility)
|
|
||||||
displayMenu.addAction(tg_line_visibility)
|
|
||||||
displayMenu.addAction(tg_event_visibility)
|
|
||||||
displayMenu.addAction(tg_sam_visibility)
|
|
||||||
displayMenu.addAction(tg_flight_path_visibility)
|
|
||||||
|
|
||||||
help_menu = self.menu.addMenu("&Help")
|
help_menu = self.menu.addMenu("&Help")
|
||||||
help_menu.addAction("&Discord Server", lambda: webbrowser.open_new_tab("https://" + "discord.gg" + "/" + "bKrt" + "rkJ"))
|
help_menu.addAction("&Discord Server", lambda: webbrowser.open_new_tab("https://" + "discord.gg" + "/" + "bKrt" + "rkJ"))
|
||||||
@ -188,6 +164,21 @@ class QLiberationWindow(QMainWindow):
|
|||||||
help_menu.addSeparator()
|
help_menu.addSeparator()
|
||||||
help_menu.addAction(self.showAboutDialogAction)
|
help_menu.addAction(self.showAboutDialogAction)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def make_display_rule_action(
|
||||||
|
display_rule, group: Optional[QActionGroup] = None) -> QAction:
|
||||||
|
def make_check_closure():
|
||||||
|
def closure():
|
||||||
|
display_rule.value = action.isChecked()
|
||||||
|
|
||||||
|
return closure
|
||||||
|
|
||||||
|
action = QAction(f"&{display_rule.menu_text}", group)
|
||||||
|
action.setCheckable(True)
|
||||||
|
action.setChecked(display_rule.value)
|
||||||
|
action.toggled.connect(make_check_closure())
|
||||||
|
return action
|
||||||
|
|
||||||
def newGame(self):
|
def newGame(self):
|
||||||
wizard = NewGameWizard(self)
|
wizard = NewGameWizard(self)
|
||||||
wizard.show()
|
wizard.show()
|
||||||
|
|||||||
@ -4,9 +4,9 @@ from PySide2.QtWidgets import (
|
|||||||
QVBoxLayout,
|
QVBoxLayout,
|
||||||
)
|
)
|
||||||
|
|
||||||
from game import Game
|
|
||||||
from gen.ato import Package
|
from gen.ato import Package
|
||||||
from gen.flights.flight import Flight
|
from gen.flights.flight import Flight
|
||||||
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.uiconstants import EVENT_ICONS
|
from qt_ui.uiconstants import EVENT_ICONS
|
||||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||||
from qt_ui.windows.mission.flight.QFlightPlanner import QFlightPlanner
|
from qt_ui.windows.mission.flight.QFlightPlanner import QFlightPlanner
|
||||||
@ -15,22 +15,22 @@ from qt_ui.windows.mission.flight.QFlightPlanner import QFlightPlanner
|
|||||||
class QEditFlightDialog(QDialog):
|
class QEditFlightDialog(QDialog):
|
||||||
"""Dialog window for editing flight plans and loadouts."""
|
"""Dialog window for editing flight plans and loadouts."""
|
||||||
|
|
||||||
def __init__(self, game: Game, package: Package, flight: Flight) -> None:
|
def __init__(self, game_model: GameModel, package: Package, flight: Flight) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.game = game
|
self.game_model = game_model
|
||||||
|
|
||||||
self.setWindowTitle("Create flight")
|
self.setWindowTitle("Create flight")
|
||||||
self.setWindowIcon(EVENT_ICONS["strike"])
|
self.setWindowIcon(EVENT_ICONS["strike"])
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
self.flight_planner = QFlightPlanner(package, flight, game)
|
self.flight_planner = QFlightPlanner(package, flight, game_model.game)
|
||||||
layout.addWidget(self.flight_planner)
|
layout.addWidget(self.flight_planner)
|
||||||
|
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
self.finished.connect(self.on_close)
|
self.finished.connect(self.on_close)
|
||||||
|
|
||||||
@staticmethod
|
def on_close(self, _result) -> None:
|
||||||
def on_close(_result) -> None:
|
|
||||||
GameUpdateSignal.get_instance().redraw_flight_paths()
|
GameUpdateSignal.get_instance().redraw_flight_paths()
|
||||||
|
self.game_model.ato_model.client_slots_changed.emit()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user