How to assign different Url to my TreeView Items - qt

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 )

Related

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

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.

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;
}
[..]
}

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.

Adding a 'None' option to a QComboBox linked to a model

I have a QComboBox so the user can a network name from from a model column. I'm using code like this:
self.networkSelectionCombo = QtGui.QComboBox()
self.networkSelectionCombo.setModel(self.model.worldLinks)
self.networkSelectionCombo.setModelColumn(WLM.NET_NAME)
I'm using PySide, but this is realy a Qt question. Answers using C++ are fine.
I need to give the user the option of not selecting any network. What I'd like to do is add an extra item to the combo box called 'None'. However this will just get overridden by the model contents.
The only way I can think of is to create an intermediate custom view on this model column and use that to update the combo, then the view can handle adding in the extra 'magic' item. Does anyone know a more elegant way of doing this?
One possible solution is to subclass the model you are using in order to add there the extra item. The implementation is straight forward. If you call your model MyModel then the subclass would look like this (C++ used):
class MyModelWithNoneEntry : public MyModel
{
public:
int rowCount() {return MyModel::rowCount()+1;}
int columnCount() {return MyModel::columnCOunt();}
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const
{
if (index.row() == 0)
{
// if we are at the desired column return the None item
if (index.column() == NET_NAME && role == Qt::DisplayRole)
return QVariant("None");
// otherwise a non valid QVariant
else
return QVariant();
}
// Return the parent's data
else
return MyModel::data(createIndex(index.row()-1,index.col()), role);
}
// parent and index should be defined as well but their implementation is straight
// forward
}
Now you can set this model to the combo box.

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