Detecting widget resize done by mouse
-
Probably I didn't explain myself enough clearly. the problem is not blocking/unblocking the signal - or when connecting the signal - but having an event which tells me WHEN doing it. there's nothing which assures me that from that moment no resize will be called again by the system, something that tells me "ok everything has been created, resized and showed.
what I ' found out is that after the main window constructor has ended it's called again a resize for all its children.The invocation of the function which loads layout file where application reads data for building subwindows and sizing them is done when mainwindow constructor is still open on the stack.
For instance:
MainWindow::MainWindow(...)
{
//...
loadLayoutFile(); // this function build subwindows}
-
What system resizing do you have in mind ?
In any case, to differentiate between events from within your application and from the system, you have the QEvent::isSpontaneous method.
-
What system resizing do you have in mind ?
In any case, to differentiate between events from within your application and from the system, you have the QEvent::isSpontaneous method.
-
@SGaist I've just tried. It recognizes all resize events occurring as not spontaneous because they are all originated inside this application
@Black-Imp
Which is what I suspected when I suggested earlier.So if you're looking for a practical, not theoretical, solution, and you can't find anything else, set off a timer when you open the main window and the layout restoration occurs, and treat resize events after that expires as user-input? Ugly? Yes. But if it suffices....
-
@Black-Imp
Which is what I suspected when I suggested earlier.So if you're looking for a practical, not theoretical, solution, and you can't find anything else, set off a timer when you open the main window and the layout restoration occurs, and treat resize events after that expires as user-input? Ugly? Yes. But if it suffices....
-
@JonB thank you i had already considered this idea but.. yes it sounds too much nasty. I'd like to understand how to recognize resize by mouse is going on but I think it's something not accessible
@Black-Imp
Well, I also suggested that if you had to you might monitor mouse downs etc. as the only way of recognising.However, if we both agree that is too flaky and that the
resize
event is simply not going to tell you, then you may say using a timer "sounds too much nasty" but you are limited in your options, aren't you?In a sense it's not that nasty. You are wanting to respond only to user resizing, so coding as "user interaction doesn't start till a second after the main window is shown" is not way off the scale, is it?
BTW, I thought about it: I have not tested it, but since you say you want a signal/event to arrive after the main window has opened/layouts have been restored, if you don't want to use a timer could you call
QCoreApplication::postEvent()
after your layout restoration code and see whether that event does indeed arrive after the lastresize
one? You'd have to test.Then there are other alternatives which come to my mind.
One is: why not accept all resizes as potentially needing to be saved back? It sounds a lot, but if you're using, say,
QSettings
to save the overhead is not too bad. You could improve by buffering changes (by time) a bit in memory before committing them, then if there are several closely-spaced resize events during restoration you would only have to deal with the final state. If the final state is actually the same as the saved layout state, discard changes.Or: on any resize event, don't save size, simply set a flag. Periodically examine the flag: if it's set, get the current geometries of sub-windows and compare against what previously saved. If the result is different from saved, only then save/set your "asterisk" to user.
Or: don't do asterisk for resizes, but do compare & save on window closure/exit. I actually think this is more normal for an app? Although apps do save layout changes, they do not tend to mark them as "asterisk" changes to the user, that only shows if the user changes document content.
Food for thought. It's not what you wanted, but there are several possible ways forward.
-
@Black-Imp
Well, I also suggested that if you had to you might monitor mouse downs etc. as the only way of recognising.However, if we both agree that is too flaky and that the
resize
event is simply not going to tell you, then you may say using a timer "sounds too much nasty" but you are limited in your options, aren't you?In a sense it's not that nasty. You are wanting to respond only to user resizing, so coding as "user interaction doesn't start till a second after the main window is shown" is not way off the scale, is it?
BTW, I thought about it: I have not tested it, but since you say you want a signal/event to arrive after the main window has opened/layouts have been restored, if you don't want to use a timer could you call
QCoreApplication::postEvent()
after your layout restoration code and see whether that event does indeed arrive after the lastresize
one? You'd have to test.Then there are other alternatives which come to my mind.
One is: why not accept all resizes as potentially needing to be saved back? It sounds a lot, but if you're using, say,
QSettings
to save the overhead is not too bad. You could improve by buffering changes (by time) a bit in memory before committing them, then if there are several closely-spaced resize events during restoration you would only have to deal with the final state. If the final state is actually the same as the saved layout state, discard changes.Or: on any resize event, don't save size, simply set a flag. Periodically examine the flag: if it's set, get the current geometries of sub-windows and compare against what previously saved. If the result is different from saved, only then save/set your "asterisk" to user.
Or: don't do asterisk for resizes, but do compare & save on window closure/exit. I actually think this is more normal for an app? Although apps do save layout changes, they do not tend to mark them as "asterisk" changes to the user, that only shows if the user changes document content.
Food for thought. It's not what you wanted, but there are several possible ways forward.
@JonB Solved!
Thank you for your kind reply. It suggested me to check again the moment when the last resize is performed by showing the window. I knew that from inside main window constructor I would never be able to do it because subwindows are resized after constructor ends...
when main window slot is invoked I already check that flag but instead of turning true by some event caught by main window I set it true from mainfile after calling main window show:
in main.cpp:
mainWin.show(); mainWin.detectLayoutModification(true); app.exec();
in main window cpp
ParentWindow::ParentWindow:QMainWIndow(...), mDetectLayoutMods(false) {} void ParentWindow::detectTemplateModification(bool detect) { mDetectLayoutMods = detect; } void ParentWindow::onLayoutModified() // this is a slot connected to subwindows signals { if (!mDetectLayoutMods) { return; } mLayoutModified = true; // used elsewhere // do something to show file has been modified .... }
About your solution: I've had aready considered a timer but there is no way to be sure it works: the time may be too long and user may do some mods as soon as file opens before I can detect it or for some reason time required for loading may be longer than usual - this software is frequently used on notebooks
About asterisks: almost every software shows you somehow if the file you are working on has been modified
thank you all for your time.
-
Hi,
An even better way would be to use a single shot QTimer with a timeout of 0 at the end of your main window constructor.The slot will be called right after the widgets are shown, so the resizing will have already happened.Another possible solution would be to use a single shot QTimer with a timeout of 0 at the end of your main window constructor.
The slot will be called at the first occasion once the event loop has started.
The fact that it's working currently is a bit of luck in the sense that the widgets are show when exec starts its work.
-
Hi,
An even better way would be to use a single shot QTimer with a timeout of 0 at the end of your main window constructor.The slot will be called right after the widgets are shown, so the resizing will have already happened.Another possible solution would be to use a single shot QTimer with a timeout of 0 at the end of your main window constructor.
The slot will be called at the first occasion once the event loop has started.
The fact that it's working currently is a bit of luck in the sense that the widgets are show when exec starts its work.
@SGaist said in Detecting widget resize done by mouse:
The slot will be called right after the widgets are shown, so the resizing will have already happened.
could you explain me better the sequence. from what I've noticed all the subwindows resize actions are performed before app.exec(); and after mainwin.show();
how can you be sure timer triggers right after constructor has ended?
if it triggers after the constructor anyway you are still before mainWin.show() after which resize is called more times.
I really don't understand
-
You have a point (I have edited my previous answer). The technique works well for loading settings when signals and slots are involved. I encourage you to try it for your use case.
As for the sequence of events you have one thing wrong, the show method schedules an event to show the widget however it won't happen until the QApplication event loop starts.
The same goes for the QTimer at the end of the constructor. The timer itself needs an event loop and thus the timeout will only happen after the constructor has ended since the event loop has not yet started.