Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[date time widget] do not use minimumDateTime for NULL values
fixes issue when setting min and max values for the widget
  • Loading branch information
3nids committed Jan 3, 2018
1 parent 2129698 commit 230e91c
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 45 deletions.
6 changes: 6 additions & 0 deletions python/gui/editorwidgets/qgsdatetimeedit.sip
Expand Up @@ -68,6 +68,12 @@ Resets the widget to show no value (ie, an "unknown" state).
protected:
virtual void mousePressEvent( QMouseEvent *event );

virtual void focusOutEvent( QFocusEvent *event );

virtual void wheelEvent( QWheelEvent *event );

virtual void showEvent( QShowEvent *event );


};

Expand Down
152 changes: 110 additions & 42 deletions src/gui/editorwidgets/qgsdatetimeedit.cpp
Expand Up @@ -38,17 +38,13 @@ QgsDateTimeEdit::QgsDateTimeEdit( QWidget *parent )

connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );

// set this by default to properly connect the calendar widget
// enable calendar widget by default so it's already created
setCalendarPopup( true );
// when clearing the widget, date of the QDateTimeEdit will be set to minimum date
// hence when the calendar popups, on selection changed if it set to the minimum date,
// the page of the current date will be shown
connect( calendarWidget(), &QCalendarWidget::selectionChanged, this, &QgsDateTimeEdit::calendarSelectionChanged );

setMinimumEditDateTime();

// init with current time so mIsNull is properly initialized
QDateTimeEdit::setDateTime( QDateTime::currentDateTime() );

setMinimumEditDateTime();
}

void QgsDateTimeEdit::setAllowNull( bool allowNull )
Expand All @@ -60,12 +56,17 @@ void QgsDateTimeEdit::setAllowNull( bool allowNull )

void QgsDateTimeEdit::clear()
{
QDateTimeEdit::blockSignals( true );
setSpecialValueText( QgsApplication::nullRepresentation() );
QDateTimeEdit::setDateTime( minimumDateTime() );
QDateTimeEdit::blockSignals( false );
changed( QDateTime() );
emit dateTimeChanged( QDateTime() );
if ( mAllowNull )
{
displayNull();

changed( QDateTime() );

// avoid slot double activation
disconnect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
emit dateTimeChanged( QDateTime() );
connect( this, &QDateTimeEdit::dateTimeChanged, this, &QgsDateTimeEdit::changed );
}
}

void QgsDateTimeEdit::setEmpty()
Expand All @@ -76,51 +77,86 @@ void QgsDateTimeEdit::setEmpty()

void QgsDateTimeEdit::mousePressEvent( QMouseEvent *event )
{
// catch mouse press on the button when in non-calendar mode to modifiy the date
// so it leads to showing current date (don't bother about time)
// catch mouse press on the button
// 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 && !calendarPopup() )
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() ) )
{
int before = 1;
if ( buttonUpRect.contains( event->pos() ) )
if ( calendarPopup() && calendarWidget() )
{
before = -1;
// ensure the line edit still displays NULL
displayNull( true );
updateCalendar = true;
}

blockSignals( true );
switch ( currentSection() )
else
{
case QDateTimeEdit::DaySection:
QDateTimeEdit::setDateTime( QDateTime::currentDateTime().addDays( before ) );
break;
case QDateTimeEdit::MonthSection:
QDateTimeEdit::setDateTime( QDateTime::currentDateTime().addMonths( before ) );
break;
case QDateTimeEdit::YearSection:
QDateTimeEdit::setDateTime( QDateTime::currentDateTime().addYears( before ) );
break;
default:
QDateTimeEdit::setDateTime( QDateTime::currentDateTime() );
break;
blockSignals( true );
resetBeforeChange( buttonUpRect.contains( event->pos() ) ? -1 : 1 );
blockSignals( false );
}
blockSignals( false );
}
}

QDateTimeEdit::mousePressEvent( event );

if ( updateCalendar )
{
// set calendar page to current date to avoid going to minimal date page when value is null
calendarWidget()->setCurrentPage( QDate::currentDate().year(), QDate::currentDate().month() );
}
}

