There is a QCompleter (set to QLineEdit) populated with QStandardItemModel. That model also populates the QTableView, I need to get the QModelIndex and select it in QTableView but it fails, it
passes text instead of QModelIndex:
completer.highlighted.connect(print_index)
passes only the first index:
completer.highlighted.connect(lambda : select_index(completer.currentIndex()))
def select_index(index):
table_view.setCurrentIndex(index)
I read docs, but cannot understand what do I do wrong.
http://doc.qt.io/qt-5/qcompleter.html#highlighted-1
There's two versions of the highlighted signal: the default one emits a string, the other emits a QModelIndex
To get the index, use:
completer.highlighted[QtCore.QModelIndex].connect(onHighlight)
But be careful, this is the index in the completion model, not the model you populated the completer with. You can use mapToSource to get the original index.
def onHighLight(index):
#completer model
print(index)
#model
sourceIndex=completer.completionModel().mapToSource(index)
print(sourceIndex)
I would like to use row() function of QmodelIndex. It will directly return the list index of your current selection.
Related
I am making a qt application with PyQt. I have a custom QTableModel that i show in a QTableView. Each row in this model can be checked, when a row is checked I want it to appear in another QTableView. To do this I made a custom proxymodel subclassing from QSortFilterProxyModel.
In my custom model I reimplemented the filterAcceptsRow method to only accept rows that are checked:
def filterAcceptsRow(self, pos, index):
model = self.sourceModel() # The sourcemodel is a 2d array of QStandardItem
row = model.row(pos) # This method returns the row at index pos
if row[0].checkState(): # The first QStandardItem has a checkbox
return True
return False
This works once at the start of my program (I assume when i call setSourceModel) but doesn't update when the checked items change. How do I make sure this function gets called when the checkstate changes in my base model? Or is there another way to do this?
I know you can do it when you have access to the QStandardItemModel but using combobox->model() returns a QAbstractItemModel which doesn't have the item(int row, int col) accessor. I've tried working with QAbstractItemModel::itemData(QModelIndex) but can't get it to work as I require.
I just need to get the CheckState of the items, if(item.checkState() == Qt::Checked) etc...
Edit: I have this code, can I cast it to a QStandardItem?
QModelIndex index(1, 0);
QVariant item = ui->SearchAssessmentCombo->model()->data(index, Qt::CheckStateRole);
You can't declare an index yourself, all indices are tied to a model. Internally, the data() function will determine that the index you gave in the parameter does not belong to the model and will return null values for everything.
You need to ask your model to give you a valid index before you can use it.
QModelIndex index = ui->SearchAssessmentCombo->model()->index(1,0);
I need to implement a table with Qt.
I believe I'll be suing a QAbstractTableModel, with a QTableView using this model.
I understand I'll have to edit the rowCount(), columnCount(), and data() functions of the model.
However, I don't understand how to exactly set the data inside the model, so that data() function can retrieve it..
Is the setData() function provided for this purpose? I have seen it takes EditRole as its parameter, which I don't want, as I don't want my table to be editable.
So, how do I "set" data inside the model, or have data for the model to get at, using data() function?
Also, how is the data() function called, i.e., who calls it and where would it need to be called?
Please help me with this.
Thanks.
How the actual data is kept in memory, generated or queried from a data store is completely up to you. If it's static data, you can use the Qt container classes or custom data structures.
You only need to reimplement the setData() method for editable models.
There are 4 methods you need to implement in a non-editable QAbstractTableModel subclass:
int rowCount()
int columnCount()
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole )
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole)
These methods are called from the view, usually a QTableView instance. The first two methods should return the dimensions of the table. For example, if rowCount() returns 10 and columnCount() returns 4, the view will invoke the data() method 40 times (once for each cell) asking for the actual data in your model's internal data structures.
As an example suppose you have implemented a custom slot retrieveDataFromMarsCuriosity() in your model. This slot populates a data structure and is connected to a QPushButton instance, so you get fresh data by clicking a button.
Now, you need to let the view know when the data is being changed so it can update properly. That's why you need to emit the beginRemoveRows(), endRemoveRows(), beginInsertRows(), endInsertRows() and its column counterparts.
The Qt Documentation has everything you need to know about this.
You don't need to use setData(...). Instead, you need to subclass QAbstractTableModel in such a way that its methods rowCount(), columnCount(), data(index) and potentially headerData(section, horizontalOrVertical) return the data you wish to display. Here's an example based on PyQt5:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
headers = ["Scientist name", "Birthdate", "Contribution"]
rows = [("Newton", "1643-01-04", "Classical mechanics"),
("Einstein", "1879-03-14", "Relativity"),
("Darwin", "1809-02-12", "Evolution")]
class TableModel(QAbstractTableModel):
def rowCount(self, parent):
# How many rows are there?
return len(rows)
def columnCount(self, parent):
# How many columns?
return len(headers)
def data(self, index, role):
if role != Qt.DisplayRole:
return QVariant()
# What's the value of the cell at the given index?
return rows[index.row()][index.column()]
def headerData(self, section, orientation, role):
if role != Qt.DisplayRole or orientation != Qt.Horizontal:
return QVariant()
# What's the header for the given column?
return headers[section]
app = QApplication([])
model = TableModel()
view = QTableView()
view.setModel(model)
view.show()
app.exec_()
It's taken from this GitHub repository and displays the following table:
I have QTableView which has QComboBox in one of the columns. The combobox is displaying data from a vector which get updates when I click a button.
When I start the application the combobox displays all the items in vector. Now I press the button (which adds more items to the vector) but the combobox doesn't reflect new data in vector. It still shows old data. I am also emitting dataChanged() once the vector is updated but I don't see any change. data() function does get call in the model which does return all the elements of the vector, but setEditorData doesn't get call in delegate.
Am I missing something.
Thanks,
Dev
Then you need to do something like this function:
void updateComboBox(QComboBox *comboToUpdate, const QStringList & list )
{
QString curentText = comboToUpdate->currntText();
comboToUpdate->clear();
comboToUpdate->insertItems(list);
comboToUpdate->setCurrentIndex(comboToUpdate->findText(currentText));
}
Lines
QString currentText = comboToUpdate->currentText();
...
comboToUpdate->setCurrentIndex(comboToUpdate->findText(currentText));
are optional and used to don't change currentItem after selection.
I'm still struggling with using QListView, I'm trying to select one particular row in the view and I cannot figure out how to do this.
I found a similar question on StackOverflow which recommends using the createIndex() method of the model, however this method is protected (perhaps it used to be public but is not anymore) so that doesn't work for me. Any suggestion?
You can get the index of anything by just calling
QModelIndex indexOfTheCellIWant = model->index(row, column, parentIndex);
Then you can call setCurrentIndex(indexOfTheCellIWant) as bruno said in his answer.
If model contains just a standard list of items as opposed to a tree structure, then it's even easier. Because we can assume that the item is a root item - no parent.
QModelIndex indexOfTheCellIWant = model->index(row, column);
With a tree structure it is a little trickier, because we can't just specify a row and a column, we need to specify these with respect to a parent. If you need to know about this part let me know and I'll explain more.
Only one more thing to note. Selection is based on cells, not really rows. So if you want to ensure that when the user selects a cell (or you do through code) that the whole row is selected you can do that by setting the "selectionBehavior" on the itself.
list->setSelectionBehavior(QAbstractItemView::SelectRows);
You can use QAbstractItemView::setCurrentIndex ( const QModelIndex & index )
Fetch an instance of QModelIndex from the QListView's model and select it:
void selectRowInQListView(int row, QListView *listView) {
QModelIndex index = listView->model()->index(row, 0);
if (index.isValid()) {
//listView->selectionModel()->select(index, QItemSelectionModel::Select);
//listView->selectionModel()->select(index, QItemSelectionModel::Current);
listView->setCurrentIndex(index);
}
}