QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsbrowserdockwidget_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsbrowserdockwidget_p.cpp
3
4 Private classes for QgsBrowserDockWidget
5
6 ---------------------
7 begin : May 2017
8 copyright : (C) 2017 by Alessandro Pasotti
9 real work done by : (C) 2011 by Martin Dobias
10 email : a dot pasotti at itopen dot it
11 ---------------------
12 ***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
21
22#include <memory>
23
24#include "qgsapplication.h"
27#include "qgsbrowsermodel.h"
28#include "qgsbrowsertreeview.h"
31#include "qgsdirectoryitem.h"
32#include "qgsgui.h"
33#include "qgslayeritem.h"
34#include "qgslogger.h"
35#include "qgsmaptoolpan.h"
36#include "qgsmeshlayer.h"
37#include "qgsnative.h"
38#include "qgspointcloudlayer.h"
39#include "qgsproject.h"
40#include "qgsrasterlayer.h"
41#include "qgstiledscenelayer.h"
42#include "qgsvectorlayer.h"
43#include "qgsvectorlayercache.h"
44#include "qgsvectortilelayer.h"
45
46#include <QAbstractTextDocumentLayout>
47#include <QDesktopServices>
48#include <QDragEnterEvent>
49#include <QFileDialog>
50#include <QHeaderView>
51#include <QMenu>
52#include <QPlainTextDocumentLayout>
53#include <QSortFilterProxyModel>
54#include <QString>
55#include <QToolButton>
56#include <QTreeView>
57
58#include "moc_qgsbrowserdockwidget_p.cpp"
59
60using namespace Qt::StringLiterals;
61
63
64
65QgsBrowserPropertiesWrapLabel::QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent )
66 : QTextEdit( text, parent )
67{
68 setReadOnly( true );
69 setFrameStyle( QFrame::NoFrame );
70 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
71 QPalette pal = palette();
72 pal.setColor( QPalette::Base, Qt::transparent );
73 setPalette( pal );
74 setLineWrapMode( QTextEdit::WidgetWidth );
75 setWordWrapMode( QTextOption::WrapAnywhere );
76 connect( document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &QgsBrowserPropertiesWrapLabel::adjustHeight );
77 setMaximumHeight( 20 );
78}
79
80void QgsBrowserPropertiesWrapLabel::adjustHeight( QSizeF size )
81{
82 const int height = static_cast<int>( size.height() ) + 2 * frameWidth();
83 setMinimumHeight( height );
84 setMaximumHeight( height );
85}
86
87QgsBrowserPropertiesWidget::QgsBrowserPropertiesWidget( QWidget *parent )
88 : QWidget( parent )
89{}
90
91void QgsBrowserPropertiesWidget::setWidget( QWidget *paramWidget )
92{
93 QVBoxLayout *layout = new QVBoxLayout( this );
94 layout->setContentsMargins( 0, 0, 0, 0 );
95 paramWidget->setParent( this );
96 layout->addWidget( paramWidget );
97}
98
99QgsBrowserPropertiesWidget *QgsBrowserPropertiesWidget::createWidget( QgsDataItem *item, const QgsDataItemGuiContext &context, QWidget *parent )
100{
101 QgsBrowserPropertiesWidget *propertiesWidget = nullptr;
102 // In general, we would like to show all items' paramWidget, but top level items like
103 // WMS etc. have currently too large widgets which do not fit well to browser properties widget
104 if ( item->type() == Qgis::BrowserItemType::Directory )
105 {
106 propertiesWidget = new QgsBrowserDirectoryProperties( parent );
107 propertiesWidget->setItem( item );
108 }
110 {
111 // try new infrastructure of creation of layer widgets
112 QWidget *paramWidget = nullptr;
113 const QList<QgsDataItemGuiProvider *> providers = QgsGui::dataItemGuiProviderRegistry()->providers();
114 for ( QgsDataItemGuiProvider *provider : providers )
115 {
116 paramWidget = provider->createParamWidget( item, context );
117 if ( paramWidget )
118 break;
119 }
120 if ( !paramWidget )
121 {
122 // try old infrastructure
124 paramWidget = item->paramWidget();
126 }
127
128 // prefer item's widget over standard layer widget
129 if ( paramWidget )
130 {
131 propertiesWidget = new QgsBrowserPropertiesWidget( parent );
132 propertiesWidget->setWidget( paramWidget );
133 }
134 else if ( item->type() == Qgis::BrowserItemType::Layer )
135 {
136 propertiesWidget = new QgsBrowserLayerProperties( parent );
137 propertiesWidget->setItem( item );
138 }
139 }
140 return propertiesWidget;
141}
142
143QgsBrowserLayerProperties::QgsBrowserLayerProperties( QWidget *parent )
144 : QgsBrowserPropertiesWidget( parent )
145{
146 setupUi( this );
147
148 // we don't want links to open in the little widget, open them externally instead
149 mMetadataTextBrowser->setOpenLinks( false );
150 connect( mMetadataTextBrowser, &QTextBrowser::anchorClicked, this, &QgsBrowserLayerProperties::urlClicked );
151
152 mMapCanvas->setProperty( "browser_canvas", true );
153 mMapCanvas->setLayers( QList<QgsMapLayer *>() );
154 mMapCanvas->setMapTool( new QgsMapToolPan( mMapCanvas ) );
155 mMapCanvas->freeze( true );
156
157 connect( mTabWidget, &QTabWidget::currentChanged, this, [this] {
158 if ( mTabWidget->currentWidget() == mPreviewTab && mMapCanvas->isFrozen() )
159 {
160 mMapCanvas->freeze( false );
161 mMapCanvas->refresh();
162 }
163 else if ( mTabWidget->currentWidget() == mAttributesTab )
164 {
165 if ( !mAttributeTableFilterModel )
166 loadAttributeTable();
167 }
168 } );
169}
170
171void QgsBrowserLayerProperties::setItem( QgsDataItem *item )
172{
173 QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( item );
174 if ( !layerItem )
175 return;
176
177 mNoticeLabel->clear();
178
179 const Qgis::LayerType type = layerItem->mapLayerType();
180 QString layerMetadata = tr( "Error" );
181
182 mLayer.reset();
183
184 // find root item
185 // we need to create a temporary layer to get metadata
186 // we could use a provider but the metadata is not as complete and "pretty" and this is easier
187 QgsDebugMsgLevel( u"creating temporary layer using path %1"_s.arg( layerItem->path() ), 2 );
188 switch ( type )
189 {
191 {
192 QgsDebugMsgLevel( u"creating raster layer"_s, 2 );
193 // should copy code from addLayer() to split uri ?
195 options.skipCrsValidation = true;
196 mLayer = std::make_unique<QgsRasterLayer>( layerItem->uri(), layerItem->name(), layerItem->providerKey(), options );
197 break;
198 }
199
201 {
202 QgsDebugMsgLevel( u"creating mesh layer"_s, 2 );
204 options.skipCrsValidation = true;
205 mLayer = std::make_unique<QgsMeshLayer>( layerItem->uri(), layerItem->name(), layerItem->providerKey(), options );
206 break;
207 }
208
210 {
211 QgsDebugMsgLevel( u"creating vector layer"_s, 2 );
213 options.skipCrsValidation = true;
214 mLayer = std::make_unique<QgsVectorLayer>( layerItem->uri(), layerItem->name(), layerItem->providerKey(), options );
215 break;
216 }
217
219 {
220 QgsDebugMsgLevel( u"creating vector tile layer"_s, 2 );
221 mLayer = std::make_unique<QgsVectorTileLayer>( layerItem->uri(), layerItem->name() );
222 break;
223 }
224
226 {
227 QgsDebugMsgLevel( u"creating point cloud layer"_s, 2 );
229 options.skipCrsValidation = true;
230 mLayer = std::make_unique<QgsPointCloudLayer>( layerItem->uri(), layerItem->name(), layerItem->providerKey(), options );
231 break;
232 }
233
235 {
236 QgsDebugMsgLevel( u"creating tiled scene layer"_s, 2 );
238 options.skipCrsValidation = true;
239 mLayer = std::make_unique<QgsTiledSceneLayer>( layerItem->uri(), layerItem->name(), layerItem->providerKey(), options );
240 break;
241 }
242
246 {
247 // TODO: support display of properties for plugin layers
248 return;
249 }
250 }
251
252 mAttributeTable->setModel( nullptr );
253 if ( mAttributeTableFilterModel )
254 {
255 // Cleanup
256 mAttributeTableFilterModel->deleteLater();
257 mAttributeTableFilterModel = nullptr;
258 }
259 if ( mLayer && mLayer->isValid() )
260 {
261 bool ok = false;
262 mLayer->loadDefaultMetadata( ok );
263 layerMetadata = mLayer->htmlMetadata();
264
265 mMapCanvas->setDestinationCrs( mLayer->crs() );
266 mMapCanvas->setLayers( QList<QgsMapLayer *>() << mLayer.get() );
267 mMapCanvas->zoomToFullExtent();
268
269 if ( mAttributesTab && mLayer->type() != Qgis::LayerType::Vector )
270 {
271 mTabWidget->removeTab( mTabWidget->indexOf( mAttributesTab ) );
272 mAttributesTab = nullptr;
273 }
274
275 // Remove Preview Tab if layer has no geometry
276 if ( QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer.get() ) )
277 {
278 if ( vLayer->geometryType() == Qgis::GeometryType::Null )
279 {
280 mTabWidget->removeTab( mTabWidget->indexOf( mPreviewTab ) );
281 mPreviewTab = nullptr;
282 }
283 }
284 }
285
286 const QString myStyle = QgsApplication::reportStyleSheet();
287 mMetadataTextBrowser->document()->setDefaultStyleSheet( myStyle );
288 mMetadataTextBrowser->setHtml( layerMetadata );
289
290 if ( mNoticeLabel->text().isEmpty() )
291 {
292 mNoticeLabel->hide();
293 }
294}
295
296void QgsBrowserLayerProperties::setCondensedMode( bool )
297{}
298
299void QgsBrowserLayerProperties::urlClicked( const QUrl &url )
300{
301 if ( !url.fragment().isEmpty() && url.toString().startsWith( '#'_L1 ) )
302 {
303 mMetadataTextBrowser->scrollToAnchor( url.fragment() );
304 return;
305 }
306 const QFileInfo file( url.toLocalFile() );
307 if ( file.exists() && !file.isDir() )
308 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
309 else
310 QDesktopServices::openUrl( url );
311}
312
313void QgsBrowserLayerProperties::loadAttributeTable()
314{
315 if ( !mLayer || !mLayer->isValid() || mLayer->type() != Qgis::LayerType::Vector )
316 return;
317
318 // Initialize the cache
319 QgsVectorLayerCache *layerCache = new QgsVectorLayerCache( qobject_cast<QgsVectorLayer *>( mLayer.get() ), 1000, this );
320 layerCache->setCacheGeometry( false );
321 QgsAttributeTableModel *tableModel = new QgsAttributeTableModel( layerCache, this );
322 mAttributeTableFilterModel = new QgsAttributeTableFilterModel( nullptr, tableModel, this );
323 tableModel->setRequest( QgsFeatureRequest().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 100 ) );
324 layerCache->setParent( tableModel );
325 tableModel->setParent( mAttributeTableFilterModel );
326
327 mAttributeTable->setModel( mAttributeTableFilterModel );
328 tableModel->loadLayer();
329 QFont font = mAttributeTable->font();
330 int fontSize = font.pointSize();
331#ifdef Q_OS_WIN
332 fontSize = std::max( fontSize - 1, 8 ); // bit less on windows, due to poor rendering of small point sizes
333#else
334 fontSize = std::max( fontSize - 2, 6 );
335#endif
336 font.setPointSize( fontSize );
337 mAttributeTable->setFont( font );
338
339 // we can safely do this expensive operation here (unlike in the main attribute table), because at most we have only 100 rows...
340 mAttributeTable->resizeColumnsToContents();
341 mAttributeTable->resizeRowsToContents();
342 mAttributeTable->verticalHeader()->setVisible( false ); // maximize valuable table space
343 mAttributeTable->setAlternatingRowColors( true );
344}
345
346QgsBrowserDirectoryProperties::QgsBrowserDirectoryProperties( QWidget *parent )
347 : QgsBrowserPropertiesWidget( parent )
348
349{
350 setupUi( this );
351
352 mPathLabel = new QgsBrowserPropertiesWrapLabel( QString(), mHeaderWidget );
353 mHeaderGridLayout->addItem( new QWidgetItem( mPathLabel ), 0, 1 );
354}
355
356void QgsBrowserDirectoryProperties::setItem( QgsDataItem *item )
357{
358 QgsDirectoryItem *directoryItem = qobject_cast<QgsDirectoryItem *>( item );
359 if ( !item )
360 return;
361
362 mPathLabel->setText( QDir::toNativeSeparators( directoryItem->dirPath() ) );
363 mDirectoryWidget = new QgsDirectoryParamWidget( directoryItem->dirPath(), this );
364 mLayout->addWidget( mDirectoryWidget );
365}
366
367QgsBrowserPropertiesDialog::QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent )
368 : QDialog( parent )
369 , mSettingsSection( settingsSection )
370{
371 setupUi( this );
373}
374
375void QgsBrowserPropertiesDialog::setItem( QgsDataItem *item, const QgsDataItemGuiContext &context )
376{
377 if ( !item )
378 return;
379
380 mPropertiesWidget = QgsBrowserPropertiesWidget::createWidget( item, context, this );
381 mLayout->addWidget( mPropertiesWidget );
382 setWindowTitle( item->type() == Qgis::BrowserItemType::Layer ? tr( "Layer Properties" ) : tr( "Directory Properties" ) );
383}
384
385
386//
387// QgsDockBrowserTreeView
388//
389
390QgsDockBrowserTreeView::QgsDockBrowserTreeView( QWidget *parent )
391 : QgsBrowserTreeView( parent )
392{
393 setDragDropMode( QTreeView::DragDrop ); // sets also acceptDrops + dragEnabled
394 setSelectionMode( QAbstractItemView::ExtendedSelection );
395 setContextMenuPolicy( Qt::CustomContextMenu );
396 setHeaderHidden( true );
397 setDropIndicatorShown( true );
398}
399
400void QgsDockBrowserTreeView::setAction( QDropEvent *e )
401{
402 // if this mime data come from layer tree, the proposed action will be MoveAction
403 // but for browser we really need CopyAction
404 if ( e->mimeData()->hasFormat( u"application/qgis.layertreemodeldata"_s ) && e->mimeData()->hasFormat( u"application/x-vnd.qgis.qgis.uri"_s ) )
405 {
406 e->setDropAction( Qt::CopyAction );
407 }
408}
409
410void QgsDockBrowserTreeView::dragEnterEvent( QDragEnterEvent *e )
411{
412 setAction( e );
413
414 // accept drag enter so that our widget will not get ignored
415 // and drag events will not get passed to QgisApp
416 e->accept();
417}
418
419void QgsDockBrowserTreeView::dragMoveEvent( QDragMoveEvent *e )
420{
421 // do not accept drops above/below items
422 /*if ( dropIndicatorPosition() != QAbstractItemView::OnItem )
423 {
424 QgsDebugMsgLevel("drag not on item", 2);
425 e->ignore();
426 return;
427 }*/
428
429 setAction( e );
430 QTreeView::dragMoveEvent( e );
431 // reset action because QTreeView::dragMoveEvent() accepts proposed action
432 setAction( e );
433
434 if ( !e->mimeData()->hasFormat( u"application/x-vnd.qgis.qgis.uri"_s ) )
435 {
436 e->ignore();
437 return;
438 }
439}
440
441void QgsDockBrowserTreeView::dropEvent( QDropEvent *e )
442{
443 setAction( e );
444 QTreeView::dropEvent( e );
445 // reset action because QTreeView::dropEvent() accepts proposed action
446 setAction( e );
447}
448
449
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2276
@ Layer
Represents a map layer.
Definition qgis.h:948
@ Field
Vector layer field.
Definition qgis.h:954
@ Custom
Custom item type.
Definition qgis.h:952
@ Fields
Collection of fields.
Definition qgis.h:953
@ Directory
Represents a file directory.
Definition qgis.h:947
@ Null
No geometry.
Definition qgis.h:384
LayerType
Types of layers that can be added to a map.
Definition qgis.h:206
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:214
@ Plugin
Plugin based layer.
Definition qgis.h:209
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:215
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:212
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
A proxy model for filtering an attribute table model.
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
Extends QTreeView with save/restore tree state and other browser-specific functionality.
Encapsulates the context in which a QgsDataItem is shown within the application GUI.
QList< QgsDataItemGuiProvider * > providers() const
Returns the list of available providers.
Abstract base class for providers which affect how QgsDataItem items behave within the application GU...
Base class for all items in the model.
Definition qgsdataitem.h:50
Qgis::BrowserItemType type() const
QString name() const
Returns the name of the item (the displayed text for the item).
QString path() const
virtual Q_DECL_DEPRECATED QWidget * paramWidget()
Returns source widget from data item for QgsBrowserPropertiesWidget.
QString providerKey() const
Returns the provider key that created this item (e.g.
A browser item for directories: contains subdirectories and layers.
QString dirPath() const
Returns the full path to the directory the item represents.
Browser parameter widget implementation for directory items.
Wraps a request for features to a vector layer (or directly its vector data provider).
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:224
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition qgsgui.cpp:99
static QgsDataItemGuiProviderRegistry * dataItemGuiProviderRegistry()
Returns the global data item GUI provider registry, used for tracking providers which affect the brow...
Definition qgsgui.cpp:194
A browser item that represents a layer that can be opened with one of the providers.
QString uri() const
Returns layer uri or empty string if layer cannot be created.
Qgis::LayerType mapLayerType() const
Returns the associated map layer type.
A map tool for panning the map.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:120
Caches features for a given QgsVectorLayer.
void setCacheGeometry(bool cacheGeometry)
Enable or disable the caching of geometries.
Represents a vector layer which manages a vector based dataset.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7504
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7503
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
Setting options for loading mesh layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Setting options for loading point cloud layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Setting options for loading raster layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Setting options for loading tiled scene layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Setting options for loading vector layers.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.