edit/delete player/war/campaign/round

This commit is contained in:
Maxime Réaux 2026-01-22 23:42:47 +01:00
parent dc854b4065
commit 185733b5d4
9 changed files with 363 additions and 58 deletions

View file

@ -1,4 +1,5 @@
from pathlib import Path from pathlib import Path
from datetime import datetime
from PyQt6.QtWidgets import QMessageBox, QDialog from PyQt6.QtWidgets import QMessageBox, QDialog
from warchron.model.model import Model from warchron.model.model import Model
@ -33,6 +34,8 @@ class Controller:
self.view.actionSave_as.triggered.connect(self.save_as) self.view.actionSave_as.triggered.connect(self.save_as)
self.view.addPlayerBtn.clicked.connect(self.add_player) self.view.addPlayerBtn.clicked.connect(self.add_player)
self.view.addWarBtn.clicked.connect(self.add_war) self.view.addWarBtn.clicked.connect(self.add_war)
self.view.on_edit_item = self.edit_item
self.view.on_delete_item = self.delete_item
def on_app_close(self) -> bool: def on_app_close(self) -> bool:
if self.is_dirty: if self.is_dirty:
@ -120,6 +123,13 @@ class Controller:
wars = self.model.get_all_wars() wars = self.model.get_all_wars()
self.view.display_wars(wars) self.view.display_wars(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 on_tree_selection_changed(self, selection): def on_tree_selection_changed(self, selection):
self.selected_war_id = None self.selected_war_id = None
self.selected_campaign_id = None self.selected_campaign_id = None
@ -137,50 +147,86 @@ class Controller:
self.view.set_add_campaign_enabled(self.selected_war_id is not None) 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) self.view.set_add_round_enabled(self.selected_campaign_id is not None)
def add_player(self): def _validate_player_inputs(self, name: str) -> bool:
dialog = PlayerDialog(self.view) if not name.strip():
result = dialog.exec() # modal blocking dialog
if result == QDialog.DialogCode.Accepted:
name = dialog.get_player_name()
if not name:
QMessageBox.warning( QMessageBox.warning(
self.view, self.view,
"Invalid name", "Invalid name",
"Player name cannot be empty." "Player name cannot be empty."
) )
return False
return True
def add_player(self):
dialog = PlayerDialog(self.view)
result = dialog.exec() # modal blocking dialog
if result == QDialog.DialogCode.Accepted:
name = dialog.get_player_name()
if not self._validate_player_inputs(name):
return return
self.model.add_player(name) self.model.add_player(name)
self.is_dirty = True self.is_dirty = True
self.refresh_players_view() self.refresh_players_view()
self.update_window_title() self.update_window_title()
def add_war(self): def _validate_war_inputs(self, name: str, year: int) -> bool:
dialog = WarDialog(self.view) if not name.strip():
result = dialog.exec() # modal blocking dialog
if result == QDialog.DialogCode.Accepted:
name = dialog.get_war_name()
if not name:
QMessageBox.warning( QMessageBox.warning(
self.view, self.view,
"Invalid name", "Invalid name",
"War name cannot be empty." "War name cannot be empty."
) )
return False
if not (1970 <= year <= 3000):
QMessageBox.warning(
self.view,
"Invalid year",
"Year must be between 1970 and 3000."
)
return False
return True
def add_war(self):
dialog = WarDialog(self.view, default_year=self.model.get_default_war_values()["year"])
result = dialog.exec() # modal blocking dialog
if result == QDialog.DialogCode.Accepted:
name = dialog.get_war_name()
year = dialog.get_war_year()
if not self._validate_war_inputs(name, year):
return return
self.model.add_war(name) self.model.add_war(name, year)
self.is_dirty = True self.is_dirty = True
self.refresh_wars_view() self.refresh_wars_view()
self.update_window_title() self.update_window_title()
def _validate_campaign_inputs(self, name: str, month: int) -> bool:
if not name.strip():
QMessageBox.warning(
self.view,
"Invalid name",
"Campaign name cannot be empty."
)
return False
if not (1 <= month <= 12):
QMessageBox.warning(
self.view,
"Invalid month",
"Month must be between 1 and 12."
)
return False
return True
def add_campaign(self): def add_campaign(self):
if not self.selected_war_id: if not self.selected_war_id:
return return
dialog = CampaignDialog(self.view) dialog = CampaignDialog(self.view, default_month=self.model.get_default_campaign_values(self.selected_war_id)["month"])
if dialog.exec() != QDialog.DialogCode.Accepted: if dialog.exec() != QDialog.DialogCode.Accepted:
return return
name = dialog.get_campaign_name() name = dialog.get_campaign_name()
if not name: month = dialog.get_campaign_month()
if not self._validate_campaign_inputs(name, month):
return return
self.model.add_campaign(self.selected_war_id, name) self.model.add_campaign(self.selected_war_id, name, month)
self.is_dirty = True self.is_dirty = True
self.refresh_wars_view() self.refresh_wars_view()
self.update_window_title() self.update_window_title()
@ -192,3 +238,54 @@ class Controller:
self.is_dirty = True self.is_dirty = True
self.refresh_wars_view() self.refresh_wars_view()
self.update_window_title() 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()

View file

@ -4,10 +4,10 @@ from datetime import datetime
from warchron.model.round import Round from warchron.model.round import Round
class Campaign: class Campaign:
def __init__(self, name): def __init__(self, name, month):
self.id = str(uuid4()) self.id = str(uuid4())
self.name = name self.name = name
self.month = datetime.now().month self.month = month
self.entrants = {} self.entrants = {}
self.rounds = [] self.rounds = []
self.is_over = False self.is_over = False
@ -36,20 +36,14 @@ class Campaign:
@staticmethod @staticmethod
def fromDict(data: dict): def fromDict(data: dict):
camp = Campaign(name=data["name"]) camp = Campaign(name=data["name"], month=data["month"])
camp.set_id(data["id"]) camp.set_id(data["id"])
camp.set_month(data["month"])
# camp.entrants = data.get("entrants", {}) # camp.entrants = data.get("entrants", {})
for rnd_data in data.get("rounds", []): for rnd_data in data.get("rounds", []):
camp.rounds.append(Round.fromDict(rnd_data)) camp.rounds.append(Round.fromDict(rnd_data))
camp.set_state(data.get("is_over", False)) camp.set_state(data.get("is_over", False))
return camp return camp
def add_round(self, number: int) -> Round:
round = Round()
self.rounds.append(round)
return round
def get_round(self, round_id) -> Round: def get_round(self, round_id) -> Round:
return self.rounds[round_id] return self.rounds[round_id]
@ -60,3 +54,8 @@ class Campaign:
round = Round() round = Round()
self.rounds.append(round) self.rounds.append(round)
return round return round
def remove_round(self, round_id: str):
rnd = next((r for r in self.rounds if r.id == round_id), None)
if rnd:
self.rounds.remove(rnd)

View file

