QComboBox with QPushButtons - qt

I would like to create a qt combo box with multiple columns containing push buttons and QLabel. If I look at the QSpinBox editor example, the editor is set only for one QSpinBox control. Can we create a complex control such as this and handle events?
Do you have any pointers?

QCombobox internally has a abstractitemview can be accessed by:
QAbstractItemView * QComboBox::view () const
Once you have a pointer to this view, you can define your own delegate for this view. This view draw the popups.
QAbstractItemView can have custom delegate, which can be a push button with QLabel or whatever you like.
Also, you may want to use this call to make delegate showing itself when view pop up:
openPersistentEditor ( const QModelIndex & index )
Here is a demo project QCombobox with button and spinbox exactly doing what you asking for.

Related

QItemDelegate with custom view widget

Qt 5.5 has a virtual method to define a custom widget for editing mode:
QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem & option ,const QModelIndex & index ) const
But how to use a custom widget to override the "view" mode?
I saw "stars rating" delegate example where paint method is used but that's not what I need. I need to show a custom widget that contains other standard widgets inside it and use it in a view mode of QTableView or QListView. No need to get mess with painting pointers and figures - just show a custom widget (that has .ui file) and contains other standard widgets with their behaviour.
For example:
There is a download manager application that can show downloads either as a table or list view. QListView with a list of downloads. Each download has URL, Title, TotalSize, DownloadedSize, ProgressBar, Pause button, Remove button, Resume button. All of those can be columns in a table (QTableView) or composed similar to HTML's DIV in one cell (QListView widget)
How to achieve it? Is there anything like QWidget *createViewer(... ?
QtWidgets are used no QML.
For static content you can use QAbstractItemView::setIndexWidget.
For dynamic content the only option is to implement paint method in you delegate class.

How to move the focus from a QLineEdit to a QTableView editable cell

I am using a QMainWindow with few QLineEdits and with some QPushButtons in it. When the focus is in a QLineEdit (if I type something in the QLineEdit) and if I press the F5 key, I want to show a QDialog.
That QDialog contains a QTableView. My question is, when I press the F5 key, I want to move the focus from the QLineEdit to the QTableView's cell. How can I achieve this?
Subclass QLineEdit and override keyPressEvent() to detect when the F5 key is pressed, or install an event filter on the QLineEdit.
If you create and show the dialog during the key event processing the dialog will automatically receive a focus in event and the first widget in the dialog that accepts focus will be the widget in focus. So either let the QTableView be the first widget, or explicitly give the focus to it using setFocus().
If the dialog is already constructed or is a non-modal dialog which is already open, you need a pointer to the dialog so that you can show it/give it the focus when the F5 key is pressed.
If you want to move to a certain cell in the QTableView you of course also need to know the cell associated with your QLineEdit.

Push button for QTableView

I would like add QPushButtons to my QTableView. How can this be done with Qt? Is it possible to specify which column holds the button If I use QItemDelegate?
You've got to create your own PushButtonDelegate by subclassing QItemDelegate.
QAbstractItemView::setItemDelegateForColumn(int column, QAbstractItemDelegate * delegate) will set your delegate for the specified column of a view.
The implementation of the delegate depends on it's desired behavior. E.g. you can implement only createEditor(), setEditorData() and setModelData() to get the button to appear when the user starts editing a cell, or you can change the cell look completely by reimplementing the delegate's paint() method.
For more information see this. Also take a look at the Qt delegate examples.

How to detect if focus shift from a widget inside a QWidget to one outside?

I'm programming in Python using Qt with PySide and I have custom QWidget defined in a file called editor.py which is inserted in my ui in windowUi.py using the promotion method in the Qt Designer.
The custom QWidget class defined in editor.py doesn't do much besides using Elixir to edit items in a sqlite3 database and importing a ui file (editor.ui). Inside editor.ui there are a couple of QLineEdits and QDateTime widgets.
This widget is originally hidden in the main window and showed when needed. So far so good, but the problem is that I cannot make it hide when not needed. I decided that the widget is not needed when the user clicks anywhere else in the main window that is not the editor widget imported, that is, focus shift from the QWidget.
I looked upon this question: QWidget focusOutEvent not received and realized that the QWidget is really not getting focus.
If I call setFocusPolicy(StrongFocus) on it then I can make it hide if, and only if, the user clicks on the QWidget background (not on any widget inside it) and then clicks outside.
The question is then, how can I make it such that when the user clicks outside of this widget, shifting focus from any QLineEdit or QDateTime that's inside it to something else, the QWidget then hides itself?
Doesn't QApplication:::focusChanged ( QWidget * old, QWidget * now ) do what you need? You can check if QWidget *now is one of your QLineEdits/QDateTime or not (f.e. by going up by the QObject::parent)
Simply connect to this signal before showing and disconnect after hiding.

QAction vs QToolButton and when to override the Basic class?

I've recently been studying Qt, and have the following questions:
What is the difference between QAction and QToolButton?
How do I know when to override QPushButton? For example, should I override in order to be informed when the mouse enters a QPushButton's bounds? I don't need to in order to get the signal click().
Question 1:
QActions are used to define tasks performed by an application in a way which can be understood by a number of different user interface objects. Using an example from the Qt docs for context:
A QAction is defined; it is given an icon image, a text description, a keyboard shortcut and a longer tooltip description, as well as being linked to a user defined function.
newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
Later in the implementation, the QAction is added both to a textual menu bar...
fileMenu->addAction(newAct);
... and an icon-based tool bar:
fileToolBar->addAction(newAct);
The menu bar uses the text description to create an entry in the menu corresponding to the action. Similarly the toolbar uses the icon set on the QAction to create an icon in the toolbar which corresponds to the action. Selecting the menu item, clicking the toolbar icon or pressing the keyboard shortcut will all result in the same effect: that defined by the linking of QAction::triggered() to newFile().
So to directly answer your question: a QAction is an abstract way of defining the various parameters and behaviour of a particular task performed by the application. A QToolbarButton is a UI object (derived from QWidget) created by a QToolbar in response to QToolbar::addAction()
Question 2:
Yes, QPushButton has a clicked() signal inherited from QAbstractButton, but it does indeed lack a way to inform when the mouse has entered its bounds. You have a couple of options in order achieve this, but first you need to first set the mouseTracking property to be enabled. This will allow you to receive mouse move events on the QPushButton even if no mouse buttons are pressed. With that done you need to explore one of the following options:
As you suggest, you could subclass QPushButton and reimplement mousePressEvent in order to respond to the mouse position.
You could install another widget as an eventFilter on the QPushButton, and watch for events of type (QEvent::MouseMove).

Resources