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