Le poste de contrôle (PC) / Les graphes /
Droit à l'erreur : Undo & Redo

Parcours de l'historique par undo & redo


Avant-propos

Réviser ou étudier :

Refactoring :


Description

Super-dictionnaires od_pkl successifs dans le temps.
 

Principe :

 

Mise en pratique :

Limites :


Ajoutez 2 boutons dans la barre d'outils :  et  , revoir si nécessaire les tutos antérieurs ou visionner la vidéo.

 Au lancement de l'appli, dictionnaire dq_histos vide (Undo et Redo désactivés).

 Des modifications, pointeur à la fin (Redo désactivé).

 Des modifications, pointeur au début (Undo désactivé)

 Des modifications, pointeur à l'intérieur, ni au début ni à la fin.

Ajoutez les boutons Undo et Redo avec Qt Designer. :


Fichier /pc/undo_redo.py, contenant la classe UndoRedo :

import copy
from collections import deque


class UndoRedo:
    """ Instancié par CtrlScene. """
    def __init__(self, o_scene):
        self.o_scene = o_scene
        self.pointer = 0
        self.b_action = False
        self.b_undo = False
        self.b_redo = False
        """ Les éléments de la liste dq_histo sont les super-dictionnaires od_pkl successifs dans le temps. """
        self.dq_histos = deque([copy.deepcopy(self.o_scene.o_pkl.od_pkl)], maxlen=100)    # Taille de l'histo = maxlen

    def state(self):
        """ État des icones 'Undo' et 'Redo' dans la toolbox. """
        histo_max = len(self.dq_histos) - 1
        self.b_undo = self.pointer > 0
        self.b_redo = self.pointer < histo_max
        """ État des boutons : actifs ou grisés. """
        self.o_scene.o_main.actionUndo.setEnabled(self.b_undo)
        self.o_scene.o_main.actionRedo.setEnabled(self.b_redo)

    def add_do(self):
        """ Le code appelant doit lever le flag b_action pour que le nouvel état soit ajouté à l'historique. """
        if self.b_action:
            """ Option : Suppression de tous les éléments après le pointeur. Décommenter pour l'activer. """
            # histo_max = len(self.dq_histo) - 1
            # for i in range(histo_max - self.pointer):
            #     self.dq_histo.pop()

            """ Ajout. Si maxlen est atteint, le 1er élément (le plus ancien) est automatiquement supprimé. """
            self.dq_histos.append(copy.deepcopy(self.o_scene.o_pkl.od_pkl))

            """ Pointeur placé à la fin. """
            self.pointer = len(self.dq_histos) - 1
            self.state()

            """ Histo à jour => On baisse le drapeau. """
            self.b_action = False

    def undo(self):
        if self.b_undo:
            self.pointer -= 1
            self.show()

    def redo(self):
        if self.b_redo:
            self.pointer += 1
            self.show()

    def show(self):
        """ Le super-dictionnaire od_pkl est surchargé par l'élément pointé de l'historique. """
        self.state()
        self.o_scene.o_pkl.od_pkl = copy.deepcopy(self.dq_histos[self.pointer])
        self.o_scene.o_pkl.backup()
        self.o_scene.show_items()

Ajoutez cette déclaration dans CtrlScene.__init__() :

        self.o_ur = None            # Instance de UndoRedo.

Ajoutez cette affectation dans CtrlScene.setup(), ne pas oublier d'importer UndoRedo :

        """ Undo-Redo. """
        self.o_ur = UndoRedo(self)

Coding :
  • Nous allons coder de façon peu habituelle : en rectifiant le code par corrections successives ...
  • ... un peu à la manière des TDD, mais avec un contrôle visuel.
  • Supposons le problème résolu, et lançons l'application :
    • Afficher plusieurs onglets contenant des graphes, par exemple Couleurs, Court-circuits et Croisements du tuto précédent.
    • Cela nous servira de base pour cet exercice.
  • Vous noterez qu'au fur et à mesure, nous découvrirons des bugs oubliés ; nous en profiterons pour les corriger.
  • Si vous êtes programmeur débutant, bienvenue au club !

Les problèmes rencontrés sont les suivants :

  1. Problème 1 : Les boutons Undo et Redo devraient être désactivés au démarrage.
  2. Problème 2 : Lorsqu'on fait une modification, il ne sa passe rien, les boutons restent désactivés.
    1. Problème 2.1 : La méthode add_do() est appelée lorsqu'on clique simplement sur un node, sans même le déplacer.
      1. Problème 2.1.1 : Lorsque la grille n'est pas magnétique, le tooltip du node affiche la position avec un grand nombre de décimales.
    2. Problème 2.2 : Mitraillage : L'appel de la méthode add_do() apparaît autant de fois qu'il y a de nodes sélectionnés, déplacés dans le graphe.
    3. Problème 2.3 : L'historique dq_histos n'a pas été incrémenté, les 2 boutons restent désactivés.
  3. Problème 3 : Suite à une modification, lorsqu'on clique sur le bouton Redo, rien ne se passe.
  4. Problème 4 : La méthode CtrlScene.show_items() est absente.

 


Problème 1

Retour au plan


Problème 2

Retour au plan


Problème 2.1

Retour au plan


Problème 2.1.1

Retour au plan


Problème 2.2

Retour au plan


Problème 2.3

Retour au plan


Problème 3

Retour au plan


Problème 4

Retour au plan


Option :

Bonjour les codeurs !