Archives par mot-clé : C

Structure d’un projet Qt

Publié dans C / C++ | Un commentaire

Note: c’est un brouillon 🙂

Ma grande question du moment, comment architecture un projet Qt pour :

  • avoir une bonne structure de dossier,
  • pouvoir gérer plusieurs modules, et choisir ceux à utiliser lors de la compilation,
  • séparer le code source du code des tests unitaires,
  • choisir lors de la compilation de lancer les tests ou non.

Structure

src
   module1/
      src/
      test/
      module1.pro
   module2/
      src/
      test/
      module2.pro
   communication
   data
   service
   util
   ui/
      project.cpp
      project.h
      project.ui
      ui.pro
   main.cpp
   src.pro
test/
   testcase/
      MyGreatTest.cpp
      MyGreatTest.h
   test.pro
   IUnitTestCase.h
   TestRunner.cpp
   TestRunner.h
vendor/
   ...
   vendor.pri
.pro

En général, j’ai plusieurs projets liés entre eux qui partagent des fichiers. Si on passe donc un cran en dessous, j’ai quelque chose du style :

project1/
project2/
vendor/
   ...
   vendor.pri
release/

Quelques informations sur les les .pro et les .pri

Ah, et il est normal qu’un message s’affiche 3 fois dans les logs (lorsqu’on utilise les commandes « message » ou « system »), puisqu’il y a 3 Makefile à générer, donc le fichier .pro est consulté 3 fois.

Inspiration

Etude – Lire un document Word, OpenDocument, PDF avec Qt (ou autre)

Publié dans C / C++ | Laisser un commentaire

Lire un document Office, OpenDocument ou PDF, ou autre format riche  programmatiquement en Qt / C++ / autre… comme il fallait s’y attendre, ce n’est pas de la tarte ! Apparemment, il est relativement faisable d’afficher un document PDF, Office ou LibreOffice directement via un objet Qt, ou une bibliothèque. Mais ici, je cherche à lire le contenu, afin de pouvoir en extraire des morceaux suivant un patron (vous l’aurez deviné, c’est un document de norme, dont j’aimerai extraire la liste des exigences ><).

Voici une liste des ressources que j’ai pu trouver sur le sujet. Je n’ai rien testé pour l’instant.

Continuer la lecture

Architecture de tests en C++ avec Qt

Publié dans C / C++ | Laisser un commentaire

Si vous êtes développeur, je pense que vous avez surement entendu parler des tests unitaires (unit test) et j’espère que vous êtes convaincu de leur utilité ! Tester unitairement un morceau de code, c’est vérifier que celui-ci fait ce que l’on souhaite dans de multiples situations. Ensuite, on peut passer sereinement aux tests d’intégration qui vont tester plusieurs morceaux de codes (ou d’applications) entre eux. On peut encore raffiner avec des tests de performances, tests système, etc, etc… Tout dépend jusqu’où on souhaite aller.

Si on est capable de lancer régulièrement l’exécution de nos tests unitaires, alors on est capable de dire que notre code continue de fonctionner comme voulu malgré les mises à jours ou les refactoring. Cela n’empêche pas les erreurs ni les bugs, car on ne peut pas tester tout notre code unitairement, ou cela peut lamentablement planter lors de l’intégration. Néanmoins, on sait qu’une base solide « fonctionne comme prévu », ce qui facilite grandement la correction d’une erreur.

Pour des myriades de raisons :
tester son code c’est génial !!!

Des études prouvent même qu’une bonne gestion des tests permet au final de gagner du temps. Si vous n’y croyez pas, je vous invite sérieusement à reconsidérer votre opinion.

Ce que j’ai déjà vu dans certains environnements et ce que j’aimerai reproduire dans mon environnement Qt / C++, se résume ainsi :

Continuer la lecture

Corriger une string JSON en Qt

Publié dans Snippet | Laisser un commentaire

La méthode ci-dessous permet d’autoriser une syntaxe moins rigoureuse en prenant soin de modifier les petites erreurs qui ont pu être commises.

/**
 * Clean a string
 * * Remove comments ("//" and "/*")
 * * Add first and last braces ("{" and "}") if missing
 * * Remove unauthorized commas
 *
 * @param data Almost JSON string that will be cleaned to become a valid JSON string
 * @return Valid JSON string (or at least, a more valid one)
 */
QString cleanJsonString(QString data)
{
    // Remove inline comms
    QRegExp pattern = QRegExp("(^|\\[|\\{|,|\\n|\\s)//.*($|\\n)");
    pattern.setMinimal(true); //ungreedy
    data.replace(pattern, "\\1\n");
    data.replace(pattern, "\\1\n"); //2 times, I am not sure why...
    // Remove bloc comms
    pattern = QRegExp("/\\*.*\\*/");
    pattern.setMinimal(true); //ungreedy
    data.replace(pattern, "");
    // Add first and last brace
    if (!data.startsWith("{")) {
        data = "{\n"+data;
    }
    if (!data.endsWith("}")) {
        data += "\n}";
    }
    // Remove commas before } or ]
    pattern = QRegExp(",(\\s*[}\\]])");
    pattern.setMinimal(true); //non-greedy
    data.replace(pattern, "\\1");
    return data;
}

J’ai commis une méthode similaire en PHP : Manipuler du JSON en PHP.

Attendre la fin d’un signal Qt de manière synchrone

Publié dans Snippet | Laisser un commentaire

Ou comment attendre la fin d’une méthode asynchrone.

Snippet

