QSql, QSqlDatabase includes do not exist
-
Did you already saw the Building a QML application chapter in Qt's documentation ?
-
Yes, I've seen that many times as well as a lot of others such as the CMake and QML modules blogs plus lots of research. While that article is a good start it assumes everything is in one directory. I could have directories and one CMakeLists.txt file in the project root and just add modules and sources as somedir/something.cpp, etc without any other CMakeLists.txt and in fact that's what I did originally to get started. However, I wanted to break things into logical groupings using directories which is what Qt seems to recommend so I moved things to appropriate directories.
I am not sure what changed but I added the find and target link to the fldbase CMakeLists.txt and left it in the project root CMakeLists.txt and it now works. The QSql includes are recognized in my fldabase.h. So it appears I need them in the project CMakeLists.txt as well as any other CMakeLists.txt for modules that need them.
-
It depends whether the code used in these modules exposes the Qt SQL module.
If you have included QtSql in your class header, then all the applications/librairies that will use it must know the QtSQL module. Most of the time there's no need to include anything from the QtSql module in your own class headers.
-
I guess I'm not sure what you mean. Initially I added it in my class header #include <QtSql> but it said it couldn't find the file so then I remembered I had to tell CMakeList.txt to find the package so I did that in my top project CMakeList.txt but that still told me the fldbase.h could not find the file. So I then moved the find package and target_link_library to the fldbase/CMakeList.txt file but that didn't work.
I now have the find_packaged for Sql and the target_link_library in both the main project CMakeLists.txt and the fldbase CMakeList .txt and it works now.
-
That's exactly what I am describing. You library leaks the need for the SQL module because you use the module include in the header file.
- Never use the module includes in your code, they pull in at least all the classes modules. They are fine for demonstration purpose but that stops there.
- Apply the "include where you use" mantra. For the rest of the time, use forward include. That will make you builds both simpler and lighter.
-
That's exactly what I am describing. You library leaks the need for the SQL module because you use the module include in the header file.
- Never use the module includes in your code, they pull in at least all the classes modules. They are fine for demonstration purpose but that stops there.
- Apply the "include where you use" mantra. For the rest of the time, use forward include. That will make you builds both simpler and lighter.
@SGaist said in QSql, QSqlDatabase includes do not exist:
That's exactly what I am describing. You library leaks the need for the SQL module because you use the module include in the header file.
- Never use the module includes in your code, they pull in at least all the classes modules. They are fine for demonstration purpose but that stops there.
- Apply the "include where you use" mantra. For the rest of the time, use forward include. That will make you builds both simpler and lighter.
I am not sure I follow what you are saying so let me see if I understand.
What do you mean by module includes - is that like <QTSql> being included?
- Are you saying don't put #include <QtSql> in my class header file fldbase.h since it's in the CMakeLists.txt it will be used or am I NOT supposed to have it in the CMakeLists.txt file? What I ran into was that if I put #include <QSqlDatabase> in my header file I ended up with an unknown file error until I added them to the CMakeLists.txt files.
- That's what I do. I only use the fldbase.h header in the fldabase class at this point.
I will read up on the forward include. So far I do not use any of the classes anywhere except in themselves. I do not call them from anywhere else but that will change when I do the next phase.
Thanks.
-
Can you show your header file ?
I am currently suspecting that you are doing stuff that is discouraged in the documentation like for example keeping a QSqlDatabase member variable. -
Can you show your header file ?
I am currently suspecting that you are doing stuff that is discouraged in the documentation like for example keeping a QSqlDatabase member variable.@SGaist said in QSql, QSqlDatabase includes do not exist:
Can you show your header file ?
I am currently suspecting that you are doing stuff that is discouraged in the documentation like for example keeping a QSqlDatabase member variable.Thank you very much for you help.
I'll include the header. As far as I know I do not keep a QSqlDatabase member as I tried to use db.database(connectname, true) to connect to it as warned about in the documentation.
I did get it to work but I had to include the headers for the three modules, Q_IMPORT_QML_PLUGIN for each module and then use the engine.rootContext to get it to recognize the imports in the qml files. At this point I'm suffering from overload on how to do it. I see notes on do not use the setcontext method for some reason but in https://doc.qt.io/qt-6/qqmlcontext.html they use it. Then I see posts with qmlRegisterType<> in main.cpp but is that correct, good, bad, do not use? Given I'm new to Qt6 and it's been so long since I did Qt5 I want to learn the correct methods for working with cmake and Qt6 and not use Qt5 habits just because they work - at some point they will break probably.
I would very much like Qt to have a comprehensive document for Qt6 approved methods of building with cmake and integrating QML and C++ (using functions from C++ in QML and setting properties, etc) which includes how they want things registered in an approved fashion. Much is available but it's in bits and pieces across various class documentation so it becomes a treasure hunt and in some case uses methods were aren't supposed to use.
Here are the header files. I have three modules in three directories.
Project root directory
main.qml
main.cpp
fldbase directory
cpp, h, CMakeLists.txt files, qml file
importdata directory
cpp, h, CMakeLists.txt files, qml file
utils directory
cpp, h, CMakeLists.txt files, qml fileHeader for fldbase. I define a QSqlDatabse item in the header and then create a connection in the class constructor.
#ifndef FLDB_H #define FLDB_H // Qt Includes #include <QCoreApplication> #include "qqmlintegration.h" #include <QObject> #include <QtQml/qqmlregistration.h> // Our Includes #include <QDebug> // Database Includes #include <QSqlDatabase> #include <QSqlError> #include <QSqlQuery> #include <QSqlRecord> // File Includes #include <QFile> class FLDBase : public QObject { Q_OBJECT QML_ELEMENT public: explicit FLDBase(QObject *parent = nullptr); signals: public slots: bool fldbready(); //QString dbname, QString driverType, QString connName); void fldbclose(); int tests(int num); private: bool fdbexists(QString dbname, QString dbdriver); QSqlDatabase fldb; QString fldbconn = "fldbconnection"; QString driverType = "QSQLITE"; QString dbname = "flightlog.db"; int sqliterowcount(QSqlDatabase dbase); }; // End class FLDB definition #endif // FLDB_H
FLDBase class constructor.```
FLDBase::FLDBase(QObject *parent)
: QObject{parent}
{
fldb = QSqlDatabase::addDatabase(driverType, fldbconn);
fldb.setDatabaseName(dbname);
fldb.database(fldbconn, true);
}Header for import data
#ifndef IMPORTDATA_H
#define IMPORTDATA_H// Qt Includes
#include <QCoreApplication>
#include "qqmlintegration.h"
#include <QObject>
#include <QVariant>
#include <QUrl>
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include <QtQml/qqmlregistration.h>
#include <QVector>
#include <QFile>
#include <QTextStream>// Our Includes
#include <QDebug>class ImportData : public QObject
{
Q_OBJECT
QML_ELEMENTpublic: explicit ImportData(QObject *parent = nullptr);
signals:
void status(QVariant data);public slots:
void bark(); // For testing - remove later.
QString readdata(QString src, QString infile);private:
QString m_datafile;
QVector<QVector<QString>> m_rawdata;
QVector<QString> m_tmpdata;// For csv input data char m_csvdelim = ',';
}; // End class ImportData definition
#endif // IMPORT_H
Header for utils.
#ifndef UTILS_H
#define UTILS_H
// Qt Includes
#include <QCoreApplication>
#include "qqmlintegration.h"
#include <QtQml/qqmlregistration.h>
#include <QObject>
#include <QUrl>
#include <QDir>// Our Includes
#include <QDebug>class Utils : public QObject
{
Q_OBJECT
QML_ELEMENTpublic:
explicit Utils(QObject *parent = nullptr);Q_INVOKABLE QString urltonativepath(const QUrl& urlpath);
signals:
};
#endif // UTILS_H
And main.cpp
//Qt Includes
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml/QQmlExtensionPlugin>
#include <QQmlContext>
#include <QQuickView>// Our Includes
#include "importdata/importdata.h"
#include "fldbase/fldbase.h"
#include "utils/utils.h"
//class Utils;// Plugins
Q_IMPORT_QML_PLUGIN(importdataPlugin)
Q_IMPORT_QML_PLUGIN(fldbasePlugin)
Q_IMPORT_QML_PLUGIN(utilsPlugin)int main(int argc, char *argv[])
{
QCoreApplication::setOrganizationName("Dakota Pilot");
QCoreApplication::setOrganizationDomain("dakotapilot.com");
QCoreApplication::setApplicationName("Flight Log");QGuiApplication app(argc, argv); QQmlApplicationEngine engine;
//=============================================================================
// Add our stuff to the root context.
ImportData getdata;
FLDBase fldbase;
Utils utils;engine.rootContext()->setContextProperty("datain", &getdata); engine.rootContext()->setContextProperty("fldbase", &fldbase); engine.rootContext()->setContextProperty("utils", &utils);
//=============================================================================
// Standard Qt, QML items.
const QUrl url(u"qrc:/FlightLog/main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);return app.exec();
}
-
private:
bool fdbexists(QString dbname, QString dbdriver);
QSqlDatabase fldb;This is exactly what you should not do.
-
private:
bool fdbexists(QString dbname, QString dbdriver);
QSqlDatabase fldb;This is exactly what you should not do.
@SGaist said in QSql, QSqlDatabase includes do not exist:
private:
bool fdbexists(QString dbname, QString dbdriver);
QSqlDatabase fldb;This is exactly what you should not do.
Thank you for taking the time to help me sort this out.
Okay. So how do I do that. Do I remove the QSqlDatabase fldb and then define it in the constructor for the class by doing the QSqlDatabase in there and then open it? What exactly does what I did do. I assume it creates a copy bound to the class and that is not good.
I'm still confused about the use of Q_PLUGIN_QML and registering the modules in main.cpp.
As I thought I understood the process it was that if I build the modules in CMakeLists.txt for the project and it's modules it would be able to find the modules and I could simply import them with import statements using the URI in the QML modules. But I see some posts and Qt documentation that say I need to use the Q_QML_PLUGIN and I need to add the set context property. If I don't do that then the QML modules import statements tell me they can't find the file.
-
@SGaist said in QSql, QSqlDatabase includes do not exist:
private:
bool fdbexists(QString dbname, QString dbdriver);
QSqlDatabase fldb;This is exactly what you should not do.
Thank you for taking the time to help me sort this out.
Okay. So how do I do that. Do I remove the QSqlDatabase fldb and then define it in the constructor for the class by doing the QSqlDatabase in there and then open it? What exactly does what I did do. I assume it creates a copy bound to the class and that is not good.
I'm still confused about the use of Q_PLUGIN_QML and registering the modules in main.cpp.
As I thought I understood the process it was that if I build the modules in CMakeLists.txt for the project and it's modules it would be able to find the modules and I could simply import them with import statements using the URI in the QML modules. But I see some posts and Qt documentation that say I need to use the Q_QML_PLUGIN and I need to add the set context property. If I don't do that then the QML modules import statements tell me they can't find the file.
@RangerQT said in QSql, QSqlDatabase includes do not exist:
Do I remove the QSqlDatabase fldb and then define it in the constructor for the class by doing the QSqlDatabase in there and then open it?
Yes. Only use
QSqlDatabase fldb
as a local variable in a function which needs it, such as when opening it initially. Why do you need it (the variable) after that anyway?QSqlQuery
etc. will automatically use it for you as your default database; if you do want to get at it for some reason use the static QSqlDatabase QSqlDatabase::database() call to access it.What exactly does what I did do. I assume it creates a copy bound to the class and that is not good.
Exactly that. And Qt does not like you doing this! It keeps a reference around in your class, and interferes with Qt's code to release it when closing down.