[SOLVED] QCombobox + QSqlQueryModel



  • Hi guys,

    I'm making a simple database application and want to do filtering on combo boxes.

    I have a products table and a modules table having a foreign key field pointing to products id column; finally I have a features table having a foreign key field pointing to modules id column; nothing fancy:
    @
    +------------------------+
    | Products |
    +------------------------+
    |id | name | description |
    +------------------------+

    +-------------------------------------+
    | Modules |
    +-------------------------------------+
    |id | productsid | name | description |
    +-------------------------------------+

    +-------------------------------------+
    | Features |
    +-------------------------------------+
    |id | modulessid | name | description |
    +-------------------------------------+@

    Then I have a form for entering the features. This form has 2 combo boxes, one for products and one for modules and I want to show only the modules that belong to a product.

    For this I have database manager class returning QSqlQueryModel pointer for both products and modules:

    @QSqlQueryModel* CDatabaseManager::productsQueryModel()
    {
    if (m_pProductsQueryModel == NULL)
    {
    m_pProductsQueryModel = new QSqlQueryModel(this);
    }

    m_pProductsQueryModel->setQuery("SELECT * FROM products");

    return m_pProductsQueryModel;
    }

    QSqlQueryModel* CDatabaseManager::modulesQueryModel()
    {
    if (m_pModulesQueryModel == NULL)
    {
    m_pModulesQueryModel = new QSqlQueryModel(this);
    }

    m_pModulesQueryModel->setQuery("SELECT * FROM modules");

    return m_pModulesQueryModel;
    }@

    I set both those pointers to the QComboBox objects and everything displays nicely except that I only want to see the modules assigned to a product.

    On the products combox box, I have a slot called when the current index of Products combo box is triggered. I get the selected product ID from the resultset and trigger a signal for the database manager to update the modules query and select only the items having the correct product ID in the second column.

    Simpler, in code that gives:

    @void AddFeatureDialog::on_productsCombobox_currentIndexChanged(int index)
    {
    QModelIndex id = ui->productsCombobox->model()->index(index, 0);
    m_nProductId = id.data().toInt();
    emit currentProductSelChanged(m_nProductId);
    }

    void CDatabaseManager::onCurrentProductSelChanged( int _nProductId )
    {
    bool bRet = false;
    if (m_db.isOpen())
    {
    QSqlQuery query;
    bRet = query.prepare("SELECT * FROM modules WHERE productid=:productid");
    query.bindValue(":productid", _nProductId);
    m_pModulesQueryModel->setQuery(query);

        if (bRet)
        {
            // How do I update the model
        }
        else
        {
            QSqlError err = query.lastError();
            //... 
        }
    }
    

    }@

    The form is simply a modal dialog:
    @void MainWindow::on_action_Feature_triggered()
    {
    AddFeatureDialog dlg;
    dlg.setProductsModel((QAbstractItemModel*)m_pDatabase->productsQueryModel());
    dlg.setModulesModel((QAbstractItemModel*)m_pDatabase->modulesQueryModel());

    connect(&dlg, SIGNAL(currentProductSelChanged(int)), m_pDatabase, SLOT(onCurrentProductSelChanged(int)));
    
    if (dlg.exec() == QDialog::Accepted)
    {}
    

    }@

    The problem here is that according to the documentation doing a setQuery() on the model should be enough to update the view. In my case the combox box gets cleared and remains empty. If within the slot I set a original query, the combo box gets empty; if I set the filter query from the form class (which I wouldn't like to do), the combo gets empty too.

    What am I doing wrong?

    Cheers,



  • Could you also post the section where you populate the combobox?



  • Well that was easy thanks to my colleague =)

    In the slot taking care of filtering

    @QSqlQuery query;
    bRet = query.prepare("SELECT * FROM modules WHERE productid=:productid");
    query.bindValue(":productid", _nProductId);
    m_pModulesQueryModel->setQuery(query);@

    becomes:
    @QSqlQuery query;
    bRet = query.prepare("SELECT * FROM modules WHERE productid=:productid");
    query.bindValue(":productid", _nProductId);
    query.exec(); // <--------- Add exec or it won't work
    m_pModulesQueryModel->setQuery(query);@

    So what the documentation does not stipulate is that exec must be called prior to setting the query.

    Tim, the combox box is automatically populated by the model / view architecture. Practically the only things required are to set a valid query to a QXmlQueryModel object and set that same QXmlQueryModel object to the QComboBox object using setModel.

    Cheers,


Log in to reply
 

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