From 2c41f418fbc82376e20cf2ff7ed756a17139f7ff Mon Sep 17 00:00:00 2001 From: lonkaars Date: Mon, 10 Apr 2023 20:49:31 +0200 Subject: circuits tab done --- gui/gui.todo | 13 ++-- gui/login_dialog.py | 2 +- gui/main_window.py | 49 +++++++++--- gui/tab_circuits.py | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++- gui/tab_drivers.py | 3 + gui/tab_teams.py | 6 +- 6 files changed, 256 insertions(+), 26 deletions(-) (limited to 'gui') diff --git a/gui/gui.todo b/gui/gui.todo index 537ecfb..9c22070 100644 --- a/gui/gui.todo +++ b/gui/gui.todo @@ -1,4 +1,4 @@ -[ ] {pick} year +[x] {pick} year [x] login dialog box (like mac system settings with padlock) (username + password) [x] drivers - [x] {show} {set} full name @@ -9,12 +9,11 @@ - [x] {show} team name - [x] {show} driver names (-> link to driver browser?) - [x] {add/remove} driver -[ ] cirucits - - [ ] {show} circuit name - - [ ] {show} circuit length - - [ ] {show} circuit lap count - - [ ] {show} location - - [ ] {show} photo / map +[x] cirucits + - [x] {show} circuit name + - [x] {show} circuit length + - [x] {show} circuit lap count + - [x] {show} photo / map [ ] races - [ ] {create} new race - [ ] {show} race number diff --git a/gui/login_dialog.py b/gui/login_dialog.py index 02ea1af..c8c5247 100644 --- a/gui/login_dialog.py +++ b/gui/login_dialog.py @@ -33,7 +33,7 @@ class LoginDialog(QDialog): self.field_password = QLineEdit(self.password) self.field_password.setPlaceholderText("password") self.field_password.setEchoMode(QLineEdit.EchoMode.Password) - self.login_button = QPushButton("login") + self.login_button = QPushButton("Login") self.login_button.clicked.connect(self.submit) layout = QFormLayout() layout.addRow(QLabel("Database:"), self.field_database) diff --git a/gui/main_window.py b/gui/main_window.py index 9e2f40e..a269f45 100644 --- a/gui/main_window.py +++ b/gui/main_window.py @@ -18,6 +18,8 @@ class MainWindow(QMainWindow): _tab_circuits: TabCircuits _tab_races: TabRaces + main_layout: QTabWidget + def set_cursor(self, cursor: mariadb.Cursor): self.cursor = cursor @@ -39,20 +41,41 @@ class MainWindow(QMainWindow): def call_update_flags(self): folder = QFileDialog().getExistingDirectory(self, "Open directory", "/var/dab2/") + if not folder: return + folder += "/" self.cursor.execute("call spUpdateFlags(?)", (folder,)) def call_update_persons(self): folder = QFileDialog().getExistingDirectory(self, "Open directory", "/var/dab2/") + if not folder: return + folder += "/" self.cursor.execute("call spUpdatePersons(?)", (folder,)) + def call_update_circuits(self): + folder = QFileDialog().getExistingDirectory(self, "Open directory", "/var/dab2/") + if not folder: return + folder += "/" + self.cursor.execute("call spUpdateCircuits(?)", (folder,)) + def call_delete_flags(self): self.cursor.execute("call spDeleteFlags()") + def focus_member(self, id): + self.set_tab_index(0) + self._tab_drivers.set_driver_id(id) + + def focus_team(self, id): + self.set_tab_index(1) + self._tab_teams.set_team_id(id) + + def set_tab_index(self, index): + self.main_layout.setCurrentIndex(index) + def update(self, cascade=True): if cascade == False: return self._tab_drivers.update() self._tab_teams.update() - # self._tab_circuits.update() + self._tab_circuits.update() # self._tab_races.update() def switch_season(self): @@ -70,33 +93,35 @@ class MainWindow(QMainWindow): self._tab_drivers = TabDrivers(self.cursor, self) self._tab_teams = TabTeams(self.cursor, self) - self._tab_circuits = TabCircuits(self) + self._tab_circuits = TabCircuits(self.cursor, self) self._tab_races = TabRaces(self) - main_layout = QTabWidget(self); - main_layout.addTab(self._tab_drivers, "drivers") - main_layout.addTab(self._tab_teams, "teams") - main_layout.addTab(self._tab_circuits, "cirucits") - main_layout.addTab(self._tab_races, "races") + self.main_layout = QTabWidget(self); + self.main_layout.addTab(self._tab_drivers, "Drivers") + self.main_layout.addTab(self._tab_teams, "Teams") + self.main_layout.addTab(self._tab_circuits, "Cirucits") + self.main_layout.addTab(self._tab_races, "Races") self.menu_bar = QMenuBar(self) - menu = self.menu_bar.addMenu("file") + menu = self.menu_bar.addMenu("File") action = menu.addAction("Exit (commit changes)") action.triggered.connect(self.exit_commit) action = menu.addAction("Exit (don't commit changes)") action.triggered.connect(self.exit_no_commit) - menu = self.menu_bar.addMenu("procedures") + menu = self.menu_bar.addMenu("Procedures") action = menu.addAction("Import/update flags") action.triggered.connect(self.call_update_flags) action = menu.addAction("Import/update driver portraits") action.triggered.connect(self.call_update_persons) + action = menu.addAction("Import/update circuit maps") + action.triggered.connect(self.call_update_circuits) action = menu.addAction("Delete flags") action.triggered.connect(self.call_delete_flags) - menu = self.menu_bar.addMenu("database") + menu = self.menu_bar.addMenu("Database") action = menu.addAction("Commit changes") action.triggered.connect(self.commit) - menu = self.menu_bar.addMenu("seasons") + menu = self.menu_bar.addMenu("Seasons") group = QActionGroup(menu) group.setExclusive(True) self.cursor.execute("select ID, year from calendar") @@ -111,5 +136,5 @@ class MainWindow(QMainWindow): group.addAction(action) self.setMenuBar(self.menu_bar) - self.setCentralWidget(main_layout) + self.setCentralWidget(self.main_layout) diff --git a/gui/tab_circuits.py b/gui/tab_circuits.py index 19ba979..a57db1d 100644 --- a/gui/tab_circuits.py +++ b/gui/tab_circuits.py @@ -1,13 +1,214 @@ import os +import mariadb from PySide6.QtGui import * from PySide6.QtWidgets import * +from PySide6.QtCore import * +from PySide6.QtCore import Qt + +from split_view_layout import * + +from dataclasses import dataclass + +@dataclass +class DBCircuit(): + id: int = 0 + name: str = "" + length: int = 0 + laps: int = 0 + photo: bytes = b"" + +class CircuitsModel(QAbstractTableModel): + cursor: mariadb.Cursor + calendar_id: int = 1 + + _header = ["name", "length", "lap count"] + _data: [DBCircuit] = [] + + def update(self): + self.beginResetModel() + self.cursor.execute("select `ID`, `name`, `length`, `laps` from `circuit`") + self._data = list() + for result in self.cursor.fetchall(): + self._data.append(DBCircuit(*result)) + self.endResetModel() + + def __init__(self, cursor): + super().__init__() + self.cursor = cursor + self.update() + + def rowCount(self, index=0): + return len(self._data) + + def columnCount(self, index=0): + return len(self._header) + + def headerData(self, section, orientation, role): + if role == Qt.DisplayRole: + if orientation == Qt.Horizontal: + return self._header[section] + else: + return self._data[section].id + + def data(self, index, role): + if role == Qt.DisplayRole: + circuit = self._data[index.row()] + return ( + circuit.name, + circuit.length, + circuit.laps, + )[index.column()] + +class CircuitBrowser(QTableView): + model_table: CircuitsModel + model_proxy: QSortFilterProxyModel + parent_update_fn: callable + selected_circuit_id: int = 1 + ignore_update: bool = False + temp_selection_index: int = 0 + + def update(self, cascade=True): + self.model_table.update() + self.ignore_update = True + self.selectRow(self.temp_selection_index) + self.ignore_update = False + + def parent_update(self): + if self.parent_update_fn != None: + self.parent_update_fn() + + def set_parent_update(self, fn): + self.parent_update_fn = fn + + def on_selection(self): + if self.ignore_update: return + rows = self.selectionModel().selectedRows() + if len(rows) == 0: return + row = rows[0].row() + self.temp_selection_index = row + index = self.model_proxy.mapToSource(self.model_proxy.index(row, 0)) + new_circuit_id = self.model_table.headerData(index.row(), Qt.Vertical, Qt.DisplayRole) + if self.selected_circuit_id == new_circuit_id: return + self.selected_circuit_id = new_circuit_id + self.parent_update() + + def __init__(self, cursor: mariadb.Cursor, parent=None): + super(CircuitBrowser, self).__init__(parent) + + self.cursor = cursor + + self.setSelectionBehavior(QAbstractItemView.SelectRows) + self.model_table = CircuitsModel(self.cursor) + self.model_proxy = QSortFilterProxyModel() + self.model_proxy.setSourceModel(self.model_table) + self.setModel(self.model_proxy) + self.setSortingEnabled(True) + self.selectionModel().selectionChanged.connect(self.on_selection) + self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + +class CircuitDetailsWidget(QWidget): + parent: QWidget + cursor: mariadb.Cursor + parent_update_fn: callable + selected_circuit_id: int = 1 + + layout: QVBoxLayout + new_member_picker: QComboBox + + label_id: QLabel + label_name: QLabel + label_length: QLabel + label_laps: QLabel + label_map: QLabel + + def update(self, cascade=True): + self.cursor.execute("select `ID`, `name`, `length`, `laps`, `photo` from `circuit` where `ID` = ?", (self.selected_circuit_id,)) + circuit = DBCircuit(*self.cursor.fetchone()) + + self.label_id.setText(f"{circuit.id}") + self.label_name.setText(f"{circuit.name}") + self.label_length.setText(f"{circuit.length}m") + self.label_laps.setText(f"{circuit.laps} laps") + + + pixmap = QPixmap() + pixmap.loadFromData(circuit.photo) + self.label_map.setScaledContents(True) + self.label_map.setPixmap(pixmap) + if cascade == False: return + + def parent_update(self): + if self.parent_update_fn != None: + self.parent_update_fn() + + def set_circuit_id(self, id): + self.selected_circuit_id = id + self.update(False) + + def set_parent_update(self, fn): + self.parent_update_fn = fn + + def __init__(self, cursor: mariadb.Cursor, parent=None): + super(CircuitDetailsWidget, self).__init__(parent) + self.parent = parent + self.cursor = cursor + + self.layout = QVBoxLayout(self) + self.layout.setAlignment(Qt.AlignmentFlag.AlignTop) + + self.layout.addWidget(QLabel("Circuit info")) + + self.label_id = QLabel("-") + self.label_name = QLabel("-") + self.label_length = QLabel("-") + self.label_laps = QLabel("-") + self.label_map = QLabel() + + form_grid = QFormLayout() + form_grid.addRow(QLabel("ID:"), self.label_id) + form_grid.addRow(QLabel("Name:"), self.label_name) + form_grid.addRow(QLabel("Length:"), self.label_length) + form_grid.addRow(QLabel("Laps:"), self.label_laps) + self.layout.addLayout(form_grid) + + self.layout.addWidget(QLabel("Map")) + self.layout.addWidget(self.label_map) + + self.setLayout(self.layout) class TabCircuits(QWidget): - def __init__(self, parent=None): + parent: QMainWindow + layout: SplitViewLayout + cursor: mariadb.Cursor + selected_circuit_id: int = 1 + + circuit_browser: CircuitBrowser + circuit_details: CircuitDetailsWidget + + def update(self, cascade=True): + print("update TabCircuits") + + if not cascade: return + self.circuit_browser.update(True) + + def child_update(self): + self.selected_circuit_id = self.circuit_browser.selected_circuit_id + self.circuit_browser.update(False) + self.circuit_details.set_circuit_id(self.selected_circuit_id) + + def __init__(self, cursor, parent=None): super(TabCircuits, self).__init__(parent) + self.parent = parent + self.layout = SplitViewLayout(self) + self.cursor = cursor + + self.circuit_browser = CircuitBrowser(self.cursor, self) + self.circuit_browser.set_parent_update(self.child_update) + self.layout.leftWidget(self.circuit_browser) - layout = QFormLayout() - layout.addWidget(QLabel("hoi")) + self.circuit_details = CircuitDetailsWidget(self.cursor, self) + self.circuit_details.set_parent_update(self.child_update) + self.layout.rightWidget(self.circuit_details) - self.setLayout(layout) + self.setLayout(self.layout) diff --git a/gui/tab_drivers.py b/gui/tab_drivers.py index 9812ce5..138f374 100644 --- a/gui/tab_drivers.py +++ b/gui/tab_drivers.py @@ -296,6 +296,9 @@ class TabDrivers(QWidget): self.driver_browser.update(False) self.driver_details.set_driver_id(self.selected_driver_id) + def set_driver_id(self, id): + print("not implemented") + def __init__(self, cursor: mariadb.Cursor, parent=None): super(TabDrivers, self).__init__(parent) self.cursor = cursor diff --git a/gui/tab_teams.py b/gui/tab_teams.py index 0335bab..b4dfd73 100644 --- a/gui/tab_teams.py +++ b/gui/tab_teams.py @@ -102,12 +102,12 @@ class TeamBrowser(QTableView): self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) class TeamDetailsWidget(QWidget): + parent: QWidget cursor: mariadb.Cursor parent_update_fn: callable selected_team_id: int = 1 team_members: QFormLayout - buttons: [QPushButton] layout: QVBoxLayout new_member_picker: QComboBox @@ -121,7 +121,6 @@ class TeamDetailsWidget(QWidget): self.update(False) def update(self, cascade=True): - self.buttons = list() for x in range(self.team_members.rowCount()): self.team_members.removeRow(0) self.cursor.execute("select member.ID, firstName, middleName, lastName from member join teamsmember on teamsmember.memberID = member.ID where teamsmember.teamsID = ?", (self.selected_team_id,)) @@ -154,6 +153,7 @@ class TeamDetailsWidget(QWidget): def __init__(self, cursor: mariadb.Cursor, parent=None): super(TeamDetailsWidget, self).__init__(parent) + self.parent = parent self.cursor = cursor self.layout = QVBoxLayout(self) @@ -174,6 +174,7 @@ class TeamDetailsWidget(QWidget): self.setLayout(self.layout) class TabTeams(QWidget): + parent: QMainWindow layout: SplitViewLayout cursor: mariadb.Cursor selected_team_id: int = 1 @@ -194,6 +195,7 @@ class TabTeams(QWidget): def __init__(self, cursor, parent=None): super(TabTeams, self).__init__(parent) + self.parent = parent self.layout = SplitViewLayout(self) self.cursor = cursor -- cgit v1.2.3