diff --git a/src/warchron/controller/controller.py b/src/warchron/controller/controller.py
index a247488..15a9461 100644
--- a/src/warchron/controller/controller.py
+++ b/src/warchron/controller/controller.py
@@ -1,20 +1,29 @@
from pathlib import Path
from PyQt6.QtWidgets import QMessageBox, QDialog
+from warchron.model.model import Model
+from warchron.view.view import View
-from warchron.view.view import PlayerDialog, WarDialog
+from warchron.view.view import PlayerDialog, WarDialog, CampaignDialog
class Controller:
- def __init__(self, model, view):
+ def __init__(self, model: Model, view: View):
self.model = model
self.view = view
self.current_file: Path | None = None
+ self.selected_war_id = None
+ self.selected_campaign_id = None
+ self.selected_round_id = None
self.view.on_close_callback = self.on_app_close
self.is_dirty = False
self.__connect()
self.refresh_players_view()
self.refresh_wars_view()
self.update_window_title()
+ self.update_actions_state()
+ self.view.on_tree_selection_changed = self.on_tree_selection_changed
+ self.view.on_add_campaign = self.add_campaign
+ self.view.on_add_round = self.add_round
def __connect(self):
self.view.actionExit.triggered.connect(self.view.close)
@@ -107,6 +116,27 @@ class Controller:
players = self.model.get_all_players()
self.view.display_players(players)
+ def refresh_wars_view(self):
+ wars = self.model.get_all_wars()
+ self.view.display_wars(wars)
+
+ def on_tree_selection_changed(self, selection):
+ self.selected_war_id = None
+ self.selected_campaign_id = None
+ self.selected_round_id = None
+ if selection:
+ if selection["type"] == "war":
+ self.selected_war_id = selection["id"]
+ elif selection["type"] == "campaign":
+ self.selected_campaign_id = selection["id"]
+ elif selection["type"] == "round":
+ self.selected_round_id = selection["id"]
+ self.update_actions_state()
+
+ def update_actions_state(self):
+ 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 add_player(self):
dialog = PlayerDialog(self.view)
result = dialog.exec() # modal blocking dialog
@@ -123,11 +153,7 @@ class Controller:
self.is_dirty = True
self.refresh_players_view()
self.update_window_title()
-
- def refresh_wars_view(self):
- wars = self.model.get_all_wars()
- self.view.display_wars(wars)
-
+
def add_war(self):
dialog = WarDialog(self.view)
result = dialog.exec() # modal blocking dialog
@@ -144,3 +170,25 @@ class Controller:
self.is_dirty = True
self.refresh_wars_view()
self.update_window_title()
+
+ def add_campaign(self):
+ if not self.selected_war_id:
+ return
+ dialog = CampaignDialog(self.view)
+ if dialog.exec() != QDialog.DialogCode.Accepted:
+ return
+ name = dialog.get_campaign_name()
+ if not name:
+ return
+ self.model.add_campaign(self.selected_war_id, name)
+ self.is_dirty = True
+ self.refresh_wars_view()
+ self.update_window_title()
+
+ def add_round(self):
+ if not self.selected_campaign_id:
+ return
+ self.model.add_round(self.selected_campaign_id)
+ self.is_dirty = True
+ self.refresh_wars_view()
+ self.update_window_title()
diff --git a/src/warchron/model/campaign.py b/src/warchron/model/campaign.py
index ffe070b..6a7eb99 100644
--- a/src/warchron/model/campaign.py
+++ b/src/warchron/model/campaign.py
@@ -9,7 +9,7 @@ class Campaign:
self.name = name
self.month = datetime.now().month
self.entrants = {}
- self.rounds = {}
+ self.rounds = []
self.is_over = False
def set_id(self, new_id):
@@ -42,4 +42,20 @@ class Campaign:
## entrants placeholder
## rounds placeholder
tmp.set_state(is_over)
- return tmp
\ No newline at end of file
+ return tmp
+
+ def add_round(self, number: int) -> Round:
+ round = Round()
+ self.rounds.append(round)
+ return round
+
+ def get_round(self, round_id) -> Round:
+ return self.rounds[round_id]
+
+ def get_all_rounds(self) -> list[Round]:
+ return list(self.rounds)
+
+ def add_round(self) -> Round:
+ round = Round()
+ self.rounds.append(round)
+ return round
\ No newline at end of file
diff --git a/src/warchron/model/model.py b/src/warchron/model/model.py
index 5e97b44..0cc4bdf 100644
--- a/src/warchron/model/model.py
+++ b/src/warchron/model/model.py
@@ -4,6 +4,8 @@ import shutil
from warchron.model.player import Player
from warchron.model.war import War
+from warchron.model.campaign import Campaign
+from warchron.model.round import Round
class Model:
def __init__(self):
@@ -69,13 +71,36 @@ class Model:
def get_all_players(self) -> list[Player]:
return list(self.players.values())
- def add_war(self, name):
+ def add_war(self, name) -> War:
war = War(name)
self.wars[war.id] = war
return war
- def get_war(self, id):
+ def get_war(self, id) -> War:
return self.wars[id]
def get_all_wars(self) -> list[War]:
return list(self.wars.values())
+
+ def add_campaign(self, war_id: str, name: str) -> Campaign:
+ war = self.get_war(war_id)
+ return war.add_campaign(name)
+
+ def get_campaign(self, campaign_id) -> Campaign:
+ for war in self.wars.values():
+ for campaign in war.campaigns:
+ if campaign.id == campaign_id:
+ return campaign
+ raise KeyError("Campaign not found")
+
+ def add_round(self, campaign_id: str) -> Round:
+ campaign = self.get_campaign(campaign_id)
+ return campaign.add_round()
+
+ def get_round(self, round_id: str) -> Round:
+ for war in self.wars.values():
+ for campaign in war.campaigns:
+ for rnd in campaign.rounds:
+ if rnd.id == round_id:
+ return rnd
+ raise KeyError("Round not found")
\ No newline at end of file
diff --git a/src/warchron/model/round.py b/src/warchron/model/round.py
index faceb0d..04cfb81 100644
--- a/src/warchron/model/round.py
+++ b/src/warchron/model/round.py
@@ -1,20 +1,21 @@
+from uuid import uuid4
+
class Round:
- def __init__(self, number):
- self.number = number
+ def __init__(self):
+ self.id = str(uuid4())
self.sectors = {}
self.choices = {}
self.battles = {}
self.is_over = False
- def set_number(self, new_number):
- self.number = new_number
+ def set_id(self, new_id):
+ self.id = new_id
def set_state(self, new_state):
self.is_over = new_state
def toDict(self):
return {
- "number" : self.number,
"sectors" : self.sectors,
"choices" : self.choices,
"battles" : self.battles,
@@ -22,8 +23,9 @@ class Round:
}
@staticmethod
- def fromDict(id, number, sectors, choices, battles, is_over):
- tmp = Round(number=number)
+ def fromDict(id, sectors, choices, battles, is_over):
+ tmp = Round()
+ tmp.set_id(id)
## sectors placeholder
## choices placeholder
## battles placeholder
diff --git a/src/warchron/model/war.py b/src/warchron/model/war.py
index 308cec2..564aeb3 100644
--- a/src/warchron/model/war.py
+++ b/src/warchron/model/war.py
@@ -9,10 +9,9 @@ class War:
self.name = name
self.year = datetime.now().year
self.entrants = {}
- self.campaigns = {}
+ self.campaigns = []
self.is_over = False
-
def set_id(self, new_id):
self.id = new_id
@@ -43,4 +42,20 @@ class War:
## entrants placeholder
## campaigns placeholder
tmp.set_state(is_over)
- return tmp
\ No newline at end of file
+ return tmp
+
+ def add_campaign(self, name) -> Campaign:
+ campaign = Campaign(name)
+ self.campaigns.append(campaign)
+ return campaign
+
+ def get_campaign(self, campaign_id) -> Campaign:
+ return self.campaigns[campaign_id]
+
+ def get_all_campaigns(self) -> list[Campaign]:
+ return list(self.campaigns)
+
+ def add_campaign(self, name: str) -> Campaign:
+ campaign = Campaign(name)
+ self.campaigns.append(campaign)
+ return campaign
\ No newline at end of file
diff --git a/src/warchron/view/ui/ui_campaign_dialog.py b/src/warchron/view/ui/ui_campaign_dialog.py
new file mode 100644
index 0000000..2482d5b
--- /dev/null
+++ b/src/warchron/view/ui/ui_campaign_dialog.py
@@ -0,0 +1,50 @@
+# Form implementation generated from reading ui file '.\src\warchron\view\ui\ui_campaign_dialog.ui'
+#
+# Created by: PyQt6 UI code generator 6.7.1
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_campaignDialog(object):
+ def setupUi(self, campaignDialog):
+ campaignDialog.setObjectName("campaignDialog")
+ campaignDialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
+ campaignDialog.resize(378, 98)
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(".\\src\\warchron\\view\\ui\\../resources/warchron_logo.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
+ campaignDialog.setWindowIcon(icon)
+ self.buttonBox = QtWidgets.QDialogButtonBox(parent=campaignDialog)
+ self.buttonBox.setGeometry(QtCore.QRect(10, 60, 341, 32))
+ self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
+ self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
+ self.buttonBox.setObjectName("buttonBox")
+ self.label = QtWidgets.QLabel(parent=campaignDialog)
+ self.label.setGeometry(QtCore.QRect(10, 20, 47, 14))
+ self.label.setObjectName("label")
+ self.campaignName = QtWidgets.QLineEdit(parent=campaignDialog)
+ self.campaignName.setGeometry(QtCore.QRect(60, 20, 113, 20))
+ self.campaignName.setObjectName("campaignName")
+
+ self.retranslateUi(campaignDialog)
+ self.buttonBox.accepted.connect(campaignDialog.accept) # type: ignore
+ self.buttonBox.rejected.connect(campaignDialog.reject) # type: ignore
+ QtCore.QMetaObject.connectSlotsByName(campaignDialog)
+
+ def retranslateUi(self, campaignDialog):
+ _translate = QtCore.QCoreApplication.translate
+ campaignDialog.setWindowTitle(_translate("campaignDialog", "Campaign"))
+ self.label.setText(_translate("campaignDialog", "Name:"))
+
+
+if __name__ == "__main__":
+ import sys
+ app = QtWidgets.QApplication(sys.argv)
+ campaignDialog = QtWidgets.QDialog()
+ ui = Ui_campaignDialog()
+ ui.setupUi(campaignDialog)
+ campaignDialog.show()
+ sys.exit(app.exec())
diff --git a/src/warchron/view/ui/ui_campaign_dialog.ui b/src/warchron/view/ui/ui_campaign_dialog.ui
new file mode 100644
index 0000000..c5ef227
--- /dev/null
+++ b/src/warchron/view/ui/ui_campaign_dialog.ui
@@ -0,0 +1,98 @@
+
+
+ campaignDialog
+
+
+ Qt::ApplicationModal
+
+
+
+ 0
+ 0
+ 378
+ 98
+
+
+
+ Campaign
+
+
+
+ ../resources/warchron_logo.png../resources/warchron_logo.png
+
+
+
+
+ 10
+ 60
+ 341
+ 32
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+ 10
+ 20
+ 47
+ 14
+
+
+
+ Name:
+
+
+
+
+
+ 60
+ 20
+ 113
+ 20
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ campaignDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ campaignDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/warchron/view/ui/ui_main_window.py b/src/warchron/view/ui/ui_main_window.py
index e5c8a37..a6c422d 100644
--- a/src/warchron/view/ui/ui_main_window.py
+++ b/src/warchron/view/ui/ui_main_window.py
@@ -51,12 +51,16 @@ class Ui_MainWindow(object):
self.addCampaignBtn.setEnabled(False)
self.addCampaignBtn.setGeometry(QtCore.QRect(110, 20, 91, 23))
self.addCampaignBtn.setObjectName("addCampaignBtn")
+ self.addRoundBtn = QtWidgets.QPushButton(parent=self.warsTab)
+ self.addRoundBtn.setEnabled(False)
+ self.addRoundBtn.setGeometry(QtCore.QRect(220, 20, 91, 23))
+ self.addRoundBtn.setObjectName("addRoundBtn")
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(".\\src\\warchron\\view\\ui\\../resources/swords-small.png"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
self.tabWidget.addTab(self.warsTab, icon2, "")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
- self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(parent=self.menubar)
self.menuFile.setObjectName("menuFile")
@@ -144,6 +148,7 @@ class Ui_MainWindow(object):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.playersTab), _translate("MainWindow", "Players"))
self.addWarBtn.setText(_translate("MainWindow", "Add war"))
self.addCampaignBtn.setText(_translate("MainWindow", "Add Campaign"))
+ self.addRoundBtn.setText(_translate("MainWindow", "Add Round"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.warsTab), _translate("MainWindow", "Wars"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
diff --git a/src/warchron/view/ui/ui_main_window.ui b/src/warchron/view/ui/ui_main_window.ui
index b88ad16..c20c876 100644
--- a/src/warchron/view/ui/ui_main_window.ui
+++ b/src/warchron/view/ui/ui_main_window.ui
@@ -124,6 +124,22 @@
Add Campaign
+
+
+ false
+
+
+
+ 220
+ 20
+ 91
+ 23
+
+
+
+ Add Round
+
+
@@ -133,7 +149,7 @@
0
0
800
- 22
+ 21