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