QGIS API Documentation 4.3.0-Master (eb72899e5dc)
Loading...
Searching...
No Matches
qgsmanageconnectionsdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmanageconnectionsdialog.cpp
3 ---------------------
4 begin : Dec 2009
5 copyright : (C) 2009 by Alexander Bruy
6 email : alexander dot bruy at gmail dot com
7
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
19#include "qgsfileutils.h"
20#include "qgsgdalcloudconnection.h"
21#include "qgshttpheaders.h"
22#include "qgsowsconnection.h"
24#include "qgssettings.h"
27#include "qgsstacconnection.h"
30
31#include <QCloseEvent>
32#include <QFileDialog>
33#include <QMessageBox>
34#include <QPushButton>
35#include <QString>
36#include <QTextStream>
37
38#include "moc_qgsmanageconnectionsdialog.cpp"
39
40using namespace Qt::StringLiterals;
41
42namespace
43{
44 enum class ActionOnDuplicate
45 {
46 Overwrite,
47 Skip,
48 Cancel
49 };
50
51 static bool loadDocument( QWidget *parent, const QString &fileName, QDomDocument &document )
52 {
53 QFile file( fileName );
54 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
55 {
56 QMessageBox::warning(
57 parent,
58 QCoreApplication::translate( "QgsManageConnectionsDialog", "Loading Connections" ),
59 QCoreApplication::translate( "QgsManageConnectionsDialog", "Cannot read file %1:\n%2." ).arg( fileName, file.errorString() )
60 );
61 return false;
62 }
63
64 QString errorString;
65 int errorLine;
66 int errorColumn;
67
68 if ( !document.setContent( &file, true, &errorString, &errorLine, &errorColumn ) )
69 {
70 // try without namespace processing, as file might miss namespace declarations
71 // see https://github.com/qgis/QGIS/issues/65477
72 file.seek( 0 );
73 if ( !document.setContent( &file, false, &errorString, &errorLine, &errorColumn ) )
74 {
75 QMessageBox::warning(
76 parent,
77 QCoreApplication::translate( "QgsManageConnectionsDialog", "Loading Connections" ),
78 QCoreApplication::translate( "QgsManageConnectionsDialog", "Parse error at line %1, column %2:\n%3" ).arg( errorLine ).arg( errorColumn ).arg( errorString )
79 );
80 return false;
81 }
82 }
83
84 return true;
85 }
86
87 static ActionOnDuplicate checkOverwritePrompt( QWidget *parent, const QString &connectionName, bool &prompt, bool &overwrite )
88 {
89 if ( prompt )
90 {
91 const int result = QMessageBox::warning(
92 parent,
93 QCoreApplication::translate( "QgsManageConnectionsDialog", "Loading Connections" ),
94 QCoreApplication::translate( "QgsManageConnectionsDialog", "Connection with name '%1' already exists. Overwrite?" ).arg( connectionName ),
95 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
96 );
97 switch ( result )
98 {
99 case QMessageBox::Yes:
100 overwrite = true;
101 break;
102 case QMessageBox::YesToAll:
103 prompt = false;
104 overwrite = true;
105 break;
106 case QMessageBox::No:
107 overwrite = false;
108 break;
109 case QMessageBox::NoToAll:
110 prompt = false;
111 overwrite = false;
112 break;
113 case QMessageBox::Cancel:
114 default:
115 return ActionOnDuplicate::Cancel;
116 }
117 }
118 return overwrite ? ActionOnDuplicate::Overwrite : ActionOnDuplicate::Skip;
119 }
120
132 static void saveDatabaseConnection( QDomElement &element, const QgsSettings &settings, const QString &path, const QStringList &keys, const QVariantMap &defaults = {} )
133 {
134 for ( const QString &key : keys )
135 {
136 const QVariant defaultValue = defaults.value( key, QString() );
137 element.setAttribute( key, settings.value( path + u'/' + key, defaultValue ).toString() );
138 }
139
140 const bool saveUsername = settings.value( path + "/saveUsername"_L1, "false"_L1 ).toString() == "true"_L1;
141 element.setAttribute( u"saveUsername"_s, saveUsername ? u"true"_s : u"false"_s );
142 if ( saveUsername )
143 {
144 element.setAttribute( u"username"_s, settings.value( path + "/username"_L1 ).toString() );
145 }
146 const bool savePassword = settings.value( path + "/savePassword"_L1, "false"_L1 ).toString() == "true"_L1;
147 element.setAttribute( u"savePassword"_s, savePassword ? u"true"_s : u"false"_s );
148 if ( savePassword )
149 {
150 element.setAttribute( u"password"_s, settings.value( path + "/password"_L1 ).toString() );
151 }
152 }
153
166 static void loadDatabaseConnection( const QDomElement &element, QgsSettings &settings, const QStringList &keys, const QVariantMap &defaults = {} )
167 {
168 for ( const QString &key : keys )
169 {
170 const QString defaultValue = defaults.value( key, QString() ).toString();
171 settings.setValue( u'/' + key, element.attribute( key, defaultValue ) );
172 }
173
174 settings.setValue( u"/saveUsername"_s, element.attribute( u"saveUsername"_s ) );
175 settings.setValue( u"/username"_s, element.attribute( u"username"_s ) );
176 settings.setValue( u"/savePassword"_s, element.attribute( u"savePassword"_s ) );
177 settings.setValue( u"/password"_s, element.attribute( u"password"_s ) );
178 }
179
180 static QString rootTagForConnectionType( QgsManageConnectionsDialog::Type type )
181 {
182 switch ( type )
183 {
185 return u"qgsWMSConnections"_s;
187 return u"qgsWFSConnections"_s;
189 return u"qgsWCSConnections"_s;
191 return u"qgsPgConnections"_s;
193 return u"qgsMssqlConnections"_s;
195 return u"qgsOracleConnections"_s;
197 return u"qgsHanaConnections"_s;
199 return u"qgsXyzTilesConnections"_s;
202 return u"qgsArcgisConnections"_s;
204 return u"qgsVectorTileConnections"_s;
206 return u"qgsTiledSceneConnections"_s;
208 return u"qgsSensorThingsConnections"_s;
210 return u"qgsCloudStorageConnections"_s;
212 return u"qgsStacConnections"_s;
213 }
214 return QString();
215 }
216 static bool checkRootTag( QWidget *parent, const QDomDocument &document, const QString &expectedTag )
217 {
218 const QDomElement root = document.documentElement();
219 if ( expectedTag.isEmpty() || root.tagName() != expectedTag )
220 {
221 QMessageBox::information( parent, QCoreApplication::translate( "QgsManageConnectionsDialog", "Loading Connections" ), QCoreApplication::translate( "QgsManageConnectionsDialog", "The file is not a valid connections exchange file for the selected service." ) );
222 return false;
223 }
224 return true;
225 }
226
227 static bool isValidDocumentType( QWidget *parent, const QDomDocument &document, QgsManageConnectionsDialog::Type type )
228 {
229 return checkRootTag( parent, document, rootTagForConnectionType( type ) );
230 }
231
232 static bool isValidDocumentType( QWidget *parent, const QDomDocument &document, const QString &service )
233 {
234 return checkRootTag( parent, document, u"qgs"_s + service.toUpper() + u"Connections"_s );
235 }
236
237 static void addNamespaceDeclarations( QDomElement &root, const QMap<QString, QString> &namespaceDeclarations )
238 {
239 for ( auto it = namespaceDeclarations.begin(); it != namespaceDeclarations.end(); ++it )
240 {
241 root.setAttribute( u"xmlns:"_s + it.key(), it.value() );
242 }
243 }
244} // namespace
245
249
250QgsManageConnectionsDialog::QgsManageConnectionsDialog( QWidget *parent, Mode mode, Type type, const QString &fileName )
251 : QDialog( parent )
252 , mFileName( fileName )
253 , mDialogMode( mode )
254 , mConnectionType( type )
255{
256 setupUi( this );
257
258 // additional buttons
259 QPushButton *pb = nullptr;
260 pb = new QPushButton( tr( "Select All" ) );
261 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
262 connect( pb, &QAbstractButton::clicked, this, &QgsManageConnectionsDialog::selectAll );
263
264 pb = new QPushButton( tr( "Clear Selection" ) );
265 buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
266 connect( pb, &QAbstractButton::clicked, this, &QgsManageConnectionsDialog::clearSelection );
267
268 if ( mDialogMode == Import )
269 {
270 label->setText( tr( "Select connections to import" ) );
271 buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Import" ) );
272 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
273 }
274 else
275 {
276 //label->setText( tr( "Select connections to export" ) );
277 buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Export" ) );
278 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
279 }
280
281 if ( !populateConnections() )
282 {
283 QApplication::postEvent( this, new QCloseEvent() );
284 }
285
286 // use OK button for starting import and export operations
287 disconnect( buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
288 connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsManageConnectionsDialog::doExportImport );
289
290 connect( listConnections, &QListWidget::itemSelectionChanged, this, &QgsManageConnectionsDialog::selectionChanged );
291}
292
294{
295 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( !listConnections->selectedItems().isEmpty() );
296}
297
299{
300 const QList<QListWidgetItem *> selection = listConnections->selectedItems();
301 if ( selection.isEmpty() )
302 {
303 QMessageBox::warning( this, tr( "Export/Import Error" ), tr( "You should select at least one connection from list." ) );
304 return;
305 }
306
307 QStringList items;
308 items.reserve( selection.size() );
309 for ( int i = 0; i < selection.size(); ++i )
310 {
311 items.append( selection.at( i )->text() );
312 }
313
314 if ( mDialogMode == Export )
315 {
316 QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Connections" ), QDir::homePath(), tr( "XML files (*.xml *.XML)" ) );
317 // return dialog focus on Mac
318 activateWindow();
319 raise();
320 if ( fileName.isEmpty() )
321 {
322 return;
323 }
324
325
326 fileName = QgsFileUtils::ensureFileNameHasExtension( fileName, { "xml" } );
327 mFileName = fileName;
328
329 QDomDocument doc;
330 switch ( mConnectionType )
331 {
332 case WMS:
333 doc = saveOWSConnections( items, u"WMS"_s );
334 break;
335 case WFS:
336 doc = saveWfsConnections( items );
337 break;
338 case PostGIS:
339 doc = savePgConnections( items );
340 break;
341 case MSSQL:
342 doc = saveMssqlConnections( items );
343 break;
344 case WCS:
345 doc = saveOWSConnections( items, u"WCS"_s );
346 break;
347 case Oracle:
348 doc = saveOracleConnections( items );
349 break;
350 case HANA:
351 doc = saveHanaConnections( items );
352 break;
353 case XyzTiles:
354 doc = saveXyzTilesConnections( items );
355 break;
356 case ArcgisMapServer:
358 doc = saveArcgisConnections( items );
359 break;
360 case VectorTile:
361 doc = saveVectorTileConnections( items );
362 break;
363 case TiledScene:
364 doc = saveTiledSceneConnections( items );
365 break;
366 case SensorThings:
367 doc = saveSensorThingsConnections( items );
368 break;
369 case CloudStorage:
370 doc = saveCloudStorageConnections( items );
371 break;
372 case STAC:
373 doc = saveStacConnections( items );
374 break;
375 }
376
377 QFile file( mFileName );
378 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
379 {
380 QMessageBox::warning( this, tr( "Saving Connections" ), tr( "Cannot write file %1:\n%2." ).arg( mFileName, file.errorString() ) );
381 return;
382 }
383
384 QTextStream out( &file );
385 doc.save( out, 4 );
386 }
387 else // import connections
388 {
389 QDomDocument doc;
390
391 if ( !loadDocument( this, mFileName, doc ) )
392 {
393 return;
394 }
395
396 switch ( mConnectionType )
397 {
398 case WMS:
399 loadOWSConnections( doc, items, u"WMS"_s );
400 break;
401 case WFS:
402 loadWfsConnections( doc, items );
403 break;
404 case PostGIS:
405 loadPgConnections( doc, items );
406 break;
407 case MSSQL:
408 loadMssqlConnections( doc, items );
409 break;
410 case WCS:
411 loadOWSConnections( doc, items, u"WCS"_s );
412 break;
413 case Oracle:
414 loadOracleConnections( doc, items );
415 break;
416 case HANA:
417 loadHanaConnections( doc, items );
418 break;
419 case XyzTiles:
420 loadXyzTilesConnections( doc, items );
421 break;
422 case ArcgisMapServer:
423 loadArcgisConnections( doc, items, u"ARCGISMAPSERVER"_s );
424 break;
426 loadArcgisConnections( doc, items, u"ARCGISFEATURESERVER"_s );
427 break;
428 case VectorTile:
429 loadVectorTileConnections( doc, items );
430 break;
431 case TiledScene:
432 loadTiledSceneConnections( doc, items );
433 break;
434 case SensorThings:
435 loadSensorThingsConnections( doc, items );
436 break;
437 case CloudStorage:
438 loadCloudStorageConnections( doc, items );
439 break;
440 case STAC:
441 loadStacConnections( doc, items );
442 break;
443 }
444 // clear connections list and close window
445 listConnections->clear();
446 accept();
447 }
448
449 mFileName.clear();
450}
451
452bool QgsManageConnectionsDialog::populateConnections()
453{
454 // Export mode. Populate connections list from settings
455 if ( mDialogMode == Export )
456 {
457 QStringList connections;
458 QgsSettings settings;
459 switch ( mConnectionType )
460 {
461 case WMS:
462 connections = QgsOwsConnection::sTreeOwsConnections->items( { u"wms"_s } );
463 break;
464 case WFS:
465 connections = QgsOwsConnection::sTreeOwsConnections->items( { u"wfs"_s } );
466 break;
467 case WCS:
468 connections = QgsOwsConnection::sTreeOwsConnections->items( { u"wcs"_s } );
469 break;
470 case PostGIS:
471 settings.beginGroup( u"/PostgreSQL/connections"_s );
472 connections = settings.childGroups();
473 break;
474 case MSSQL:
475 settings.beginGroup( u"/MSSQL/connections"_s );
476 connections = settings.childGroups();
477 break;
478 case Oracle:
479 settings.beginGroup( u"/Oracle/connections"_s );
480 connections = settings.childGroups();
481 break;
482 case HANA:
483 settings.beginGroup( u"/HANA/connections"_s );
484 connections = settings.childGroups();
485 break;
486 case XyzTiles:
488 break;
489 case ArcgisMapServer:
492 break;
493 case VectorTile:
494 connections = QgsVectorTileProviderConnection::sTreeConnectionVectorTile->items();
495 break;
496 case TiledScene:
497 connections = QgsTiledSceneProviderConnection::sTreeConnectionTiledScene->items();
498 break;
499 case SensorThings:
500 connections = QgsSensorThingsProviderConnection::sTreeSensorThingsConnections->items();
501 break;
502 case CloudStorage:
503 connections = QgsGdalCloudProviderConnection::sTreeConnectionCloud->items();
504 break;
505 case STAC:
506 connections = QgsStacConnection::sTreeConnectionStac->items();
507 break;
508 }
509 for ( const QString &connection : std::as_const( connections ) )
510 {
511 QListWidgetItem *item = new QListWidgetItem();
512 item->setText( connection );
513 listConnections->addItem( item );
514 }
515 }
516 // Import mode. Populate connections list from file
517 else
518 {
519 QDomDocument doc;
520 if ( !loadDocument( this, mFileName, doc ) )
521 {
522 return false;
523 }
524
525 if ( !isValidDocumentType( this, doc, mConnectionType ) )
526 {
527 return false;
528 }
529
530 const QDomElement root = doc.documentElement();
531 QDomElement child = root.firstChildElement();
532 while ( !child.isNull() )
533 {
534 QListWidgetItem *item = new QListWidgetItem();
535 item->setText( child.attribute( u"name"_s ) );
536 listConnections->addItem( item );
537 child = child.nextSiblingElement();
538 }
539 }
540 return true;
541}
542
543QDomDocument QgsManageConnectionsDialog::saveOWSConnections( const QStringList &connections, const QString &service )
544{
545 QDomDocument doc( u"connections"_s );
546 QDomElement root = doc.createElement( "qgs" + service.toUpper() + "Connections" );
547 root.setAttribute( u"version"_s, u"1.0"_s );
548 doc.appendChild( root );
549
550 QMap<QString, QString> namespaceDeclarations;
551 for ( int i = 0; i < connections.count(); ++i )
552 {
553 QDomElement el = doc.createElement( service.toLower() );
554 el.setAttribute( u"name"_s, connections[i] );
555 el.setAttribute( u"url"_s, QgsOwsConnection::settingsUrl->value( { service.toLower(), connections[i] } ) );
556
557 if ( service == "WMS"_L1 )
558 {
559 el.setAttribute( u"ignoreGetMapURI"_s, QgsOwsConnection::settingsIgnoreGetMapURI->value( { service.toLower(), connections[i] } ) );
560 el.setAttribute( u"ignoreGetFeatureInfoURI"_s, QgsOwsConnection::settingsIgnoreGetFeatureInfoURI->value( { service.toLower(), connections[i] } ) );
561 el.setAttribute( u"ignoreAxisOrientation"_s, QgsOwsConnection::settingsIgnoreAxisOrientation->value( { service.toLower(), connections[i] } ) );
562 el.setAttribute( u"invertAxisOrientation"_s, QgsOwsConnection::settingsInvertAxisOrientation->value( { service.toLower(), connections[i] } ) );
563 el.setAttribute( u"smoothPixmapTransform"_s, QgsOwsConnection::settingsSmoothPixmapTransform->value( { service.toLower(), connections[i] } ) );
564 el.setAttribute( u"dpiMode"_s, static_cast<int>( QgsOwsConnection::settingsDpiMode->value( { service.toLower(), connections[i] } ) ) );
565 el.setAttribute( u"disableDecompressedSafetyCheckThreshold"_s, QgsOwsConnection::settingsDisableDecompressedSafetyCheckThreshold->value( { service.toLower(), connections[i] } ) );
566
567 QgsHttpHeaders httpHeader( QgsOwsConnection::settingsHeaders->value( { service.toLower(), connections[i] } ) );
568 httpHeader.updateDomElement( el, namespaceDeclarations );
569 }
570
571 el.setAttribute( u"username"_s, QgsOwsConnection::settingsUsername->value( { service.toLower(), connections[i] } ) );
572 el.setAttribute( u"password"_s, QgsOwsConnection::settingsPassword->value( { service.toLower(), connections[i] } ) );
573 root.appendChild( el );
574 }
575
576 addNamespaceDeclarations( root, namespaceDeclarations );
577
578 return doc;
579}
580
581QDomDocument QgsManageConnectionsDialog::saveWfsConnections( const QStringList &connections )
582{
583 QDomDocument doc( u"connections"_s );
584 QDomElement root = doc.createElement( u"qgsWFSConnections"_s );
585 root.setAttribute( u"version"_s, u"1.1"_s );
586 doc.appendChild( root );
587
588 for ( int i = 0; i < connections.count(); ++i )
589 {
590 QDomElement el = doc.createElement( u"wfs"_s );
591 el.setAttribute( u"name"_s, connections[i] );
592 el.setAttribute( u"url"_s, QgsOwsConnection::settingsUrl->value( { u"wfs"_s, connections[i] } ) );
593
594 el.setAttribute( u"version"_s, QgsOwsConnection::settingsVersion->value( { u"wfs"_s, connections[i] } ) );
595 el.setAttribute( u"maxnumfeatures"_s, QgsOwsConnection::settingsMaxNumFeatures->value( { u"wfs"_s, connections[i] } ) );
596 el.setAttribute( u"pagesize"_s, QgsOwsConnection::settingsPagesize->value( { u"wfs"_s, connections[i] } ) );
597 el.setAttribute( u"pagingenabled"_s, QgsOwsConnection::settingsPagingEnabled->value( { u"wfs"_s, connections[i] } ) );
598 el.setAttribute( u"ignoreAxisOrientation"_s, QgsOwsConnection::settingsIgnoreAxisOrientation->value( { u"wfs"_s, connections[i] } ) );
599 el.setAttribute( u"invertAxisOrientation"_s, QgsOwsConnection::settingsInvertAxisOrientation->value( { u"wfs"_s, connections[i] } ) );
600 el.setAttribute( u"username"_s, QgsOwsConnection::settingsUsername->value( { u"wfs"_s, connections[i] } ) );
601 el.setAttribute( u"password"_s, QgsOwsConnection::settingsPassword->value( { u"wfs"_s, connections[i] } ) );
602 el.setAttribute( u"httpMethod"_s, QgsOwsConnection::settingsPreferredHttpMethod->value( { u"wfs"_s, connections[i] } ) == Qgis::HttpMethod::Post ? u"post"_s : u"get"_s );
603 el.setAttribute( u"featureMode"_s, QgsOwsConnection::settingsWfsFeatureMode->value( { u"wfs"_s, connections[i] } ) );
604 el.setAttribute( u"disableDecompressedSafetyCheckThreshold"_s, QgsOwsConnection::settingsDisableDecompressedSafetyCheckThreshold->value( { u"wfs"_s, connections[i] } ) );
605 root.appendChild( el );
606 }
607
608 return doc;
609}
610
611QDomDocument QgsManageConnectionsDialog::savePgConnections( const QStringList &connections )
612{
613 QDomDocument doc( u"connections"_s );
614 QDomElement root = doc.createElement( u"qgsPgConnections"_s );
615 root.setAttribute( u"version"_s, u"1.0"_s );
616 doc.appendChild( root );
617
618 const QgsSettings settings;
619 QString path;
620 for ( int i = 0; i < connections.count(); ++i )
621 {
622 path = "/PostgreSQL/connections/" + connections[i];
623 QDomElement element = doc.createElement( u"postgis"_s );
624 saveDatabaseConnection(
625 element,
626 settings,
627 path,
628 { u"name"_s,
629 u"host"_s,
630 u"port"_s,
631 u"database"_s,
632 u"service"_s,
633 u"sslmode"_s,
634 u"estimatedMetadata"_s,
635 u"projectsInDatabase"_s,
636 u"dontResolveType"_s,
637 u"allowGeometrylessTables"_s,
638 u"geometryColumnsOnly"_s,
639 u"publicOnly"_s,
640 u"schema"_s },
641 { { u"sslmode"_s, "1" },
642 { u"estimatedMetadata"_s, "0" },
643 { u"projectsInDatabase"_s, "0" },
644 { u"dontResolveType"_s, "0" },
645 { u"allowGeometrylessTables"_s, "0" },
646 { u"geometryColumnsOnly"_s, "0" },
647 { u"publicOnly"_s, "0" },
648 {} }
649 );
650
651 root.appendChild( element );
652 }
653
654 return doc;
655}
656
657QDomDocument QgsManageConnectionsDialog::saveMssqlConnections( const QStringList &connections )
658{
659 QDomDocument doc( u"connections"_s );
660 QDomElement root = doc.createElement( u"qgsMssqlConnections"_s );
661 root.setAttribute( u"version"_s, u"1.0"_s );
662 doc.appendChild( root );
663
664 const QgsSettings settings;
665 QString path;
666 for ( int i = 0; i < connections.count(); ++i )
667 {
668 path = "/MSSQL/connections/" + connections[i];
669 QDomElement element = doc.createElement( u"mssql"_s );
670 saveDatabaseConnection( element, settings, path, { u"name"_s, u"host"_s, u"port"_s, u"database"_s, u"service"_s, u"sslmode"_s, u"estimatedMetadata"_s }, { { u"sslmode"_s, "1" }, { u"estimatedMetadata"_s, "0" } } );
671 root.appendChild( element );
672 }
673
674 return doc;
675}
676
677QDomDocument QgsManageConnectionsDialog::saveOracleConnections( const QStringList &connections )
678{
679 QDomDocument doc( u"connections"_s );
680 QDomElement root = doc.createElement( u"qgsOracleConnections"_s );
681 root.setAttribute( u"version"_s, u"1.0"_s );
682 doc.appendChild( root );
683
684 const QgsSettings settings;
685 QString path;
686 for ( int i = 0; i < connections.count(); ++i )
687 {
688 path = "/Oracle/connections/" + connections[i];
689 QDomElement element = doc.createElement( u"oracle"_s );
690 saveDatabaseConnection(
691 element,
692 settings,
693 path,
694 { u"name"_s, u"host"_s, u"port"_s, u"database"_s, u"dboptions"_s, u"dbworkspace"_s, u"schema"_s, u"estimatedMetadata"_s, u"userTablesOnly"_s, u"geometryColumnsOnly"_s, u"allowGeometrylessTables"_s },
695 { { u"estimatedMetadata"_s, "0" }, { u"userTablesOnly"_s, "0" }, { u"geometryColumnsOnly"_s, "0" }, { u"allowGeometrylessTables"_s, "0" } }
696 );
697
698 root.appendChild( element );
699 }
700
701 return doc;
702}
703
704QDomDocument QgsManageConnectionsDialog::saveHanaConnections( const QStringList &connections )
705{
706 QDomDocument doc( u"connections"_s );
707 QDomElement root = doc.createElement( u"qgsHanaConnections"_s );
708 root.setAttribute( u"version"_s, u"1.0"_s );
709 doc.appendChild( root );
710
711 const QgsSettings settings;
712 QString path;
713 for ( int i = 0; i < connections.count(); ++i )
714 {
715 path = "/HANA/connections/" + connections[i];
716 QDomElement element = doc.createElement( u"hana"_s );
717 saveDatabaseConnection(
718 element,
719 settings,
720 path,
721 { u"name"_s,
722 u"driver"_s,
723 u"host"_s,
724 u"identifierType"_s,
725 u"identifier"_s,
726 u"multitenant"_s,
727 u"database"_s,
728 u"schema"_s,
729 u"userTablesOnly"_s,
730 u"allowGeometrylessTables"_s,
731 u"sslEnabled"_s,
732 u"sslCryptoProvider"_s,
733 u"sslKeyStore"_s,
734 u"sslTrustStore"_s,
735 u"sslValidateCertificate"_s,
736 u"sslHostNameInCertificate"_s },
737 { { u"userTablesOnly"_s, "0" }, { u"allowGeometrylessTables"_s, "0" }, { u"sslEnabled"_s, u"false"_s }, { u"sslCryptoProvider"_s, u"openssl"_s }, { u"sslValidateCertificate"_s, u"false"_s } }
738 );
739 root.appendChild( element );
740 }
741
742 return doc;
743}
744
745QDomDocument QgsManageConnectionsDialog::saveXyzTilesConnections( const QStringList &connections )
746{
747 QDomDocument doc( u"connections"_s );
748 QDomElement root = doc.createElement( u"qgsXYZTilesConnections"_s );
749 root.setAttribute( u"version"_s, u"1.0"_s );
750 doc.appendChild( root );
751
752 QMap<QString, QString> namespaceDeclarations;
753 for ( int i = 0; i < connections.count(); ++i )
754 {
755 QDomElement el = doc.createElement( u"xyztiles"_s );
756
757 el.setAttribute( u"name"_s, connections[i] );
758 el.setAttribute( u"url"_s, QgsXyzConnectionSettings::settingsUrl->value( connections[i] ) );
759 el.setAttribute( u"zmin"_s, QgsXyzConnectionSettings::settingsZmin->value( connections[i] ) );
760 el.setAttribute( u"zmax"_s, QgsXyzConnectionSettings::settingsZmax->value( connections[i] ) );
761 el.setAttribute( u"authcfg"_s, QgsXyzConnectionSettings::settingsAuthcfg->value( connections[i] ) );
762 el.setAttribute( u"username"_s, QgsXyzConnectionSettings::settingsUsername->value( connections[i] ) );
763 el.setAttribute( u"password"_s, QgsXyzConnectionSettings::settingsPassword->value( connections[i] ) );
764 el.setAttribute( u"tilePixelRatio"_s, QgsXyzConnectionSettings::settingsTilePixelRatio->value( connections[i] ) );
765
766 QgsHttpHeaders httpHeader( QgsXyzConnectionSettings::settingsHeaders->value( connections[i] ) );
767 httpHeader.updateDomElement( el, namespaceDeclarations );
768
769 root.appendChild( el );
770 }
771
772 addNamespaceDeclarations( root, namespaceDeclarations );
773
774 return doc;
775}
776
777QDomDocument QgsManageConnectionsDialog::saveArcgisConnections( const QStringList &connections )
778{
779 QDomDocument doc( u"connections"_s );
780 QDomElement root = doc.createElement( "qgsARCGISFEATURESERVERConnections" );
781 root.setAttribute( u"version"_s, u"1.0"_s );
782 doc.appendChild( root );
783
784 QMap<QString, QString> namespaceDeclarations;
785 for ( const QString &connection : connections )
786 {
787 QDomElement el = doc.createElement( u"arcgisfeatureserver"_s );
788 el.setAttribute( u"name"_s, connection );
789 el.setAttribute( u"url"_s, QgsArcGisConnectionSettings::settingsUrl->value( connection ) );
790
791 QgsHttpHeaders httpHeader( QgsArcGisConnectionSettings::settingsHeaders->value( connection ) );
792 httpHeader.updateDomElement( el, namespaceDeclarations );
793
794 el.setAttribute( u"username"_s, QgsArcGisConnectionSettings::settingsUsername->value( connection ) );
795 el.setAttribute( u"password"_s, QgsArcGisConnectionSettings::settingsPassword->value( connection ) );
796 el.setAttribute( u"authcfg"_s, QgsArcGisConnectionSettings::settingsAuthcfg->value( connection ) );
797
798 root.appendChild( el );
799 }
800
801 addNamespaceDeclarations( root, namespaceDeclarations );
802
803 return doc;
804}
805
806QDomDocument QgsManageConnectionsDialog::saveVectorTileConnections( const QStringList &connections )
807{
808 QDomDocument doc( u"connections"_s );
809 QDomElement root = doc.createElement( u"qgsVectorTileConnections"_s );
810 root.setAttribute( u"version"_s, u"1.0"_s );
811 doc.appendChild( root );
812
813 QMap<QString, QString> namespaceDeclarations;
814 for ( int i = 0; i < connections.count(); ++i )
815 {
816 QDomElement el = doc.createElement( u"vectortile"_s );
817
818 el.setAttribute( u"name"_s, connections[i] );
819 el.setAttribute( u"url"_s, QgsVectorTileProviderConnection::settingsUrl->value( connections[i] ) );
820 el.setAttribute( u"zmin"_s, QgsVectorTileProviderConnection::settingsZmin->value( connections[i] ) );
821 el.setAttribute( u"zmax"_s, QgsVectorTileProviderConnection::settingsZmax->value( connections[i] ) );
822 el.setAttribute( u"serviceType"_s, QgsVectorTileProviderConnection::settingsServiceType->value( connections[i] ) );
823 el.setAttribute( u"authcfg"_s, QgsVectorTileProviderConnection::settingsAuthcfg->value( connections[i] ) );
824 el.setAttribute( u"username"_s, QgsVectorTileProviderConnection::settingsUsername->value( connections[i] ) );
825 el.setAttribute( u"password"_s, QgsVectorTileProviderConnection::settingsPassword->value( connections[i] ) );
826 el.setAttribute( u"styleUrl"_s, QgsVectorTileProviderConnection::settingsStyleUrl->value( connections[i] ) );
827
828 QgsHttpHeaders httpHeader( QgsVectorTileProviderConnection::settingsHeaders->value( connections[i] ) );
829 httpHeader.updateDomElement( el, namespaceDeclarations );
830
831 root.appendChild( el );
832 }
833
834 addNamespaceDeclarations( root, namespaceDeclarations );
835
836 return doc;
837}
838
839QDomDocument QgsManageConnectionsDialog::saveTiledSceneConnections( const QStringList &connections )
840{
841 QDomDocument doc( u"connections"_s );
842 QDomElement root = doc.createElement( u"qgsTiledSceneConnections"_s );
843 root.setAttribute( u"version"_s, u"1.0"_s );
844 doc.appendChild( root );
845
846 QMap<QString, QString> namespaceDeclarations;
847 for ( int i = 0; i < connections.count(); ++i )
848 {
849 QDomElement el = doc.createElement( u"tiledscene"_s );
850
851 el.setAttribute( u"name"_s, connections[i] );
852 el.setAttribute( u"provider"_s, QgsTiledSceneProviderConnection::settingsProvider->value( connections[i] ) );
853 el.setAttribute( u"url"_s, QgsTiledSceneProviderConnection::settingsUrl->value( connections[i] ) );
854 el.setAttribute( u"authcfg"_s, QgsTiledSceneProviderConnection::settingsAuthcfg->value( connections[i] ) );
855 el.setAttribute( u"username"_s, QgsTiledSceneProviderConnection::settingsUsername->value( connections[i] ) );
856 el.setAttribute( u"password"_s, QgsTiledSceneProviderConnection::settingsPassword->value( connections[i] ) );
857
858 QgsHttpHeaders httpHeader( QgsTiledSceneProviderConnection::settingsHeaders->value( connections[i] ) );
859 httpHeader.updateDomElement( el, namespaceDeclarations );
860
861 root.appendChild( el );
862 }
863
864 addNamespaceDeclarations( root, namespaceDeclarations );
865
866 return doc;
867}
868
869QDomDocument QgsManageConnectionsDialog::saveSensorThingsConnections( const QStringList &connections )
870{
871 QDomDocument doc( u"connections"_s );
872 QDomElement root = doc.createElement( u"qgsSensorThingsConnections"_s );
873 root.setAttribute( u"version"_s, u"1.0"_s );
874 doc.appendChild( root );
875
876 QMap<QString, QString> namespaceDeclarations;
877 for ( int i = 0; i < connections.count(); ++i )
878 {
879 QDomElement el = doc.createElement( u"sensorthings"_s );
880
881 el.setAttribute( u"name"_s, connections[i] );
882 el.setAttribute( u"url"_s, QgsSensorThingsProviderConnection::settingsUrl->value( connections[i] ) );
883 el.setAttribute( u"authcfg"_s, QgsSensorThingsProviderConnection::settingsAuthcfg->value( connections[i] ) );
884 el.setAttribute( u"username"_s, QgsSensorThingsProviderConnection::settingsUsername->value( connections[i] ) );
885 el.setAttribute( u"password"_s, QgsSensorThingsProviderConnection::settingsPassword->value( connections[i] ) );
886
887 QgsHttpHeaders httpHeader( QgsSensorThingsProviderConnection::settingsHeaders->value( connections[i] ) );
888 httpHeader.updateDomElement( el, namespaceDeclarations );
889
890 root.appendChild( el );
891 }
892
893 addNamespaceDeclarations( root, namespaceDeclarations );
894
895 return doc;
896}
897
898QDomDocument QgsManageConnectionsDialog::saveCloudStorageConnections( const QStringList &connections )
899{
900 QDomDocument doc( u"connections"_s );
901 QDomElement root = doc.createElement( u"qgsCloudStorageConnections"_s );
902 root.setAttribute( u"version"_s, u"1.0"_s );
903 doc.appendChild( root );
904
905 for ( int i = 0; i < connections.count(); ++i )
906 {
907 QDomElement el = doc.createElement( u"cloudstorage"_s );
908
909 el.setAttribute( u"name"_s, connections[i] );
910 el.setAttribute( u"handler"_s, QgsGdalCloudProviderConnection::settingsVsiHandler->value( connections[i] ) );
911 el.setAttribute( u"container"_s, QgsGdalCloudProviderConnection::settingsContainer->value( connections[i] ) );
912 el.setAttribute( u"path"_s, QgsGdalCloudProviderConnection::settingsPath->value( connections[i] ) );
913
914 const QVariantMap credentialOptions = QgsGdalCloudProviderConnection::settingsCredentialOptions->value( connections[i] );
915 QString credentialString;
916 for ( auto it = credentialOptions.constBegin(); it != credentialOptions.constEnd(); ++it )
917 {
918 if ( !it.value().toString().isEmpty() )
919 {
920 credentialString += u"|credential:%1=%2"_s.arg( it.key(), it.value().toString() );
921 }
922 }
923 el.setAttribute( u"credentials"_s, credentialString );
924
925 root.appendChild( el );
926 }
927
928 return doc;
929}
930
931QDomDocument QgsManageConnectionsDialog::saveStacConnections( const QStringList &connections )
932{
933 QDomDocument doc( u"connections"_s );
934 QDomElement root = doc.createElement( u"qgsStacConnections"_s );
935 root.setAttribute( u"version"_s, u"1.0"_s );
936 doc.appendChild( root );
937
938 QMap<QString, QString> namespaceDeclarations;
939 for ( int i = 0; i < connections.count(); ++i )
940 {
941 QDomElement el = doc.createElement( u"stac"_s );
942
943 el.setAttribute( u"name"_s, connections[i] );
944 el.setAttribute( u"url"_s, QgsStacConnection::settingsUrl->value( connections[i] ) );
945 el.setAttribute( u"authcfg"_s, QgsStacConnection::settingsAuthcfg->value( connections[i] ) );
946 el.setAttribute( u"username"_s, QgsStacConnection::settingsUsername->value( connections[i] ) );
947 el.setAttribute( u"password"_s, QgsStacConnection::settingsPassword->value( connections[i] ) );
948
949 QgsHttpHeaders httpHeader( QgsStacConnection::settingsHeaders->value( connections[i] ) );
950 httpHeader.updateDomElement( el, namespaceDeclarations );
951
952 root.appendChild( el );
953 }
954
955 addNamespaceDeclarations( root, namespaceDeclarations );
956
957 return doc;
958}
959
960void QgsManageConnectionsDialog::loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service )
961{
962 if ( !isValidDocumentType( this, doc, service ) )
963 {
964 return;
965 }
966
967 QString connectionName;
968 const QDomElement root = doc.documentElement();
969 QDomElement child = root.firstChildElement();
970 bool prompt = true;
971 bool overwrite = true;
972
973 while ( !child.isNull() )
974 {
975 connectionName = child.attribute( u"name"_s );
976 if ( !items.contains( connectionName ) )
977 {
978 child = child.nextSiblingElement();
979 continue;
980 }
981
982 if ( QgsOwsConnection::settingsUrl->exists( { service.toLower(), connectionName } ) )
983 {
984 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
985 {
986 case ActionOnDuplicate::Overwrite:
987 break;
988 case ActionOnDuplicate::Skip:
989 child = child.nextSiblingElement();
990 continue;
991 case ActionOnDuplicate::Cancel:
992 return;
993 }
994 }
995
996 QgsOwsConnection::settingsUrl->setValue( child.attribute( u"url"_s ), { service.toLower(), connectionName } );
997 QgsOwsConnection::settingsIgnoreGetMapURI->setValue( child.attribute( u"ignoreGetMapURI"_s ) == "true"_L1, { service.toLower(), connectionName } );
998 QgsOwsConnection::settingsIgnoreGetFeatureInfoURI->setValue( child.attribute( u"ignoreGetFeatureInfoURI"_s ) == "true"_L1, { service.toLower(), connectionName } );
999 QgsOwsConnection::settingsIgnoreAxisOrientation->setValue( child.attribute( u"ignoreAxisOrientation"_s ) == "true"_L1, { service.toLower(), connectionName } );
1000 QgsOwsConnection::settingsInvertAxisOrientation->setValue( child.attribute( u"invertAxisOrientation"_s ) == "true"_L1, { service.toLower(), connectionName } );
1001 QgsOwsConnection::settingsSmoothPixmapTransform->setValue( child.attribute( u"smoothPixmapTransform"_s ) == "true"_L1, { service.toLower(), connectionName } );
1002 QgsOwsConnection::settingsDpiMode->setValue( static_cast<Qgis::DpiMode>( child.attribute( u"dpiMode"_s, u"7"_s ).toInt() ), { service.toLower(), connectionName } );
1003 QgsOwsConnection::settingsDisableDecompressedSafetyCheckThreshold->setValue( child.attribute( u"disableDecompressedSafetyCheckThreshold"_s ) == "true"_L1, { service.toLower(), connectionName } );
1004
1005 QgsHttpHeaders httpHeader( child );
1006 QgsOwsConnection::settingsHeaders->setValue( httpHeader.headers(), { service.toLower(), connectionName } );
1007
1008 if ( !child.attribute( u"username"_s ).isEmpty() )
1009 {
1010 QgsOwsConnection::settingsUsername->setValue( child.attribute( u"username"_s ), { service.toUpper(), connectionName } );
1011 QgsOwsConnection::settingsPassword->setValue( child.attribute( u"password"_s ), { service.toUpper(), connectionName } );
1012 }
1013 child = child.nextSiblingElement();
1014 }
1015}
1016
1017void QgsManageConnectionsDialog::loadWfsConnections( const QDomDocument &doc, const QStringList &items )
1018{
1019 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::WFS ) )
1020 {
1021 return;
1022 }
1023
1024 QString connectionName;
1025 QStringList keys = QgsOwsConnection::sTreeOwsConnections->items( { u"wfs"_s } );
1026
1027 const QDomElement root = doc.documentElement();
1028 QDomElement child = root.firstChildElement();
1029 bool prompt = true;
1030 bool overwrite = true;
1031
1032 while ( !child.isNull() )
1033 {
1034 connectionName = child.attribute( u"name"_s );
1035 if ( !items.contains( connectionName ) )
1036 {
1037 child = child.nextSiblingElement();
1038 continue;
1039 }
1040
1041 // check for duplicates
1042 if ( keys.contains( connectionName ) )
1043 {
1044 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1045 {
1046 case ActionOnDuplicate::Overwrite:
1047 break;
1048 case ActionOnDuplicate::Skip:
1049 child = child.nextSiblingElement();
1050 continue;
1051 case ActionOnDuplicate::Cancel:
1052 return;
1053 }
1054 }
1055 else
1056 {
1057 keys << connectionName;
1058 }
1059
1060 QgsOwsConnection::settingsUrl->setValue( child.attribute( u"url"_s ), { u"wfs"_s, connectionName } );
1061 QgsOwsConnection::settingsVersion->setValue( child.attribute( u"version"_s ), { u"wfs"_s, connectionName } );
1062 QgsOwsConnection::settingsMaxNumFeatures->setValue( child.attribute( u"maxnumfeatures"_s ), { u"wfs"_s, connectionName } );
1063 QgsOwsConnection::settingsPagesize->setValue( child.attribute( u"pagesize"_s ), { u"wfs"_s, connectionName } );
1064 QgsOwsConnection::settingsPagingEnabled->setValue( child.attribute( u"pagingenabled"_s ), { u"wfs"_s, connectionName } );
1065 QgsOwsConnection::settingsIgnoreAxisOrientation->setValue( child.attribute( u"ignoreAxisOrientation"_s ).toInt(), { u"wfs"_s, connectionName } );
1066 QgsOwsConnection::settingsInvertAxisOrientation->setValue( child.attribute( u"invertAxisOrientation"_s ).toInt(), { u"wfs"_s, connectionName } );
1068 ->setValue( child.attribute( u"httpMethod"_s ).compare( "post"_L1, Qt::CaseInsensitive ) == 0 ? Qgis::HttpMethod::Post : Qgis::HttpMethod::Get, { u"wfs"_s, connectionName } );
1069 QgsOwsConnection::settingsWfsFeatureMode->setValue( child.attribute( u"featureMode"_s ), { u"wfs"_s, connectionName } );
1070 QgsOwsConnection::settingsDisableDecompressedSafetyCheckThreshold->setValue( child.attribute( u"disableDecompressedSafetyCheckThreshold"_s ) == "true"_L1, { u"wfs"_s, connectionName } );
1071
1072 if ( !child.attribute( u"username"_s ).isEmpty() )
1073 {
1074 QgsOwsConnection::settingsUsername->setValue( child.attribute( u"username"_s ), { u"wfs"_s, connectionName } );
1075 QgsOwsConnection::settingsPassword->setValue( child.attribute( u"password"_s ), { u"wfs"_s, connectionName } );
1076 }
1077 child = child.nextSiblingElement();
1078 }
1079}
1080
1081void QgsManageConnectionsDialog::loadPgConnections( const QDomDocument &doc, const QStringList &items )
1082{
1083 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::PostGIS ) )
1084 {
1085 return;
1086 }
1087
1088 QString connectionName;
1089 QgsSettings settings;
1090 settings.beginGroup( u"/PostgreSQL/connections"_s );
1091 QStringList keys = settings.childGroups();
1092 settings.endGroup();
1093 const QDomElement root = doc.documentElement();
1094 QDomElement child = root.firstChildElement();
1095 bool prompt = true;
1096 bool overwrite = true;
1097
1098 while ( !child.isNull() )
1099 {
1100 connectionName = child.attribute( u"name"_s );
1101 if ( !items.contains( connectionName ) )
1102 {
1103 child = child.nextSiblingElement();
1104 continue;
1105 }
1106
1107 if ( keys.contains( connectionName ) )
1108 {
1109 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1110 {
1111 case ActionOnDuplicate::Overwrite:
1112 break;
1113 case ActionOnDuplicate::Skip:
1114 child = child.nextSiblingElement();
1115 continue;
1116 case ActionOnDuplicate::Cancel:
1117 return;
1118 }
1119 }
1120 else
1121 {
1122 keys << connectionName;
1123 }
1124
1125 settings.beginGroup( "/PostgreSQL/connections/" + connectionName );
1126 loadDatabaseConnection(
1127 child,
1128 settings,
1129 { u"host"_s,
1130 u"port"_s,
1131 u"database"_s,
1132 u"ervice"_s,
1133 u"sslmode"_s,
1134 u"estimatedMetadata"_s,
1135 u"projectsInDatabase"_s,
1136 u"dontResolveType"_s,
1137 u"allowGeometrylessTables"_s,
1138 u"geometryColumnsOnly"_s,
1139 u"publicOnly"_s,
1140 u"schema"_s },
1141 { { u"service"_s, "" }, { u"projectsInDatabase"_s, 0 }, { u"dontResolveType"_s, 0 }, { u"allowGeometrylessTables"_s, 0 }, { u"geometryColumnsOnly"_s, 0 }, { u"publicOnly"_s, 0 } }
1142 );
1143 settings.endGroup();
1144
1145 child = child.nextSiblingElement();
1146 }
1147}
1148
1149void QgsManageConnectionsDialog::loadMssqlConnections( const QDomDocument &doc, const QStringList &items )
1150{
1151 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::MSSQL ) )
1152 {
1153 return;
1154 }
1155
1156 QString connectionName;
1157 QgsSettings settings;
1158 settings.beginGroup( u"/MSSQL/connections"_s );
1159 QStringList keys = settings.childGroups();
1160 settings.endGroup();
1161 const QDomElement root = doc.documentElement();
1162 QDomElement child = root.firstChildElement();
1163 bool prompt = true;
1164 bool overwrite = true;
1165
1166 while ( !child.isNull() )
1167 {
1168 connectionName = child.attribute( u"name"_s );
1169 if ( !items.contains( connectionName ) )
1170 {
1171 child = child.nextSiblingElement();
1172 continue;
1173 }
1174
1175 // check for duplicates
1176 if ( keys.contains( connectionName ) )
1177 {
1178 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1179 {
1180 case ActionOnDuplicate::Overwrite:
1181 break;
1182 case ActionOnDuplicate::Skip:
1183 child = child.nextSiblingElement();
1184 continue;
1185 case ActionOnDuplicate::Cancel:
1186 return;
1187 }
1188 }
1189 else
1190 {
1191 keys << connectionName;
1192 }
1193
1194 settings.beginGroup( "/MSSQL/connections/" + connectionName );
1195 loadDatabaseConnection( child, settings, { u"host"_s, u"port"_s, u"database"_s, u"service"_s, u"sslmode"_s, u"estimatedMetadata"_s }, { { u"service"_s, "" } } );
1196 settings.endGroup();
1197
1198 child = child.nextSiblingElement();
1199 }
1200}
1201
1202void QgsManageConnectionsDialog::loadOracleConnections( const QDomDocument &doc, const QStringList &items )
1203{
1204 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::Oracle ) )
1205 {
1206 return;
1207 }
1208
1209 QString connectionName;
1210 QgsSettings settings;
1211 settings.beginGroup( u"/Oracle/connections"_s );
1212 QStringList keys = settings.childGroups();
1213 settings.endGroup();
1214 const QDomElement root = doc.documentElement();
1215 QDomElement child = root.firstChildElement();
1216 bool prompt = true;
1217 bool overwrite = true;
1218
1219 while ( !child.isNull() )
1220 {
1221 connectionName = child.attribute( u"name"_s );
1222 if ( !items.contains( connectionName ) )
1223 {
1224 child = child.nextSiblingElement();
1225 continue;
1226 }
1227
1228 if ( keys.contains( connectionName ) )
1229 {
1230 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1231 {
1232 case ActionOnDuplicate::Overwrite:
1233 break;
1234 case ActionOnDuplicate::Skip:
1235 child = child.nextSiblingElement();
1236 continue;
1237 case ActionOnDuplicate::Cancel:
1238 return;
1239 }
1240 }
1241 else
1242 {
1243 keys << connectionName;
1244 }
1245
1246 settings.beginGroup( "/Oracle/connections/" + connectionName );
1247 loadDatabaseConnection( child, settings, { u"host"_s, u"port"_s, u"database"_s, u"dboptions"_s, u"dbworkspace"_s, u"schema"_s, u"estimatedMetadata"_s, u"userTablesOnly"_s, u"geometryColumnsOnly"_s, u"allowGeometrylessTables"_s } );
1248 settings.endGroup();
1249
1250 child = child.nextSiblingElement();
1251 }
1252}
1253
1254void QgsManageConnectionsDialog::loadHanaConnections( const QDomDocument &doc, const QStringList &items )
1255{
1256 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::HANA ) )
1257 {
1258 return;
1259 }
1260
1261 QDomElement root = doc.documentElement();
1262 const QDomAttr version = root.attributeNode( "version" );
1263 if ( version.value() != "1.0"_L1 )
1264 {
1265 QMessageBox::warning( this, tr( "Loading Connections" ), tr( "The HANA connections exchange file version '%1' is not supported." ).arg( version.value() ) );
1266 return;
1267 }
1268
1269 QgsSettings settings;
1270 settings.beginGroup( u"/HANA/connections"_s );
1271 QStringList keys = settings.childGroups();
1272 settings.endGroup();
1273 QDomElement child = root.firstChildElement();
1274 bool prompt = true;
1275 bool overwrite = true;
1276
1277 while ( !child.isNull() )
1278 {
1279 const QString connectionName = child.attribute( u"name"_s );
1280 if ( !items.contains( connectionName ) )
1281 {
1282 child = child.nextSiblingElement();
1283 continue;
1284 }
1285
1286 if ( keys.contains( connectionName ) )
1287 {
1288 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1289 {
1290 case ActionOnDuplicate::Overwrite:
1291 break;
1292 case ActionOnDuplicate::Skip:
1293 child = child.nextSiblingElement();
1294 continue;
1295 case ActionOnDuplicate::Cancel:
1296 return;
1297 }
1298 }
1299 else
1300 {
1301 keys << connectionName;
1302 }
1303
1304 settings.beginGroup( "/HANA/connections/" + connectionName );
1305 loadDatabaseConnection(
1306 child,
1307 settings,
1308 { u"driver"_s,
1309 u"host"_s,
1310 u"database"_s,
1311 u"identifierType"_s,
1312 u"identifier"_s,
1313 u"multitenant"_s,
1314 u"schema"_s,
1315 u"userTablesOnly"_s,
1316 u"allowGeometrylessTables"_s,
1317 u"saveUsername"_s,
1318 u"username"_s,
1319 u"savePassword"_s,
1320 u"password"_s,
1321 u"sslEnabled"_s,
1322 u"sslCryptoProvider"_s,
1323 u"sslKeyStore"_s,
1324 u"sslTrustStore"_s,
1325 u"sslValidateCertificate"_s,
1326 u"sslHostNameInCertificate"_s }
1327 );
1328 settings.endGroup();
1329
1330 child = child.nextSiblingElement();
1331 }
1332}
1333
1334void QgsManageConnectionsDialog::loadXyzTilesConnections( const QDomDocument &doc, const QStringList &items )
1335{
1336 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::XyzTiles ) )
1337 {
1338 return;
1339 }
1340
1341 QString connectionName;
1343 const QDomElement root = doc.documentElement();
1344 QDomElement child = root.firstChildElement();
1345 bool prompt = true;
1346 bool overwrite = true;
1347
1348 while ( !child.isNull() )
1349 {
1350 connectionName = child.attribute( u"name"_s );
1351 if ( !items.contains( connectionName ) )
1352 {
1353 child = child.nextSiblingElement();
1354 continue;
1355 }
1356
1357 if ( keys.contains( connectionName ) )
1358 {
1359 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1360 {
1361 case ActionOnDuplicate::Overwrite:
1362 break;
1363 case ActionOnDuplicate::Skip:
1364 child = child.nextSiblingElement();
1365 continue;
1366 case ActionOnDuplicate::Cancel:
1367 return;
1368 }
1369 }
1370 else
1371 {
1372 keys << connectionName;
1373 }
1374
1375 QgsXyzConnectionSettings::settingsUrl->setValue( child.attribute( u"url"_s ), connectionName );
1376 QgsXyzConnectionSettings::settingsZmin->setValue( child.attribute( u"zmin"_s ).toInt(), connectionName );
1377 QgsXyzConnectionSettings::settingsZmax->setValue( child.attribute( u"zmax"_s ).toInt(), connectionName );
1378 QgsXyzConnectionSettings::settingsAuthcfg->setValue( child.attribute( u"authcfg"_s ), connectionName );
1379 QgsXyzConnectionSettings::settingsUsername->setValue( child.attribute( u"username"_s ), connectionName );
1380 QgsXyzConnectionSettings::settingsPassword->setValue( child.attribute( u"password"_s ), connectionName );
1381 QgsXyzConnectionSettings::settingsTilePixelRatio->setValue( child.attribute( u"tilePixelRatio"_s ).toInt(), connectionName );
1382
1383 QgsHttpHeaders httpHeader( child );
1384 QgsXyzConnectionSettings::settingsHeaders->setValue( httpHeader.headers(), connectionName );
1385
1386 child = child.nextSiblingElement();
1387 }
1388}
1389
1390void QgsManageConnectionsDialog::loadArcgisConnections( const QDomDocument &doc, const QStringList &items, const QString &service )
1391{
1392 if ( !isValidDocumentType( this, doc, service ) )
1393 {
1394 return;
1395 }
1396
1397 QString connectionName;
1399 const QDomElement root = doc.documentElement();
1400 QDomElement child = root.firstChildElement();
1401 bool prompt = true;
1402 bool overwrite = true;
1403
1404 while ( !child.isNull() )
1405 {
1406 connectionName = child.attribute( u"name"_s );
1407 if ( !items.contains( connectionName ) )
1408 {
1409 child = child.nextSiblingElement();
1410 continue;
1411 }
1412
1413 if ( keys.contains( connectionName ) )
1414 {
1415 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1416 {
1417 case ActionOnDuplicate::Overwrite:
1418 break;
1419 case ActionOnDuplicate::Skip:
1420 child = child.nextSiblingElement();
1421 continue;
1422 case ActionOnDuplicate::Cancel:
1423 return;
1424 }
1425 }
1426 else
1427 {
1428 keys << connectionName;
1429 }
1430
1431 QgsArcGisConnectionSettings::settingsUrl->setValue( child.attribute( u"url"_s ), connectionName );
1432 QgsArcGisConnectionSettings::settingsHeaders->setValue( QgsHttpHeaders( child ).headers(), connectionName );
1433 QgsArcGisConnectionSettings::settingsUsername->setValue( child.attribute( u"username"_s ), connectionName );
1434 QgsArcGisConnectionSettings::settingsPassword->setValue( child.attribute( u"password"_s ), connectionName );
1435 QgsArcGisConnectionSettings::settingsAuthcfg->setValue( child.attribute( u"authcfg"_s ), connectionName );
1436
1437 child = child.nextSiblingElement();
1438 }
1439}
1440
1441void QgsManageConnectionsDialog::loadVectorTileConnections( const QDomDocument &doc, const QStringList &items )
1442{
1443 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::VectorTile ) )
1444 {
1445 QMessageBox::information( this, tr( "Loading Connections" ), tr( "The file is not a Vector Tile connections exchange file." ) );
1446 return;
1447 }
1448
1449 QString connectionName;
1450 QgsSettings settings;
1451 settings.beginGroup( u"/qgis/connections-vector-tile"_s );
1452 QStringList keys = settings.childGroups();
1453 settings.endGroup();
1454 const QDomElement root = doc.documentElement();
1455 QDomElement child = root.firstChildElement();
1456 bool prompt = true;
1457 bool overwrite = true;
1458
1459 while ( !child.isNull() )
1460 {
1461 connectionName = child.attribute( u"name"_s );
1462 if ( !items.contains( connectionName ) )
1463 {
1464 child = child.nextSiblingElement();
1465 continue;
1466 }
1467
1468 if ( keys.contains( connectionName ) )
1469 {
1470 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1471 {
1472 case ActionOnDuplicate::Overwrite:
1473 break;
1474 case ActionOnDuplicate::Skip:
1475 child = child.nextSiblingElement();
1476 continue;
1477 case ActionOnDuplicate::Cancel:
1478 return;
1479 }
1480 }
1481 else
1482 {
1483 keys << connectionName;
1484 }
1485
1486 QgsVectorTileProviderConnection::settingsUrl->setValue( child.attribute( u"url"_s ), connectionName );
1487 QgsVectorTileProviderConnection::settingsZmin->setValue( child.attribute( u"zmin"_s ).toInt(), connectionName );
1488 QgsVectorTileProviderConnection::settingsZmax->setValue( child.attribute( u"zmax"_s ).toInt(), connectionName );
1489 QgsVectorTileProviderConnection::settingsServiceType->setValue( child.attribute( u"serviceType"_s ), connectionName );
1490 QgsVectorTileProviderConnection::settingsAuthcfg->setValue( child.attribute( u"authcfg"_s ), connectionName );
1491 QgsVectorTileProviderConnection::settingsUsername->setValue( child.attribute( u"username"_s ), connectionName );
1492 QgsVectorTileProviderConnection::settingsPassword->setValue( child.attribute( u"password"_s ), connectionName );
1493 QgsVectorTileProviderConnection::settingsStyleUrl->setValue( child.attribute( u"styleUrl"_s ), connectionName );
1494
1495 QgsHttpHeaders httpHeader( child );
1496 QgsVectorTileProviderConnection::settingsHeaders->setValue( httpHeader.headers(), connectionName );
1497
1498 child = child.nextSiblingElement();
1499 }
1500}
1501
1502void QgsManageConnectionsDialog::loadTiledSceneConnections( const QDomDocument &doc, const QStringList &items )
1503{
1504 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::TiledScene ) )
1505 {
1506 return;
1507 }
1508
1509 QString connectionName;
1510 QgsSettings settings;
1511 settings.beginGroup( u"/qgis/connections-tiled-scene"_s );
1512 QStringList keys = settings.childGroups();
1513 settings.endGroup();
1514 const QDomElement root = doc.documentElement();
1515 QDomElement child = root.firstChildElement();
1516 bool prompt = true;
1517 bool overwrite = true;
1518
1519 while ( !child.isNull() )
1520 {
1521 connectionName = child.attribute( u"name"_s );
1522 if ( !items.contains( connectionName ) )
1523 {
1524 child = child.nextSiblingElement();
1525 continue;
1526 }
1527
1528 if ( keys.contains( connectionName ) )
1529 {
1530 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1531 {
1532 case ActionOnDuplicate::Overwrite:
1533 break;
1534 case ActionOnDuplicate::Skip:
1535 child = child.nextSiblingElement();
1536 continue;
1537 case ActionOnDuplicate::Cancel:
1538 return;
1539 }
1540 }
1541 else
1542 {
1543 keys << connectionName;
1544 }
1545
1546 QgsTiledSceneProviderConnection::settingsProvider->setValue( child.attribute( u"provider"_s ), connectionName );
1547 QgsTiledSceneProviderConnection::settingsUrl->setValue( child.attribute( u"url"_s ), connectionName );
1548 QgsTiledSceneProviderConnection::settingsAuthcfg->setValue( child.attribute( u"authcfg"_s ), connectionName );
1549 QgsTiledSceneProviderConnection::settingsUsername->setValue( child.attribute( u"username"_s ), connectionName );
1550 QgsTiledSceneProviderConnection::settingsPassword->setValue( child.attribute( u"password"_s ), connectionName );
1551
1552 QgsHttpHeaders httpHeader( child );
1553 QgsTiledSceneProviderConnection::settingsHeaders->setValue( httpHeader.headers(), connectionName );
1554
1555 child = child.nextSiblingElement();
1556 }
1557}
1558
1559void QgsManageConnectionsDialog::loadSensorThingsConnections( const QDomDocument &doc, const QStringList &items )
1560{
1561 if ( !isValidDocumentType( this, doc, QgsManageConnectionsDialog::SensorThings ) )
1562 {
1563 QMessageBox::information( this, tr( "Loading Connections" ), tr( "The file is not a SensorThings connections exchange file." ) );
1564 return;
1565 }
1566
1567 QString connectionName;
1568 QgsSettings settings;
1569 settings.beginGroup( u"/connections/sensorthings/items"_s );
1570 QStringList keys = settings.childGroups();
1571 settings.endGroup();
1572 const QDomElement root = doc.documentElement();
1573 QDomElement child = root.firstChildElement();
1574 bool prompt = true;
1575 bool overwrite = true;
1576
1577 while ( !child.isNull() )
1578 {
1579 connectionName = child.attribute( u"name"_s );
1580 if ( !items.contains( connectionName ) )
1581 {
1582 child = child.nextSiblingElement();
1583 continue;
1584 }
1585
1586 // check for duplicates
1587 if ( keys.contains( connectionName ) )
1588 {
1589 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1590 {
1591 case ActionOnDuplicate::Overwrite:
1592 break;
1593 case ActionOnDuplicate::Skip:
1594 child = child.nextSiblingElement();
1595 continue;
1596 case ActionOnDuplicate::Cancel:
1597 return;
1598 }
1599 }
1600 else
1601 {
1602 keys << connectionName;
1603 }
1604
1605 QgsSensorThingsProviderConnection::settingsUrl->setValue( child.attribute( u"url"_s ), connectionName );
1606 QgsSensorThingsProviderConnection::settingsAuthcfg->setValue( child.attribute( u"authcfg"_s ), connectionName );
1607 QgsSensorThingsProviderConnection::settingsUsername->setValue( child.attribute( u"username"_s ), connectionName );
1608 QgsSensorThingsProviderConnection::settingsPassword->setValue( child.attribute( u"password"_s ), connectionName );
1609
1610 QgsHttpHeaders httpHeader( child );
1611 QgsSensorThingsProviderConnection::settingsHeaders->setValue( httpHeader.headers(), connectionName );
1612
1613 child = child.nextSiblingElement();
1614 }
1615}
1616
1617void QgsManageConnectionsDialog::loadCloudStorageConnections( const QDomDocument &doc, const QStringList &items )
1618{
1619 const QDomElement root = doc.documentElement();
1620 if ( root.tagName() != "qgsCloudStorageConnections"_L1 )
1621 {
1622 QMessageBox::information( this, tr( "Loading Connections" ), tr( "The file is not a cloud storage connections exchange file." ) );
1623 return;
1624 }
1625
1626 QString connectionName;
1627 QgsSettings settings;
1628 settings.beginGroup( u"/connections/cloud/items"_s );
1629 QStringList keys = settings.childGroups();
1630 settings.endGroup();
1631 QDomElement child = root.firstChildElement();
1632 bool prompt = true;
1633 bool overwrite = true;
1634
1635 while ( !child.isNull() )
1636 {
1637 connectionName = child.attribute( u"name"_s );
1638 if ( !items.contains( connectionName ) )
1639 {
1640 child = child.nextSiblingElement();
1641 continue;
1642 }
1643
1644 if ( keys.contains( connectionName ) )
1645 {
1646 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1647 {
1648 case ActionOnDuplicate::Overwrite:
1649 break;
1650 case ActionOnDuplicate::Skip:
1651 child = child.nextSiblingElement();
1652 continue;
1653 case ActionOnDuplicate::Cancel:
1654 return;
1655 }
1656 }
1657 else
1658 {
1659 keys << connectionName;
1660 }
1661
1662 QgsGdalCloudProviderConnection::settingsVsiHandler->setValue( child.attribute( u"handler"_s ), connectionName );
1663 QgsGdalCloudProviderConnection::settingsContainer->setValue( child.attribute( u"container"_s ), connectionName );
1664 QgsGdalCloudProviderConnection::settingsPath->setValue( child.attribute( u"path"_s ), connectionName );
1665
1666 QString credentialString = child.attribute( u"credentials"_s );
1667
1668 QVariantMap credentialOptions;
1669 while ( true )
1670 {
1671 const thread_local QRegularExpression credentialOptionRegex( u"\\|credential:([^|]*)"_s );
1672 const thread_local QRegularExpression credentialOptionKeyValueRegex( u"(.*?)=(.*)"_s );
1673
1674 const QRegularExpressionMatch match = credentialOptionRegex.match( credentialString );
1675 if ( match.hasMatch() )
1676 {
1677 const QRegularExpressionMatch keyValueMatch = credentialOptionKeyValueRegex.match( match.captured( 1 ) );
1678 if ( keyValueMatch.hasMatch() )
1679 {
1680 credentialOptions.insert( keyValueMatch.captured( 1 ), keyValueMatch.captured( 2 ) );
1681 }
1682 credentialString = credentialString.remove( match.capturedStart( 0 ), match.capturedLength( 0 ) );
1683 }
1684 else
1685 {
1686 break;
1687 }
1688 }
1689
1690 QgsGdalCloudProviderConnection::settingsCredentialOptions->setValue( credentialOptions, connectionName );
1691
1692 child = child.nextSiblingElement();
1693 }
1694}
1695
1696void QgsManageConnectionsDialog::loadStacConnections( const QDomDocument &doc, const QStringList &items )
1697{
1698 const QDomElement root = doc.documentElement();
1699 if ( root.tagName() != "qgsStacConnections"_L1 )
1700 {
1701 QMessageBox::information( this, tr( "Loading Connections" ), tr( "The file is not a STAC connections exchange file." ) );
1702 return;
1703 }
1704
1705 QString connectionName;
1706 QgsSettings settings;
1707 settings.beginGroup( u"/qgis/connections-stac"_s );
1708 QStringList keys = settings.childGroups();
1709 settings.endGroup();
1710 QDomElement child = root.firstChildElement();
1711 bool prompt = true;
1712 bool overwrite = true;
1713
1714 while ( !child.isNull() )
1715 {
1716 connectionName = child.attribute( u"name"_s );
1717 if ( !items.contains( connectionName ) )
1718 {
1719 child = child.nextSiblingElement();
1720 continue;
1721 }
1722
1723 if ( keys.contains( connectionName ) )
1724 {
1725 switch ( checkOverwritePrompt( this, connectionName, prompt, overwrite ) )
1726 {
1727 case ActionOnDuplicate::Overwrite:
1728 break;
1729 case ActionOnDuplicate::Skip:
1730 child = child.nextSiblingElement();
1731 continue;
1732 case ActionOnDuplicate::Cancel:
1733 return;
1734 }
1735 }
1736 else
1737 {
1738 keys << connectionName;
1739 }
1740
1741 QgsStacConnection::settingsUrl->setValue( child.attribute( u"url"_s ), connectionName );
1742 QgsStacConnection::settingsAuthcfg->setValue( child.attribute( u"authcfg"_s ), connectionName );
1743 QgsStacConnection::settingsUsername->setValue( child.attribute( u"username"_s ), connectionName );
1744 QgsStacConnection::settingsPassword->setValue( child.attribute( u"password"_s ), connectionName );
1745
1746 QgsHttpHeaders httpHeader( child );
1747 QgsStacConnection::settingsHeaders->setValue( httpHeader.headers(), connectionName );
1748
1749 child = child.nextSiblingElement();
1750 }
1751}
1752
1754{
1755 listConnections->selectAll();
1756 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( !listConnections->selectedItems().isEmpty() );
1757}
1758
1760{
1761 listConnections->clearSelection();
1762 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
1763}
DpiMode
DpiMode enum.
Definition qgis.h:3596
@ Post
POST method.
Definition qgis.h:1140
@ Get
GET method.
Definition qgis.h:1139
static const QgsSettingsEntryString * settingsUsername
static const QgsSettingsEntryString * settingsUrl
static const QgsSettingsEntryString * settingsPassword
static const QgsSettingsEntryVariantMap * settingsHeaders
static QgsSettingsTreeNamedListNode * sTreeConnectionArcgis
static const QgsSettingsEntryString * settingsAuthcfg
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
QgsManageConnectionsDialog(QWidget *parent=nullptr, Mode mode=Export, Type type=WMS, const QString &fileName=QString())
Constructor for QgsManageConnectionsDialog.
@ STAC
SpatioTemporal Asset Catalog connections.
@ SensorThings
SensorThings connections.
@ TiledScene
Tiled scene connection.
@ CloudStorage
Cloud storage connections.
static const QgsSettingsEntryEnumFlag< Qgis::HttpMethod > * settingsPreferredHttpMethod
static const QgsSettingsEntryString * settingsPagingEnabled
static const QgsSettingsEntryString * settingsMaxNumFeatures
static QgsSettingsTreeNamedListNode * sTreeOwsConnections
static const QgsSettingsEntryBool * settingsIgnoreGetFeatureInfoURI
static const QgsSettingsEntryString * settingsPassword
static const QgsSettingsEntryString * settingsWfsFeatureMode
static const QgsSettingsEntryEnumFlag< Qgis::DpiMode > * settingsDpiMode
static const QgsSettingsEntryBool * settingsIgnoreAxisOrientation
static const QgsSettingsEntryBool * settingsInvertAxisOrientation
static const QgsSettingsEntryString * settingsVersion
static const QgsSettingsEntryString * settingsPagesize
static const QgsSettingsEntryVariantMap * settingsHeaders
static const QgsSettingsEntryString * settingsUsername
static const QgsSettingsEntryBool * settingsSmoothPixmapTransform
static const QgsSettingsEntryString * settingsUrl
static const QgsSettingsEntryBool * settingsDisableDecompressedSafetyCheckThreshold
static const QgsSettingsEntryBool * settingsIgnoreGetMapURI
bool setValue(const T &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
QStringList items(const QStringList &parentsNamedItems=QStringList()) const
Returns the list of items.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QStringList childGroups(Qgis::SettingsOrigin origin=Qgis::SettingsOrigin::Any) const
Returns a list of all key top-level groups that contain keys that can be read using the QSettings obj...
void endGroup()
Resets the group to what it was before the corresponding beginGroup() call.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QgsSettingsTreeNamedListNode * sTreeXyzConnections
static const QgsSettingsEntryString * settingsPassword
static const QgsSettingsEntryDouble * settingsTilePixelRatio
static const QgsSettingsEntryString * settingsUsername
static const QgsSettingsEntryString * settingsAuthcfg
static const QgsSettingsEntryInteger * settingsZmin
static const QgsSettingsEntryInteger * settingsZmax
static const QgsSettingsEntryString * settingsUrl
static const QgsSettingsEntryVariantMap * settingsHeaders