add/edit/delet objectives and participants in war

This commit is contained in:
Maxime Réaux 2026-01-28 16:25:40 +01:00
parent e33dec40be
commit 495a5adb98
14 changed files with 1088 additions and 322 deletions

View file

@ -5,8 +5,8 @@ from PyQt6.QtWidgets import QMessageBox, QDialog
from warchron.model.model import Model
from warchron.view.view import View
from warchron.constants import ItemType
from warchron.view.view import PlayerDialog, WarDialog, CampaignDialog
from warchron.constants import ItemType, RefreshScope
from warchron.view.view import PlayerDialog, WarDialog, CampaignDialog, ObjectiveDialog, ParticipantDialog
class Controller:
def __init__(self, model: Model, view: View):
@ -35,6 +35,8 @@ class Controller:
self.view.actionSave_as.triggered.connect(self.save_as)
self.view.addPlayerBtn.clicked.connect(self.add_player)
self.view.addWarBtn.clicked.connect(self.add_war)
self.view.addObjectiveBtn.clicked.connect(self.add_objective)
self.view.addWarParticipantBtn.clicked.connect(self.add_war_participant)
self.view.on_edit_item = self.edit_item
self.view.on_delete_item = self.delete_item
@ -51,6 +53,8 @@ class Controller:
elif reply == QMessageBox.StandardButton.Cancel:
return False
return True
# Menu bar methods
def new(self):
if self.is_dirty:
@ -106,6 +110,8 @@ class Controller:
self.is_dirty = False
self.update_window_title()
# Display methods
def update_window_title(self):
base = "WarChron"
if self.current_file:
@ -124,17 +130,17 @@ class Controller:
wars = self.model.get_all_wars()
self.view.display_wars_tree(wars)
def refresh_views(self):
current = self.view.get_current_tab()
if current == "players":
self.refresh_players_view()
elif current == "wars":
self.refresh_wars_view()
def _fill_war_details(self, war_id: str):
war = self.model.get_war(war_id)
self.view.warName.setText(war.name)
self.view.warYear.setText(str(war.year))
self.view.show_war_details(name=war.name, year=war.year)
objectives = war.get_all_objectives()
self.view.display_war_objectives(objectives)
participants = war.get_all_war_participants()
participants_for_display = [
(self.model.get_player_name(p.id), p.faction, p.id)
for p in participants
]
self.view.display_war_participants(participants_for_display)
def _fill_campaign_details(self, campaign_id: str):
camp = self.model.get_campaign(campaign_id)
@ -173,6 +179,118 @@ class Controller:
self.view.set_add_campaign_enabled(self.selected_war_id is not None)
self.view.set_add_round_enabled(self.selected_campaign_id is not None)
def refresh(self, scope: RefreshScope):
match scope:
case RefreshScope.PLAYERS_LIST:
self.refresh_players_view()
case RefreshScope.WARS_TREE:
self.refresh_wars_view()
case RefreshScope.WAR_DETAILS:
if self.selected_war_id:
self.view.show_details(ItemType.WAR)
self._fill_war_details(self.selected_war_id)
case RefreshScope.CAMPAIGN_DETAILS:
if self.selected_campaign_id:
self.view.show_details(ItemType.CAMPAIGN)
self._fill_campaign_details(self.selected_campaign_id)
case RefreshScope.ROUND_DETAILS:
if self.selected_round_id:
self.view.show_details(ItemType.ROUND)
self._fill_round_details(self.selected_round_id)
self.update_window_title()
# Common command methods
def refresh_and_select(self, scope: RefreshScope, *, item_type: ItemType, item_id: str):
self.refresh(scope)
self.view.select_tree_item(item_type=item_type, item_id=item_id)
def edit_item(self, item_type: str, item_id: str):
if item_type == ItemType.PLAYER:
play = self.model.get_player(item_id)
dialog = PlayerDialog(self.view, default_name=play.name)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_player_name()
if not self._validate_player_inputs(name):
return
self.model.update_player(item_id, name=name)
self.refresh(RefreshScope.PLAYERS_LIST)
elif item_type == ItemType.WAR:
war = self.model.get_war(item_id)
dialog = WarDialog(self.view, default_name=war.name, default_year=war.year)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_war_name()
year = dialog.get_war_year()
if not self._validate_war_inputs(name, year):
return
self.model.update_war(item_id, name=name, year=year)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war.id)
elif item_type == ItemType.CAMPAIGN:
camp = self.model.get_campaign(item_id)
dialog = CampaignDialog(self.view, default_name=camp.name, default_month=camp.month)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_campaign_name()
month = dialog.get_campaign_month()
if not self._validate_campaign_inputs(name, month):
return
self.model.update_campaign(item_id, name=name, month=month)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp.id)
elif item_type == ItemType.OBJECTIVE:
obj = self.model.get_objective(item_id)
dialog = ObjectiveDialog(self.view, default_name=obj.name, default_description=obj.description)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_objective_name()
description = dialog.get_objective_description()
if not self._validate_objective_inputs(name, description):
return
self.model.update_objective(item_id, name=name, description=description)
self.refresh(RefreshScope.WAR_DETAILS)
elif item_type == ItemType.WAR_PARTICIPANT:
part = self.model.get_war_participant(item_id)
player = self.model.get_player(part.id)
dialog = ParticipantDialog(self.view, players=[player], default_player_id=part.id, default_faction=part.faction)
if dialog.exec() == QDialog.DialogCode.Accepted:
id = dialog.get_player_id()
faction = dialog.get_participant_faction()
self.model.update_war_participant(item_id, faction=faction)
self.refresh(RefreshScope.WAR_DETAILS)
self.is_dirty = True
def delete_item(self, item_type: str, item_id: str):
reply = QMessageBox.question(
self.view,
"Confirm deletion",
"Are you sure you want to delete this item?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
)
if reply != QMessageBox.StandardButton.Yes:
return
if item_type == ItemType.PLAYER:
self.model.remove_player(item_id)
self.refresh(RefreshScope.PLAYERS_LIST)
elif item_type == ItemType.WAR:
self.model.remove_war(item_id)
self.refresh(RefreshScope.WARS_TREE)
elif item_type == ItemType.CAMPAIGN:
war = self.model.get_war_by_campaign(item_id)
war_id = war.id
self.model.remove_campaign(item_id)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war_id)
elif item_type == ItemType.OBJECTIVE:
self.model.remove_objective(item_id)
self.refresh(RefreshScope.WAR_DETAILS)
elif item_type == ItemType.WAR_PARTICIPANT:
self.model.remove_war_participant(item_id)
self.refresh(RefreshScope.WAR_DETAILS)
elif item_type == ItemType.ROUND:
camp = self.model.get_campaign_by_round(item_id)
camp_id = camp.id
self.model.remove_round(item_id)
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp_id)
self.is_dirty = True
# Player methods
def _validate_player_inputs(self, name: str) -> bool:
if not name.strip():
QMessageBox.warning(
@ -192,8 +310,9 @@ class Controller:
return
self.model.add_player(name)
self.is_dirty = True
self.refresh_players_view()
self.update_window_title()
self.refresh(RefreshScope.PLAYERS_LIST)
# War methods
def _validate_war_inputs(self, name: str, year: int) -> bool:
if not name.strip():
@ -220,10 +339,54 @@ class Controller:
year = dialog.get_war_year()
if not self._validate_war_inputs(name, year):
return
self.model.add_war(name, year)
war = self.model.add_war(name, year)
self.is_dirty = True
self.refresh_wars_view()
self.update_window_title()
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.WAR, item_id=war.id)
# Objective methods
def _validate_objective_inputs(self, name: str, description: int) -> bool:
if not name.strip():
QMessageBox.warning(
self.view,
"Invalid name",
"Campaign name cannot be empty."
)
return False
return True
def add_objective(self):
if not self.selected_war_id:
return
dialog = ObjectiveDialog(self.view)
if dialog.exec() != QDialog.DialogCode.Accepted:
return
name = dialog.get_objective_name()
description = dialog.get_objective_description()
if not name:
return
self.model.add_objective(self.selected_war_id, name, description)
self.is_dirty = True
self.refresh(RefreshScope.WAR_DETAILS)
# War participant methods
def add_war_participant(self):
if not self.selected_war_id:
return
players = self.model.get_available_players(self.selected_war_id)
dialog = ParticipantDialog(self.view, players=players)
if dialog.exec() != QDialog.DialogCode.Accepted:
return
player_id = dialog.get_player_id()
faction = dialog.get_participant_faction()
if not player_id:
return
self.model.add_war_participant(self.selected_war_id, player_id, faction)
self.is_dirty = True
self.refresh(RefreshScope.WAR_DETAILS)
# Campaign methods
def _validate_campaign_inputs(self, name: str, month: int) -> bool:
if not name.strip():
@ -252,66 +415,15 @@ class Controller:
month = dialog.get_campaign_month()
if not self._validate_campaign_inputs(name, month):
return
self.model.add_campaign(self.selected_war_id, name, month)
camp = self.model.add_campaign(self.selected_war_id, name, month)
self.is_dirty = True
self.refresh_wars_view()
self.update_window_title()
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.CAMPAIGN, item_id=camp.id)
# Round methods
def add_round(self):
if not self.selected_campaign_id:
return
self.model.add_round(self.selected_campaign_id)
rnd = self.model.add_round(self.selected_campaign_id)
self.is_dirty = True
self.refresh_wars_view()
self.update_window_title()
def edit_item(self, item_type: str, item_id: str):
if item_type == "player":
play = self.model.get_player(item_id)
dialog = PlayerDialog(self.view, default_name=play.name)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_player_name()
if not self._validate_player_inputs(name):
return
self.model.update_player(item_id, name=name)
elif item_type == "war":
war = self.model.get_war(item_id)
dialog = WarDialog(self.view, default_name=war.name, default_year=war.year)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_war_name()
year = dialog.get_war_year()
if not self._validate_war_inputs(name, year):
return
self.model.update_war(item_id, name=name, year=year)
elif item_type == "campaign":
camp = self.model.get_campaign(item_id)
dialog = CampaignDialog(self.view, default_name=camp.name, default_month=camp.month)
if dialog.exec() == QDialog.DialogCode.Accepted:
name = dialog.get_campaign_name()
month = dialog.get_campaign_month()
if not self._validate_campaign_inputs(name, month):
return
self.model.update_campaign(item_id, name=name, month=month)
self.is_dirty = True
self.refresh_views()
def delete_item(self, item_type: str, item_id: str):
reply = QMessageBox.question(
self.view,
"Confirm deletion",
"Are you sure you want to delete this item?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
)
if reply != QMessageBox.StandardButton.Yes:
return
if item_type == "player":
self.model.remove_player(item_id)
elif item_type == "war":
self.model.remove_war(item_id)
elif item_type == "campaign":
self.model.remove_campaign(item_id)
elif item_type == "round":
self.model.remove_round(item_id)
self.is_dirty = True
self.refresh_views()
self.refresh_and_select(RefreshScope.WARS_TREE, item_type=ItemType.ROUND, item_id=rnd.id)