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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
| #!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import os
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
elif index.column() == 1: # => on est dans la colonne des flottants
# crée le widget d'édition des flottants
editor = QtWidgets.QDoubleSpinBox(parent)
editor.setRange(-1000000.0, +1000000.0)
editor.setDecimals(15)
# 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))
elif index.column() == 1: # => on est dans la colonne des flottants
# 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(float(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
elif index.column() == 1: # => 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(basesql):
"""ouvre la base sqlite3 "basesql" sous PyQt5 et renvoie la connexion
si échec, retourne None
"""
driver = "QSQLITE"
cnx = QtSql.QSqlDatabase.addDatabase(driver)
cnx.setDatabaseName(basesql)
if not cnx.open():
cnx = None
return cnx
#############################################################################
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, basesql, nomtable, parent=None):
super().__init__(parent)
self.setWindowTitle("Code test SQL")
self.resize(800, 600)
self.basesql = basesql # nom de la base de donnnées
self.nomtable = nomtable # nom de la table à afficher
# ouvre la base de données
self.cnx = ouvrebaseqt(self.basesql)
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)
basesql = os.path.abspath("mabase.db3")
table = "matable"
fen = Fenetre(basesql, table)
fen.show()
sys.exit(app.exec_()) |
Partager