PDA

View Full Version : Qt View adds empty rows



RaymondMcEvilly
25th June 2012, 10:48
Hi,

I am quite new to Qt programming. So please bare with me. I have a simple application that connects to a database using a QSQLRelationalTableModel. A QTableView is used to display the data in the model. Running the application works perfectly. The amount of rows in the table view is exactly the same as the amount of records in the model.

Now, when a new filter is applied on the model (using setFilter()) and calling select() again, the table is updated as it should, i.e. the new data is displayed in the table. The problem is, extra empty rows are added to the bottom of the table. The amount of rows that are "added" is exactly the same amount of rows that were previously in the table, i.e. before a new filter was applied. Thus it seems as if the previous data is removed out of the cells, the empty rows are kept, and the new rows are added on top of the old rows.

How can I get rid of these empty rows quick and simple? I have been looking everywhere for a function that will sort of reset the view to only display the data in the model (and to remove any old rows).

Some code:

#include "studentmainwindow.h"
#include "ui_studentmainwindow.h"
#include "QDebug"


StudentMainWindow::StudentMainWindow(QString userID, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::StudentMainWindow)
{
this->userID = userID;
ui->setupUi(this);
ui->userNameLabel->setText(userID);

connectToDatabase();
updateComboBox();

databaseModel = new QSqlRelationalTableModel(this);
ui->databaseView->setModel(databaseModel);

updateView(ui->subjectsComboBox->currentText());

connect(ui->subjectsComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateView(QString)));
}

void StudentMainWindow::connectToDatabase(){
database = QSqlDatabase::addDatabase("QMYSQL");
database.setHostName("127.0.0.1");
database.setDatabaseName("studentmanagement");
database.setUserName("root");
database.setPassword("");
}


void StudentMainWindow::updateComboBox(){
if (!database.open()){
connectToDatabase();
}

QSqlQuery query;
QStringList subjects;
if (query.exec("SELECT * FROM subject")){
while(query.next()){
subjects.append(query.value(1).toString());
}
ui->subjectsComboBox->addItems(subjects);
}else {
QMessageBox::critical(this, "SQL Error", "Could not retrieve subjects: </br>" + database.lastError().text(), QMessageBox::Ok);
}
query.clear();
}

void StudentMainWindow::updateView(QString subject){
if (database.open()){
databaseModel->setTable("marks");
databaseModel->setFilter("marks.studentID = '" + userID + "' AND marks.subjectID = (SELECT subject.subjectID FROM subject WHERE subject.subjectName = '" + subject + "')");
databaseModel->select();
qDebug() << databaseModel->rowCount();
}else {
QMessageBox::critical(this, "Error Connecting", "Error Connecting to Database: </br>" + database.lastError().text(), QMessageBox::Ok);
}
}

wysota
25th June 2012, 11:06
Show us some code.

Hardtobenormal
22nd February 2013, 03:24
I am having a similar issue.




--- mainwindow.cpp ----

this->drive_ = new Drive(driveName, this);
this->ui->tableView->setModel(this->drive_);
this->ui->treeView->setModel(this->drive_->tagTree_);

QObject::connect(this->ui->treeView,SIGNAL(clicked(const QModelIndex&)),
this,SLOT(recalculate()));
QObject::connect(this->ui->treeView,SIGNAL(viewReleased()),
this->ui->tableView,SLOT(reset()));
QObject::connect(this->ui->treeView,SIGNAL(viewReleased()),
this->ui->tableView,SLOT(scrollToTop()));

... unrelated code ...

void MainWindow::recalculate() {
QModelIndexList selection = this->ui->treeView->selectionModel()->selectedIndexes();
this->drive_->recalculate(selection);
}



--- drive.cpp ----

int Drive::rowCount(const QModelIndex &parent) const {
return results_.size();
}



recalculate() is called whenever a new item in the treeView is clicked. It changes the underlying model for the tableView at which point its reset() and scrollToTop() slots are called.

Say, for example, there are 25 items in the view before recalculate is called. If the result of the recalculation has 5 items, the tableView will show the information for the 5 items in the model and 20 empty rows. Apparently the reset doesn't remove those rows. Is there any way for these rows to be removed?

rowCount() is defined as the size of the set of results returned by a recalculation.

Thanks!

ChrisW67
22nd February 2013, 05:48
If your custom model does not emit the relevant signals when adjusting the row count then the view has no way to know the row count has changed. Since we cannot see your custom model code we are hard pressed to see the errors.

You are resetting the view not the model, so only the selections, current item and visual position of the view are changed. This does not cause the view to assume the row or column count has changed.

Hardtobenormal
24th February 2013, 04:10
Thanks for the help! My implementation of recalculate() in drive never called beginInsertRows(), endInsertRows(), beginRemoveRows() or endRemoveRows() so, like you had said, the view never knew that there was a change in the number of rows.