mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-17 00:09:36 -04:00
QgsDataSourceSelectDialog: filter, refresh and scroll to last selected item
plus: - expand children of last selected item - save/restore status
This commit is contained in:
parent
4cdde31c17
commit
02ecb56d95
@ -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
|
||||
|
||||
};
|
||||
|
@ -19,8 +19,10 @@
|
||||
#include "qgssettings.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgis.h"
|
||||
#include "qgsbrowsermodel.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QMenu>
|
||||
|
||||
QgsDataSourceSelectDialog::QgsDataSourceSelectDialog(
|
||||
QgsBrowserModel *browserModel,
|
||||
@ -32,6 +34,7 @@ QgsDataSourceSelectDialog::QgsDataSourceSelectDialog(
|
||||
if ( ! browserModel )
|
||||
{
|
||||
mBrowserModel = qgis::make_unique<QgsBrowserModel>();
|
||||
mBrowserModel->initialize();
|
||||
mOwnModel = true;
|
||||
}
|
||||
else
|
||||
@ -44,12 +47,12 @@ 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
|
||||
@ -57,7 +60,55 @@ QgsDataSourceSelectDialog::QgsDataSourceSelectDialog(
|
||||
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()
|
||||
@ -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 );
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,17 @@ 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
|
||||
@ -80,6 +91,9 @@ class GUI_EXPORT QgsDataSourceSelectDialog: public QDialog, private Ui::QgsDataS
|
||||
|
||||
private:
|
||||
|
||||
//! Refresh the model
|
||||
void refreshModel( const QModelIndex &index );
|
||||
|
||||
QgsBrowserProxyModel mBrowserProxyModel;
|
||||
std::unique_ptr<QgsBrowserModel> mBrowserModel;
|
||||
bool mOwnModel = true;
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
<width>700</width>
|
||||
<height>629</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -15,7 +15,143 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QgsBrowserTreeView" name="mBrowserTreeView"/>
|
||||
<widget class="QWidget" name="mContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolBar" name="mBrowserToolbar">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<addaction name="mActionRefresh"/>
|
||||
<addaction name="mActionShowFilter"/>
|
||||
<addaction name="mActionCollapse"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="mWidgetFilter" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="mBtnFilterOptions">
|
||||
<property name="toolTip">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionOptions.svg</normaloff>:/images/themes/default/mActionOptions.svg</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::InstantPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsFilterLineEdit" name="mLeFilter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsBrowserTreeView" name="mBrowserTreeView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
@ -28,15 +164,64 @@
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
<action name="mActionRefresh">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionRefresh.svg</normaloff>:/images/themes/default/mActionRefresh.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionShowFilter">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionFilter2.svg</normaloff>:/images/themes/default/mActionFilter2.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter Browser</string>
|
||||
</property>
|
||||
<property name="iconText">
|
||||
<string>Filter Browser</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Filter Browser</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionCollapse">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionCollapseTree.svg</normaloff>:/images/themes/default/mActionCollapseTree.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Collapse All</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Collapse All</string>
|
||||
</property>
|
||||
</action>
|
||||
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsFilterLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>qgsfilterlineedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsBrowserTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>qgsbrowsertreeview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
|
Loading…
x
Reference in New Issue
Block a user