void QgsDateTimeEdit::focusOutEvent( QFocusEvent *event )
{
if ( mAllowNull && mIsNull )
{
if ( lineEdit()->text() != QgsApplication::nullRepresentation() )
{
displayNull();
}
QWidget::focusOutEvent( event );
emit editingFinished();
}
else
{
QDateTimeEdit::focusOutEvent( event );
}
}

void QgsDateTimeEdit::wheelEvent( QWheelEvent *event )
{
// dateTime might have been set to minimum in calendar mode
if ( mAllowNull && mIsNull )
{
resetBeforeChange( -event->delta() );
}
QDateTimeEdit::wheelEvent( event );
}

void QgsDateTimeEdit::showEvent( QShowEvent *event )
{
QDateTimeEdit::showEvent( event );
if ( mAllowNull && mIsNull &&
lineEdit()->text() != QgsApplication::nullRepresentation() )
{
displayNull();
}
}

void QgsDateTimeEdit::changed( const QDateTime &dateTime )
{
mIsEmpty = false;
bool isNull = dateTime.isNull() || dateTime == minimumDateTime();
if ( mIsNull != isNull )
bool isNull = dateTime.isNull();
if ( isNull != mIsNull )
{
mIsNull = isNull;
if ( mIsNull )
Expand All @@ -136,16 +172,49 @@ void QgsDateTimeEdit::changed( const QDateTime &dateTime )
lineEdit()->setStyleSheet( mOriginalStyleSheet );
}
}

mClearAction->setVisible( mAllowNull && !mIsNull );
}

void QgsDateTimeEdit::calendarSelectionChanged()
void QgsDateTimeEdit::displayNull( bool updateCalendar )
{
// set calendar page to current date to avoid going to minimal date page when value is null
if ( mAllowNull && calendarWidget() && calendarWidget()->selectedDate() == minimumDate() )
blockSignals( true );
if ( updateCalendar )
{
calendarWidget()->setCurrentPage( QDate::currentDate().year(), QDate::currentDate().month() );
// 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 );
}

void QgsDateTimeEdit::resetBeforeChange( int delta )
{
QDateTime dt = QDateTime::currentDateTime();
switch ( currentSection() )
{
case QDateTimeEdit::DaySection:
dt = dt.addDays( delta );
break;
case QDateTimeEdit::MonthSection:
dt = dt.addMonths( delta );
break;
case QDateTimeEdit::YearSection:
dt = dt.addYears( delta );
break;
default:
break;
}
if ( dt < minimumDateTime() )
{
dt = minimumDateTime();
}
else if ( dt > maximumDateTime() )
{
dt = maximumDateTime();
}
QDateTimeEdit::setDateTime( dt );
}

void QgsDateTimeEdit::setDateTime( const QDateTime &dateTime )
Expand All @@ -160,7 +229,6 @@ void QgsDateTimeEdit::setDateTime( const QDateTime &dateTime )
else
{
QDateTimeEdit::setDateTime( dateTime );
mIsNull = false;
changed( dateTime );
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/gui/editorwidgets/qgsdatetimeedit.h
Expand Up @@ -64,20 +64,26 @@ class GUI_EXPORT QgsDateTimeEdit : public QDateTimeEdit

protected:
void mousePressEvent( QMouseEvent *event ) override;
void focusOutEvent( QFocusEvent *event ) override;
void wheelEvent( QWheelEvent *event ) override;
void showEvent( QShowEvent *event ) override;

private slots:
void changed( const QDateTime &dateTime );

void calendarSelectionChanged();

private:
bool mAllowNull = true;
bool mIsNull = true;
bool mIsNull = false;
bool mIsEmpty = false;

QString mOriginalStyleSheet = QString();
QAction *mClearAction;

void displayNull( bool updateCalendar = false );

//! reset the value to current date time
void resetBeforeChange( int delta );

/**
* Set the lowest Date that can be displayed with the Qt::ISODate format
* - uses QDateTimeEdit::setMinimumDateTime (since Qt 4.4)
Expand Down

0 comments on commit 230e91c

Please sign in to comment.