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