@ -1,6 +1,7 @@
from pathlib import Path from pathlib import Path
import json import json
import shutil import shutil
from datetime import datetime
from warchron.model.player import Player from warchron.model.player import Player
from warchron.model.war import War from warchron.model.war import War
@ -60,8 +61,8 @@ class Model:
def get_player(self, id): def get_player(self, id):
return self.players[id] return self.players[id]
def update_player(self, id, name): def update_player(self, player_id: str, *, name: str):
player = self.get_player(id) player = self.get_player(player_id)
player.set_name(name) player.set_name(name)
def delete_player(self, id): def delete_player(self, id):
@ -70,20 +71,41 @@ class Model:
def get_all_players(self) -> list[Player]: def get_all_players(self) -> list[Player]:
return list(self.players.values()) return list(self.players.values())
def add_war(self, name) -> War: def get_default_war_values(self) -> dict:
war = War(name) return {
"year": datetime.now().year
}
def add_war(self, name: str, year: int) -> War:
war = War(name, year)
self.wars[war.id] = war self.wars[war.id] = war
return war return war
def get_war(self, id) -> War: def get_war(self, id) -> War:
return self.wars[id] return self.wars[id]
def get_war_by_campaign(self, campaign_id: str) -> War:
for war in self.wars.values():
for camp in war.campaigns:
if camp.id == campaign_id:
return war
raise KeyError(f"Campaign {campaign_id} not found in any War")
def update_war(self, war_id: str, *, name: str, year: int):
war = self.get_war(war_id)
war.set_name(name)
war.set_year(year)
def get_all_wars(self) -> list[War]: def get_all_wars(self) -> list[War]:
return list(self.wars.values()) return list(self.wars.values())
def add_campaign(self, war_id: str, name: str) -> Campaign: def get_default_campaign_values(self, war_id: str) -> dict:
war = self.get_war(war_id) war = self.get_war(war_id)
return war.add_campaign(name) return war.get_default_campaign_values()
def add_campaign(self, war_id: str, name: str, month: int) -> Campaign:
war = self.get_war(war_id)
return war.add_campaign(name, month)
def get_campaign(self, campaign_id) -> Campaign: def get_campaign(self, campaign_id) -> Campaign:
for war in self.wars.values(): for war in self.wars.values():
@ -92,6 +114,17 @@ class Model:
return campaign return campaign
raise KeyError("Campaign not found") raise KeyError("Campaign not found")
def get_campaign_by_round(self, round_id: str) -> Campaign:
for war in self.wars.values():
camp = war.get_campaign_by_round(round_id)
if camp is not None:
return camp
raise KeyError(f"Round {round_id} not found")
def update_campaign(self, campaign_id: str, *, name: str, month: int):
war = self.get_war_by_campaign(campaign_id)
war.update_campaign(campaign_id, name=name, month=month)
def add_round(self, campaign_id: str) -> Round: def add_round(self, campaign_id: str) -> Round:
campaign = self.get_campaign(campaign_id) campaign = self.get_campaign(campaign_id)
return campaign.add_round() return campaign.add_round()
@ -103,3 +136,17 @@ class Model:
if rnd.id == round_id: if rnd.id == round_id:
return rnd return rnd
raise KeyError("Round not found") raise KeyError("Round not found")
def remove_player(self, player_id: str):
del self.players[player_id]
def remove_war(self, war_id: str):
del self.wars[war_id]
def remove_campaign(self, campaign_id: str):
war = self.get_war_by_campaign(campaign_id)
war.remove_campaign(campaign_id)
def remove_round(self, round_id: str):
camp = self.get_campaign_by_round(round_id)
camp.remove_round(round_id)

View file

@ -4,10 +4,10 @@ from datetime import datetime
from warchron.model.campaign import Campaign from warchron.model.campaign import Campaign
class War: class War:
def __init__(self, name): def __init__(self, name, year):
self.id = str(uuid4()) self.id = str(uuid4())
self.name = name self.name = name
self.year = datetime.now().year self.year = year
self.entrants = {} self.entrants = {}
self.campaigns = [] self.campaigns = []
self.is_over = False self.is_over = False
@ -36,27 +36,47 @@ class War:
@staticmethod @staticmethod
def fromDict(data: dict): def fromDict(data: dict):
war = War(name=data["name"]) war = War(name=data["name"], year=data["year"])
war.set_id(data["id"]) war.set_id(data["id"])
war.set_year(data["year"])
# war.entrants = data.get("entrants", {}) # war.entrants = data.get("entrants", {})
for camp_data in data.get("campaigns", []): for camp_data in data.get("campaigns", []):
war.campaigns.append(Campaign.fromDict(camp_data)) war.campaigns.append(Campaign.fromDict(camp_data))
war.set_state(data.get("is_over", False)) war.set_state(data.get("is_over", False))
return war return war
def add_campaign(self, name) -> Campaign: def get_default_campaign_values(self) -> dict:
campaign = Campaign(name) return {
"month": datetime.now().month
}
def add_campaign(self, name: str, month: int | None = None) -> Campaign:
if month is None:
month = self.get_default_campaign_values()["month"]
campaign = Campaign(name, month)
self.campaigns.append(campaign) self.campaigns.append(campaign)
return campaign return campaign
def get_campaign(self, campaign_id) -> Campaign: def get_campaign(self, campaign_id) -> Campaign:
return self.campaigns[campaign_id] for camp in self.campaigns:
if camp.id == campaign_id:
return camp
raise KeyError(f"Campaign {campaign_id} not found in War {self.id}")
def get_campaign_by_round(self, round_id: str) -> Campaign:
for camp in self.campaigns:
for rnd in camp.rounds:
if rnd.id == round_id:
return camp
raise KeyError(f"Round {round_id} not found in any Campaign")
def update_campaign(self, campaign_id: str, *, name: str, month: int):
camp = self.get_campaign(campaign_id)
camp.set_name(name)
camp.set_month(month)
def get_all_campaigns(self) -> list[Campaign]: def get_all_campaigns(self) -> list[Campaign]:
return list(self.campaigns) return list(self.campaigns)
def add_campaign(self, name: str) -> Campaign: def remove_campaign(self, campaign_id: str):
campaign = Campaign(name) camp = self.get_campaign(campaign_id)
self.campaigns.append(campaign) self.campaigns.remove(camp)
return campaign

