Редактирование данных в ячейке QStandardItemModel() с сохранением в базе данных
Всем привет! Как в модели QStandardItemModel() при редактировании ячейки сохранить изменения в базе данных. Я попытался это сделать путем создания собственного класса, наследуемого от QStyledItemDelegate. В этот же класс я поместил метод для изменений данных в базе данных. И, вроде, работает, но в приложении, которое я делаю изменения в базе данных происходят на определенную дату, которую выбирает пользователь в календаре. А "print('Date: ', MyCalendar().selectedDate().toString('dd.MM.yyyy'))" выводит всегда только сегодняшнюю дату. Я предполагаю почему, но не могу понять как это исправить. Вопрос "Как это сделать???". P.S. Про QSqlTableModel() в курсе. Хотел бы знать, как это сделать в QStandardItemModel().
import sys
import traceback
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItem
from PyQt5.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QPushButton, QTableView, \
QCalendarWidget, QMessageBox, QDialog, QDialogButtonBox, QLineEdit, QFormLayout
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
LIST_OF_HEADLABELS = ['Date', 'Time', 'FIO']
def create_table():
createTableQuery = QSqlQuery()
return createTableQuery.exec("""CREATE TABLE IF NOT EXISTS for_stackoverflow (id INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE NOT NULL, date VARCHAR(40) NOT NULL, time VARCHAR(40) NOT NULL,
fio VARCHAR(40) NOT NULL)""")
def create_connection(databasename):
connection = QSqlDatabase.addDatabase("QSQLITE")
connection.setDatabaseName(databasename)
if not connection.open():
QMessageBox.warning(None, "RP Contact", f"Database Error: {connection.lastError().text()}")
return False
create_table()
return True
def add_to_db(list_with_data):
insert_data_query = QSqlQuery()
insert_data_query.prepare('INSERT INTO for_stackoverflow (date, time, fio) VALUES (?, ?, ?)')
insert_data_query.addBindValue(list_with_data[0])
insert_data_query.addBindValue(list_with_data[1])
insert_data_query.addBindValue(list_with_data[2])
insert_data_query.exec_()
class MyWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("for_stackoverflow")
self.resize(600, 300)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.layout = QHBoxLayout()
self.centralWidget.setLayout(self.layout)
self.model = ContactsModel()
self.layout_for_table = QVBoxLayout()
self.layout.addLayout(self.layout_for_table)
self.layout_for_action_button = QVBoxLayout()
self.layout.addLayout(self.layout_for_action_button)
self.table_view = QTableView()
self.layout_for_table.addWidget(self.table_view)
self.table_view.setItemDelegateForColumn(2, LineEditDelegate())
self.button_action1 = QPushButton('ADD')
self.layout_for_action_button.addWidget(self.button_action1)
self.button_action1.clicked.connect(self.open_add_dialog)
self.cal = QCalendarWidget()
self.layout_for_action_button.addWidget(self.cal, alignment=Qt.AlignRight | Qt.AlignBottom)
self.cal.setVerticalHeaderFormat(QCalendarWidget.NoVerticalHeader)
self.table_view.setModel(self.model.model)
header = self.table_view.horizontalHeader()
header.setSectionResizeMode(header.ResizeMode.Stretch)
v_header = self.table_view.verticalHeader()
v_header.hide()
self.from_db()
def from_db(self):
data_from_db = QSqlQuery()
data_from_db.prepare('SELECT date, time, fio FROM for_stackoverflow')
data_from_db.exec_()
row = 0
while data_from_db.next():
column_count = self.model.model.columnCount()
for i in range(0, column_count):
self.model.model.setItem(row, i, QStandardItem(data_from_db.value(i)))
row += 1
def open_add_dialog(self):
dialog = AddDialog(self)
if dialog.exec() == QDialog.Accepted:
for i, k in enumerate(dialog.data):
self.model.model.setItem(self.table_view.currentIndex().row(), i + 1, QStandardItem(k))
add_to_db(dialog.data)
class ContactsModel:
def __init__(self):
self.model = QtGui.QStandardItemModel()
self.create_model()
def create_model(self):
self.model.setHorizontalHeaderLabels(LIST_OF_HEADLABELS)
class AddDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setWindowTitle("Add")
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.data = None
self.date_field = QLineEdit()
self.time_field = QLineEdit()
self.name_field = QLineEdit()
self.setupUI()
def setupUI(self):
layout = QFormLayout()
layout.addRow("Date:", self.date_field)
layout.addRow("Time:", self.time_field)
layout.addRow('Name: ', self.name_field)
self.layout.addLayout(layout)
self.buttonsBox = QDialogButtonBox(self)
self.buttonsBox.setOrientation(Qt.Horizontal)
self.buttonsBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonsBox.accepted.connect(self.accept)
self.buttonsBox.rejected.connect(self.reject)
self.layout.addWidget(self.buttonsBox)
def accept(self):
self.data = []
for field in (self.date_field, self.time_field, self.name_field):
self.data.append(field.text())
super().accept()
class LineEditDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)
self.time = None
self.date = None
self.name = None
def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
return editor
def setEditorData(self, editor, index):
editor.setText(index.model().data(index, QtCore.Qt.EditRole))
self.name = index.model().data(index, QtCore.Qt.EditRole)
def setModelData(self, editor, model, index):
value = editor.text()
model.setData(index, value, QtCore.Qt.EditRole)
self.date = model.item(index.row(), 0).text()
self.time = model.item(index.row(), 1).text()
self.update_cell_data()
print('Date: ', MyCalendar().selectedDate().toString('dd.MM.yyyy'))
def update_cell_data(self):
update_cell = QSqlQuery()
update_cell.prepare('UPDATE for_stackoverflow SET fio = ? WHERE date = ? AND time = ?')
update_cell.addBindValue(self.name)
update_cell.addBindValue(self.date)
update_cell.addBindValue(self.time)
update_cell.exec_()
class MyCalendar(QCalendarWidget):
def __init__(self):
super().__init__()
def excepthook(exc_type, exc_value, exc_tb):
tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
print("Error!:", tb)
if __name__ == "__main__":
sys.excepthook = excepthook
app = QtWidgets.QApplication(sys.argv)
if not create_connection("for_stackoverflow.sqlite"):
sys.exit(1)
window = MyWindow()
window.show()
sys.exit(app.exec_())