Skip to content

Commit

Permalink
QgsDataSourceSelectDialog: filter, refresh and scroll to last selecte…
Browse files Browse the repository at this point in the history
…d item

plus:
- expand children of last selected item
- save/restore status
  • Loading branch information
elpaso committed Nov 7, 2018
1 parent 4cdde31 commit 02ecb56
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 5 deletions.
22 changes: 22 additions & 0 deletions python/gui/auto_generated/qgsdatasourceselectdialog.sip.in
Expand Up @@ -55,6 +55,28 @@ Sets layer type filter to ``layerType`` and activates the filtering
QgsMimeDataUtils::Uri uri() const;
%Docstring
Returns the (possibly invalid) uri of the selected data source
%End

void showFilterWidget( bool visible );
%Docstring
Show/hide filter widget
%End
void setFilterSyntax( QAction * );
%Docstring
Sets filter syntax
%End
void setCaseSensitive( bool caseSensitive );
%Docstring
Sets filter case sensitivity
%End
void setFilter();
%Docstring
Apply filter to the model
%End
virtual void showEvent( QShowEvent *e );

%Docstring
Scroll to last selected index and expand it's children
%End

};
Expand Down
156 changes: 155 additions & 1 deletion src/gui/qgsdatasourceselectdialog.cpp
Expand Up @@ -19,8 +19,10 @@
#include "qgssettings.h"
#include "qgsgui.h"
#include "qgis.h"
#include "qgsbrowsermodel.h"

#include <QPushButton>
#include <QMenu>

