accepting dialog before/after a mass update
-
i have a table view with lots of items, and a dialog which contains a line edit. when the user enters some text there, i update the table view, and then accept the dialog:
void Dialog::onOk() { // update table view // ... // accept the dialog QDialog::accept(); }
the problem is that, since table has many rows, the dialog is closed only after the table is updated.
calling
close()
before doing the update doesn't work (i'm not even sure if it's correct to do so), becausepaintEvent()
is not sent after update and new data is not drawn in table view. same happens when iaccpet()
the dialog before doing the update.what can i do?
-
Hi,
As they are a bit unrelated, why is the update being done from the dialog ?
From your explanation, the dialog should provide a value and upon the click to OK the update should be triggered. Thus, it seems that the class that shows that dialog likely also handled the table view and should do the update. -
@SGaist
yes i agree that ok button should not perform the update. the way dialog invocation is implemented in the code is like this (it's using a language binding and the dialog invoked using a "command" of that language):void onActionClicked() { invoke dialog with name='updateDialog' }
in my method i don't have the pointer to the dialog. i cannot get a pointer to it because the dialog is deleted after exec().
-
@user4592357
I'm sure we'd be interested to hear what this "language binding" actually is?A modal dialog is typically exited with
accept()
orreject()
, returningAccepted
orRejected
true/false to the caller. It is very common (for a modal) dialog to goresult = dialog.exec()
, get that result, and act on it accordingly. Are you sure your language binding does not allow you to see the exit result from a modal dialog, it would be a bit of an omission if it does not?Having said that. Do you want the dialog to stay while doing a long update? What happens if there is an error (perhaps there can't be I don't know)? If you want to exit the dialog immediately, and have the update perform after that, and you can't get the dialog exit result, have you considered doing your table view update on a
QTimer::singleShot()
(probably with interval of 0) instead? That would allow the dialog to close first. You might have to be a bit careful about allowing the user to interact with the table view while the update has not yet completed.Finally, just how long is the update delay? If you're not actually updating a database, even with a lot of rows it's all in memory, I'd expect the update to complete pretty quickly?
-
@JonB
it's tcl language binding for c++. actually it has the idea of return value, but in case of dialog invocation the result is not set to the result of dialog execution.i tried with single shot. the problem is that, when i first accept the dialog then do update, dialog's event loop is finished before doing the update and the view is not updated immediately.
but when i do the update then accept the dialog, the view is updated because the event loop is returned to main thread and paint event is received.and i'm updating a database with a lot of rows.
-
@user4592357
Sorry, now I do not understand what you want. First you said "problem is [...] the dialog is closed only after the table is updated", now you say "dialog's event loop is finished before doing the update ", which one do you want, what is it you want to happen? And btw, where is this table view you want updated? I assumed it was back in the caller, can't see much point it being on the dialog, but I don't know.... -
@JonB
sorry to mislead you.
actually, first the update is performed, then the dialog is closed. if the update takes long, the dialog sin't closed until the update is finished.
if i accept the dialog before doing the update, the table view is not updated immediately. -
if i accept the dialog before doing the update, the table view is not updated immediately.
Depends what you mean by "immediately". The update takes some time. You don't seem to want it to happen before the dialog closes, and then you don't want it after the dialog is closed either. It has to happen some time!! What/when do you want, you seem to my understanding to be rejecting both possibilities? It should be "as immediate as it can be" after dialog closure if you use
singleShot(0)
? And I asked you to clarify that your table view is indeed back on the caller (e.g. main window?) of the dialog, not on the dialog itself? -
@JonB
i want the best of both worlds :) i.e. the dialog to be closed after pressing ok, and the table view to be updated as soon as new data is available.if i accepted the dialog before updating, the database was updated but the view wasn't repainted, i.e. i need to click on table cell to see the new value.
i tried single shot with 0, but it didn't even update the db (consequently, neither the table view). i did that before accepting the dialog.
-
@user4592357 said in accepting dialog before/after a mass update:
i tried single shot with 0, but it didn't even update the db (consequently, neither the table view). i did that before accepting the dialog.
Well you may need to sort out what you did/didn't do there. (Don't forget, it won't do anything before you close the dialog on the next line, the idea is that it will happen afterward.) If you want the dialog to close and then the updates to happen, it may be what you need, given that you can't get result back from dialog.
-
@JonB
i need the dialog to be closed after the data is updated in the database.the reason for this is that, when the dialog is closed, its event loop is finished, and the control returns back to main thread, which receives paint event and the table view is updated with new data.
if i put the accept dialog code before updating the database, the dialog will be closed immediately (that's what i want), then database will be updated. BUT in this case, table view will not be updated with the new data immediately because dialog's event loop was finished before updating the database. when i trigger a repaint, e.g. click on a table cell, only then i see the new data (this is NOT what i want).
-
@user4592357 said in accepting dialog before/after a mass update:
when i trigger a repaint, e.g. click on a table cell, only then i see the new data (this is NOT what i want).
Indeed, that should not be the case.
When I suggest
QTimer::singleShot()
and have that do the updates (after the dialog exits), you should see the updates reflected in the table view. Without you having to click anything, or code doing any explicit repaints. This would happen a little after you close the dialog, according as the time you say it takes it to update. Which I think you will settle for/is what you are looking for, as you have to spend the update time somewhere. If you are not getting it to work this way, you are not succeeding in using the timer as it should be.If you cannot get all this to work, you could just go back to your original code and have it put up some indication to the user while the database updates take place before the dialog closes. That could be changing wording on the dialog, putting up a "wait" cursor, or putting up a further dialog to say "Updating...".
-
@JonB
these are last two lines of ok button's slot:QDialog::accept(); QTimer::singleShot(0, this, [&] { // update the database });
with this i get a segfault with stack trace looking like this:
QEventLoop::exit(int) () from ... QCoreApplication::exit(int) () from ... ?? () from ... QMetaObject::activate(QObject*, int, int, void**) () from ... QWidgetPrivate::close_helper(QWidgetPrivate::CloseMode) () from ...
and if i mix up the lines, then the database is not updated...
-
@user4592357
Purely at a guess, you passthis
as the context, but the dialog dies once you accept it and exit? It's up to you to write the database update code so it does not depend on the dialog being in existence.If you or someone else has a better solution. I suggested it as an approach, I don't know what the whole of your code does, nor what the "language binding" might affect.
-
One thing you could do is write down how you want your logic to work.
Most of the time, like already written in this thread, its:
- Show dialog
- Click Ok / Cancel -> closes the dialog
- If Ok, grab data from dialog
- Do update
- Be happy
If "Do update" takes some more time, you can use a progress bar / sign so your users know that something is happening without having the feeling that your application is somehow stuck because the dialog is still there and nothing is updating.
-
Well, that's step three: processing happens after the dialog has been closed. because you either used
exec
, oropen
with a slot which in both case should result in the logic continuing after the dialog has disappeared. -
@SGaist
You have to read up. Remember, OP claims he cannot receive result from dialog via his "binding", so he has to put the update logic to be called from within the dialog.in my method i don't have the pointer to the dialog.
invoke dialog with name='updateDialog'
it's tcl language binding for c++. actually it has the idea of return value, but in case of dialog invocation the result is not set to the result of dialog execution.I did ask whether it is really not possible to retrieve the dialog result. I did also suggest a message while updating.
@user4592357
So long as your update logic relies on the dialog being in existence, you may have problems doing it when the dialog is no longer there, as you want. You may have to divorce your update code from the dialog, if you really need this. -