QTableWidget with setItem cannot access the data in the tablewidget - c++

void IdListForTrain::SetListIdInList(QStringList IdList)
{
QTableWidgetItem *item=nullptr;
for(int index=0;index<IdList.count();index++)
{
ui->Id_tableWidget->insertRow(index);
for(qint32 columnIndex=0;columnIndex<=1;columnIndex++)
{
item = new QTableWidgetItem;
if(columnIndex==0)
{
ui->Id_tableWidget->setItem(index,columnIndex,item);
item->setText("00:00:00");
}
if(columnIndex==1)
{
ui->Id_tableWidget->setItem(index,columnIndex,item);
item->setText(IdList.at(index));
}
QString tmp1 = ui->Id_tableWidget->item(index,1)->text();
QString tmp = item->text();
}
}
}
Hi! I am new to Qt and I'm facing a problem. I was asked to create a tablewidget with the effective date of train Ids in one column and the names of the trains in another column,I did this code to the best of my knowledge but I can't set or access the data in the widget in the line eventhough the code doesnt give any errors but it crashes everytime I open the application window at this line,
QString tmp1 = ui->Id_tableWidget->item(index,1)->text();
I'm not sure what the reason is.

Let look at first iteration - index=0 and columnIndex=0.
You go through if(columnIndex==0) condition and set item to
QTableWidget's row = 0 (index) and column = 0 (columnIndex)
Second condition skipped
You try to access item at row = 0 (index) and column = 1 with code QString tmp1 = ui->Id_tableWidget->item(index,1)->text();. But at this time you have no item assigned to that column
That's all!

Related

How to get a specific cell when row is clicked in my qtableview

