Details
-
Bug
-
Resolution: Invalid
-
P4: Low
-
None
-
6.8.3, 6.9.0
-
None
Description
Consider such use case:
int main(int argc, char *argv[]) { QApplication app(argc, argv); QDateTimeEdit edit; edit.setCalendarPopup(true); QObject::connect(&edit, &QDateTimeEdit::dateChanged, [&]() { qDebug() << "Changing date, blocking"; QSignalBlocker blocker = QSignalBlocker{&edit}; QDate date = edit.date().addDays(1); edit.setDate(date); }); edit.show(); return app.exec(); }
User wants to change date one more time upon it was just changed. And a signal blocker is there for not causing infinite loop.
The expected workflow is:
Open calendar widget -> Pick a different date -> Lambda is triggered -> Date is changed again but that is it since no more signals
But the actual outcome is:
Lambda is triggered twice. Not once (the expected), not arbitrarily many times either (signal blocker works, so to speak).
Some observations:
1. Comment out "edit.setCalendarPopup(true);", get rid of QCalendarWidget, change date with only up/down arrows and problem is gone. So the cause is QCalendarWidget. But it is not QCalendarWidget that sends the additional signal. See #2.
2. Add another blocker for edit.calendarWidget(); but problem is not solved.
3. Change signal blocker to a pointer so that it does not go out of scope and problem is solved.
4. To avoid permanent blocking due to #3, we can choose a proper timing of deleting signal blocker pointer. This actually works:
int main(int argc, char *argv[]) { QApplication app(argc, argv); QSignalBlocker *blocker; QDateTimeEdit edit; edit.setCalendarPopup(true); QObject::connect(&edit, &QDateTimeEdit::dateChanged, [&]() { qDebug() << "Changing date, blocking"; blocker = new QSignalBlocker{&edit}; QDate date = edit.date().addDays(1); edit.setDate(date); }); QObject::connect(edit.calendarWidget(), &QCalendarWidget::clicked, [&]() { qDebug() << "Date changed, unblocking"; delete blocker; blocker = nullptr; }); edit.show(); return app.exec(); }
So my conclusion is that QCalendarWidget somehow causes QDateTimeEdit to send another signal at an unknown timing. It is later than "right after QDateTimeEdit::dateChanged" but earlier than "QCalendarWidget::clicked".
We may want to change the behavior so that there won't be any duplicated signals. Or at least document the behavior so that users are not caught in surprise.