Retour aux projetsKLEIN.
Projet C++ / Qt$ Terminé
Dépôt GitHub

Treemap - Visualiseur d'Espace Disque

Une application Windows en C++17 / Qt6 qui scanne un disque et affiche l'espace utilisé sous forme de treemap : chaque dossier et fichier est représenté par un rectangle dont l'aire est proportionnelle à sa taille, façon WinDirStat.

Scan complet du disque système C:\ (648 Go) affiché en treemap
~/stack.json

"Langage & Standard":

C++17

"Framework GUI":

Qt 6 (Widgets, QGraphicsView)

"Algorithme":

Squarified Treemap (Bruls, Huizing, van Wijk)

"Scan disque":

std::filesystem + QtConcurrent

Présentation du Projet

Le principe est simple : sélectionner un disque, lancer un scan en arrière-plan (l'interface ne freeze pas), puis explorer visuellement l'espace utilisé sous forme de rectangles colorés par type de fichier. Un panneau arborescence synchronisé permet de naviguer directement dans un dossier précis, sans avoir à zoomer niveau par niveau dans le treemap.

Treemap Coloré par Type

Chaque rectangle est coloré selon son type de fichier (exécutables, vidéos, images, code, archives...), pour repérer d'un coup d'œil ce qui occupe l'espace.

Arborescence Synchronisée

Panneau arborescence à gauche avec la taille de chaque dossier, synchronisé en temps réel avec le treemap affiché à droite.

Navigation par Clic

Zoom dans un dossier au clic, bouton Retour pour remonter, ou clic direct dans l'arborescence pour sauter à n'importe quel niveau.

Info-bulles & Explorateur

Survol pour afficher le chemin complet, la taille et le % du dossier parent ; clic droit pour afficher l'élément dans l'explorateur Windows.

Arborescence synchronisée avec le treemap
Arborescence synchronisée - cliquer un dossier zoome directement dans le treemap.
Navigation imbriquée sur un disque de jeux D:\
Disque de jeux (D:\, 703 Go) - vidéos en violet, données en orange.

Focus Algorithmique : Squarified Treemap

Le cœur du projet est une implémentation de l'algorithme squarified treemap (Bruls, Huizing, van Wijk) : à chaque niveau, les enfants sont regroupés en rangées de façon à garder des rectangles aussi proches du carré que possible, plutôt que des bandes fines illisibles. Taille minimum garantie pour qu'un petit fichier à côté d'un dossier énorme ne devienne jamais invisible.

Récursif vs itératif - le bug réel derrière le choix

Récursif - crash (rejeté)

stack overflow

Une frame par fichier traité. Sur un dossier à plusieurs centaines de milliers d'entrées, la pile déborde et le programme plante - sans message exploitable.

Itératif - stable (retenu)

...

Une boucle while sur une pile explicite : la mémoire utilisée reste plate, quel que soit le nombre de fichiers.

Architecture en Quatre Briques

Le projet est découpé en quatre briques indépendantes, chacune responsable d'une étape du pipeline scan → layout → affichage.

FileNode

La structure de données de base : un nœud représente un fichier ou un dossier. Le chemin complet n'est jamais stocké dans chaque nœud (seulement le nom) - pour un scan de plusieurs millions de fichiers, ça doublerait inutilement la mémoire utilisée. Il se reconstruit à la demande en remontant le pointeur parent.

Scanner

Parcourt le disque récursivement avec std::filesystem. Exclut les dossiers système inaccessibles ($Recycle.Bin, WinSxS...), détecte les jonctions/reparse points, et isole les erreurs par entrée pour ne jamais interrompre le reste du scan.

TreeMapLayout

Le cœur algorithmique : transforme l'arbre de FileNode en rectangles via l'algorithme squarified treemap, de façon itérative pour supporter les dossiers à plusieurs milliers d'enfants.

MainWindow

L'interface Qt Widgets : barre du haut (scan, retour, progression), QSplitter horizontal entre QTreeWidget et QGraphicsView/QGraphicsScene, profondeur de rendu limitée à 3 niveaux pour rester lisible.

Défis Techniques & Solutions

Stack Overflow sur les Gros Scans

Le scan complet du disque système (C:\, 648 Go) a débusqué un crash par stack overflow, résolu en passant à une boucle itérative.

Boucles Infinies sur les Jonctions

Détection via FILE_ATTRIBUTE_REPARSE_POINT, avec une limite de profondeur (256) en filet de sécurité.

Interface Réactive Pendant le Scan

Thread séparé via QtConcurrent::run, callback renvoyé via QMetaObject::invokeMethod.

Compilation & Limites

~/treemap/build

$ compilation (CMake + Qt6)

cmake -B build -S .
cmake --build build

Testé avec Qt 6.11.1 / MinGW 64-bit sur Windows.

  • Windows uniquement pour l'instant (les détections de jonctions/reparse points utilisent l'API Win32).
  • Pas d'annulation possible une fois un scan lancé.

Ce que j'ai appris

Algorithmique Itérative & Robustesse

Implémentation du squarified treemap sous forme de boucle while plutôt que récursive : un dossier peut contenir des milliers d'enfants, et une version récursive classique fait planter le programme par stack overflow sur ce genre de cas réel.

Concurrence avec Qt (QtConcurrent)

Exécution du scan disque dans un thread séparé via QtConcurrent::run pour ne jamais geler l'interface, avec un callback de progression renvoyé proprement sur le thread principal via QMetaObject::invokeMethod.

Système de Fichiers & API Win32

Parcours récursif avec std::filesystem, détection des jonctions et reparse points Windows pour éviter les boucles infinies, et isolation des erreurs par entrée pour qu'un seul fichier problématique n'interrompe jamais tout le scan.

Qt Widgets Avancé

Synchronisation bidirectionnelle entre un QTreeWidget et une QGraphicsScene, calcul du layout dans un repère logique fixe (1600×900) étiré via fitInView pour un rendu stable quel que soit le redimensionnement de la fenêtre.