Skip to content

Commit

Permalink
fix date time NULL handling (#6591)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
3nids committed Mar 12, 2018
1 parent d68107e commit ad6491d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 21 deletions.
52 changes: 36 additions & 16 deletions src/gui/editorwidgets/qgsdatetimeedit.cpp
Expand Up @@ -26,6 +26,8 @@
#include "qgsapplication.h"
#include "qgslogger.h"



QgsDateTimeEdit::QgsDateTimeEdit( QWidget *parent )
: QDateTimeEdit( parent )
{
Expand Down Expand Up @@ -70,6 +72,10 @@ void QgsDateTimeEdit::clear()
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
emit dateTimeChanged( QDateTime() );
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );

// otherwise, NULL is not displayed in the line edit
// this might not be the right way to do it
clearFocus();
}
}

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

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

bool updateCalendar = false;

if ( mIsNull )
{
QStyleOptionSpinBox opt;
this->initStyleOption( &opt );
const QRect buttonUpRect = style()->subControlRect( QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxUp );
const QRect buttonDownRect = style()->subControlRect( QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxDown );
if ( buttonUpRect.contains( event->pos() ) || buttonDownRect.contains( event->pos() ) )
QStyle::SubControl control;
if ( calendarPopup() )
{
if ( calendarPopup() && calendarWidget() )
QStyleOptionComboBox optCombo;
optCombo.init( this );
optCombo.editable = true;
optCombo.subControls = QStyle::SC_All;
control = style()->hitTestComplexControl( QStyle::CC_ComboBox, &optCombo, event->pos(), this );

if ( control == QStyle::SC_ComboBoxArrow && calendarWidget() )
{
mCurrentPressEvent = true;
// ensure the line edit still displays NULL
displayNull( true );
updateCalendar = true;
displayNull( updateCalendar );
mCurrentPressEvent = false;
}
else
}
else
{
QStyleOptionSpinBox opt;
this->initStyleOption( &opt );
control = style()->hitTestComplexControl( QStyle::CC_SpinBox, &opt, event->pos(), this );

if ( control == QStyle::SC_SpinBoxDown || control == QStyle::SC_SpinBoxUp )
{
blockSignals( true );
resetBeforeChange( buttonUpRect.contains( event->pos() ) ? -1 : 1 );
blockSignals( false );
mCurrentPressEvent = true;
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
resetBeforeChange( control == QStyle::SC_SpinBoxDown ? -1 : 1 );
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
mCurrentPressEvent = false;
}
}
}
Expand All @@ -121,13 +141,13 @@ void QgsDateTimeEdit::mousePressEvent( QMouseEvent *event )

void QgsDateTimeEdit::focusOutEvent( QFocusEvent *event )
{
if ( mAllowNull && mIsNull )
if ( mAllowNull && mIsNull && !mCurrentPressEvent )
{
QAbstractSpinBox::focusOutEvent( event );
if ( lineEdit()->text() != QgsApplication::nullRepresentation() )
{
displayNull();
}
QAbstractSpinBox::focusOutEvent( event );
emit editingFinished();
}
else
Expand Down Expand Up @@ -184,15 +204,15 @@ void QgsDateTimeEdit::changed( const QDateTime &dateTime )

void QgsDateTimeEdit::displayNull( bool updateCalendar )
{
blockSignals( true );
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
if ( updateCalendar )
{
// set current time to minimum date time to avoid having
// a date selected in calendar widget
QDateTimeEdit::setDateTime( minimumDateTime() );
}
lineEdit()->setText( QgsApplication::nullRepresentation() );
blockSignals( false );
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
}

void QgsDateTimeEdit::resetBeforeChange( int delta )
Expand Down
1 change: 1 addition & 0 deletions src/gui/editorwidgets/qgsdatetimeedit.h
Expand Up @@ -88,6 +88,7 @@ class GUI_EXPORT QgsDateTimeEdit : public QDateTimeEdit
bool mAllowNull = true;
bool mIsNull = false;
bool mIsEmpty = false;
bool mCurrentPressEvent = false;

QString mOriginalStyleSheet = QString();
QAction *mClearAction;
Expand Down
17 changes: 12 additions & 5 deletions src/gui/editorwidgets/qgsdatetimeeditwrapper.cpp
Expand Up @@ -126,15 +126,22 @@ void QgsDateTimeEditWrapper::dateTimeChanged( const QDateTime &dateTime )
emit valueChanged( dateTime.time() );
break;
default:
const bool fieldIsoFormat = config( QStringLiteral( "field_iso_format" ), false ).toBool();
const QString fieldFormat = config( QStringLiteral( "field_format" ), QgsDateTimeFieldFormatter::defaultFormat( field().type() ) ).toString();
if ( fieldIsoFormat )
if ( !dateTime.isValid() || dateTime.isNull() )
{
emit valueChanged( dateTime.toString( Qt::ISODate ) );
emit valueChanged( QVariant( field().type() ) );
}
else
{
emit valueChanged( dateTime.toString( fieldFormat ) );
const bool fieldIsoFormat = config( QStringLiteral( "field_iso_format" ), false ).toBool();
const QString fieldFormat = config( QStringLiteral( "field_format" ), QgsDateTimeFieldFormatter::defaultFormat( field().type() ) ).toString();
if ( fieldIsoFormat )
{
emit valueChanged( dateTime.toString( Qt::ISODate ) );
}
else
{
emit valueChanged( dateTime.toString( fieldFormat ) );
}
}
break;
}
Expand Down

0 comments on commit ad6491d

Please sign in to comment.