war add & display

This commit is contained in:
Maxime Réaux 2026-01-20 08:46:58 +01:00
parent cfa65a41f0
commit 9e966baf9b
4 changed files with 223 additions and 30 deletions

View file

@ -2,7 +2,7 @@ from pathlib import Path
from PyQt6.QtWidgets import QMessageBox, QDialog from PyQt6.QtWidgets import QMessageBox, QDialog
from warchron.view.view import PlayerDialog from warchron.view.view import PlayerDialog, WarDialog
class Controller: class Controller:
def __init__(self, model, view): def __init__(self, model, view):
@ -13,20 +13,32 @@ class Controller:
self.is_dirty = False self.is_dirty = False
self.__connect() self.__connect()
self.refresh_players_view() self.refresh_players_view()
self.refresh_wars_view()
self.update_window_title() self.update_window_title()
def __connect(self): def __connect(self):
self.view.addPlayerBtn.clicked.connect(self.add_player)
self.view.actionExit.triggered.connect(self.view.close) self.view.actionExit.triggered.connect(self.view.close)
self.view.actionNew.triggered.connect(self.new) self.view.actionNew.triggered.connect(self.new)
self.view.actionOpen.triggered.connect(self.open_file) self.view.actionOpen.triggered.connect(self.open_file)
self.view.actionSave.triggered.connect(self.save) self.view.actionSave.triggered.connect(self.save)
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.addWarBtn.clicked.connect(self.add_war)
def refresh_players_view(self): def on_app_close(self) -> bool:
players = self.model.get_all_players() if self.is_dirty:
self.view.display_players(players) reply = QMessageBox.question(
self.view,
"Unsaved changes",
"You have unsaved changes. Do you want to save before quitting?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel
)
if reply == QMessageBox.StandardButton.Yes:
self.save()
elif reply == QMessageBox.StandardButton.Cancel:
return False
return True
def new(self): def new(self):
if self.is_dirty: if self.is_dirty:
reply = QMessageBox.question( reply = QMessageBox.question(
@ -41,6 +53,7 @@ class Controller:
self.current_file = None self.current_file = None
self.is_dirty = False self.is_dirty = False
self.refresh_players_view() self.refresh_players_view()
self.refresh_wars_view()
self.update_window_title() self.update_window_title()
def open_file(self): def open_file(self):
@ -60,22 +73,9 @@ class Controller:
self.current_file = path self.current_file = path
self.is_dirty = False self.is_dirty = False
self.refresh_players_view() self.refresh_players_view()
self.refresh_wars_view()
self.update_window_title() self.update_window_title()
def on_app_close(self) -> bool:
if self.is_dirty:
reply = QMessageBox.question(
self.view,
"Unsaved changes",
"You have unsaved changes. Do you want to save before quitting?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel
)
if reply == QMessageBox.StandardButton.Yes:
self.save()
elif reply == QMessageBox.StandardButton.Cancel:
return False
return True
def save(self): def save(self):
if not self.current_file: if not self.current_file:
self.save_as() self.save_as()
@ -103,6 +103,9 @@ class Controller:
base = base + " *" base = base + " *"
self.view.setWindowTitle(base) self.view.setWindowTitle(base)
def refresh_players_view(self):
players = self.model.get_all_players()
self.view.display_players(players)
def add_player(self): def add_player(self):
dialog = PlayerDialog(self.view) dialog = PlayerDialog(self.view)
@ -120,3 +123,24 @@ class Controller:
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 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
if result == QDialog.DialogCode.Accepted:
name = dialog.get_war_name()
if not name:
QMessageBox.warning(
self.view,
"Invalid name",
"War name cannot be empty."
)
return
self.model.add_war(name)
self.is_dirty = True
self.refresh_wars_view()
self.update_window_title()

View file

@ -0,0 +1,50 @@
# Form implementation generated from reading ui file '.\src\warchron\view\ui\ui_war_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_warDialog(object):
def setupUi(self, warDialog):
warDialog.setObjectName("warDialog")
warDialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
warDialog.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)
warDialog.setWindowIcon(icon)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=warDialog)
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=warDialog)
self.label.setGeometry(QtCore.QRect(10, 20, 47, 14))
self.label.setObjectName("label")
self.warName = QtWidgets.QLineEdit(parent=warDialog)
self.warName.setGeometry(QtCore.QRect(60, 20, 113, 20))
self.warName.setObjectName("warName")
self.retranslateUi(warDialog)
self.buttonBox.accepted.connect(warDialog.accept) # type: ignore
self.buttonBox.rejected.connect(warDialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(warDialog)
def retranslateUi(self, warDialog):
_translate = QtCore.QCoreApplication.translate
warDialog.setWindowTitle(_translate("warDialog", "War"))
self.label.setText(_translate("warDialog", "Name:"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
warDialog = QtWidgets.QDialog()
ui = Ui_warDialog()
ui.setupUi(warDialog)
warDialog.show()
sys.exit(app.exec())

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>warDialog</class>
<widget class="QDialog" name="warDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>378</width>
<height>98</height>
</rect>
</property>
<property name="windowTitle">
<string>War</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../resources/warchron_logo.png</normaloff>../resources/warchron_logo.png</iconset>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>47</width>
<height>14</height>
</rect>
</property>
<property name="text">
<string>Name:</string>
</property>
</widget>
<widget class="QLineEdit" name="warName">
<property name="geometry">
<rect>
<x>60</x>
<y>20</y>
<width>113</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>warDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>warDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -1,11 +1,12 @@
from pathlib import Path from pathlib import Path
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QDialog, QFileDialog from PyQt6.QtWidgets import QDialog, QFileDialog, QTreeWidgetItem
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
from warchron.view.ui.ui_player_dialog import Ui_playerDialog from warchron.view.ui.ui_player_dialog import Ui_playerDialog
from warchron.view.ui.ui_war_dialog import Ui_warDialog
class View(QtWidgets.QMainWindow, Ui_MainWindow): class View(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None): def __init__(self, parent=None):
@ -13,14 +14,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
self.setupUi(self) self.setupUi(self)
self.on_close_callback = None self.on_close_callback = None
def display_players(self, players: list):
table = self.playersTable
table.setRowCount(len(players))
for row, player in enumerate(players):
table.setItem(row, 0, QtWidgets.QTableWidgetItem(player.name))
table.setItem(row, 1, QtWidgets.QTableWidgetItem(player.id))
table.resizeColumnsToContents()
def closeEvent(self, event: QCloseEvent): def closeEvent(self, event: QCloseEvent):
if self.on_close_callback: if self.on_close_callback:
proceed = self.on_close_callback() proceed = self.on_close_callback()
@ -47,6 +40,25 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow):
) )
return Path(filename) if filename else None return Path(filename) if filename else None
def display_players(self, players: list):
table = self.playersTable
table.setRowCount(len(players))
for row, player in enumerate(players):
table.setItem(row, 0, QtWidgets.QTableWidgetItem(player.name))
table.setItem(row, 1, QtWidgets.QTableWidgetItem(player.id))
table.resizeColumnsToContents()
def display_wars(self, wars: list):
tree = self.warsTree
tree.clear()
tree.setColumnCount(1)
tree.setHeaderLabels(["Wars"])
for war in wars:
war_item = QTreeWidgetItem([f"{war.name} ({war.year})"])
war_item.setData(0, 1, war.id) # role=1 to store id
tree.addTopLevelItem(war_item)
tree.expandAll()
class PlayerDialog(QDialog): class PlayerDialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
@ -55,3 +67,12 @@ class PlayerDialog(QDialog):
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):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_warDialog()
self.ui.setupUi(self)
def get_war_name(self) -> str:
return self.ui.warName.text().strip()