QSqlQueryModel to QStandardItemModel?



  • I'm trying to move all the data from a QSqlQueryModel to a QStandardItemModel. Is this possible? If show how?

    Reason: I need to have two QTableViews show two separate sets of data from an SQL db. So far I have not been able to do this.

    So far, when I create one QSqlQueryModel 1 and fill it with data, and then create a second QSqlQuerymodel 2 and fill it with data, The first QSqlQueryModel 1 data gets lost.



  • @Core2
    Huh? If you have 2 separate views and 2 separate tables you shouldn't have any problems or be "losing" any data. You don't want to have to use standard models if what you have & want is SQL query models. Clarify or show code?



  • @JonB

    Hello thank for the response.

    EDIT: i'm going to have to respond in parts. my post is flagged as spam. yay.

    Part 1

    The following code is my current setup:
    mainwindow.h

    ifndef MAINWINDOW_H
    define MAINWINDOW_H
    
    include <QMainWindow>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
    };
    
    endif // MAINWINDOW_H
    


  • @JonB

    Part 2

    main.cpp

    include "mainwindow.h"
    include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    mainwindow.cpp

    include "mainwindow.h"
    include "ui_mainwindow.h"
    include "animalsearch.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        AnimalSearch animalsearch;
        animalsearch.setModal(true);
        animalsearch.exec();
    }
    
    


  • @JonB

    Part 3
    animalsearch.h

    #ifndef ANIMALSEARCH_H
    #define ANIMALSEARCH_H
    
    #include <QDialog>
    #include <QtSql>
    #include <QStandardItemModel>
    
    namespace Ui {
    class AnimalSearch;
    }
    
    class AnimalSearch : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit AnimalSearch(QWidget *parent = 0);
        ~AnimalSearch();
        QSqlQueryModel *PreviousSearchModel;
        QSqlQueryModel *SearchModel;
        QStandardItemModel *TestModel;
    
    private slots:
        void on_OkButton_clicked();
        void on_SearchButton_clicked();
        void on_pushButton_clicked();
    
    private:
        Ui::AnimalSearch *ui;
    };
    
    #endif // ANIMALSEARCH_H
    


  • @JonB

    Part 4

    Edit remove trailing " from sqlconnect.h

    animalsearch.cpp

    //trust me the syntax is correct in the actual file
    include animalsearch.h
    include ui_animalsearch.h
    include sqlconnect.h
    include QDebug
    include QStandardItemModel
    
    AnimalSearch::AnimalSearch(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::AnimalSearch)
    {
        ui->setupUi(this);
    
        //Create an object named PreviousSearch
        sqlconnect PreviousSearch;
        qDebug() << "PreviousSearch Object:";
        qDebug() << "Type of PreviousSearch: " << typeid(PreviousSearch).name();
        QString uname = qgetenv("USER");
        if (uname.isEmpty())
            uname = qgetenv("USERNAME");
        qDebug() << "Type of uname: " << typeid(uname).name();
        qDebug() << "Address of uname: " << &uname;
        QString GetAutoComplete = "some query to return data";
        qDebug() << "Output of PreviousSearchModel in Ui Setup: " << PreviousSearchModel;
        qDebug() << "Address of PreviousSearchModel in Ui Setup: " << &PreviousSearchModel;
        this->PreviousSearchModel = new QSqlQueryModel();
        qDebug() << "Type of PreviousSearchModel: " << typeid(PreviousSearchModel).name();
        PreviousSearchModel = PreviousSearch.QueryDB(GetAutoComplete);
        ui->PreviousSearchTableView->setModel(PreviousSearchModel);
        ui->SearchTableView->setModel(PreviousSearchModel);
        qDebug() << PreviousSearchModel;
        qDebug() << "\n";
    }
    
    AnimalSearch::~AnimalSearch()
    {
        delete ui;
    }
    
    void AnimalSearch::on_OkButton_clicked()
    {
        close();
    }
    
    void AnimalSearch::on_SearchButton_clicked()
    {
        sqlconnect CurrentSearch;
        qDebug() << "The Address of CurrentSearch Object: " << &CurrentSearch;
        QString SearchQuery = "somequery to return data'";
        this->SearchModel = new QSqlQueryModel();
        SearchModel = CurrentSearch.QueryDB(SearchQuery);
        ui->SearchTableView->setModel(SearchModel);
        qDebug() << "The Address of PreviousSearchModel Object after SearchButton_Clicked(): " << &PreviousSearchModel;
    
    }
    
    void AnimalSearch::on_pushButton_clicked()
    {
       //if this line wasn't here the code crashes, at some qsql_odbc.cpp line.
        ui->PreviousSearchTableView->setUpdatesEnabled(false);
    
        int Columns = PreviousSearchModel->columnCount();
        int Rows = PreviousSearchModel->rowCount();
        qDebug() << "Number of Rows: " << Rows;
        qDebug() << "Number of Columns: " << Columns;
        this->TestModel = new QStandardItemModel(Rows, Columns);
        for(int row = 0; row < Rows; ++row) {
            for(int column=0; column < Columns; ++column) {
                //QStandardItem *item = PreviousSearchModel->data(PreviousSearchModel->index(row,column));
                //TestModel.setItem(row, column, item);
                //for fun output all contents of PreviousSearchModel to screen
                qDebug() << PreviousSearchModel->data(PreviousSearchModel->index(row, column)).type();
                qDebug() << PreviousSearchModel->data(PreviousSearchModel->index(row, column)).toString();
                //ui->PreviousSearchTableView->setModel(PreviouSearchModel);
            }
        }
    }
    


  • @JonB

    Final Part, 5

    sqlconnect.h

    //again trust me syntax is correct in actual file
    ifndef SQLCONNECT_H
    define SQLCONNECT_H
    include <QString>
    include <QtSql>
    
    class sqlconnect
    {
    
    public:
        QSqlDatabase db;
        QSqlQueryModel *QueryModel;
    
        int Test(QString Test)
        {
            qDebug() << "Did this class test print?";
            return 0;
        }
    
        QSqlQueryModel* QueryDB(QString Query)
        {
             db = QSqlDatabase::addDatabase("QODBC");
             db.setDatabaseName("someDB");
             db.setUserName("SomeUser");
             db.setPassword("12345");
             //Create a new QSqlQueryModel using 
             this->QueryModel = new QSqlQueryModel();
             qDebug() << "Address of QueryModel: " << &QueryModel;
             if(db.open())
             {
                 //Execute the query and store data in QueryModel
                 QueryModel->setQuery(Query);
             }
             else
             {
                 qDebug() << "DB not connected";
             }
             return QueryModel;
        }
        int closeDB()
        {
            db.close();
            QSqlDatabase::removeDatabase("SomeDB");
            return 0;
        }
    };
    
    #endif
    
    

    The program crashes if you click the pushbutton a second time and the code tries to dump the PreviousSearchModel to the screen. It fails at this line, qDebug() << PreviousSearchModel->data(PreviousSearchModel->index(row, column)).type(); found in the animalsearch.cpp
    with exception code: 0xc0000005: read access violation at : 0x0

    in the animalsearch ui:
    0_1523550142640_animalsearch_ui.png



  • @Core2

    include sqlconnect.h"

    [In Part 4] Can you just please remove that trailing " right now so that I can see the rest of my code without my eyes hurting, please? :)



  • @JonB

    done:) I have to remove the # and some times the " and <> to get Askimet off my back.



  • @Core2 said in QSqlQueryModel to QStandardItemModel?:

    to get Askimet off my back.

    In these cases posting the code to https://pastebin.com/ and only sharing the link might help

    As of the matter at hand:
    from http://doc.qt.io/qt-5/qsqldatabase.html#addDatabase

    Warning: If you add a connection with the same name as an existing connection, the new connection replaces the old one. If you call this function more than once without specifying connectionName, the default connection will be the one replaced.

    Do not call addDatabase every time you use QueryDB use:

    // you should never have QSqlDatabase as a member of the class, read QSqlDatabase docs
    QSqlDatabase db = QSqlDatabase::database("MyDatabase", false);
    if (!db.isValid()) {
                db = QSqlDatabase::addDatabase("QODBC", "MyDatabase");
                db.setDatabaseName("someDB");
             db.setUserName("SomeUser");
             db.setPassword("12345");
            }
            if (!db.isOpen()){
            if (db.open())
               QSqlQueryModel* tempModel= new QSqlQueryModel();
    tempModel->setQuery(Query);
    return tempModel;
    }
    qDebug() << "DB not connected";
    

    P.S.
    The view does not own the model so you are leaking it. call setParent on the returned model



  • @Core2
    I'm not used to looking through loads of other peoples' code to debug it, plus I use Python/PyQt not C++, so quite a bit would be different.

    Having said that, in the nicest way your code & approach is all over the place! :) I don't really understand what you're trying to do and how you're approaching achieving it. But I don't think it can be right.

    I suspect your crash comes down to your class sqlconnect and how you use it. It creates and holds a connection to a database (QSqlDatabase) and a corresponding QSqlQueryModel. Its scope is limited to one invocation of MainWindow::on_pushButton_clicked() and its AnimalSearch animalsearch. If it's clicked a second time, and during that it tries to do something (like via a Table View) which refers to a model which was created "previously" using a "previous" sqlconnect it will have gone out of scope. I suspect that will be the cause of the eror.

    I can see @VRonin has already posted. The most important thing is to start by redesigning your code so that you only do the db = QSqlDatabase::addDatabase("QODBC"); once, and use that for all queries/models/views. Your whole QueryDB needs redesigning.

        this->SearchModel = new QSqlQueryModel();
        SearchModel = CurrentSearch.QueryDB(SearchQuery);
    

    This leaks a QSqlQueryModel. It news one, then overwrites the result with another one. You have this pattern all over the place.



  • @VRonin @JonB

    Thank you both for looking through my code. I will be looking into what each of you have advised and applying it in my code.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.