QGIS API Documentation 3.41.0-Master (cea29feecf2)
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#include "moc_qgsbrowserdockwidget_p.cpp"
22
23#include <memory>
24
25#include <QAbstractTextDocumentLayout>
26#include <QHeaderView>
27#include <QTreeView>
28#include <QMenu>
29#include <QToolButton>
30#include <QFileDialog>
31#include <QPlainTextDocumentLayout>
32#include <QSortFilterProxyModel>
33#include <QDesktopServices>
34#include <QDragEnterEvent>
35
36#include "qgsbrowsermodel.h"
37#include "qgsbrowsertreeview.h"
38#include "qgslogger.h"
39#include "qgsrasterlayer.h"
40#include "qgsvectorlayer.h"
41#include "qgsproject.h"
42#include "qgsmeshlayer.h"
43#include "qgsgui.h"
44#include "qgsnative.h"
45#include "qgsmaptoolpan.h"
46#include "qgsvectorlayercache.h"
47#include "qgsvectortilelayer.h"
50#include "qgsapplication.h"
53#include "qgspointcloudlayer.h"
54#include "qgslayeritem.h"
55#include "qgsdirectoryitem.h"
56#include "qgstiledscenelayer.h"
57
59
60
61QgsBrowserPropertiesWrapLabel::QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent )
62 : QTextEdit( text, parent )
63{
64 setReadOnly( true );
65 setFrameStyle( QFrame::NoFrame );
66 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
67 QPalette pal = palette();
68 pal.setColor( QPalette::Base, Qt::transparent );
69 setPalette( pal );
70 setLineWrapMode( QTextEdit::WidgetWidth );
71 setWordWrapMode( QTextOption::WrapAnywhere );
72 connect( document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &QgsBrowserPropertiesWrapLabel::adjustHeight );
73 setMaximumHeight( 20 );
74}
75
76void QgsBrowserPropertiesWrapLabel::adjustHeight( QSizeF size )
77{
78 const int height = static_cast<int>( size.height() ) + 2 * frameWidth();
79 setMinimumHeight( height );
80 setMaximumHeight( height );
81}
82
83QgsBrowserPropertiesWidget::QgsBrowserPropertiesWidget( QWidget *parent )
84 : QWidget( parent )
85{
86}
87
88void QgsBrowserPropertiesWidget::setWidget( QWidget *paramWidget )
89{
90 QVBoxLayout *layout = new QVBoxLayout( this );
91 layout->setContentsMargins( 0, 0, 0, 0 );
92 paramWidget->setParent( this );
93 layout->addWidget( paramWidget );
94}
95
96QgsBrowserPropertiesWidget *QgsBrowserPropertiesWidget::createWidget( QgsDataItem *item, const QgsDataItemGuiContext &context, QWidget *parent )
97{
98 QgsBrowserPropertiesWidget *propertiesWidget = nullptr;
99 // In general, we would like to show all items' paramWidget, but top level items like
100 // WMS etc. have currently too large widgets which do not fit well to browser properties widget
101 if ( item->type() == Qgis::BrowserItemType::Directory )
102 {
103 propertiesWidget = new QgsBrowserDirectoryProperties( parent );
104 propertiesWidget->setItem( item );
105 }
106 else if ( item->type() == Qgis::BrowserItemType::Layer
109 || item->type() == Qgis::BrowserItemType::Field )
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, [=] {
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( QStringLiteral( "creating temporary layer using path %1" ).arg( layerItem->path() ), 2 );
188 switch ( type )
189 {
191 {
192 QgsDebugMsgLevel( QStringLiteral( "creating raster layer" ), 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( QStringLiteral( "creating mesh layer" ), 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( QStringLiteral( "creating vector layer" ), 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( QStringLiteral( "creating vector tile layer" ), 2 );
221 mLayer = std::make_unique<QgsVectorTileLayer>( layerItem->uri(), layerItem->name() );
222 break;
223 }
224
226 {
227 QgsDebugMsgLevel( QStringLiteral( "creating point cloud layer" ), 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( QStringLiteral( "creating tiled scene layer" ), 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
276 const QString myStyle = QgsApplication::reportStyleSheet();
277 mMetadataTextBrowser->document()->setDefaultStyleSheet( myStyle );
278 mMetadataTextBrowser->setHtml( layerMetadata );
279
280 if ( mNoticeLabel->text().isEmpty() )
281 {
282 mNoticeLabel->hide();
283 }
284}
285
286void QgsBrowserLayerProperties::setCondensedMode( bool )
287{
288}
289
290void QgsBrowserLayerProperties::urlClicked( const QUrl &url )
291{
292 if ( !url.fragment().isEmpty() && url.toString().startsWith( QLatin1Char( '#' ) ) )
293 {
294 mMetadataTextBrowser->scrollToAnchor( url.fragment() );
295 return;
296 }
297 const QFileInfo file( url.toLocalFile() );
298 if ( file.exists() && !file.isDir() )
299 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
300 else
301 QDesktopServices::openUrl( url );
302}
303
304void QgsBrowserLayerProperties::loadAttributeTable()
305{
306 if ( !mLayer || !mLayer->isValid() || mLayer->type() != Qgis::LayerType::Vector )
307 return;
308
309 // Initialize the cache
310 QgsVectorLayerCache *layerCache = new QgsVectorLayerCache( qobject_cast<QgsVectorLayer *>( mLayer.get() ), 1000, this );
311 layerCache->setCacheGeometry( false );
312 QgsAttributeTableModel *tableModel = new QgsAttributeTableModel( layerCache, this );
313 mAttributeTableFilterModel = new QgsAttributeTableFilterModel( nullptr, tableModel, this );
314 tableModel->setRequest( QgsFeatureRequest().setFlags( Qgis::FeatureRequestFlag::NoGeometry ).setLimit( 100 ) );
315 layerCache->setParent( tableModel );
316 tableModel->setParent( mAttributeTableFilterModel );
317
318 mAttributeTable->setModel( mAttributeTableFilterModel );
319 tableModel->loadLayer();
320 QFont font = mAttributeTable->font();
321 int fontSize = font.pointSize();
322#ifdef Q_OS_WIN
323 fontSize = std::max( fontSize - 1, 8 ); // bit less on windows, due to poor rendering of small point sizes
324#else
325 fontSize = std::max( fontSize - 2, 6 );
326#endif
327 font.setPointSize( fontSize );
328 mAttributeTable->setFont( font );
329
330 // we can safely do this expensive operation here (unlike in the main attribute table), because at most we have only 100 rows...
331 mAttributeTable->resizeColumnsToContents();
332 mAttributeTable->resizeRowsToContents();
333 mAttributeTable->verticalHeader()->setVisible( false ); // maximize valuable table space
334 mAttributeTable->setAlternatingRowColors( true );
335}
336
337QgsBrowserDirectoryProperties::QgsBrowserDirectoryProperties( QWidget *parent )
338 : QgsBrowserPropertiesWidget( parent )
339
340{
341 setupUi( this );
342
343 mPathLabel = new QgsBrowserPropertiesWrapLabel( QString(), mHeaderWidget );
344 mHeaderGridLayout->addItem( new QWidgetItem( mPathLabel ), 0, 1 );
345}
346
347void QgsBrowserDirectoryProperties::setItem( QgsDataItem *item )
348{
349 QgsDirectoryItem *directoryItem = qobject_cast<QgsDirectoryItem *>( item );
350 if ( !item )
351 return;
352
353 mPathLabel->setText( QDir::toNativeSeparators( directoryItem->dirPath() ) );
354 mDirectoryWidget = new QgsDirectoryParamWidget( directoryItem->dirPath(), this );
355 mLayout->addWidget( mDirectoryWidget );
356}
357
358QgsBrowserPropertiesDialog::QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent )
359 : QDialog( parent )
360 , mSettingsSection( settingsSection )
361{
362 setupUi( this );
364}
365
366void QgsBrowserPropertiesDialog::setItem( QgsDataItem *item, const QgsDataItemGuiContext &context )
367{
368 if ( !item )
369 return;
370
371 mPropertiesWidget = QgsBrowserPropertiesWidget::createWidget( item, context, this );
372 mLayout->addWidget( mPropertiesWidget );
373 setWindowTitle( item->type() == Qgis::BrowserItemType::Layer ? tr( "Layer Properties" ) : tr( "Directory Properties" ) );
374}
375
376
377//
378// QgsDockBrowserTreeView
379//
380
381QgsDockBrowserTreeView::QgsDockBrowserTreeView( QWidget *parent )
382 : QgsBrowserTreeView( parent )
383{
384 setDragDropMode( QTreeView::DragDrop ); // sets also acceptDrops + dragEnabled
385 setSelectionMode( QAbstractItemView::ExtendedSelection );
386 setContextMenuPolicy( Qt::CustomContextMenu );
387 setHeaderHidden( true );
388 setDropIndicatorShown( true );
389}
390
391void QgsDockBrowserTreeView::setAction( QDropEvent *e )
392{
393 // if this mime data come from layer tree, the proposed action will be MoveAction
394 // but for browser we really need CopyAction
395 if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) && e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
396 {
397 e->setDropAction( Qt::CopyAction );
398 }
399}
400
401void QgsDockBrowserTreeView::dragEnterEvent( QDragEnterEvent *e )
402{
403 setAction( e );
404
405 // accept drag enter so that our widget will not get ignored
406 // and drag events will not get passed to QgisApp
407 e->accept();
408}
409
410void QgsDockBrowserTreeView::dragMoveEvent( QDragMoveEvent *e )
411{
412 // do not accept drops above/below items
413 /*if ( dropIndicatorPosition() != QAbstractItemView::OnItem )
414 {
415 QgsDebugMsgLevel("drag not on item", 2);
416 e->ignore();
417 return;
418 }*/
419
420 setAction( e );
421 QTreeView::dragMoveEvent( e );
422 // reset action because QTreeView::dragMoveEvent() accepts proposed action
423 setAction( e );
424
425 if ( !e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
426 {
427 e->ignore();
428 return;
429 }
430}
431
432void QgsDockBrowserTreeView::dropEvent( QDropEvent *e )
433{
434 setAction( e );
435 QTreeView::dropEvent( e );
436 // reset action because QTreeView::dropEvent() accepts proposed action
437 setAction( e );
438}
439
440
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ Layer
Represents a map layer.
@ Field
Vector layer field.
@ Custom
Custom item type.
@ Fields
Collection of fields.
@ Directory
Represents a file directory.
LayerType
Types of layers that can be added to a map.
Definition qgis.h:169
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ Vector
Vector layer.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ Raster
Raster layer.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
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 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...
The QgsBrowserTreeView class extends QTreeView with save/restore tree state 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:46
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 directory: contains subdirectories and layers.
QString dirPath() const
Returns the full path to the directory the item represents.
Browser parameter widget implementation for directory items.
This class 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:210
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition qgsgui.cpp:85
static QgsDataItemGuiProviderRegistry * dataItemGuiProviderRegistry()
Returns the global data item GUI provider registry, used for tracking providers which affect the brow...
Definition qgsgui.cpp:180
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:113
This class caches features of a given QgsVectorLayer.
void setCacheGeometry(bool cacheGeometry)
Enable or disable the caching of geometries.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:6601
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:6600
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
Setting options for loading mesh layers.
Setting options for loading point cloud layers.
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.
Setting options for loading vector layers.