QGIS API Documentation 4.3.0-Master (9b7fa678901)
Loading...
Searching...
No Matches
qgsvectortilelayerproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectortilelayerproperties.cpp
3 --------------------------------------
4 Date : May 2020
5 Copyright : (C) 2020 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsapplication.h"
20#include "qgsgui.h"
21#include "qgshelp.h"
22#include "qgsjsonutils.h"
27#include "qgsmetadatawidget.h"
33#include "qgsvectortilelayer.h"
35#include "qgsvectortileutils.h"
36
37#include <QDesktopServices>
38#include <QFileDialog>
39#include <QMenu>
40#include <QMessageBox>
41#include <QString>
42#include <QTextStream>
43
44#include "moc_qgsvectortilelayerproperties.cpp"
45
46using namespace Qt::StringLiterals;
47
48QgsVectorTileLayerProperties::QgsVectorTileLayerProperties( QgsVectorTileLayer *lyr, QgsMapCanvas *canvas, QgsMessageBar *messageBar, QWidget *parent, Qt::WindowFlags flags )
49 : QgsLayerPropertiesDialog( lyr, canvas, u"VectorTileLayerProperties"_s, parent, flags )
50 , mLayer( lyr )
51{
52 setupUi( this );
53
54 mRendererWidget = new QgsVectorTileBasicRendererWidget( nullptr, canvas, messageBar, this );
55 mOptsPage_Style->layout()->addWidget( mRendererWidget );
56 mOptsPage_Style->layout()->setContentsMargins( 0, 0, 0, 0 );
57
58 mLabelingWidget = new QgsVectorTileBasicLabelingWidget( nullptr, canvas, messageBar, this );
59 mOptsPage_Labeling->layout()->addWidget( mLabelingWidget );
60 mOptsPage_Labeling->layout()->setContentsMargins( 0, 0, 0, 0 );
61
62 connect( this, &QDialog::accepted, this, &QgsVectorTileLayerProperties::apply );
63 connect( this, &QDialog::rejected, this, &QgsVectorTileLayerProperties::rollback );
64 connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsVectorTileLayerProperties::apply );
65 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorTileLayerProperties::showHelp );
66
67 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorTileLayerProperties::crsChanged );
68
69 // scale based layer visibility related widgets
70 mScaleRangeWidget->setMapCanvas( mCanvas );
71
72 // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
73 // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
74 // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
75 initOptionsBase( false );
76
77 mSourceGroupBox->hide();
78
79 mOptsPage_Information->setContentsMargins( 0, 0, 0, 0 );
80
81 QVBoxLayout *layout = new QVBoxLayout( metadataFrame );
82 layout->setContentsMargins( 0, 0, 0, 0 );
83 metadataFrame->setContentsMargins( 0, 0, 0, 0 );
84 mMetadataWidget = new QgsMetadataWidget( this, mLayer );
85 mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
86 mMetadataWidget->setMapCanvas( mCanvas );
87 layout->addWidget( mMetadataWidget );
88 metadataFrame->setLayout( layout );
89 mOptsPage_Metadata->setContentsMargins( 0, 0, 0, 0 );
90
91 setMetadataWidget( mMetadataWidget, mOptsPage_Metadata );
92
93 mMapLayerServerPropertiesWidget->setHasWfsTitle( false );
94
95 connect( mMetadataViewer, &QTextBrowser::anchorClicked, this, &QgsVectorTileLayerProperties::openUrl );
96
97 // update based on lyr's current state
99
100 QgsSettings settings;
101 // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
102 // this will be read by restoreOptionsBaseUi()
103 if ( !settings.contains( u"/Windows/VectorTileLayerProperties/tab"_s ) )
104 {
105 settings.setValue( u"Windows/VectorTileLayerProperties/tab"_s, mOptStackedWidget->indexOf( mOptsPage_Style ) );
106 }
107
108 mBtnStyle = new QPushButton( tr( "Style" ) );
109 QMenu *menuStyle = new QMenu( this );
110 menuStyle->addAction( tr( "Load Style…" ), this, &QgsVectorTileLayerProperties::loadStyle );
111 menuStyle->addAction( tr( "Save Style…" ), this, &QgsVectorTileLayerProperties::saveStyleToFile );
112 menuStyle->addSeparator();
113 menuStyle->addAction( tr( "Save as Default" ), this, &QgsVectorTileLayerProperties::saveStyleAsDefault );
114 menuStyle->addAction( tr( "Restore Default" ), this, &QgsVectorTileLayerProperties::loadDefaultStyle );
115 mBtnStyle->setMenu( menuStyle );
116 connect( menuStyle, &QMenu::aboutToShow, this, &QgsVectorTileLayerProperties::aboutToShowStyleMenu );
117
118 buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
119
120 mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
121 QMenu *menuMetadata = new QMenu( this );
122 mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata…" ), this, &QgsVectorTileLayerProperties::loadMetadataFromFile );
123 mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata…" ), this, &QgsVectorTileLayerProperties::saveMetadataToFile );
124 mBtnMetadata->setMenu( menuMetadata );
125 buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
126
127 initialize();
128}
129
131{
132 if ( mSourceWidget )
133 {
134 const QString newSource = mSourceWidget->sourceUri();
135 if ( newSource != mLayer->source() )
136 {
137 mLayer->setDataSource( newSource, mLayer->name(), mLayer->providerType(), QgsDataProvider::ProviderOptions() );
138 }
139 }
140
141 mLayer->setName( mLayerOrigNameLineEd->text() );
142 mLayer->setCrs( mCrsSelector->crs() );
143
144 mRendererWidget->apply();
145 mLabelingWidget->apply();
146 mMetadataWidget->acceptMetadata();
147
148 mLayer->setScaleBasedVisibility( chkUseScaleDependentRendering->isChecked() );
149 mLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
150 mLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
151
152 mMapLayerServerPropertiesWidget->save();
153}
154
156{
157 if ( !mLayer )
158 return;
159
160 /*
161 * Information Tab
162 */
163 QString myStyle = QgsApplication::reportStyleSheet();
164 myStyle.append( u"body { margin: 10px; }\n "_s );
165 mMetadataViewer->clear();
166 mMetadataViewer->document()->setDefaultStyleSheet( myStyle );
167 mMetadataViewer->setHtml( mLayer->htmlMetadata() );
168
169 /*
170 * Source
171 */
172
173 mLayerOrigNameLineEd->setText( mLayer->name() );
174 mCrsSelector->setCrs( mLayer->crs() );
175
176 if ( !mSourceWidget )
177 {
178 mSourceWidget = QgsGui::sourceWidgetProviderRegistry()->createWidget( mLayer );
179 if ( mSourceWidget )
180 {
181 QHBoxLayout *layout = new QHBoxLayout();
182 layout->addWidget( mSourceWidget );
183 mSourceGroupBox->setLayout( layout );
184 if ( !mSourceWidget->groupTitle().isEmpty() )
185 mSourceGroupBox->setTitle( mSourceWidget->groupTitle() );
186 mSourceGroupBox->show();
187
188 connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [this]( bool isValid ) {
189 buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
190 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
191 } );
192 }
193 }
194
195 if ( mSourceWidget )
196 {
197 mSourceWidget->setMapCanvas( mCanvas );
198 mSourceWidget->setSourceUri( mLayer->source() );
199 }
200
201 /*
202 * Symbology Tab
203 */
204 mRendererWidget->syncToLayer( mLayer );
205
206 /*
207 * Labels Tab
208 */
209 mLabelingWidget->setLayer( mLayer );
210
211 /*
212 * Rendering
213 */
214 chkUseScaleDependentRendering->setChecked( mLayer->hasScaleBasedVisibility() );
215 mScaleRangeWidget->setScaleRange( mLayer->minimumScale(), mLayer->maximumScale() );
216
217 mMapLayerServerPropertiesWidget->setServerProperties( mLayer->serverProperties() );
218}
219
224
226{
227 const QgsSettings settings; // where we keep last used filter in persistent state
228
229 QgsMapLayerLoadStyleDialog dlg( mLayer );
230
231 if ( dlg.exec() )
232 {
233 mOldStyle = mLayer->styleManager()->style( mLayer->styleManager()->currentStyle() );
234 const QgsMapLayer::StyleCategories categories = dlg.styleCategories();
235 const QString type = dlg.fileExtension();
236 if ( type.compare( "qml"_L1, Qt::CaseInsensitive ) == 0 )
237 {
238 QString message;
239 bool defaultLoadedFlag = false;
240 const QString filePath = dlg.filePath();
241 message = mLayer->loadNamedStyle( filePath, defaultLoadedFlag, categories );
242
243 //reset if the default style was loaded OK only
244 if ( defaultLoadedFlag )
245 {
246 syncToLayer();
247 }
248 else
249 {
250 //let the user know what went wrong
251 QMessageBox::warning( this, tr( "Load Style" ), message );
252 }
253 }
254 else if ( type.compare( "json"_L1, Qt::CaseInsensitive ) == 0 )
255 {
256 QFile file( dlg.filePath() );
257 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
258 {
259 QMessageBox::warning( this, tr( "Load Style" ), tr( "Could not read %1" ).arg( QDir::toNativeSeparators( dlg.filePath() ) ) );
260 }
261 else
262 {
263 QTextStream in( &file );
264 const QString content = in.readAll();
265
267 // convert automatically from pixel sizes to millimeters, because pixel sizes
268 // are a VERY edge case in QGIS and don't play nice with hidpi map renders or print layouts
270 //assume source uses 96 dpi
271 context.setPixelSizeConversionFactor( 25.4 / 96.0 );
272
273 //load sprites
274 QVariantMap styleDefinition = QgsJsonUtils::parseJson( content ).toMap();
275
276 QFileInfo fi( dlg.filePath() );
277 QgsVectorTileUtils::loadSprites( styleDefinition, context, u"file://"_s + fi.absolutePath() );
278
280
281 if ( converter.convert( content, &context ) != QgsMapBoxGlStyleConverter::Success )
282 {
283 QMessageBox::warning( this, tr( "Load Style" ), converter.errorMessage() );
284 }
285 else
286 {
288 {
289 mLayer->setRenderer( converter.renderer().release() );
290 }
292 {
293 mLayer->setLabeling( converter.labeling().release() );
294 }
295 syncToLayer();
296 }
297 }
298 }
299 activateWindow(); // set focus back to properties dialog
300 }
301}
302
307
308void QgsVectorTileLayerProperties::aboutToShowStyleMenu()
309{
310 QMenu *m = qobject_cast<QMenu *>( sender() );
311
313 // re-add style manager actions!
314 m->addSeparator();
316}
317
318void QgsVectorTileLayerProperties::showHelp()
319{
320 const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
321
322 if ( helpPage.isValid() )
323 {
324 QgsHelp::openHelp( helpPage.toString() );
325 }
326 else
327 {
328 QgsHelp::openHelp( u"working_with_vector_tiles/vector_tiles_properties.html"_s );
329 }
330}
331
332void QgsVectorTileLayerProperties::crsChanged( const QgsCoordinateReferenceSystem &crs )
333{
334 QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mCanvas, tr( "Select Transformation" ) );
335 mLayer->setCrs( crs );
336 mMetadataWidget->crsChanged();
337}
@ Millimeters
Millimeters.
Definition qgis.h:5759
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
Represents a coordinate reference system (CRS).
static bool run(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr, const QString &windowTitle=QString())
Runs the dialog (if required) prompting for the desired transform to use from sourceCrs to destinatio...
static QgsProviderSourceWidgetProviderRegistry * sourceWidgetProviderRegistry()
Returns the registry of provider source widget providers.
Definition qgsgui.cpp:135
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:41
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned and ...
void saveMetadataToFile()
Allows the user to save the layer's metadata as a file.
virtual void rollback()
Rolls back changes made to the layer.
void saveStyleAsDefault()
Saves the current layer style as the default for the layer.
void setMetadataWidget(QgsMetadataWidget *widget, QWidget *page)
Sets the metadata widget and page associated with the dialog.
void loadDefaultStyle()
Reloads the default style for the layer.
virtual void apply()=0
Applies the dialog settings to the layer.
virtual void syncToLayer()=0
Resets the dialog to the current layer state.
void saveStyleToFile()
Allows the user to save the layer's style to a file.
QgsMapCanvas * mCanvas
Associated map canvas.
QgsLayerPropertiesDialog(QgsMapLayer *layer, QgsMapCanvas *canvas, const QString &settingsKey, QWidget *parent=nullptr, Qt::WindowFlags fl=Qt::WindowFlags(), QgsSettings *settings=nullptr)
Constructor for QgsLayerPropertiesDialog.
QgsMapLayerStyle mOldStyle
Previous layer style.
void loadMetadataFromFile()
Allows the user to load layer metadata from a file.
void initialize()
Initialize the dialog.
void openUrl(const QUrl &url)
Handles opening a url from the dialog.
Context for a MapBox GL style conversion operation.
void setTargetUnit(Qgis::RenderUnit targetUnit)
Sets the target unit type.
void setPixelSizeConversionFactor(double sizeConversionFactor)
Sets the pixel size conversion factor, used to scale the original pixel sizes when converting styles.
Handles conversion of MapBox GL styles to QGIS vector tile renderers and labeling settings.
Result convert(const QVariantMap &style, QgsMapBoxGlStyleConversionContext *context=nullptr)
Converts a JSON style map, and returns the resultant status of the conversion.
@ Success
Conversion was successful.
std::unique_ptr< QgsVectorTileLabeling > labeling() const
Returns a new instance of a vector tile labeling representing the converted style,...
QString errorMessage() const
Returns a descriptive error message if an error was encountered during the style conversion,...
std::unique_ptr< QgsVectorTileRenderer > renderer() const
Returns a new instance of a vector tile renderer representing the converted style,...
Map canvas is a class for displaying all GIS data types on a canvas.
A reusable dialog which allows users to select stored layer styles and categories to load for a map l...
QgsMapLayer::StyleCategories styleCategories() const
Returns the list of selected style categories the user has opted to load.
QString filePath() const
Returns the full path to the selected layer style source file.
QString fileExtension() const
Returns the file extension for the selected layer style source file.
void removesExtraMenuSeparators(QMenu *m)
removes extra separators from the menu
void addStyleManagerActions(QMenu *m, QgsMapLayer *layer)
adds actions to the menu in accordance to the layer
static QgsMapLayerStyleGuiUtils * instance()
returns a singleton instance of this class
QString name
Definition qgsmaplayer.h:87
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setDataSource(const QString &dataSource, const QString &baseName=QString(), const QString &provider=QString(), bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
QFlags< StyleCategory > StyleCategories
@ Symbology
Symbology.
@ Labeling
Labeling.
A bar for displaying non-blocking messages to the user.
A wizard to edit metadata on a map layer.
QStackedWidget * mOptStackedWidget
void initOptionsBase(bool restoreUi=true, const QString &title=QString())
Set up the base ui connections for vertical tabs.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void crsChanged(const QgsCoordinateReferenceSystem &crs)
Emitted when the selected CRS is changed.
QgsProviderSourceWidget * createWidget(QgsMapLayer *layer, QWidget *parent=nullptr)
Creates a new widget to configure the source of the specified layer.
void validChanged(bool isValid)
Emitted whenever the validation status of the widget changes.
virtual QString sourceUri() const =0
Returns the source URI as currently defined by the widget.
Stores settings for use within QGIS.
Definition qgssettings.h:68
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Q_DECL_DEPRECATED void saveDefaultStyle() SIP_DEPRECATED
Saves the default style when appropriate button is pressed.
Q_DECL_DEPRECATED void saveStyleAs() SIP_DEPRECATED
Saves a style when appriate button is pressed.
void loadStyle()
Loads a saved style when appropriate button is pressed.
QgsVectorTileLayerProperties(QgsVectorTileLayer *lyr, QgsMapCanvas *canvas, QgsMessageBar *messageBar, QWidget *parent=nullptr, Qt::WindowFlags=QgsGuiUtils::ModalDialogFlags)
Constructor.
Implements a map layer that is dedicated to rendering of vector tiles.
static void loadSprites(const QVariantMap &styleDefinition, QgsMapBoxGlStyleConversionContext &context, const QString &styleUrl=QString())
Downloads the sprite image and sets it to the conversion context.
Setting options for creating vector data providers.