Projet Qt5 : lecteur de musique

Posté par  . Édité par Nils Ratusznik, baud123, Nÿco, gst, Florent Zara et Davy Defaud. Modéré par baud123. Licence CC By‑SA.
Étiquettes : aucune
44
28
fév.
2013
C et C++
   
Comme vous avez pu le voir dans cette dépêche, le framework C++ Qt5 est maintenant sorti. Cette dépêche revient sur certaines bases de la programmation C++/Qt, ainsi que ses évolutions à travers un cas concret : la création d’un lecteur de musique. logo QT

Sommaire

Un projet Qt est divisé en 3 parties : le code principal du programme, la partie graphique et une couche faisant le lien entre les deux.
En fait, c'est une implémentation du MVC (Modèle, Vue, Contrôleur) plus proche du Modèle/Vue.

Projet avec Qt

Qt est une bibliothèque très importante avec beaucoup de fonctionnalités. En général, on utilise Qt Creator qui est l'environnement de développement dédié, Qt Designer servira pour la partie graphique. Je ne développerai pas cette partie, tout est affaire de QWidget que l'on place, comme avec tout éditeur visuel.
Sachez aussi qu'il est possible de coder via QML (Qt Markup Language) qui est un langage adapté, proche du XML, Javascript, CSS à la sauce moderne -> voir cette dépêche.
Enfin, Qt étant multi-plateforme, le style visuel de chaque widget s'adapte à son environnement et on peut aussi l'adapter grâce à des styles semblables aux CSS.

Le code principal

Le code principal ressemble à du C++, mais étant donné qu'on utilise souvent un nombre important de fonctions Qt, on a plus l'impression de faire un nouveau langage. Après, cela dépend de l'application.

Signaux et slots

Dans Qt, pour communiquer, tout est à base de signaux et slots. Cela permet de faire de la programmation événementielle. L'idée est d'envoyer un signal quand un évènement vient de se passer (ex : une valeur modifiée). Chaque objet qui veut recevoir un signal doit posséder un slot compatible. Ensuite, on fait un connect et le tour est joué. C'est tout simplement une implémentation du pattern observateur/observable.

Déclaration :

//Création d'une classe foo implémentant signaux et slots pour gérer la modification d'une valeur

class Foo: public QObject
{
  Q_OBJECT
public :
  Foo();
  int value() const {return val;}
public slots :
  void setValue(int); //A un corps
signals :
  void valueChanged(int); //N'a pas de corps
private :
  int val;
}

Lancement d'un signal :

void MonQObject::setValue(int v)
{
  if(v!=val){
    val=v;
    emit valueChanged(v); //On émet le changement de valeur
                          //Un autre objet pourra ainsi agir après l’émission
  }
}

Connexion :

Foo a,b;
connect(&a, &Foo::valueChanged, &b, &Foo::setValue);

Plus d'informations et exemples : http://web.njit.edu/all_topics/Prog_Lang_Docs/html/qt/signalsandslots.html (en Qt3) et pour Qt5 : http://qt-project.org/doc/qt-5.0/qtcore/signalsandslots.html

L'interface programme/graphique

Cette partie fait le lien entre le code principal du programme et la partie graphique. Chaque classe hérite en public de QWidget et en privé de la classe graphique correspondante (créée avec le designer) Ui::Maclasse.
Les seuls attributs sont les informations nécessaires à l'affichage. Par exemple : bool isRunning pour mon player sert à afficher l’icône play ou pause selon l'état du player.
On crée ensuite des slots correspondant aux boutons de l'interface graphique pour faire les modifications graphiques nécessaires.
On émet les signaux correspondant à nos slots. Exemple : j'ai un slot setPlayPause, je regarde l'état isRunning, je met à jour l’icône play/pause et j’émets le signal pause.

Les connect entre interface graphique et slots sont faits dans le constructeur.

L'environnement de développement

Qt Creator

Qt creator offre tout ce que l'on peut attendre d'un IDE moderne, il offre des connexions avec des gestionnaires de version, des fonctions de refactorisation, l'intégration d'un débogueur et d'un analyseur de code, un clone de Vim anecdotique mais appréciable, et une gestion de la documentation très intéressante.

Documentation

D'ailleurs, je veux parler très rapidement de la documentation, car c'est un véritable bonheur. Vous n'avez que l’embarras du choix : elle est disponible de manière complète dans Qt Creator dans un onglet séparé, elle s'affiche à droite de l'écran par l'appui de F1 au survol du code, elle est disponible dans une version web sur le site de digia et dans un logiciel dédié : Qt designer. Qt designer est en fait un navigateur web sur la doc que vous possédez en local et comme il a spécialement été adapté pour celle-ci, il offre un confort de recherche accru, tout en proposant toutes les fonctionnalités pratiques de votre navigateur web préféré.

Traduction

Qt et Qt creator ont un outil de traduction pratique à utiliser, il suffit d'entourer les chaînes de caractères traduisibles dans un programme par un appel à la fonction tr() et un fichier de traduction sera généré.

Les apports de Qt5

Comme vu dans la dépêche de sa sortie, Qt5 apporte beaucoup de choses. Dans le cadre d'un lecteur audio, il y a toute une partie qui m'a été très utile : QMultimedia. Le QMedia player se dote maintenant d'une bonne gestion des listes de lecture et d'objets pour manipuler directement des fichiers audio et vidéo. Bien entendu, toutes les fonctions de base sont là : lecture, pause, changement de volume, changement de vitesse, mode de lecture ou autre. On n'est plus obligé de passer par la bibliothèque phonon.

En outre, le confort de c++ 2011 est là donc on peut allègrement employer les lambda tant qu'on possède un compilateur adapté.

Enfin, Qt5 apporte la vérification des signaux et slots à la compilation et des gains de performance.

