Skip to content

project_database FR

ispyisail edited this page Sep 11, 2026 · 1 revision

La base de données du projet

QElectroTech construit une base de données SQLite pour chaque projet ouvert. Il vaut la peine d'être précis sur ce qu'est cette base, car son nom invite à une supposition qui est fausse :

La base de données du projet est un cache dérivé, en mémoire. Elle est reconstruite à partir du XML .qet à chaque ouverture du projet, et elle n'est jamais réécrite dans le fichier projet. Le XML est la seule chose qui persiste.

Tout le reste de cette page découle de cette seule phrase.

Source : sources/dataBase/projectdatabase.{h,cpp}.


1. Pourquoi elle existe

Répondre à « liste tous les composants de ce projet, avec leurs références fabricant, groupés par folio » depuis une scène graphique suppose de parcourir des milliers de QGraphicsItem et de comparer des chaînes. Y répondre depuis une table, c'est un SELECT.

QET conserve donc la même information sous une seconde forme, adaptée aux requêtes, et s'en sert pour ce qui est naturellement une requête :

Consommateur Ce qu'il lit
Tableaux de nomenclature placés sur un folio element_nomenclature_view, via ProjectDBModel
Le constructeur de requêtes de nomenclature n'importe laquelle des vues, assemblée dans ElementQueryWidget
Dialogue de liste de câblage wiring_list_view
--export-bom (ligne de commande) element_nomenclature_view
--export-wires, --export-cables wiring_list_view
Tableaux récapitulatifs de folios project_summary_view

Aucun de ces usages n'est du stockage. Chacun est un rapport sur des données qui existent déjà dans le XML.


2. Cycle de vie

QETProject construit
    └── projectDataBase construit  →  createDataBase()
                                       ├── ouvre une connexion SQLite anonyme
                                       ├── CREATE TABLE × 6, CREATE VIEW × 3
                                       └── updateDB()
XML du projet lu
    └── updateDB()   ← repeuplement complet, une fois, tout étant chargé
l'utilisateur édite le folio
    └── addElement / removeElement / elementInfoChanged
        addDiagram  / removeDiagram / diagramInfoChanged / diagramOrderChanged
        addConductor/ removeConductor / updateConductor      ← incrémental
projet fermé
    └── base abandonnée

QSqlDatabase::addDatabase("QSQLITE", …) est appelé sans setDatabaseName() : il n'y a donc aucun fichier sur disque vers lequel la connexion pointerait. Pendant le chargement, les signaux de la base sont bloqués et un unique updateDB() s'exécute à la fin, plutôt qu'une insertion par objet au fur et à mesure de la construction de la scène.

Trois PRAGMA sont posés juste après l'ouverture — temp_store = MEMORY, journal_mode = MEMORY, synchronous = OFF. Ces réglages seraient inconsidérés pour une base à laquelle on tient. Ils sont corrects ici précisément parce que tout perdre ne coûte rien : elle est reconstruite à l'ouverture suivante.

QETProject::readProjectXml() journalise la durée de chaque phase du chargement, dont la reconstruction de la base : le coût sur un projet donné se lit donc directement dans la sortie console au lieu d'être supposé.


3. Schéma

Six tables :

