En fait (vous allez me tuer je le sens

), Qt n'utilise pas vraiment MVC mais une version simplifiée de ce système : l'architecture modèle/vue.
Et le contrôleur on en fait quoi ? Poubelle ? Notre programme ne réfléchit pas ?
Si si, je vous rassure. En fait, le contrôleur est intégré à la vue avec Qt.
Grâce à ça, les données sont toujours séparées de leur affichage, mais on diminue un peu la complexité du modèle MVC en évitant au programmeur d'avoir à gérer les 3 parties.
On s'éloigne donc un petit peu de la théorie pure sur MVC ici, pour s'intéresser à la façon dont Qt utilise ce principe en pratique.
Vous venez donc d'apprendre que Qt adaptait ce principe à sa manière, pour garder les bonnes idées principales sans pour autant vous obliger à "trop" découper votre code ce qui aurait pu être un peu trop complexe et répétitif à la longue.
Nous n'allons donc plus parler ici que de modèle et de vue. Comment sont gérés chacun de ces éléments avec Qt ?
Cette question... avec des classes, comme d'habitude !
Les classes gérant le modèle
Il y a plusieurs types de modèles différents. En effet : on ne stocke pas de la même manière une liste d'élèves qu'une liste de villes !
Vous avez 2 possibilités :
- Soit vous créez votre propre classe de modèle. Il faut créer une classe héritant de QAbstractItemModel. C'est la solution la plus flexible mais aussi la plus complexe, nous ne la verrons pas ici.
- Soit vous utilisez une des classes génériques toutes prêtes offertes par Qt :
- QStringListModel : une liste de chaînes de caractères, de type QString. Très simple, très basique. Ca peut suffire pour les cas les plus simples.
- QStandardItemModel : une liste d'éléments organisés sous forme d'arbre (chaque élément peut contenir des sous-éléments). Ce type de modèle est plus complexe que le précédent, car il gère plusieurs niveaux d'éléments. Avec QStringListModel, c'est un des modèles les plus utilisés.
- QDirModel : la liste des fichiers et dossiers stockés sur votre ordinateur. Ce modèle va analyser en arrière-plan votre disque dur, et restitue la liste de vos fichiers sous la forme d'un modèle prêt à l'emploi.
- QSqlQueryModel, QSqlTableModel et QSqlRelationalTableModel : données issues d'une base de données. On peut s'en servir pour accéder à une base de données (ceux qui ont déjà utilisé MySQL, Oracle ou un autre système du genre seront probablement intéressés).
Je ne vais pas rentrer dans les détails de la connexion à une base de données dans ce chapitre, ce serait un peu hors-sujet.
Toutes ces classes proposent donc des modèles prêts à l'emploi, qui héritent de QAbstractItemModel.
Si aucune de ces classes ne vous convient, vous devrez créer votre propre classe en héritant de QAbstractItemModel.
Notez que je n'ai pas représenté toutes les classes de modèles ici.
Les classes gérant la vue
Pour afficher les données issues du modèle, il nous faut une vue. Avec Qt, la vue est un widget, puisqu'il s'agit d'un affichage dans une fenêtre.
Tous les widgets de Qt ne sont pas bâtis autour de l'architecture modèle/vue, loin de là (et ça n'aurait pas d'intérêt pour les plus simples d'entre eux que nous avons vu jusqu'à présent).
On compte 3 widgets adaptés pour la vue avec Qt :
- QListView : une liste d'éléments.
- QTreeView : un arbre d'éléments, où chaque élément peut avoir des éléments enfants.
- QTableView : un tableau.
Voilà donc les fameux "widgets" complexes que je vais vous présenter dans ce chapitre. Mais pour pouvoir les utiliser et les peupler de données, il faut d'abord créer un modèle !
Appliquer un modèle à la vue
Lorsqu'on utilise l'architecture modèle/vue avec Qt, cela se passe toujours en 3 temps. Il faut :
- Créer le modèle
- Créer la vue
- Associer la vue et le modèle
La dernière étape est essentielle. Cela revient en quelque sorte à "connecter" notre modèle à notre vue. Si on ne donne pas de modèle à la vue, elle ne saura pas quoi afficher, donc elle n'affichera rien.
La connexion se fait toujours avec la méthode
setModel()
de la vue :
Le contrôleur n'a pas été représenté sur ce schéma car, comme je vous l'ai dit, Qt utilise une architecture modèle/vue simplifiée et se charge de gérer la partie contrôleur pour vous.
Voilà donc comment on connecte un modèle à une vue en pratique.

L'avantage de ce système, c'est qu'il est flexible. On peut avoir 2 modèles et appliquer soit l'un soit l'autre à la vue en fonction des besoins. Un gros intérêt est que dès que l'on modifie le modèle, la vue affiche instantanément les nouveaux éléments !
Plusieurs modèles ou plusieurs vues
On peut pousser le principe un peu plus loin. Essayons d'imaginer que l'on a plusieurs modèles ou plusieurs vues.
Plusieurs modèles et une vue
Imaginons que l'on ait 2 modèles : un qui contient une liste d'élèves, un autre qui contient une liste de capitales avec leur pays. Notre vue peut afficher soit l'un, soit l'autre :
Il faut bien sûr faire un choix : une vue ne peut afficher qu'un seul modèle à la fois !
L'avantage, c'est qu'au besoin on peut changer le modèle affiché par la vue en cours d'exécution, en appelant juste la méthode
setModel()
!
Un modèle pour plusieurs vues
Imaginons le cas inverse. On a un modèle, mais plusieurs vues. Cette fois, rien ne nous empêche d'appliquer ce modèle à 2 vues en même temps !
On peut ainsi visualiser le même modèle de 2 façons différentes (ici sous forme de tableau ou de liste dans mon schéma).
Comme le même modèle est associé à 2 vues différentes, si le modèle change alors les 2 vues changent en même temps ! Par exemple, si je modifie l'âge d'un des élèves dans une cellule du tableau, l'autre vue (la liste) est automatiquement mise à jour sans avoir besoin d'écrire la moindre ligne de code !