diff --git a/qt_ui/windows/AirWingDialog.py b/qt_ui/windows/AirWingDialog.py index 2fb25dbd..17ad45a5 100644 --- a/qt_ui/windows/AirWingDialog.py +++ b/qt_ui/windows/AirWingDialog.py @@ -3,111 +3,36 @@ from typing import Optional from PySide2.QtCore import ( QItemSelectionModel, QModelIndex, - QSize, Qt, ) -from PySide2.QtGui import QFont, QFontMetrics, QIcon, QPainter from PySide2.QtWidgets import ( QAbstractItemView, QDialog, QListView, - QStyle, - QStyleOptionViewItem, - QStyledItemDelegate, QVBoxLayout, ) from game.squadrons import Squadron -from qt_ui.delegates import painter_context +from qt_ui.delegates import TwoColumnRowDelegate from qt_ui.models import GameModel, AirWingModel, SquadronModel from qt_ui.windows.SquadronDialog import SquadronDialog -class SquadronDelegate(QStyledItemDelegate): - FONT_SIZE = 10 - HMARGIN = 4 - VMARGIN = 4 - +class SquadronDelegate(TwoColumnRowDelegate): def __init__(self, air_wing_model: AirWingModel) -> None: - super().__init__() + super().__init__(rows=2, columns=1, font_size=12) self.air_wing_model = air_wing_model - def get_font(self, option: QStyleOptionViewItem) -> QFont: - font = QFont(option.font) - font.setPointSize(self.FONT_SIZE) - return font - @staticmethod def squadron(index: QModelIndex) -> Squadron: return index.data(AirWingModel.SquadronRole) - def first_row_text(self, index: QModelIndex) -> str: - return self.air_wing_model.data(index, Qt.DisplayRole) - - def second_row_text(self, index: QModelIndex) -> str: - return self.squadron(index).nickname - - 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)) - - @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, - ) + def text_for(self, index: QModelIndex, row: int, column: int) -> str: + if row == 0: + return self.air_wing_model.data(index, Qt.DisplayRole) + elif row == 1: + return self.squadron(index).nickname + return "" class SquadronList(QListView): diff --git a/qt_ui/windows/PendingTransfersDialog.py b/qt_ui/windows/PendingTransfersDialog.py index 7242fa5b..982ae9f8 100644 --- a/qt_ui/windows/PendingTransfersDialog.py +++ b/qt_ui/windows/PendingTransfersDialog.py @@ -1,13 +1,10 @@ -from typing import Optional - from PySide2.QtCore import ( QItemSelection, QItemSelectionModel, QModelIndex, - QSize, Qt, ) -from PySide2.QtGui import QContextMenuEvent, QFont, QFontMetrics, QIcon, QPainter +from PySide2.QtGui import QContextMenuEvent from PySide2.QtWidgets import ( QAbstractItemView, QAction, @@ -16,102 +13,29 @@ from PySide2.QtWidgets import ( QListView, QMenu, QPushButton, - QStyle, - QStyleOptionViewItem, - QStyledItemDelegate, QVBoxLayout, ) from game.transfers import TransferOrder -from qt_ui.delegates import painter_context +from qt_ui.delegates import TwoColumnRowDelegate from qt_ui.models import GameModel, TransferModel -class TransferDelegate(QStyledItemDelegate): - FONT_SIZE = 10 - HMARGIN = 4 - VMARGIN = 4 - +class TransferDelegate(TwoColumnRowDelegate): def __init__(self, transfer_model: TransferModel) -> None: - super().__init__() + super().__init__(rows=2, columns=1, font_size=12) self.transfer_model = transfer_model - def get_font(self, option: QStyleOptionViewItem) -> QFont: - font = QFont(option.font) - font.setPointSize(self.FONT_SIZE) - return font - @staticmethod def transfer(index: QModelIndex) -> TransferOrder: return index.data(TransferModel.TransferRole) - def first_row_text(self, index: QModelIndex) -> str: - return self.transfer_model.data(index, Qt.DisplayRole) - - def second_row_text(self, index: QModelIndex) -> str: - return self.transfer(index).description - - 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)) - - @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, - ) + def text_for(self, index: QModelIndex, row: int, column: int) -> str: + if row == 0: + return self.transfer_model.data(index, Qt.DisplayRole) + elif row == 1: + return self.transfer(index).description + return "" class PendingTransfersList(QListView): @@ -190,7 +114,7 @@ class PendingTransfersDialog(QDialog): def can_cancel(self, index: QModelIndex) -> bool: if not index.isValid(): return False - return self.transfer_model.pilot_at_index(index).player + return self.transfer_model.transfer_at_index(index).player def on_selection_changed( self, selected: QItemSelection, _deselected: QItemSelection diff --git a/qt_ui/windows/SquadronDialog.py b/qt_ui/windows/SquadronDialog.py index c1582c3d..4ce56184 100644 --- a/qt_ui/windows/SquadronDialog.py +++ b/qt_ui/windows/SquadronDialog.py @@ -1,112 +1,35 @@ -from typing import Optional - from PySide2.QtCore import ( QItemSelectionModel, QModelIndex, - QSize, Qt, ) -from PySide2.QtGui import QFont, QFontMetrics, QIcon, QPainter from PySide2.QtWidgets import ( QAbstractItemView, QDialog, QListView, - QStyle, - QStyleOptionViewItem, - QStyledItemDelegate, QVBoxLayout, ) from game.squadrons import Pilot -from qt_ui.delegates import painter_context +from qt_ui.delegates import TwoColumnRowDelegate from qt_ui.models import SquadronModel -class PilotDelegate(QStyledItemDelegate): - FONT_SIZE = 10 - HMARGIN = 4 - VMARGIN = 4 - +class PilotDelegate(TwoColumnRowDelegate): def __init__(self, squadron_model: SquadronModel) -> None: - super().__init__() + super().__init__(rows=2, columns=1, font_size=12) self.squadron_model = squadron_model - def get_font(self, option: QStyleOptionViewItem) -> QFont: - font = QFont(option.font) - font.setPointSize(self.FONT_SIZE) - return font - @staticmethod def pilot(index: QModelIndex) -> Pilot: return index.data(SquadronModel.PilotRole) - def first_row_text(self, index: QModelIndex) -> str: - return self.squadron_model.data(index, Qt.DisplayRole) - - def second_row_text(self, index: QModelIndex) -> str: - return "Alive" if self.pilot(index).alive else "Dead" - - 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)) - - @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, - ) + def text_for(self, index: QModelIndex, row: int, column: int) -> str: + if row == 0: + return self.squadron_model.data(index, Qt.DisplayRole) + elif row == 1: + return "Alive" if self.pilot(index).alive else "Dead" + return "" class PilotList(QListView):