Tag Archives: dev

L5R présentation

Retours d’expérience d’une présentation QML

Pour préparer ma conférence à Pas Sage En Seine [FR], j’ai décidé de faire une présentation QML.
Cela offre un bien meilleur contrôle, bien plus de possibilité graphique (animations, intégration de code, 3D…) et de même de l’interactivité.
Bien sûr, une présentation QML demande plus de temps à faire. Le but de l’article est ici d’expliquer les astuces que j’ai mises en place. Espérant gagner du temps la prochaine fois.

Le contenu de la présentation QML:

Comme vous pouvez le voir, la présentation est une application C++ qui affiche du QML. Cette méthode permet de faciliter le contrôle de la partie QML. Je m’en sers pour enregistrer des captures d’écran de la présentation afin d’en faire un PDF. C’est le meilleur pour distribuer la présentation ou dans le cas ou pour éviter l’effet démo.
Tout en haut, il y a les classes C++, les fichiers de management du projet et le fichier main.qml. Dans le répertoire «pages», vous y trouverez les différentes slides de la présentation. Dans rsrc, il y a l’ensemble des images nécessaire à la présentation.

├── cpphighlighter.cpp
├── cpphighlighter.h 
├── deployment.pri 
├── LICENSE 
├── main.cpp 
├── main.qml 
├── pages 
│ ├── 01_intro.qml 
│ ├── 02_presentation.qml 
│ ├── 03_jdr_et_rolisteam.qml 
│ ├── 043_Exemple_code_1.qml 
│ ├── 04_jdr_avantages_pb.qml 
│ ├── 05_avantage_jdr_virtuel.qml 
│ ├── 06_fonctionnalites_rolisteam.qml 
│ ├── 07_rolisteam_debut.qml 
│ ├── 08_Rolistik_a_Rolisteam.qml 
│ ├── 10_frise_chronologique.qml 
│ ├── 11_son_usage.qml 
│ ├── 12_son_fonctionnement.qml 
│ ├── 13_dice_parser.qml 
│ ├── 14_themes_audio_3_pistes.qml 
│ ├── 15_nouveaute_1_8.qml 
│ ├── 16_projet_avenir.qml 
│ ├── 17_reussites.qml 
│ ├── 18_les_lecons.qml 
│ ├── 19_objectif_rolisteam_libre.qml 
│ ├── 20_FAQ.qml 
├── pasSageEnSeine.pro 
├── pasSageEnSeine.pro.user 
├── qmlcontroler.cpp 
├── qmlcontroler.h 
├── qmlcontroler.ui 
├── qml.qrc 
├── README.md 
├── rsrc 
│ ├── all.png 
│ ├── cc.png 
│ └── chat.png

L’application C++

Il peut être utile de connaître l’état de la présentation QML, et de pouvoir lire des notes sur chaque volet. Pour faire cela, j’ai écris une petite application C++.

le fichier main.cpp

Le premier objectif de l’application est d’afficher la présentation QML. Il faut donc charger le QML et établir des moyens de communication entre le monde QML et le C++. Comme vous pouvez le voir, je passe en paramètre la taille de la présentation en paramètre du QML. Ce dernier élément n’est pas obligatoire car par défaut j’utilise la taille de l’écran comme référence.

#include <QApplication>
#include <QQmlApplicationEngine>
#include "qmlcontroler.h"
#include <QQmlContext>
#include <QQuickTextDocument>

#include "cpphighlighter.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("ScreenW",1280);
    engine.rootContext()->setContextProperty("ScreenH",720);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QmlControler ctr;
    ctr.setEngine(&engine);

    return app.exec();
}
main.cpp

Dans ce projet, la classe QmlControler est l’objet (fenêtre) C++ qui affiche l’aperçu de la présentation et les commentaires/notes.

Regardons en détails cet élément:

La fenêtre d’aperçu

C’est une simple fenêtre. Elle est découpée en deux parties.  Celle de gauche affiche dans un QLabel l’aperçu de la présentation QML. La partie de droite affiche les notes et commentaires sur la page courante dans un QTextArea.

void QmlControler::currentPageHasChanged(int i)
{
    m_currentScreen = i;
    QImage img = m_window->grabWindow();

    if(img.isNull())
        return;

    static int count = 0;


    img.save(tr("screens/%1_screen.png").arg(++count,3,10,QChar('0')),"png");
    qDebug() << "screen shot save" << count;

    m_ratioImage = (double)img.size().width()/img.size().height();
    m_ratioImageBis = (double)img.size().height()/img.size().width();

    m_label->setPixmap(QPixmap::fromImage(img));

    if((i+1>=0)&&(i+1<m_commentData.size()))
    {
        ui->textEdit->setHtml(m_commentData.at(i+1));
    }
    resizeLabel();
}
Current slide has changed

Quand la page courante change, la fenêtre C++ est informé par l’appel du slot: currentPageHasChanged alors l’application récupère une capture de la vue QML, l’affiche à l’écran (dans la partie gauche), affiche les notes à propos de la page courante et peut sauvegarder la capture dans un fichier.

Sauvegarder les captures dans des fichiers vous permet de créer un fichier PDF de votre présentation. Il s’agit là d’une solution de secours en cas de problème avec le matériel de la présentation ou une facilité pour distribuer votre présentation.

