QSqlTableModel Read only



  • I use QSqlTableModel to access a DB2 remote database. It works well.

    I would like to restrict access to Read Only but I can't find how. I would like to lock the tableview or lock the database connection.

    I tried also this command without any success. No error but I can modify the datas inside the table.

    @
    db = QSqlDatabase::addDatabase("QDB2","db2db");
    db.setConnectOptions("SQL_ATTR_ACCESS_MODE=SQL_MODE_READ_ONLY");
    @

    And I found no parameter in QSqlTableModel to lock the view in Read Only mode.


  • Lifetime Qt Champion

    Hi,

    You can use a QSqlQueryModel then, it's the read-only base of QSqlTableModel

    Hope it helps



  • It works in read only when I modify my code like you said:

    @
    model = new QSqlQueryModel(this);
    model->setQuery(QString("SELECT * FROM tablexyz"), db);
    ui->tableView->setModel(model);
    ui->tableView->resizeColumnsToContents();
    ui->tableView->horizontalHeader()->setSectionsClickable(true);
    ui->tableView->horizontalHeader()->setSectionsMovable(true);
    ui->tableView->setSortingEnabled(true);
    ui->tableView->show();

    @

    But... I lose sorting! I saw arrows when I click on the header field but no sort is done.

    And scrolling in the tableview react a little bit slowly... (my db is remote on internet and big for some tables, 26 000 rows... but even small tables with 25 rows are slow.).


  • Lifetime Qt Champion

    You can use a QSortFilterProxyModel



  • Ok I tried this:

    @
    model = new QSqlQueryModel(this);
    model->setQuery(QString("SELECT * FROM tablexyz), db);
    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    ui->tableView->setModel(proxyModel);

    @

    I have sorting. But for a query of 25 rows (of 40 columns) it's slow... about 2 seconds for sorting. QSqlTableModel was faster... (but not read only :(


  • Lifetime Qt Champion

    Then subclass QSqlTableModel, reimplement flags to ensure items are not editable and setData to do nothing, then you should be good to go



  • This thread is a little ridiculous.

    I don't know why you'd do, or even suggest, any of the things here, like subclassing models and stuff.

    Just turn off the edit triggers in your table view. You can do it in designer (set the edit triggers to NoEditTriggers), or in code:

    myTableView->setEditTriggers(QTableView::NoEditTriggers);


  • @mnbv While it's the fastest solution this does not prevent another view to modify the model. To make the model read-only regardless of the implementation of the view attached to it, reimplement flags() and setData() as suggested above.

    If you are still not convinced imagine if you are writing a library and your model can be accessed via a public method of your class. You would have no control on the edit triggers of the view so the subclassing and reimplementation is the only way

    P.S.
    You could aso use a QIdentityProxyModel subclass reimplementing the same methods to have a more general solution that you can apply to many models:

    #include <QIdentityProxyModel>
    class ReadOnlyProxy : public QIdentityProxyModel{
        Q_OBJECT
        Q_DISABLE_COPY(ReadOnlyProxy)
    public:
        explicit ReadOnlyProxy(QObject* parent = nullptr)
            :QIdentityProxyModel(parent)
        {}
        virtual ~ReadOnlyProxy() = default;
        virtual Qt::ItemFlags flags(const QModelIndex &index) const override {
            return QIdentityProxyModel::flags(index) & (~Qt::ItemIsEditable);
        }
        virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override {
            Q_UNUSED(index)
            Q_UNUSED(value)
            Q_UNUSED(role)
            return false;
        }
    };
    
    

Log in to reply
 

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