Ensure that QDateTimeEdit::calendarWidget() will always return a valid widget.
This case may be triggered in the (admittedly slightly abnormal) case where a user wishes to embed the calendar widget in a layout or, for whatever reason, do something else that will change its ownership. We work around this by detecting when it is deleted and recreating the widget. This will also have a positive side effect if setCalendarWidget() is called with a widget which is then subsequently deleted, returning the default widget instead of a pointer to (now deleted) memory. Reviewed-by: Denis Dzyubenko Merge-request: 2568 Reviewed-by: Denis Dzyubenko <denis.dzyubenko@nokia.com> (cherry picked from commit 124ec3200f8453142717fcfe7a4aa0a55164aaa6)
This commit is contained in:
parent
202df2ae89
commit
0bb70c3164
@ -2538,20 +2538,32 @@ void QDateTimeEditPrivate::syncCalendarWidget()
|
||||
}
|
||||
|
||||
QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
|
||||
: QWidget(parent, Qt::Popup), calendar(0)
|
||||
: QWidget(parent, Qt::Popup)
|
||||
{
|
||||
setAttribute(Qt::WA_WindowPropagation);
|
||||
|
||||
dateChanged = false;
|
||||
if (!cw) {
|
||||
cw = new QCalendarWidget(this);
|
||||
verifyCalendarInstance();
|
||||
} else {
|
||||
setCalendarWidget(cw);
|
||||
}
|
||||
}
|
||||
|
||||
QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
|
||||
{
|
||||
if (calendar.isNull()) {
|
||||
QCalendarWidget *cw = new QCalendarWidget(this);
|
||||
cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
|
||||
#ifdef QT_KEYPAD_NAVIGATION
|
||||
if (QApplication::keypadNavigationEnabled())
|
||||
cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
|
||||
#endif
|
||||
setCalendarWidget(cw);
|
||||
return cw;
|
||||
} else {
|
||||
return calendar.data();
|
||||
}
|
||||
setCalendarWidget(cw);
|
||||
}
|
||||
|
||||
void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
|
||||
@ -2563,28 +2575,29 @@ void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
|
||||
widgetLayout->setMargin(0);
|
||||
widgetLayout->setSpacing(0);
|
||||
}
|
||||
delete calendar;
|
||||
calendar = cw;
|
||||
widgetLayout->addWidget(calendar);
|
||||
delete calendar.data();
|
||||
calendar = QWeakPointer<QCalendarWidget>(cw);
|
||||
widgetLayout->addWidget(cw);
|
||||
|
||||
connect(calendar, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
|
||||
connect(calendar, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
|
||||
connect(calendar, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
|
||||
connect(cw, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
|
||||
connect(cw, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
|
||||
connect(cw, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
|
||||
|
||||
calendar->setFocus();
|
||||
cw->setFocus();
|
||||
}
|
||||
|
||||
|
||||
void QCalendarPopup::setDate(const QDate &date)
|
||||
{
|
||||
oldDate = date;
|
||||
calendar->setSelectedDate(date);
|
||||
verifyCalendarInstance()->setSelectedDate(date);
|
||||
}
|
||||
|
||||
void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
|
||||
{
|
||||
calendar->setMinimumDate(min);
|
||||
calendar->setMaximumDate(max);
|
||||
QCalendarWidget *cw = verifyCalendarInstance();
|
||||
cw->setMinimumDate(min);
|
||||
cw->setMaximumDate(max);
|
||||
}
|
||||
|
||||
void QCalendarPopup::mousePressEvent(QMouseEvent *event)
|
||||
@ -2620,7 +2633,7 @@ bool QCalendarPopup::event(QEvent *event)
|
||||
void QCalendarPopup::dateSelectionChanged()
|
||||
{
|
||||
dateChanged = true;
|
||||
emit newDateSelected(calendar->selectedDate());
|
||||
emit newDateSelected(verifyCalendarInstance()->selectedDate());
|
||||
}
|
||||
void QCalendarPopup::dateSelected(const QDate &date)
|
||||
{
|
||||
|
@ -148,11 +148,11 @@ class QCalendarPopup : public QWidget
|
||||
Q_OBJECT
|
||||
public:
|
||||
QCalendarPopup(QWidget *parent = 0, QCalendarWidget *cw = 0);
|
||||
QDate selectedDate() { return calendar->selectedDate(); }
|
||||
QDate selectedDate() { return verifyCalendarInstance()->selectedDate(); }
|
||||
void setDate(const QDate &date);
|
||||
void setDateRange(const QDate &min, const QDate &max);
|
||||
void setFirstDayOfWeek(Qt::DayOfWeek dow) { calendar->setFirstDayOfWeek(dow); }
|
||||
QCalendarWidget *calendarWidget() const { return calendar; }
|
||||
void setFirstDayOfWeek(Qt::DayOfWeek dow) { verifyCalendarInstance()->setFirstDayOfWeek(dow); }
|
||||
QCalendarWidget *calendarWidget() const { return const_cast<QCalendarPopup*>(this)->verifyCalendarInstance(); }
|
||||
void setCalendarWidget(QCalendarWidget *cw);
|
||||
Q_SIGNALS:
|
||||
void activated(const QDate &date);
|
||||
@ -171,7 +171,9 @@ protected:
|
||||
bool event(QEvent *e);
|
||||
|
||||
private:
|
||||
QCalendarWidget *calendar;
|
||||
QCalendarWidget *verifyCalendarInstance();
|
||||
|
||||
QWeakPointer<QCalendarWidget> calendar;
|
||||
QDate oldDate;
|
||||
bool dateChanged;
|
||||
};
|
||||
|
@ -275,6 +275,8 @@ private slots:
|
||||
void focusNextPrevChild();
|
||||
|
||||
void taskQTBUG_12384_timeSpecShowTimeOnly();
|
||||
|
||||
void deleteCalendarWidget();
|
||||
|
||||
private:
|
||||
EditorDateEdit* testWidget;
|
||||
@ -3438,5 +3440,26 @@ void tst_QDateTimeEdit::taskQTBUG_12384_timeSpecShowTimeOnly()
|
||||
QCOMPARE(edit.time(), time.time());
|
||||
}
|
||||
|
||||
void tst_QDateTimeEdit::deleteCalendarWidget()
|
||||
{
|
||||
{
|
||||
// setup
|
||||
QCalendarWidget *cw = 0;
|
||||
QDateEdit edit;
|
||||
QVERIFY(!edit.calendarWidget());
|
||||
edit.setCalendarPopup(true);
|
||||
QVERIFY(edit.calendarWidget());
|
||||
edit.calendarWidget()->setObjectName("cw1");;
|
||||
|
||||
// delete
|
||||
cw = edit.calendarWidget();
|
||||
delete cw;
|
||||
|
||||
// it should create a new widget
|
||||
QVERIFY(edit.calendarWidget());
|
||||
QVERIFY(edit.calendarWidget()->objectName() != "cw1");
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QDateTimeEdit)
|
||||
#include "tst_qdatetimeedit.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user