Mon projet : Mandarine

Cahier des charges

Mandarine est un projet d'école, c'est censé être une copie de Clémentine (lecteur de musique Linux, Mac OS X et Windows).
Comme tout bon lecteur de musique il doit gérer les fonctionnalités suivantes :

  • lecture de fichiers ou flux audio ;
  • gestion de listes de lectures (playlist) ;
  • gestion de bibliothèques ;
  • affichage de jaquettes et d'informations sur les artistes et albums (intégration de Wikipédia).

Détail du projet

Le GUI

L'interface graphique se veut simple, aucunement révolutionnaire. La seule fantaisie est peut être le gestionnaire de bibliothèque qui est un dock qu'on peut détacher dans une fenêtre séparée.

La lecture de flux audio utilise plusieurs classes, voici l'exemple d'une d'elles.

PlayerControls

(gestion des boutons de lecture).

Ceci est typiquement une classe qui sert d'interface programme/code.
On n’interagit qu'avec les boutons, on modifie les icônes et on renvoie les signaux intéressants.

Fonctionnalités :

  • lecture / pause (même bouton, changement dynamique d’icône) ;
  • stop ;
  • morceau suivant et précédent ;
  • possibilité de désactivation des contrôles en lot si besoin ;
  • bouton « vitesse de lecture » : menu contextuel ;
  • bouton « mode de lecture » : menu contextuel (séquentielle, en boucle, aléatoire : case à cocher).

Membres :

  • boolean isplaying = false
  • int speedLevel = SPEED_NORMAL
  • int playMode = SEQUENTIAL { SEQUENTIAL, LOOP, RANDOM }
  • int mode = BEGIN { BEGIN, RUNNING, ENDING }

Signaux :

  • play() / pause() / stop()
  • fastForward(level)
  • next() / previous()
  • playModeChanged(playMode)
  • modeChanged(mode)
  • speedChanged()

Slots :

  • setStatus(bool enabled) //(activer ou désactiver tous les boutons)
  • setMode(mode)
  • setPlayMode(playMode)
  • reset() //setStatus(disable), setMode(SEQUENTIAL), setPlayMode(BEGIN)

playercontrol.h
playercontrol.cpp

Cette partie s'adresse à deux types de personnes : le débutant en programmation et quelqu'un qui n'aurait jamais vraiment fait ce genre de choses, le c++ n'est pas un langage voué à mourir de sitôt, on peut facilement faire des programmes dignes du 21ème siècle.

La suite du projet

En toute logique, tout s’arrête là, aucune mise à jour n'est à prévoir. Ses différents atouts : simplicité, légèreté, modernité vous plairont peut être, j'aiderai quiconque voulant le reprendre pour un faire un vrai petit logiciel sympa.

