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