CMake 08: Una finestra About

Finora abbiamo usato CMake per controllare la versione o l’icona da inserire nell’eseguibile. Ora vediamo come fare in modo che i dati impostati in CMake possano essere utilizzati nel codice della nostra applicazione. Ovviamente sto parlando del nome dell’applicazione e della sua versione, ma il meccanismo può essere esteso ad altre informazioni.

Prima di iniziare vi ricordo che trovate il codice su GitHub, e la lista di tutti gli altri episodi alla pagina CMake is the future.

Creare il file version.h

Il meccanismo si basa sul comando configure_file() che abbiamo già usato per il file di risorse WinResources.rc. Iniziamo creando il file

version.h.in

che poi verrà convertito in

version.h

Nel file version.h.in mettiamo una serie di #define e una serie di tag che poi CMake espanderà in stringhe. Ecco il codice:

#ifndef VERSION_H
#define VERSION_H

#define VERSION "@PROJECT_VERSION@"
#define NAME "@PROJECT_NAME@"
#define COPYRIGHT "@LEGAL_COPYRIGHT@"

#endif // VERSION_H

Poi nel progetto CMakeLists.txt metto:

configure_file(version.h.in version.h)

Mentre version.h lo aggiungo nella lista dei file di add_executable():

${CMAKE_CURRENT_BINARY_DIR}/version.h

A questo punto il file version.h compare nell’albero, sotto alla cartella Build Directory, mentre il file version.h.in compare nella cartella CMake Modules.

Una volta eseguito CMake il file diventa version.h e i #define diventano:

#define PROJECT_VERSION "1.2.3.4"
#define PROJECT_NAME "CMakeWidgetProject"
#define LEGAL_COPYRIGHT "(C) 2020 www.GianbattistaGualeni.it"

Da questo momento includendo version.h, in un file cpp posso accedere a tutte le informazioni che voglio leggere da CMakeLists.txt

Finestra di dialogo About

Creiamo ora una nuova finestra di dialogo che chiameremo dlgAbout, selezionando il template “Dialog without Buttons”.

Carino da parte di Qt Creator ricordarci che i file non verranno aggiunti automaticamente a CmakeLists.txt. Speriamo che in Qt 6 il meccanismo venga automatizzato! Che dite? (Forse lo ho già detto…)

Andiamo ad aggiungere ad add_executable() i 3 file seguenti:

  add_executable(CMakeWidgetProject
    ... 
    dlgAbout.cpp
    dlgAbout.h
    dlgAbout.ui
)

A questo punto, in Qt Creator posso aprire dlgAbout.ui ed inserire un oggetto QTextBrowser di nome textBrowser, in modo che riempia tutta la finestra di dialogo. Usare QTextBrowser al posto di QPlainTextEdit mi permette di inserire più velocemente dei link http cliccabili dall’utente.

Poi passo al file dlgAbout.cpp, ed inserisco:

#include "version.h"

Compilare la casella di testo

Nel costruttore della classe creo il testo come stringa HTML, e lo metto in plainTextEdit.

Oltre al nome della applicazione e alla versione, voglio mettere anche dei reference ai siti da cui ho preso le icone. Per non impazzire inserendo codice HTML in codice c++, creo una sorta di tabella con NomeCampo e Attributo, sotto forma di lista di stringhe separate da TAB che poi scompongo e converto in HTML. Ecco il primo pezzo del metodo con la lista di stringhe

