Empty qsqlrelationaltablemodel - c++

When I put model->select(); after relations, the model is empty, when I put it back before relations, the table displays correctly, but when I edit any cell the whole row becomes empty and gets "!" on the left. No errors.
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this, db1);
model->setTable("syllabi");
model->setEditStrategy(QSqlTableModel::OnFieldChange);
model->select();
model->setRelation(3, QSqlRelation("activity_types", "activity_type_id", "activity_type_name"));
model->setRelation(0, QSqlRelation("teachers", "teacher_id", "teacher_name"));
//model->select();
qDebug() << model->lastError();
ui->tableView->setModel(model);
ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));
ui->tableView->horizontalHeader()->setStretchLastSection(true);
ui->tableView->setColumnHidden(9, true);

Related

How to select next row automatically in Qt tableView whenever a pushbutton is pressed?

I have a Qt tableView that loads the data from the SQLite database and I have configured it in such a way that in the default view, the first row is automatically selected and I can execute a query on that row by pressing a button-'Present'. Now, I want my program to automatically select the next row after I pressed the 'button' for the first time so that the when I press 'Present' for the second time, the query is executed on the second row. So, basically, I want to change the selection of row whenever a button is pressed until the end of row numbers is reached.
I have searched quite a few sites for the solution, but I could not get the one for my problem.
Code for viewing table s_info and selecting the first row as default.
void table::on_view_clicked()
{
MainWindow conn;
QSqlQueryModel * modal = new QSqlQueryModel();
conn.connOpen();
QSqlQuery* qry= new QSqlQuery(conn.info);
qry->prepare("Select Name,Roll_No from s_info order by Roll_no");
qry->exec();
modal->setQuery(*qry);
ui-> tableView ->setModel(modal);
ui->tableView-> setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->selectRow(0);
ui->tableView->setFocus();
conn.connClose();
qDebug()<< (modal->rowCount());
}
Code for the execution of a query when a button name 'Present' is clicked.
Note that I have performed query execution based on Column Roll_No in my s_info table and index of Roll No for the 1st row is(0,1)
void table::on_present_clicked()
{
QAbstractItemModel *model = ui->tableView->model();
QModelIndex index = model->index(0,1);
QString roll= (index.data().toString());
MainWindow conn;
conn.connOpen();
QSqlQuery qry;
QSqlTableModel modal;
qry.prepare("Update s_info set Present_Days=Present_Days + 1 where
Roll_No='"+roll+"'");
qry.exec();
conn.connClose();
}
I expect that when I click a Present for the second time, the row selection is shifted to the second row and the query is executed on that row. I want this to occur until I reached the end of the number of rows.
The following example illustrates what you are going to achieve. The key-point is that you are going to need an QItemSelectionModel, which manages you selection. Very often one forgets to explicitly set the model of the QItemSelectionModel being the model of the view.
Now, if you will select one row in an table view the next button will select the next row. Selecting the next row basically means to select all columns in the next row.
It shouldn't matter if you are using something like an QSqlTableModel the usage should be simply the same.
#include <QApplication>
#include <QTableView>
#include <QPushButton>
#include <QHBoxLayout>
#include <QStandardItemModel>
#include <QItemSelectionModel>
int main(int argc, char** args) {
QApplication app(argc, args);
auto frame = new QFrame;
frame->setLayout(new QHBoxLayout);
auto tableView = new QTableView;
tableView->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
tableView->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);
auto model = new QStandardItemModel;
tableView->setModel(model);
auto selectionModel = new QItemSelectionModel;
selectionModel->setModel(model);
tableView->setSelectionModel(selectionModel);
frame->layout()->addWidget(tableView);
auto button = new QPushButton("Next");
frame->layout()->addWidget(button);
model->setRowCount(10);
model->setColumnCount(10);
frame->show();
QObject::connect(button, &QPushButton::clicked, [&]()
{
auto indices = selectionModel->selectedIndexes();
if (indices.isEmpty()) return;
QModelIndexList empty;
selectionModel->select(QModelIndex(), QItemSelectionModel::SelectionFlag::Clear);
for (auto index : indices)
{
auto newIndex=index.sibling(index.row() + 1, index.column());
selectionModel->select(newIndex,QItemSelectionModel::SelectionFlag::Select);
}
});
app.exec();
}

Add items to columns in QStandardItemModel