Table Clé Remarques
diagram uuid plus pos, l'ordre des folios
element uuid diagram_uuid, pos, type, sub_type
diagram_info diagram_uuid une colonne par QETInformation::diagramInfoKeys() — 9 aujourd'hui
element_info element_uuid une colonne par QETInformation::elementInfoKeys() — 57 aujourd'hui
terminal (uuid, element_uuid) voir §4
conductor uuid les deux extrémités en paires (uuid de borne, uuid d'élément)

Trois vues : element_nomenclature_view, project_summary_view, wiring_list_view.

Remarquez ce que signifient ces listes de colonnes : le schéma est engendré à l'exécution à partir de elementInfoKeys(). Ajouter un champ d'information d'élément ajoute une colonne automatiquement, sans migration ni version de schéma — parce qu'il n'existe aucune base à migrer. C'est la conséquence pratique la plus importante du fait que le cache soit dérivé.

Le filtre est dans la vue, pas dans la table

element contient tous les types d'éléments, esclaves et renvois de folio compris. La restriction aux « choses qu'une nomenclature doit mentionner » (type IN ('simple','terminal','master','thumbnail')) se fait à l'intérieur de element_nomenclature_view.

Il n'en a pas toujours été ainsi, et la raison du changement est instructive : avec le filtre dans la table, un élément esclave (un contact de relais) était totalement absent de la base, si bien que tout autre lecteur de la table — la liste de câblage, par exemple — perdait silencieusement chaque conducteur aboutissant à un contact de relais. L'opinion d'une nomenclature sur ce qui constitue une ligne n'a pas sa place dans le modèle que le projet a de lui-même.


4. L'identité, et pourquoi les bornes sont difficiles

Les lignes ont besoin de clés stables. Les éléments et les folios ont de vrais UUID : pas de problème. Les bornes, non.

Terminal::uuid() provient de la définition .elmt du catalogue. Il identifie une position de borne dans un symbole — « la borne du haut d'un contacteur » — et il est donc identique pour chaque instance placée de ce symbole. Il est en outre vide pour tout élément créé avant l'existence de ce champ, c'est-à-dire pour l'essentiel de la collection installée.

Deux conséquences, toutes deux traitées :

  • Une instance de borne n'est unique que par la paire (uuid, element_uuid) : c'est pourquoi cette paire, et non uuid seul, est la clé primaire de la table des bornes et la cible des clés étrangères de la table des conducteurs.
  • Terminal::stableUuid() fournit une identité lorsque la définition n'en donne aucune, dérivée en UUID v5 à partir de la position locale et de l'orientation de la borne dans son élément — la même base que celle que le format de projet utilise déjà pour rattacher un conducteur à une borne. Les noms sont délibérément exclus de la dérivation, car QET réécrit une borne nommée _ comme non nommée, ce qui changerait son identité dès la première réécriture.

projectDataBase::excludedConductorCount() indique combien de conducteurs n'ont pu être indexés du tout, en comptant depuis la scène vivante et non depuis la base — « précisément parce que la base est là où ces conducteurs ne sont pas ». C'est ce qui permet à une liste de câblage d'annoncer « N fils manquent, et voici pourquoi » au lieu de présenter une liste incomplète comme si elle était complète.

C'est la contrainte à garder en tête pour tout travail futur sur la persistance. Tant que la base est dérivée, une borne dont l'identité est devinée par la géométrie coûte un défaut de cache. Dans un format de fichier, la même supposition devient une migration définitive, en une seule fois, des projets de tout le monde.


5. Ce qui découle de « dérivée »

Parce qu'elle est dérivée… …ceci est vrai
Reconstruite à chaque ouverture Aucune version de schéma, aucune migration, jamais
Jamais écrite dans le .qet Une ligne erronée ne coûte rien — rouvrez, elle a disparu
Le XML fait autorité La base ne peut pas contredire le dessin ; si c'est le cas, c'est la base qui a tort
Abandonnée à la fermeture synchronous = OFF et consorts sont sans danger
Vit dans un seul processus Elle n'est ni partagée, ni concurrente, ni multi-utilisateur

Et le revers, tout aussi vrai :

Parce qu'elle est dérivée… …ceci est vrai aussi
Rien ne survit à la fermeture Tout ce que la base seule sait est perdu
Reconstruite intégralement à l'ouverture Le coût d'ouverture croît avec la taille du projet
Absente du fichier Deux personnes ne peuvent pas interroger la même base de projet

6. La voir par soi-même

Les compilations avec QET_EXPORT_PROJECT_DB disposent d'une entrée de menu, Exporter la base de donnée interne du projet, qui copie la base vivante dans un fichier .sqlite via l'API de sauvegarde de SQLite. L'option CMake vaut OFF par défaut, mais les empaquetages officiels Windows, macOS, Flatpak et Snap l'activent tous — sur une version publiée, l'entrée est donc normalement présente.

Le fichier exporté est un instantané, pour inspection. Le modifier ne change rien : rien ne le relit jamais.

sqlite3 monprojet.sqlite ".schema"
sqlite3 monprojet.sqlite "SELECT label, designation FROM element_nomenclature_view LIMIT 20;"

7. Ce qu'elle n'est pas

Ce n'est pas le fichier projet, ni une base partagée à laquelle une équipe se connecte, ni l'architecture « base de composants plus vue de dessin » d'outils comme EPLAN. Un projet reste un unique fichier XML ; la base est un index de requêtes au-dessus de lui, qui vit tant que la fenêtre est ouverte.

Savoir si cela doit rester ainsi est une question ouverte — voir les pages Vision et Feuille de route. Tout mouvement vers une persistance est une modification du format de fichier, dont le problème d'identité des bornes du §4 est le premier véritable obstacle.

Tant qu'une telle décision n'est pas prise, une règle empirique mérite d'être suivie lorsqu'on ajoute une fonctionnalité : ne créez pas d'état que seul le XML connaît, et ne créez pas d'état que seule la base connaît. Le premier rend le cache incomplet ; le second ne survit pas à une fermeture.

Getting Started

Home

🌐 Languages — English · Français · Deutsch

Downloads

Windows without admin rights — the portable archive, no installer

Quick Start Guide

User Manual

FAQ

Tips & Tricks

Guides

Conductors — wire properties, what feeds which export, cables, and hops where wires cross

Wires per terminal — limit the wires on a terminal, chain wiring instead of stars

Printing and exporting — paper, PDF, images, and what each path does differently

Linking elements — master, slave, terminal

PLC modules — I/O tables and linking a wire to a specific point

Using the element editor — drawing tools, saving, checks

Grid size and element size — why symbols aren't all the same scale, and scaling one without leaving the grid

Preferences reference — what each settings page does

Saving and loading settings — your whole setup in one file, to copy or keep

Keyboard-only control — mouseless QET, and what still needs a mouse

Mouse modifiers — what Shift, Ctrl and Alt change while you drag

3D mouse — SpaceMouse pan, zoom and buttons

Aligning items — snap symbols back to the grid, or line them up

Pictures on a sheet — labels, crop, transparency, what they cost in the file

Arcs and curved wires — the Arc tool, pulling an arc in or out, rounding a corner with a fillet, dashed arcs for lighting layouts

Grouping items — select, move and copy several items as one

Finding your place on a sheet — go to a cell like B13 or 4-B7, keep the headers in sight, show the cell limits, zoom and pan

Showing and hiding kinds of items — hide texts, wire numbers, shapes, pictures, tables or cross-references on every sheet

Drawing faster — place without dragging, the S shortcut bar, command search, gestures

Customising QElectroTech — keys, toolbar size and contents, the gesture ring (partly pending)

Managing collections — folders, writability, building your own shortlist

Templates — reusable multi-element blocks, placed by double-click or drag

Search & Replace — bulk property changes

Building a nomenclature query — the BOM/summary table builder

Linking wires across pages — sheet reports

Variables & formulas — %f, %{label}, sequences

Auto-numbering — schemes, sequences, freezing

Terminal strips — strips, levels, bridges

Title block templates — the .titleblock format

Importing EPLAN parts (.edz) — EPLAN Data Portal

DXF import & export — two unrelated features, one format; command-line export and layers

The project database — the in-memory SQLite cache

File formats
Elements XML
Project XML
Development

Building from Source

Contributing Code

Automating QET — CLI, XML formats, external tools

CLI Reference — command line usage

JavaScript Scripting — --run, geometry editing, undo

MCP server — let an AI assistant read, verify and edit projects

Connecting an AI assistant — setup for Claude, Copilot, Gemini, Codex, Cursor, LM Studio

Script buttons — stored scripts with an icon, by hand or by an assistant

Live mode — an assistant working in the open project while you watch

Macro recorder — record a task by hand, for an assistant to script

Development Roadmap

Vision — proposal, under discussion

Developer Tools

About

Features

History

Community

License

Contributing to this Wiki

Clone this wiki locally