dlgAbout::dlgAbout(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::dlgAbout)
{
    ui->setupUi(this);
    QStringList msgList;
    msgList << "Application Name\t" PROJECT_NAME;
    msgList << "Release\t" PROJECT_VERSION;
    msgList << "Copyright\t" LEGAL_COPYRIGHT;
    msgList << "Created with\t" "www.qt.io " QT_VERSION_STR;
    msgList << "Iconset:\t" "www.flaticon.com";
    msgList << "Iconset:\t" "www.flaticon.com/authors/freepik";
    msgList << "Iconset:\t" "www.icons8.it";

Notate che ho messo un riferimento anche a Qt ed ho usato la stringa QT_VERSION_STR per inserire la versione di Qt usata, sottoforma di stringa.

Ora, converto le stringe in HTML, avendo cura di rappresentare in grassetto il nome del campo e di convertire i riferimenti a delle pagine web in link cliccabili.

    QString msg;
    QRegularExpression reWebURL("(www|http:|https:)+[^\\s]+[\\w]");
    QRegularExpressionMatch match;
    for (auto row : msgList) {
        auto split = row.split("\t");
        // URL Expansion
        QString attribute = split.last().trimmed();
        match = reWebURL.match(attribute);
        if(match.hasMatch()) {
            QString urlExpansion =
                QString("<a href=\"https://%1\">%1</a>")
                    .arg(match.captured());
            attribute.replace(match.captured(), urlExpansion);
        }
        msg += QString("<p><b>%1</b>: %2</p>")
                   .arg(split.first()).arg(attribute);
    }

Per verificare se si tratta di un riferimenti web, uso la regular expression:

QRegularExpression reWebURL("(www|http:|https:)+[^\\s]+[\\w]");

Se il match è positivo, converto il testo in un link usando il tag <a href=””></a>

<a href=\"https://%1\">%1</a>

Per finire non mi resta che abilitare il controllo textBrowser ad aprire link esterni e ad impostare il testo HTML del controllo.

    ui->textBrowser->setOpenExternalLinks(true);
    ui->textBrowser->setHtml(msg);

Aprire la finestra About

Nella finestra principale creo un pulsante per aprire la dlgAbout.

Partiamo aggiungendo una nuova icona alla cartella icons: io ho scelto icons8-about.png da Icons8, ma potete usare l’icona che preferite.

L’importante è aggiungere l’icona al file CMakeWidgetProject-res.qrc. Magari è bene compilare il tutto, giusto per essere sicuri che tutti i pezzi siano in posizione.

Ora apriamo mainwindow.ui, inseriamo un nuovo pulsante QPushButton che chiamiamo cmdAbout, impostiamo la sua icona, con una dimensione 32×32 ed inseriamo il testo “About”:

Poi andiamo a scrivere lo slot dell’evento clicked, cliccando con il tasto destro “Go to slot…” – “clicked()”.

Ora siamo in mainwindow.cpp e per prima cosa aggiungiamo il riferimento alla dlgAbout:

#include "dlgAbout.h"

Poi inserisco il codice necessario ad aprire la finestra di dialogo in modo modale:

void MainWindow::on_cmdAbout_clicked()
{
    dlgAbout dlg(this);
    dlg.exec();
}

Risultato in macOS

Ecco il risultato finale per macOS. Provate a cliccare sui link e controllate che funzionino.

Risultato finale in Linux

Ecco come appare la finestra di dialogo in Linux:

Risultato finale in Windows10

Ecco come appare la finestra di dialogo in Windows 10:

Conclusioni

Questo è un esempio veloce. Nella finestra di about ho menzionato anche la versione di Qt che sto usando, sia per correttezza che per dovere verso TheQtCompany.

Inoltre avrete notato come in questa puntata non abbiamo dovuto scrivere codice specifico per ogni sistema operativo, e il risultato è diverso per ogni piattaforma, nello spirito di Qt che cerca di replicare lo stile nativo di ogni sistema operativo.

Credo si noti molto lo stile Dark per macOS, comparato con Linux e Windows.

Tenetevi forte, perchè nelle prossime puntate vedremo come funziona il deployment di una applicazione. Inizieremo creando la cartella in cui copiare il target compilato, poi passeremo macDeployQt e a winDeployQt.

Newsletter QtQb

Se vuoi ricevere i miei post e le mie notizie via mail, iscriviti!

Autore: Gianbattista

Appassionato di tecnologia, sono l'autore di Qt5 Quanto Basta. Per lavoro mi occupo di elaborazione delle immagini per applicazioni industriali, ma nel tempo libero adoro creare applicazioni con Qt (www.qt.io)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *