1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
| #!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5 import (QtWidgets, QtCore, QtSql)
#############################################################################
def ouvrebaseqt(basesql):
"""ouvre la base 'basesql' avec le pilote "QSQLITE" pour sqlite3, et
renvoie la connexion (ou None si échec)
"""
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(basesql)
if not db.open():
db = None
return db
#############################################################################
def fermebaseqt(db):
if db!=None:
db.close()
#############################################################################
class VoirTableSql(QtWidgets.QMainWindow):
def __init__(self, basesql, nomtable, relations=[], titres=[], parent=None):
super().__init__(parent)
self.setWindowTitle("Affichage de la table %s" % (nomtable,))
self.resize(400, 320)
# enregistre les arguments passés
self.basesql = basesql # base de données
self.nomtable = nomtable # nom de la table à afficher
self.relations = relations # liste des contraintes de clés étrangères
self.titres = titres # liste des titres des colonnes de la table
# ouvre la base SQL
self.db = ouvrebaseqt(self.basesql)
if self.db == None:
QtWidgets.QMessageBox.critical(self,
"Ouverture de la base de données",
"Erreur d'ouverture")
self.close()
sys.exit()
# crée le modèle et sa liaison avec la base SQL ouverte
self.model = QtSql.QSqlRelationalTableModel(self, self.db)
# stratégie en cas de modification de données par l'utilisateur
self.model.setEditStrategy(QtSql.QSqlRelationalTableModel.OnManualSubmit)
# désigne la table à afficher
self.model.setTable(self.nomtable)
# enregistre les contraintes de clés étrangères (plusieurs possible)
for col, tab, champ1, champ2 in self.relations:
self.model.setRelation(col, QtSql.QSqlRelation(tab, champ1, champ2))
# force le chargement complet de la table contenant la clé étrangère
modelref = self.model.relationModel(col)
while modelref.canFetchMore():
modelref.fetchMore()
# peuple le modèle avec les données de la table
self.model.select()
# trie si nécessaire selon la colonne 0
self.model.sort(0, QtCore.Qt.AscendingOrder) # ou DescendingOrder
for i, titre in enumerate(self.titres):
self.model.setHeaderData(i, QtCore.Qt.Horizontal, titre)
# crée la table graphique et son lien avec le modèle
self.vuetable = QtWidgets.QTableView(self)
self.vuetable.setModel(self.model)
# active le tri en cliquant sur les têtes de colonnes
self.vuetable.setSortingEnabled(True)
# met un delegate standard pour l'édition
self.vuetable.setItemDelegate(QtSql.QSqlRelationalDelegate(self.vuetable))
# ajuste hauteur lignes et largeur colonnes selon contenus
self.vuetable.resizeColumnsToContents()
self.vuetable.resizeRowsToContents()
# crée un bouton pour enregistrer les modifications dans la base
self.bouton1 = QtWidgets.QPushButton("Enregistrer les modifications", self)
self.bouton1.clicked.connect(self.appliquer)
# crée un bouton pour annuler les modifications non enregistrées
self.bouton2 = QtWidgets.QPushButton("Annuler les modifications", self)
self.bouton2.clicked.connect(self.annuler)
# positionne les widgets dans la fenêtre QMainWindow
self.setCentralWidget(QtWidgets.QFrame())
posit = QtWidgets.QGridLayout()
posit.addWidget(self.bouton1, 0, 0)
posit.addWidget(self.bouton2, 0, 1)
posit.addWidget(self.vuetable, 1, 0, 1, 2)
self.centralWidget().setLayout(posit)
#========================================================================
def appliquer(self):
"""Enregistre les modifications des données
"""
if self.model.submitAll():
# ajuste hauteur lignes et largeur colonnes selon contenus
self.vuetable.resizeColumnsToContents()
self.vuetable.resizeRowsToContents()
# message ok
QtWidgets.QMessageBox.information(self,
"Enregistrement des modifications",
"Enregistrement terminé")
else:
# message erreur
QtWidgets.QMessageBox.warning(self,
"Enregistrement des modifications",
"Erreur: %s" % self.model.lastError().text())
#========================================================================
def annuler(self):
"""Annule les modifications des données faites avant enregistrement
"""
self.model.revertAll()
#========================================================================
def closeEvent(self, event=None):
"""Méthode appelée automatiquement à la fermeture de la fenêtre
"""
# ferme la base
fermebaseqt(self.db)
# et accepte la fermeture de la fenêtre
event.accept()
#############################################################################
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
nombase = "mabase.db3"
table = "clients"
relations = [[3, 'nations', 'nation', 'nation']]
titres = ['idclient', 'nom', 'prénom', 'nation']
fen = VoirTableSql(nombase, table, relations, titres)
fen.show()
sys.exit(app.exec_()) |
Partager