Aller plus loin

  • # Lien HS

    Posté par  (site web personnel) . Évalué à 3.

    Attention, le premier lien de la dépêche est faux. (mélange avec kernel.org).

  • # Une idée

    Posté par  (site web personnel) . Évalué à 5.

    J'ai testé bon nombre de players / gestionnaires de médiathèques et aucuns, sauf Banshee, propose la création de playlist aléatoire. Une playlist qui peut prendre plusieurs paramètres mais dans mon cas un seul m'intéresse : la taille totale des fichiers qui la compose. Je l'utilise pour remplir mon lecteur mp3 que j'emmène le matin. C'est très pratique quand on aiment de tout et qu'on changent souvent le contenu de son lecteur.

    Born to Kill EndUser !

    • [^] # Re: Une idée

      Posté par  (site web personnel) . Évalué à 1.

      Tu es sur d'avoir tout essaye ?

      création de playlist aléatoire.

      $ mpc listall | shuf
      
      

      Une playlist qui peut prendre plusieurs paramètres mais dans mon cas un seul m'intéresse : la taille totale des fichiers qui la compose

      Un subtil mélange de mpc lsinfo, du, sort et head pour ne choisir que les X premiers devrait pouvoir faire ce qui t'interesse. Ça prend un peu de temps a mettre en place, mais ça te donne un script facilement réutilisable.

      • [^] # Re: Une idée

        Posté par  (site web personnel) . Évalué à 4.

        MPD c'est joli mais…

        • comment tu fais pour en faire une copie sur ton lecteur mp3?
        • est-ce une playlist à part entière ou bien faut relancer ton truc à chaque fois?
        • est-ce que ma fille de 10 ans peut le faire en un clic?
        • [^] # Re: Une idée

          Posté par  (site web personnel) . Évalué à 1.

          Les commandes citées ont justement pour astuce de sortir le résultat sur la sortie standard, en texte brut; c'est le format idéal pour réutiliser ailleurs.

          comment tu fais pour en faire une copie sur ton lecteur mp3?

          Tu rajoutes le chemin de ta bibliothèque avant chaque nom, et tu as des chemins complets que tu peux passer a n'importe quel utilitaire de copie digne de ce nom

          est-ce une playlist à part entière ou bien faut relancer ton truc à chaque fois?

          Chaque lancement te fait une nouvelle playlist, dont tu peux faire ce que tu veux : tu peux l'afficher, la stocker dans un fichier, l'envoyer, …

          est-ce que ma fille de 10 ans peut le faire en un clic?

          Non, mais c'est l'occasion de lui apprendre a faire du shell =]

          Plus sérieusement, j'admets tout a fait que cette solution a base d'outils simples s’avère lourde a mettre en place (en gros, pour avoir quelque chose qui t’intéresse, il faudra passer par un script shell), d'autant plus qu'elle suppose l'utilisation d'un terminal. Mais elle a l'avantage d’être flexible, documentée, et plus propre (même si ce n'est que mon avis). En plus, tu n'as pas besoin de te farcir l'ensemble des commandes a chaque fois : un script shell, un double clic, et n'importe qui peut utiliser.

        • [^] # Re: Une idée

          Posté par  . Évalué à 1.

          mpd étant juste le daemon, il te faut un client pour interagir. Le client en ligne de commande de référence mpc permet de tout programmer si tu aimes le shell, mais pour ta fille de 10 ans tu peux aussi voir si un parmi les dizaines de clients graphiques disponibles ne lui conviendrait pas mieux. http://mpd.wikia.com/wiki/Clients

          • [^] # Re: Une idée

            Posté par  . Évalué à 3.

            Mouais. J'ai beau apprécier MPD pour son côté KISS et sa conception, il n'y a clairement pas de client à la hauteur d'Amarok. La plupart ont vu leur développement s'arrêter alors qu'ils n'ont que les fonctions de base.

            Il y a bien GMPC qui fournit pas mal de fonctionnalités et se personnalise bien, mais je trouve son ergonomie en deça. Qui plus est, il est pour GNOME et il n'y a pas de client potable pour KDE, QMPD étant assez limité et pas bien intégré.

            Sinon il y a MPDDroid qui est super mais faut un appareil sous Android et du WiFi.

            Article Quarante-Deux : Toute personne dépassant un kilomètre de haut doit quitter le Tribunal. -- Le Roi de Cœur

            • [^] # Re: Une idée

              Posté par  . Évalué à 1.

              As-tu essayé Cantata ? C'est un client pour KDE (il peut aussi être en Qt pur, sans dépendances KDE) et son développement est régulier.

              • [^] # Re: Une idée

                Posté par  . Évalué à 2.

                Merci, je ne connaissais pas et en effet il est vraiment pas mal du tout ce petit logiciel. Je viens de m'en faire un petit paquet debian et c'est nickel, ça va tout seul à compiler.

                Article Quarante-Deux : Toute personne dépassant un kilomètre de haut doit quitter le Tribunal. -- Le Roi de Cœur

            • [^] # Re: Une idée

              Posté par  . Évalué à 1.

              Côté Gtk, ario n'est pas mal. Dernier commit un peu vieux par contre, c'est vrai (10 mois).
              En ncurses: ncmpcpp.

              Bon, après, connais pas amarok, mais mes besoins sont comblés avec ce que j'utilise.

              • [^] # Re: Une idée

                Posté par  (site web personnel) . Évalué à 2.

                Ce que j'apprécie avec mpd + mpc + ncmpcpp, c'est la souplesse du machin.
                Je viens d'Amarok, et comme j'utilise de plus en plus la console (avec tmux et yakuake), je voulais quelque chose d'accessible immédiatement au clavier et c'était l'occasion de tester mpd. Je m'inquiétais de ne pas pouvoir retrouver LA feature qui pour moi est indispensable pour un lecteur de musique : les raccourcis clavier globaux (mettre en pause où que je me trouve avec une combinaison de touches), mais avec les raccourcis globaux de KDE + un petit script de pause toggle qui va bien en appelant mpc + l'élégance de ncmpcpp (dont je n'utilise pas encore les tags donc en fait je pourrais parler aussi de ncmpc), je suis comblé.

                • [^] # Re: Une idée

                  Posté par  . Évalué à 3.

                  Je n'ai jamais bien compris pourquoi mpd a autant d’engouement et xmms2 si peu (je n'ai pas l'impression que tant de monde utilise mpd sur le réseau). Le toggle de xmms2 c'est ça :

                  $ nyxmms2 toggle
                  
                  

                  Personnellement je ne cherchais qu'un lecteur de musique en cli (et j'ai bien dis cli pas ncurse) après avoir un peu essayé mpd et l'avoir trouvé un peu compliqué à configurer, nyxmms2 est apparu génial.

                  Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                  • [^] # Re: Une idée

                    Posté par  . Évalué à 2.

                    Un peu comme "mpc toggle" en fait ?

                    • [^] # Re: Une idée

                      Posté par  . Évalué à 2.

                      Peut être mais pourquoi sortir des script comme ça alors ?

                      #!/bin/sh
                      # vim: ft=sh
                      MPC=/usr/bin/mpc
                      if [ "$($MPC status | grep pause | cut -d ' ' -f1)" == "[paused]" ]; then 
                         $MPC play 1>/dev/null
                      else
                         $MPC pause 1>/dev/null
                      fi
                      
                      

                      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: Une idée

              Posté par  . Évalué à 4. Dernière modification le 01 mars 2013 à 17:32.

              Les avantages de mpd pour moi :

              • Il fonctionne sans client graphique, je peux l'utiliser sans X ou quand ça plante (un programme openGL buggué ou des commandes openGL non supportées peuvent faire planter le driver, ce qui oblige à redémarrer X). avec ou sans X, et sans interruption quand je redémarre X pour tester quelque chose.
              • À l'extinction de la machine, il enregistre où il en était dans sa lecture. Au démarrage de la machine, il recommence tout seul à jouer, avant même que X soit lancé.
              • Il recommence à jouer à la même seconde que là où il s'est arrêté. La plupart des lecteurs musicaux ne font que « redémarrer au début de la chanson » ce qui n'est pas adapté à l'écoute de fichiers de plusieurs heures (opéras, intégrale symphonique, etc.)
              • Il est contrôlable par des raccourcis clavier, en associant à une touche de fonction à une ligne de commande. J'utilise le démon actkbd, lit les /dev/input/event du noyau, et ainsi fonctionne avec n'importe quel système de bureau et sous console et avec les mêmes touches. J'ai associé des touches de fonction à : morceau suivant et précédent, avance/recule de 30 s et 5 min et pause (toggle).
              • Il est interrogeable par un système de moniteur, par exemple configurer conky pour afficher le nom du morceau.
              • Il n'occupe aucun espace sur mon écran, ne me distrait pas les yeux alors que j'essaie de me concentrer sur mon travail/moulage, sauf si je décide effectivement de lancer un client graphique.

              Il fonctionne ainsi sans aucune manipulation, ce qui me permet de me concentrer sur ce que je fais et en fait le compagnon de travail idéal dans un open-space bruyant.

      • [^] # Re: Une idée

        Posté par  (site web personnel) . Évalué à 0.

        Non je n'ai pas tout essayé c'est certain. Petit truc que j'ai pas dis, ma médiathèque est sur un mediacenter géré par xbmc donc je ne sais pas si il est accessible par mpc et puis à la limite je m'en fou puisque les fichiers sont accessible via le réseau (cifs). Ce n'est pas les X premiers que je veux, mon lecteur fais 1Go et je veux en mettre pour 998Mo.

        Bon c'est pas irréalisable en script mais si accessoirement je pouvais gérer les tags, les pochettes et puis choisir aussi ce que je veux écouter et transférer ça serait le top… Mais peut être suis-je trop gourmand ? :)

        Comme je suis un gourmand j'en rajoute une couche, mon lecteur est un Shuffle 1ere génération (pas de commentaires merci), je l'ai paramétré pour qu'il soit reconnu comme périphérie de stockage et j'utilise rebuild_db http://shuffle-db.sourceforge.net/ pour générer les fichiers qui vont bien sur le lecteur. L'idée serait de pouvoir lancer un programme après une action défini.

        Born to Kill EndUser !

        • [^] # Re: Une idée

          Posté par  . Évalué à 1.

          Bon c'est pas irréalisable en script mais si accessoirement je pouvais gérer les tags, les pochettes et puis choisir aussi ce que je veux écouter et transférer ça serait le top… Mais peut être suis-je trop gourmand ? :)

          mpd gère ces choses. En tout cas, les clients que j'ai sont capables de traiter ces données, et je ne crois pas qu'ils se fassent leur propre base de données.

          L'idée serait de pouvoir lancer un programme après une action défini.

          echo "alias macommande='macommande && monaction'" > ~/.bash_aliases

  • # Concernant les commentaires (headers)

    Posté par  . Évalué à 5.

    Tu as commenté la classe et les méthodes (en TODO) dans le '.h', il me semble que Qt met ses commentaires plutôt dans le '.cpp' et de manière générale tout ce qui peut y être mis en matière de documentation.

    Ça peut paraitre étrange comme pratique mais ça a l'avantage d'éviter de recompiler tout ce qui dépend d'un header lors du changement d'un commentaire, ce qui peut arriver assez souvent. Pour un gros projet ça peut être une économie de temps non. La documentation générée par Doxygen n'en n'est pas altérée.

    • [^] # Re: Concernant les commentaires (headers)

      Posté par  (site web personnel) . Évalué à 8.

      Mettre la doc dans le .h a l'avantage que les .h sont installé et pas les .cpp.

      Et que l'IDE a plus facile à trouver les .h que les .cpp pour pouvoir afficher la doc dans un tooltip par exemple (ou afficher la doc quand on navigue vers la déclaration du symbole)

  • # Qt5

    Posté par  . Évalué à 4. Dernière modification le 28 février 2013 à 18:01.

    L’un des plus grand apports de Qt 5 est Qt Quick 2.0 (basé sur QML qui, contrairement à ce qui est dit dans la dépêche, n’a rien à voir avec du XML).

    Mettre en avant le fait que Mandarine soit basé sur Qt 5 mais utiliser le module Widget avec toute la lourdeur des anciennes interfaces .ui, les boilerplates de gestion des signaux, et autres joyeusetés de Qt 3 et inférieurs me laisse dubitatif.

    Qt 5 est une plateforme très complète pour le développement d’applications scriptables (via QML) tout en étant très rapide (C++/V8). Ce qui permet de développer des applications graphiques très rapidement (via Qt Quick 2.0), en ne donnant qu’un minimum de code pour les connexions des signaux (encore QML).

    • [^] # Re: Qt5

      Posté par  . Évalué à 6.

      À titre pédagogique, il serait sympa que quelqu'un connaissant Qt Quick 2.0 nous code exactement la même application dans une version actuelle de ce que permet Qt5.

      Merci d'avance au volontaire !

      • [^] # Re: Qt5

        Posté par  . Évalué à 2.

        C'est bien ça le souci, pour le moment, en QML, les Desktop Components ne sont pas intégrés, ils le seront normalement en avril avec Qt 5.1 (sous le nom de Controls). à partir de ce moment il sera très avantageux de faire les GUI en QML (sauf s'il y a des widgets non standards, qu'il faudra donc transformer).

        Autant, j'ai vu des bouts de code pour incorporer une vue QML dans une fenêtre à base de widgets, autant l'inverse ne me dit rien…. donc ça veut dire qu'il faut tout recoder dans le cas d'un widget vraiment customisé.

        Bref, à partir d'avril, ça devrait être jouable, d'ici là, c'est un poil fatiguant (ou alors, faut le code en composants Harmattan / Silica / Plasma / Ubuntu )

    • [^] # Re: Qt5

      Posté par  . Évalué à 4.

      Mine de rien, il y a quand même un nombre important d'optimisations au niveau du MVC qui font la différence. J'avoue ne pas avoir fait de tests poussés.

      Pour le reste, j'ai du développer de cette manière pour ne pas trop m'éloigner du sujet donné (c'est un sujet d'école à la base).
      De plus, même si cette dépêche ne parait que maintenant, cela fait quelques temps que je l'ai développé, j'ai commencé à la beta de Qt5, tout n'était pas parfaitement intégré.

    • [^] # Re: Qt5

      Posté par  (site web personnel) . Évalué à 6.

      En quoi est ce que les interfaces .ui sont lourdes ?
      Tu donne un lien vers le xml, mais il n'est pas sensé être lu ou édité par un humain. Il faut utiliser Qt designer, qui est quand même vachement pratique.

      Et puis il n'y a pas tellement de boiler plate dans la gestion des signaux. Bon, c'est vrai qu'il aurais pu faire ça dans une boucle plutôt de se répéter pour chaque action.

      • [^] # Re: Qt5

        Posté par  (site web personnel) . Évalué à 2.

        Bon, c'est vrai qu'il aurais pu faire ça dans une boucle plutôt de se répéter pour chaque action.

        Comment tu verrais cette boucle ? Parce que là, y'a quand même beaucoup de critères différents dans chaque connect.

        • [^] # Re: Qt5

          Posté par  (site web personnel) . Évalué à 4.

          Quelque chose du genre.

          QPair<QAction *, int> array[] = { {sequential, QMediaPlaylist::Sequential} , 
                                            {loopItem, QMediaPlaylist::CurrentItemInLoop} ,
                                            /* { ..., ... } */   };
          for ( const auto & pair : array) {  
              connect(pair.first, &QAction::toggled, [this,pair] {
                  qDebug() << "PlayerControls -> setPlayMode(" <<  pair.second << ")";
                  setPlayMode(pair.second);
              });
          }
          
          
  • # Signaux / slot

    Posté par  . Évalué à 0.

    Pendant longtemps, je n'ai vu que des descriptions comme faites ici au sujet des signaux et des slots et je trouvais ça débile. Se fader qmake pour une fonctionnalité de base de POO (et qu'on peut très bien retrouver dans des langages non-objet comme le C) ça ne donne pas envie.

    On m'a expliqué assez récemment que le vrai avantage de cette construction c'est que ce qui ailleurs est un simple appels de méthode entre 2 objets est ici une communication inter-thread. Ça c'est un vrai apport qui explique l'utilisation de qmake (et une syntaxe toute pourrie jusqu'à Qt4 qui n'était pas capable de vérifier la validité d'une connexion de manière statique).

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Signaux / slot

      Posté par  (site web personnel) . Évalué à -6.

      Même pour de l'interthread, le machin de qt est has been:

      http://www.boost.org/doc/libs/1_53_0/doc/html/signals2.html

      Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

    • [^] # Re: Signaux / slot

      Posté par  . Évalué à 8. Dernière modification le 01 mars 2013 à 07:04.

      Le principal avantage d’utiliser les signaux et slots de Qt est qu’il s’agit d’un mécanisme très bien intégré dans la plateforme, c’est déjà l’option de facilité quand on utilise Qt. Évidemment il est toujours possible de connecter un signal Qt (genre l’appui sur un bouton) à un slot Boost, mais c’est chiant (et ça rajoute une dépendance).

      Se fader qmake pour une fonctionnalité de base

      QMake est un gestionnaire de builds, qui appelle moc. C’est moc qui est chargé de créer le code C++ à partir des QObjects (pour les signaux, les propriétés, et toutes les extensions dynamiques de Qt au modèle objet de C++). Or moc est très bien intégré à tous les gestionnaires de build actuels, par exemple CMake.

      le vrai avantage […] est ici une communication inter-thread

      C’est thread-safe. Ça a été un des avantages de Qt sur les autres bibliothèques, mais Boost propose quelque chose de similaire maintenant.

      qui n'était pas capable de vérifier la validité d'une connexion de manière statique

      Un des nouveaux avantages de cette syntaxe dans Qt5 est de permettre d’avoir des fermetures anonymes comme slots. Le fait que la validation soit faite de manière dynamique est une propriété fondamentale du modèle QObject de Qt, qui inclu aussi les propriétés dynamiques qu’on peut rajouter aux QObjects. C’est par exemple utile pour scripter Qt, en particulier avec le nouveau QML, mais aussi avec tous les autres langages qui s’interfacent à Qt (Lua, Python, etc). Ça permet de découvrir à la volée les signaux et propriétés (introspection), de les scripter facilement ou de charger les connexions à la volée.

      Ça permet par exemple d’écrire rapidement une connexion entre un signal Qt quelconque, et un callback en QML, directement dans du code C++, sans avoir à re-déclarer le QML dans le C++. La connexion étant évidemment vérifiée dynamiquement par Qt.

      Je sais pas trop où en est Boost, mais en Qt on d’autres petites features comme la possibilité d’ignorer des arguments en passant d’un signal à un slot, la déconnexion automatique en cas de destruction des slots, la connexion automatiques de signaux et slots avec des noms qui vont bien ou la configuration de l’ordonnancement des signaux.

      • [^] # Re: Signaux / slot

        Posté par  (site web personnel) . Évalué à -3.

        inclu aussi les propriétés dynamiques qu’on peut rajouter aux QObjects

        Ca pourrait être fait par des macros au lieu d'un compilateur spécial. D'ailleurs pour les propriétés c'est déjà un peu le cas avec la macro Q_PROPERTY.

        Je sais pas trop où en est Boost, mais en Qt on d’autres petites features comme la possibilité d’ignorer des arguments en passant d’un signal à un slot, la déconnexion automatique en cas de destruction des slots, la connexion automatiques de signaux et slots avec des noms qui vont bien ou la configuration de l’ordonnancement des signaux.

        Boost sait faire!

        Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

        • [^] # Re: Signaux / slot

          Posté par  (site web personnel) . Évalué à 7.

          Boost sait faire!

          Comment est-ce que boost fait une connection inter-thread ? Avec quelle boucle d'événements il s'intègre ?
          Dans Qt, chaque QObject « vit » dans un thread (QObject::thread()) et si le thread est différent, un événement Qt est posté dans la boucle d'événement du thread en question. (Et la boucle d'événement Qt peux facilement être intégrée dans les boucles d'événement d'autres bobliothèques)

          Comment est-ce que boost fait la connection autmatique avec les noms qui vont biens ? Comment font ils sans l'introspection fournie par moc ?
          Ce que Qt fait est que le moc génère du code C++ qui contiens le nom (sous forme de char*) des slots et signaux, et ainsi faire une connection automatique (avec QMetaObject::connectSlotsByName)

          Les signaux de boost peuvent en effet faire beaucoup de chose, mais Qt rends ça plus facile.

          De plus, grâce à l'introspection fournie par moc, il est facile de faire des bindings avec des languages de scripts comme javascript et QML.

          • [^] # Re: Signaux / slot

            Posté par  (site web personnel) . Évalué à 0.

            Tu peux lire la doc pour plus de détails, mais j'ai donné l'exemple de boost pour montrer qu'il était parfaitement possible de gérer les signals/slots sans se taper un précompilateur.

            Idem pour l'introspection, il existe des solutions à base de macros (que même Qt utilise d'ailleurs).

            moc, c'était bien il y a 10 ans, mais aujourd'hui, je trouve que ça ne vaut plus le coup.

            Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

            • [^] # Re: Signaux / slot

              Posté par  (site web personnel) . Évalué à 7.

              J'ai bien vu la doc, mais les réponses à mes questions n'y est pas. Tout simplement parce que la réponse est en fait « Boost sait pas faire »

              Comment fais tu l'introspection sans te farcir plein de boiler plate et de répétitions propices aux erreurs ?
              Biensûr que tout est possible avec des macros et des templates, mais est-ce que on arrive à du code aussi clair que celui de Qt ?

              Un autre aventage des signaux et propriétés de Qt: on peux en rajouter dans les objects sans casser la compatibilité binaire.

              Quand à savoir si moc vaut le coup ? Quel est le coût ? Quel est le problème avec moc ? Il s'intrègre bien dans lessystèmes de build. Le code qu'il génère est relativement simple et ne pose pas de problème avec les outils de debug ou autre.

              Pour rappel, le moc génère un fichier .cpp additionel qui est compilé avec le code. Il ne modifie pas le fichier original (contrairement à ce qui est parfois pensé). Le fichier .h est un fichier C++ standard, annotés à l'aide de macro pour le moc. Cela ne pause aucun problème avec les IDE ou autre outils qui parse le C++ standard.

              • [^] # Re: Signaux / slot

                Posté par  . Évalué à -1.

                Biensûr que tout est possible avec des macros et des templates, mais est-ce que on arrive à du code aussi clair que celui de Qt ?

                Tout dépend des goûts, mais au final, tu obtiens du code C++ standard. Et ça, c'est inestimable..

                Un autre aventage des signaux et propriétés de Qt: on peux en rajouter dans les objects sans casser la compatibilité binaire.

                Rajouter des signaux sans rajouter des slots, ça à un intérêt un peu limité.

                Quel est le problème avec moc ?

                Il ne supporte pas les templates de QObject. Tu peux faire des contournements crades, mais ce sont des contournements crades, et tu peux pas avoir un slot/signal qui dépend ou est conditionné par un paramètre template. Au final, tu à quand même perdu une bonne partie des fonctionnalités de C++, et tu te retrouve avec un langage orienté objet pur aussi chiant que Java.

                Et QObject est une grosse classe dieu qui fait tout, donc si tu a besoin qu'une partie des fonctionnalités (genre la gestion mémoire arriérée) qui ne nécessité pas de compiler du code généré, et bien tu te tappe quand même du code généré et toutes les limitations de moc.

                • [^] # Re: Signaux / slot

                  Posté par  (site web personnel) . Évalué à 4.

                  au final, tu obtiens du code C++ standard

                  Qu'est-ce que les macro de Qt ont de moins standard que les macro de, disons, boost ?

                  Il ne supporte pas les templates de QObject

                  C'est vrai. C'est un petit inconvénient du système actuel. Mais apparemment, pas tellement de développeurs ont besoin de ça.

                  (Dans Qt5 tu peux connecté à un slot parametré par un template.)

                  si tu a besoin qu'une partie des fonctionnalités […] qui ne nécessité pas de compiler du code généré, et bien tu te tappe quand même du code généré et toutes les limitations de moc

                  Non. Tu ne met pas la macro Q_OBJECT et tu n'as pas besoin de code généré.
                  Et tu peux donc avoir des QObject avec template (exemple: QFutureWatcher)

                • [^] # Re: Signaux / slot

                  Posté par  . Évalué à 4.

                  Tout dépend des goûts, mais au final, tu obtiens du code C++ standard. Et ça, c'est inestimable..

                  Mais dépendant d'une certaine version, d'une certaine bibliothèque, avec un code pas forcément lisible.

                  Entre une dépendance à boost ou une dépendance à Qt, la différence est faible. Et si de devais choisir entre boost + autre tookit graphique ou Qt, mon choix ira immédiatement à Qt.

                  Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                  • [^] # Re: Signaux / slot

                    Posté par  . Évalué à 1.

                    Mais dépendant d'une certaine version, d'une certaine bibliothèque, avec un code pas forcément lisible.

                    Une bibliothèque ? ou ça ? boost::signal2 ne sont que des entêtes. La seule dépendance, c'est un compilateur C++ standard … ou pas.

                    Entre une dépendance à boost ou une dépendance à Qt, la différence est faible.

                    Donc en gros, pour toi, dépendre d'entêtes écrites en C++ standard utilisant uniquement la bibliothèque standard, c'est pareil que d'utiliser une bibliothèque externe et un générateur de code ?

                    • [^] # Re: Signaux / slot

                      Posté par  . Évalué à 3. Dernière modification le 01 mars 2013 à 14:57.

                      dans le cas de signal2 ce n'est que les entêtes, pour beaucoup d'autres choses, boost c'est une bibliothèque avec laquelle il faut linker rien que sur le projet où je suis on a

                      -lboost_thread -lboost_filesystem -lboost_regex -lboost_iostreams

                      et je cite le Tuto de boost

                      Linking against the Signals2 library
                      Unlike the original Boost.Signals library, Boost.Signals2 is currently header-only.

                      La mise en gras est de moi, rien n'indique que ça ne changera pas dans le futur. Et en tout cas dans le passé ce n'était pas le cas.

                      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                      • [^] # Re: Signaux / slot

                        Posté par  . Évalué à -1.

                        Certaines (la plupart?) bibliothèques de boost proposent une version header-only: Il suffit juste d'inclure un entête contenant l'implémentation dans un de tes fichiers, et hop, plus besoin de bibliothèque.
                        Après ça fait de la duplication de code, mais faut savoir ce qu'on veut.

                        Et puis bon, si on compare la taille des bibliothèque que tu utilise à QtCore uniquement, la différence est vite vue: boost ne réimplémente pas toute la bibliothèque standard C++03, contrairement à Qt.

                        Et sinon, certaines des bibliothèque de boost peuvent être évitées en utilisant des constructions plus statiques, ou en passant à C++11.

                        • [^] # Re: Signaux / slot

                          Posté par  . Évalué à 4.

                          Bah oui mais rien que QString, QStringList, QVariant, QRegExp suffisent largement à me faire préférer Qt à c++ + boost, même si au final on arrive à faire la même chose avec boost, on a d'un coté un truc simple et bien intégré et de l'autre un machin complexe qui jongle avec une classe string trop simple.

                          Par ailleurs tu continues de ne regarder que c++ + boost, sauf que les projets ne faisant 'que' du mode console, y'en a pas des masses, tu vas souvent avoir un autre tookit pour l'affichage, gtk, IlogViews, Win32… Et bien peu on boost déjà intégré avec eux, et tu te retrouves à pester contre le truc super pratique qui n'existe pas.

                          Tant que je fais de la console, j'ai tendance à me limiter à c++ + boost, dès que je touche le graphique, j'abandonne boost, et je fait avec du c++ + Qt.

                          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                          • [^] # Re: Signaux / slot

                            Posté par  . Évalué à 4.

                            Bah oui mais rien que QString, QStringList, QVariant, QRegExp suffisent largement à me faire préférer Qt à c++ + boost, même si au final on arrive à faire la même chose avec boost, on a d'un coté un truc simple et bien intégré et de l'autre un machin complexe qui jongle avec une classe string trop simple.

                            Ça n'est que ton avis. Moi j'écrirai pas un parseur avec Qt.

                            Par ailleurs tu continues de ne regarder que c++ + boost, sauf que les projets ne faisant 'que' du mode console, y'en a pas des masses, tu vas souvent avoir un autre tookit pour l'affichage, gtk, IlogViews, Win32…

                            Et pourquoi pas Qt ? Quand je l'utilise, je fait tout le modèle + contrôleur en boost, puis la vue en Qt (+ boost pour tout ce que Qt ne fait pas).

                            Même si, je te l'accorde, je fais plus souvent des logiciels sans interface graphique pour des machines sans écrans.

                            • [^] # Re: Signaux / slot

                              Posté par  (site web personnel) . Évalué à 2.

                              Et pourquoi pas Qt ? Quand je l'utilise, je fait tout le modèle + contrôleur en boost, puis la vue en Qt (+ boost pour tout ce que Qt ne fait pas).

                              Itou. Il n'y a que des avantages à mixer les deux!

                              Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                              • [^] # Re: Signaux / slot

                                Posté par  (site web personnel) . Évalué à 6.

                                Sur ce point nous sommes d'accord.

                                Ce avec quoi je ne suis pas d'accord c'est de dénigrer Qt à cause de moc juste pour le principe qu'avoir un générateur de code c'est « pas propre » alors qu'en réalité ça ne pose pas vraiment de problèmes.

                                • [^] # Re: Signaux / slot

                                  Posté par  (site web personnel) . Évalué à 3.

                                  Pointer les défauts d'un produit, ce n'est pas le dénigrer.

                                  Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                                  • [^] # Re: Signaux / slot

                                    Posté par  . Évalué à 3.

                                    Si ça ne pose pas de problèmes, ce n'est pas un défaut.

                                    "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                                    • [^] # Re: Signaux / slot

                                      Posté par  (site web personnel) . Évalué à 1.

                                      Mais ça pose problème: dès que l'on sort de qmake et qt creator, ce qui est très courant sur les projets qui ne sont pas purement qt, il faut le gérer les appels à moc. Rien d'insurmontable, mais on s'en passerait bien!

                                      Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                                      • [^] # Re: Signaux / slot

                                        Posté par  . Évalué à 6.

                                        Cmake gère relativement bien les appels à moc.

                                        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                                    • [^] # Re: Signaux / slot

                                      Posté par  . Évalué à 1.

                                      Mais il y a un problème: Ça ne gère pas les templates. Vous savez, la chose qui sert normalement à générer du code en C++, et accessoirement à faire du polymorphisme.

                                • [^] # Re: Signaux / slot

                                  Posté par  . Évalué à 3.

                                  Ce avec quoi je ne suis pas d'accord c'est de dénigrer Qt à cause de moc juste pour le principe qu'avoir un générateur de code c'est « pas propre » alors qu'en réalité ça ne pose pas vraiment de problèmes.

                                  Je ne dénigre pas Qt, il y a pleins de choses super dedans. Enfin j'imagine parce que le coté Qtifiant de ce framework ne me plaît pas. C'est peut être purement physique, mais moi j'ai envie de coller une petite interface graphique à mes logiciels souvent après coup, pas à écrire tout le logiciel en Qt parce que peut être que je voudrais une fonctionnalité de Qt plus tard.

                                  Et malgrès la panoplie de builder qui existe mon préféré reste make donc l'intégration dans CMake me fait une (très) jolie jambe.

                                  Mais à part ça elle est très bien, c'est juste que moi elle a quelque chose qui me gène.

                                  Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                              • [^] # Re: Signaux / slot

                                Posté par  (site web personnel) . Évalué à 3.

                                faut pas être allergique au mélange QCamelCase et under_score

                                • [^] # Re: Signaux / slot

                                  Posté par  . Évalué à 2.

                                  Ou à sa gestion mémoire. Ou à l'orienté objet pur.

            • [^] # Re: Signaux / slot

              Posté par  (site web personnel) . Évalué à 4.

              Tu peux lire la doc pour plus de détails, mais j'ai donné l'exemple de boost pour montrer qu'il était parfaitement possible de gérer les signals/slots sans se taper un précompilateur.

              Oui, c'est possible. Mais avec des restrictions par rapport à moc qui font que ce n'est pas utilisable (compatibilité toussa).

              Idem pour l'introspection, il existe des solutions à base de macros (que même Qt utilise d'ailleurs).

              Oui, il existe des solutions. Mais qui ne remplacent pas complètement ce que fait moc.

        • [^] # Re: Signaux / slot

          Posté par  . Évalué à 7.

          Boost sait faire!

          Et faire une doc compréhensible par un humains sans devoir y passer des plombes? Parce que si il y a bien une chose qui m'a marqué en utilisant Qt, outre sa classe QString (et consort) très complète, c'est la qualité de sa doc.

          J'aime beaucoup boost, mais il faut bien avouer qu'il lui manque clairement une doc.

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

          • [^] # Re: Signaux / slot

            Posté par  (site web personnel) . Évalué à 0.

            http://www.boost.org/doc/libs/1_53_0/doc/html/signals2.html Ce n'est pas clair?

            Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

            • [^] # Re: Signaux / slot

              Posté par  (site web personnel) . Évalué à 6.

              Oui, c'est très clair : Boost ne sait pas faire tout ce que permet moc.

              • [^] # Re: Signaux / slot

                Posté par  (site web personnel) . Évalué à 2.

                L'inverse est vrai aussi, mais encore une fois le propos n'est pas de jeter moc et de le remplacer par boost.signals, mais juste de montrer qu'il est possible de faire sans génération de code.

                Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                • [^] # Re: Signaux / slot

                  Posté par  (site web personnel) . Évalué à 3.

                  On n'a pas dit que c'était impossible.

                  Seulement les solutions autres que moc passent par un objet « signal ». De ce fait, les signaux ont une existence au niveau de l'ABI. Changer les signaux implique donc de casser la compatibilité binaire. Or, c'est inacceptable pour Qt. Ce n'est pas pour rien que toute la bibliothèque utilise le principe du d-pointer.

                  Une application compilée avec Qt4.0 fonctionne telle quelle avec Qt 4.8 là où une recompilation est nécessaire entre boost 1.41 et 1.42, 1.43 / 1.44 et 1.44 / 1.45 par exemple.
                  À choisir, je préfère largement la politique de Qt qui évite d'avoir 4 versions différentes de la même bibliothèque parce que chaque application utilise une version différente.

                  • [^] # Re: Signaux / slot

                    Posté par  (site web personnel) . Évalué à -2.

                    Le principe du d-pointer avec boost.signals est possible. Un collègue l'avait implémenté :-)

                    Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                    • [^] # Re: Signaux / slot

                      Posté par  (site web personnel) . Évalué à 3.

                      Le problème n'est pas de réussir faire du PIMPL Idiom avec les signaux Boost, mais le fait que les signaux Boost eux-même ne soient pas PIMP Idiom.

                      • [^] # Re: Signaux / slot

                        Posté par  (site web personnel) . Évalué à 2.

                        Justement les signaux étaient le pimpl et tu appelais juste une méthode void connect(templatedesiouxpourwrapperunfunctor) dans la classe hébergeant le pimpl.

                        Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                        • [^] # Re: Signaux / slot

                          Posté par  (site web personnel) . Évalué à 3.

                          Donc en gros tu te refais un wrapper sur les signaux boost que tu compartimentes dans une zone restreinte de ton code ? Ca n'évitera pas le cassage de l'ABI, non ?

                          • [^] # Re: Signaux / slot

                            Posté par  (site web personnel) . Évalué à 3.

                            Aaaah tu parlais de l'ABI de boost, je pensais que tu parlais de l'ABI de ton code…

                            boost.signals2 est "header only", donc l'ABI pour un usage interne, on s'en fiche…

                            Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

            • [^] # Re: Signaux / slot

              Posté par  . Évalué à 8.

              désolé, mais comparé à ça

              http://qt-project.org/doc/qt-5.0/qtcore/signalsandslots.html

              C'est moins clair. Alors oui, il y a des capacité supplémentaire à l'implémentation de boost (notamment au niveau du retour des signaux).

              Il ne faut pas décorner les boeufs avant d'avoir semé le vent

        • [^] # Re: Signaux / slot

          Posté par  (site web personnel) . Évalué à 5.

          Oui, oui, Boost sait faire.

          Sauf que Qt a des exigences supplémentaires comme pouvoir ajouter des signaux à une classe existante sans casser la compatibilité binaire. Et ça, c'est impossible avec boost.

  • # Qt designer ou Qt Assistant ?

    Posté par  . Évalué à 10.

    Tu parles de "Qt designer est en fait un navigateur web sur la doc" pour moi c'est Qt Assistant qui fait ça, Qt Designer sert à créer graphiquement l'IHM.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.