mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Configurable RF/TCN/ICLS/LINK4 with UI feedback
Resolves #70 Freq/Channel will turn orange when double booked. Freq will turn red if GUARD freq was assigned.
This commit is contained in:
101
qt_ui/widgets/QFrequencyWidget.py
Normal file
101
qt_ui/widgets/QFrequencyWidget.py
Normal file
@@ -0,0 +1,101 @@
|
||||
from PySide2.QtCore import Signal
|
||||
from PySide2.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game.ato import Flight
|
||||
from game.radio.RadioFrequencyContainer import RadioFrequencyContainer
|
||||
from game.radio.radios import RadioFrequency, RadioRange, MHz, kHz
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.windows.QRadioFrequencyDialog import QRadioFrequencyDialog
|
||||
|
||||
|
||||
class QFrequencyWidget(QWidget):
|
||||
|
||||
freq_changed = Signal(QWidget)
|
||||
|
||||
def __init__(
|
||||
self, container: RadioFrequencyContainer, game_model: GameModel
|
||||
) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.ct = container
|
||||
self.gm = game_model
|
||||
|
||||
columns = QHBoxLayout()
|
||||
self.setLayout(columns)
|
||||
|
||||
self.freq = QLabel(self._get_label_text())
|
||||
self.check_freq()
|
||||
columns.addWidget(self.freq)
|
||||
columns.addStretch()
|
||||
|
||||
self.set_freq_btn = QPushButton("Set FREQ")
|
||||
self.set_freq_btn.setProperty("class", "comms")
|
||||
self.set_freq_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.set_freq_btn)
|
||||
self.set_freq_btn.clicked.connect(self.open_freq_dialog)
|
||||
|
||||
self.reset_freq_btn = QPushButton("Reset FREQ")
|
||||
self.reset_freq_btn.setProperty("class", "btn-danger comms")
|
||||
self.reset_freq_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.reset_freq_btn)
|
||||
self.reset_freq_btn.clicked.connect(self.reset_freq)
|
||||
|
||||
def _get_label_text(self) -> str:
|
||||
freq = "AUTO" if self.ct.frequency is None else self.ct.frequency
|
||||
return f"<b>FREQ: {freq}</b>"
|
||||
|
||||
def open_freq_dialog(self) -> None:
|
||||
range = RadioRange(MHz(30), MHz(400), kHz(25))
|
||||
if isinstance(self.ct, Flight):
|
||||
if self.ct.unit_type.intra_flight_radio is not None:
|
||||
range = self.ct.unit_type.intra_flight_radio.ranges[0]
|
||||
self.frequency_dialog = QRadioFrequencyDialog(self, self.ct, range)
|
||||
self.frequency_dialog.accepted.connect(self.assign_frequency)
|
||||
self.frequency_dialog.show()
|
||||
|
||||
def assign_frequency(self) -> None:
|
||||
hz = round(self.frequency_dialog.frequency_input.value() * 10**6)
|
||||
self._try_remove()
|
||||
self.ct.frequency = RadioFrequency(hertz=hz)
|
||||
self.gm.allocated_freqs.append(self.ct.frequency)
|
||||
self.freq.setText(self._get_label_text())
|
||||
self.check_freq()
|
||||
self.freq_changed.emit(self)
|
||||
|
||||
def reset_freq(self) -> None:
|
||||
self._try_remove()
|
||||
self.ct.frequency = None
|
||||
self.freq.setText(self._get_label_text())
|
||||
self._reset_color_and_tooltip()
|
||||
self.freq_changed.emit(self)
|
||||
|
||||
def check_freq(self) -> None:
|
||||
if self.ct.frequency is None:
|
||||
return
|
||||
if self.gm.allocated_freqs.count(self.ct.frequency) > 1:
|
||||
self.freq.setStyleSheet("color: orange")
|
||||
self.freq.setToolTip(
|
||||
"Double booked frequency, verify that this was your intention."
|
||||
)
|
||||
elif self.gm.allocated_freqs.count(self.ct.frequency) == 1:
|
||||
self._reset_color_and_tooltip()
|
||||
if self.ct.frequency == MHz(243) or self.ct.frequency == MHz(121, 500):
|
||||
self.freq.setStyleSheet("color: red")
|
||||
self.freq.setToolTip(
|
||||
"GUARD Freq. was assigned, verify that this was your intention."
|
||||
)
|
||||
|
||||
def _reset_color_and_tooltip(self):
|
||||
self.freq.setStyleSheet("color: white")
|
||||
self.freq.setToolTip(None)
|
||||
|
||||
def _try_remove(self) -> None:
|
||||
try:
|
||||
self.gm.allocated_freqs.remove(self.ct.frequency)
|
||||
except ValueError:
|
||||
pass
|
||||
86
qt_ui/widgets/QICLSWidget.py
Normal file
86
qt_ui/widgets/QICLSWidget.py
Normal file
@@ -0,0 +1,86 @@
|
||||
from PySide2.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game.radio.ICLSContainer import ICLSContainer
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.windows.QICLSDialog import QICLSDialog
|
||||
|
||||
|
||||
class QICLSWidget(QWidget):
|
||||
def __init__(self, container: ICLSContainer, game_model: GameModel) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.ct = container
|
||||
self.gm = game_model
|
||||
|
||||
columns = QHBoxLayout()
|
||||
self.setLayout(columns)
|
||||
|
||||
self.channel = QLabel(self._get_label_text())
|
||||
self.check_channel()
|
||||
columns.addWidget(self.channel)
|
||||
columns.addStretch()
|
||||
|
||||
self.set_icls_btn = QPushButton("Set ICLS")
|
||||
self.set_icls_btn.setProperty("class", "comms")
|
||||
self.set_icls_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.set_icls_btn)
|
||||
self.set_icls_btn.clicked.connect(self.open_icls_dialog)
|
||||
|
||||
self.reset_icls_btn = QPushButton("Reset ICLS")
|
||||
self.reset_icls_btn.setProperty("class", "btn-danger comms")
|
||||
self.reset_icls_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.reset_icls_btn)
|
||||
self.reset_icls_btn.clicked.connect(self.reset_icls)
|
||||
|
||||
def _get_label_text(self) -> str:
|
||||
c = "AUTO" if self.ct.icls_channel is None else self.ct.icls_channel
|
||||
cs = self.ct.icls_name
|
||||
cs = "" if cs is None else f" ({cs})"
|
||||
return f"<b>ICLS: {c}{cs}</b>"
|
||||
|
||||
def open_icls_dialog(self) -> None:
|
||||
self.icls_dialog = QICLSDialog(self, self.ct)
|
||||
self.icls_dialog.accepted.connect(self.assign_icls)
|
||||
self.icls_dialog.show()
|
||||
|
||||
def assign_icls(self) -> None:
|
||||
self._try_remove()
|
||||
self.ct.icls_channel = self.icls_dialog.icls_input.value()
|
||||
self.gm.allocated_icls.append(self.ct.icls_channel)
|
||||
if cs := self.icls_dialog.callsign_input.text():
|
||||
self.ct.icls_name = cs.upper()
|
||||
self.channel.setText(self._get_label_text())
|
||||
self.check_channel()
|
||||
|
||||
def reset_icls(self) -> None:
|
||||
self._try_remove()
|
||||
self.ct.icls_channel = None
|
||||
self.ct.icls_name = None
|
||||
self.channel.setText(self._get_label_text())
|
||||
self._reset_color_and_tooltip()
|
||||
|
||||
def check_channel(self) -> None:
|
||||
if self.ct.icls_channel is None:
|
||||
return
|
||||
if self.gm.allocated_icls.count(self.ct.icls_channel) > 1:
|
||||
self.channel.setStyleSheet("color: orange")
|
||||
self.channel.setToolTip(
|
||||
"Double booked ICLS channel, verify that this was your intention."
|
||||
)
|
||||
elif self.gm.allocated_icls.count(self.ct.icls_channel) == 1:
|
||||
self._reset_color_and_tooltip()
|
||||
|
||||
def _reset_color_and_tooltip(self):
|
||||
self.channel.setStyleSheet("color: white")
|
||||
self.channel.setToolTip(None)
|
||||
|
||||
def _try_remove(self) -> None:
|
||||
try:
|
||||
self.gm.allocated_icls.remove(self.ct.icls_channel)
|
||||
except ValueError:
|
||||
pass
|
||||
95
qt_ui/widgets/QLink4Widget.py
Normal file
95
qt_ui/widgets/QLink4Widget.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from PySide2.QtCore import Signal
|
||||
from PySide2.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game.radio.radios import RadioFrequency, RadioRange, MHz, kHz
|
||||
from game.theater import NavalControlPoint
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.windows.QRadioFrequencyDialog import QRadioFrequencyDialog
|
||||
|
||||
|
||||
class QLink4Widget(QWidget):
|
||||
|
||||
freq_changed = Signal(QWidget)
|
||||
|
||||
def __init__(self, cp: NavalControlPoint, game_model: GameModel) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.cp = cp
|
||||
self.gm = game_model
|
||||
|
||||
columns = QHBoxLayout()
|
||||
self.setLayout(columns)
|
||||
|
||||
self.freq = QLabel(self._get_label_text())
|
||||
self.check_freq()
|
||||
columns.addWidget(self.freq)
|
||||
columns.addStretch()
|
||||
|
||||
self.set_freq_btn = QPushButton("Set LINK4")
|
||||
self.set_freq_btn.setProperty("class", "comms")
|
||||
self.set_freq_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.set_freq_btn)
|
||||
self.set_freq_btn.clicked.connect(self.open_freq_dialog)
|
||||
|
||||
self.reset_freq_btn = QPushButton("Reset LINK4")
|
||||
self.reset_freq_btn.setProperty("class", "btn-danger comms")
|
||||
self.reset_freq_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.reset_freq_btn)
|
||||
self.reset_freq_btn.clicked.connect(self.reset_freq)
|
||||
|
||||
def _get_label_text(self) -> str:
|
||||
freq = "AUTO" if self.cp.link4 is None else self.cp.link4
|
||||
return f"<b>LINK4: {freq}</b>"
|
||||
|
||||
def open_freq_dialog(self) -> None:
|
||||
range = RadioRange(MHz(225), MHz(400), kHz(25))
|
||||
self.frequency_dialog = QRadioFrequencyDialog(self, self.cp, range, link4=True)
|
||||
self.frequency_dialog.accepted.connect(self.assign_frequency)
|
||||
self.frequency_dialog.show()
|
||||
|
||||
def assign_frequency(self) -> None:
|
||||
hz = round(self.frequency_dialog.frequency_input.value() * 10**6)
|
||||
self._try_remove()
|
||||
self.cp.link4 = RadioFrequency(hertz=hz)
|
||||
self.gm.allocated_freqs.append(self.cp.link4)
|
||||
self.freq.setText(self._get_label_text())
|
||||
self.check_freq()
|
||||
self.freq_changed.emit(self)
|
||||
|
||||
def reset_freq(self):
|
||||
self._try_remove()
|
||||
self.cp.link4 = None
|
||||
self.freq.setText(self._get_label_text())
|
||||
self._reset_color_and_tooltip()
|
||||
self.freq_changed.emit(self)
|
||||
|
||||
def check_freq(self):
|
||||
if self.cp.link4 is None:
|
||||
return
|
||||
if self.gm.allocated_freqs.count(self.cp.link4) > 1:
|
||||
self.freq.setStyleSheet("color: orange")
|
||||
self.freq.setToolTip(
|
||||
"Double booked frequency, verify that this was your intention."
|
||||
)
|
||||
elif self.gm.allocated_freqs.count(self.cp.link4) == 1:
|
||||
self._reset_color_and_tooltip()
|
||||
if self.cp.link4 == MHz(243) or self.cp.link4 == MHz(121, 500):
|
||||
self.freq.setStyleSheet("color: red")
|
||||
self.freq.setToolTip(
|
||||
"GUARD Freq. was assigned, verify that this was your intention."
|
||||
)
|
||||
|
||||
def _reset_color_and_tooltip(self):
|
||||
self.freq.setStyleSheet("color: white")
|
||||
self.freq.setToolTip(None)
|
||||
|
||||
def _try_remove(self):
|
||||
try:
|
||||
self.gm.allocated_freqs.remove(self.cp.link4)
|
||||
except ValueError:
|
||||
pass
|
||||
90
qt_ui/widgets/QTacanWidget.py
Normal file
90
qt_ui/widgets/QTacanWidget.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from PySide2.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game.radio.TacanContainer import TacanContainer
|
||||
from game.radio.tacan import TacanChannel, TacanBand
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.windows.QTacanDialog import QTacanDialog
|
||||
|
||||
|
||||
class QTacanWidget(QWidget):
|
||||
def __init__(self, container: TacanContainer, game_model: GameModel) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.ct = container
|
||||
self.gm = game_model
|
||||
|
||||
columns = QHBoxLayout()
|
||||
self.setLayout(columns)
|
||||
|
||||
self.channel = QLabel(self._get_label_text())
|
||||
self.check_channel()
|
||||
columns.addWidget(self.channel)
|
||||
columns.addStretch()
|
||||
|
||||
self.set_tacan_btn = QPushButton("Set TACAN")
|
||||
self.set_tacan_btn.setProperty("class", "comms")
|
||||
self.set_tacan_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.set_tacan_btn)
|
||||
self.set_tacan_btn.clicked.connect(self.open_tacan_dialog)
|
||||
|
||||
self.reset_tacan_btn = QPushButton("Reset TACAN")
|
||||
self.reset_tacan_btn.setProperty("class", "btn-danger comms")
|
||||
self.reset_tacan_btn.setFixedWidth(100)
|
||||
columns.addWidget(self.reset_tacan_btn)
|
||||
self.reset_tacan_btn.clicked.connect(self.reset_tacan)
|
||||
|
||||
def _get_label_text(self) -> str:
|
||||
c = "AUTO" if self.ct.tacan is None else self.ct.tacan
|
||||
cs = self.ct.tcn_name
|
||||
cs = "" if cs is None else f" ({cs})"
|
||||
return f"<b>TACAN: {c}{cs}</b>"
|
||||
|
||||
def open_tacan_dialog(self) -> None:
|
||||
self.tacan_dialog = QTacanDialog(self, self.ct)
|
||||
self.tacan_dialog.accepted.connect(self.assign_tacan)
|
||||
self.tacan_dialog.show()
|
||||
|
||||
def assign_tacan(self) -> None:
|
||||
channel = self.tacan_dialog.tacan_input.value()
|
||||
band = self.tacan_dialog.band_input.currentText()
|
||||
band = TacanBand.X if band == "X" else TacanBand.Y
|
||||
self._try_remove()
|
||||
self.ct.tacan = TacanChannel(number=channel, band=band)
|
||||
self.gm.allocated_tacan.append(self.ct.tacan)
|
||||
if cs := self.tacan_dialog.callsign_input.text():
|
||||
self.ct.tcn_name = cs.upper()
|
||||
self.channel.setText(self._get_label_text())
|
||||
self.check_channel()
|
||||
|
||||
def reset_tacan(self) -> None:
|
||||
self._try_remove()
|
||||
self.ct.tacan = None
|
||||
self.ct.tcn_name = None
|
||||
self.channel.setText(self._get_label_text())
|
||||
self._reset_color_and_tooltip()
|
||||
|
||||
def check_channel(self) -> None:
|
||||
if self.ct.tacan is None:
|
||||
return
|
||||
if self.gm.allocated_tacan.count(self.ct.tacan) > 1:
|
||||
self.channel.setStyleSheet("color: orange")
|
||||
self.channel.setToolTip(
|
||||
"Double booked TACAN channel, verify that this was your intention."
|
||||
)
|
||||
elif self.gm.allocated_tacan.count(self.ct.tacan) == 1:
|
||||
self._reset_color_and_tooltip()
|
||||
|
||||
def _reset_color_and_tooltip(self):
|
||||
self.channel.setStyleSheet("color: white")
|
||||
self.channel.setToolTip(None)
|
||||
|
||||
def _try_remove(self) -> None:
|
||||
try:
|
||||
self.gm.allocated_tacan.remove(self.ct.tacan)
|
||||
except ValueError:
|
||||
pass
|
||||
Reference in New Issue
Block a user