IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Ouverture d'un fichier .h et actualisation d'un QLineEdit


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 11
    Par défaut Ouverture d'un fichier .h et actualisation d'un QLineEdit
    Bonsoir à tous,

    Dans le cadre d'un projet, j'aimerais ouvrir un fichier .h, récupérer un mot/caractère via une expression régulière et si c'est le cas actualiser le QLineEdit correspondant par le mot récupéré.

    Exemple :

    Si dans mon fichier j'ai une ligne : " Salut je m'appelle Toto"
    Je veux ouvrir mon fichier, récupérer le mot : Toto et afficher dans la zone de saisie de mon interface (qui s'intitule "Nom :" ) Toto.

    Je suis débutant en C++, j'ai tenté plusieurs choses voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    void FenPrincipale::ouvrirFichier()
    {
        QString fichier = QFileDialog::getOpenFileName(this,"Ouvrir",QString(),".../test(*.txt)");
     
        bool valid  = QFile::exists(".../test.txt");
        QString code;
     
        //if(valid == true)
        //{
            QString fileName = "fichier.txt";
            QFile fichier1(fileName);
            fichier1.open(QIODevice::ReadOnly | QIODevice::Text);
            QTextStream flux(&fichier);
     
            QString ligne;
            while(!flux.atEnd())
            {
                ligne = flux.readLine(); //traitement de la ligne
                QRegularExpressionMatch *match=new QRegularExpressionMatch;
                QRegularExpression re("class[ \t]+(?<name>\\w+)([ \t]*:[ \t]*public[ \t]+(?<nameParent>\\w+))?");
                QMessageBox::information(this,"",fichier);
                if(ligne.contains(re, match))
                {
                    QStringList stringList = ligne.split(" ");
                    nom->setText(stringList[1]);
                    //nom->insert(stringList[1]);
                    this->update();
                    printf(" Ca a marché !");
     
                    //QString className = match.captured("name");
                    //QString classeMere = match->captured("nameParent");
                }
     
                this->update();
            }
    Merci d'avance et bonne soirée à tous.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 150
    Billets dans le blog
    150
    Par défaut
    Bonjour,

    Si vous avez la main sur le projet dans lequel est inclut le fichier .h, je vous propose de faire autrement en extrayant le nom de ce fichier, en le mettant en tant que define dans un fichier .h dédié.
    Comme ça, la lecture du fichier sera beaucoup plus simple.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 11
    Par défaut
    Bonsoir LittleWhite,

    Je vais t'expliquer ce que je cherche à faire, ca sera plus simple pour tout le monde

    J'ai une interface de ce type :

    Nom : Capture.PNG
Affichages : 399
Taille : 11,0 Ko

    Le but de cette interface est de générer un texte dans une nouvelle fenêtre en fonction des choix et des données entrées.

    Exemple :
    Nom : Capture1.PNG
Affichages : 354
Taille : 29,6 Ko

    Pour l'instant l'interface fonctionne bien.
    J'arrive à sauvegarder le texte de la nouvelle fenêtre dans un fichier .h sur mon ordinateur (avec un bouton sauvegarder que j'ai créée).

    Mon problème c'est que maintenant je souhaite :
    - Réaliser l'étape inverse, c'est à dire qu'en partant d'un fichier texte lambda je souhaite qu'avec des expressions régulières le programme soit capable de remplir les zones de saisies de mon interface.

    Exemple :
    Nom : exemple.png
Affichages : 408
Taille : 139,3 Ko

    Voilà un exemple de ce que je souhaite obtenir en partant du fichier .h pour aboutir à un remplissage automatique de l'interface.

    Je souhaite ouvrir (à l'aide du bouton "ouvrir" ) le fichier .h fruit_salad et utiliser un bouton "remplissage automatique" (par exemple) afin que les champs de saisies et les cases à cocher de mon interface s'actualisent en fonction du contenu du fichier chargé.

    Sais tu comment je pourrais m'y prendre ? J'ai vu qu'il fallait utiliser les expressions régulières mais je suis totalement perdu au niveau du fonctionnement !

    Bonne soirée à toi et à tous les lecteurs !

    matmaat.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Pour commencer, si tu veux pouvoir ouvrir des fichiers d'extension .h, alors il te faut donner le bon filtre à la fonction statique getOpenFileName() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QString fichier = QFileDialog::getOpenFileName(this, "Ouvrir", QString(), "Headers (*.h)");
                                                                                        ~~~
    À noter que l'utilisateur peut choisir d'annuler cette ouverture, auquel cas le QString retourné sera nul. Il est donc judicieux de tester ce cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (fichier.isNull()) {
        return; // On quitte de suite la fonction sans rien faire d'autre
    }
    Ensuite, (c'est peut-être lié à un test que tu as fait, mais je préfère m'en assurer) QString fileName = "fichier.txt"; n'a aucun lien avec le fichier sélectionné ci-dessus. Il s'agit littéralement d'un fichier très précisément nommé fichier.txt que tu vas tenter d'ouvrir à la place de celui sélectionné à l'aide de la boîte de dialogue.

    QTextStream flux(&fichier); : (possiblement une confusion due aux deux variables fichier et fichier1 aux noms proches mais désignant deux choses distinctes) là encore ça ne va pas faire ce que tu attends. Au lieu de travailler sur le contenu du fichier sélectionné, tu vas simplement travailler sur son chemin.

    while(!flux.atEnd()) fait partie des erreurs classiques : il ne faut pas tester si on est ou non arrivé à la fin, mais si la lecture s'est bien passée. La version Qt 5.5 a apporté la fonction readLineInto() qui permet d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (flux.readLineInto(&ligne)) {
    QRegularExpressionMatch *match=new QRegularExpressionMatch; : allocation inutile et qui mène à une fuite mémoire qui plus est (à chaque itération, tu ne le deletes jamais). Contente-toi de créer une variable locale et de passer son adresse.

    Enfin, tu crées des groupes de capture nommés dans ton expression régulière, je vois cette partie censée les récupérer commentée et tu pars sur un split… il est dommage de ne pas t'en servir.

    Le tout corrigé nous donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    void FenPrincipale::ouvrirFichier()
    {
        const QString chemin = QFileDialog::getOpenFileName(this, "Ouvrir", QString(), "Headers (*.h)");
        if (chemin.isNull()) { // Si l'utilisateur a annulé l'ouverture
            return;
        }
     
        QFile fichier(chemin); // On passe directement le chemin retourné par getOpenFileName()
        fichier.open(QIODevice::ReadOnly | QIODevice::Text);
        QTextStream flux(&fichier); // C'est le QFile qu'il faut passer, pas le chemin
     
        // C'est plutôt couteux à créer, évitons de le recréer inutilement à chaque itération
        const QRegularExpression re("class[ \t]+(?<name>\\w+)([ \t]*:[ \t]*public[ \t]+(?<nameParent>\\w+))?");
     
        QString ligne;
        while (flux.readLineInto(&ligne)) {
            QRegularExpressionMatch match;
            if(ligne.contains(re, &match)) {
                const QString className = match.captured("name");
                const QString classeMere = match.captured("nameParent");
     
                nom->setText(className);
                if (!classeMere.isNull()) {
                    // Présence d'héritage d'une classe mère
                    // je te laisse le mettre dans le bon champ
                }
     
                this->update();
                return; // Si tu n'as rien d'autre à récupérer, inutile de continuer le parcours
            }
        }
    }

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 11
    Par défaut
    Bonjour Winjerome !

    Merci pour ta réponse, ca m'a grandement aidé et j'ai pu nettement améliorer mon code !
    J'ai un petit problème qui persiste dans mon code, j'aimerais parcourir mon fichier texte ligne par ligne (comme tu m'as aidé à le faire) et en plus de ca tester plusieurs conditions.

    Exemple :
    Lorsque je parcours mon fichier texte si certaines expression sont identifiées mon interface s'actualise par exemple, si un mot est présent après le mot class le mot en question apparaitra dans la zone de saisie Nom : de mon interface, etc...

    Le problème c'est que mon code s'arrete apès avoir lu la première ligne de mon fichier texte et donc, il ne vérifie qu'une seule condition... Je pense qu'il ne nécessite que quelques ajustements mais je suis un peu perdu !
    Je mets mon code ci-dessous pour plus de clarté !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    void FenPrincipale::ouvrirFichier()
    {
        const QString chemin = QFileDialog::getOpenFileName(this, "Ouvrir", QString(), "Headers (*.h)");
        if (chemin.isNull()) { // Si l'utilisateur a annulé l'ouverture
            return;
        }
     
        QFile fichier(chemin); // On passe directement le chemin retourné par getOpenFileName()
        fichier.open(QIODevice::ReadOnly | QIODevice::Text);
        QTextStream flux(&fichier); // C'est le QFile qu'il faut passer, pas le chemin
     
        // C'est plutôt couteux à créer, évitons de le recréer inutilement à chaque itération
        const QRegularExpression re("class[ \t]+(?<name>\\w+)([ \t]*:[ \t]*public[ \t]+(?<nameParent>\\w+))?");
        const QRegularExpression header("#ifndef");
        const QRegularExpression defaultconstructor("<name>()");
        const QRegularExpression defaultdestructor("~<name>()");
        QString ligne;
        while (!flux.atEnd()) //flux.readLineInto(&ligne)
        {
            QRegularExpressionMatch match;
            ligne = flux.readLine();
            if(ligne.contains(re, &match))
            {
                const QString className = match.captured("name");
                const QString classMere = match.captured("nameParent");
     
                //if (!classMere.isNull()) {
                    // Présence d'héritage d'une classe mère
                    // je te laisse le mettre dans le bon champ
                //}
     
                this->update();
                nom->setText(className);
                classeMere->setText(classMere);
                return; // Si tu n'as rien d'autre à récupérer, inutile de continuer le parcours
            }
     
            else if(ligne.contains(header, &match))
            {
                this->update();
                protections->setChecked(1);
                return; // Si tu n'as rien d'autre à récupérer, inutile de continuer le parcours
            }
     
            else if(ligne.contains(defaultconstructor, &match))
            {
                this->update();
                genererConstructeur->setChecked(1);
                return; // Si tu n'as rien d'autre à récupérer, inutile de continuer le parcours
            }
     
            else if(ligne.contains(defaultdestructor, &match))
            {
                this->update();
                genererDestructeur->setChecked(1);
                return; // Si tu n'as rien d'autre à récupérer, inutile de continuer le parcours
            }
        }
    Merci d'avance pour votre aide à tous et bonnes fêtes à tous !

    Matmaat.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Tu n'as pas dû bien lire le commentaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return; // Si tu n'as rien d'autre à récupérer, inutile de continuer le parcours
    Là, tu as bien autre chose à récupérer (tu as plusieurs conditions) alors il ne faut justement pas le mettre. Car son effet est justement de quitter directement la fonction sans continuer la lecture et la vérification des lignes suivantes.

    Plutôt que d'exécuter this->update(); sur chaque condition, tu peux te contenter de l'exécuter une seule fois après la boucle.

    const QRegularExpression header("#ifndef"); : ici un simple QString suffit.

    Par contre tes deux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        const QRegularExpression defaultconstructor("<name>()");
        const QRegularExpression defaultdestructor("~<name>()");
    ne vont pas fonctionner. Avec, tu vas littéralement rechercher <name> et ~<name>. Et note qu'il te faut échapper les () en \(\). (Après je pourrais t'embêter en te disant qu'un constructeur par défaut peut aussi avoir des paramètres avec des valeurs par défaut. Par ex. QWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())).

    L'expression régulière utilisée jusque là, c'est précisément (?<nomDonnéAuGroupe>expression) qui va servir à trouver l'expression et la récupérer par le biais du nom donné. Mais là le <name> ne va pas se transformer tout seul en nom de la classe className trouvée. Il va falloir le faire toi-même au moment où tu le trouves.
    Dernière modification par Invité ; 25/12/2020 à 19h10.

Discussions similaires

  1. Ouverture d'un fichier excel predefini
    Par nberthonneau dans le forum Access
    Réponses: 10
    Dernier message: 13/06/2007, 22h14
  2. [Système] ouverture d'un fichier pdf
    Par joneil dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 17/05/2005, 10h36
  3. Réponses: 2
    Dernier message: 06/04/2005, 12h01
  4. Réponses: 5
    Dernier message: 27/07/2004, 17h04
  5. Réponses: 2
    Dernier message: 22/07/2002, 12h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo