How to select next row in QTableView programmatically - c++

I have QTableView subclass that I am marking and saving its state with this :
connect(this,
SIGNAL(clicked(const QModelIndex &)),
this,
SLOT(clickedRowHandler(const QModelIndex &))
);
void PlayListPlayerView::clickedRowHandler(const QModelIndex & index)
{
int iSelectedRow = index.row();
QString link = index.model()->index(index.row(),0, index.parent()).data(Qt::UserRole).toString();
emit UpdateApp(1,link );
}
now i like programmatically to move the selection to the next row (not by pressing the row with the mouse)
and invoking clickedRowHandler(...) how shall i do that ?
Thanks

You already have the current row index, so use something like the following to get the modelindex for the next row
QModelIndex next_index = table->model()->index(row + 1, 0);
Then you can set that modelindex as the current one using
table->setCurrentIndex(next_index);
Obviously you'll need to make sure you're not running past the end of the table, and there's probably some extra steps to make sure the entire row is selected, but that should get you closer.

/*
* selectNextRow() requires a row based selection model.
* selectionMode = SingleSelection
* selectionBehavior = SelectRows
*/
void MainWindow::selectNextRow( QTableView *view )
{
QItemSelectionModel *selectionModel = view->selectionModel();
int row = -1;
if ( selectionModel->hasSelection() )
row = selectionModel->selection().first().indexes().first().row();
int rowcount = view->model()->rowCount();
row = (row + 1 ) % rowcount;
QModelIndex newIndex = view->model()->index(row, 0);
selectionModel->select( newIndex, QItemSelectionModel::ClearAndSelect );
}

Related

Use QAxObject to save the data of QTableView as local excel sheets

I need a feature to save the data of qtableview as local excel sheet,i can get data from qtableview,i can make sure that values have been token correctly from qtableview when i step into my 'SetCellValue' function,but they are incorrect in my excel sheet
Get value from qtableview and set them into my excel sheet
for (int row = 0; row < m_nDefectNum[2]; row++)
{
QModelIndex NoModelIndex = categoriesTableList[2]->model()->index(row, 0);
QModelIndex NameModelIndex = categoriesTableList[2]->model()->index(row, 1);
QModelIndex backACountModelIndex = categoriesTableList[2]->model()->index(row, 2);
QModelIndex backARateModelIndex = categoriesTableList[2]->model()->index(row, 3);
QModelIndex backBCountModelIndex = categoriesTableList[3]->model()->index(row, 2);
QModelIndex backBRateModelIndex = categoriesTableList[3]->model()->index(row, 3);
QString backCountStr = QString::number(categoriesTableList[2]->model()->data(backACountModelIndex).toInt() + categoriesTableList[3]->model()->data(backBCountModelIndex).toInt());
QString backRateStr = QString::number(categoriesTableList[2]->model()->data(backARateModelIndex).toDouble() + categoriesTableList[3]->model()->data(backBRateModelIndex).toDouble(), 'f', 2) + "%";
excel->SetCellValue(row + 1, 0, categoriesTableList[2]->model()->data(NoModelIndex).toString());
excel->SetCellValue(row + 1, 1, categoriesTableList[2]->model()->data(NameModelIndex).toString());
excel->SetCellValue(row + 1, 2, backCountStr);
excel->SetCellValue(row + 1, 3, backRateStr);
}
SetCellValue
void ExcelExporterHelper::SetCellValue(int row, int column, const QString& value)
{
int cellRow = row + 1;
int cellCol = column + 1;
QAxObject* pRange = m_pSheet->querySubObject("Cells(int,int)", cellRow, cellCol);
pRange->dynamicCall("SetValue(const QString&)",value);
}
such as , the value i get are "300 30%",they will become "300 300%" when i see the excel file,i don't know what's wrong with my code, i need some help,
i can sure that values have been token from qtableview successfully,but failed when they are saved into excel
step into
my excel

Qcombobox remove and add item in C++ Qt