/**
 * Wait synchronously for a Qt signal (+ timeout management)
 * May be useful for test purpose
 * Not recommended for production usage
 */

// -- Configure the waiting
// Signal to wait
QEventLoop loop;
QObject::connect(&anObject, SIGNAL(signalToWait()), &loop, SLOT(quit()));
// Timeout to avoid infite waiting
QTimer timer;
timer.setInterval(10*1000); //10s
timer.setSingleShot(true);
QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));

// -- Do stuff that should trigger the signal
// ...

// -- Start to wait
// What is done after "loop.exec()" is not executed until "loop.quit()" is called
timer.start();
loop.exec();
timer.stop(); // Just in case there is no timeout

// -- Other stuff
// ...

Array en C/C++

Publié dans Snippet | Laisser un commentaire

Static

int anArray[] = { 1, 2 };
// OR
int anArray[2] = { 1, 2 };
// OR
int anArray[2];
anArray[0] = 1;
anArray[1] = 2;

Dynamic (C++)

int anArray = new int[2]
anArray[0] = 1;
anArray[1] = 2;

Et ne pas oublier la suppression :

delete[] anArrat;

Dessiner des graphiques avec Qt

Publié dans C / C++ | Laisser un commentaire

Dessiner des courbes, des graphiques, des histogrammes, c’est relativement faisable avec Qt. Il « suffit » d’utiliser la classe QGraphicsScene. C’est en réalité bien compliqué. Pour permettre la réutilisation (ce qui est souhaitable dans ce cas afin d’éviter les cheveux blancs précoces), il est préférable d’étendre cette classe, et d’y ajouter une méthode « addCurve » auquel il faut fournir tout ce qui est nécessaire pour dessiner une courbe (au sens mathématiques du terme ou non) : une liste de points, une formule… Une autre méthode « addAxes » pourrait permettre de dessiner les deux axes.

Bref, franchement, j’en suis à la quatrième itération d’une classe appelée CurveGraphicScene, et ce n’est pas la panacée. Oh que non ! Quand j’aurai quelque chose d’un peu plus compréhensible, je verrai ce que je peux en dire ici.
En attendant, je note deux bibliothèques Qt : Qwt et QCustomPlot. Elles permettent de faire ce genre de choses, avec normalement moins de peines. Je n’ai pu encore les tester, soit à cause d’une difficulté d’installation, un manque de documentation (et donc la crainte d’y perdre beaucoup de temps), ou à cause des conditions d’utilisation non compatibles avec mes projets du moment.

Continuer la lecture

Qt: No matching function for call to connect

Publié dans C / C++ | Un commentaire

Qt permet de relier facilement entre elle des classes héritant de QObject avec des liens signaux / slots. Voici un petit exemple de connexion.

class OtherQObject : public QObject
{
Q_OBJECT
public:
    OtherQObject();

signal:
    void aSuperSignal();
};
class MyQObject : public QObject
{
Q_OBJECT
public:
    MyQObject();

public slots:
    void myGreatMethod();
};
MyQObject *myClass;
OtherQObject *otherClass;
connect(otherClass, SIGNAL(aSuperSignal()), myClass, SLOT(myGreatMethod());

A de nombreuses reprises, il m’est arrivé d’être confronté à l’erreur suivante (ou similaire) : « No matching function for call to connect ». Plus précisément :

error: no matching function for call to ‘mainWindow::connect(MyQObject *&, const char [38], OtherQObject *&, const char [30])’
note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
note: bool QObject::connect(const QObject*, const char*, const char*, Qt::Connection

J’aimerai lister ici quelques causes possibles de ce type d’erreur. Un article sans fioriture, avec l’information brute de chez brute, mais qui sait, peut-être aurais-je un jour l’envi de peaufiner un petit peu ce bric à brac ?

Continuer la lecture

Les pointeurs intelligents C++ avec Qt

Publié dans C / C++ | Laisser un commentaire

J’entends parler de pointeurs intelligents (ou smart pointers) en C++ depuis pas mal de temps. N’étant pas encore tout à fait à l’aise avec cette notion, je me suis fait une petit séance d’état de l’art. Je compte utiliser des shared pointers tout bientôt, ce qui devrait me permettre d’acquérir d’avantage d’expérience sur le sujet.

Oh le joli pointeur intelligent !

Oh le joli pointeur intelligent !

L’idée qui se cache derrière, c’est de faciliter la gestion mémoire, et d’éviter les fuites mémoires par la même occasion. Je ne sais pas quand l’idée est apparue, mais pour bien comprendre l’état actuel de ce domaine, il faut savoir que les premières implémentations n’ont pas tout de suite été disponibles nativement dans le langage C++. La librairie Boost propose différentes sortes de pointeurs intelligents, tout comme le framework Qt. Il en existe d’autres bien assurément.
Je crois qu’aujourd’hui depuis C++11 (??? à vérifier), trois types de smart pointers sont disponibles nativement.
Continuer la lecture

Injection de dépendances en C++

Publié dans C / C++ | Laisser un commentaire

L’injection de dépendances, que l’on retrouve généralement sous le terme de dependency injection (DI pour les intimes) est un concept de programmation très simple.

Pistolet à injection

Pistolet à injection (de dépendances of course)

L’idée de base c’est de ne pas faire ça :

class Foo {
    private Bar bar;

    public Foo() {
        bar = new Bar();
    }
}

Mais ça :

class Foo {
    private IBar bar;

    public Foo(IBar bar) {
        this->bar = bar;
    }
}

Continuer la lecture