Skip to content

Commit ad6491d

Browse files
authored
fix date time NULL handling (#6591)
* fix #18299 date time widget does not correctly set value from calendar the use of QStyle::subControlRect was returning only the rect of the arrows and not of the whole clickable area. QStyle::hitTestComplexControl has been used instead * correctly emit NULL and not empty string for date/time widget for string fields * finer tuning of style options
1 parent d68107e commit ad6491d

File tree

3 files changed

+49
-21
lines changed

3 files changed

+49
-21
lines changed

src/gui/editorwidgets/qgsdatetimeedit.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "qgsapplication.h"
2727
#include "qgslogger.h"
2828

29+
30+
2931
QgsDateTimeEdit::QgsDateTimeEdit( QWidget *parent )
3032
: QDateTimeEdit( parent )
3133
{
@@ -70,6 +72,10 @@ void QgsDateTimeEdit::clear()
7072
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
7173
emit dateTimeChanged( QDateTime() );
7274
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
75+
76+
// otherwise, NULL is not displayed in the line edit
77+
// this might not be the right way to do it
78+
clearFocus();
7379
}
7480
}
7581

@@ -81,31 +87,45 @@ void QgsDateTimeEdit::setEmpty()
8187

8288
void QgsDateTimeEdit::mousePressEvent( QMouseEvent *event )
8389
{
84-
// catch mouse press on the button
90+
// catch mouse press on the button (when the current value is null)
8591
// in non-calendar mode: modifiy the date so it leads to showing current date (don't bother about time)
8692
// in calendar mode: be sure NULL is displayed when needed and show page of current date in calendar widget
8793

8894
bool updateCalendar = false;
8995

9096
if ( mIsNull )
9197
{
92-
QStyleOptionSpinBox opt;
93-
this->initStyleOption( &opt );
94-
const QRect buttonUpRect = style()->subControlRect( QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxUp );
95-
const QRect buttonDownRect = style()->subControlRect( QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxDown );
96-
if ( buttonUpRect.contains( event->pos() ) || buttonDownRect.contains( event->pos() ) )
98+
QStyle::SubControl control;
99+
if ( calendarPopup() )
97100
{
98-
if ( calendarPopup() && calendarWidget() )
101+
QStyleOptionComboBox optCombo;
102+
optCombo.init( this );
103+
optCombo.editable = true;
104+
optCombo.subControls = QStyle::SC_All;
105+
control = style()->hitTestComplexControl( QStyle::CC_ComboBox, &optCombo, event->pos(), this );
106+
107+
if ( control == QStyle::SC_ComboBoxArrow && calendarWidget() )
99108
{
109+
mCurrentPressEvent = true;
100110
// ensure the line edit still displays NULL
101-
displayNull( true );
102111
updateCalendar = true;
112+
displayNull( updateCalendar );
113+
mCurrentPressEvent = false;
103114
}
104-
else
115+
}
116+
else
117+
{
118+
QStyleOptionSpinBox opt;
119+
this->initStyleOption( &opt );
120+
control = style()->hitTestComplexControl( QStyle::CC_SpinBox, &opt, event->pos(), this );
121+
122+
if ( control == QStyle::SC_SpinBoxDown || control == QStyle::SC_SpinBoxUp )
105123
{
106-
blockSignals( true );
107-
resetBeforeChange( buttonUpRect.contains( event->pos() ) ? -1 : 1 );
108-
blockSignals( false );
124+
mCurrentPressEvent = true;
125+
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
126+
resetBeforeChange( control == QStyle::SC_SpinBoxDown ? -1 : 1 );
127+
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
128+
mCurrentPressEvent = false;
109129
}
110130
}
111131
}
@@ -121,13 +141,13 @@ void QgsDateTimeEdit::mousePressEvent( QMouseEvent *event )
121141

122142
void QgsDateTimeEdit::focusOutEvent( QFocusEvent *event )
123143
{
124-
if ( mAllowNull && mIsNull )
144+
if ( mAllowNull && mIsNull && !mCurrentPressEvent )
125145
{
146+
QAbstractSpinBox::focusOutEvent( event );
126147
if ( lineEdit()->text() != QgsApplication::nullRepresentation() )
127148
{
128149
displayNull();
129150
}
130-
QAbstractSpinBox::focusOutEvent( event );
131151
emit editingFinished();
132152
}
133153
else
@@ -184,15 +204,15 @@ void QgsDateTimeEdit::changed( const QDateTime &dateTime )
184204

185205
void QgsDateTimeEdit::displayNull( bool updateCalendar )
186206
{
187-
blockSignals( true );
207+
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
188208
if ( updateCalendar )
189209
{
190210
// set current time to minimum date time to avoid having
191211
// a date selected in calendar widget
192212
QDateTimeEdit::setDateTime( minimumDateTime() );
193213
}
194214
lineEdit()->setText( QgsApplication::nullRepresentation() );
195-
blockSignals( false );
215+
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
196216
}
197217

198218
void QgsDateTimeEdit::resetBeforeChange( int delta )

src/gui/editorwidgets/qgsdatetimeedit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class GUI_EXPORT QgsDateTimeEdit : public QDateTimeEdit
8888
bool mAllowNull = true;
8989
bool mIsNull = false;
9090
bool mIsEmpty = false;
91+
bool mCurrentPressEvent = false;
9192

9293
QString mOriginalStyleSheet = QString();
9394
QAction *mClearAction;

src/gui/editorwidgets/qgsdatetimeeditwrapper.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,22 @@ void QgsDateTimeEditWrapper::dateTimeChanged( const QDateTime &dateTime )
126126
emit valueChanged( dateTime.time() );
127127
break;
128128
default:
129-
const bool fieldIsoFormat = config( QStringLiteral( "field_iso_format" ), false ).toBool();
130-
const QString fieldFormat = config( QStringLiteral( "field_format" ), QgsDateTimeFieldFormatter::defaultFormat( field().type() ) ).toString();
131-
if ( fieldIsoFormat )
129+
if ( !dateTime.isValid() || dateTime.isNull() )
132130
{
133-
emit valueChanged( dateTime.toString( Qt::ISODate ) );
131+
emit valueChanged( QVariant( field().type() ) );
134132
}
135133
else
136134
{
137-
emit valueChanged( dateTime.toString( fieldFormat ) );
135+
const bool fieldIsoFormat = config( QStringLiteral( "field_iso_format" ), false ).toBool();
136+
const QString fieldFormat = config( QStringLiteral( "field_format" ), QgsDateTimeFieldFormatter::defaultFormat( field().type() ) ).toString();
137+
if ( fieldIsoFormat )
138+
{
139+
emit valueChanged( dateTime.toString( Qt::ISODate ) );
140+
}
141+
else
142+
{
143+
emit valueChanged( dateTime.toString( fieldFormat ) );
144+
}
138145
}
139146
break;
140147
}

0 commit comments

Comments
 (0)