QGIS API Documentation 3.28.14-Firenze (exported)
Loading...
Searching...
No Matches
qgsmetadatawidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 QgsAbstractMetadataBasewidget.h - description
3 -------------------
4 begin : 17/05/2017
5 copyright : (C) 2017 by Etienne Trimaille
6 email : etienne at kartoza.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include <QIcon>
19#include <QPushButton>
20#include <QComboBox>
21#include <QString>
22#include <QInputDialog>
23#include <QStringListModel>
24
25#include "qgsbox3d.h"
26#include "qgsmetadatawidget.h"
27#include "qgslogger.h"
29#include "qgsapplication.h"
30#include "qgsmapcanvas.h"
31#include "qgsprojectmetadata.h"
32#include "qgsproject.h"
33
35 : QWidget( parent ),
36 mLayer( layer )
37{
38 setupUi( this );
39 tabWidget->setCurrentIndex( 0 );
40
41 // Disable the encoding
42 encodingFrame->setHidden( true );
43
44 spinBoxZMinimum->setClearValue( 0 );
45 spinBoxZMaximum->setClearValue( 0 );
46
47 // Default categories, we want them translated, so we are not using a CSV.
48 mDefaultCategories << tr( "Farming" ) << tr( "Climatology Meteorology Atmosphere" ) << tr( "Location" ) << tr( "Intelligence Military" ) << tr( "Transportation" ) << tr( "Structure" ) << tr( "Boundaries" );
49 mDefaultCategories << tr( "Inland Waters" ) << tr( "Planning Cadastre" ) << tr( "Geoscientific Information" ) << tr( "Elevation" ) << tr( "Health" ) << tr( "Biota" ) << tr( "Oceans" ) << tr( "Environment" );
50 mDefaultCategories << tr( "Utilities Communication" ) << tr( "Economy" ) << tr( "Society" ) << tr( "Imagery Base Maps Earth Cover" );
51 mDefaultCategoriesModel = new QStringListModel( mDefaultCategories, this );
52 mDefaultCategoriesModel->sort( 0 ); // Sorting using translations
53 listDefaultCategories->setModel( mDefaultCategoriesModel );
54
55 // Categories
56 mCategoriesModel = new QStringListModel( listCategories );
57 listCategories->setModel( mCategoriesModel );
58
59 // Rights
60 mRightsModel = new QStringListModel( listRights );
61 listRights->setModel( mRightsModel );
62
63 // Setup the constraints view
64 mConstraintsModel = new QStandardItemModel( tabConstraints );
65 mConstraintsModel->setColumnCount( 2 );
66 QStringList constraintheaders;
67 constraintheaders << tr( "Type" ) << tr( "Constraint" );
68 mConstraintsModel->setHorizontalHeaderLabels( constraintheaders );
69 tabConstraints->setModel( mConstraintsModel );
70 tabConstraints->setItemDelegate( new ConstraintItemDelegate( this ) );
71
72 // Extent
73 dateTimeFrom->setAllowNull( true );
74 dateTimeTo->setAllowNull( true );
75
76 // Setup the link view
77 mLinksModel = new QStandardItemModel( tabLinks );
78 mLinksModel->setColumnCount( 7 );
79 QStringList headers = QStringList();
80 headers << tr( "Name" ) << tr( "Type" ) << tr( "URL" ) << tr( "Description" ) << tr( "Format" ) << tr( "MIME" ) << tr( "Size" );
81 mLinksModel->setHorizontalHeaderLabels( headers );
82 tabLinks->setModel( mLinksModel );
83 tabLinks->setItemDelegate( new LinkItemDelegate( this ) );
84
85 // History
86 mHistoryModel = new QStringListModel( listHistory );
87 listHistory->setModel( mHistoryModel );
88
89 // Connect signals and slots
90 connect( tabWidget, &QTabWidget::currentChanged, this, &QgsMetadataWidget::updatePanel );
91 connect( btnAutoSource, &QPushButton::clicked, this, &QgsMetadataWidget::fillSourceFromLayer );
92 connect( btnAddVocabulary, &QPushButton::clicked, this, &QgsMetadataWidget::addVocabulary );
93 connect( btnRemoveVocabulary, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedVocabulary );
94 connect( btnAddRight, &QPushButton::clicked, this, &QgsMetadataWidget::addRight );
95 connect( btnRemoveRight, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedRight );
96 connect( btnAddLicence, &QPushButton::clicked, this, &QgsMetadataWidget::addLicence );
97 connect( btnRemoveLicence, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedLicence );
98 connect( btnAddConstraint, &QPushButton::clicked, this, &QgsMetadataWidget::addConstraint );
99 connect( btnRemoveConstraint, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedConstraint );
100 connect( btnSetCrsFromLayer, &QPushButton::clicked, this, &QgsMetadataWidget::fillCrsFromLayer );
101 connect( btnSetCrsFromProvider, &QPushButton::clicked, this, &QgsMetadataWidget::fillCrsFromProvider );
102 connect( btnAddAddress, &QPushButton::clicked, this, &QgsMetadataWidget::addAddress );
103 connect( btnRemoveAddress, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedAddress );
104 connect( btnAddLink, &QPushButton::clicked, this, &QgsMetadataWidget::addLink );
105 connect( btnRemoveLink, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedLink );
106 connect( btnAddHistory, &QPushButton::clicked, this, &QgsMetadataWidget::addHistory );
107 connect( btnRemoveHistory, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedHistory );
108 connect( btnNewCategory, &QPushButton::clicked, this, &QgsMetadataWidget::addNewCategory );
109 connect( btnAddDefaultCategory, &QPushButton::clicked, this, &QgsMetadataWidget::addDefaultCategories );
110 connect( btnRemoveCategory, &QPushButton::clicked, this, &QgsMetadataWidget::removeSelectedCategories );
111
112 fillComboBox();
113 if ( !mLayer )
114 {
115 btnAutoSource->setEnabled( false );
116 btnAutoEncoding->setEnabled( false );
117 btnSetCrsFromLayer->setEnabled( false );
118 }
119
120 if ( mLayer )
121 {
122 mMetadata.reset( mLayer->metadata().clone() );
124 setUiFromMetadata();
125 }
126
127 connect( lineEditTitle, &QLineEdit::textChanged, this, &QgsMetadataWidget::titleChanged );
128}
129
131{
132 QString type;
133 QString typeUpper;
134 mMode = mode;
135 switch ( mMode )
136 {
137 case LayerMetadata:
138 type = tr( "dataset" );
139 typeUpper = tr( "Dataset" );
140 mEncodingFrame->show();
141 mAuthorFrame->hide();
142 btnAutoSource->setEnabled( mLayer );
143 break;
144
145 case ProjectMetadata:
146 type = tr( "project" );
147 typeUpper = tr( "Project" );
148 mEncodingFrame->hide();
149 mAuthorFrame->show();
150 tabWidget->removeTab( 4 );
151 tabWidget->removeTab( 3 );
152 btnAutoSource->setEnabled( true );
153 break;
154 }
155
156 mIdLabel->setText( tr( "This page describes the basic attribution of the %1. Please use the tooltips for more information." ).arg( type ) );
157 mLabelCategories->setText( tr( "%1 categories." ).arg( typeUpper ) );
158 mLabelContact->setText( tr( "Contacts related to the %1." ).arg( type ) );
159 mLabelLinks->setText( tr( "Links describe ancillary resources and information related to this %1." ).arg( type ) );
160 mLabelHistory->setText( tr( "History about the %1." ).arg( type ) );
161 labelKeywords->setText( tr( "<html><head/><body><p>Keywords are optional, and provide a way to provide additional descriptive information about "
162 "the %1. Edits made in the categories tab will update the category entry below. For the concept, we suggest "
163 "to use a standard based vocabulary such as <a href=\"https://www.eionet.europa.eu/gemet/en/inspire-themes/\">"
164 "<span style=\" text-decoration: underline; color:#0000ff;\">GEMET.</span></a></p></body></html>" ).arg( type ) );
165 btnAutoSource->setText( tr( "Set from %1" ).arg( mMode == LayerMetadata ? tr( "layer" ) : tr( "project" ) ) );
166}
167
169{
170 if ( !metadata )
171 return;
172
173 if ( dynamic_cast< const QgsLayerMetadata * >( metadata ) && mMode != LayerMetadata )
175 else if ( dynamic_cast< const QgsProjectMetadata * >( metadata ) && mMode != ProjectMetadata )
177
178 mMetadata.reset( metadata->clone() );
179 setUiFromMetadata();
180}
181
183{
184 std::unique_ptr< QgsAbstractMetadataBase > md;
185 switch ( mMode )
186 {
187 case LayerMetadata:
188 md = std::make_unique< QgsLayerMetadata >();
189 break;
190
191 case ProjectMetadata:
192 md = std::make_unique< QgsProjectMetadata >();
193 break;
194
195 }
196 saveMetadata( md.get() );
197 return md.release();
198}
199
200void QgsMetadataWidget::fillSourceFromLayer()
201{
202 switch ( mMode )
203 {
204 case LayerMetadata:
205 if ( mLayer )
206 {
207 lineEditIdentifier->setText( mLayer->publicSource() );
208 }
209 break;
210
211 case ProjectMetadata:
212 lineEditIdentifier->setText( QgsProject::instance()->fileName() );
213 break;
214 }
215
216}
217
218void QgsMetadataWidget::addVocabulary()
219{
220 const int row = tabKeywords->rowCount();
221 tabKeywords->setRowCount( row + 1 );
222 QTableWidgetItem *pCell = nullptr;
223
224 // Vocabulary
225 pCell = new QTableWidgetItem( tr( "undefined %1" ).arg( row + 1 ) );
226 tabKeywords->setItem( row, 0, pCell );
227
228 // Keywords
229 pCell = new QTableWidgetItem();
230 tabKeywords->setItem( row, 1, pCell );
231}
232
233void QgsMetadataWidget::removeSelectedVocabulary()
234{
235 QItemSelectionModel *selectionModel = tabKeywords->selectionModel();
236 const QModelIndexList selectedRows = selectionModel->selectedRows();
237 for ( int i = 0; i < selectedRows.size() ; i++ )
238 {
239 tabKeywords->model()->removeRow( selectedRows[i].row() );
240 }
241}
242
243void QgsMetadataWidget::addLicence()
244{
245 QString newLicence = QInputDialog::getItem( this, tr( "New Licence" ), tr( "New Licence" ), parseLicenses(), 0, true );
246 if ( tabLicenses->findItems( newLicence, Qt::MatchExactly ).isEmpty() )
247 {
248 const int row = tabLicenses->rowCount();
249 tabLicenses->setRowCount( row + 1 );
250 QTableWidgetItem *pCell = new QTableWidgetItem( newLicence );
251 tabLicenses->setItem( row, 0, pCell );
252 }
253}
254
255void QgsMetadataWidget::removeSelectedLicence()
256{
257 QItemSelectionModel *selectionModel = tabLicenses->selectionModel();
258 const QModelIndexList selectedRows = selectionModel->selectedRows();
259 for ( int i = 0; i < selectedRows.size() ; i++ )
260 {
261 tabLicenses->model()->removeRow( selectedRows[i].row() );
262 }
263}
264
265void QgsMetadataWidget::addRight()
266{
267 QString newRight = QInputDialog::getText( this, tr( "New Right" ), tr( "New Right" ) );
268 QStringList existingRights = mRightsModel->stringList();
269 if ( ! existingRights.contains( newRight ) )
270 {
271 existingRights.append( newRight );
272 mRightsModel->setStringList( existingRights );
273 }
274}
275
276void QgsMetadataWidget::removeSelectedRight()
277{
278 QItemSelectionModel *selection = listRights->selectionModel();
279 if ( selection->hasSelection() )
280 {
281 QModelIndex indexElementSelectionne = selection->currentIndex();
282
283 QVariant item = mRightsModel->data( indexElementSelectionne, Qt::DisplayRole );
284 QStringList list = mRightsModel->stringList();
285 list.removeOne( item.toString() );
286 mRightsModel->setStringList( list );
287 }
288}
289
290void QgsMetadataWidget::addConstraint()
291{
292 const int row = mConstraintsModel->rowCount();
293 mConstraintsModel->setItem( row, 0, new QStandardItem( tr( "undefined %1" ).arg( row + 1 ) ) );
294 mConstraintsModel->setItem( row, 1, new QStandardItem( tr( "undefined %1" ).arg( row + 1 ) ) );
295}
296
297void QgsMetadataWidget::removeSelectedConstraint()
298{
299 const QModelIndexList selectedRows = tabConstraints->selectionModel()->selectedRows();
300 if ( selectedRows.empty() )
301 return;
302 mConstraintsModel->removeRow( selectedRows[0].row() );
303}
304
306{
307 if ( ( mCrs.isValid() ) && ( mLayer ) )
308 {
309 lblCurrentCrs->setText( tr( "CRS: %1" ).arg( mCrs.userFriendlyIdentifier() ) );
310 spatialExtentSelector->setEnabled( true );
311 spatialExtentSelector->setOutputCrs( mCrs );
312
313 if ( mCrs == mLayer->crs() && mCrs == mLayer->dataProvider()->crs() )
314 {
315 lblCurrentCrsStatus->setText( tr( "Same as layer properties and provider." ) );
316 }
317 else if ( mCrs == mLayer->crs() && mCrs != mLayer->dataProvider()->crs() )
318 {
319 lblCurrentCrsStatus->setText( tr( "Same as layer properties but different than the provider." ) );
320 }
321 else if ( mCrs != mLayer->crs() && mCrs == mLayer->dataProvider()->crs() )
322 {
323 lblCurrentCrsStatus->setText( tr( "Same as the provider but different than the layer properties." ) );
324 }
325 else
326 {
327 lblCurrentCrsStatus->setText( tr( "Does not match either layer properties or the provider." ) );
328 }
329 }
330 else
331 {
332 lblCurrentCrs->setText( tr( "CRS: Not set." ) );
333 lblCurrentCrsStatus->setText( QString() );
334 spatialExtentSelector->setEnabled( false );
335 }
336}
337
338void QgsMetadataWidget::addAddress()
339{
340 const int row = tabAddresses->rowCount();
341 tabAddresses->setRowCount( row + 1 );
342 QTableWidgetItem *pCell = nullptr;
343
344 // Type
345 pCell = new QTableWidgetItem( tr( "postal" ) );
346 tabAddresses->setItem( row, 0, pCell );
347
348 // Address
349 tabAddresses->setItem( row, 1, new QTableWidgetItem() );
350
351 // postal code
352 tabAddresses->setItem( row, 2, new QTableWidgetItem() );
353
354 // City
355 tabAddresses->setItem( row, 3, new QTableWidgetItem() );
356
357 // Admin area
358 tabAddresses->setItem( row, 4, new QTableWidgetItem() );
359
360 // Country
361 tabAddresses->setItem( row, 5, new QTableWidgetItem() );
362}
363
364void QgsMetadataWidget::removeSelectedAddress()
365{
366 QItemSelectionModel *selectionModel = tabAddresses->selectionModel();
367 const QModelIndexList selectedRows = selectionModel->selectedRows();
368 for ( int i = 0; i < selectedRows.size() ; i++ )
369 {
370 tabAddresses->model()->removeRow( selectedRows[i].row() );
371 }
372}
373
374void QgsMetadataWidget::fillCrsFromLayer()
375{
376 mCrs = mLayer->crs();
377 crsChanged();
378}
379
380void QgsMetadataWidget::fillCrsFromProvider()
381{
382 mCrs = mLayer->dataProvider()->crs();
383 crsChanged();
384}
385
386void QgsMetadataWidget::addLink()
387{
388 const int row = mLinksModel->rowCount();
389 mLinksModel->setItem( row, 0, new QStandardItem( tr( "undefined %1" ).arg( row + 1 ) ) );
390 mLinksModel->setItem( row, 1, new QStandardItem() );
391 mLinksModel->setItem( row, 2, new QStandardItem() );
392 mLinksModel->setItem( row, 3, new QStandardItem() );
393 mLinksModel->setItem( row, 4, new QStandardItem() );
394 mLinksModel->setItem( row, 5, new QStandardItem() );
395 mLinksModel->setItem( row, 6, new QStandardItem() );
396}
397
398void QgsMetadataWidget::removeSelectedLink()
399{
400 const QModelIndexList selectedRows = tabLinks->selectionModel()->selectedRows();
401 if ( selectedRows.empty() )
402 return;
403
404 mLinksModel->removeRow( selectedRows[0].row() );
405}
406
407void QgsMetadataWidget::addHistory()
408{
409 QString newHistory = QInputDialog::getText( this, tr( "New History" ), tr( "New History" ) );
410 QStringList existingHistory = mHistoryModel->stringList();
411 if ( ! existingHistory.contains( newHistory ) )
412 {
413 existingHistory.append( newHistory );
414 mHistoryModel->setStringList( existingHistory );
415 }
416}
417
418void QgsMetadataWidget::removeSelectedHistory()
419{
420 QItemSelectionModel *selection = listHistory->selectionModel();
421 if ( selection->hasSelection() )
422 {
423 QModelIndex indexElementSelectionne = selection->currentIndex();
424
425 QVariant item = mHistoryModel->data( indexElementSelectionne, Qt::DisplayRole );
426 QStringList list = mHistoryModel->stringList();
427 list.removeOne( item.toString() );
428 mHistoryModel->setStringList( list );
429 }
430}
431
432void QgsMetadataWidget::fillComboBox()
433{
434 // Set default values in type combobox
435 // It is advised to use the ISO 19115 MD_ScopeCode values. E.g. 'dataset' or 'series'.
436 // http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml
437 comboType->setEditable( true );
438 comboType->clear();
439 QMap<QString, QString> types = parseTypes();
440 const QStringList &keys = types.keys();
441 int i = 0;
442 for ( const QString &type : keys )
443 {
444 comboType->insertItem( i, type );
445 comboType->setItemData( i, types.value( type ), Qt::ToolTipRole );
446 i++;
447 }
448
449 // Set default values in language combobox
450 // It is advised to use the ISO 639.2 or ISO 3166 specifications, e.g. 'ENG' or 'SPA',
451 comboLanguage->setEditable( true );
452 comboLanguage->clear();
453 QMap<QString, QString> countries = parseLanguages();
454 const QStringList &k = countries.keys();
455 i = 0;
456 for ( const QString &countryCode : k )
457 {
458 comboLanguage->insertItem( i, countryCode );
459 comboLanguage->setItemData( i, countries.value( countryCode ), Qt::ToolTipRole );
460 i++;
461 }
462}
463
464void QgsMetadataWidget::setUiFromMetadata()
465{
466 // Parent ID
467 lineEditParentId->setText( mMetadata->parentIdentifier() );
468
469 // Identifier
470 if ( ! mMetadata->identifier().isEmpty() )
471 {
472 lineEditIdentifier->setText( mMetadata->identifier() );
473 }
474
475 // Title
476 if ( ! mMetadata->title().isEmpty() )
477 {
478 whileBlocking( lineEditTitle )->setText( mMetadata->title() );
479 }
480
481 // Type
482 if ( ! mMetadata->type().isEmpty() )
483 {
484 if ( comboType->findText( mMetadata->type() ) == -1 )
485 {
486 comboType->addItem( mMetadata->type() );
487 }
488 comboType->setCurrentIndex( comboType->findText( mMetadata->type() ) );
489 }
490
491 // Language
492 if ( ! mMetadata->language().isEmpty() )
493 {
494 if ( comboLanguage->findText( mMetadata->language() ) == -1 )
495 {
496 comboLanguage->addItem( mMetadata->language() );
497 }
498 comboLanguage->setCurrentIndex( comboLanguage->findText( mMetadata->language() ) );
499 }
500
501 // Abstract
502 textEditAbstract->setPlainText( mMetadata->abstract() );
503
504 // Categories
505 mCategoriesModel->setStringList( mMetadata->categories() );
506
507 // Keywords
508 tabKeywords->setRowCount( 0 );
509 QMapIterator<QString, QStringList> i( mMetadata->keywords() );
510 while ( i.hasNext() )
511 {
512 i.next();
513 addVocabulary();
514 int currentRow = tabKeywords->rowCount() - 1;
515 tabKeywords->item( currentRow, 0 )->setText( i.key() );
516 tabKeywords->item( currentRow, 1 )->setText( i.value().join( QLatin1Char( ',' ) ) );
517 }
518
519 if ( QgsLayerMetadata *layerMetadata = dynamic_cast< QgsLayerMetadata * >( mMetadata.get() ) )
520 {
521 // Encoding
522 comboEncoding->setCurrentText( layerMetadata->encoding() );
523
524 // Fees
525 lineEditFees->setText( layerMetadata->fees() );
526
527 // Licenses
528 tabLicenses->setRowCount( 0 );
529 const QStringList &licenses = layerMetadata->licenses();
530 for ( const QString &licence : licenses )
531 {
532 int currentRow = tabLicenses->rowCount();
533 tabLicenses->setRowCount( currentRow + 1 );
534 QTableWidgetItem *pCell = tabLicenses->item( currentRow, 0 );
535 if ( !pCell )
536 {
537 pCell = new QTableWidgetItem;
538 tabLicenses->setItem( currentRow, 0, pCell );
539 }
540 pCell->setText( licence );
541 }
542
543 // Rights
544 mRightsModel->setStringList( layerMetadata->rights() );
545
546 // Constraints
547 mConstraintsModel->clear();
548 const QList<QgsLayerMetadata::Constraint> &constraints = layerMetadata->constraints();
549 for ( const QgsLayerMetadata::Constraint &constraint : constraints )
550 {
551 const int row = mConstraintsModel->rowCount();
552 mConstraintsModel->setItem( row, 0, new QStandardItem( constraint.type ) );
553 mConstraintsModel->setItem( row, 1, new QStandardItem( constraint.constraint ) );
554 }
555
556 // CRS
557 mCrs = layerMetadata->crs();
558 crsChanged();
559
560 // Spatial extent
561 const QList<QgsLayerMetadata::SpatialExtent> &spatialExtents = layerMetadata->extent().spatialExtents();
562 if ( ! spatialExtents.isEmpty() )
563 {
564 // Even if it's a list, it's supposed to store the same extent in different CRS.
565 spatialExtentSelector->setOutputCrs( spatialExtents.at( 0 ).extentCrs );
566 spatialExtentSelector->setOriginalExtent( spatialExtents.at( 0 ).bounds.toRectangle(), spatialExtents.at( 0 ).extentCrs );
567 spatialExtentSelector->setOutputExtentFromOriginal();
568 spinBoxZMaximum->setValue( spatialExtents.at( 0 ).bounds.zMaximum() );
569 spinBoxZMinimum->setValue( spatialExtents.at( 0 ).bounds.zMinimum() );
570 }
571
572 // Temporal extent
573 const QList<QgsDateTimeRange> &temporalExtents = layerMetadata->extent().temporalExtents();
574 if ( ! temporalExtents.isEmpty() )
575 {
576 // Even if it's a list, it seems we use only one for now (cf discussion with Tom)
577 dateTimeFrom->setDateTime( temporalExtents.at( 0 ).begin() );
578 dateTimeTo->setDateTime( temporalExtents.at( 0 ).end() );
579 }
580 else
581 {
582 dateTimeFrom->clear();
583 dateTimeTo->clear();
584 }
585 }
586 else if ( QgsProjectMetadata *projectMetadata = dynamic_cast< QgsProjectMetadata * >( mMetadata.get() ) )
587 {
588 mLineEditAuthor->setText( projectMetadata->author() );
589 mCreationDateTimeEdit->setDateTime( projectMetadata->creationDateTime() );
590 }
591
592 // Contacts
593 const QList<QgsAbstractMetadataBase::Contact> &contacts = mMetadata->contacts();
594 if ( ! contacts.isEmpty() )
595 {
596 // Only one contact supported in the UI for now
597 const QgsAbstractMetadataBase::Contact &contact = contacts.at( 0 );
598 lineEditContactName->setText( contact.name );
599 lineEditContactEmail->setText( contact.email );
600 lineEditContactFax->setText( contact.fax );
601 lineEditContactOrganization->setText( contact.organization );
602 lineEditContactPosition->setText( contact.position );
603 lineEditContactVoice->setText( contact.voice );
604 if ( comboContactRole->findText( contact.role ) == -1 )
605 {
606 comboContactRole->addItem( contact.role );
607 }
608 comboContactRole->setCurrentIndex( comboContactRole->findText( contact.role ) );
609 tabAddresses->setRowCount( 0 );
610 const QList<QgsAbstractMetadataBase::Address> &addresses = contact.addresses;
611 for ( const QgsAbstractMetadataBase::Address &address : addresses )
612 {
613 int currentRow = tabAddresses->rowCount();
614 tabAddresses->setRowCount( currentRow + 1 );
615 tabAddresses->setItem( currentRow, 0, new QTableWidgetItem( address.type ) );
616 tabAddresses->setItem( currentRow, 1, new QTableWidgetItem( address.address ) );
617 tabAddresses->setItem( currentRow, 2, new QTableWidgetItem( address.postalCode ) );
618 tabAddresses->setItem( currentRow, 3, new QTableWidgetItem( address.city ) );
619 tabAddresses->setItem( currentRow, 4, new QTableWidgetItem( address.administrativeArea ) );
620 tabAddresses->setItem( currentRow, 5, new QTableWidgetItem( address.country ) );
621 }
622 }
623
624 // Links
625 const QList<QgsAbstractMetadataBase::Link> &links = mMetadata->links();
626 mLinksModel->setRowCount( 0 );
627 for ( const QgsAbstractMetadataBase::Link &link : links )
628 {
629 const int row = mLinksModel->rowCount();
630 mLinksModel->setItem( row, 0, new QStandardItem( link.name ) );
631 mLinksModel->setItem( row, 1, new QStandardItem( link.type ) );
632 mLinksModel->setItem( row, 2, new QStandardItem( link.url ) );
633 mLinksModel->setItem( row, 3, new QStandardItem( link.description ) );
634 mLinksModel->setItem( row, 4, new QStandardItem( link.format ) );
635 mLinksModel->setItem( row, 5, new QStandardItem( link.mimeType ) );
636 mLinksModel->setItem( row, 6, new QStandardItem( link.size ) );
637 }
638
639 // History
640 mHistoryModel->setStringList( mMetadata->history() );
641}
642
644{
645 if ( !metadata )
646 return;
647
648 metadata->setParentIdentifier( lineEditParentId->text() );
649 metadata->setIdentifier( lineEditIdentifier->text() );
650 metadata->setTitle( lineEditTitle->text() );
651 metadata->setType( comboType->currentText() );
652 metadata->setLanguage( comboLanguage->currentText() );
653 metadata->setAbstract( textEditAbstract->toPlainText() );
654
655 // Keywords, it will save categories too.
656 syncFromCategoriesTabToKeywordsTab();
657 QMap<QString, QStringList> keywords;
658 for ( int i = 0; i < tabKeywords->rowCount() ; i++ )
659 {
660 keywords.insert( tabKeywords->item( i, 0 )->text(), tabKeywords->item( i, 1 )->text().split( ',' ) );
661 }
662 metadata->setKeywords( keywords );
663
664 switch ( mMode )
665 {
666 case LayerMetadata:
667 {
668 QgsLayerMetadata *layerMetadata = static_cast< QgsLayerMetadata * >( metadata );
669 // Fees
670 layerMetadata->setFees( lineEditFees->text() );
671
672 // Licenses
673 QStringList licenses;
674 for ( int i = 0; i < tabLicenses->rowCount() ; i++ )
675 {
676 licenses.append( tabLicenses->item( i, 0 )->text() );
677 }
678 layerMetadata->setLicenses( licenses );
679
680 // Rights
681 layerMetadata->setRights( mRightsModel->stringList() );
682
683 // Encoding
684 layerMetadata->setEncoding( comboEncoding->currentText() );
685
686 // Constraints
687 QList<QgsLayerMetadata::Constraint> constraints;
688 for ( int row = 0; row < mConstraintsModel->rowCount() ; row++ )
689 {
691 constraint.type = mConstraintsModel->item( row, 0 )->text();
692 constraint.constraint = mConstraintsModel->item( row, 1 )->text();
693 constraints.append( constraint );
694 }
695 layerMetadata->setConstraints( constraints );
696
697 // CRS
698 if ( mCrs.isValid() )
699 {
700 layerMetadata->setCrs( mCrs );
701 }
702
703 // Extent
705 spatialExtent.bounds = QgsBox3d( spatialExtentSelector->outputExtent() );
706 spatialExtent.bounds.setZMinimum( spinBoxZMinimum->value() );
707 spatialExtent.bounds.setZMaximum( spinBoxZMaximum->value() );
708 spatialExtent.extentCrs = spatialExtentSelector->outputCrs();
709 QList<QgsLayerMetadata::SpatialExtent> spatialExtents;
710 spatialExtents.append( spatialExtent );
711 QList<QgsDateTimeRange> temporalExtents;
712 temporalExtents.append( QgsDateTimeRange( dateTimeFrom->dateTime(), dateTimeTo->dateTime() ) );
714 extent.setSpatialExtents( spatialExtents );
715 extent.setTemporalExtents( temporalExtents );
716 layerMetadata->setExtent( extent );
717 break;
718 }
719
720 case ProjectMetadata:
721 {
722 QgsProjectMetadata *projectMetadata = static_cast< QgsProjectMetadata * >( metadata );
723 projectMetadata->setAuthor( mLineEditAuthor->text() );
724 projectMetadata->setCreationDateTime( mCreationDateTimeEdit->dateTime() );
725 break;
726 }
727 }
728
729 // Contacts, only one contact supported in the UI for now.
730 // We don't want to lost data if more than one contact, so we update only the first one.
731 QList<QgsAbstractMetadataBase::Contact> contacts = mMetadata->contacts();
732 if ( contacts.size() > 0 )
733 contacts.removeFirst();
735 contact.email = lineEditContactEmail->text();
736 contact.position = lineEditContactPosition->text();
737 contact.fax = lineEditContactFax->text();
738 contact.voice = lineEditContactVoice->text();
739 contact.name = lineEditContactName->text();
740 contact.organization = lineEditContactOrganization->text();
741 contact.role = comboContactRole->currentText();
742 QList<QgsAbstractMetadataBase::Address> addresses;
743 for ( int i = 0; i < tabAddresses->rowCount() ; i++ )
744 {
746 address.type = tabAddresses->item( i, 0 )->text();
747 address.address = tabAddresses->item( i, 1 )->text();
748 address.postalCode = tabAddresses->item( i, 2 )->text();
749 address.city = tabAddresses->item( i, 3 )->text();
750 address.administrativeArea = tabAddresses->item( i, 4 )->text();
751 address.country = tabAddresses->item( i, 5 )->text();
752 addresses.append( address );
753 }
754 contact.addresses = addresses;
755 contacts.insert( 0, contact );
756 metadata->setContacts( contacts );
757
758 // Links
759 QList<QgsAbstractMetadataBase::Link> links;
760 for ( int row = 0; row < mLinksModel->rowCount() ; row++ )
761 {
763 link.name = mLinksModel->item( row, 0 )->text();
764 link.type = mLinksModel->item( row, 1 )->text();
765 link.url = mLinksModel->item( row, 2 )->text();
766 link.description = mLinksModel->item( row, 3 )->text();
767 link.format = mLinksModel->item( row, 4 )->text();
768 link.mimeType = mLinksModel->item( row, 5 )->text();
769 link.size = mLinksModel->item( row, 6 )->text();
770 links.append( link );
771 }
772 metadata->setLinks( links );
773
774 // History
775 metadata->setHistory( mHistoryModel->stringList() );
776}
777
779{
780 std::unique_ptr< QgsAbstractMetadataBase > md( metadata() );
781
782 std::unique_ptr< QgsNativeMetadataBaseValidator > validator;
783 switch ( mMode )
784 {
785 case LayerMetadata:
786 validator = std::make_unique< QgsNativeMetadataValidator>();
787 break;
788
789 case ProjectMetadata:
790 validator = std::make_unique< QgsNativeProjectMetadataValidator>();
791 break;
792 }
793
794 QList<QgsAbstractMetadataBaseValidator::ValidationResult> validationResults;
795 bool results = validator->validate( md.get(), validationResults );
796
797 QString errors;
798 if ( !results )
799 {
800 for ( const QgsAbstractMetadataBaseValidator::ValidationResult &result : std::as_const( validationResults ) )
801 {
802 errors += QLatin1String( "<b>" ) % result.section;
803 if ( ! QgsVariantUtils::isNull( result._identifier() ) )
804 {
805 errors += QLatin1Char( ' ' ) % QVariant( result._identifier().toInt() + 1 ).toString();
806 }
807 errors += QLatin1String( "</b>: " ) % result.note % QLatin1String( "<br />" );
808 }
809 }
810 else
811 {
812 errors = tr( "Ok, it seems valid according to the QGIS Schema." );
813 }
814
815 QString myStyle = QgsApplication::reportStyleSheet();
816 myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
817 resultsCheckMetadata->clear();
818 resultsCheckMetadata->document()->setDefaultStyleSheet( myStyle );
819 resultsCheckMetadata->setHtml( errors );
820
821 return results;
822}
823
824QMap<QString, QString> QgsMetadataWidget::parseLanguages()
825{
826 QMap<QString, QString> countries;
827 countries.insert( QString(), QString() ); // We add an empty line, because it's not compulsory.
828
829 QString path = QDir( QgsApplication::metadataPath() ).absoluteFilePath( QStringLiteral( "language_codes_ISO_639.csv" ) );
830 QFile file( path );
831 if ( !file.open( QIODevice::ReadOnly ) )
832 {
833 QgsDebugMsg( QStringLiteral( "Error while opening the CSV file: %1, %2 " ).arg( path, file.errorString() ) );
834 return countries;
835 }
836
837 // Skip the first line of the CSV
838 file.readLine();
839 while ( !file.atEnd() )
840 {
841 QByteArray line = file.readLine();
842 QList<QByteArray> items = line.split( ',' );
843 countries.insert( QString( items.at( 0 ).constData() ).trimmed(), QString( items.at( 1 ).constData() ).trimmed() );
844 }
845 file.close();
846
847 path = QDir( QgsApplication::metadataPath() ).absoluteFilePath( QStringLiteral( "country_code_ISO_3166.csv" ) );
848 QFile secondFile( path );
849 if ( !secondFile.open( QIODevice::ReadOnly ) )
850 {
851 QgsDebugMsg( QStringLiteral( "Error while opening the CSV file: %1, %2 " ).arg( path, file.errorString() ) );
852 return countries;
853 }
854
855 // Skip the first line of the CSV
856 secondFile.readLine();
857 while ( !secondFile.atEnd() )
858 {
859 QByteArray line = secondFile.readLine();
860 QList<QByteArray> items = line.split( ',' );
861 countries.insert( QString( items.at( 2 ).constData() ).trimmed(), QString( items.at( 0 ).constData() ).trimmed() );
862 }
863 secondFile.close();
864 return countries;
865}
866
868{
869 QStringList wordList;
870 wordList.append( QString() ); // We add an empty line, because it's not compulsory.
871
872 QString path = QDir( QgsApplication::metadataPath() ).absoluteFilePath( QStringLiteral( "licenses.csv" ) );
873 QFile file( path );
874 if ( !file.open( QIODevice::ReadOnly ) )
875 {
876 QgsDebugMsg( QStringLiteral( "Error while opening the CSV file: %1, %2 " ).arg( path, file.errorString() ) );
877 return wordList;
878 }
879
880 // Skip the first line of the CSV
881 file.readLine();
882 while ( !file.atEnd() )
883 {
884 QByteArray line = file.readLine();
885 wordList.append( line.split( ',' ).at( 0 ).trimmed() );
886 }
887 file.close();
888 return wordList;
889}
890
892{
893 QStringList wordList;
894 wordList.append( QString() ); // We add an empty line, because it's not compulsory.
895
896 QString path = QDir( QgsApplication::metadataPath() ).absoluteFilePath( QStringLiteral( "LinkPropertyLookupTable.csv" ) );
897 QFile file( path );
898 if ( !file.open( QIODevice::ReadOnly ) )
899 {
900 QgsDebugMsg( QStringLiteral( "Error while opening the CSV file: %1, %2 " ).arg( path, file.errorString() ) );
901 return wordList;
902 }
903
904 // Skip the first line of the CSV
905 file.readLine();
906 while ( !file.atEnd() )
907 {
908 QByteArray line = file.readLine();
909 wordList.append( line.split( ',' ).at( 0 ).trimmed() );
910 }
911 file.close();
912 return wordList;
913}
914
916{
917 QStringList wordList;
918 wordList.append( QString() ); // We add an empty line, because it's not compulsory.
919
920 QString path = QDir( QgsApplication::metadataPath() ).absoluteFilePath( QStringLiteral( "mime.csv" ) );
921 QFile file( path );
922 if ( !file.open( QIODevice::ReadOnly ) )
923 {
924 QgsDebugMsg( QStringLiteral( "Error while opening the CSV file: %1, %2 " ).arg( path, file.errorString() ) );
925 return wordList;
926 }
927
928 while ( !file.atEnd() )
929 {
930 QByteArray line = file.readLine();
931 wordList.append( line.split( ',' ).at( 0 ).trimmed() );
932 }
933 file.close();
934 return wordList;
935}
936
937QMap<QString, QString> QgsMetadataWidget::parseTypes()
938{
939 QMap<QString, QString> types;
940 types.insert( QString(), QString() ); // We add an empty line, because it's not compulsory.
941 QString path = QDir( QgsApplication::metadataPath() ).absoluteFilePath( QStringLiteral( "md_scope_codes.csv" ) );
942 QFile file( path );
943 if ( !file.open( QIODevice::ReadOnly ) )
944 {
945 QgsDebugMsg( QStringLiteral( "Error while opening the CSV file: %1, %2 " ).arg( path, file.errorString() ) );
946 return types;
947 }
948
949 types.insert( QString(), QString() ); // We add an empty line, because it's not compulsory.
950 while ( !file.atEnd() )
951 {
952 QByteArray line = file.readLine();
953 QList<QByteArray> items = line.split( ';' );
954 types.insert( items.at( 0 ).constData(), items.at( 1 ).constData() );
955 }
956 file.close();
957 return types;
958}
959
961{
962 if ( canvas )
963 spatialExtentSelector->setCurrentExtent( canvas->extent(), canvas->mapSettings().destinationCrs() );
964}
965
967{
968 return lineEditTitle->text();
969}
970
971void QgsMetadataWidget::setTitle( const QString &title )
972{
973 if ( title != lineEditTitle->text() )
974 {
975 whileBlocking( lineEditTitle )->setText( title );
976 emit titleChanged( title );
977 }
978}
979
981{
982 saveMetadata( mMetadata.get() );
983 switch ( mMode )
984 {
985 case LayerMetadata:
986 if ( mLayer )
987 {
988 // Save layer metadata properties
989 mLayer->setMetadata( *static_cast< QgsLayerMetadata * >( mMetadata.get() ) );
990 }
991 break;
992
993 case ProjectMetadata:
994 QgsProject::instance()->setMetadata( *static_cast< QgsProjectMetadata * >( mMetadata.get() ) );
995 break;
996 }
997}
998
999void QgsMetadataWidget::syncFromCategoriesTabToKeywordsTab()
1000{
1001 if ( mCategoriesModel->rowCount() > 0 )
1002 {
1003 QList<QTableWidgetItem *> categories = tabKeywords->findItems( QStringLiteral( "gmd:topicCategory" ), Qt::MatchExactly );
1004 int row;
1005 if ( !categories.isEmpty() )
1006 {
1007 row = categories.at( 0 )->row();
1008 }
1009 else
1010 {
1011 // Create a new line with 'gmd:topicCategory'
1012 addVocabulary();
1013 row = tabKeywords->rowCount() - 1;
1014 tabKeywords->item( row, 0 )->setText( QStringLiteral( "gmd:topicCategory" ) );
1015 }
1016 tabKeywords->item( row, 1 )->setText( mCategoriesModel->stringList().join( QLatin1Char( ',' ) ) );
1017 }
1018}
1019
1020void QgsMetadataWidget::updatePanel()
1021{
1022 int index = tabWidget->currentIndex();
1023 QString currentTabText = tabWidget->widget( index )->objectName();
1024 if ( currentTabText == QLatin1String( "tabCategoriesDialog" ) )
1025 {
1026 // Categories tab
1027 // We need to take keywords and insert them into the list
1028 QList<QTableWidgetItem *> categories = tabKeywords->findItems( QStringLiteral( "gmd:topicCategory" ), Qt::MatchExactly );
1029 if ( !categories.isEmpty() )
1030 {
1031 const int row = categories.at( 0 )->row();
1032 mCategoriesModel->setStringList( tabKeywords->item( row, 1 )->text().split( ',' ) );
1033 }
1034 else
1035 {
1036 mCategoriesModel->setStringList( QStringList() );
1037 }
1038 }
1039 else if ( currentTabText == QLatin1String( "tabKeywordsDialog" ) )
1040 {
1041 // Keywords tab
1042 // We need to take categories and insert them into the table
1043 syncFromCategoriesTabToKeywordsTab();
1044 }
1045 else if ( currentTabText == QLatin1String( "tabValidationDialog" ) )
1046 {
1047 checkMetadata();
1048 }
1049}
1050
1051void QgsMetadataWidget::addNewCategory()
1052{
1053 bool ok;
1054 QString text = QInputDialog::getText( this, tr( "New Category" ),
1055 tr( "New Category:" ), QLineEdit::Normal,
1056 QString(), &ok );
1057 if ( ok && !text.isEmpty() )
1058 {
1059 QStringList list = mCategoriesModel->stringList();
1060 if ( ! list.contains( text ) )
1061 {
1062 list.append( text );
1063 mCategoriesModel->setStringList( list );
1064 mCategoriesModel->sort( 0 );
1065 }
1066 }
1067}
1068
1069void QgsMetadataWidget::addDefaultCategories()
1070{
1071 const QModelIndexList selectedIndexes = listDefaultCategories->selectionModel()->selectedIndexes();
1072 QStringList defaultCategoriesList = mDefaultCategoriesModel->stringList();
1073 QStringList selectedCategories = mCategoriesModel->stringList();
1074
1075 for ( const QModelIndex &selection : selectedIndexes )
1076 {
1077 QVariant item = mDefaultCategoriesModel->data( selection, Qt::DisplayRole );
1078 defaultCategoriesList.removeOne( item.toString() );
1079
1080 selectedCategories.append( item.toString() );
1081 }
1082
1083 mDefaultCategoriesModel->setStringList( defaultCategoriesList );
1084 mCategoriesModel->setStringList( selectedCategories );
1085 mCategoriesModel->sort( 0 );
1086}
1087
1088void QgsMetadataWidget::removeSelectedCategories()
1089{
1090 const QModelIndexList selectedIndexes = listCategories->selectionModel()->selectedIndexes();
1091 QStringList categories = mCategoriesModel->stringList();
1092 QStringList defaultList = mDefaultCategoriesModel->stringList();
1093
1094 for ( const QModelIndex &selection : selectedIndexes )
1095 {
1096 QVariant item = mCategoriesModel->data( selection, Qt::DisplayRole );
1097 categories.removeOne( item.toString() );
1098
1099 if ( mDefaultCategories.contains( item.toString() ) )
1100 {
1101 defaultList.append( item.toString() );
1102 }
1103 }
1104 mCategoriesModel->setStringList( categories );
1105
1106 mDefaultCategoriesModel->setStringList( defaultList );
1107 mDefaultCategoriesModel->sort( 0 );
1108}
1109
1111LinkItemDelegate::LinkItemDelegate( QObject *parent )
1112 : QStyledItemDelegate( parent )
1113{
1114
1115}
1116
1117QWidget *LinkItemDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
1118{
1119 if ( index.column() == 1 )
1120 {
1121 // Link type
1122 QComboBox *typeEditor = new QComboBox( parent );
1123 typeEditor->setEditable( true );
1124 QStringListModel *model = new QStringListModel( parent );
1125 model->setStringList( QgsMetadataWidget::parseLinkTypes() );
1126 typeEditor->setModel( model );
1127 return typeEditor;
1128 }
1129 else if ( index.column() == 5 )
1130 {
1131 // MIME
1132 QComboBox *mimeEditor = new QComboBox( parent );
1133 mimeEditor->setEditable( true );
1134 QStringListModel *model = new QStringListModel( parent );
1135 model->setStringList( QgsMetadataWidget::parseMimeTypes() );
1136 mimeEditor->setModel( model );
1137 return mimeEditor;
1138 }
1139
1140 return QStyledItemDelegate::createEditor( parent, option, index );
1141}
1142
1143ConstraintItemDelegate::ConstraintItemDelegate( QObject *parent )
1144 : QStyledItemDelegate( parent )
1145{
1146
1147}
1148
1149QWidget *ConstraintItemDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
1150{
1151 if ( index.column() == 0 )
1152 {
1153 // Constraint type
1154 QComboBox *typeEditor = new QComboBox( parent );
1155 typeEditor->setEditable( true );
1156 QStringList types;
1157 types << QStringLiteral( "access" ) << QStringLiteral( "use" ) << QStringLiteral( "other" );
1158 QStringListModel *model = new QStringListModel( parent );
1159 model->setStringList( types );
1160 typeEditor->setModel( model );
1161 return typeEditor;
1162 }
1163
1164 return QStyledItemDelegate::createEditor( parent, option, index );
1165}
Contains the parameters describing a metadata validation failure.
An abstract base class for metadata stores.
void setAbstract(const QString &abstract)
Sets a free-form abstract (description) of the resource.
void setType(const QString &type)
Sets the type (nature) of the resource.
void setParentIdentifier(const QString &parentIdentifier)
Sets a reference, URI, URL or some other mechanism to identify the parent resource that this resource...
void setTitle(const QString &title)
Sets the human readable title (name) of the resource, typically displayed in search results.
void setHistory(const QStringList &history)
Sets the freeform description of the history or lineage of the resource.
void setLinks(const QgsAbstractMetadataBase::LinkList &links)
Sets the list of online resources associated with the resource.
void setIdentifier(const QString &identifier)
Sets the reference, URI, URL or some other mechanism to identify the resource.
void setContacts(const QgsAbstractMetadataBase::ContactList &contacts)
Sets the list of contacts or entities associated with the resource.
void setKeywords(const QgsAbstractMetadataBase::KeywordMap &keywords)
Sets the keywords map, which is a set of descriptive keywords associated with the resource.
void setLanguage(const QString &language)
Sets the human language associated with the resource.
virtual QgsAbstractMetadataBase * clone() const =0
Clones the metadata object.
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
static QString metadataPath()
Returns the path to the metadata directory.
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:39
void setZMinimum(double z)
Sets the minimum z value.
Definition qgsbox3d.cpp:59
void setZMaximum(double z)
Sets the maximum z value.
Definition qgsbox3d.cpp:64
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString userFriendlyIdentifier(IdentifierType type=MediumString) const
Returns a user friendly identifier for the CRS.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
A structured metadata store for a map layer.
void setConstraints(const QgsLayerMetadata::ConstraintList &constraints)
Sets the list of constraints associated with using the resource.
void setFees(const QString &fees)
Sets the fees associated with using the resource.
void setLicenses(const QStringList &licenses)
Sets a list of licenses associated with the resource.
void setRights(const QStringList &rights)
Sets a list of rights (attribution or copyright strings) associated with the resource.
void setEncoding(const QString &encoding)
Sets the character encoding of the data in the resource.
QgsLayerMetadata * clone() const override
Clones the metadata object.
void setExtent(const QgsLayerMetadata::Extent &extent)
Sets the spatial and temporal extents associated with the resource.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the coordinate reference system for the layer's metadata.
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Base class for all map layer types.
Definition qgsmaplayer.h:73
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:79
QgsLayerMetadata metadata
Definition qgsmaplayer.h:78
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
void acceptMetadata()
Saves the metadata to the layer.
QgsMetadataWidget(QWidget *parent SIP_TRANSFERTHIS=nullptr, QgsMapLayer *layer=nullptr)
Constructor for the wizard.
static QMap< QString, QString > parseTypes()
Returns a list of types available by default in the wizard.
void crsChanged()
If the CRS is updated.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas associated with the widget.
static QStringList parseLicenses()
Returns a list of licences available by default in the wizard.
void saveMetadata(QgsAbstractMetadataBase *metadata)
Save all fields in a metadata object.
static QMap< QString, QString > parseLanguages()
Returns a list of languages available by default in the wizard.
void setMetadata(const QgsAbstractMetadataBase *metadata)
Sets the metadata to display in the widget.
static QStringList parseLinkTypes()
Returns a list of link types available by default in the wizard.
bool checkMetadata()
Check if values in the wizard are correct.
@ LayerMetadata
Show layer metadata.
@ ProjectMetadata
Show project metadata.
Mode mode() const
Returns the widget's current mode.
static QStringList parseMimeTypes()
Returns a list of MIME types available by default in the wizard.
QgsAbstractMetadataBase * metadata() SIP_FACTORY
Returns a QgsAbstractMetadataBase object representing the current state of the widget.
void setMode(Mode mode)
Sets the widget's current mode.
void titleChanged(const QString &title)
Emitted when the title field is changed.
void setTitle(const QString &title)
Sets the title field for the metadata.
A structured metadata store for a map layer.
void setCreationDateTime(const QDateTime &creationDateTime)
Sets the project's creation date/timestamp.
void setAuthor(const QString &author)
Sets the project author string.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void setMetadata(const QgsProjectMetadata &metadata)
Sets the project's metadata store.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:2453
#define QgsDebugMsg(str)
Definition qgslogger.h:38
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:693
QString administrativeArea
Administrative area (state, province/territory, etc.).
QString address
Free-form physical address component, e.g.
QString city
City or locality name.
QString country
Free-form country string.
QString postalCode
Postal (or ZIP) code.
QString position
Position/title of contact.
QList< QgsAbstractMetadataBase::Address > addresses
List of addresses associated with this contact.
QString email
Electronic mail address.
QString organization
Organization contact belongs to/represents.
Metadata constraint structure.
QString constraint
Free-form constraint string.
QString type
Constraint type.
Metadata extent structure.
void setSpatialExtents(const QList< QgsLayerMetadata::SpatialExtent > &extents)
Sets the spatial extents of the resource.
void setTemporalExtents(const QList< QgsDateTimeRange > &extents)
Sets the temporal extents of the resource.
Metadata spatial extent structure.
QgsCoordinateReferenceSystem extentCrs
Coordinate reference system for spatial extent.
QgsBox3d bounds
Geospatial extent of the resource.