Customizing the checkboxes of the items of a QTreeView - qt

I'm having the following situation: I need to create a custom tree control, whose checkboxes are also customized. I have easily made most of the customizations for the tree control by using style sheets; I have succeeded adding checkboxes to the QTreeView's items, but I'm having big problems with customizing them - I need to display a custom image for the checked state, and another for the unchecked state.
The place I concluded this can be done is in my subclass of QStyledItemDelegate, in the paint event (i.e. CheckBoxItemDelegate::paint). What I need is to display the text, the icon, and the checkbox for the item. But the problems are:
- I can't get the style of the item (which I set using the stylesheet) - otherwise my text can be drawn with the incorrect color;
- I don't know the rects of each subitem (the checkbox, the icon, the text);
- I don't know how to get the icon of an item (given its QModelIndex) to draw it.
P.S. I had subclassed the QTreeView (obviously), and, as I am working with QFileSystemModel, I have subclassed it too in order to add the checkbox functionality to it.
Can anybody help me, please?
Is QStyledItemDelegate::paint the proper place for changing the visuals of the checkbox of the tree items? If yes, can you please give me a small example or something, how I can do that?

This is how I rendered checkable items inside a QTreeView with two images (eye opened/eye closed, to represent their visibility state) instead of a checkbox:
ui.myTreeView->setStyleSheet(
"QTreeView::indicator:unchecked {image: url(:/icons/eye_grey.png);}"
"QTreeView::indicator:checked {image: url(:/icons/eye.png);}"
);
Items should be set as checkable, of course. Hope this helps.

Related

Qt: Change the icon in a QListView

Is there a way to change the icon of an element in a QListView after it has been displayed?
I can't find a way to do a setData with the DecorationRole (the role used for the icon).
The model used is a custom QFileSystemModel, but the default implementation is only good for the EditRole so to change the name of the item.
I'm don't know how the the overridden setData can be done.
The goal is to change the icon when the mouse is over the item (through mouseMoveEvent)
You will need to subclass QListView and implement the behavior that changes the role of the displayed icon when the mouse hovers over the item.
Such a subclass could use an internal proxy model so that it wouldn't need to mess with the base view's painting. Simply inform the proxy that a given item's decoration role data has changed, and the base view will know what to do.

Does Qt have combo boxes like Word?

In Microsoft Word, if you want to use Bullets you have a combo box (If we can call it a combo box) to select the shape of the bullet (by clicking the little triangle) or you can just apply the default one by clicking the combo box's button.
Actually the combo box in Word has two parts. For an example let's consider a situation where I want to have a combo box in Qt that has these items as menu items:
"Restart", "Shutdown" and "Log off". User needs to choose one of them but he also can apply previously selected item by clicking its button exactly like Windows shutdown menu in start. You can click Shut down or select another option.
How can we achieve this in Qt?
If you are pursuing after a menu that looks like in the second picture, you can use QToolButton to achieve your goal. Use a QToolButton with popupMode set to MenuButtonPopup. It will render a control something similar to following.
Then you can style the look & feel further more using Qt Style Sheets. Read this example on how to style a QToolButton.
Create a QMenu dynamically, so you can attach it to the QToolButton at run-time in such a way that all items will be included in the menu except for the default item. Default action has to be assigned to the QToolButton itself.
You can use void QToolButton::setMenu (QMenu * menu) to assign a QMenu to your QToolButton at run-time.
If you are trying to design a control that is in your 1st screenshot, you will have to create a custom Qt control I guess. There is no default control available, which can yield that look & feel out of the box.

How to update a QLayout and get the new dimensions before returning?

This is driving me nuts. I have a custom menu class that, when set visible, shows a list of items located in a particular folder. When a hardware button is pressed, my application gets the latest list of items, populates the menu with them, and returns.
The menu displaying these items uses a QListWidget filled with custom widgets. Each of the widgets contains one or more QLabels in a horizontal layout, and is created at the time the menu is shown. In order to adjust the text displayed based on the menu width available, I need to get the size of the QLabel AFTER it has been resized according to the layout, but before the menu becomes visible to the user. The problem is, my layout does not get updated until all of the functions constructing my list return.
I have tried QApplication::ProcessEvents() and the layout update functions, but none of them have updated the values of my QLabels before returning. I can set a QTimer when the button is initially pressed, and have it show the menu, update the items, and stop itself, but that seems like a terrible solution.
Any help would really be appreciated! I've spent most of a day on this.
Marlon
I had this exact problem and could not find an answer anywhere on the Internet. Calling Layout.update(), Layout.activate(), or widget.adjustSize() (all suggested in various places) all did not work.
I had a widget with a vertical layout that I wanted to add a QLabel to and then immediately use the size of the QLabel.
The only thing that worked reliably was
layout->addWidget(myLabel);
myLabel->show();
size = myLabel->size();
It would seem that layouts will just not recalculate until you either return from a function and allow the Qt event loop to progress or manually call show() yourself.
How to update a QLayout and get the new dimensions before returning?
Don't. You're not meant to do that. It'll drive you "nuts" because you're doing it backwards. Layout updates are handled asynchronously from the event loop. Instead of getting layout dimensions right away, set yourself up to be part of the system. Some options are:
Implement a custom widget that will interact properly with the layout, growing to fill the available width of the layout. Perhaps all you need is a size policy and a way to elide text?
Make a custom layout that takes the special properties of your use case into account.
You want to call QWidget::adjustSize() on your parent widget. This will force the layout recalculations.
Have you tried using layout()->update(); ?
I've tried many but nothing works for me on Qt 5.15.
Only invented little patch - create timer and get size after 20 msec:
QTimer::singleShot(20, this, [this]
{
const auto height = myLayout->contentsRect().height();
// ...
});

How to use Qt's Model-View programming

I'm trying to display some cards into a QListView but I'm really having trouble understanding how to use Qt's model/view pattern, and I can't find any simple examples.
Basically, I have two classes:
Card - my "model" which contains the name of the card, id, etc.
CardWidget - can load and render a Card object (display the card name and other info)
So how can I use Card and CardWidget to display a list of cards into a ListView? Do I need to change something to my classes, or should QListView be able to display them directly?
If someone could show me the basic steps or point me in the right direction that would be perfect.
See the documentation of QAbstractItemDelegate, which has an example of rendering items in a QTableView.
Its not obvious what you are trying to do here - in a list view, you can render a view of an item which is not the same as having a widget in every cell.
An item delegate can provide a widget as an editor and also how to render a cell's contents.
If you actually want fixed widgets in the view, you could use QListView::openPersistentEditor on all the cells you want a fixed widget for. The item delegate should outline how to create an editor for the cell in question.

Can I make QCompleter complete inline and show a popup

Qt 4.5 (PyQt 4.6.1)
I'm looking for a widget similar to a QComboBox that automatically filters its entries to the ones starting with the input in the text field. There are around 300 items in the combo box.
I've tried two approaches:
QLineEdit with QCompleter
Advantages
Filtering the items works.
Disadvantages
Doesn't show a popup if the text field is empty.
Doesn't do inline completion.
Allows to insert items not in the list.
Editable QComboBox with insertion set to no
Advantages
Nice popup
Completes inline in the text field.
Disadvantages
No filtering
Input is only possible in either the text field or the popup. Clicking on the popup doesn't select the best-matching item in the popup.
What I need
A popup to select the items.
Slow tippers should be able to start tipping the name of an item and the popup switches to the best matching one.
Preferably I should filter the items so that only partially-matching items are shown.
Concerning you first try with QLineEdit, you can set the completionMode to do it inline.
For your second try, you can add a QCompleter object to you QCombBox in order to filter your items as you want.The QCompleter member of the QComboBox is to offer an easy way to use QCompleter.
Anyway, if you are not satisfied with this method, you can manage a QCompleter object by yourself. This allows you to choose how item list is display (using any views) and to define items order in the list. See basic QCompleter details.

Resources