Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite...

24
Version PDF du document http://tvaira.free.fr/dev/qt-android/qt-android-base-donnees- sqlite.html Thierry Vaira <[email protected] > 2019 (rev. 1.0) L’application à développer devra utiliser la technique dite embedded SQL : les instructions en langage SQL seront incorporées dans le code source d’un programme écrit dans un autre langage (ici le C++ sous Qt pour Android). Lire : Activité bases de données SQLite est un moteur de base de données relationnelle accessible par le langage SQL et intégrée dans chaque appareil Android. Remarques : Si l’application crée une base de données, celle-ci est par défaut enregistrée dans le répertoire : /data/APP_NAME/databases/DATABASE_NAME . Il est possible ensuite de récupérer la base de données créée à partir de l’émulateur adb : $ adb -d shell "run-as com.example.tv.APP_NAME cat /data/com.example.tv.APP_NAME/databases/DATABA SE_NAME" > bd.sqlite On peut ensuite l’ouvrir avec le plugin SQLite Manager de Firefox ou avec l’application sqlitebrowser ou sqliteman sous Linux. Il existe aussi un exemple pour une base de données MySQL . SQLite est une bibliothèque écrite en C qui propose un moteur de base de données relationnelle accessible par le langage SQL. Contrairement aux serveurs de bases de données traditionnels, comme MySQL ou PostgreSQL, sa particularité est de ne pas reproduire le schéma habituel client-serveur mais d’être directement intégrée aux programmes. L’intégralité de la base de données (déclarations, tables, index et données) est stockée dans un fichier indépendant de la plateforme. SQLite est le moteur de base de données le plus distribué au monde, grâce à son utilisation dans de nombreux logiciels grand public comme Firefox, Skype, Google Gears, dans certains produits d’Apple, d’Adobe et de McAfee et dans les bibliothèques standards de nombreux langages comme PHP ou Python. De par son extrême légèreté (moins de 300 Kio), il est également très populaire sur les systèmes embarqués, notamment sur la plupart des smartphones modernes : l’iPhone ainsi que les systèmes d’exploitation mobiles Symbian et Android l’utilisent comme base de données embarquée. Qt pour Android : Base de données SQLite SQLite

Transcript of Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite...

Page 1: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

VersionPDFdudocumenthttp://tvaira.free.fr/dev/qt-android/qt-android-base-donnees-sqlite.htmlThierryVaira<[email protected]>2019(rev.1.0)

L’applicationàdévelopperdevrautiliserlatechniquediteembeddedSQL:lesinstructionsenlangageSQLserontincorporéesdanslecodesourced’unprogrammeécritdansunautrelangage(icileC++sousQtpourAndroid).

Lire:Activitébasesdedonnées

SQLiteestunmoteurdebasededonnéesrelationnelleaccessibleparlelangageSQLetintégréedanschaqueappareilAndroid.

Remarques:

Sil’applicationcréeunebasededonnées,celle-ciestpardéfautenregistréedanslerépertoire:/data/APP_NAME/databases/DATABASE_NAME .

Ilestpossibleensuitederécupérerlabasededonnéescrééeàpartirdel’émulateur adb :

$adb-dshell"run-ascom.example.tv.APP_NAMEcat/data/com.example.tv.APP_NAME/databases/DATABASE_NAME">bd.sqlite

Onpeutensuitel’ouvriraveclepluginSQLiteManagerdeFirefoxouavecl’application sqlitebrowser ousqliteman sousLinux.

IlexisteaussiunexemplepourunebasededonnéesMySQL.