QgsDataSourceSelectDialog::QgsDataSourceSelectDialog(
QgsBrowserModel *browserModel,
Expand All @@ -32,6 +34,7 @@ QgsDataSourceSelectDialog::QgsDataSourceSelectDialog(
if ( ! browserModel )
{
mBrowserModel = qgis::make_unique<QgsBrowserModel>();
mBrowserModel->initialize();
mOwnModel = true;
}
else
Expand All @@ -44,20 +47,68 @@ QgsDataSourceSelectDialog::QgsDataSourceSelectDialog(
setWindowTitle( tr( "Select a Data Source" ) );
QgsGui::enableAutoGeometryRestore( this );

mBrowserModel->initialize();
mBrowserProxyModel.setBrowserModel( mBrowserModel.get() );
mBrowserTreeView->setHeaderHidden( true );

if ( setFilterByLayerType )
{
// This will also set the (proxy) model
setLayerTypeFilter( layerType );
}
else
{
mBrowserTreeView->setModel( &mBrowserProxyModel );
buttonBox->button( QDialogButtonBox::StandardButton::Ok )->setEnabled( false );
}

mBrowserTreeView->setBrowserModel( mBrowserModel.get() );

mWidgetFilter->hide();
mLeFilter->setPlaceholderText( tr( "Type here to filter visible items…" ) );
// icons from http://www.fatcow.com/free-icons License: CC Attribution 3.0

QMenu *menu = new QMenu( this );
menu->setSeparatorsCollapsible( false );
mBtnFilterOptions->setMenu( menu );
QAction *action = new QAction( tr( "Case Sensitive" ), menu );
action->setData( "case" );
action->setCheckable( true );
action->setChecked( false );
connect( action, &QAction::toggled, this, &QgsDataSourceSelectDialog::setCaseSensitive );
menu->addAction( action );
QActionGroup *group = new QActionGroup( menu );
action = new QAction( tr( "Filter Pattern Syntax" ), group );
action->setSeparator( true );
menu->addAction( action );
action = new QAction( tr( "Normal" ), group );
action->setData( QgsBrowserProxyModel::Normal );
action->setCheckable( true );
action->setChecked( true );
menu->addAction( action );
action = new QAction( tr( "Wildcard(s)" ), group );
action->setData( QgsBrowserProxyModel::Wildcards );
action->setCheckable( true );
menu->addAction( action );
action = new QAction( tr( "Regular Expression" ), group );
action->setData( QgsBrowserProxyModel::RegularExpression );
action->setCheckable( true );
menu->addAction( action );

mBrowserTreeView->setExpandsOnDoubleClick( false );

connect( mActionRefresh, &QAction::triggered, [ = ] { refreshModel( QModelIndex() ); } );
connect( mBrowserTreeView, &QgsBrowserTreeView::clicked, this, &QgsDataSourceSelectDialog::onLayerSelected );
connect( mActionCollapse, &QAction::triggered, mBrowserTreeView, &QgsBrowserTreeView::collapseAll );
connect( mActionShowFilter, &QAction::triggered, this, &QgsDataSourceSelectDialog::showFilterWidget );
connect( mLeFilter, &QgsFilterLineEdit::returnPressed, this, &QgsDataSourceSelectDialog::setFilter );
connect( mLeFilter, &QgsFilterLineEdit::cleared, this, &QgsDataSourceSelectDialog::setFilter );
connect( mLeFilter, &QgsFilterLineEdit::textChanged, this, &QgsDataSourceSelectDialog::setFilter );
connect( group, &QActionGroup::triggered, this, &QgsDataSourceSelectDialog::setFilterSyntax );

if ( QgsSettings().value( QStringLiteral( "datasourceSelectFilterVisible" ), false, QgsSettings::Section::Gui ).toBool() )
{
mActionShowFilter->trigger();
}
}

QgsDataSourceSelectDialog::~QgsDataSourceSelectDialog()
Expand All @@ -66,6 +117,107 @@ QgsDataSourceSelectDialog::~QgsDataSourceSelectDialog()
mBrowserModel.release();
}


void QgsDataSourceSelectDialog::showEvent( QShowEvent *e )
{
QDialog::showEvent( e );
QString lastSelectedPath( QgsSettings().value( QStringLiteral( "datasourceSelectLastSelectedItem" ),
QString(), QgsSettings::Section::Gui ).toString() );
if ( ! lastSelectedPath.isEmpty() )
{
QModelIndexList items = mBrowserProxyModel.match(
mBrowserProxyModel.index( 0, 0 ),
QgsBrowserModel::PathRole,
QVariant::fromValue( lastSelectedPath ),
1,
Qt::MatchRecursive );
if ( items.count( ) > 0 )
{
QModelIndex expandIndex = items.at( 0 );
if ( expandIndex.isValid() )
{
mBrowserTreeView->scrollTo( expandIndex, QgsBrowserTreeView::QgsBrowserTreeView::ScrollHint::PositionAtTop );
mBrowserTreeView->expand( expandIndex );
}
}
}
}

void QgsDataSourceSelectDialog::showFilterWidget( bool visible )
{
QgsSettings().setValue( QStringLiteral( "datasourceSelectFilterVisible" ), visible, QgsSettings::Section::Gui );
mWidgetFilter->setVisible( visible );
if ( ! visible )
{
mLeFilter->setText( QString() );
setFilter();
}
else
{
mLeFilter->setFocus();
}
}

void QgsDataSourceSelectDialog::setFilter()
{
QString filter = mLeFilter->text();
mBrowserProxyModel.setFilterString( filter );
}


void QgsDataSourceSelectDialog::refreshModel( const QModelIndex &index )
{

QgsDataItem *item = mBrowserModel->dataItem( index );
if ( item )
{
QgsDebugMsg( "path = " + item->path() );
}
else
{
QgsDebugMsg( QStringLiteral( "invalid item" ) );
}

if ( item && ( item->capabilities2() & QgsDataItem::Fertile ) )
{
mBrowserModel->refresh( index );
}

for ( int i = 0; i < mBrowserModel->rowCount( index ); i++ )
{
QModelIndex idx = mBrowserModel->index( i, 0, index );
QModelIndex proxyIdx = mBrowserProxyModel.mapFromSource( idx );
QgsDataItem *child = mBrowserModel->dataItem( idx );

// Check also expanded descendants so that the whole expanded path does not get collapsed if one item is collapsed.
// Fast items (usually root items) are refreshed so that when collapsed, it is obvious they are if empty (no expand symbol).
if ( mBrowserTreeView->isExpanded( proxyIdx ) || mBrowserTreeView->hasExpandedDescendant( proxyIdx ) || ( child && child->capabilities2() & QgsDataItem::Fast ) )
{
refreshModel( idx );
}
else
{
if ( child && ( child->capabilities2() & QgsDataItem::Fertile ) )
{
child->depopulate();
}
}
}
}


void QgsDataSourceSelectDialog::setFilterSyntax( QAction *action )
{
if ( !action )
return;
mBrowserProxyModel.setFilterSyntax( static_cast< QgsBrowserProxyModel::FilterSyntax >( action->data().toInt() ) );
}

void QgsDataSourceSelectDialog::setCaseSensitive( bool caseSensitive )
{
mBrowserProxyModel.setFilterCaseSensitivity( caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive );
}

void QgsDataSourceSelectDialog::setLayerTypeFilter( QgsMapLayer::LayerType layerType )
{
mBrowserProxyModel.setFilterByLayerType( true );
Expand Down Expand Up @@ -95,6 +247,8 @@ void QgsDataSourceSelectDialog::onLayerSelected( const QModelIndex &index )
{
isLayerCompatible = true;
mUri = layerItem->mimeUri();
// Store last viewed item
QgsSettings().setValue( QStringLiteral( "datasourceSelectLastSelectedItem" ), mBrowserProxyModel.data( index, QgsBrowserModel::PathRole ).toString(), QgsSettings::Section::Gui );
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/gui/qgsdatasourceselectdialog.h
Expand Up @@ -73,13 +73,27 @@ class GUI_EXPORT QgsDataSourceSelectDialog: public QDialog, private Ui::QgsDataS
*/
QgsMimeDataUtils::Uri uri() const;

//! Show/hide filter widget
void showFilterWidget( bool visible );
//! Sets filter syntax
void setFilterSyntax( QAction * );
//! Sets filter case sensitivity
void setCaseSensitive( bool caseSensitive );
//! Apply filter to the model
void setFilter();
//! Scroll to last selected index and expand it's children
void showEvent( QShowEvent *e ) override;

private slots:

//! Triggered when a layer is selected in the browser
void onLayerSelected( const QModelIndex &index );

private:

//! Refresh the model
void refreshModel( const QModelIndex &index );

QgsBrowserProxyModel mBrowserProxyModel;
std::unique_ptr<QgsBrowserModel> mBrowserModel;
bool mOwnModel = true;
Expand Down

0 comments on commit 02ecb56

Please sign in to comment.