Partage
  • Partager sur Facebook
  • Partager sur Twitter

Qt architecture Model View Delegate

Comment interfacer les 3 classes ?

    7 septembre 2021 à 13:49:57

    Bonjour, je poste aujourd'hui car j'ai vraiment du mal à comprendre comment implémenter correctement le design pattern MVD, ne sachant pas vraiment comment m'y prendre je code un peu ce qui me passe par la tête, je me rend bien compte qu'il y a des trucs bizarres sans vraiment savoir comment je pourrais faire mieux 

    Pour le contexte et le besoin d'utiliser un pattern MVD, je vous laisse vous référer au premier message de mon post récent et l'échange que j'ai eu avec Bacelar sur la séparation des parties métiers et affichage 

    J'ai essayé de suivre les indications de la doc Qt au sujet du MVD mais ça ne m'a pas vraiment aider à comprendre concrètement comment implémenter ces 3 classes et comment les interfacer les unes avec les autres. La plupart des exemples n'étant qu'avec des modèles et des vues existantes telle que ListModel, TableModel et TreeModel qui ne me semblent pas adaptés à ce que je cherche à faire (si vous vous référez au screen de mon premier sujet, ma vue c'est le QTabWidget avec tout ce qu'il contient => les 2 QSpinBox)

    Ce que j'ai déjà concrètement codé, c'est pas grand chose mais voilà :

    Une MainWindow pour mettre la vue en centralWidget et gérer d'autres fenêtres secondaires 

    class ModelData;
    class Delegate;
    class ViewModel;
    class StepWidget;
    
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    
    private:
        Ui::MainWindow *ui;
    
        // Un pointeur sur chacune des 3 classes du MVD
        ModelData *m_model { nullptr };
        Delegate *m_delegate { nullptr };
        ViewModel *m_view { nullptr };
        
    };


    Et son constructeur :

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        m_model(new ModelData(this)),
        m_delegate(new Delegate(this)),
        m_view(new ViewModel(this))    
    {
        ui->setupUi(this);
    
        this->setCentralWidget(m_view);
    
        setWindowIcon(QIcon(":/images/windowIcon.png"));
        setWindowTitle("Arduino setter");
    
        // Faire tous les connects entre m_model, m_delegate et m_view ici ???
        
    }

    La question que je me pose surtout c'est :

    Est ce que le model, la vue et le delegate doivent être 3 classes complètement indépendantes les unes des autres et reliées uniquement par des signaux et slots connectés dans la MainWindow ?

    Est ce qu'il serait pertinent que ma vue possède en variable membre un pointeur vers le modèle et le delegate pour que la vue puisse utiliser les getters du modèle dans ses slots pour récupérer les données à afficher (flèche directe Rendering enttre modèle et vue dans la doc de QT) ?

    Le modèle contient un QList<StepWidget*> dont certains seront affichés ou non en fonction du nombre indiqué par le SpinBox "Number of Step". Dans le cas où le nombre de Step demandé est supérieur au nombre de StepWidget déjà créés et stockés dans la QList du modèle, le delegate demandera au modèle de créer de nouveaux StepWidget. Sachant celà, est-ce qu'il ne serait pas aussi pertinent que le delegate possède un pointeur sur le modèle pour appeller directement ses fonctions publiques ?

    Mais c'est là que je regarde en arrière et que je me dis que si ma classe modèle propose ces services dans son interface publique, il ne faut surtout pas que la vue ai un pointeur sur le modèle, ce n'est pas la responsabilité de la vue d'appeller des fonctions publiques du modèle pour le modifier directement, on ne doit donc pas lui en laisser la possibilité ... Voilà vous commencez à voir que je tourne en rond dans ma tête et que j'arrive pas à trouver par quel bout je dois prendre ce problème pour faire une architecture propre, fonctionnelle, ou chacun n'a bien qu'un rôle

    D'un autre côté si mes 3 classes sont parfaitements séparées, j'ai l'impresion de faire une tonne de signaux et slots redondants

    Par exemple pour informer le modèle que le nombre de step à afficher a changé j'aurais :

    Dans ViewModel.cpp, un slot connecté au SPinBox du nombre de step qui émet lui même un signal vers l'extérieur :

    void ViewModel::on_nbStepSpinBox_valueChanged(int arg1)
    {
        Q_ASSERT(arg1 >= 0);
        emit requestNbSteps(arg1);
    }

    Dans le constructeur de la MainWindow j'ai un connect du style :

    connect(m_view, &ViewModel::requestNbSteps, m_delegate, &Delegate::someDelegateSlot);

    Le slot du delegate qui a besoin de connaitre le contenue de la liste de StepWidget du model pour savoir si il doit en créer de nouveaux ou demander à en cacher/afficher et c'est là que je me dis que j'ai besoin que le delegate possède un pointeur vers le modèle sinon on repart sur emit un nouveau signal du delegate juste pour appeller un slot du modèle pour nous renvoyer la liste .... ça fait un enchaiement de 3 ou 4 slots qui ne font rien d'autre qu'emit un signal pour transmettre la requête pour l'information de proche en proche ...

    J'ai conscience que ma question est plutôt vague car j'ai peu de code à présenter et qu'elle est plutôt conceptuelle mais ça m'aiderait énormément si quelqu'un pouvait me mettre sur la bonne voie svp :D 

    Merci d'avance

    -
    Edité par ThibaultVnt 7 septembre 2021 à 14:03:26

    • Partager sur Facebook
    • Partager sur Twitter
      7 septembre 2021 à 19:48:36

      C'est trop vague. A priori, tu n'as pas besoin de créer un nouveau modèle (utiliser le standard item model) ni une vue (utilise une liste view).
      • Partager sur Facebook
      • Partager sur Twitter

      Rejoignez le discord NaN pour discuter programmation.

      Qt architecture Model View Delegate

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      • Editeur
      • Markdown