View file

@ -28,6 +28,14 @@ class Ui_campaignDialog(object):
self.campaignName = QtWidgets.QLineEdit(parent=campaignDialog) self.campaignName = QtWidgets.QLineEdit(parent=campaignDialog)
self.campaignName.setGeometry(QtCore.QRect(60, 20, 113, 20)) self.campaignName.setGeometry(QtCore.QRect(60, 20, 113, 20))
self.campaignName.setObjectName("campaignName") self.campaignName.setObjectName("campaignName")
self.label_2 = QtWidgets.QLabel(parent=campaignDialog)
self.label_2.setGeometry(QtCore.QRect(10, 50, 47, 14))
self.label_2.setObjectName("label_2")
self.campaignMonth = QtWidgets.QSpinBox(parent=campaignDialog)
self.campaignMonth.setGeometry(QtCore.QRect(60, 50, 71, 22))
self.campaignMonth.setMinimum(1)
self.campaignMonth.setMaximum(12)
self.campaignMonth.setObjectName("campaignMonth")
self.retranslateUi(campaignDialog) self.retranslateUi(campaignDialog)
self.buttonBox.accepted.connect(campaignDialog.accept) # type: ignore self.buttonBox.accepted.connect(campaignDialog.accept) # type: ignore
@ -38,6 +46,7 @@ class Ui_campaignDialog(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
campaignDialog.setWindowTitle(_translate("campaignDialog", "Campaign")) campaignDialog.setWindowTitle(_translate("campaignDialog", "Campaign"))
self.label.setText(_translate("campaignDialog", "Name:")) self.label.setText(_translate("campaignDialog", "Name:"))
self.label_2.setText(_translate("campaignDialog", "Month:"))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -59,6 +59,35 @@
</rect> </rect>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>47</width>
<height>14</height>
</rect>
</property>
<property name="text">
<string>Month:</string>
</property>
</widget>
<widget class="QSpinBox" name="campaignMonth">
<property name="geometry">
<rect>
<x>60</x>
<y>50</y>
<width>71</width>
<height>22</height>
</rect>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>12</number>
</property>
</widget>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>

View file

@ -13,12 +13,12 @@ class Ui_warDialog(object):
def setupUi(self, warDialog): def setupUi(self, warDialog):
warDialog.setObjectName("warDialog") warDialog.setObjectName("warDialog")
warDialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) warDialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
warDialog.resize(378, 98) warDialog.resize(378, 124)
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(".\\src\\warchron\\view\\ui\\../resources/warchron_logo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off) icon.addPixmap(QtGui.QPixmap(".\\src\\warchron\\view\\ui\\../resources/warchron_logo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
warDialog.setWindowIcon(icon) warDialog.setWindowIcon(icon)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=warDialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=warDialog)
self.buttonBox.setGeometry(QtCore.QRect(10, 60, 341, 32)) self.buttonBox.setGeometry(QtCore.QRect(10, 80, 341, 32))
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
@ -28,6 +28,14 @@ class Ui_warDialog(object):
self.warName = QtWidgets.QLineEdit(parent=warDialog) self.warName = QtWidgets.QLineEdit(parent=warDialog)
self.warName.setGeometry(QtCore.QRect(60, 20, 113, 20)) self.warName.setGeometry(QtCore.QRect(60, 20, 113, 20))
self.warName.setObjectName("warName") self.warName.setObjectName("warName")
self.label_2 = QtWidgets.QLabel(parent=warDialog)
self.label_2.setGeometry(QtCore.QRect(10, 50, 47, 14))
self.label_2.setObjectName("label_2")
self.warYear = QtWidgets.QSpinBox(parent=warDialog)
self.warYear.setGeometry(QtCore.QRect(60, 50, 71, 22))
self.warYear.setMinimum(1970)
self.warYear.setMaximum(3000)
self.warYear.setObjectName("warYear")
self.retranslateUi(warDialog) self.retranslateUi(warDialog)
self.buttonBox.accepted.connect(warDialog.accept) # type: ignore self.buttonBox.accepted.connect(warDialog.accept) # type: ignore
@ -38,6 +46,7 @@ class Ui_warDialog(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
warDialog.setWindowTitle(_translate("warDialog", "War")) warDialog.setWindowTitle(_translate("warDialog", "War"))
self.label.setText(_translate("warDialog", "Name:")) self.label.setText(_translate("warDialog", "Name:"))
self.label_2.setText(_translate("warDialog", "Year:"))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -10,7 +10,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>378</width> <width>378</width>
<height>98</height> <height>124</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -24,7 +24,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>60</y> <y>80</y>
<width>341</width> <width>341</width>
<height>32</height> <height>32</height>
</rect> </rect>
@ -59,6 +59,35 @@
</rect> </rect>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>47</width>
<height>14</height>
</rect>
</property>
<property name="text">
<string>Year:</string>
</property>
</widget>
<widget class="QSpinBox" name="warYear">
<property name="geometry">
<rect>
<x>60</x>
<y>50</y>
<width>71</width>
<height>22</height>
</rect>
</property>
<property name="minimum">
<number>1970</number>
</property>
<property name="maximum">
<number>3000</number>
</property>
</widget>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>

View file

@ -3,7 +3,7 @@ import calendar
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from PyQt6.QtCore import Qt from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QDialog, QFileDialog, QTreeWidgetItem from PyQt6.QtWidgets import QDialog, QFileDialog, QTreeWidgetItem, QMenu
from PyQt6.QtGui import QCloseEvent from PyQt6.QtGui import QCloseEvent
from warchron.view.ui.ui_main_window import Ui_MainWindow from warchron.view.ui.ui_main_window import Ui_MainWindow
@ -22,7 +22,13 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
self.on_selection_changed = None self.on_selection_changed = None
self.on_add_campaign = None self.on_add_campaign = None
self.on_add_round = None self.on_add_round = None
self.on_edit_item = None
self.on_delete_item = None
self.playersTable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.playersTable.customContextMenuRequested.connect(self._on_players_table_context_menu)
self.warsTree.currentItemChanged.connect(self._emit_selection_changed) self.warsTree.currentItemChanged.connect(self._emit_selection_changed)
self.warsTree.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.warsTree.customContextMenuRequested.connect(self._on_wars_tree_context_menu)
self.addCampaignBtn.clicked.connect(self._on_add_campaign_clicked) self.addCampaignBtn.clicked.connect(self._on_add_campaign_clicked)
self.addRoundBtn.clicked.connect(self._on_add_round_clicked) self.addRoundBtn.clicked.connect(self._on_add_round_clicked)
@ -37,6 +43,41 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
"id": current.data(0, ROLE_ID), "id": current.data(0, ROLE_ID),
}) })
def _on_players_table_context_menu(self, pos):
item = self.playersTable.itemAt(pos)
if not item:
return
row = item.row()
player_item = self.playersTable.item(row, 0)
player_id = player_item.data(Qt.ItemDataRole.UserRole)
menu = QMenu(self)
edit_action = menu.addAction("Edit")
delete_action = menu.addAction("Delete")
action = menu.exec(self.playersTable.viewport().mapToGlobal(pos))
if action == edit_action and self.on_edit_item:
self.on_edit_item("player", player_id)
elif action == delete_action and self.on_delete_item:
self.on_delete_item("player", player_id)
def _on_wars_tree_context_menu(self, pos):
item = self.warsTree.itemAt(pos)
if not item:
return
item_type = item.data(0, ROLE_TYPE)
item_id = item.data(0, ROLE_ID)
menu = QMenu(self)
edit_action = None
if item_type != "round":
edit_action = menu.addAction("Edit")
delete_action = menu.addAction("Delete")
action = menu.exec(self.warsTree.viewport().mapToGlobal(pos))
if action == edit_action:
if self.on_edit_item:
self.on_edit_item(item_type, item_id)
elif action == delete_action:
if self.on_delete_item:
self.on_delete_item(item_type, item_id)
def _on_add_campaign_clicked(self): def _on_add_campaign_clicked(self):
if self.on_add_campaign: if self.on_add_campaign:
self.on_add_campaign() self.on_add_campaign()
@ -75,8 +116,12 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
table = self.playersTable table = self.playersTable
table.setRowCount(len(players)) table.setRowCount(len(players))
for row, player in enumerate(players): for row, player in enumerate(players):
table.setItem(row, 0, QtWidgets.QTableWidgetItem(player.name)) name_item = QtWidgets.QTableWidgetItem(player.name)
table.setItem(row, 1, QtWidgets.QTableWidgetItem(player.id)) name_item.setData(Qt.ItemDataRole.UserRole, player.id)
table.setItem(row, 0, name_item)
id_item = QtWidgets.QTableWidgetItem(player.id)
id_item.setFlags(id_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
table.setItem(row, 1, id_item)
table.resizeColumnsToContents() table.resizeColumnsToContents()
def display_wars(self, wars: list): def display_wars(self, wars: list):
@ -116,29 +161,50 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
def set_add_round_enabled(self, enabled: bool): def set_add_round_enabled(self, enabled: bool):
self.addRoundBtn.setEnabled(enabled) self.addRoundBtn.setEnabled(enabled)
def get_current_tab(self) -> str:
index = self.tabWidget.currentIndex()
if index == 0:
return "players"
elif index == 1:
return "wars"
return ""
class PlayerDialog(QDialog): class PlayerDialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None, *, default_name: str = ""):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_playerDialog() self.ui = Ui_playerDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.playerName.setText(default_name)
def get_player_name(self) -> str: def get_player_name(self) -> str:
return self.ui.playerName.text().strip() return self.ui.playerName.text().strip()
class WarDialog(QDialog): class WarDialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None, default_name: str = "", default_year: int | None = None):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_warDialog() self.ui = Ui_warDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.warName.setText(default_name)
if default_year is not None:
self.ui.warYear.setValue(default_year)
def get_war_name(self) -> str: def get_war_name(self) -> str:
return self.ui.warName.text().strip() return self.ui.warName.text().strip()
def get_war_year(self) -> int:
return int(self.ui.warYear.value())
class CampaignDialog(QDialog): class CampaignDialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None, default_name: str = "", default_month: int | None = None):
super().__init__(parent) super().__init__(parent)
self.ui = Ui_campaignDialog() self.ui = Ui_campaignDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.campaignName.setText(default_name)
if default_month is not None:
self.ui.campaignMonth.setValue(default_month)
def get_campaign_name(self) -> str: def get_campaign_name(self) -> str:
return self.ui.campaignName.text().strip() return self.ui.campaignName.text().strip()
def get_campaign_month(self) -> int:
return int(self.ui.campaignMonth.value())