diff --git a/src/warchron/controller/controller.py b/src/warchron/controller/controller.py index 8d92385..d653ff8 100644 --- a/src/warchron/controller/controller.py +++ b/src/warchron/controller/controller.py @@ -19,17 +19,15 @@ from warchron.controller.dtos import ( ChoiceDTO, BattleDTO, ) -from warchron.view.view import ( - PlayerDialog, - WarDialog, - CampaignDialog, - ObjectiveDialog, - WarParticipantDialog, - CampaignParticipantDialog, - SectorDialog, - ChoicesDialog, - BattlesDialog, -) +from warchron.view.player_dialog import PlayerDialog +from warchron.view.war_dialog import WarDialog +from warchron.view.campaign_dialog import CampaignDialog +from warchron.view.objective_dialog import ObjectiveDialog +from warchron.view.war_participant_dialog import WarParticipantDialog +from warchron.view.campaign_participant_dialog import CampaignParticipantDialog +from warchron.view.sector_dialog import SectorDialog +from warchron.view.choices_dialog import ChoicesDialog +from warchron.view.battles_dialog import BattlesDialog class Controller: @@ -363,6 +361,7 @@ class Controller: self.refresh(scope) self.view.select_tree_item(item_type=item_type, item_id=item_id) + # TODO separate routing and dedicated edit methods def edit_item(self, item_type: str, item_id: str) -> None: if item_type == ItemType.PLAYER: play = self.model.get_player(item_id) diff --git a/src/warchron/model/battle.py b/src/warchron/model/battle.py new file mode 100644 index 0000000..04a24c7 --- /dev/null +++ b/src/warchron/model/battle.py @@ -0,0 +1,35 @@ +class Battle: + def __init__( + self, + sector_id: str, + player_1_id: str | None = None, + player_2_id: str | None = None, + ): + self.sector_id: str = sector_id # ref to Campaign.sector + self.player_1_id: str | None = player_1_id # ref to Campaign.participants + self.player_2_id: str | None = player_2_id # ref to Campaign.participants + self.winner_id: str | None = None + self.score: str | None = None + self.victory_condition: str | None = None + self.comment: str | None = None + + def set_id(self, new_id: str) -> None: + self.sector_id = new_id + + def set_player_1(self, new_player_id: str | None) -> None: + self.player_1_id = new_player_id + + def set_player_2(self, new_player_id: str | None) -> None: + self.player_2_id = new_player_id + + def set_winner(self, new_player_id: str | None) -> None: + self.winner_id = new_player_id + + def set_score(self, new_score: str | None) -> None: + self.score = new_score + + def set_victory_condition(self, new_victory_condition: str | None) -> None: + self.victory_condition = new_victory_condition + + def set_comment(self, new_comment: str | None) -> None: + self.comment = new_comment diff --git a/src/warchron/model/campaign.py b/src/warchron/model/campaign.py index bf3431e..7b9d022 100644 --- a/src/warchron/model/campaign.py +++ b/src/warchron/model/campaign.py @@ -2,7 +2,11 @@ from __future__ import annotations from uuid import uuid4 from typing import Any, Dict, List -from warchron.model.round import Round, Choice, Battle +from warchron.model.campaign_participant import CampaignParticipant +from warchron.model.sector import Sector +from warchron.model.round import Round +from warchron.model.choice import Choice +from warchron.model.battle import Battle class Campaign: @@ -227,62 +231,3 @@ class Campaign: def remove_battle(self, round_id: str, sector_id: str) -> None: rnd = self.get_round(round_id) rnd.remove_battle(sector_id) - - -class CampaignParticipant: - def __init__( - self, *, war_participant_id: str, leader: str | None, theme: str | None - ): - self.id: str = str(uuid4()) - self.war_participant_id: str = war_participant_id # ref to War.participants - self.leader: str | None = leader - self.theme: str | None = theme - - def set_id(self, new_id: str) -> None: - self.id = new_id - - def set_war_participant(self, new_participant: str) -> None: - self.war_participant_id = new_participant - - def set_leader(self, new_faction: str) -> None: - self.leader = new_faction - - def set_theme(self, new_theme: str) -> None: - self.theme = new_theme - - -class Sector: - def __init__( - self, - name: str, - round_id: str, - major_id: str | None, - minor_id: str | None, - influence_id: str | None, - ): - self.id: str = str(uuid4()) - self.name: str = name - self.round_id: str = round_id - self.major_objective_id: str | None = major_id # ref to War.objectives - self.minor_objective_id: str | None = minor_id # ref to War.objectives - self.influence_objective_id: str | None = influence_id # ref to War.objectives - self.mission: str | None = None - self.description: str | None = None - - def set_id(self, new_id: str) -> None: - self.id = new_id - - def set_name(self, new_name: str) -> None: - self.name = new_name - - def set_round(self, new_round_id: str) -> None: - self.round_id = new_round_id - - def set_major(self, new_major_id: str) -> None: - self.major_objective_id = new_major_id - - def set_minor(self, new_minor_id: str) -> None: - self.minor_objective_id = new_minor_id - - def set_influence(self, new_influence_id: str) -> None: - self.influence_objective_id = new_influence_id diff --git a/src/warchron/model/campaign_participant.py b/src/warchron/model/campaign_participant.py new file mode 100644 index 0000000..aa98528 --- /dev/null +++ b/src/warchron/model/campaign_participant.py @@ -0,0 +1,24 @@ +from __future__ import annotations +from uuid import uuid4 + + +class CampaignParticipant: + def __init__( + self, *, war_participant_id: str, leader: str | None, theme: str | None + ): + self.id: str = str(uuid4()) + self.war_participant_id: str = war_participant_id # ref to War.participants + self.leader: str | None = leader + self.theme: str | None = theme + + def set_id(self, new_id: str) -> None: + self.id = new_id + + def set_war_participant(self, new_participant: str) -> None: + self.war_participant_id = new_participant + + def set_leader(self, new_faction: str) -> None: + self.leader = new_faction + + def set_theme(self, new_theme: str) -> None: + self.theme = new_theme diff --git a/src/warchron/model/choice.py b/src/warchron/model/choice.py new file mode 100644 index 0000000..d49ec66 --- /dev/null +++ b/src/warchron/model/choice.py @@ -0,0 +1,27 @@ +class Choice: + def __init__( + self, + participant_id: str, + priority_sector_id: str | None = None, + secondary_sector_id: str | None = None, + ): + self.participant_id: str = participant_id # ref to Campaign.participants + self.priority_sector_id: str | None = ( + priority_sector_id # ref to Campaign.sectors + ) + self.secondary_sector_id: str | None = ( + secondary_sector_id # ref to Campaign.sectors + ) + self.comment: str | None = None + + def set_id(self, new_id: str) -> None: + self.participant_id = new_id + + def set_priority(self, new_priority_id: str | None) -> None: + self.priority_sector_id = new_priority_id + + def set_secondary(self, new_secondary_id: str | None) -> None: + self.secondary_sector_id = new_secondary_id + + def set_comment(self, new_comment: str | None) -> None: + self.comment = new_comment diff --git a/src/warchron/model/model.py b/src/warchron/model/model.py index 1a17563..dd0ad09 100644 --- a/src/warchron/model/model.py +++ b/src/warchron/model/model.py @@ -5,9 +5,15 @@ import shutil from datetime import datetime from warchron.model.player import Player -from warchron.model.war import War, Objective, WarParticipant -from warchron.model.campaign import Campaign, Sector, CampaignParticipant -from warchron.model.round import Round, Choice, Battle +from warchron.model.war import War +from warchron.model.war_participant import WarParticipant +from warchron.model.objective import Objective +from warchron.model.campaign import Campaign +from warchron.model.campaign_participant import CampaignParticipant +from warchron.model.sector import Sector +from warchron.model.round import Round +from warchron.model.choice import Choice +from warchron.model.battle import Battle class Model: diff --git a/src/warchron/model/objective.py b/src/warchron/model/objective.py index e69de29..d3e5d76 100644 --- a/src/warchron/model/objective.py +++ b/src/warchron/model/objective.py @@ -0,0 +1,18 @@ +from __future__ import annotations +from uuid import uuid4 + + +class Objective: + def __init__(self, name: str, description: str): + self.id: str = str(uuid4()) + self.name: str = name + self.description: str = description + + def set_id(self, new_id: str) -> None: + self.id = new_id + + def set_name(self, new_name: str) -> None: + self.name = new_name + + def set_description(self, new_description: str) -> None: + self.description = new_description diff --git a/src/warchron/model/round.py b/src/warchron/model/round.py index 420eea8..62cd5c7 100644 --- a/src/warchron/model/round.py +++ b/src/warchron/model/round.py @@ -2,6 +2,9 @@ from __future__ import annotations from uuid import uuid4 from typing import Any, Dict +from warchron.model.choice import Choice +from warchron.model.battle import Battle + class Round: def __init__(self) -> None: @@ -98,69 +101,3 @@ class Round: def remove_battle(self, sector_id: str) -> None: del self.battles[sector_id] - - -class Choice: - def __init__( - self, - participant_id: str, - priority_sector_id: str | None = None, - secondary_sector_id: str | None = None, - ): - self.participant_id: str = participant_id # ref to Campaign.participants - self.priority_sector_id: str | None = ( - priority_sector_id # ref to Campaign.sectors - ) - self.secondary_sector_id: str | None = ( - secondary_sector_id # ref to Campaign.sectors - ) - self.comment: str | None = None - - def set_id(self, new_id: str) -> None: - self.participant_id = new_id - - def set_priority(self, new_priority_id: str | None) -> None: - self.priority_sector_id = new_priority_id - - def set_secondary(self, new_secondary_id: str | None) -> None: - self.secondary_sector_id = new_secondary_id - - def set_comment(self, new_comment: str | None) -> None: - self.comment = new_comment - - -class Battle: - def __init__( - self, - sector_id: str, - player_1_id: str | None = None, - player_2_id: str | None = None, - ): - self.sector_id: str = sector_id # ref to Campaign.sector - self.player_1_id: str | None = player_1_id # ref to Campaign.participants - self.player_2_id: str | None = player_2_id # ref to Campaign.participants - self.winner_id: str | None = None - self.score: str | None = None - self.victory_condition: str | None = None - self.comment: str | None = None - - def set_id(self, new_id: str) -> None: - self.sector_id = new_id - - def set_player_1(self, new_player_id: str | None) -> None: - self.player_1_id = new_player_id - - def set_player_2(self, new_player_id: str | None) -> None: - self.player_2_id = new_player_id - - def set_winner(self, new_player_id: str | None) -> None: - self.winner_id = new_player_id - - def set_score(self, new_score: str | None) -> None: - self.score = new_score - - def set_victory_condition(self, new_victory_condition: str | None) -> None: - self.victory_condition = new_victory_condition - - def set_comment(self, new_comment: str | None) -> None: - self.comment = new_comment diff --git a/src/warchron/model/sector.py b/src/warchron/model/sector.py new file mode 100644 index 0000000..47cb4a8 --- /dev/null +++ b/src/warchron/model/sector.py @@ -0,0 +1,39 @@ +from __future__ import annotations +from uuid import uuid4 + + +class Sector: + def __init__( + self, + name: str, + round_id: str, + major_id: str | None, + minor_id: str | None, + influence_id: str | None, + ): + self.id: str = str(uuid4()) + self.name: str = name + self.round_id: str = round_id + self.major_objective_id: str | None = major_id # ref to War.objectives + self.minor_objective_id: str | None = minor_id # ref to War.objectives + self.influence_objective_id: str | None = influence_id # ref to War.objectives + self.mission: str | None = None + self.description: str | None = None + + def set_id(self, new_id: str) -> None: + self.id = new_id + + def set_name(self, new_name: str) -> None: + self.name = new_name + + def set_round(self, new_round_id: str) -> None: + self.round_id = new_round_id + + def set_major(self, new_major_id: str) -> None: + self.major_objective_id = new_major_id + + def set_minor(self, new_minor_id: str) -> None: + self.minor_objective_id = new_minor_id + + def set_influence(self, new_influence_id: str) -> None: + self.influence_objective_id = new_influence_id diff --git a/src/warchron/model/war.py b/src/warchron/model/war.py index 70cf6f4..2a895a2 100644 --- a/src/warchron/model/war.py +++ b/src/warchron/model/war.py @@ -3,8 +3,14 @@ from uuid import uuid4 from datetime import datetime from typing import Any, Dict, List -from warchron.model.campaign import Campaign, Sector, CampaignParticipant -from warchron.model.round import Round, Choice, Battle +from warchron.model.war_participant import WarParticipant +from warchron.model.objective import Objective +from warchron.model.campaign_participant import CampaignParticipant +from warchron.model.sector import Sector +from warchron.model.campaign import Campaign +from warchron.model.round import Round +from warchron.model.choice import Choice +from warchron.model.battle import Battle class War: @@ -312,35 +318,3 @@ class War: def remove_battle(self, round_id: str, sector_id: str) -> None: camp = self.get_campaign_by_round(round_id) camp.remove_battle(round_id, sector_id) - - -class Objective: - def __init__(self, name: str, description: str): - self.id: str = str(uuid4()) - self.name: str = name - self.description: str = description - - def set_id(self, new_id: str) -> None: - self.id = new_id - - def set_name(self, new_name: str) -> None: - self.name = new_name - - def set_description(self, new_description: str) -> None: - self.description = new_description - - -class WarParticipant: - def __init__(self, *, player_id: str, faction: str): - self.id: str = str(uuid4()) - self.player_id: str = player_id # ref to WarModel.players - self.faction: str = faction - - def set_id(self, new_id: str) -> None: - self.id = new_id - - def set_player(self, new_player: str) -> None: - self.player_id = new_player - - def set_faction(self, new_faction: str) -> None: - self.faction = new_faction diff --git a/src/warchron/model/war_participant.py b/src/warchron/model/war_participant.py index e69de29..4b405f0 100644 --- a/src/warchron/model/war_participant.py +++ b/src/warchron/model/war_participant.py @@ -0,0 +1,18 @@ +from __future__ import annotations +from uuid import uuid4 + + +class WarParticipant: + def __init__(self, *, player_id: str, faction: str): + self.id: str = str(uuid4()) + self.player_id: str = player_id # ref to WarModel.players + self.faction: str = faction + + def set_id(self, new_id: str) -> None: + self.id = new_id + + def set_player(self, new_player: str) -> None: + self.player_id = new_player + + def set_faction(self, new_faction: str) -> None: + self.faction = new_faction diff --git a/src/warchron/view/battles_dialog.py b/src/warchron/view/battles_dialog.py new file mode 100644 index 0000000..2ef86a0 --- /dev/null +++ b/src/warchron/view/battles_dialog.py @@ -0,0 +1,68 @@ +from typing import cast, List + +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.controller.dtos import ParticipantOption, SectorDTO +from warchron.view.helpers import select_if_exists +from warchron.view.ui.ui_battle_result_dialog import Ui_battleResultDialog + + +class BattlesDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + *, + sectors: List[SectorDTO], + default_sector_id: str | None = None, + players: List[ParticipantOption], + default_player_1_id: str | None = None, + default_player_2_id: str | None = None, + default_winner_id: str | None = None, + default_score: str | None = None, + default_victory_condition: str | None = None, + default_comment: str | None = None, + ) -> None: + super().__init__(parent) + self.ui: Ui_battleResultDialog = Ui_battleResultDialog() + self.ui.setupUi(self) # type: ignore + for sect in sectors: + self.ui.sectorComboBox.addItem(sect.name, sect.id) + select_if_exists(self.ui.sectorComboBox, default_sector_id) + self.ui.sectorComboBox.setEnabled(False) + + self.ui.player1ComboBox.addItem("(none)", None) + self.ui.player2ComboBox.addItem("(none)", None) + for play in players: + self.ui.player1ComboBox.addItem(play.name, play.id) + self.ui.player2ComboBox.addItem(play.name, play.id) + select_if_exists(self.ui.player1ComboBox, default_player_1_id) + select_if_exists(self.ui.player2ComboBox, default_player_2_id) + self.ui.winnerComboBox.addItem("(none)", None) + for play in players: + if play.id in (default_player_1_id, default_player_2_id): + self.ui.winnerComboBox.addItem(play.name, play.id) + select_if_exists(self.ui.winnerComboBox, default_winner_id) + self.ui.score.setText(default_score) + self.ui.victoryCondition.setText(default_victory_condition) + self.ui.battleComment.setPlainText(default_comment) + + def get_sector_id(self) -> str: + return cast(str, self.ui.sectorComboBox.currentData()) + + def get_player_1_id(self) -> str: + return cast(str, self.ui.player1ComboBox.currentData()) + + def get_player_2_id(self) -> str: + return cast(str, self.ui.player2ComboBox.currentData()) + + def get_winner_id(self) -> str: + return cast(str, self.ui.winnerComboBox.currentData()) + + def get_score(self) -> str: + return self.ui.score.text().strip() + + def get_victory_condition(self) -> str: + return self.ui.victoryCondition.text().strip() + + def get_comment(self) -> str: + return self.ui.battleComment.toPlainText().strip() diff --git a/src/warchron/view/campaign_dialog.py b/src/warchron/view/campaign_dialog.py new file mode 100644 index 0000000..185203f --- /dev/null +++ b/src/warchron/view/campaign_dialog.py @@ -0,0 +1,25 @@ +from PyQt6.QtWidgets import QDialog + +from warchron.view.ui.ui_campaign_dialog import Ui_campaignDialog +from PyQt6.QtWidgets import QWidget + + +class CampaignDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + default_name: str = "", + default_month: int | None = None, + ) -> None: + super().__init__(parent) + self.ui: Ui_campaignDialog = Ui_campaignDialog() + self.ui.setupUi(self) # type: ignore + self.ui.campaignName.setText(default_name) + if default_month is not None: + self.ui.campaignMonth.setValue(default_month) + + def get_campaign_name(self) -> str: + return self.ui.campaignName.text().strip() + + def get_campaign_month(self) -> int: + return int(self.ui.campaignMonth.value()) diff --git a/src/warchron/view/campaign_participant_dialog.py b/src/warchron/view/campaign_participant_dialog.py new file mode 100644 index 0000000..ae0fd86 --- /dev/null +++ b/src/warchron/view/campaign_participant_dialog.py @@ -0,0 +1,40 @@ +from typing import cast, List + +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.controller.dtos import ParticipantOption +from warchron.view.helpers import select_if_exists +from warchron.view.ui.ui_campaign_participant_dialog import ( + Ui_campaignParticipantDialog, +) + + +class CampaignParticipantDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + *, + participants: List[ParticipantOption], + default_participant_id: str | None = None, + default_leader: str | None = "", + default_theme: str | None = "", + editable_player: bool = True, + ) -> None: + super().__init__(parent) + self.ui: Ui_campaignParticipantDialog = Ui_campaignParticipantDialog() + self.ui.setupUi(self) # type: ignore + for part in participants: + self.ui.playerComboBox.addItem(part.name, part.id) + select_if_exists(self.ui.playerComboBox, default_participant_id) + self.ui.playerComboBox.setEnabled(editable_player) + self.ui.leader.setText(default_leader) + self.ui.theme.setText(default_theme) + + def get_player_id(self) -> str: + return cast(str, self.ui.playerComboBox.currentData()) + + def get_participant_leader(self) -> str: + return self.ui.leader.text().strip() + + def get_participant_theme(self) -> str: + return self.ui.theme.text().strip() diff --git a/src/warchron/view/choices_dialog.py b/src/warchron/view/choices_dialog.py new file mode 100644 index 0000000..afaa79a --- /dev/null +++ b/src/warchron/view/choices_dialog.py @@ -0,0 +1,48 @@ +from typing import cast, List + +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.controller.dtos import ParticipantOption, SectorDTO +from warchron.view.helpers import select_if_exists +from warchron.view.ui.ui_choices_dialog import Ui_choicesDialog + + +class ChoicesDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + *, + participants: List[ParticipantOption], + default_participant_id: str | None = None, + sectors: List[SectorDTO], + default_priority_id: str | None = None, + default_secondary_id: str | None = None, + default_comment: str | None = None, + ) -> None: + super().__init__(parent) + self.ui: Ui_choicesDialog = Ui_choicesDialog() + self.ui.setupUi(self) # type: ignore + for part in participants: + self.ui.playerComboBox.addItem(part.name, part.id) + select_if_exists(self.ui.playerComboBox, default_participant_id) + self.ui.playerComboBox.setEnabled(False) + self.ui.priorityComboBox.addItem("(none)", None) + self.ui.secondaryComboBox.addItem("(none)", None) + for sect in sectors: + self.ui.priorityComboBox.addItem(sect.name, sect.id) + self.ui.secondaryComboBox.addItem(sect.name, sect.id) + select_if_exists(self.ui.priorityComboBox, default_priority_id) + select_if_exists(self.ui.secondaryComboBox, default_secondary_id) + self.ui.choiceComment.setPlainText(default_comment) + + def get_participant_id(self) -> str: + return cast(str, self.ui.playerComboBox.currentData()) + + def get_priority_id(self) -> str: + return cast(str, self.ui.priorityComboBox.currentData()) + + def get_secondary_id(self) -> str: + return cast(str, self.ui.secondaryComboBox.currentData()) + + def get_comment(self) -> str: + return self.ui.choiceComment.toPlainText().strip() diff --git a/src/warchron/view/helpers.py b/src/warchron/view/helpers.py new file mode 100644 index 0000000..3e2f585 --- /dev/null +++ b/src/warchron/view/helpers.py @@ -0,0 +1,27 @@ +import calendar + +from PyQt6.QtWidgets import QComboBox + +from warchron.controller.dtos import WarDTO, CampaignDTO + + +def select_if_exists(combo: QComboBox, value: str | None) -> None: + if value is None: + return + idx = combo.findData(value) + if idx != -1: + combo.setCurrentIndex(idx) + + +def format_war_label(war: WarDTO) -> str: + return f"{war.name} ({war.year})" + + +def format_campaign_label(camp: CampaignDTO) -> str: + return f"{camp.name} ({calendar.month_name[camp.month]})" + + +def format_round_label(index: int) -> str: + if index is None: + return "" + return f"Round {index}" diff --git a/src/warchron/view/objective_dialog.py b/src/warchron/view/objective_dialog.py new file mode 100644 index 0000000..a414c8b --- /dev/null +++ b/src/warchron/view/objective_dialog.py @@ -0,0 +1,24 @@ +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.view.ui.ui_objective_dialog import Ui_objectiveDialog + + +class ObjectiveDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + *, + default_name: str = "", + default_description: str | None = "", + ) -> None: + super().__init__(parent) + self.ui: Ui_objectiveDialog = Ui_objectiveDialog() + self.ui.setupUi(self) # type: ignore + self.ui.objectiveName.setText(default_name) + self.ui.objectiveDescription.setPlainText(default_description) + + def get_objective_name(self) -> str: + return self.ui.objectiveName.text().strip() + + def get_objective_description(self) -> str: + return self.ui.objectiveDescription.toPlainText().strip() diff --git a/src/warchron/view/player_dialog.py b/src/warchron/view/player_dialog.py new file mode 100644 index 0000000..af039e6 --- /dev/null +++ b/src/warchron/view/player_dialog.py @@ -0,0 +1,16 @@ +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.view.ui.ui_player_dialog import Ui_playerDialog + + +class PlayerDialog(QDialog): + def __init__( + self, parent: QWidget | None = None, *, default_name: str = "" + ) -> None: + super().__init__(parent) + self.ui: Ui_playerDialog = Ui_playerDialog() + self.ui.setupUi(self) # type: ignore + self.ui.playerName.setText(default_name) + + def get_player_name(self) -> str: + return self.ui.playerName.text().strip() diff --git a/src/warchron/view/sector_dialog.py b/src/warchron/view/sector_dialog.py new file mode 100644 index 0000000..74312dd --- /dev/null +++ b/src/warchron/view/sector_dialog.py @@ -0,0 +1,54 @@ +from typing import cast, List + +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.controller.dtos import ObjectiveDTO, RoundDTO +from warchron.view.helpers import select_if_exists, format_round_label +from warchron.view.ui.ui_sector_dialog import Ui_sectorDialog + + +class SectorDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + *, + default_name: str = "", + rounds: List[RoundDTO], + default_round_id: str | None = None, + objectives: List[ObjectiveDTO], + default_major_id: str | None = None, + default_minor_id: str | None = None, + default_influence_id: str | None = None, + ) -> None: + super().__init__(parent) + self.ui: Ui_sectorDialog = Ui_sectorDialog() + self.ui.setupUi(self) # type: ignore + self.ui.majorComboBox.addItem("(none)", None) + self.ui.minorComboBox.addItem("(none)", None) + self.ui.influenceComboBox.addItem("(none)", None) + self.ui.sectorName.setText(default_name) + for index, rnd in enumerate(rounds, start=1): + self.ui.roundComboBox.addItem(format_round_label(index), rnd.id) + select_if_exists(self.ui.roundComboBox, default_round_id) + for obj in objectives: + self.ui.majorComboBox.addItem(obj.name, obj.id) + self.ui.minorComboBox.addItem(obj.name, obj.id) + self.ui.influenceComboBox.addItem(obj.name, obj.id) + select_if_exists(self.ui.majorComboBox, default_major_id) + select_if_exists(self.ui.minorComboBox, default_minor_id) + select_if_exists(self.ui.influenceComboBox, default_influence_id) + + def get_sector_name(self) -> str: + return self.ui.sectorName.text().strip() + + def get_round_id(self) -> str: + return cast(str, self.ui.roundComboBox.currentData()) + + def get_major_id(self) -> str: + return cast(str, self.ui.majorComboBox.currentData()) + + def get_minor_id(self) -> str: + return cast(str, self.ui.minorComboBox.currentData()) + + def get_influence_id(self) -> str: + return cast(str, self.ui.influenceComboBox.currentData()) diff --git a/src/warchron/view/view.py b/src/warchron/view/view.py index 3b34fcf..8a86271 100644 --- a/src/warchron/view/view.py +++ b/src/warchron/view/view.py @@ -1,17 +1,10 @@ -from typing import cast, Callable, List +from typing import Callable, List from pathlib import Path import calendar from PyQt6 import QtWidgets from PyQt6.QtCore import Qt, QPoint -from PyQt6.QtWidgets import ( - QWidget, - QDialog, - QFileDialog, - QTreeWidgetItem, - QMenu, - QComboBox, -) +from PyQt6.QtWidgets import QWidget, QFileDialog, QTreeWidgetItem, QMenu from PyQt6.QtGui import QCloseEvent from warchron.constants import ROLE_TYPE, ROLE_ID, ItemType @@ -21,49 +14,17 @@ from warchron.controller.dtos import ( WarDTO, WarParticipantDTO, ObjectiveDTO, - CampaignDTO, CampaignParticipantDTO, SectorDTO, - RoundDTO, ChoiceDTO, BattleDTO, ) -from warchron.view.ui.ui_main_window import Ui_MainWindow -from warchron.view.ui.ui_player_dialog import Ui_playerDialog -from warchron.view.ui.ui_war_dialog import Ui_warDialog -from warchron.view.ui.ui_campaign_dialog import Ui_campaignDialog -from warchron.view.ui.ui_objective_dialog import Ui_objectiveDialog -from warchron.view.ui.ui_war_participant_dialog import Ui_warParticipantDialog -from warchron.view.ui.ui_campaign_participant_dialog import ( - Ui_campaignParticipantDialog, +from warchron.view.helpers import ( + format_campaign_label, + format_round_label, + format_war_label, ) -from warchron.view.ui.ui_sector_dialog import Ui_sectorDialog -from warchron.view.ui.ui_choices_dialog import Ui_choicesDialog -from warchron.view.ui.ui_battle_result_dialog import Ui_battleResultDialog - -# utils... - - -def select_if_exists(combo: QComboBox, value: str | None) -> None: - if value is None: - return - idx = combo.findData(value) - if idx != -1: - combo.setCurrentIndex(idx) - - -def format_war_label(war: WarDTO) -> str: - return f"{war.name} ({war.year})" - - -def format_campaign_label(camp: CampaignDTO) -> str: - return f"{camp.name} ({calendar.month_name[camp.month]})" - - -def format_round_label(index: int) -> str: - if index is None: - return "" - return f"Round {index}" +from warchron.view.ui.ui_main_window import Ui_MainWindow class View(QtWidgets.QMainWindow, Ui_MainWindow): @@ -517,285 +478,3 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): table.setItem(row, 1, player_1_item) table.setItem(row, 2, player_2_item) table.resizeColumnsToContents() - - -class PlayerDialog(QDialog): - def __init__( - self, parent: QWidget | None = None, *, default_name: str = "" - ) -> None: - super().__init__(parent) - self.ui: Ui_playerDialog = Ui_playerDialog() - self.ui.setupUi(self) # type: ignore - self.ui.playerName.setText(default_name) - - def get_player_name(self) -> str: - return self.ui.playerName.text().strip() - - -class WarDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - default_name: str = "", - default_year: int | None = None, - ) -> None: - super().__init__(parent) - self.ui: Ui_warDialog = Ui_warDialog() - self.ui.setupUi(self) # type: ignore - self.ui.warName.setText(default_name) - if default_year is not None: - self.ui.warYear.setValue(default_year) - - def get_war_name(self) -> str: - return self.ui.warName.text().strip() - - def get_war_year(self) -> int: - return int(self.ui.warYear.value()) - - -class CampaignDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - default_name: str = "", - default_month: int | None = None, - ) -> None: - super().__init__(parent) - self.ui: Ui_campaignDialog = Ui_campaignDialog() - self.ui.setupUi(self) # type: ignore - self.ui.campaignName.setText(default_name) - if default_month is not None: - self.ui.campaignMonth.setValue(default_month) - - def get_campaign_name(self) -> str: - return self.ui.campaignName.text().strip() - - def get_campaign_month(self) -> int: - return int(self.ui.campaignMonth.value()) - - -class ObjectiveDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - *, - default_name: str = "", - default_description: str | None = "", - ) -> None: - super().__init__(parent) - self.ui: Ui_objectiveDialog = Ui_objectiveDialog() - self.ui.setupUi(self) # type: ignore - self.ui.objectiveName.setText(default_name) - self.ui.objectiveDescription.setPlainText(default_description) - - def get_objective_name(self) -> str: - return self.ui.objectiveName.text().strip() - - def get_objective_description(self) -> str: - return self.ui.objectiveDescription.toPlainText().strip() - - -class WarParticipantDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - *, - players: List[ParticipantOption], - default_player_id: str | None = None, - default_faction: str | None = "", - editable_player: bool = True, - ): - super().__init__(parent) - self.ui: Ui_warParticipantDialog = Ui_warParticipantDialog() - self.ui.setupUi(self) # type: ignore - for player in players: - self.ui.playerComboBox.addItem(player.name, player.id) - select_if_exists(self.ui.playerComboBox, default_player_id) - self.ui.playerComboBox.setEnabled(editable_player) - self.ui.faction.setText(default_faction) - - def get_player_id(self) -> str: - return cast(str, self.ui.playerComboBox.currentData()) - - def get_participant_faction(self) -> str: - return self.ui.faction.text().strip() - - -class CampaignParticipantDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - *, - participants: List[ParticipantOption], - default_participant_id: str | None = None, - default_leader: str | None = "", - default_theme: str | None = "", - editable_player: bool = True, - ) -> None: - super().__init__(parent) - self.ui: Ui_campaignParticipantDialog = Ui_campaignParticipantDialog() - self.ui.setupUi(self) # type: ignore - for part in participants: - self.ui.playerComboBox.addItem(part.name, part.id) - select_if_exists(self.ui.playerComboBox, default_participant_id) - self.ui.playerComboBox.setEnabled(editable_player) - self.ui.leader.setText(default_leader) - self.ui.theme.setText(default_theme) - - def get_player_id(self) -> str: - return cast(str, self.ui.playerComboBox.currentData()) - - def get_participant_leader(self) -> str: - return self.ui.leader.text().strip() - - def get_participant_theme(self) -> str: - return self.ui.theme.text().strip() - - -class SectorDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - *, - default_name: str = "", - rounds: List[RoundDTO], - default_round_id: str | None = None, - objectives: List[ObjectiveDTO], - default_major_id: str | None = None, - default_minor_id: str | None = None, - default_influence_id: str | None = None, - ) -> None: - super().__init__(parent) - self.ui: Ui_sectorDialog = Ui_sectorDialog() - self.ui.setupUi(self) # type: ignore - self.ui.majorComboBox.addItem("(none)", None) - self.ui.minorComboBox.addItem("(none)", None) - self.ui.influenceComboBox.addItem("(none)", None) - self.ui.sectorName.setText(default_name) - for index, rnd in enumerate(rounds, start=1): - self.ui.roundComboBox.addItem(format_round_label(index), rnd.id) - select_if_exists(self.ui.roundComboBox, default_round_id) - for obj in objectives: - self.ui.majorComboBox.addItem(obj.name, obj.id) - self.ui.minorComboBox.addItem(obj.name, obj.id) - self.ui.influenceComboBox.addItem(obj.name, obj.id) - select_if_exists(self.ui.majorComboBox, default_major_id) - select_if_exists(self.ui.minorComboBox, default_minor_id) - select_if_exists(self.ui.influenceComboBox, default_influence_id) - - def get_sector_name(self) -> str: - return self.ui.sectorName.text().strip() - - def get_round_id(self) -> str: - return cast(str, self.ui.roundComboBox.currentData()) - - def get_major_id(self) -> str: - return cast(str, self.ui.majorComboBox.currentData()) - - def get_minor_id(self) -> str: - return cast(str, self.ui.minorComboBox.currentData()) - - def get_influence_id(self) -> str: - return cast(str, self.ui.influenceComboBox.currentData()) - - -class ChoicesDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - *, - participants: List[ParticipantOption], - default_participant_id: str | None = None, - sectors: List[SectorDTO], - default_priority_id: str | None = None, - default_secondary_id: str | None = None, - default_comment: str | None = None, - ) -> None: - super().__init__(parent) - self.ui: Ui_choicesDialog = Ui_choicesDialog() - self.ui.setupUi(self) # type: ignore - for part in participants: - self.ui.playerComboBox.addItem(part.name, part.id) - select_if_exists(self.ui.playerComboBox, default_participant_id) - self.ui.playerComboBox.setEnabled(False) - self.ui.priorityComboBox.addItem("(none)", None) - self.ui.secondaryComboBox.addItem("(none)", None) - for sect in sectors: - self.ui.priorityComboBox.addItem(sect.name, sect.id) - self.ui.secondaryComboBox.addItem(sect.name, sect.id) - select_if_exists(self.ui.priorityComboBox, default_priority_id) - select_if_exists(self.ui.secondaryComboBox, default_secondary_id) - self.ui.choiceComment.setPlainText(default_comment) - - def get_participant_id(self) -> str: - return cast(str, self.ui.playerComboBox.currentData()) - - def get_priority_id(self) -> str: - return cast(str, self.ui.priorityComboBox.currentData()) - - def get_secondary_id(self) -> str: - return cast(str, self.ui.secondaryComboBox.currentData()) - - def get_comment(self) -> str: - return self.ui.choiceComment.toPlainText().strip() - - -class BattlesDialog(QDialog): - def __init__( - self, - parent: QWidget | None = None, - *, - sectors: List[SectorDTO], - default_sector_id: str | None = None, - players: List[ParticipantOption], - default_player_1_id: str | None = None, - default_player_2_id: str | None = None, - default_winner_id: str | None = None, - default_score: str | None = None, - default_victory_condition: str | None = None, - default_comment: str | None = None, - ) -> None: - super().__init__(parent) - self.ui: Ui_battleResultDialog = Ui_battleResultDialog() - self.ui.setupUi(self) # type: ignore - for sect in sectors: - self.ui.sectorComboBox.addItem(sect.name, sect.id) - select_if_exists(self.ui.sectorComboBox, default_sector_id) - self.ui.sectorComboBox.setEnabled(False) - - self.ui.player1ComboBox.addItem("(none)", None) - self.ui.player2ComboBox.addItem("(none)", None) - for play in players: - self.ui.player1ComboBox.addItem(play.name, play.id) - self.ui.player2ComboBox.addItem(play.name, play.id) - select_if_exists(self.ui.player1ComboBox, default_player_1_id) - select_if_exists(self.ui.player2ComboBox, default_player_2_id) - self.ui.winnerComboBox.addItem("(none)", None) - for play in players: - if play.id in (default_player_1_id, default_player_2_id): - self.ui.winnerComboBox.addItem(play.name, play.id) - select_if_exists(self.ui.winnerComboBox, default_winner_id) - self.ui.score.setText(default_score) - self.ui.victoryCondition.setText(default_victory_condition) - self.ui.battleComment.setPlainText(default_comment) - - def get_sector_id(self) -> str: - return cast(str, self.ui.sectorComboBox.currentData()) - - def get_player_1_id(self) -> str: - return cast(str, self.ui.player1ComboBox.currentData()) - - def get_player_2_id(self) -> str: - return cast(str, self.ui.player2ComboBox.currentData()) - - def get_winner_id(self) -> str: - return cast(str, self.ui.winnerComboBox.currentData()) - - def get_score(self) -> str: - return self.ui.score.text().strip() - - def get_victory_condition(self) -> str: - return self.ui.victoryCondition.text().strip() - - def get_comment(self) -> str: - return self.ui.battleComment.toPlainText().strip() diff --git a/src/warchron/view/war_dialog.py b/src/warchron/view/war_dialog.py new file mode 100644 index 0000000..3d17a3f --- /dev/null +++ b/src/warchron/view/war_dialog.py @@ -0,0 +1,24 @@ +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.view.ui.ui_war_dialog import Ui_warDialog + + +class WarDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + default_name: str = "", + default_year: int | None = None, + ) -> None: + super().__init__(parent) + self.ui: Ui_warDialog = Ui_warDialog() + self.ui.setupUi(self) # type: ignore + self.ui.warName.setText(default_name) + if default_year is not None: + self.ui.warYear.setValue(default_year) + + def get_war_name(self) -> str: + return self.ui.warName.text().strip() + + def get_war_year(self) -> int: + return int(self.ui.warYear.value()) diff --git a/src/warchron/view/war_participant_dialog.py b/src/warchron/view/war_participant_dialog.py new file mode 100644 index 0000000..9718602 --- /dev/null +++ b/src/warchron/view/war_participant_dialog.py @@ -0,0 +1,33 @@ +from typing import cast, List + +from PyQt6.QtWidgets import QWidget, QDialog + +from warchron.controller.dtos import ParticipantOption +from warchron.view.helpers import select_if_exists +from warchron.view.ui.ui_war_participant_dialog import Ui_warParticipantDialog + + +class WarParticipantDialog(QDialog): + def __init__( + self, + parent: QWidget | None = None, + *, + players: List[ParticipantOption], + default_player_id: str | None = None, + default_faction: str | None = "", + editable_player: bool = True, + ): + super().__init__(parent) + self.ui: Ui_warParticipantDialog = Ui_warParticipantDialog() + self.ui.setupUi(self) # type: ignore + for player in players: + self.ui.playerComboBox.addItem(player.name, player.id) + select_if_exists(self.ui.playerComboBox, default_player_id) + self.ui.playerComboBox.setEnabled(editable_player) + self.ui.faction.setText(default_faction) + + def get_player_id(self) -> str: + return cast(str, self.ui.playerComboBox.currentData()) + + def get_participant_faction(self) -> str: + return self.ui.faction.text().strip()