Can I use a string as an index in a QComboBox? - qt

I'm currently calling a stored proc in Oracle to populate a QComboBox in PYQT. The data appears like this:
code: 'PAY_COMP'
description: 'Payment Company'
code: 'USER_COMP'
description: 'User Company'
I want to show the description in the combobox but want to use the code as the index, is this possible? Reason is, when user selects 'Payment Company', I want to send 'PAY_COMP' to the backend to be updated.
Or is there another way to implement this?

I don't know about python, but at least in C++ you can attach QVariant data to each element in the combo box. A QVariant can be virtually every type, for example a string or an enum.
When populating the combo box I would use the member function void QComboBox::addItem(const QString & text, const QVariant & userData = QVariant()). Then when an item is selected by the user and I know the current index of the combo box, I can use QVariant QComboBox::itemData(int index, int role = Qt::UserRole) const in order to obtain the QVariant of that item, which can then be converted to the actual type the contained data has, for example using QString QVariant::toString() const.
The combo box also provides a method for obtaining the index of one particular data item: int QComboBox::findData(const QVariant & data, int role = Qt::UserRole, Qt::MatchFlags flags = static_cast<Qt::MatchFlags> ( Qt::MatchExactly | Qt::MatchCaseSensitive )) const
Now you'll only have to transfer that to python, but I assume the interface will be the same.

Related

qt5 view different roles of model data

I want to use a QTableView to show different roles of an item, e.g. column 1 shows the DisplayRole data, column 2 shows UserRole, column 3 shows UserRole+1, etc
I've created this by making my own item delegate and assigning it to the appropriate column. However, to get access to the same item the delegates have to access their siblings. For example, here's my setEditorData function:
void UserRoleDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QModelIndex baseIndex = index.sibling(index.row(),0);
QVariant v = baseIndex.data(Qt::UserRole);
if(v.isValid())
static_cast<QLineEdit*>(editor)->setText(v.toString());
}
Right now, it's hardcoded that column 0 contains the real object and other columns just access that via the sibling function. I'm worried, though, that it's fragile in that changing the column order will break it.
There are obvious ways to manage that, but I'm just wondering if I'm taking the right approach. Is there a better option to display different aspects of the same item?
To avoid possible code rewrite you simple could use the enumeration for your column numbers. For example:
enum ColumnNumber {
Base,
Sub1,
Sub2
}
And in your delegate's code:
[..]
QModelIndex baseIndex = index.sibling(index.row(), Base);
Thus, if you need to change the column order, you simply need to change the order of your enum values. The rest of code will work correctly as it is.
WRT to item delgate usage - it looks rather strange. Such things used to made in the model class, especially in QAbstractItemModel::data(...) function, using it with Qt::EditRole role. For example:
QVariant Model::data(const QModelIndex &index, int role) const
{
if (role == Qt::EditRole) {
// Get the data that stored in the first column
// ..
return data;
}
[..]
}

Qt5 Is it possible to retrieve an item's checkstate from a combobox without having a pointer to the model?

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);

Displaying a tooltip for QTreeWidgetItem when it's hovered without calling setTooltip() for every item

I want to display a tooltip for QTreeWidgetItem that's hovered. However, getting a tooltip is not a very fast process in my case, so I don't want to call setTooltip() for every single item. I want to do it on demand, on some event or signal. What's the easiest way to do it?
The best solution I've found is to subclass QTreeWidgetItem, override virtual QVariant data(int column, int role) const; and return a tooltip for this item when data is called for Qt::ToolTipRole.
I think that it should be easier to achieve what you want if you migrate to a QTreeView/Model pattern.
QAbstractItemModel has a role for tooltips: Qt::ToolTipRole
You could subclass a Model to reimplement the
QVariant QAbstractItemModel::data ( const QModelIndex & index, int role = Qt::DisplayRole ) const [pure virtual
method.
So, when receives a Qt::TooltipRole, it calculates/recovers from an internal cache.

How to assign different Url to my TreeView Items

I am new to Qt. I had created a Qtree View using QStandard item model.
Now I want to set Url to my items. How can I assign url for tree view items.
you can use setData API of QStandardItem, with user defined role for storing URL.
void QStandardItem::setData ( const QVariant & value, int role = Qt::UserRole + 1 )

Using a delegate with a QDataWidgetMapper and QLabel

I'm trying to use a delegate to customize the way data from a model is displayed when using a QDataWidgetMapper.
I have two different versions of a widget, one is view-only (the data is displayed in QLabels) and the other is used to edit the data (the data is displayed in appropriate editors).
The latter one works perfectly with the delegate, everything is fine.
As you may have guessed the problem arises with the first one... When mapping the sections of my model to QLabels using the QDataWidgetMapper, the delegate is never called and the data is displayed correctly for the sections with regular data (strings, ints,...) but no data is displayed for the sections of my model with a custom data type (a kind of list) which I would like to format as a string using the delegate.
I've already performed this operation successfully when the same data is displayed in a QTableView (the method paint() of the delegate is called when the data is displayed).
After having looked at it a little bit closer, I've been able to see that, when using QLabels to display the data, the delegate is never called though I've explicitly associated a delegate to the QDataWidgetMapper using its method setItemDelegate().
So in synthesis, assume a class CustomItemDelegate which inherits QStyledItemDelegate with virtual methods:
void CustomItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
qDebug() << "DELEGATE: PAINT" << index.column();
QStyledItemDelegate::paint(painter, option, index);
}
void CustomItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
qDebug() << "DELEGATE: SET EDITOR DATA" << index.column();
QStyledItemDelegate::setEditorData(editor, index);
}
and a widget with following in it:
QDataWidgetMapper* mapper = new QDataWidgetMapper();
CustomItemDelegate* delegate = new CustomItemDelegate();
mapper->setModel(model);
mapper->setItemDelegate(delegate);
mapper->addMapping(editorWidget, 1);
mapper->addMapping(label, 2, "text");
mapper->toFirst();
QTableView* view = new QTableView();
CustomItemDelegate* delegate2 = new CustomItemDelegate();
view->setModel(model);
view->setItemDelegate(delegate2);
the code outputs:
DELEGATE: SET EDITOR DATA 1
// NOTHING ?!
DELEGATE: PAINT 1
DELEGATE: PAINT 2
and as a result I got
my editorWidget with the correct data in it (whatever data type the section contains: regular or custom, as long as the editor handles the type of course),
my label only displays the data if the section contains a regular type of the data as the delegate is not called
my view would display everything fine as the delegate is called for each section
So my questions are:
why isn't the delegate called when the mapped widget is a QLabel?
in this case, how come the data is even displayed when the data type is regular? Magic?
Thanks very much and I apologize in advance if the answer is obvious (but even then, thank you for pointing it out :P),
ixM
This is the code from QT that populates widgets
void QDataWidgetMapperPrivate::populate(WidgetMapper &m)
{
if (m.widget.isNull())
return;
m.currentIndex = indexAt(m.section);
if (m.property.isEmpty())
delegate->setEditorData(m.widget, m.currentIndex);
else
m.widget->setProperty(m.property, m.currentIndex.data(Qt::EditRole));
}
In the first case when you do not specify a property delegate is used whereas in the second case the data is set to widget directly by passing your delegate.
I don't know why it was designed this way but this is how it works currently !

Resources