__blackjack__ hat geschrieben: Samstag 9. September 2023, 16:14
@mechanicalStore:
Danke!
Leider habe ich schon wieder ein Problem, stehe auf dem Schlauch. Dazu muss ich allerdings 4 Dateien her kopieren, ich weiß nicht, wie ich das sinnvoll kürzen kann, damit es noch läuft. Es ist einfach so, dass in p_datafill.py Zeilen 80 und 88 ignoriert werden und ich verstehe nicht warum. Hauptprogramm ist p_projectdata.py. (Zusatzfrage; lässt sich p_alchemy.py schöber gestalten?). Nach klick auf den Button "new" in der toolbar kommt der Eingabedialog. Testdaten für Projekt (wegen regex) z.B. "PA-12-123". Am Ende steht der Eintrag in der Datenbank, aber die View wird (wieder mal) nicht upgedatet. Ich rufe in den Zeilen 80 und 88 beginResetModel / endResetModel auf, was von da aus offenbar nicht geht, obwohl ich ja die Instanz auf model mitgebe.
p_alchemy.py
Code: Alles auswählen
#!/usr/bin/env python3
from sqlalchemy import INTEGER, TEXT, Column, create_engine, select
from sqlalchemy.orm import sessionmaker, declarative_base
Base = declarative_base()
Session = sessionmaker()
class Project(Base):
__tablename__ = "project"
project_id = Column(INTEGER, primary_key=True)
project_name = Column(TEXT, nullable=False, unique=True)
project_netplan = Column(TEXT, nullable=True)
project_description = Column(TEXT, nullable=True)
@classmethod
def run(self):
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
session = Session(bind=engine)
return session
@classmethod
def get_all_projects(self, session):
return session.execute(select(Project)).scalars().all()
@classmethod
def add_project(self, session, name, netplan, description):
if Project.is_existing_project(session, name):
return False
else:
project = Project(project_name = name,
project_netplan = netplan,
project_description = description)
session.add(project)
session.commit()
return True
@classmethod
def is_existing_project(self, session, name):
if session.execute(select(Project).filter_by(project_name = name)).scalars().first():
return True
else:
return False
def main():
session = Project.run()
# Testdaten erzeugen
for i in range(1, 12, 2):
if not Project.add_project(session,
f'P-{i}-{i*10}',
f'Netplan-{i / 5}',
f'Description-{i * 22}'):
print(f'Projekt P-{i}-{i*10} ist schon in der Datenbank')
# Test-Duplikate erzwingen
for i in range(1, 12, 1):
if not Project.add_project(session,
f'P-{i}-{i*10}',
f'Netplan-{i / 5}',
f'Description-{i * 22}'):
print(f'Projekt P-{i}-{i*10} ist schon in der Datenbank')
# Testdaten ausgeben
for pq in Project.get_all_projects(session):
print(f'{pq.project_name} {pq.project_netplan} {pq.project_description} {pq.project_id}')
if __name__ == '__main__':
main()
p_datafill.py
Code: Alles auswählen
#!/usr/bin/env python3
import re
from PySide6.QtCore import Qt, QSize, Slot
from PySide6.QtWidgets import (QDialog, QLabel, QTextEdit, QLineEdit, QMessageBox,
QDialogButtonBox, QGridLayout, QVBoxLayout)
from p_alchemy import Project
# from p_modeldata import TableModel
class AddDialogWidget(QDialog):
def __init__(self, session, model, parent=None):
super().__init__(parent)
self.resize(QSize(400, 200))
self.session = session
self.model = model
self.project_regex = re.compile('^[a-zA-Z]{1,2}\-\d{2}\-\d{3}$')
self.msgBox = QMessageBox()
self.project_label = QLabel("Projekt:")
self.project_input = QLineEdit()
self.netplan_label = QLabel("Netzplan-Nr:")
self.netplan_input = QLineEdit()
self.description_label = QLabel("Beschreibung")
self.description_input = QLineEdit()
self.button_box = QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Cancel)
self.grid = QGridLayout()
self.grid.setColumnStretch(1, 2)
self.grid.addWidget(self.project_label, 1, 0)
self.grid.addWidget(self.project_input, 1, 1)
self.grid.addWidget(self.netplan_label, 2, 0)
self.grid.addWidget(self.netplan_input, 2, 1)
self.grid.addWidget(self.description_label, 3, 0)
self.grid.addWidget(self.description_input, 3, 1)
self.main_layout = QVBoxLayout()
self.main_layout.addLayout(self.grid)
self.main_layout.addWidget(self.button_box)
self.setLayout(self.main_layout)
self.setWindowTitle("Neues Projekt")
self.button_box.accepted.connect(self.check_validat)
self.button_box.rejected.connect(self.reject)
def check_validat(self):
project_text = self.project_input.text().strip().upper()
self.project_input.setText(project_text)
netplan_text = self.netplan_input.text().strip().upper()
self.netplan_input.setText(netplan_text)
description_text = self.description_input.text().strip().upper()
self.description_input.setText(description_text)
if not self.project_regex.match(project_text):
self.msgBox.setText("Eingabe ungültig")
self.msgBox.exec()
elif Project.is_existing_project(self.session, project_text):
self.msgBox.setText("Projekt schon in der Datenbank vorhanden")
self.msgBox.exec()
else:
self.model.beginResetModel() # <---- Aufruf hat keine Wirkung
if not Project.add_project(self.session,
project_text,
netplan_text,
description_text):
self.msgBox.setText("Projekt konnte nicht angelegt werden")
self.msgBox.exec()
self.model.endResetModel() # <---- Aufruf hat keine Wirkung
# Testdaten ausgeben
for pq in Project.get_all_projects(self.session):
print(f'{pq.project_name} {pq.project_netplan} {pq.project_description} ID = {pq.project_id}')
print()
self.accept()
@property
def project_text(self):
return self.project_input.text()
@property
def netplan_text(self):
return self.netplan_input.text()
@property
def description_text(self):
return self.description_input.text()
def main():
import sys
from PySide6.QtWidgets import QApplication
session = Project.run()
app = QApplication(sys.argv)
dialog = AddDialogWidget(session)
if (dialog.exec()):
print(dialog.project_text)
print(dialog.netplan_text)
print(dialog.description_text)
if __name__ == '__main__':
main()
p_modeldata.py
Code: Alles auswählen
#!/usr/bin/env python3
from PyQt6.QtCore import (QAbstractTableModel, Qt, QModelIndex)
from p_alchemy import Project
class TableModel(QAbstractTableModel):
def __init__(self, session):
super().__init__()
self.session = session
self.column_labels = ['Projekt', 'Netzplan', 'Beschreibung']
self.column_attributes = ['project_name', 'project_netplan', 'project_description']
self.projects = Project.get_all_projects(session)
def headerData(self, section, orientation, role):
if role == Qt.ItemDataRole.DisplayRole:
if orientation == Qt.Orientation.Horizontal:
return self.column_labels[section]
elif orientation == Qt.Orientation.Vertical:
return f'Zeile-{section} '
else:
return False
def data(self, index, role):
if role == Qt.ItemDataRole.DisplayRole or role == Qt.ItemDataRole.EditRole:
return getattr(self.projects[index.row()], self.column_attributes[index.column()])
# def setData(self, index, value, role):
# if role == Qt.ItemDataRole.EditRole:
# self.beginResetModel()
# setattr(self.projects[index.row()], self.column_attributes[index.column()], value)
# self.session.commit()
# self.endResetModel()
# return True
# return False
# def flags(self, index):
# return Qt.ItemFlag.NoItemFlags | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable
def rowCount(self, _index):
return len(self.projects)
def columnCount(self, _index):
return len(self.column_labels)
p_projectdata.py
Code: Alles auswählen
#!/usr/bin/env python3
import sys
from PyQt6.QtCore import QSize, Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView, QVBoxLayout, QWidget, QToolBar, QStatusBar
from PyQt6.QtGui import QAction, QIcon
from p_alchemy import Project
from p_modeldata import TableModel
from p_datafill import AddDialogWidget
class MainWindow(QMainWindow):
def __init__(self, session):
super().__init__(windowTitle = "Main Window")
self.resize(QSize(1000, 500))
self.session = session
self.toolbar = QToolBar("Toolbar Test")
self.toolbar.setIconSize(QSize(16,16))
self.addToolBar(self.toolbar)
self.button_new = QAction(QIcon("../icons/new.png"), "Neu", self)
self.button_new.setStatusTip("Neues Projekt hinzufügen")
self.button_new.triggered.connect(self.buttonNewClick)
self.toolbar.addAction(self.button_new)
self.button_delete = QAction(QIcon("../icons/cross.png"), "Löschen", self)
self.button_delete.setStatusTip("Markiertes Projekt Löschen")
self.button_delete.triggered.connect(self.buttonDeleteClick)
self.toolbar.addAction(self.button_delete)
self.button_exit = QAction(QIcon("../icons/arrow-skip.png"), "Exit", self)
self.button_exit.setStatusTip("Projekt-Daten verlassen")
self.button_exit.triggered.connect(self.buttonExitClick)
self.toolbar.addAction(self.button_exit)
self.setStatusBar(QStatusBar(self))
self.table = QTableView()
self.model = TableModel(self.session)
self.table.setModel(self.model)
self.table.resizeColumnsToContents()
self.layout = QVBoxLayout()
self.layout.addWidget(self.table)
self.widget = QWidget()
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
def buttonNewClick(self, s):
dialog = AddDialogWidget(self.session, self.model)
dialog.exec()
def buttonDeleteClick(self, s):
print("Hello")
def buttonExitClick(self, s):
print("Hello")
def main():
session = Project.run()
# Testdaten erzeugen
for i in range(1, 12, 2):
if not Project.add_project(session,
f'P-{i}-{i*10}',
f'Netplan-{i / 5}',
f'Description-{i * 22}'):
print(f'Projekt P-{i}-{i*10} ist schon in der Datenbank')
# Testdaten ausgeben
for pq in Project.get_all_projects(session):
print(f'{pq.project_name} {pq.project_netplan} {pq.project_description} {pq.project_id}')
app = QApplication(sys.argv)
window = MainWindow(session)
window.show()
app.exec()
if __name__ == "__main__":
main()