Results 1 to 20 of 61

Thread: using an isntance of QSqlDatabase for connection defiinition

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Quote Originally Posted by jfinn88 View Post
    You are talking about binding my Msg variable correct? the parameter I'm using in my sql statement?
    Yes

    Quote Originally Posted by jfinn88 View Post
    How do I set the conn1 connection since The prepare() fcn only takes one argument can't pass it the connection name with sql statement
    You pass the QSqlDatabase handle to the QSqlQuery constructor.
    Qt Code:
    1. QSqlQuery insertQuery(m_insertDataBase);
    2. insertQuery.prepare(...);
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by jfinn88 View Post
    I will look at documentation on isValid(). How do I only call those methods once when the instance is not valid? little explanation on how this works be great, you got a example?
    Qt Code:
    1. if (!m_insertDataBase.isValid() {
    2. // addDatabase, setDatabaseName
    3. }
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

  2. #2
    Join Date
    Jun 2016
    Posts
    99
    Thanks
    18
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    I have two classes I need to use an instance variable of the class QSqlDatabase to set database connections. I created an instance variable of the QSqlDatabase class in both classes under private:
    --------------- Header file----------------
    Qt Code:
    1. //Data struct for user event log
    2. struct userEventLogMsg{
    3. //hold all values for a single list entry,
    4. QString id;
    5. QString username;
    6. QString eventmessage;
    7. QString datetime;
    8. };
    9.  
    10. //---Class UserEventDailyLog responsible for XMUI UserEvnetLog | Subed classed: QAbstractTableModel---//
    11. class UserEventLog : public QAbstractListModel
    12. {
    13. Q_OBJECT
    14.  
    15. public:
    16. explicit UserEventLog(QObject *parent = 0);
    17.  
    18. ~UserEventLog();
    19.  
    20. enum userEventRoles {idRole= Qt::UserRole + 220, nameRole, msgRole, dateRole};
    21.  
    22. int rowCount(const QModelIndex & parent) const;
    23.  
    24. QHash<int, QByteArray> roleNames() const;
    25.  
    26. QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
    27.  
    28. Q_INVOKABLE void addEvent(const userEventLogMsg &msg);
    29.  
    30. void dbConnect();
    31.  
    32. void sqlSelect();
    33.  
    34. private:
    35. QList<userEventLogMsg> m_userEventList;
    36. QSqlDatabase m_selectDataBase;
    37. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. //---------CPP file--------------//
    2. //
    3. // UserEventLogModel
    4. //
    5.  
    6. //---Constructor---//
    7. UserEventLog::UserEventLog(QObject *parent):QAbstractListModel(parent) {
    8.  
    9. }
    10. //---Destructor---//
    11. UserEventLog::~UserEventLog() {
    12.  
    13. }
    14.  
    15. int UserEventLog::rowCount(const QModelIndex &parent) const {
    16. Q_UNUSED(parent);
    17. qDebug()<< m_userEventList.count();
    18. return m_userEventList.count();
    19. }
    20.  
    21. QHash<int, QByteArray> UserEventLog::roleNames() const {
    22. QHash<int, QByteArray> roleNames;
    23. roleNames.insert(idRole, "id");
    24. roleNames.insert(nameRole, "userName");
    25. roleNames.insert(msgRole, "eventMessage");
    26. roleNames.insert(dateRole, "dateTime");
    27. qDebug()<< roleNames;
    28. return roleNames;
    29. }
    30.  
    31. QVariant UserEventLog::data(const QModelIndex &index, int role) const {
    32. if (index.row() < 0 || index.row() >= m_userEventList.count()){
    33. return QVariant();
    34. }
    35.  
    36. QVariant text;
    37.  
    38. if(role == idRole) {
    39. userEventLogMsg msg = m_userEventList.at(index.row());
    40. text = msg.id;
    41. qDebug() << text;
    42. }
    43. else if(role == nameRole) {
    44. userEventLogMsg msg = m_userEventList.at(index.row());
    45. text = msg.username;
    46. qDebug() << text;
    47. }
    48. else if(role == msgRole) {
    49. userEventLogMsg msg = m_userEventList.at(index.row());
    50. text = msg.eventmessage;
    51. qDebug() << text;
    52. }
    53. if(role == dateRole) {
    54. userEventLogMsg msg = m_userEventList.at(index.row());
    55. text = msg.datetime;
    56. qDebug() << text;
    57. }
    58. return text;
    59. }
    60.  
    61. void UserEventLog::addEvent(const userEventLogMsg &msg) {
    62.  
    63. beginInsertRows(QModelIndex(), 0, 0);
    64. m_userEventList.insert(0, msg);
    65. endInsertRows();
    66. }
    67.  
    68. void UserEventLog::dbConnect() {
    69. m_selectDataBase = QSqlDatabase::addDatabase("QSQLITE", "conn2");
    70. qDebug() << m_selectDataBase.isValid();
    71. m_selectDataBase.setDatabaseName("/home/amet/userLog.db");
    72. m_selectDataBase.open();
    73.  
    74. if(!m_selectDataBase.open()){
    75. qDebug() <<"error in opening DB";
    76. }
    77. else{
    78. qDebug() <<"connected to DB" ;
    79. }
    80. }
    81. void UserEventLog::sqlSelect() {
    82.  
    83. //m_selectDataBase = QSqlDatabase::database("conn2");
    84. qDebug() << m_selectDataBase.isValid();
    85. m_selectDataBase.open();
    86. QSqlQuery selectQuery;
    87. selectQuery.prepare("SELECT id, userName, eventMessage, dateTime FROM userlogevents");
    88. qDebug() <<selectQuery.lastError();
    89.  
    90. if(selectQuery.exec()){
    91. qDebug()<<"sql statement exicuted fine";
    92. }
    93. else{
    94. qDebug() <<"Errors accured with sql statement";
    95. qDebug() <<selectQuery.lastError();
    96. }
    97.  
    98. while (selectQuery.next()){
    99. userEventLogMsg msg;
    100. UserEventLog model;
    101. msg.id = selectQuery.value(0).toString();
    102. msg.username = selectQuery.value(1).toString();
    103. msg.eventmessage = selectQuery.value(2).toString();
    104. msg.datetime = selectQuery.value(3).toString();
    105. model.addEvent(msg);
    106. }
    107. //m_selectDataBase.close();
    108. //m_selectDataBase.removeDatabase("conn2");
    109. }
    110. //----------------------------------------------------------------//
    To copy to clipboard, switch view to plain text mode 

    my other class that need a database connection to the same database

    ---------CPP file-----------
    Qt Code:
    1. void XMUI::hdpiWindow()
    2. {
    3. mUserEventLogModel = new UserEventLog();
    4. mUserEventLogModel->dbConnect();
    5. mUserEventLogModel->sqlSelect();
    6. m_QmlEngine->rootContext()->setContextProperty("UserEventLog", mUserEventLogModel);
    7. }
    8.  
    9. void XMUI::insertLogMessage(QString msg)
    10. {
    11. m_insertDataBase = QSqlDatabase::addDatabase("QSQLITE", "conn1");
    12. m_insertDataBase.setDatabaseName("/home/amet/userLog.db");
    13. m_insertDataBase.open();
    14.  
    15. if(m_insertDataBase.isOpen()){
    16.  
    17. qDebug() <<"connected to DB" ;
    18. }
    19. else{
    20. qDebug() <<"error in opening DB";
    21. m_insertDataBase.open();
    22. }
    23.  
    24. qDebug() << "insert Log Message called";
    25. QSqlQuery insertQuery(m_insertDataBase);
    26. insertQuery.prepare("INSERT INTO userlogevents (firstName, lastName, userName, eventMessage, dateTime) VALUES('John', 'Doe', 'JohnnyD', ':eventMessage', datetime(current_timestamp))");
    27. insertQuery.bindValue(":eventMessage", msg);
    28. insertQuery.exec();
    29. //m_insertDataBase.close();
    30. //m_insertDataBase.removeDatabase("conn1");
    31. }
    To copy to clipboard, switch view to plain text mode 


    ----header file--------
    Qt Code:
    1. class XMUI : public QObject
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. explicit XMUI(QQuickWidget* _quickWidget);
    7.  
    8. void hdpiWindow();
    9.  
    10. Q_INVOKABLE void insertLogMessage(QString msg);
    11.  
    12. private:
    13. QSqlDatabase m_insertDataBase;
    To copy to clipboard, switch view to plain text mode 


    Added after 18 minutes:


    Quote Originally Posted by anda_skoa View Post
    Yes


    You pass the QSqlDatabase handle to the QSqlQuery constructor.
    Qt Code:
    1. QSqlQuery insertQuery(m_insertDataBase);
    2. insertQuery.prepare(...);
    To copy to clipboard, switch view to plain text mode 
    I was passing the name of my connection not the instance variable, changed it to instance variable.

    Qt Code:
    1. if (!m_insertDataBase.isValid() {
    2. // addDatabase, setDatabaseName
    3. }
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _
    I moved the add and set methods inside an if condition to set them if the database is not valid. However I get confused because I need to connect to the database to begin with... If I'm only setting them when it not valid how do I initially set the connect the first time. set it in the constructor?

    Qt Code:
    1. void XMUI::insertLogMessage(QString msg)
    2. {
    3. //qDebug() << m_insertDataBase.connectionNames();
    4.  
    5. if(!m_insertDataBase.isValid()){
    6. qDebug() <<"error in opening DB";
    7. m_insertDataBase = QSqlDatabase::addDatabase("QSQLITE", "conn1");
    8. m_insertDataBase.setDatabaseName("/home/amet/userLog.db");
    9. qDebug() << m_insertDataBase.connectionNames();
    10. }
    11. else{
    12. qDebug() <<"connected to DB";
    13. m_insertDataBase.open();
    14. //qDebug() << m_insertDataBase.lastError();
    15. }
    16.  
    17. m_insertDataBase.open();
    18. QSqlQuery m_insertQuery(m_insertDataBase);
    19. m_insertQuery.prepare("INSERT INTO userlogevents (firstName, lastName, userName, eventMessage, dateTime) VALUES('John', 'Doe', 'JohnnyD', ':eventMessage', datetime(current_timestamp))");
    20. m_insertQuery.bindValue(":eventMessage", msg);
    21. m_insertQuery.exec();
    22. qDebug() << m_insertQuery.lastError();
    23. //m_insertDataBase.close();
    24. //QSqlDatabase::removeDatabase("conn1");
    25. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by jfinn88; 24th August 2016 at 21:38.

  3. #3
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    You can call open inside the same if(), or after the whole if/else block.

    There is no point in calling open() before it is valid and there is no point in passing the instance to QSqlQuery before it is opened.

    There is also no point in using prepare if you are still just concenating strings instead of passing the msg value as via bindValue().

    You also might want to think what your while loop is doing, in particular the life time of the "model" object and which class you are in.

    Cheers,
    _

  4. #4
    Join Date
    Jun 2016
    Posts
    99
    Thanks
    18
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Quote Originally Posted by anda_skoa View Post
    There is also no point in using prepare if you are still just concenating strings instead of passing the msg value as via bindValue().
    I updated this right before you posted this. I'm using the bind value method now with the prepare method

    Quote Originally Posted by anda_skoa View Post
    There is no point in calling open() before it is valid and there is no point in passing the instance to QSqlQuery before it is opened.
    Now that you point it out that makes sense will move open() call inside if() statement, since the if statement is checking for validation would you also pass the instance to QSqlQuery inside the if() block?
    Qt Code:
    1. //---------Inserts data into database (XMUI Global Funciton)--------------//
    2. void XMUI::insertLogMessage(QString msg)
    3. {
    4. //qDebug() << m_insertDataBase.connectionNames();
    5.  
    6. if(!m_insertDataBase.isValid()){
    7. qDebug() <<"error in opening DB";
    8. m_insertDataBase = QSqlDatabase::addDatabase("QSQLITE", "conn1");
    9. m_insertDataBase.setDatabaseName("/home/amet/userLog.db");
    10. qDebug() << m_insertDataBase.connectionNames();
    11. }
    12. else{
    13. qDebug() <<"connected to DB";
    14. m_insertDataBase.open();
    15. //qDebug() << m_insertDataBase.lastError();
    16. }
    17.  
    18. m_insertDataBase.open();
    19. QSqlQuery m_insertQuery(m_insertDataBase);
    20. m_insertQuery.prepare("INSERT INTO userlogevents (firstName, lastName, userName, eventMessage, dateTime) VALUES('John', 'Doe', 'JohnnyD', :eventMessage, datetime(current_timestamp))");
    21. m_insertQuery.bindValue(":eventMessage", msg);
    22. m_insertQuery.exec();
    23. qDebug() << m_insertQuery.lastError();
    24. //m_insertDataBase.close();
    25. //QSqlDatabase::removeDatabase("conn1");
    26. }
    27. //----------------------------------------------------------------//
    To copy to clipboard, switch view to plain text mode 

    Having trouble with connection to database... app crashes. I use a default connection for a user login and close it in the destructor, once the user logins in a series of method calls to insertLogMessage() takes place It seems like it never changes connection from default to conn1...

    Tried placing some qdebug error checks:
    Qt Code:
    1. qDebug() << m_insertDataBase.lastError(); & qDebug() << m_insertQuery.lastError();
    To copy to clipboard, switch view to plain text mode 
    but I dont get any errors back: QSqlError("", "", "") I list the connection names using
    Qt Code:
    1. qDebug() << m_insertDataBase.connectionNames();
    To copy to clipboard, switch view to plain text mode 
    it shows the default connection and the conn1 connection | verified insert query pushes to database data is showing up now!

    do I need to close or remove the database?

    Now I need help fixing my function in my other class

    Qt Code:
    1. void UserEventLog::dbConnect() {
    2.  
    3. if(!m_selectDataBase.isValid()){
    4. qDebug() << "error in opening DB";
    5. m_selectDataBase = QSqlDatabase::addDatabase("QSQLITE", "conn2");
    6. m_selectDataBase.setDatabaseName("/home/amet/userLog.db");
    7. }
    8. else{
    9. qDebug() <<"connected to DB" ;
    10. }
    11. m_selectDataBase.open();
    12. }
    13. void UserEventLog::sqlSelect() {
    14.  
    15. //---Check is Database is valid---//
    16. if(!m_selectDataBase.isValid())
    17. {
    18. qDebug() << "error in opening DB";
    19. m_selectDataBase = QSqlDatabase::addDatabase("QSQLITE", "conn2");
    20. m_selectDataBase.setDatabaseName("/home/amet/userLog.db");
    21. m_selectDataBase.open();
    22. }
    23. else{
    24. qDebug()<<"connected to DB";
    25. m_selectDataBase.open();
    26. }
    27.  
    28. //---Check if database is open---//
    29. if(!m_selectDataBase.open())
    30. {
    31. qDebug() << "database was closed";
    32. m_selectDataBase.open();
    33. }
    34. else{
    35. qDebug() << "database is open";
    36. }
    37.  
    38. QSqlQuery selectQuery("SELECT id, userName, eventMessage, dateTime FROM userlogevents");
    39.  
    40. //---Check if Sql Query Ran---//
    41. if(selectQuery.exec()){
    42. qDebug()<<"sql statement exicuted fine";
    43. }
    44. else{
    45. qDebug() << "Errors accured with sql statement";
    46. qDebug() << selectQuery.lastError();
    47. }
    48.  
    49. while (selectQuery.next()){
    50. //---Instance of userEventLogMsg Class Struct---//
    51. userEventLogMsg msg;
    52. //---Instance of userEventlog Class---//
    53. UserEventLog model;
    54. //---Add query data to the msg class struct---//
    55. msg.id = selectQuery.value(0).toString();
    56. msg.username = selectQuery.value(1).toString();
    57. msg.eventmessage = selectQuery.value(2).toString();
    58. msg.datetime = selectQuery.value(3).toString();
    59. //---Use model object to access an call addEvent()---//
    60. model.addEvent(msg);
    61. }
    62. //m_selectDataBase.close();
    63. //QSqlDatabase::removeDatabase("conn2");
    64. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by jfinn88; 24th August 2016 at 23:41.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Quote Originally Posted by jfinn88 View Post
    Now that you point it out that makes sense will move open() call inside if() statement, since the if statement is checking for validation would you also pass the instance to QSqlQuery inside the if() block?
    No, I would leave the QSqlQuery outside.

    Quote Originally Posted by jfinn88 View Post
    do I need to close or remove the database?
    No, you should be able to keep more than one connection at any given time.


    Now I need help fixing my function in my other class

    Quote Originally Posted by jfinn88 View Post
    Qt Code:
    1. QSqlQuery selectQuery("SELECT id, userName, eventMessage, dateTime FROM userlogevents");
    To copy to clipboard, switch view to plain text mode 
    You likely want to use the m_selectDataBase for this query, no?

    Quote Originally Posted by jfinn88 View Post
    Qt Code:
    1. while (selectQuery.next()){
    2. //---Instance of userEventLogMsg Class Struct---//
    3. userEventLogMsg msg;
    4. //---Instance of userEventlog Class---//
    5. UserEventLog model;
    6. //---Add query data to the msg class struct---//
    7. msg.id = selectQuery.value(0).toString();
    8. msg.username = selectQuery.value(1).toString();
    9. msg.eventmessage = selectQuery.value(2).toString();
    10. msg.datetime = selectQuery.value(3).toString();
    11. //---Use model object to access an call addEvent()---//
    12. model.addEvent(msg);
    13. }
    To copy to clipboard, switch view to plain text mode 
    This doesn't look at all what I assume you want.
    This creates a new model instance in every loop iteration, adds one record and then destroys the model (when it goes out of scope).

    Cheers,
    _

  6. #6
    Join Date
    Jun 2016
    Posts
    99
    Thanks
    18
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Quote Originally Posted by anda_skoa View Post
    No, I would leave the QSqlQuery outside.
    Okay, That makes sense played with it and I declare it before the if() block.

    No, you should be able to keep more than one connection at any given time.
    Okay, so I'm fine with leaving conn1, and conn2 connected.

    You likely want to use the m_selectDataBase for this query, no?
    I can pass it with the sql statement correct ?

    Qt Code:
    1. QSqlQuery selectQuery("SELECT id, userName, eventMessage, dateTime FROM userlogevents", m_selectDataBase);
    To copy to clipboard, switch view to plain text mode 

    This doesn't look at all what I assume you want.
    This creates a new model instance in every loop iteration, adds one record and then destroys the model (when it goes out of scope).
    you are correct I do not want to create a new object every time it goes threw while loop moved object declaration above while loop. Will calling addEvent () in the while loop be fine or should it be called once after the while loop is done putting data in struct?

    I’m still little confused how the virtual functions get called... from my understanding is when the instance variable of my class is created (to pass the model to C++ by setting rootContext item) it makes a call to the constructor and when the constructor gets called the virtual functions get called (trying to clear any confuse I still have with models and virtual functions) ?
    Qt Code:
    1. //---Instance of userEventLogMsg Class Struct---//
    2. userEventLogMsg msg;
    3.  
    4. while (selectQuery.next()){
    5. //---Add query data to the userEventLogMsg class struct---//
    6. msg.id = selectQuery.value(0).toString();
    7. msg.username = selectQuery.value(1).toString();
    8. msg.eventmessage = selectQuery.value(2).toString();
    9. msg.datetime = selectQuery.value(3).toString();
    10. //---Use model object to access an call addEvent()---//
    11. addEvent(msg);
    12. }
    To copy to clipboard, switch view to plain text mode 

    Also I want to call dbConnect and selectQuery() methods from QML (button click)
    in the header file I declare the function as Q_INVOKABLE now I know I could register the QML type to make the class accessible in QML and import it in the QML to call the function but I think I would have to make the class global object? is there a simpler way to do this ?

    I have seen an example with Q_INVOKABLE and setting the context property, but I get confused on what engine object/class I need to use to set it. I don't quit understand the rootContext methodology yet and have a QML engine already defined and in use that I don't want to mess up, Im not sure if replacing what is currently on the engine stack is the right way todo it? or if using a new engine object is correct... would I need to create an instance object of a qml engine in my userEvetnLog class? (how can I tell what object this is pointing to?)

    Qt Code:
    1. mUserEventLogModel = new UserEventLog();
    2. m_QmlEngine->rootContext()->setContextProperty("UserEventLog", mUserEventLogModel);
    To copy to clipboard, switch view to plain text mode 

    In my QML I call my funtions

    Qt Code:
    1. Action {
    2. id: action_userEventLogBtn
    3. enabled:!inSequence
    4. onTriggered:{
    5. //----Code to Load User Event Database into tableView-----//
    6. input_loader.filename = ""
    7. UserEventLog.dbConnect();
    8. UserEventLog.sqlSelect();
    9. weld_view.state = "USEREVENT"
    10. onLoaded: console.log("User Event Log");
    To copy to clipboard, switch view to plain text mode 

    update: Okay I got my functions working in QML used previously defined QQmlEngine and instance of UserEventLog class that was used to make my model available to QML

    update: made a stupid mistake when calling my addEvent function and now just realized it. Was getting a segfault fixed by removing UserEventLog object and just calling addEvent since Im in the class.
    Last edited by jfinn88; 25th August 2016 at 19:37.

  7. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Quote Originally Posted by jfinn88 View Post
    I can pass it with the sql statement correct ?
    Yes.

    Quote Originally Posted by jfinn88 View Post
    Will calling addEvent () in the while loop be fine or should it be called once after the while loop is done putting data in struct?
    In every loop iteration.
    You can basically keep your code, but instead of calling addEvent() on a different model you just call addEvent() of the current object.

    Quote Originally Posted by jfinn88 View Post
    I’m still little confused how the virtual functions get called... from my understanding is when the instance variable of my class is created (to pass the model to C++ by setting rootContext item) it makes a call to the constructor and when the constructor gets called the virtual functions get called (trying to clear any confuse I still have with models and virtual functions) ?
    When you create an object, the constructor for that class is called.

    Once the object is created, calls to virtual functions always end up in the most specific subclass.
    E.g. if you overwrite roleNames() a call to roleNames() will end up calling your implementation.

    Quote Originally Posted by jfinn88 View Post
    Also I want to call dbConnect and selectQuery() methods from QML (button click)
    For what purpose?
    I can see a use case of re-running the query on demand, but dbConnect?
    dbConnect() is really internal, no? It has to be called before database access happens, so the class itself should know when to call it.

    Quote Originally Posted by jfinn88 View Post
    in the header file I declare the function as Q_INVOKABLE now I know I could register the QML type to make the class accessible in QML and import it in the QML to call the function but I think I would have to make the class global object? is there a simpler way to do this ?
    That is unnecessary.
    Q_INVOKABLE methods and slots are already accessible as functions on an object set as a context property.
    Registration of a type is only necessary if instances of that type need to be created from QML or if it has enum definitions where the QML code should be able to use the names.

    Quote Originally Posted by jfinn88 View Post
    I have seen an example with Q_INVOKABLE and setting the context property, but I get confused on what engine object/class I need to use to set it.
    You don't have to change anything in your code.

    Cheers,
    _

  8. The following user says thank you to anda_skoa for this useful post:

    jfinn88 (26th August 2016)

  9. #8
    Join Date
    Jun 2016
    Posts
    99
    Thanks
    18
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Thank you for all the help anda_skoa,
    Model seems to be working good now I will posted updated code
    I'm now wanting to add some functionality to my tableView, Like to be able to search by date and userName... I want to pass text values back to my c++ function a would like to use the signal and slot mechanism to perform this action. However I get lost with what Object I need to pass the QObject::connect() method, for it to work.
    I created two signals and two slots one for the date text field in qml and the other is for the userName text field in qml.
    in C++ I created to slots to receive the qml signals and to out put the text data passed to the console using a debug() method.
    I'm little confused on where to place the QObject::connect method in my project... main.cpp or sqliteModel.cpp in the constructor ?
    I am unsure what objects to pass the connect() method for the signal to receive the slot ?
    I would also Like to create a table in the database for each separate day for user event logging and delete old tables after 30 days
    here is my code: (had to remove functions for model in cpp file to get it to fit)

    =========== main.qml===============
    Qt Code:
    1. import QtQuick 2.5
    2. import QtQuick.Layouts 1.1
    3. import QtQuick.Controls 1.3
    4. import QtQuick.Window 2.2
    5. import QtQuick.Dialogs 1.2
    6. import QtQuick.Layouts 1.1
    7. import QtQuick.Controls 1.4
    8.  
    9. Window {
    10. signal submitDateText(string text)
    11. signal submitUserNameText(string text)
    12. visible: true
    13. width: 760
    14. height: 450
    15. title: "User Event Log"
    16. TableView {
    17. width: 750;
    18. height: 350;
    19. anchors.centerIn: parent;
    20. horizontalScrollBarPolicy: 0
    21. frameVisible: true
    22. model: sqliteModel
    23. TableViewColumn {
    24. role: "id"
    25. title: "id"
    26. width: 100
    27. }
    28. TableViewColumn {
    29. role: "userName"
    30. title: "User Name"
    31. width: 200
    32. }
    33. TableViewColumn {
    34. role: "eventMessage"
    35. title: "Event Message"
    36. width: 200
    37. }
    38. TableViewColumn {
    39. role: "dateTime"
    40. title: "Date Time"
    41. width: 200
    42. }
    43. }
    44. RowLayout {
    45. id: row1
    46. x: 201
    47. y: 403
    48. anchors.horizontalCenter: parent.horizontalCenter;
    49. anchors.bottom: parent.bottom
    50. width: 750
    51. height: 47;
    52. clip: false
    53. opacity: 0.9
    54. Button {
    55. id: load_btn
    56. text: qsTr("Load")
    57. MouseArea{
    58. anchors.fill: parent
    59. onClicked: {
    60. sqliteModel.dbConnect();
    61. sqliteModel.sqlSelect();
    62. }
    63. }
    64. }
    65. Label {
    66. id: userNameLabel
    67. text: qsTr("User Name")
    68. }
    69. TextField {
    70. id: userNameTextField
    71. placeholderText: qsTr("User Name")
    72. }
    73. Label {
    74. id: dateLabel
    75. width: 39
    76. height: 17
    77. text: qsTr("Date")
    78. }
    79. TextField {
    80. id: dateTextField
    81. width: 125
    82. height: 25
    83. placeholderText: qsTr("mm//dd/yyyy")
    84. }
    85. Button {
    86. id: searchBtn
    87. text: qsTr("Search")
    88. MouseArea{
    89. anchors.fill: parent
    90. onClicked: {
    91. // emit the submitTextField signal
    92. submitDateText(dateTextField.text);
    93. submitUserNameText(userNameTextField.text);
    94. }
    95. }
    96. }
    97. Button {
    98. id: exit_btn
    99. text: qsTr("Exit")
    100. MouseArea{
    101. anchors.fill: parent
    102. onClicked: close();
    103. }
    104. }
    105. }
    106. }
    To copy to clipboard, switch view to plain text mode 

    =========== main.cpp===============
    Qt Code:
    1. #include <QGuiApplication>
    2. #include <QQmlApplicationEngine>
    3. #include <QSqlDatabase>
    4. #include "sqlitemodel.h"
    5. #include <QUrl>
    6.  
    7. int main(int argc, char *argv[])
    8. {
    9. QGuiApplication app(argc, argv);
    10. sqliteModel *model = new sqliteModel;
    11. QQmlApplicationEngine engine;
    12. QQmlContext *contxt = engine.rootContext();
    13. contxt->setContextProperty("sqliteModel", model);
    14. engine.load(QUrl("qrc:/main.qml"));
    15. return app.exec();
    16. }
    To copy to clipboard, switch view to plain text mode 

    =========== sqliteModel.cpp==========
    Qt Code:
    1. #include "sqlitemodel.h"
    2.  
    3. sqliteModel::sqliteModel(QObject *parent):QAbstractListModel(parent)
    4. {
    5. // connect our QML signal to our C++ slot
    6. QObject::connect(/*QMLObject(?)*/, SIGNAL(submitDateText(QString)), this, SLOT(searchDateText(QString)));
    7. }
    8.  
    9. sqliteModel::~sqliteModel()
    10. {
    11. }
    12.  
    13. void sqliteModel::createDailyTable()
    14. {
    15. dbConnect();
    16. int addOne;
    17. QSqlQuery createTableQry(m_selectDataBase);
    18. createTableQry.prepare("CREATE TABLE userlogevents1 AS SELECT * FROM userlogevents WHERE 0");
    19. createTableQry.exec();
    20. m_selectDataBase.close();
    21. }
    22.  
    23. void sqliteModel::deleteDailyTable()
    24. {
    25. dbConnect();
    26. QSqlQuery selectTables(m_selectDataBase);
    27. //---Selects all tables older than 30 days in database | Gets date created---//
    28. selectTables.prepare("SELECT usereventlog, create_date FROM sys.tables WHERE DATEDIFF(day, create_date, getdate()) > 30");
    29. selectTables.exec();
    30. QString selectTableResult;
    31. selectTableResult = selectTables.value(0).toString();
    32. selectTableResult.append(selectTables.value(1).toString());
    33. selectTableResult.append(selectTables.value(2).toString());
    34. qDebug() << selectTableResult;
    35.  
    36. //--- If the table is older than 30 days drop it---//
    37. QSqlQuery deleteTableQry(m_selectDataBase);
    38. deleteTableQry.prepare("DROP TABLE userlogevetns");
    39. deleteTableQry.exec();
    40. m_selectDataBase.close();
    41. }
    42.  
    43. void sqliteModel::searchDateFcn(QString dateText)
    44. {
    45. dbConnect();
    46. QSqlQuery searchDateQry(m_selectDataBase);
    47. searchDateQry.prepare("SELECT id, userName, eventMessage, dateTime FROM usereventlog WHERE userName = "+dateText);
    48. searchDateQry.exec();
    49. m_selectDataBase.close();
    50. }
    51.  
    52. void sqliteModel::searchUserNameFcn(QString userNameText)
    53. {
    54. dbConnect();
    55. QSqlQuery searchDateQry(m_selectDataBase);
    56. searchDateQry.prepare("SELECT id, userName, eventMessage, dateTime FROM usereventlog WHERE userName = "+ userNameText);
    57. searchDateQry.exec();
    58. m_selectDataBase.close();
    59. }
    60.  
    61. void sqliteModel::searchDateText(const QString &dateText)
    62. {
    63. qDebug() << "c++: sqliteModel::searchDateText:" << dateText;
    64. }
    65.  
    66. void sqliteModel::searchUserNameText(const QString &userNameText)
    67. {
    68. qDebug() << "c++: sqliteModel::searchUserNameText:" << userNameText;
    69. }
    To copy to clipboard, switch view to plain text mode 

    =========== sqliteModel.h===============
    Qt Code:
    1. #ifndef SQLITEMODEL_H
    2. #define SQLITEMODEL_H
    3.  
    4. #include <assert.h>
    5. #include <list>
    6. #include <QList>
    7. #include <QColor>
    8. #include <QObject>
    9. #include <QDebug>
    10. #include <QString>
    11. #include <QFileInfo>
    12. #include <QDateTime>
    13. #include <QQmlError>
    14. #include <QQmlApplicationEngine>
    15. #include <QQmlEngine>
    16. #include <QQmlContext>
    17. #include <QtSql/QSqlDatabase>
    18. #include <QtSql/QSqlQuery>
    19. #include <QtSql/QSqlError>
    20. #include <QtSql/QSqlRecord>
    21. #include <QModelIndex>
    22. #include <QAbstractListModel>
    23.  
    24. struct userEventLogMsg{
    25. QString id;
    26. QString username;
    27. QString eventmessage;
    28. QString datetime;
    29. };
    30.  
    31. class sqliteModel:public QAbstractListModel
    32. {
    33. Q_OBJECT
    34. public:
    35. explicit sqliteModel(QObject *parent = 0);
    36. ~sqliteModel();
    37. enum userEventRoles {idRole= Qt::UserRole + 220, nameRole, msgRole, dateRole};
    38. int rowCount(const QModelIndex & parent) const;
    39. QHash<int, QByteArray> roleNames() const;
    40. QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
    41. Q_INVOKABLE void addEvent(const userEventLogMsg &msg);
    42. Q_INVOKABLE void dbConnect();
    43. Q_INVOKABLE void sqlSelect();
    44. void createDailyTable();
    45. void deleteDailyTable();
    46. void searchDateFcn(QString userDateText);
    47. void searchUserNameFcn(QString userNameText);
    48. public slots:
    49. void searchDateText(const QString &dateIn);
    50. void searchUserNameText(const QString &userNameIn);
    51. private:
    52. QList<userEventLogMsg> m_msgList;
    53. QSqlDatabase m_selectDataBase;
    54. QSqlQuery m_selectQuery;
    55. };
    To copy to clipboard, switch view to plain text mode 

    I was able to pass the text form qml to my cpp slot by expose Qt slot to QML element. By using the context property I set for my model to be exposed to QML.

    now my searchDateText fcn and searchUserName fcn can be called in qml by:
    Qt Code:
    1. Button {
    2. id: searchBtn
    3. text: qsTr("Search")
    4. MouseArea{
    5. anchors.fill: parent
    6. onClicked: {
    7. sqliteModel.searchDateText(dateTextField.text);
    8. sqliteModel.searchUserNameText(userNameTextField.text);
    9. }
    10. }
    11. }
    To copy to clipboard, switch view to plain text mode 

    (?) I did the same for my dbConnect and sqlSelect fcns however I have to include Q_INVOKABLE when intializing them in the header file or for some reason or I cant call them in QML with out the Q_INVOKABLE keyword but my searchDateText & searchUserNameText fucntions do??? -> error: Property 'dbConnect' of object sqliteModel() is not a function

    I would like to pass the QML text using a QML signal to a CPP slot using the QObject::connect() mainly for learning purposes... The objects that I need to pass the connect() method make more sense now, I need to pass a QML object for the qml signal() and pass a class object (sqliteModel) for the slot(), if I use the connect() method in my cpp class (in the constructor) I can use keyword "this" for the CPP object for the connect method?
    Last edited by jfinn88; 26th August 2016 at 23:26.

  10. #9
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: using an isntance of QSqlDatabase for connection defiinition

    Quote Originally Posted by jfinn88 View Post
    Like to be able to search by date and userName... I want to pass text values back to my c++ function a would like to use the signal and slot mechanism to perform this action. However I get lost with what Object I need to pass the QObject::connect() method, for it to work.
    I created two signals and two slots one for the date text field in qml and the other is for the userName text field in qml.
    in C++ I created to slots to receive the qml signals and to out put the text data passed to the console using a debug() method.
    I'm little confused on where to place the QObject::connect method in my project... main.cpp or sqliteModel.cpp in the constructor ?
    I am unsure what objects to pass the connect() method for the signal to receive the slot ?
    You just call the slots directly.
    Slots, like Q_INVOKABLE methods, can be called from QML.

    Your QML code suggests that you want to pass both date and user name when clicking search, so a single slot with two arguments will do.

    Quote Originally Posted by jfinn88 View Post
    I would also Like to create a table in the database for each separate day for user event logging and delete old tables after 30 days
    here is my code: (had to remove functions for model in cpp file to get it to fit)
    I guess you have two options:
    - use an additional table that maps from a date to a table name for that date
    - encode the date in the table name

    Quote Originally Posted by jfinn88 View Post
    I was able to pass the text form qml to my cpp slot by expose Qt slot to QML element. By using the context property I set for my model to be exposed to QML.
    Yes, exactly, though you probably want to use a single method if both inputs are to be used in the search.

    Quote Originally Posted by jfinn88 View Post
    (?) I did the same for my dbConnect and sqlSelect fcns however I have to include Q_INVOKABLE when intializing them in the header file or for some reason or I cant call them in QML with out the Q_INVOKABLE keyword but my searchDateText & searchUserNameText fucntions do??? -> error: Property 'dbConnect' of object sqliteModel() is not a function
    They have to be slots or Q_INVOKABLE.

    From the QML side's point of view there is actually no difference.
    It is customary though to use Q_INVOKABLE when methods return something, as slots usually don't do that.

    In your case all methods you have so far could be slots.

    Quote Originally Posted by jfinn88 View Post
    I would like to pass the QML text using a QML signal to a CPP slot using the QObject::connect() mainly for learning purposes...
    I would advise against that, you would put effort into learning something that you then don't want to use.
    I.e. you don't want your C++ code to be dependent on specific QML objects or their specific signals.

    Quote Originally Posted by jfinn88 View Post
    The objects that I need to pass the connect() method make more sense now, I need to pass a QML object for the qml signal() and pass a class object (sqliteModel) for the slot()
    Yes, but you really don't want to do that.

    Quote Originally Posted by jfinn88 View Post
    if I use the connect() method in my cpp class (in the constructor) I can use keyword "this" for the CPP object for the connect method?
    Theoretically yes, but the QML scene has not been loaded yet when the model's constructor runs, so the connect would have to happen from outside after both model and QML objects exist.

    Cheers,
    _

Similar Threads

  1. Replies: 16
    Last Post: 4th September 2013, 00:49
  2. How to set x509 on a QSqlDatabase Connection?
    By m3rlin in forum Qt Programming
    Replies: 24
    Last Post: 21st February 2012, 04:04
  3. Windows OCI QSqlDatabase connection
    By hollyberry in forum Newbie
    Replies: 10
    Last Post: 13th February 2012, 22:13
  4. QSqlDatabase Connection Close on Destruction
    By Sanuden in forum Qt Programming
    Replies: 1
    Last Post: 1st September 2011, 15:32
  5. QSqlDatabase connection timeout?
    By joseprl89 in forum Qt Programming
    Replies: 6
    Last Post: 27th March 2011, 01:43

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.