QGIS API Documentation  3.12.1-București (121cc00ff0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsdatasourceselectdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatasourceselectdialog.cpp - QgsDataSourceSelectDialog
3 
4  ---------------------
5  begin : 1.11.2018
6  copyright : (C) 2018 by Alessandro Pasotti
7  email : elpaso@itopen.it
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
18 #include "ui_qgsdatasourceselectdialog.h"
19 
20 #include "qgis.h"
21 #include "qgsbrowsermodel.h"
22 #include "qgsgui.h"
23 #include "qgsguiutils.h"
24 #include "qgssettings.h"
25 #include "qgsnative.h"
26 
27 #include <QPushButton>
28 #include <QMenu>
29 #include <QDesktopServices>
30 
32  QgsBrowserGuiModel *browserModel,
33  bool setFilterByLayerType,
34  QgsMapLayerType layerType,
35  QWidget *parent )
36  : QDialog( parent )
37 {
38  if ( ! browserModel )
39  {
40  mBrowserModel = new QgsBrowserGuiModel( this );
41  mBrowserModel->initialize();
42  }
43  else
44  {
45  mBrowserModel = browserModel;
46  mBrowserModel->initialize();
47  }
48 
49  setupUi( this );
50  setWindowTitle( tr( "Select a Data Source" ) );
52 
53  mBrowserProxyModel.setBrowserModel( mBrowserModel );
54  mBrowserTreeView->setHeaderHidden( true );
55 
56  if ( setFilterByLayerType )
57  {
58  // This will also set the (proxy) model
59  setLayerTypeFilter( layerType );
60  }
61  else
62  {
63  mBrowserTreeView->setModel( &mBrowserProxyModel );
64  buttonBox->button( QDialogButtonBox::StandardButton::Ok )->setEnabled( false );
65  }
66 
67  mBrowserTreeView->setBrowserModel( mBrowserModel );
68 
69  mWidgetFilter->hide();
70  mLeFilter->setPlaceholderText( tr( "Type here to filter visible items…" ) );
71  // icons from http://www.fatcow.com/free-icons License: CC Attribution 3.0
72 
73  QMenu *menu = new QMenu( this );
74  menu->setSeparatorsCollapsible( false );
75  mBtnFilterOptions->setMenu( menu );
76  QAction *action = new QAction( tr( "Case Sensitive" ), menu );
77  action->setData( "case" );
78  action->setCheckable( true );
79  action->setChecked( false );
80  connect( action, &QAction::toggled, this, &QgsDataSourceSelectDialog::setCaseSensitive );
81  menu->addAction( action );
82  QActionGroup *group = new QActionGroup( menu );
83  action = new QAction( tr( "Filter Pattern Syntax" ), group );
84  action->setSeparator( true );
85  menu->addAction( action );
86  action = new QAction( tr( "Normal" ), group );
87  action->setData( QgsBrowserProxyModel::Normal );
88  action->setCheckable( true );
89  action->setChecked( true );
90  menu->addAction( action );
91  action = new QAction( tr( "Wildcard(s)" ), group );
92  action->setData( QgsBrowserProxyModel::Wildcards );
93  action->setCheckable( true );
94  menu->addAction( action );
95  action = new QAction( tr( "Regular Expression" ), group );
96  action->setData( QgsBrowserProxyModel::RegularExpression );
97  action->setCheckable( true );
98  menu->addAction( action );
99 
100  mBrowserTreeView->setExpandsOnDoubleClick( false );
101 
102  connect( mActionRefresh, &QAction::triggered, this, [ = ] { refreshModel( QModelIndex() ); } );
103  connect( mBrowserTreeView, &QgsBrowserTreeView::clicked, this, &QgsDataSourceSelectDialog::onLayerSelected );
104  connect( mBrowserTreeView, &QgsBrowserTreeView::doubleClicked, this, &QgsDataSourceSelectDialog::itemDoubleClicked );
105  connect( mActionCollapse, &QAction::triggered, mBrowserTreeView, &QgsBrowserTreeView::collapseAll );
106  connect( mActionShowFilter, &QAction::triggered, this, &QgsDataSourceSelectDialog::showFilterWidget );
107  connect( mLeFilter, &QgsFilterLineEdit::returnPressed, this, &QgsDataSourceSelectDialog::setFilter );
109  connect( mLeFilter, &QgsFilterLineEdit::textChanged, this, &QgsDataSourceSelectDialog::setFilter );
110  connect( group, &QActionGroup::triggered, this, &QgsDataSourceSelectDialog::setFilterSyntax );
111 
112  mBrowserToolbar->setIconSize( QgsGuiUtils::iconSize( true ) );
113 
114  if ( QgsSettings().value( QStringLiteral( "datasourceSelectFilterVisible" ), false, QgsSettings::Section::Gui ).toBool() )
115  {
116  mActionShowFilter->trigger();
117  }
118 }
119 
121 
123 {
124  QDialog::showEvent( e );
125  QString lastSelectedPath( QgsSettings().value( QStringLiteral( "datasourceSelectLastSelectedItem" ),
126  QString(), QgsSettings::Section::Gui ).toString() );
127  if ( ! lastSelectedPath.isEmpty() )
128  {
129  QModelIndexList items = mBrowserProxyModel.match(
130  mBrowserProxyModel.index( 0, 0 ),
132  QVariant::fromValue( lastSelectedPath ),
133  1,
134  Qt::MatchRecursive );
135  if ( items.count( ) > 0 )
136  {
137  QModelIndex expandIndex = items.at( 0 );
138  if ( expandIndex.isValid() )
139  {
140  mBrowserTreeView->scrollTo( expandIndex, QgsBrowserTreeView::ScrollHint::PositionAtTop );
141  mBrowserTreeView->expand( expandIndex );
142  }
143  }
144  }
145 }
146 
148 {
149  QgsSettings().setValue( QStringLiteral( "datasourceSelectFilterVisible" ), visible, QgsSettings::Section::Gui );
150  mWidgetFilter->setVisible( visible );
151  if ( ! visible )
152  {
153  mLeFilter->setText( QString() );
154  setFilter();
155  }
156  else
157  {
158  mLeFilter->setFocus();
159  }
160 }
161 
162 void QgsDataSourceSelectDialog::setDescription( const QString &description )
163 {
164  if ( !description.isEmpty() )
165  {
166  if ( !mDescriptionLabel )
167  {
168  mDescriptionLabel = new QLabel();
169  mDescriptionLabel->setWordWrap( true );
170  mDescriptionLabel->setMargin( 4 );
171  mDescriptionLabel->setTextInteractionFlags( Qt::TextBrowserInteraction );
172  connect( mDescriptionLabel, &QLabel::linkActivated, this, [ = ]( const QString & link )
173  {
174  QUrl url( link );
175  QFileInfo file( url.toLocalFile() );
176  if ( file.exists() && !file.isDir() )
177  QgsGui::instance()->nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
178  else
179  QDesktopServices::openUrl( url );
180  } );
181  verticalLayout->insertWidget( 1, mDescriptionLabel );
182  }
183  mDescriptionLabel->setText( description );
184  }
185  else
186  {
187  if ( mDescriptionLabel )
188  {
189  verticalLayout->removeWidget( mDescriptionLabel );
190  delete mDescriptionLabel;
191  mDescriptionLabel = nullptr;
192  }
193  }
194 }
195 
197 {
198  QString filter = mLeFilter->text();
199  mBrowserProxyModel.setFilterString( filter );
200 }
201 
202 
203 void QgsDataSourceSelectDialog::refreshModel( const QModelIndex &index )
204 {
205 
206  QgsDataItem *item = mBrowserModel->dataItem( index );
207  if ( item )
208  {
209  QgsDebugMsg( "path = " + item->path() );
210  }
211  else
212  {
213  QgsDebugMsg( QStringLiteral( "invalid item" ) );
214  }
215 
216  if ( item && ( item->capabilities2() & QgsDataItem::Fertile ) )
217  {
218  mBrowserModel->refresh( index );
219  }
220 
221  for ( int i = 0; i < mBrowserModel->rowCount( index ); i++ )
222  {
223  QModelIndex idx = mBrowserModel->index( i, 0, index );
224  QModelIndex proxyIdx = mBrowserProxyModel.mapFromSource( idx );
225  QgsDataItem *child = mBrowserModel->dataItem( idx );
226 
227  // Check also expanded descendants so that the whole expanded path does not get collapsed if one item is collapsed.
228  // Fast items (usually root items) are refreshed so that when collapsed, it is obvious they are if empty (no expand symbol).
229  if ( mBrowserTreeView->isExpanded( proxyIdx ) || mBrowserTreeView->hasExpandedDescendant( proxyIdx ) || ( child && child->capabilities2() & QgsDataItem::Fast ) )
230  {
231  refreshModel( idx );
232  }
233  else
234  {
235  if ( child && ( child->capabilities2() & QgsDataItem::Fertile ) )
236  {
237  child->depopulate();
238  }
239  }
240  }
241 }
242 
243 
245 {
246  if ( !action )
247  return;
248  mBrowserProxyModel.setFilterSyntax( static_cast< QgsBrowserProxyModel::FilterSyntax >( action->data().toInt() ) );
249 }
250 
252 {
253  mBrowserProxyModel.setFilterCaseSensitivity( caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive );
254 }
255 
257 {
258  mBrowserProxyModel.setFilterByLayerType( true );
259  mBrowserProxyModel.setLayerType( layerType );
260  // reset model and button
261  mBrowserTreeView->setModel( &mBrowserProxyModel );
262  buttonBox->button( QDialogButtonBox::StandardButton::Ok )->setEnabled( false );
263 }
264 
266 {
267  return mUri;
268 }
269 
270 void QgsDataSourceSelectDialog::onLayerSelected( const QModelIndex &index )
271 {
272  bool isLayerCompatible = false;
273  mUri = QgsMimeDataUtils::Uri();
274  if ( index.isValid() )
275  {
276  const QgsDataItem *dataItem( mBrowserProxyModel.dataItem( index ) );
277  if ( dataItem )
278  {
279  const QgsLayerItem *layerItem = qobject_cast<const QgsLayerItem *>( dataItem );
280  if ( layerItem && ( ! mBrowserProxyModel.filterByLayerType() ||
281  ( layerItem->mapLayerType() == mBrowserProxyModel.layerType() ) ) )
282  {
283  isLayerCompatible = true;
284  mUri = layerItem->mimeUri();
285  // Store last viewed item
286  QgsSettings().setValue( QStringLiteral( "datasourceSelectLastSelectedItem" ), mBrowserProxyModel.data( index, QgsBrowserGuiModel::PathRole ).toString(), QgsSettings::Section::Gui );
287  }
288  }
289  }
290  buttonBox->button( QDialogButtonBox::StandardButton::Ok )->setEnabled( isLayerCompatible );
291 }
292 
293 void QgsDataSourceSelectDialog::itemDoubleClicked( const QModelIndex &index )
294 {
295  onLayerSelected( index );
296  if ( buttonBox->button( QDialogButtonBox::StandardButton::Ok )->isEnabled() )
297  accept();
298 }
299 
void setDescription(const QString &description)
Sets a description label.
QgsMimeDataUtils::Uri uri() const
Returns the (possibly invalid) uri of the selected data source.
QString path() const
Definition: qgsdataitem.h:320
void setLayerTypeFilter(QgsMapLayerType layerType)
Sets layer type filter to layerType and activates the filtering.
void setFilterSyntax(QAction *)
Sets filter syntax.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS&#39;s underlying public inte...
Definition: qgsgui.cpp:68
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void setLayerType(QgsMapLayerType type)
Sets the layer type to filter the model by.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
void setFilter()
Apply filter to the model.
QgsMapLayerType mapLayerType() const
Returns QgsMapLayerType.
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
QgsMapLayerType layerType() const
Returns the layer type to filter the model by.
QgsDataSourceSelectDialog(QgsBrowserGuiModel *browserModel=nullptr, bool setFilterByLayerType=false, QgsMapLayerType layerType=QgsMapLayerType::VectorLayer, QWidget *parent=nullptr)
Constructs a QgsDataSourceSelectDialog, optionally filtering by layer type.
virtual void depopulate()
Remove children recursively and set as not populated. This is used when refreshing collapsed items...
A model for showing available data sources and other items in a structured tree.
static QgsGui * instance()
Returns a pointer to the singleton instance.
Definition: qgsgui.cpp:62
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
Item path used to access path in the tree, see QgsDataItem::mPath.
void setCaseSensitive(bool caseSensitive)
Sets filter case sensitivity.
void showEvent(QShowEvent *e) override
Scroll to last selected index and expand it&#39;s children.
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
void initialize()
Delayed initialization, needed because the provider registry must be already populated.
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index...
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window&#39;s toolbar icons.
~QgsDataSourceSelectDialog() override
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
bool filterByLayerType() const
Returns true if the model is filtered by map layer type.
Base class for all items in the model.
Definition: qgsdataitem.h:49
Can create children. Even items without this capability may have children, but cannot create them...
Definition: qgsdataitem.h:235
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QgsMimeDataUtils::Uri mimeUri() const override
Returns mime URI for the data item.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
void cleared()
Emitted when the widget is cleared.
void refresh(const QString &path)
Refresh item specified by path.
Standard string filtering.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:133
void showFilterWidget(bool visible)
Show/hide filter widget.
Item that represents a layer that can be opened with one of the providers.
Definition: qgsdataitem.h:485
void setFilterByLayerType(bool enabled)
Sets whether the model is filtered by map layer type.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:66
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or nullptr if no item exists at the index...
CreateChildren() is fast enough to be run in main thread when refreshing items, most root items (wms...
Definition: qgsdataitem.h:236
virtual Capabilities capabilities2() const
Returns the capabilities for the data item.
Definition: qgsdataitem.h:276