SQLiteestunebibliothèqueécriteenCquiproposeunmoteurdebasededonnéesrelationnelleaccessibleparlelangageSQL.Contrairementauxserveursdebasesdedonnéestraditionnels,commeMySQLouPostgreSQL,saparticularitéestdenepasreproduireleschémahabituelclient-serveurmaisd’êtredirectementintégréeauxprogrammes.L’intégralitédelabasededonnées(déclarations,tables,indexetdonnées)eststockéedansunfichierindépendantdelaplateforme.SQLiteestlemoteurdebasededonnéesleplusdistribuéaumonde,grâceàsonutilisationdansdenombreuxlogicielsgrandpubliccommeFirefox,Skype,GoogleGears,danscertainsproduitsd’Apple,d’AdobeetdeMcAfeeetdanslesbibliothèquesstandardsdenombreuxlangagescommePHPouPython.Deparsonextrêmelégèreté(moinsde300Kio),ilestégalementtrèspopulairesurlessystèmesembarqués,notammentsurlaplupartdessmartphonesmodernes:l’iPhoneainsiquelessystèmesd’exploitationmobilesSymbianetAndroidl’utilisentcommebasededonnéesembarquée.

QtpourAndroid:BasededonnéesSQLite

SQLite

Page 2: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

Qtfournitdenombreusesclassespourlagestiondesbasededonnées.Ilfaudraactiverlemoduledanssonfichierdeprojet .pro pourpouvoiraccéderauxclasses:

...QT+=sql...

Onutiliseraalorslaclasse QSqlDatabase quipermetlaconnexionàunebasededonnées.

Lien:LaclasseQSqlDatabaseQt5(en)

Etensuitelaclasse QSqlQuery pourexécuterdesrequêtesSQL:

Lien:LaclasseQSqlQueryQt5(en)

Onpeutassurerledéploiementdelabasededonnéesliéeàl’applicationdanssonfichierdeprojet .pro :

Android(apk):

...deployment.files+=mabase.sqlitedeployment.path=/assets/dbINSTALLS+=deployment

Desktop(build):

...#copielabasededonnéesdansledossierbuildCONFIG+=file_copiesCOPIES+=bdbd.files=mabase.sqlitebd.path=$$OUT_PWD/bd.base=$$PWD/

Pourl’exemple,onvacréerunebasededonnées mabase.sqlite comprenant2tables:

latable releves quicontiendraladescriptiondesrelevéslatable mesures quicontiendralesmesureshorodatéesdetempératurespourchaquerelevé

APIQt

Déploiement

Exemple

Page 3: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

pragmaforeign_keys=on;

CREATETABLEreleves(idReleveINTEGERPRIMARYKEYAUTOINCREMENTNOTNULL,descriptionVARCHAR(255)NULL);

CREATETABLEmesures(idMesureINTEGERPRIMARYKEYAUTOINCREMENTNOTNULL,idReleveINTEGERNOTNULL,horodatageDATETIME,temperatureDOUBLENULL,CONSTRAINTfk_mesures_1FOREIGNKEY(idReleve)REFERENCESreleves(idReleve)ONDELETECASCADE);

Pourlestests,onvainsérerquelquesmesures:

INSERTINTOreleves(idReleve,description)VALUES(1,'Relevédelaserre1');INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0108:00:00',35.23);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0108:30:00',35.1);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0109:00:00',34.45);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0109:30:00',35.02);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0110:00:00',35.53);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0110:30:00',35.24);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0111:00:00',35.25);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0111:30:00',35.7);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0112:00:00',35.61);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0112:30:00',35.65);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0113:00:00',35.75);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0113:30:00',36.03);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0114:00:00',36.1);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0114:30:00',36.05);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0115:00:00',36.33);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(1,'2017-04-0115:30:00',36.5);

INSERTINTOreleves(idReleve,description)VALUES(2,'Relevédelaserre2');INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0108:00:00',35.1);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0108:30:00',35.15);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0109:00:00',35.25);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0109:30:00',35.05);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0110:00:00',35.35);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0110:30:00',35.24);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0111:00:00',35.65);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0111:30:00',35.7);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0112:00:00',35.71);

Page 4: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0112:30:00',35.75);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0113:00:00',35.65);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0113:30:00',35.93);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0114:00:00',36.1);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0114:30:00',36.15);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0115:00:00',36.4);INSERTINTOmesures(idReleve,horodatage,temperature)VALUES(2,'2017-04-0115:30:00',36.35);

EtquelquesrequêtesSQLquel’onutiliseraensuitedanslecode:

//lalistedesrelevésSELECTdescriptionFROMrelevesORDERBYreleves.descriptionASC

//Les5dernièresmesuresdurelevé1SELECT*FROM(SELECTmesures.horodatage,mesures.temperatureFROMmesuresINNERJOINrelevesONreleves.idReleve=mesures.idReleveWHEREreleves.description='Relevédelaserre1'ORDERBYmesures.horodatageDESCLIMIT5)tmpORDERBYhorodatageASCLIMIT5

//Lamoyennedes5dernièresmesuresdurelevé1SELECTAVG(temperature)FROM(SELECTmesures.horodatage,mesures.temperatureFROMmesuresINNERJOINrelevesONreleves.idReleve=mesures.idReleveWHEREreleves.description='Relevédelaserre1'ORDERBYmesures.horodatageDESCLIMIT5)tmpORDERBYhorodatageASCLIMIT5

OncréeunprojetQtQMLQuick:

ProjetQt

Page 5: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

Aufinal,lefichier .pro seralesuivant:

QT+=quickquickcontrols2sqlCONFIG+=c++11

HEADERS+=\releve.h\mesure.h

SOURCES+=main.cpp\releve.cpp\mesure.cpp

RESOURCES+=qml.qrc\icons/MonApplicationBD/index.theme\$$files(icons/*.png,true)

unix:!macx:{android:{DISTFILES+=\android-sources/AndroidManifest.xmlANDROID_PACKAGE_SOURCE_DIR=$$PWD/android-sources#déploielabasededonnéesavecl'apkdeployment.files+=mabase.sqlitedeployment.path=/assets/dbINSTALLS+=deployment}!android:{#copielabasededonnéesdansledossierbuildCONFIG+=file_copies

Page 6: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

COPIES+=bdbd.files=mabase.sqlitebd.path=$$OUT_PWD/bd.base=$$PWD/}}

Onaajoutéuneclasse Releve quiauralacharged’ouvirlabasededonnées mabase.sqlite ,d’effectuerles3requêtesSQLetdefournirlesrésultatsàl’IHM.

Laclasse Releve héritede QObject afindebénificierdesmécanismesQt:

#ifndefRELEVE_H#defineRELEVE_H

#include<QObject>

classReleve:publicQObject{Q_OBJECT

public:explicitReleve(QObject*parent=nullptr);

private:

signals:

publicslots:};

#endif//RELEVE_H

Oninstancieraunobjet Releve quel’onrendraaccessibleàpartirdel’IHMdécritedans qmain.qml .Celaserafaitdanslefichier main.cpp avec setContextProperty() :

#include<QGuiApplication>#include<QIcon>#include<QQmlApplicationEngine>#include<QQmlContext>

#include"releve.h"

intmain(intargc,char*argv[]){QGuiApplication::setApplicationName("MonApplicationBD");QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplicationapp(argc,argv);

QIcon::setThemeName("MonApplicationBD");

QQmlApplicationEngineengine;engine.rootContext()->setContextProperty("Releve",newReleve());engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if(engine.rootObjects().isEmpty())

InteractionsC++/QML

Page 7: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

return-1;

returnapp.exec();}

Dans qmain.qml ,onaccèderaànotreobjetavecl’identifiant Releve .

L’interactionentrelaclasseC++ Releve etl’IHM main.qml serabaséesur3mécanismes:

lespropriétésquisedéclarentaveclamacro Q_PROPERTY enC++lesappelsdeméthodesquiserontdéclaréesaveclepréfixe Q_INVOKABLE enC++lessignauxquiserontconnectésavecl’élément Connections enQML

Onajoutera4propriétés:

erreurConnexion :pourgérerl’erreurd’ouverturedelabasededonnéeslisteReleves :pourrécupérerlalistedesrelevésdelatable relevesmesures :lesmesuresd’unrelevésouslaformed’unelistede Mesuremoyenne :lamoyennedel’ensembledes mesures

Les3dernièrespropriétésnesontaccessiblesqu’enlectureauxquellesonassocieraunaccesseurpourREAD .

Q_PROPERTY(boolerreurConnexionMEMBERerreurConnexionNOTIFYerreurChanged)Q_PROPERTY(QStringListlisteRelevesREADgetRelevesNOTIFYlisteRelevesChanged)Q_PROPERTY(QVariantmesuresREADgetMesuresNOTIFYmesuresUpdated)Q_PROPERTY(QStringmoyenneREADgetMoyenneNOTIFYmoyenneUpdated)

Onpourraparexempleaccéderàlapropriété moyenne directementenQMLcommececi:

labelMoyenne.text="Moyenne:"+Releve.moyenne+"°C";

CôtéC++,ilfaudradéfinirl’accesseur getMoyenne() quipermettradelire(READ)lapropriétédumêmenom:

QStringReleve::getMoyenne(){returnmoyenne;}

Oncréera3méthodespubliquesappelablesdepuisQML:

lireReleve() et lireMoyenneReleve() quirecevrontenparamètreslenomdurelevéetlenombredesdernièresmesuresdésirées(0signifieratouteslesmesuresdurelevé)executerRequete() quirecevraenparamètreunerequêteSQLdetype INSERT , UPDATE ouDELETE

Q_INVOKABLEboollireReleve(QStringreleve,intnb=0);Q_INVOKABLEvoidlireMoyenneReleve(QStringreleve,intnb=0);Q_INVOKABLEboolexecuterRequete(QStringrequete);

CôtéQML,onpourraapellerunedecesméthodesdelamanièresuivante:

Page 8: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

Button{id:purgerReleveenabled:true;text:"Purgerlerelevé"onClicked:{Releve.executerRequete("DELETEFROMrelevesWHEREreleves.description='"+choixReleve.currentText+"'");//...}}

Onauraaussibesoindessigauxsuivants:

signals:voiderreurChanged();voidlisteRelevesChanged();voidmesuresUpdated();voidmesuresErreur();voidmoyenneUpdated();...

EnQML,ilestpossibledeconnecterunslotàunsignalde target enlepréfixantavec on commececi:

Connections{target:ReleveonMoyenneUpdated:{labelMoyenne.text="Moyenne:"+Releve.moyenne+"°C";labelMoyenne.color="#0000FF"labelMoyenne.visible=true}onMesuresErreur:{labelMoyenne.text="Aucunemesurepourcerelevé!";labelMoyenne.color="#FF0000"labelMoyenne.visible=truelisteMesures.visible=false}}

Onajoutelesmembresprivéssuivants:

private:QSqlDatabasedb;boolerreurConnexion;QStringListreleves;QList<QObject*>mesures;QStringmoyenne;...

Aufinal,ladéclarationdelaclasse Releve estlasuivante:

#ifndefRELEVE_H#defineRELEVE_H

#include<QObject>

Page 9: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

#include<QString>#include<QtSql/QtSql>#include<QSqlDatabase>

#defineNOM_BDQString("mabase.sqlite")

classReleve:publicQObject{Q_OBJECTQ_PROPERTY(boolerreurConnexionMEMBERerreurConnexionNOTIFYerreurChanged)Q_PROPERTY(QStringListlisteRelevesREADgetRelevesNOTIFYlisteRelevesChanged)Q_PROPERTY(QVariantmesuresREADgetMesuresNOTIFYmesuresUpdated)Q_PROPERTY(QStringmoyenneREADgetMoyenneNOTIFYmoyenneUpdated)

public:explicitReleve(QObject*parent=nullptr);virtual~Releve();

Q_INVOKABLEboollireReleve(QStringreleve,intnb=0);Q_INVOKABLEvoidlireMoyenneReleve(QStringreleve,intnb=0);Q_INVOKABLEboolexecuterRequete(QStringrequete);QStringListgetReleves();QVariantgetMesures();QStringgetMoyenne();

private:QSqlDatabasedb;boolerreurConnexion;QStringListreleves;QList<QObject*>mesures;QStringmoyenne;

boolrecuperer(QStringrequete,QStringList&donnees);boolrecuperer(QStringrequete,QVector<QStringList>&donnees);boolrecuperer(QStringrequete,QString&donnee);boolcopier(QFile&sfile,QFile&dfile);boolremplacer(QFile&sfile,QFile&dfile);boolestBDPresente(QStringBD);

signals:voiderreurChanged();voidlisteRelevesChanged();voidmesuresUpdated();voidmesuresErreur();voidmoyenneUpdated();

publicslots:};

#endif//RELEVE_H

Dansleconstructeurdelaclasse Releve ,onassureral’ouverturedelabasededonnéesSQLite.

Onpréciseratoutd’abordaveclaméthodestatique addDatabase() letype QSQLITE .

SousAndroid,ilfaudrapréalablementcopierlabasededonnéesdepuisl’apk(“assets:/db”)àlaracinede

BasededonnéesSQLite

Page 10: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

l’applicationpuisluidonnerlesdroits.

Remarque:sil’applicationAndroidestdéjàinstallée,labasededonnéesneserapas“re-copier”.Sivoussouhaitezréinstallerlabasededonnées,vousdevezsoitdésinstallerl’applicationAndroidsoitappelerlaméthode remplacer() quisupprimerad’abordlefichier mabase.sqlite avantdelecopier.

Ensuite,onfixeralenomdelabasededonnéesavec setDatabaseName() etonl’ouvriraavec open() .

Releve::Releve(QObject*parent):QObject(parent),erreurConnexion(false){db=QSqlDatabase::addDatabase("QSQLITE");

QFilesfile(QString("assets:/db")+QString("/"+NOM_BD));QFiledfile(QString("./"+NOM_BD));

copier(sfile,dfile);//ou://remplacer(sfile,dfile);

if(estBDPresente(QString("./")+NOM_BD)){db.setDatabaseName(QString("./")+NOM_BD);db.open();erreurConnexion=false;QSqlQueryr;r.exec("pragmaforeign_keys=on;");}else{erreurConnexion=true;}

emiterreurChanged();}

boolReleve::copier(QFile&sfile,QFile&dfile){if(sfile.exists()){returnsfile.copy(dfile.fileName());}returnfalse;}

boolReleve::remplacer(QFile&sfile,QFile&dfile){boolretour;

//supprimelefichierdestinationif(sfile.exists()){if(dfile.exists()){retour=dfile.remove();if(!retour){returnfalse;}

Page 11: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

}}

returncopier(sfile,dfile);}

boolReleve::estBDPresente(QStringBD){QFilefichier(BD);

returnfichier.exists();}

Ici,lesignal erreurChanged() estutilepourprévenirl’utilisateursiunproblèmed’ouvertureaeulieu.Danscecas,onafficherauneboîtededialogeavecunmessaged’erreur:

...onErreurChanged:{if(Releve.erreurConnexion){messageErreur.text=qsTr("Problèmed'ouverturedelabasededonnées!")erreurDialog.open()}}

...

Dialog{id:erreurDialogx:(parent.width-width)/2y:(parent.height-height)/2standardButtons:Dialog.Closetitle:"Erreur"Label{id:messageErreurtext:""}}

Page 12: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

PourexécuterdesrequêtesSQL,onaurabesoind’unobjet QSqlQuery .IlfaudradistinguerlesrequêtesSQL SELECT ,quiretournentdesrésultats,desrequêtes INSERT , UPDATE ou DELETE quineproduisentpasderésultatsenretour.

Onpasserapardesméthodesprivées:

executerRequete() quirecevraenparamètreunerequêteSQLdetype INSERT , UPDATE ouDELETErecuperer() quirecevraenparamètreunerequêteSQLdetype SELECT etuntypepourstockerlesdonnéessélectionnéesparlarequête.Onsurchargeralaméthodepourlestypessuivants: QString ,QStringList et QVector<QStringList> .

boolReleve::executerRequete(QStringrequete){QSqlQueryr;

if(db.isOpen()){boolretour=r.exec(requete);returnretour;}returnfalse;}

boolReleve::recuperer(QStringrequete,QStringList&donnees)

Page 13: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

{QSqlQueryr;boolretour;

if(db.isOpen()){retour=r.exec(requete);if(retour){//pourchaqueenregistrementwhile(r.next()){//onstockel'enregistrementdansleQStringListdonnees<<r.value(0).toString();}returntrue;}else{returnfalse;}}elsereturnfalse;}

boolReleve::recuperer(QStringrequete,QVector<QStringList>&donnees){QSqlQueryr;boolretour;QStringListdata;

if(db.isOpen()){retour=r.exec(requete);if(retour){//pourchaqueenregistrementwhile(r.next()){//onrécupèresousformedeQStringlavaleurdetousleschampssélectionnés//etonlesstockedansunelistedeQStringfor(inti=0;i<r.record().count();i++)data<<r.value(i).toString();

//onstockel'enregistrementdansleQVectordonnees.push_back(data);

//oneffacelalistedeQStringpourleprochainenregistrementdata.clear();}returntrue;}else{returnfalse;}}elsereturnfalse;

Page 14: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

}

boolReleve::recuperer(QStringrequete,QString&donnee){QSqlQueryr;boolretour;

if(db.isOpen()){retour=r.exec(requete);if(retour){//onsepositionnesurl'enregistrementr.first();

//onvérifiel'étatdel'enregistrementretournéif(!r.isValid()){returnfalse;}

//onrécupèresousformedeQStringlavaleurduchampif(r.isNull(0)){returnfalse;}donnee=r.value(0).toString();returntrue;}else{returnfalse;}}elsereturnfalse;}

L’utilisationdesméthodes recuperer() seferaàpartirdesméthodespubliquessuivantes:

getReleves() quirécuperalalistedesrelevés

lireReleve() quirecevraenparamètreslenomdurelevéetlenombredesdernièresmesuresdésirées(0signifieratouteslesmesuresdurelevé)etquifabriqueralalistedes Mesure

lireMoyenneReleve() quirecevrontenparamètreslenomdurelevéetlenombredesdernièresmesuresàprendreencomptedanslecalculdelamoyenne(0signifieratouteslesmesuresdurelevé)etquiaffecteral’attribut moyenne

QStringListReleve::getReleves(){if(!erreurConnexion){releves.clear();recuperer("SELECTdescriptionFROMrelevesORDERBYreleves.descriptionASC",releves);}

returnreleves;

Page 15: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

}

boolReleve::lireReleve(QStringreleve,intnb){if(erreurConnexion)returnfalse;

QVector<QStringList>relevesMesures;QStringrequete;

if(nb>0){//lesnbdernièresmesuresrequete="SELECT*FROM(SELECTmesures.horodatage,mesures.temperatureFROMmesuresINNERJOINrelevesONreleves.idReleve=mesures.idReleveWHEREreleves.description='"+releve+"'ORDERBYmesures.horodatageDESCLIMIT"+QString::number(nb)+")tmpORDERBYhorodatageASCLIMIT"+QString::number(nb);}else{//touteslesmesuresdurelevérequete="SELECTmesures.horodatage,mesures.temperatureFROMmesuresINNERJOINrelevesONreleves.idReleve=mesures.idReleveWHEREreleves.description='"+releve+"'ORDERBYmesures.horodatageASC";}

qDeleteAll(mesures);mesures.clear();

if(recuperer(requete,relevesMesures)){for(inti=0;i<relevesMesures.count();i++){Mesure*m=newMesure(QDateTime::fromString(relevesMesures.at(i).at(0),"yyyy-MM-ddHH:mm:ss"),relevesMesures.at(i).at(1).toDouble(),this);mesures.append(m);}

if(mesures.count()>0){emitmesuresUpdated();returntrue;}else{emitmesuresErreur();}}else{qDebug()<<Q_FUNC_INFO;emitmesuresErreur();}returnfalse;}

voidReleve::lireMoyenneReleve(QStringreleve,intnb){if(erreurConnexion)return;

Page 16: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

QStringrequete;

if(nb>0){//lamoyennedesnbdernièresmesuresrequete="SELECTAVG(temperature)FROM(SELECTmesures.horodatage,mesures.temperatureFROMmesuresINNERJOINrelevesONreleves.idReleve=mesures.idReleveWHEREreleves.description='"+releve+"'ORDERBYmesures.horodatageDESCLIMIT"+QString::number(nb)+")tmpORDERBYhorodatageASCLIMIT"+QString::number(nb);}else{//lamoyennedetouteslesmesuresdurelevérequete="SELECTAVG(mesures.temperature)FROMmesuresINNERJOINrelevesONreleves.idReleve=mesures.idReleveWHEREreleves.description='"+releve+"'ORDERBYmesures.horodatageASC";}

if(recuperer(requete,moyenne)){emitmoyenneUpdated();}}

L’accèsaurelevéde Mesure seferaparl’accesseurdelapropriété listeReleves :

QVariantReleve::getMesures(){returnQVariant::fromValue(mesures);}

Oncréeraunenouvelleclasse Mesure pourstockerunemesurequiestcaractériséepar:

unetempérature(un double )etsonhorodatage(un QDateTime quel’onretournerasouslaformed’un QString )

#ifndefMESURE_H#defineMESURE_H

#include<QObject>#include<QDateTime>

classMesure:publicQObject{Q_OBJECTQ_PROPERTY(doubletemperatureREADgetTemperatureNOTIFYmesure)Q_PROPERTY(QStringhorodatageREADgetHorodatageNOTIFYmesure)

public:explicitMesure(QDateTimehorodatage,doubletemperature,QObject*parent=nullptr);

doublegetTemperature()const;QStringgetHorodatage()const;

private:QDateTimehorodatage;

Page 17: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

doubletemperature;

signals:voidmesure();

publicslots:};

#endif//MESURE_H

L’interfaceutilisateurseradécriteenQMLavecQtQuickControls2.

Onutiliseraun AppWindow dans main.qml :

importQtQuick2.11importQtQuick.Window2.3importQtQuick.Controls2.2importQtQuick.Layouts1.3

ApplicationWindow{id:windowtitle:qsTr("MonApplicationBD")width:Screen.desktopAvailableWidthheight:Screen.desktopAvailableHeightpropertyboolerreur:Releve.erreurConnexionvisible:true

onErreurChanged:{if(Releve.erreurConnexion){messageErreur.text=qsTr("Problèmed'ouverturedelabasededonnées!")erreurDialog.open()}}header:ToolBar{RowLayout{spacing:20anchors.fill:parentLabel{id:titretext:qsTr("MonApplicationBD")font.pixelSize:20elide:Label.ElideRighthorizontalAlignment:Qt.AlignHCenterverticalAlignment:Qt.AlignVCenterLayout.fillWidth:true}ToolButton{id:toolButton2icon.name:"menu"onClicked:menu.open()}}}Menu{id:menu

L’IHM

Page 18: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

x:parent.width-widthtransformOrigin:Menu.TopRightMenuItem{id:abouttext:"Àpropos"onTriggered:{aPropos.open()}}}Dialog{id:aProposmodal:truefocus:truetitle:"Àpropos"x:(window.width-width)/2y:window.height/6width:Math.min(window.width,window.height)/3*2contentHeight:message.heightLabel{id:messagewidth:aPropos.availableWidthtext:"Exempled'utilisationd'uneBasededonnéesSQLiteenQtQuickControls2."wrapMode:Label.Wrapfont.pixelSize:12}}Dialog{id:erreurDialogx:(parent.width-width)/2y:(parent.height-height)/2standardButtons:Dialog.Closetitle:"Erreur"Label{id:messageErreurtext:""}}footer:Label{width:parent.widthhorizontalAlignment:Qt.AlignRightpadding:10text:qsTr("©http://tvaira.free.fr")font.pixelSize:14font.italic:true}Releves{id:pageReleve}}

L’affichagedurelevéseferadans Releve.qml .Onlisteralesnomsderelevésdansun ComboBox etonajouteralapossibilitédechoisirlenombrededernièresmesuresquel’onsouhaite.

OncomplèteralaGUIavectroisboutons:

“Annuler”:pourmasquerl’affichagedesrésultats

Page 19: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

“Voirlerelevé”:pourafficherlesmesures“Purgerlerelevé”:poursupprimerunrelevéetsesmesures

Onpositionneralesélémentsavec Column et Row .

importQtQuick2.9importQtQuick.Window2.2importQtQuick.Controls2.2importQtQuick.Layouts1.3

Page{width:parent.widthpadding:10

Connections{target:ReleveonMoyenneUpdated:{labelMoyenne.text="Moyenne:"+Releve.moyenne+"°C";labelMoyenne.color="#0000FF"labelMoyenne.visible=true}onMesuresErreur:{labelMoyenne.text="Aucunemesurepourcerelevé!";labelMoyenne.color="#FF0000"labelMoyenne.visible=truelisteMesures.visible=false}}Column{id:colonnePagewidth:parent.widthspacing:15Row{Label{id:introductionwrapMode:Label.Wraptext:"Relevésdemesuresdetempératuresdanslesserres"}}Row{ComboBox{id:choixRelevewidth:introduction.widthmodel:Releve.listeRelevesenabled:true;}}Row{spacing:20Label{wrapMode:Label.Wraptext:"Nbdernièresmesures:"anchors.verticalCenter:parent.verticalCenter}SpinBox{id:limiteNbMesuresenabled:choixReleve.count>0?true:false;value:5editable:true

Page 20: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

}}Row{spacing:20Button{id:annuleReleveenabled:choixReleve.count>0?true:false;text:"Annuler"onClicked:{listeMesures.visible=falselabelMoyenne.visible=false}}Button{id:voirReleveenabled:choixReleve.count>0?true:false;text:"Voirlerelevé"onClicked:{if(Releve.lireReleve(choixReleve.currentText,limiteNbMesures.value)){listeMesures.visible=trueReleve.lireMoyenneReleve(choixReleve.currentText,limiteNbMesures.value);}}}Button{id:purgerReleveenabled:choixReleve.count>0?true:false;text:"Purgerlerelevé"onClicked:{Releve.executerRequete("DELETEFROMrelevesWHEREreleves.description='"+choixReleve.currentText+"'");listeMesures.visible=falselabelMoyenne.visible=false}}}Row{Mesures{id:listeMesuresvisible:falsewidth:colonnePage.width//onglets.widthheight:Screen.desktopAvailableHeight*0.45color:"#cfcfcf"}}Row{Label{id:labelMoyennevisible:falseanchors.margins:5wrapMode:Label.Wraptext:""}}}}

Page 21: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

L’affichagedesmesuresseferadans Mesures.qml .Onutiliseraun ListView .

ListView permetunevueenlistedesélémentsfournisparun model ,icinotrerelevéaccessibleparlapropriété mesures .L’affichagedesélémentsdelalisteseraprisenchargeparun delegate .Ledéléguéfournitunmodèledéfinissantchaqueélémentinstanciéparla ListView .Letype ItemDelegate utiliséiciestl’élémentdevuestandard.

La ListView étantdéfilabledanslavueenfonctiondunombredemesures,onajouteraunScrollIndicator .

importQtQuick2.9importQtQuick.Window2.2importQtQuick.Controls2.2importQtQuick.Layouts1.3importQtQuick.Controls.Material2.1

Rectangle{ListView{id:listeMesuresanchors.fill:parentspacing:10anchors.margins:5model:Releve.mesuresdelegate:ItemDelegate{width:parent.widthheight:colonne.implicitHeightColumn{id:colonnepadding:5Text{text:model.modelData.horodatage;}Text{text:'<b>Température:'+model.modelData.temperature+'°C</b>';font.italic:true}}}focus:trueclip:trueScrollIndicator.vertical:ScrollIndicator{}}}

Onobtient:

Capturesd’écran

Page 22: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et
Page 23: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

Lien:MonApplicationBD.zip

QtfournitlemoduleQtChartspourdessinerdesgraphiques.

Voir:QtpourAndroid:dessinerdesgraphiques

Codesource

Voiraussi

Page 24: Qt pour Android : Base de données SQLitetvaira.free.fr/.../qt-android-base-donnees-sqlite.pdfSQLite est un moteur de base de données relationnelle accessible par le langage SQL et

Ilestaussipossibled’utiliserunebasededonnéesMySQL.

Voir:QtpourAndroid:BasededonnéesMySQL

http://tvaira.free.fr/