Qt: DefaultContextMenu vs CustomContextMenu - qt

What's the difference between setting ContextMenuPolicy to DefaultContextMenu or CustomContextMenu? From what I can tell, they're the same things? Either way, you get to create a custom context menu if needed.

They are certainly not the same.
While they both could create a custom menu, their behavior is quite different. Consider the QWidget documentation:
The default value of this property is Qt::DefaultContextMenu, which means the contextMenuEvent() handler is called.
This means that you need to specifically override contextMenuEvent() in order to eventually show the context menu. This usually means that subclassing is required and only the widget will handle that event (which could also be ignored) and possibly its menu.
Note that overriding contextMenuEvent() could be done also for special cases of the event management, from the simplest one (accepting it, to avoid propagation to the parent) to more complex situations that need to set up some aspects before letting the default implementation to handle the event as usual.
With Qt::CustomContextMenu, the signal customContextMenuRequested() is emitted.
This means that any object can connect to that signal (and potentially more than once), even a completely unrelated one, and eventually do something from there. This also means that there is absolutely no access to the event, which will always be considered as accepted.

Related

qt permanently display delegate in view

How do you use QStyledItemDelegate / QItemDelegate to permanently display a complex widget, i.e. to handle the Qt.DisplayRole, not just Qt.EditRole?
The documentation eludes to using paint()... but that's just way to complex! Let's take for example rendering a QTreeView or QTableVeiw inside of a QTableView cell.
There is QAbstractItemView.setIndexWidget(), but that is a bad idea as it only used to display static content (and whats the fun in static models?).
Note
I found part of the answer in another post, but it was only a small subset of the answer, so I thought it warranted a new post with proper question.
The key is to use QAbstractItemView.openPersistentEditor() to always keep the cell in edit mode.
Some additional key elements
The Qt.EditRole flag will need to be provided for the cells which use delegates.
QStyledItemDelegate.sizeHintChanged.emit(index) needs to be called anytime the size of the editor widget has changed.
Implementing QStyledItemDelegate.sizeHint() can be tricky and tedious (or you can do index.internalPointer().editor_widget.sizeHint() assuming you saved a reference of the editor to the internal pointer during QStyledItemDelegate.createEditor()
here is a good post on how to determine sizes: What are the mechanics of the default delegate for item views in Qt?
Caution
It should be mentioned that opening editors is costly, so if you have thousands of indexes and they are all loaded at once, it can take a while. There are many ways to mitigate this issue:
Load the model incrementally using a thread
Use Qt's fetchMore() mechanism
call openPersistentEditor incrementally (using a timer, or as they come into view for the first time)
call openPersistentEditor when the parent is expanded and closePersistentEditor when the parent is collapsed, and possibly restrict the use of expand-all on nodes with many children.

Flex custom components, events and scope

I'm starting to give up on the Flex forums so I'l re-post here and see how things go. Long time lurker, first time poster ;-)
I'm trapping keyboard events on the stage and dispatching custom events through a framework (Mate, though I don't know that this is an important issue), but I'm pretty confused by the scope. The structure is:
--application (traps keyboard events and dispatches custom event
-- mainPanel (receives dispatched events but mainCalendar (a child element)
is null on debugging. Obviously if I try to call a public method on
mainCalendar it errors out, even though it's a child of mainPanel.
However, mainCalendar is NOT null IF I use
FlexGlobals.topLevelApplication.mainPanel.mainCalendar.
Outerdocument and parentDocument do not expose mainCalendar either, BTW
-- mainCalendar (a custom component inside mainPanel with public methods.
Creation policy is 'all' and it's visible and exists long before I
trap any keystrokes at the top level)
Could someone take a minute and explain why the mainCalendar is out of scope when mainPanel receives a custom event, even though mainCalendar is a child of mainPanel. Is there a better way to manage the events so I don't have to always address the component via the topLevelApplication?
Thanks
(creating answer so this question could be marked as answered)
Usually, when reference to component is null and it should not, this means component isn't created yet. This might have place before application initialize event or if component's parent isn't visible and not validated.

How do I propagate a mousePressEvent() to a group of QGraphicsItems?

I'm writing a program that uses the Qt Graphics View framework. I have subclassed QGraphicsItem to a class that includes other QGraphicsItem (or other subclasses of it). This class is the parent of the included QGraphicsItem; the idea is to work with composite objects.
From the docs it seems to be a conflict in what I try to achieve:
Calling ignore() in mousePressEvent will make my object unmovable. I want to move it.
Calling accept() in mousePressEvent will prevent the event from being propagated to the child object. Some of the child objects should react to mouse events.
How can I make this work?
I think your interpretation of the documentation is incorrect.
Calling ignore() in mousePressEvent will make my object unmovable.
I don't believe that is true. To me it looks like calling ignore() is like the object saying "I have assessed this event. I have taken all actions I want to in response to this event. I have also decided it was not intended for me, so I will now pass it on to the next object underneath me". I can't find anything which suggests the ignore event will unset the QGraphicsItem::ItemIsMovable flag (which is what decides if the QGraphicsItem is movable or not).
I don't see why you couldn't make your object move and ignore() the event, but I would advise that this is not a sensible approach (in most instances: obviously you may have cause for it).
Calling accept() in mousePressEvent will prevent the event from being propagated to the child object.
I believe this is true, but the parent can still modify its children. My understanding is calling accept() is like the object saying "I have assessed this event. I have taken all actions I want to in response to this event (which may include modifying my children). I have also decided that the event was intended for me, so I will not be passing the event on".
In your parent QGraphicsItem, you might try to
MyObject::mousePressEvent ( QGraphicsSceneMouseEvent * event )
{
QGraphicsItem::mousePressEvent(event);
event->ignore();
}
This would allow normal processing of the mouse event (i.e. make your object moveable), but then ignoring it so that it is propagated.
The logic would need to be more robust, though, because there is a high risk of side effects if a parent and child respond to the same mouse event.
Send QCoreApplication::postEvent(child, mouseEvent) to child objects.

Qt: How to initialize dialog widgets?

I would like to know what the established procedure is for initializing the controls within a Qt custom dialog box. In the code I am writing, the dialog would present a QListView containing directories from an object passed (by reference) to the dialog class during construction. When the dialog is displayed, I obviously want the list to display the directories currently configured in the object.
Where should this be done though? Perhaps in the overridden showEvent() method?
Background: I used to do a lot of MFC programming back in the day, and would have done this sort of stuff in the OnCreate method, or some such, once the window object had been created.
Thankfully Qt doesn't require you to do any hooking to find the moment to create things (unless you want to). If you look over the Qt examples for dialogs, most do all the constructing in the constructor:
http://doc.qt.io/archives/qt-4.7/examples-dialogs.html
The tab dialog example--for instance--doesn't do "on-demand" initializing of tabs. Although you could wire something up via the currentChanged signal:
http://doc.qt.io/archives/qt-4.7/qtabwidget.html#currentChanged
Wizard-style dialogs have initializePage and cleanupPage methods:
http://doc.qt.io/archives/qt-4.7/qwizardpage.html#initializePage
http://doc.qt.io/archives/qt-4.7/qwizardpage.html#cleanupPage
But by and large, you can just use the constructor. I guess the main exception would be if find yourself allocating the dialog at a much earlier time from when you actually display it (via exec), and you don't want to bear the performance burden for some part of that until it's actually shown. Such cases should be rare and probably the easiest thing to do is just add your own function that you call (like finalizeCreationBeforeExec).

QWidget signal sent when menu action selected - how do I prevent this?

In more than one of my Qt applications I've noticed that, whenever the menu bar is clicked, the last signal to have been sent from a widget within the GUI is re-sent before the menu action is invoked. Most of the time this doesn't matter; but on some occasions it matters very much.
In a few cases where the widget's signal is connected to one of its own slots, it's straightforward to begin the slot with a
if (hasFocus())
{
// ...
}
...block so that such spurious signals, not generated by the user actually clicking on the widget, can be ignored.
However, I've recently identified that this behaviour is responsible for several related bugs where the spurious signals are passed on through several layers of the program before being acted upon, so simply checking whether a particular widget has focus is not trivial to implement.
My question, therefore, is:
why on earth does clicking on a menu item cause a signal to be emitted from a widget elsewhere on the screen? I can't find this behaviour documented anywhere?
how do I stop it?
Many thanks,
Stephen.
As you deduced yourself, the QLineEdit::editingFinished signal can be emitted twice if the user press enter and the QLineEdit loses the focus later. An old bug was created but behaviour has not been changed : https://bugreports.qt.io/browse/QTBUG-40.
Your solution is fine : overload QLineEdit and check if the value has changed before triggering the signal. You can use the flag QLineEdit::isModified for the check : it has a default value of false and is changed to true whenever the user changes the line edit's contents. It has to be manually reset to false when you emit the signal.
You can also do that check in the receiver object, just checking if the value has a meaning (is different from the last recorded value for example) and process it or not.
Therefore the polluting signals would not be a problem. It is in my opinion the cleanest solution, then you have a robust model. Because the user could also hit enter a few times with the same text value and you have to handle this anyway.
You can also use QLineEdit::returnPressed but this requires the user to always press enter to validate a value. Not always intuitive but forces the user to explicitly validate the inputs.

Resources