#!/usr/bin/python3 # -*- coding: utf-8 -*- import sys from config import * from PyQt5 import QtCore, QtGui, QtWidgets, QtSql ############################################################################# class MonSqlRelationalDelegate(QtSql.QSqlRelationalDelegate): #======================================================================== def __init__(self, parent=None): super().__init__(parent) #======================================================================== def createEditor(self, parent, option, index): """Crée et initialise le widget d'édition aParent: type 'PyQt5.QtWidgets.QWidget' option: type 'PyQt5.QtWidgets.QStyleOptionViewItem' index: type 'PyQt5.QtCore.QModelIndex' Retourne l'éditeur utilisé """ if index.column() == 0: # => on est dans la colonne des entiers # crée le widget d'édition des entiers editor = QtWidgets.QSpinBox(parent) editor.setRange(-1000000, +1000000) # retourne le widget return editor else: # cas d'une autre colonne: on repasse la main à l'ancêtre return super().createEditor(parent, option, index) #======================================================================== def setEditorData(self, editor, index): """Définit l'état du widget concerné à l'entrée du mode édition editor: QtWidgets.QWidget index: QtCore.QModelIndex Retour: None """ if index.column() == 0: # => on est dans la colonne des entiers # récupère la valeur de la base de données valeur = index.model().data(index, QtCore.Qt.EditRole) # charge la valeur dans le widget avec le bon type editor.setValue(int(valeur)) else: # cas d'une autre colonne: on repasse la main à l'ancêtre super().setEditorData(editor, index) #======================================================================== def setModelData(self, editor, model, index): """ Enregistre la valeur modifiée dans la base de données editor: type 'QtWidgets.QWidget' model: type 'QtCore.QAbstractItemModel' index: type 'QtCore.QModelIndex' Retour: None """ if index.column() == 0: # => on est dans la colonne des entiers #lit la valeur affichée dans le widget en fin d'édition valeur = editor.value() # enregistre dans le modèle la valeur affichée model.setData(index, str(valeur), QtCore.Qt.EditRole) return else: # traite les autres cas super().setModelData(editor, model, index) return ############################################################################# def ouvrebaseqt(): """ouvre la base avec le pilote "QPSQL" pour PostgreSQL, et renvoie la connexion (ou None si échec) """ params = config() db = QtSql.QSqlDatabase.addDatabase("QPSQL") db.setHostName(params['host']) db.setDatabaseName(params['database']) db.setUserName(params['user']) db.setPassword(params['password']) db.open() if not db.open(): db = None return db ############################################################################# def fermebaseqt(cnx): """Ferme la base ouverte avec la connexion cnx de PyQt5 """ if cnx!=None: cnx.close() ############################################################################## class Fenetre(QtWidgets.QWidget): #========================================================================= def __init__(self, nomtable, parent=None): super().__init__(parent) self.setWindowTitle("Code test SQL") self.resize(800, 600) self.nomtable = nomtable # nom de la table à afficher # ouvre la base de données self.cnx = ouvrebaseqt() if self.cnx==None: QtWidgets.QMessageBox.critical(self, "Ouverture de la base de données", "Echec: base défaillante ou non trouvée") self.close() sys.exit() # crée le modèle self.model = QtSql.QSqlRelationalTableModel(self, self.cnx) # pour afficher la table demandée self.model.setTable(self.nomtable) # pour mise à jour de la base à chaque modification d'une valeur self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange) # crée la grille d'affichage self.vuetable = QtWidgets.QTableView(self) # lien avec le modèle self.vuetable.setModel(self.model) # active la possibilité de tri self.vuetable.setSortingEnabled(True) # lien avec un delegate personnalisé pour l'édition self.vuetable.setItemDelegate(MonSqlRelationalDelegate(self.vuetable)) # peuple le modèle avec les données de la table de la base de données self.vuetable.model().select() # tri si nécessaire selon la colonne 0 self.model.sort(0, QtCore.Qt.AscendingOrder) # ou DescendingOrder # positionne la grille d'affichage dans la fenêtre layout = QtWidgets.QGridLayout() layout.addWidget(self.vuetable, 0, 0) self.setLayout(layout) #========================================================================= def closeEvent(self, event): if self.cnx!=None: fermebaseqt(self.cnx) event.accept() ############################################################################## if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) table = "tabletest" fen = Fenetre(table) fen.show() sys.exit(app.exec_())