QGIS/src/gui/qgsfeaturelistcombobox.cpp
2017-10-26 16:31:10 +02:00

238 lines
8.7 KiB
C++

/***************************************************************************
qgsfieldlistcombobox.cpp - QgsFieldListComboBox
---------------------
begin : 10.3.2017
copyright : (C) 2017 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsfeaturelistcombobox.h"
#include "qgsfeaturefiltermodel.h"
#include "qgsanimatedicon.h"
#include "qgsfilterlineedit.h"
#include "qgslogger.h"
#include <QCompleter>
#include <QLineEdit>
#include <QKeyEvent>
QgsFeatureListComboBox::QgsFeatureListComboBox( QWidget *parent )
: QComboBox( parent )
, mModel( new QgsFeatureFilterModel( this ) )
, mCompleter( new QCompleter( mModel ) )
{
mCompleter->setCaseSensitivity( Qt::CaseInsensitive );
mCompleter->setFilterMode( Qt::MatchContains );
setCompleter( mCompleter );
mCompleter->setWidget( this );
connect( mModel, &QgsFeatureFilterModel::sourceLayerChanged, this, &QgsFeatureListComboBox::sourceLayerChanged );
connect( mModel, &QgsFeatureFilterModel::displayExpressionChanged, this, &QgsFeatureListComboBox::displayExpressionChanged );
connect( mModel, &QgsFeatureFilterModel::filterExpressionChanged, this, &QgsFeatureListComboBox::filterExpressionChanged );
connect( mModel, &QgsFeatureFilterModel::isLoadingChanged, this, &QgsFeatureListComboBox::onLoadingChanged );
connect( mModel, &QgsFeatureFilterModel::filterJobCompleted, this, &QgsFeatureListComboBox::onFilterUpdateCompleted );
connect( mModel, &QgsFeatureFilterModel::allowNullChanged, this, &QgsFeatureListComboBox::allowNullChanged );
connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueChanged, this, &QgsFeatureListComboBox::identifierValueChanged );
connect( mModel, &QgsFeatureFilterModel::extraIdentifierValueIndexChanged, this, &QgsFeatureListComboBox::setCurrentIndex );
connect( mModel, &QgsFeatureFilterModel::identifierFieldChanged, this, &QgsFeatureListComboBox::identifierFieldChanged );
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::highlighted ), this, &QgsFeatureListComboBox::onItemSelected );
connect( mCompleter, static_cast<void( QCompleter::* )( const QModelIndex & )>( &QCompleter::activated ), this, &QgsFeatureListComboBox::onActivated );
connect( mModel, &QgsFeatureFilterModel::beginUpdate, this, &QgsFeatureListComboBox::storeLineEditState );
connect( mModel, &QgsFeatureFilterModel::endUpdate, this, &QgsFeatureListComboBox::restoreLineEditState );
connect( mModel, &QgsFeatureFilterModel::dataChanged, this, &QgsFeatureListComboBox::onDataChanged );
connect( this, static_cast<void( QgsFeatureListComboBox::* )( int )>( &QgsFeatureListComboBox::currentIndexChanged ), this, &QgsFeatureListComboBox::onCurrentIndexChanged );
mLineEdit = new QgsFilterLineEdit();
mLineEdit->setSelectOnFocus( true );
setEditable( true );
setLineEdit( mLineEdit );
setModel( mModel );
connect( mLineEdit, &QgsFilterLineEdit::textEdited, this, &QgsFeatureListComboBox::onCurrentTextChanged );
setToolTip( tr( "Just start typing what you are looking for." ) );
}
QgsVectorLayer *QgsFeatureListComboBox::sourceLayer() const
{
return mModel->sourceLayer();
}
void QgsFeatureListComboBox::setSourceLayer( QgsVectorLayer *sourceLayer )
{
mModel->setSourceLayer( sourceLayer );
}
QString QgsFeatureListComboBox::displayExpression() const
{
return mModel->displayExpression();
}
void QgsFeatureListComboBox::setDisplayExpression( const QString &expression )
{
mModel->setDisplayExpression( expression );
}
void QgsFeatureListComboBox::onCurrentTextChanged( const QString &text )
{
mIsCurrentlyEdited = true;
mPopupRequested = true;
mModel->setFilterValue( text );
}
void QgsFeatureListComboBox::onFilterUpdateCompleted()
{
if ( mPopupRequested )
mCompleter->complete();
mPopupRequested = false;
}
void QgsFeatureListComboBox::onLoadingChanged()
{
mLineEdit->setShowSpinner( mModel->isLoading() );
}
void QgsFeatureListComboBox::onItemSelected( const QModelIndex &index )
{
setCurrentIndex( index.row() );
}
void QgsFeatureListComboBox::onCurrentIndexChanged( int i )
{
mIsCurrentlyEdited = false;
QModelIndex modelIndex = mModel->index( i, 0, QModelIndex() );
mModel->setExtraIdentifierValue( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValueRole ) );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
mLineEdit->setFont( mModel->data( modelIndex, Qt::FontRole ).value<QFont>() );
QPalette palette = mLineEdit->palette();
palette.setBrush( mLineEdit->foregroundRole(), mModel->data( modelIndex, Qt::ForegroundRole ).value<QBrush>() );
mLineEdit->setPalette( palette );
}
void QgsFeatureListComboBox::onActivated( QModelIndex modelIndex )
{
setIdentifierValue( mModel->data( modelIndex, QgsFeatureFilterModel::IdentifierValueRole ) );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
}
void QgsFeatureListComboBox::storeLineEditState()
{
if ( mIsCurrentlyEdited )
mLineEditState.store( mLineEdit );
}
void QgsFeatureListComboBox::restoreLineEditState()
{
if ( mIsCurrentlyEdited )
mLineEditState.restore( mLineEdit );
}
void QgsFeatureListComboBox::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
{
Q_UNUSED( roles )
if ( !mIsCurrentlyEdited )
{
const int currentIndex = mModel->extraIdentifierValueIndex();
if ( currentIndex >= topLeft.row() && currentIndex <= bottomRight.row() )
{
QModelIndex modelIndex = mModel->index( currentIndex, 0, QModelIndex() );
mLineEdit->setText( mModel->data( modelIndex, QgsFeatureFilterModel::ValueRole ).toString() );
}
}
}
QString QgsFeatureListComboBox::identifierField() const
{
return mModel->identifierField();
}
void QgsFeatureListComboBox::setIdentifierField( const QString &identifierField )
{
mModel->setIdentifierField( identifierField );
}
QModelIndex QgsFeatureListComboBox::currentModelIndex() const
{
return mModel->index( mModel->extraIdentifierValueIndex(), 0, QModelIndex() );
}
void QgsFeatureListComboBox::focusOutEvent( QFocusEvent *event )
{
Q_UNUSED( event )
QComboBox::focusOutEvent( event );
mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
}
void QgsFeatureListComboBox::keyPressEvent( QKeyEvent *event )
{
if ( event->key() == Qt::Key_Escape )
{
mLineEdit->setText( mModel->data( currentModelIndex(), QgsFeatureFilterModel::ValueRole ).toString() );
}
QComboBox::keyReleaseEvent( event );
}
bool QgsFeatureListComboBox::allowNull() const
{
return mModel->allowNull();
}
void QgsFeatureListComboBox::setAllowNull( bool allowNull )
{
mModel->setAllowNull( allowNull );
}
QVariant QgsFeatureListComboBox::identifierValue() const
{
return mModel->extraIdentifierValue();
}
void QgsFeatureListComboBox::setIdentifierValue( const QVariant &identifierValue )
{
mModel->setExtraIdentifierValue( identifierValue );
}
QgsFeatureRequest QgsFeatureListComboBox::currentFeatureRequest() const
{
if ( mModel->extraIdentifierValue().isNull() )
return QgsFeatureRequest().setFilterFids( QgsFeatureIds() ); // NULL: Return a request that's guaranteed to not return anything
else
return QgsFeatureRequest().setFilterExpression( QStringLiteral( "%1 = %2" ).arg( QgsExpression::quotedColumnRef( mModel->identifierField() ), QgsExpression::quotedValue( mModel->extraIdentifierValue() ) ) );
}
QString QgsFeatureListComboBox::filterExpression() const
{
return mModel->filterExpression();
}
void QgsFeatureListComboBox::setFilterExpression( const QString &filterExpression )
{
mModel->setFilterExpression( filterExpression );
}
void QgsFeatureListComboBox::LineEditState::store( QLineEdit *lineEdit )
{
text = lineEdit->text();
selectionStart = lineEdit->selectionStart();
selectionLength = lineEdit->selectedText().length();
cursorPosition = lineEdit->cursorPosition();
}
void QgsFeatureListComboBox::LineEditState::restore( QLineEdit *lineEdit ) const
{
lineEdit->setText( text );
lineEdit->setCursorPosition( cursorPosition );
if ( selectionStart > -1 )
lineEdit->setSelection( selectionStart, selectionLength );
}