La commande qui va bien (sous linux) :

$ convert *.png mypresentation.pdf

 

L’application QML

Le système de chargement (Loader)

Par souci de clarté, je préfère avoir un fichier par page. Cela évite l’écueil d’un fichier QML long et complexe. L’application charge les pages en accord avec le modele de données principal dans le même ordre.  Pour faire cela, j’ai utilisé un ListModel. Une page est définie par un titre, un nom de fichier, un temps (non utilisé), et le nom de la page suivante.
Le fichier main.qml  affiche toutes les pages comme un «delegate» d’un pathview.  Toutes les pages sont chargés depuis le fichier de ressources de Qt (inclue dans le binaire grâce au système de ressources de Qt).

ListModel {
            id: panelModel
            ListElement {
                name: "Intro"
                path: "01_intro.qml"
                time: 1
                next: "Présentation de Rolisteam"
            }
First item of the model.

La donnée vraiment utile pour le chargement est bien sûr le nom du fichier.
Les autres sont là pour aider la rédaction ou la présentation.

Le loader fait son travail, voici les lignes importantes:

    PathView {
        id: view
        anchors.fill: parent
        model: panelModel
        highlightRangeMode:PathView.StrictlyEnforceRange
        snapMode: PathView.SnapOneItem
        delegate:  Loader {
             source: "pages/"+path
        }
Path View

Le temps était destiné à afficher un compte à rebours pour chaque slide mais je n’ai pas eu le temps de l’implémenter.

Il est important de mettre dans le main.qml tous les éléments que vous souhaitez avoir sur toutes les pages: le sommaire, l’indication de la page courante sur le total de pages, etc.

Ajouter un sommaire

Pour réaliser un sommaire, j’ai ajouté un ListView avec le modele suivant:

    ListView {
        id: listView1
        x: ScreenW*0.02
        y: ScreenH*0.3
        width: ScreenW/2
        height: ScreenH*0.2
        delegate: Item {
            width: ScreenW/2
            height: listView1.height/listView1.count
                Text {
                    color: view.currentIndex>=index ? "black" : "gray"
                    text: name
                    font.pointSize: ScreenH/48
                    anchors.verticalCenter: parent.verticalCenter
                    font.bold: true

                }
        }
        visible: view.currentIndex>0 ? true : false

        model: ListModel {
            ListElement {
                name: "Concepts"
                index:1
            }
            ListElement {
                name: "Chroniques"
                index:6
            }
            ListElement {
                name: "Logiciel"//système de build, code spécifique par OS.
                index:9
            }
            ListElement {
                name: "Bilan"
                index:15
            }
        }
    }
Table of contents in QML

Le champs index du modèle permet de connaître la page qui démarre cette section du sommaire.

Page suivante

Quand il y a beaucoup de pages il peut être intéressant de connaître la prochaine page afin de faire une petite transition vers elle. Dans mon cas, j’affiche dans le coin haut-droit le titre de la prochaine page. Ce fut assez utile pour les répétitions, je n’en ai presque pas eu besoin pendant la conférence.

    Text {
        anchors.top: parent.top
        anchors.right: parent.right
        text: panelModel.get(view.currentIndex).next+">"
    }
Next slide

L’autre possibilité est d’utiliser les notes dans la fenêtre C++.

Créer une Page de présentation QML

Chaque page est indépendante, elles peuvent être totalement différentes cependant pour des raisons de simplicité, elle utilise une conception identique. Dans mon cas, elles sont constituées d’une ListView avec un modèle. Chaque élément du modèle est un titre de section à évoquer pendant la présentation.

Les éléments ont un index. Cet index est contrôlé par le clavier (flèche bas pour augmenter l’index, haut pour réduire l’index).  Grâce à cet index, il est possible de cacher la liste et d’afficher une image, un schéma ou une vidéo.

Par exemple, dans ma présentation la fonctionnalité «Alias de dés» a pour index 10. Quand la index de la page devient 10, l’élément «Alias de dés» apparaît avec une petite animation. Puis l’index passe à 11, j’affiche une image illustrant la fonctionnalité des alias de dés. A 12, l’image disparaît et le texte revient.

Position et taille

Pour s’assurer de la lisibilité des éléments, je réalise l’ensemble des calculs en rapport à la taille de l’écran. Le positionnement est assuré par des ancres (anchors en qml).

    Image {
        id: image1
        anchors.left: parent.left
        anchors.top: parent.top
        anchors.leftMargin: ScreenW*0.04
        fillMode: Image.PreserveAspectFit
        source: "qrc:/rsrc/Rolisteam.svg"
        width: ScreenW*0.2
    }
Display the logo at the right position and size.

Autre piste

Il existe un module qui fournit des éléments QML pour faciliter la réalisation d’une présentation. Je ne l’ai pas utilisé mais il y a des choses intéressantes.

Module QML

Obtenir le code de mes présentations

Je vous invite à cloner ce code : https://github.com/obiwankennedy/pses

Autre exemple avec une image: https://github.com/obiwankennedy/l5rSummary

L5R présentation QML

Exemple de présentation QML