I am working with a qtableview that is filled by a model and has two columns. I can get the contents of a selected cell no problem but only want the contents of the second column even if the first column is clicked.
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
QString cellText;
if (index.isValid()) {
cellText = index.data().toString();
}
ui->lineEdit->setText(cellText);
}
the index looks like this for column 0:
QModelIndex(7,0,0x55f2e5d06b00,QStandardItemModel(0x55f2e5d09740))
And for column 1:
QModelIndex(8,1,0x55f2e5d06b00,QStandardItemModel(0x55f2e5d09740))
I tried to find a way to change the index for the cell that is clicked but I think there is no way to change it directly and I can not seem to find a way to tell my function to always use column 1 the second column.
Thanks for your time.
Code edited to reflect comment 1 below
{
QString cellText;
if (index.isValid()) {
QModelIndex idx = index;
idx = idx.sibling(idx.row(), 1);
cellText = idx.data().toString();
}
ui->lineEdit->setText(cellText);
}```

Always show a QComboBox in a cell of a QTableView

I have a QTableView with an associated model. I want to have a QComboBox in each cell of the third column.
I used a QItemDelegate as shown in this page : https://wiki.qt.io/Combo_Boxes_in_Item_Views.
It works but the combo box is only shown after double clicking in the cell, the user has to click again to show the list of possible values. This is a bit inconvenient.
Is there a way to make the combo boxes always visible ?
I'm trying with openPersistentEditor method, but it does not work right now ...
there is a bit of code close to my code (ComboBoxItemDelegate is the same than the exemple linked before):
MonWidget::MonWidget() : _ui(new Ui::MonWidget())
{
// ...
// Links Model
_linksModel = new QStandardItemModel(this);
// Links Headers
QStringList linksTableViewHeader << "Name" << "Path" << "Version";
_linksModel->setHorizontalHeaderLabels(linksTableViewHeader) ;
// Create itemDelegate for linksView
_itemDelegate = new ComboBoxItemDelegate(_ui->_linksView);
// Set the links model on the links table view
_ui->_linksView->setModel(_linksModel);
_ui->_linksView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
_ui->_linksView->horizontalHeader()->setStretchLastSection(true);
_ui->_linksView->horizontalHeader()->setMinimumSectionSize(100);
_ui->_linksView->setSelectionBehavior(QAbstractItemView::SelectRows);
_ui->_linksView->setItemDelegate(_itemDelegate);
}
// AddLinksInListView : method called when I add some rows ...
void MonWidget::AddLinksInListView(QList<DataItem*> listLinks)
{
int j=0;
int initialLinksNumber = _linksModel->rowCount();
// For each link, add a row with the link information
for (int row=initialLinksNumber; row<(initialLinksNumber + listLinks.size()) ; row++)
{
for (int column = 0; column < _linksModel->columnCount(); column++) {
//item used to display information for each column in the table view of links contained in the collection
QStandardItem *item=0;
switch(column)
{
case MonWidget::NAME:
{
item = new QStandardItem(listLinks.at(j)->data(MonWidget::NAME).toString());
_linksModel->setItem(row, column, item);
break;
}
case MonWidget::PATH:
{
item = new QStandardItem(listLinks.at(j)->data(MonWidget::PATH).toString());
_linksModel->setItem(row, column, item);
break;
}
case MonWidget::VERSION:
{
item = new QStandardItem(listLinks.at(j)->data(MonWidget::PATH).toString());
_linksModel->setItem(row, column, item);
_ui->_linksView->openPersistentEditor(_linksModel->index(row, column));
break;
}
}
}
j++;
}
}
Yes, there is a way, using openPersistentEditor. Assuming your model is named myModel:
YourDelegate* comboDelegate = new YourDelegate(this);
setItemDelegateForColumn(2, comboDelegate); // delegate set for the third column
...
// when adding a new line, use this.
// The combo box will be always visible
openPersistentEditor(myModel->index(iRow, 1));

Adjusting QSqlTableModel for a QTreeView

I'm trying to put a MySQL table into a treeView.
Each entry has three values in the database - id, text, parentId.
This treeView needs to be editable so I really like the QSqlTableModel approach, as the functionality to save back to database is already built in.
Now, the treeView is showing all entries in the same line, of course, and I need a hierarchy. What would be the best way to build this hierarchy, while maintaining the editing and saving capabilities?
(I'm using MySQL.)
mainwindow.h
private: QSqlTableModel* goalModel;
mainwindow.cpp
(this makes a flat table hierarchy. the table is filtered based on which entry is clicked in another table)
void MainWindow::on_tableViewGoals_clicked(const QModelIndex &index)
{
goalModel = new QSqlTableModel(this);
goalModel->setTable("goals");
//Gets the id from the clicked entry to use as filter
QString idGoals = index.sibling(row,0).data().toString();
goalModel->setFilter( "id_goals=" + idGoals );
goalModel->setEditStrategy(QSqlTableModel::OnRowChange);
goalModel->select();
ui->treeView->setModel(goalModel);
...
I tried this. It's wrong, but I don't really know why. (the third column contains the parentId value, if the entry has it)
for (int row = 0; row < goalModel->rowCount(); ++row)
{
//if the entry has a value over 0 in the parentId column
if (goalModel->index(row,2).data().toInt() > 0)
{
//get number in column 2
int parentId;
parentId = goalModel->index(row,2).data().toInt();
QModelIndex newChild = goalModel->index(row,0);
//find QModelIndex row with matching number in column 0
for (int row = 0; row < goalModel->rowCount(); ++row)
{
if (goalModel->index(row,0).data().toInt() == parentId )
{
//make this entry that entry's child
QModelIndex newParent = goalModel->index(row,0);
newChild = goalModel->index(0,0,newParent);
}
}
}
}
All indexes are already made, so no need to make new ones, just assign a parent to all those who have one. How best to do that?

Filter with QComboBox C++

I want to create an editable QComboBox which filters results according to the search query and updates the dropdown entries accordingly.
After reading How do I Filter the PyQt QCombobox Items based on the text input? I tried to implement something similar in C++.
But I can't store anything inside the QComboBox now. Even after adding new entries through addItem() the total count remains 0.
What is the reason for this and how do I insert entries inside the QComboBox with QSortFilterProxyModel?
Here is the relevant snippet of the code:
SearchBox = new QComboBox(this);
SearchBox->setEditable(true);
// Try adding a few entries and check if they persist after changing the model
SearchBox->addItem(QString("hi"));
SearchBox->addItem(QString("bye"));
int count = SearchBox->count(); // count = 2
ProxyModel = new QSortFilterProxyModel;
ProxyModel->setSourceModel(SearchBox->model());
ProxyModel->setFilterCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
SearchBox->setModel(ProxyModel);
// Check count again
count = SearchBox->count(); // count = 0 <- Why?
// Try adding new entries
SearchBox->addItem(QString("Hi again"));
count = SearchBox->count(); // count = 0 .. So new entries don't get stored
Completer = new QCompleter(ProxyModel,this);
Completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
SearchBox->setCompleter(Completer);
QObject::connect(SearchBox->lineEdit(), SIGNAL(textChanged(const QString)), ProxyModel, SLOT(setFilterFixedString(const QString)));
QObject::connect(Completer, SIGNAL(activated(const QString &)), this, SLOT(onCompleterActivated(const QString &)));
Use QStringListModel to store items. Application crashes if proxy model have no items (if filter string filters out all items)(this needs further investigation - is this completer issue or combobox). This can be fixed by not applying such filter (onTextChanged(QString text) slot). Completer completes input if theres only one item (not sure if it's ok). And sometimes checkbox doubles all items (don't know why). If this issues is critical, I think you need to write custom ComboBox from scratch and this is serious work.
{
SearchBox = new QComboBox(this);
SearchBox->setEditable(true);
QStringList Items;
Items << "hi" << "bye";
StringListModel = new QStringListModel();
StringListModel->setStringList(Items);
ProxyModel = new QSortFilterProxyModel;
ProxyModel->setSourceModel(StringListModel);
ProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
SearchBox->setModel(ProxyModel);
// Check count again
int count = SearchBox->count(); // count = 2
// Try adding new entries
QStringList Items_ = StringListModel->stringList();
Items_ << "hi again";
StringListModel->setStringList(Items_);
count = SearchBox->count(); // count = 3
Completer = new QCompleter(ProxyModel,this);
Completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
SearchBox->setCompleter(Completer);
QObject::connect(SearchBox->lineEdit(), SIGNAL(textChanged(const QString)), this, SLOT(onTextChanged(QString)));
QObject::connect(Completer, SIGNAL(activated(const QString &)), this, SLOT(onCompleterActivated(const QString &)));
}
void MainWindow::onTextChanged(QString Text) {
QStringList Items = StringListModel->stringList();
QString Item;
foreach(Item,Items) {
if (Item.indexOf(Text) > -1) {
ProxyModel->setFilterFixedString(Text);
return;
}
}
}

How to remove all rows and child rows from QTreeview

I don't know why I have trouble removing all rows and sub rows from qtreeview
I'm using QStandardItemModel as the model. Now here is my code that doesn't work.
What could be the problem?
QModelIndex FirstQModelIndex;
QModelIndex parentQModelIndex;
int iMdlChidCound = m_model->hasChildren();
if(iMdlChidCound > 0)
{
// only if there at list 1 row in the view
FirstQModelIndex = m_model->item(0,0)->index();
QStandardItem* feedItem = m_model->itemFromIndex(FirstQModelIndex);
// get the parent of the first row its the header row
QStandardItem* parentItem = feedItem->parent();
// here im getting exception
int parent_rows= parentItem->hasChildren();
parentQModelIndex = m_model->indexFromItem(parentItem);
// now i like to delete all the rows under the header , and its dosnt work
if(parent_rows>0)
{
bool b = feedItem->model()->removeRows(0,y,parentQModelIndex);
}
}
It seems like a lot of what you're doing is superfluous. If your only goal is to remove all the rows from the model, you could probably just use QStandardItemModel::clear
In your code you're jumping between the model and the items in a way you don't have to.
if(m_model->hasChildren()) {
m_model->removeRows(0, m_model->rowCount());
}
That should do what you're seeking.
QStandardItemModel::clear()
Which clears all the items including the header rows.