I am currently adding rows to my QTableView as such
QStandardItem* itm;
QStandardItemModel* model = new QStandardItemModel(this);
model->setColumnCount(2);
model->appendRow(new QStandardItem("Some Text in Column1");
How do I add items to column 2 dynamically by appending?
In the above example column 2 is empty. How do I add item to column 2?
Calling appendRow(QStandardItem *) only adds a single item to the first column. You would need to pass in a QList to appendRow() to add items to each column, e.g.:
QList<QStandardItem *> items;
items.append(new QStandardItem("Column 1 Text"));
items.append(new QStandardItem("Column 2 Text"));
QStandardItemModel* model = new QStandardItemModel(this);
model->setColumnCount(2);
model->appendRow(items);
See http://doc.qt.io/qt-5/qstandarditemmodel.html#appendRow for more detail.

How to fill database sqlite tablewidget

I am writing "SQLite" database and I create the database table like this:
void MainWindow::createdata()
{
QSqlQuery query;
query.exec("DROP TABLE messages");
query.exec("CREATE TABLE messages("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"IPAddress VARCHAR(20),"
"date VARCHAR(10),"
"message VARCHAR(30))");
query.prepare("INSERT INTO messages(IPAddress, date, message) values(?,?,?)");
query.addBindValue("192.168.1.1");
query.addBindValue("jun 3 2016");
query.addBindValue("hello");
if (query.exec()) {
qDebug() << "ok!";
}
else
{
qDebug() << query.executedQuery();
qDebug() << query.lastError();
}
}
And i create "qtablewidget" like this:
QTableWidget* table = new QTableWidget();
table->setRowCount(10);
table->setColumnCount(4);
table->setWindowTitle("Received Message");
table->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
table->setHorizontalHeaderLabels(QString("ID;HostAddress;Date;Message").split(";"));
table->setStyleSheet("QTableView {selection-background-color: blue;}");
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
table->setSelectionBehavior(QAbstractItemView::SelectRows);
table->setSelectionMode(QAbstractItemView::SingleSelection);
QSqlQuery query("SELECT * FROM messages");
but i don't know how should i fill the "tablewidget" to show with query.
Can anyone please help me?Thanks
You should use QTableView (Model based version of table view) and then using QSqlQueryModel, you can populate your table.
QSqlQueryModel *model = new QSqlQueryModel();
model->setQuery(query);
tableView->setModel(model);
To use QSqlQueryModel with a QTableWidget, you should iterate through QSqlQueryModel row by row and add them to your QTableWidget.
QSqlQueryModel *model = new QSqlQueryModel();
model->setQuery(query);
int i;
QSqlRecord row
for(i = 0, row = model->record(i); !row.isEmpty(); i++, row = model->record(i)){
// Get each field using `value` method of variabale 'row'
// and insert this fields to its corresponding cell in QTableWidget
}
Relevant Question:
Setting the model to a QTableWidget

How to make a column of a table editable?

I'm trying to make a table that will allow a user to enter a mark out of 10 given some criteria. I'm connected to my SQLite database and retrieving a column on the left for the description of the criteria, and a column on the right where I want to be able to enter a grade (an editable column). Here is my code:
QSqlQueryModel *model = new QSqlQueryModel();
QSqlQuery* qry = new QSqlQuery(conn.mydb);
qry->prepare("select I.itemDescription, S.grade from Items I, ItemsToStudent S where I.itemID = S.itemID and I.rubricID = ? and S.courseID = ? and S.studentID = ?");
qry->addBindValue(actid);
qry->addBindValue(courseid);
qry->addBindValue(studentid);
qry->exec();
model->setQuery(*qry);
ui->rubricTable->setModel(model);
However, I can't make the second column editable. How would I go about accomplishing this?
The QSqlQueryModel class provides a read-only data model for SQL result sets. You can use QSqlRelationalTableModel like:
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this,conn.mydb);
model->setEditStrategy(QSqlTableModel::OnFieldChange);
model->setJoinMode(QSqlRelationalTableModel::LeftJoin);
model->setTable( "Items" );
model->setRelation( 0, QSqlRelation( "ItemsToStudent", "itemID", "grade" ) );
model->setFilter( QString("rubricID = ? and courseID = ? and studentID = ?") );
model->select();
model->setHeaderData( 1, Qt::Horizontal, tr("Criteria") );
model->setHeaderData( 2, Qt::Horizontal, tr("Grade") );
ui->rubricTable->setModel(model);
You can also hide the columns you don't want to show like:
ui->rubricTable_tbl->hideColumn(3);

Retrieving a QStandardItem through QStandardItemModel by searching or key

Is there any way to assign a unique key to an entry in a QStandardItemModel so that we can check for the presence of that key. If it is present we get the relevant QstandardItem ?
Update:
Here is what I am trying to do. I have 3 column in my table so so i have 3 QStandardItem.
This is the code I am using:
QStandardItem* item0 = new QStandardItem("Column1");
QStandardItem* item1 = new QStandardItem("Column2");
QStandardItem* item2 = new QStandardItem("Column3");
Now my model is called model and I am attaching these to my model as such
moddel->setItem(0,0,item0);
moddel->setItem(0,1,item1);
moddel->setItem(0,2,item2);
I need to assign a row some unique key so that I could check the model for that key and the model would return the row number. Any suggestions.
You could use the setData function of QStandardItem in order to set a custom key for a user defined role, eg
#define MyRole Qt::UserRole + 2
myItem->setData(Qvariant(key), MyRole)
You can get the data of any index in your model by using the data call.
QVariant d = mymodel->data(anindex, MyRole)
Writing a function that checks if a key exists should be straight forward.
The answer by pnezis addresses the storing of a key but not the accessing of a QStandardItem from the model. I addressed the storing of data with a QStandardItem by sub classing QStandardItem as I needed to store a lot of complex data.
To obtain the QStandardItem from the model you need to create a QModelIndex instance with the row/column and then call itemFromIndex(index)
on the model.
My example is taken from a selection callback.
QModelIndex& selectedItem = itemsSelected.front();
QStandardItemModel* model = reinterpret_cast<QStandardItemModel*>(tableView->model());
if (nullptr == model)
return;
QStandardItem *item = model->itemFromIndex(selectedItem);
if (nullptr == item)
return ;