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
    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,
    _

  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

    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.

  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

    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,
    _

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

    jfinn88 (26th August 2016)

  5. #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

    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.

  6. #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
    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.