Creating a combobox in Qtableview2 column 1 and passing values from Qtableview1 column1
so i am storing column1 table1 values in Qstringlist and passing to combobox
void cymodel::rowvalues() {
QAbstractItemModel* table1 = ui.tableView->model();
QAbstractItemModel* table2 = ui.tableView_2->model();
QStringList colvallist1;
for (int r = 0, maxI = table1->rowCount(); r < maxI; ++r)
colvallist1.append(table1->data(table1->index(r, 0)).toString());//store value in stringlist
for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i)//for all rows
{
const QModelIndex idx = table2->index(i, 1);
QComboBox* combo = qobject_cast<QComboBox*>(ui.tableView_2->indexWidget(idx));
if (!combo)
{
combo = new QComboBox(); // make combo
ui.tableView_2->setIndexWidget(idx, combo);// add combo
}
// combo->model()->removeRows(0, combo->count(), combo->rootModelIndex());
colvallist1.removeDuplicates(); // clear duplicates in colvallist1
colvallist1.removeAll(QString("")); //remove empty row data
combo->setPlaceholderText(QString(" "));
combo->addItems(colvallist1);
}
}
connect(ui.tableView->model(), &QAbstractItemModel::dataChanged, this,
&cymodel::rowvalues);
Using removerows() all items are removed everytime,,if I added some values in column0 table1 then select in combobox and again adding values in table1 Column0 that time combobox selection go away
but if i don't use removerows() then when I'm adding new item to combobox then its adding multiple time like 2 values added then i add 2 more in table1 col then in combobox it become 4
So, how to add those that appear in colvallist1 but are not already in the combo & remove those that don't appear in colvallist1 ??
Thanks Plz help!!
thnks,,,i solved this..
to remove the items in combobox which are not in colvallist1..without change in selection
here is the code--
void cymodel::rowvalues() {
QAbstractItemModel* table1 = ui.tableView->model();
QAbstractItemModel* table2 = ui.tableView_2->model();
QStringList colvallist1;
for (int r = 0, maxI = table1->rowCount(); r < maxI; ++r)
colvallist1.append(table1->data(table1->index(r, 0)).toString());//store value in stringlist
for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i)//for all rows
{
const QModelIndex idx = table2->index(i, 1);
QComboBox* combo1 = qobject_cast<QComboBox*>(ui.tableView_2-
>indexWidget(idx));
if (!combo1)
{
combo1 = new QComboBox(); // make combo
ui.tableView_2->setIndexWidget(idx, combo);// add combo
}
colvallist1.removeDuplicates(); // clear duplicates in colvallist1
colvallist1.removeAll(QString("")); //remove empty row data
combo1->setPlaceholderText(QString(" "))
QString selected = combo1->currentText();
int indx = combo1->currentIndex();
combo1->clear();
combo1->addItems(colvallist1);
combo1->findData(selected);
combo1->setCurrentIndex(indx);
combo1->setCurrentText(selected);
}

removeRows() and QPersistentModelIndex

I have implemented my own QAbstractListModel which is based on an std::vector. I now want to display the contents of this model in a QGraphicsScene. For this I have implemented my own QGraphicsItem which stores a QPersistentModelIndex as a pointer to the data.
I have implemented the removeRows method as follows:
bool VectorModel::removeRows(int row, int count, const QModelIndex& parent) {
if (row + count < _vector.size()) {
beginRemoveRows(QModelIndex(), row, row + count);
_vector.erase(_vector.begin() + row, _vector.begin() + row + count);
endRemoveRows();
return true;
}
return false;
}
Now since I erase some elements, the index of the following elements will change. Because of this the QPersistentModelIndex needs to be adjusted.
I have found the changePersistentIndex() method in QAbstractItemModel and I know that I can get all persistent indices with persistentIndexList(). However I don't know how to adjust the indices accordingly using this method. How can this be done?
Will changing these indices be enough to prevent Invalid index errors?
Update
I have changed the removeRows() with the enhancements of #Sebastian Lange, however it is still not working as expected and I receive Invalid index errors:
bool LabelModel::removeRows(int row, int count, const QModelIndex& parent) {
Q_UNUSED(parent)
if (row + count < _vector.size()) {
beginRemoveRows(QModelIndex(), row, row + count);
_vector.erase(_vector.begin() + row, _vector.begin() + row + count);
endRemoveRows();
auto pil = persistentIndexList();
for(int i = 0; i < pil.size(); ++i)
{
if (i >= row + count) {
changePersistentIndex(pil[i], pil[i-count]);
}
}
return true;
}
return false;
}
The emitted errors look like this (when removing the 7th element):
QAbstractItemModel::endRemoveRows: Invalid index ( 7 , 1 ) in model QAbstractListModel(0x101559320)
QAbstractItemModel::endRemoveRows: Invalid index ( 8 , 1 ) in model QAbstractListModel(0x101559320)
QAbstractItemModel::endRemoveRows: Invalid index ( 9 , 1 ) in model QAbstractListModel(0x101559320)
QAbstractItemModel::endRemoveRows: Invalid index ( 10 , 1 ) in model QAbstractListModel(0x101559320)
QAbstractItemModel::endRemoveRows: Invalid index ( 6 , 1 ) in model QAbstractListModel(0x101559320)
Well, you do not need to fiddle with changePersistentIndex, calling beginRemoveRows and endRemoveRows will automatically update all the persistent indexes currently existing on the model. The only invalid QPersistentModelIndex you should have after removing rows are the index on rows which have been actually deleted

