war add & display
This commit is contained in:
parent
cfa65a41f0
commit
9e966baf9b
4 changed files with 223 additions and 30 deletions
|
|
@ -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,19 +13,31 @@ 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:
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
50
src/warchron/view/ui/ui_war_dialog.py
Normal file
50
src/warchron/view/ui/ui_war_dialog.py
Normal 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())
|
||||||
98
src/warchron/view/ui/ui_war_dialog.ui
Normal file
98
src/warchron/view/ui/ui_war_dialog.ui
Normal 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>
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue