Expandable list view with customized scrollbar in Qt - c++

I want to build a widget like this one that we can find in Word :
So, there is a list view using a specific scrollbar with 3 buttons and no scroll.
When you click on the last button at the bottom right, a new list view with a classic scrollbar is shown over the previous list view (hidden when losing focus). So basically, the smae behavior as the one in Word.
We are already capable of displaying a list view with custom content.
My main concern is how to build the widget in the first image: the list view with the custom scrollbar (3 buttons, no scroll)?
What is the proper way to do this ?

I assume that you're implementing a subclass of QAbstractListView.
I don't believe you need a custom scrollbar - just put the scrollbar and the button into a QVBoxLayout; hide the button once it's checked (you could even connect its toggled() to its setHidden() for that).

At first hide the default scroll-bar by calling the QAbstractScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) method.
Then create your three buttons on the left side and connect the QPushButton::clicked() signals to some slots where you just scroll your list by calling the QAbstractItemView::scrollTo(index), QAbstractItemView::scrollToBottom() or QAbstractItemView::scrollToTop().

While it is correct that you could just build a custom widget consisting of a view with hidden scrollbars and add the buttons to the layout, connecting the signals/slots needed to provide the proper actions, you can also consider to implement your own QScrollBar class. QListView is derived from QAbstractScrollArea, which provides setVerticalScrollBar() so you can just set an object of it to be used by the view. The integration of scroll area and scroll bar should be much more straightforward this way, but you'll have to do the painting of the scroll bar's content yourself, or put a layout and the buttons in there (QScrollBar derives from QWidget, and you'll have to reimplement paintEvent()).

Related

Is there a way to attach or anchor two QWidgets together?

I'm getting started with Qt and decided to build a full-screen text editor. I want to have a button (button with arrow in screenshot) attached to a QDockWidget which opens and closes it so the button is always visible to the right side of the screen and stay anchored to it when dock is visible or resized.
My current app is a simple fullscreen textEdit set to centeralwidget in Mainwindow.
I haven't found a way to do this yet with layouts or existing addAnchor() functions so any help or direction is appreciated.
You can achieve what you want by using a container for your text edit and the button. A QWidget instance can be used as an "invisible"*** container for other widgets.
So in Qt Designer you add a widget as a central widget of the main-window, inside this widget you add the text edit and the button, then you set a vertical layout for this container widget.
Don't forget to restrict the docking widget to only dock to the right side, you can do that with: dock->setAllowedAreas(Qt::DockWidgetArea::RightDockWidgetArea); //assuming dock is the pointer to your QDockWidget.
In case you want the dockWidget to be able to dock to any side and the button to follow, you can do that too, but it get a little bit more complicated. Basically you need to connect a slot to dockLocationChanged of your dockWidget and based on where it's docked you need to set-up a new layout for the container widget to be vertical or horizontal and the order of the textEdit and the button based on the side the dock happened.
LE:*** you will most likely need to set the margins you want, since both the widget and it's layout can have them and the actual content might have higher spacing than you want.

How to add QMenus or Qactions on a Widget like QlistWidget area as a list item?

Is there any way to add QActions as a list item on QListWidget?
I want to make a customization window which will show list of actions on a widget for move up, move down, Rename and other options. I'd like to display it on the widget same as it appears as a context menu.
I tried adding it as a list item with icon and text, but the look it not very good:
i) list items with blank icon are not aligning properly, even after adding a blank icon of size 16*16 is not taking up any space and text with icons & w/o icon are not aligning.
ii) I'm unable to add right-pointing black triangle at the right most, in-case of sub-menus cause somehow unicode character for this is not getting displayed on my Linux machine.
That's why I want to add QActions as it are getting popped at original place.
Any suggestions?
Yes I have a suggestion : do not try to make fancy widgets like this, users will not find it intuitive
You should find another way to implement this.
Imo, something like a QToolButton with a QToolButton::MenuButtonPopup popup mode will do the trick. This way, you can embed menu and sub-menus in a widget, using QToolButton::setMenu().

How can I set Qt tab order for a form with a composite widget?

I have a form written with Qt Designer, which contains a QWidget promoted to a custom widget I have. The custom widget contains several combo boxes. I want the form to have a reasonable tab order, with focus moving from the widget immediately before the custom widget, then going through the combo boxes in the custom widget, and proceeding to the widget after the custom widget. So I set the QWidget to have tab focus in Designer, but the custom widget doesn't handle having focus properly.
I could solve this problem using QWidget::setTabOrder, but that would be messy because I would have to reach into the custom widget from the outside. Alternatively I could give the custom widget a member function to set the tab order. Ideally there should be a simpler way. Is there?

Hiding Q*BoxLayout

I have a dialog box with 2 radio buttons. Each should be connected to a Q*BoxLayout (some content in it), so when the user presses first one, it should show the first Layout with its content, if the user chooses second one, it should display (or enable the visibility) of the second, but I cannot hide an entire layout
Is it possible to hide it?
If no, what would you suggest?
Put the content of the boxlayout inside a QWidget. Then add suitable boxlayout to the QWidget. Now you can hide and show that container widget.

How to draw a progress bar inside a list widget in Qt

I want to have a list of items that need to be processed in a QListWidget. Similar to Windows Media Player CD import, there should be a progress bar for every item in the list.
Now there seems to be a way to do this by creating a regular progress bar, using QPixmap::grabWidget() to save its appearance in a QPixmap and then adding this QPixmap as Icon to the QListWidgetItem via QListWidgetItem::setIcon().
However, this seems to be horribly wacky.
Do you know a more elegant way to achieve a progress bar inside a list widget?
Each item in a QListWidget can be represented by a QWidget of your choice, rather than the default rendering (text). You can set this by calling QListWidget::setItemWidget(). In this case, I'd recommend using QProgressBar as the rendering widget -- you should get the desired result.
From the documentation of QListWidget::setItemWidget():
This function should only be used to
display static content in the place of
a list widget item. If you want to
display custom dynamic content or
implement a custom editor widget, use
QListView and subclass QItemDelegate
instead.
You could do it by converting your list widget into a model/view/delegate combo. Then you can set a delegate on the list view that overrides the paint functions and draws the progress bar wherever you want it. I don't know how easy it would be to get an actual QProgressBar widget into the drawing area, however.
Alternately, you could consider making your own list-widget like container that knows about the progress bars.