Interact with editor widgets' data in QTableView - qt

I'm using an editable QTableView + QStandardItemModel.
While editing a cell in a table view, I'd like to do something according to the new input data in this specific cell when committing the new data into the table view.
To do this, I need the new input data and the current model index (or column & row number).
I tried some slots such as
virtual void closeEditor (QWidget * editor,
QAbstractItemDelegate::EndEditHint hint)
and
virtual void commitData ( QWidget * editor ).
commitData seems to be what I need, however, the parameter is only the editor and I cannot figure out how to obtain the text in this editor widget.
I looked QTextEdit but it's not a inherited class of QWidget.
I wonder if there's any way to obtain the data (text) and axis (column, row) of an editor widget?

I suggest to implement your own item delegate, inheriting QStandardItemDelegate (or QAbstractItemDelegate). There you can override
void setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const
Simply do you your custom processing and then call QStandardItemDelegate::setModelData(...) to make sure that your model is updated with the newly edited data.

The itemChanged(QStandardItem*) signal is emitted by a QStandardItemModel whenever an item's data changes.
From the given QStandardItem, you can retrieve the row and column directly. To get the displayed text, pass Qt::DisplayRole to the item's data() method.

Related

How to implement mixed selection model for QTableView

I have custom table view that shows content of custom abstract model.
I need to implement mixed selection for these view.
When user clicks on the first column the whole row should be selected (AbstractItemView::SelectRow).
When user clicks on cell in other column just the particular cell should be selected (AbstractItemView::SelectItems).
What need to do to achieve such behaviour?
Just do this:
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
//if(!index.column()) more elegant
if(index.column() == 0)
ui->tableView->selectRow(index.row());
}
Catch clicked() signal and check is it first column. If so, then selectRow() with current row (index.row())
I use here QTableView but QAbstractItemView has clicked signal too.

QlistView setCurrentIndex() not working

I am facing a problem with a QListView component.
I created a simple form with a listview and a tableview.
Then I put this code, both widgets populate with the data model as I want:
QSqlQueryModel * modela = new QSqlQueryModel();
QSqlQueryModel * modelb = new QSqlQueryModel();
[...]
ui->listView->setModel(modela);
ui->tableView->setModel(modelb);
[...]
void MyWindow::on_listView_clicked(const QModelIndex &index)
{
ui->tableView->setCurrentIndex(ui->listView->currentIndex());
}
void MyWindow::on_tableView_clicked(const QModelIndex &index)
{
ui->listView->setCurrentIndex(ui->tableView->currentIndex());
// FAILS, does not react...
}
The first slot (when I click any item in the listview widget) works as expected, it automatically selects the corresponding item in the tableview widget, but the second case does not work, it just does not select any item in the listview...
What I want is that whatever item the user clicks in the tableview gets selected in the listview.
Is it possible?
I tried hard, looking for examples and the official qt documentation, but I don't find the right way to do (also tried to connect with signal/slots, but I don't know how to exactly connect both widgets).
Thanks in advance.
QModelIndex is an integral part of a certain QAbstractItemModel. It means that you can't use an index from model A to select an item in a view of model B.
QModelIndex is not just a couple of x,y. It also keeps a pointer to a model which created it.
So if you need to select the same row as selected in the first view, you need to extract a row from the first index, then get a right index in the second model and use it to select an item in the second view:
void selectTheSameRow(const QModelIndex& indexFromModelA)
{
int row = indexFromModelA.row();
QModelIndex indexFromModelB = modelB->index(row, 0);
viewB->setCurrentIndex(indexFromModelB);
}

QStandardItemModel within QTtableview

I am using QStandardItemModel inside QTtableview. Is it possible to add checkbox in on column cell & combobox in another column cell.
So that i can select predefined option from the combo box.
Please suggest how to achieve this.
For the first:
You can setFlags() on an QStandardItem to make it checkable:
Qt::ItemFlags QStandardItem::flags() const
void QStandardItem::setFlags ( Qt::ItemFlags flags )
Qt::ItemIsUserCheckable
( enum Qt::ItemFlag )
For the second:
You should create your own Custom Delegate class inheriting QStyledItemDelegate and reimplement the createEditor, setEditorData and setModelData methods. Check this link and, for a more complete example, the SpinBox Delegate example
Edit: Once you got your custom delegate class, you have to tell your view to use it in a given column with QAbstractItemView::setItemDelegateForColumn

Adding Icons to Combobox Items such that Icons are visible at the Right Side

I am working on an application in which I need to show the List of Program Names and corresponding Icons in a Combobox Popup Menu.
I tried following things:
a. Created the Custom Widget deriving from QCombobox
b. ReImplemented the showPopup() function as follows
void CMyComboBox::showPopup()
{
QComboBox::showPopup();
mp_Popup = this->findChild<QFrame *>();
mp_Popup->move( mp_Popup->x(), mp_Popup->y() - this->height() - mp_Popup->height() );
}
c. Adding Items to Combobox
QString Name = "XYZ";
QIcon icon("Sample.png");
myComboBox->insertItem(0, icon, Name);
Question is: When I insert using above method, it inserts the Icon at the left side(i.e.., Icon followed by Name) .
How do I make the Icons to come at the Right Side(i.e.., First Name followed by Icon)
Regards
Santhosh
QComboBox uses QAbstractModel for showing data. You can replace standard model with a custom one using function void QComboBox::setModel ( QAbstractItemModel * model ).
Icon position in relation to the text is controlled via style options. You should do something like this:
QStyleOptionViewItem option;
option.decorationAlignment = Qt::AlignRight | Qt::AlignVCenter;
option.decorationPosition = QStyleOptionViewItem::Top;

How to insert QPushButton into TableView?

I am implementing QAbstractTableModel and I would like to insert a QPushButton in the last column of each row. When users click on this button, a new window is shown with more information about this row.
Do you have any idea how to insert the button? I know about delegating system but all examples are only about "how to edit color with the combo box"...
You can use
QPushButton* viewButton = new QPushButton("View");
tableView->setIndexWidget(model->index(counter,2), viewButton);
The model-view architecture isn't made to insert widgets into different cells, but you can draw the push button within the cell.
The differences are:
It will only be a drawing of a pushbutton
Without extra work (perhaps quite a bit of extra work) the button won't be highlighted on mouseover
In consequence of #1 above, you can't use signals and slots
That said, here's how to do it:
Subclass QAbstractItemDelegate (or QStyledItemDelegate) and implement the paint() method. To draw the pushbutton control (or any other control for that matter) you'll need to use a style or the QStylePainter::drawControl() method:
class PushButtonDelegate : public QAbstractItemDelegate
{
// TODO: handle public, private, etc.
QAbstractItemView *view;
public PushButtonDelegate(QAbstractItemView* view)
{
this->view = view;
}
void PushButtonDelegate::paint(
QPainter* painter,
const QStyleOptionViewItem & option,
const QModelIndex & index
) const
{
// assuming this delegate is only registered for the correct column/row
QStylePainter stylePainter(view);
// OR: stylePainter(painter->device)
stylePainter->drawControl(QStyle::CE_PushButton, option);
// OR: view->style()->drawControl(QStyle::CE_PushButton, option, painter, view);
// OR: QApplication::style()->drawControl(/* params as above */);
}
}
Since the delegate keeps you within the model-view realm, use the views signals about selection and edits to popup your information window.
You can use setCellWidget(row,column,QWidget*) to set a widget in a specific cell.

Resources