QT QTableWidget::item() returns nullptr even when widget assigned to it

This is driving me nuts. Here's the relevant code:
//Inside UI class
QTableWidget *table_view;
Later,
QLabel* lb_param_id = new QLabel(this);
lb_param_id->setText(QString::number(param_id));
QLabel* lb_param_name = new QLabel(this);
lb_param_name->setText(QString(param_name));
QLineEdit* te_value = new QLineEdit(this);
te_value->setText(QString(value));
QPushButton* pb_command = new QPushButton();
pb_command->setText("Change");
...
if(ui->table_view->rowCount() <= param_id)
ui->table_view->setRowCount(param_id + 1);
ui->table_view->setCellWidget(param_id, 0, lb_param_id);
ui->table_view->setCellWidget(param_id, 1, lb_param_name);
ui->table_view->setCellWidget(param_id, 2, te_value);
ui->table_view->setCellWidget(param_id, 3, pb_command);
for(int i =0; i < ui->table_view->rowCount(); ++i)
{
for(int j = 0; j < ui->table_view->columnCount(); ++j)
{
QTableWidgetItem* item = ui->table_view->item(i, j);
//Here, item is nullptr. Why?
item->setForeground(QColor::fromRgb(255,255,255));
}
}
I set widgets, then try to change foreground of all widgets inside QTableWidget. However, what is returned from ui->table_view->item() is nullptr. What is going on here? btw, The column count is set at initialization.
Add following few lines of code.
if(ui->table_view->rowCount() <= param_id)
ui->table_view->setRowCount(param_id + 1);
ui->table_view->setColumnCount(4);
ui->table_view->setItem(param_id, 0, new QTableWidgetItem());
ui->table_view->setItem(param_id, 1, new QTableWidgetItem());
ui->table_view->setItem(param_id, 2, new QTableWidgetItem());
ui->table_view->setItem(param_id, 3, new QTableWidgetItem());
ui->table_view->setCellWidget(param_id, 0, lb_param_id);
...
Basically, you need to insert the data into the cell first before you can set widget. In your case, you don't have meaning fully data.
Inspecting the qt source, this is the how setCellWidget() imaplemented:
void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
{
QModelIndex index = model()->index(row, column, QModelIndex());
QAbstractItemView::setIndexWidget(index, widget);
}
Without setting the cell first, the model index is invalid index. I agree qt should insert the data if returned index is invalid. For now, you have to work with qt code.

dynamically add rows to tableview

I want to have a table view in my Qt code. It has four column and many rows (not know ) before hand in table view Qt how can I dynamically add rows as
QStandardItemModel model(0,2);
What to do add rows dynamically?
there is a huge set of functions for that ,
void appendColumn ( const QList<QStandardItem *> & items )
void appendRow ( const QList<QStandardItem *> & items )
void appendRow ( QStandardItem * item )
void insertColumn ( int column, const QList<QStandardItem *> & items )
bool insertColumn ( int column, const QModelIndex & parent = QModelIndex() )
void insertRow ( int row, const QList<QStandardItem *> & items )
bool insertRow ( int row, const QModelIndex & parent = QModelIndex() )
void insertRow ( int row, QStandardItem * item )
look in qt docs for their description
UPD:
QStandardItemModel m(3,3);
QList<QStandardItem*> newRow;
for (int i=0;i<m.colCount();i++)
{
QStandardItem* itm = new QStandardItem(QString("data for col %1").arg(i));
newRow.append(itm);
}
m.append(newRow);
haven't test it but it should work