Skip to content

Commit

Permalink
[feature] Add key dates to layer/project metadata
Browse files Browse the repository at this point in the history
This adds the following fields to the QGIS layer/project metadata
standard:

- Date created
- Date published
- Date revised
- Date superseded

(Previously the layer metadata had no date fields, and project
metadata had only the created date field)
  • Loading branch information
nyalldawson committed Nov 30, 2022
1 parent 82462b5 commit 6b65b42
Show file tree
Hide file tree
Showing 13 changed files with 450 additions and 22 deletions.
8 changes: 8 additions & 0 deletions python/core/auto_additions/qgis.py
Expand Up @@ -2266,3 +2266,11 @@
Qgis.AttributeActionType.__doc__ = 'Attribute action types.\n\nPrior to QGIS 3.30 this was available as :py:class:`QgsAction`.ActionType\n\n.. versionadded:: 3.30\n\n' + '* ``Generic``: ' + Qgis.AttributeActionType.Generic.__doc__ + '\n' + '* ``GenericPython``: ' + Qgis.AttributeActionType.GenericPython.__doc__ + '\n' + '* ``Mac``: ' + Qgis.AttributeActionType.Mac.__doc__ + '\n' + '* ``Windows``: ' + Qgis.AttributeActionType.Windows.__doc__ + '\n' + '* ``Unix``: ' + Qgis.AttributeActionType.Unix.__doc__ + '\n' + '* ``OpenUrl``: ' + Qgis.AttributeActionType.OpenUrl.__doc__ + '\n' + '* ``SubmitUrlEncoded``: ' + Qgis.AttributeActionType.SubmitUrlEncoded.__doc__ + '\n' + '* ``SubmitUrlMultipart``: ' + Qgis.AttributeActionType.SubmitUrlMultipart.__doc__
# --
Qgis.AttributeActionType.baseClass = Qgis
# monkey patching scoped based enum
Qgis.MetadataDateType.Created.__doc__ = "Date created"
Qgis.MetadataDateType.Published.__doc__ = "Date published"
Qgis.MetadataDateType.Revised.__doc__ = "Date revised"
Qgis.MetadataDateType.Superseded.__doc__ = "Date superseded"
Qgis.MetadataDateType.__doc__ = 'Date types for metadata.\n\n.. versionadded:: 3.30\n\n' + '* ``Created``: ' + Qgis.MetadataDateType.Created.__doc__ + '\n' + '* ``Published``: ' + Qgis.MetadataDateType.Published.__doc__ + '\n' + '* ``Revised``: ' + Qgis.MetadataDateType.Revised.__doc__ + '\n' + '* ``Superseded``: ' + Qgis.MetadataDateType.Superseded.__doc__
# --
Qgis.MetadataDateType.baseClass = Qgis
19 changes: 19 additions & 0 deletions python/core/auto_generated/metadata/qgsabstractmetadatabase.sip.in
Expand Up @@ -399,6 +399,24 @@ Adds an individual ``link`` to the existing links.
.. seealso:: :py:func:`links`

.. seealso:: :py:func:`setLinks`
%End

QDateTime dateTime( Qgis::MetadataDateType type ) const;
%Docstring
Returns the date for the specified date ``type``.

.. seealso:: :py:func:`setDateTime`

.. versionadded:: 3.30
%End

void setDateTime( Qgis::MetadataDateType type, QDateTime date );
%Docstring
Sets a date value for the specified date ``type``.

.. seealso:: :py:func:`dateTime`

.. versionadded:: 3.30
%End

virtual bool readMetadataXml( const QDomElement &metadataElement );
Expand Down Expand Up @@ -452,6 +470,7 @@ QgsAbstractMetadataBase cannot be instantiated directly, it must be subclassed.




bool equals( const QgsAbstractMetadataBase &other ) const;
%Docstring
Tests whether the common metadata fields in this object are equal to ``other``.
Expand Down
8 changes: 8 additions & 0 deletions python/core/auto_generated/qgis.sip.in
Expand Up @@ -1502,6 +1502,14 @@ The development version
SubmitUrlMultipart,
};

enum class MetadataDateType
{
Created,
Published,
Revised,
Superseded,
};

static const double DEFAULT_SEARCH_RADIUS_MM;

static const float DEFAULT_MAPTOPIXEL_THRESHOLD;
Expand Down
24 changes: 24 additions & 0 deletions resources/qgis-base-metadata.xsd
Expand Up @@ -66,6 +66,11 @@
<xs:documentation>Set of descriptive keywords associated with a given resource.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="dates" type="rm:datesType">
<xs:annotation>
<xs:documentation>Set of key dates associated with a given resource.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="contact" type="rm:contactType" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Contact person/entity associated with a given resource.</xs:documentation>
Expand Down Expand Up @@ -102,6 +107,25 @@
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="datesType">
<xs:sequence>
<xs:element name="date" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A dates associated with a resource.</xs:documentation>
</xs:annotation>
<xs:attribute name="type" type="xs:string">
<xs:annotation>
<xs:documentation>Date type, valid values are Created, Published, Revised, Superseded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="value" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Associated datetime value.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="contactType">
<xs:sequence>
<xs:element name="name" type="xs:string">
Expand Down
63 changes: 62 additions & 1 deletion src/core/metadata/qgsabstractmetadatabase.cpp
Expand Up @@ -160,6 +160,19 @@ void QgsAbstractMetadataBase::addLink( const QgsAbstractMetadataBase::Link &link
mLinks << link;
}

QDateTime QgsAbstractMetadataBase::dateTime( Qgis::MetadataDateType type ) const
{
return mDates.value( type );
}

void QgsAbstractMetadataBase::setDateTime( Qgis::MetadataDateType type, QDateTime date )
{
if ( !date.isValid() || date.isNull() )
mDates.remove( type );
else
mDates[type] = date;
}

QString QgsAbstractMetadataBase::language() const
{
return mLanguage;
Expand Down Expand Up @@ -281,6 +294,24 @@ bool QgsAbstractMetadataBase::readMetadataXml( const QDomElement &metadataElemen
}
setHistory( historyList );

{
mDates.clear();
const QDomElement dateElement = metadataElement.firstChildElement( QStringLiteral( "dates" ) );
if ( !dateElement.isNull() )
{
const QDomNodeList dateNodeList = dateElement.elementsByTagName( QStringLiteral( "date" ) );
const QMetaEnum dateEnum = QMetaEnum::fromType<Qgis::MetadataDateType>();
for ( int i = 0; i < dateNodeList.size(); i++ )
{
const QDomElement dateElement = dateNodeList.at( i ).toElement();
const Qgis::MetadataDateType type = static_cast< Qgis::MetadataDateType >( dateEnum.keyToValue( dateElement.attribute( QStringLiteral( "type" ) ).toStdString().c_str() ) );
const QDateTime value = QDateTime::fromString( dateElement.attribute( QStringLiteral( "value" ) ), Qt::ISODate );
if ( value.isValid() && !value.isNull() )
mDates.insert( type, value );
}
}
}

return true;
}

Expand Down Expand Up @@ -429,6 +460,24 @@ bool QgsAbstractMetadataBase::writeMetadataXml( QDomElement &metadataElement, QD
metadataElement.appendChild( historyElement );
}

// dates
{
const QMetaEnum dateEnum = QMetaEnum::fromType<Qgis::MetadataDateType>();
QDomElement datesElement = document.createElement( QStringLiteral( "dates" ) );
for ( int k = 0; k < dateEnum.keyCount(); k++ )
{
const Qgis::MetadataDateType type = static_cast< Qgis::MetadataDateType >( dateEnum.value( k ) );
if ( mDates.contains( type ) && mDates.value( type ).isValid() )
{
QDomElement dateElement = document.createElement( QStringLiteral( "date" ) );
dateElement.setAttribute( QStringLiteral( "type" ), dateEnum.valueToKey( static_cast< int >( type ) ) );
dateElement.setAttribute( QStringLiteral( "value" ), mDates.value( type ).toString( Qt::ISODate ) );
datesElement.appendChild( dateElement );
}
}
metadataElement.appendChild( datesElement );
}

return true;
}

Expand Down Expand Up @@ -466,6 +515,17 @@ void QgsAbstractMetadataBase::combine( const QgsAbstractMetadataBase *other )

if ( !other->links().isEmpty() )
mLinks = other->links();

const QMetaEnum dateEnum = QMetaEnum::fromType<Qgis::MetadataDateType>();
for ( int k = 0; k < dateEnum.keyCount(); k++ )
{
const Qgis::MetadataDateType type = static_cast< Qgis::MetadataDateType >( dateEnum.value( k ) );
if ( other->mDates.contains( type ) && other->mDates.value( type ).isValid() )
{
mDates.insert( type, other->mDates[type] );
}
}

}

bool QgsAbstractMetadataBase::equals( const QgsAbstractMetadataBase &metadataOther ) const
Expand All @@ -479,7 +539,8 @@ bool QgsAbstractMetadataBase::equals( const QgsAbstractMetadataBase &metadataOth
( mHistory == metadataOther.mHistory ) &&
( mKeywords == metadataOther.mKeywords ) &&
( mContacts == metadataOther.mContacts ) &&
( mLinks == metadataOther.mLinks ) );
( mLinks == metadataOther.mLinks ) &&
( mDates == metadataOther.mDates ) );
}


Expand Down
20 changes: 20 additions & 0 deletions src/core/metadata/qgsabstractmetadatabase.h
Expand Up @@ -20,6 +20,7 @@

#include "qgis_sip.h"
#include "qgis_core.h"
#include "qgis.h"
#include <QMap>
#include <QString>
#include <QMetaType>
Expand Down Expand Up @@ -502,6 +503,22 @@ class CORE_EXPORT QgsAbstractMetadataBase
*/
void addLink( const QgsAbstractMetadataBase::Link &link );

/**
* Returns the date for the specified date \a type.
*
* \see setDateTime()
* \since QGIS 3.30
*/
QDateTime dateTime( Qgis::MetadataDateType type ) const;

/**
* Sets a date value for the specified date \a type.
*
* \see dateTime()
* \since QGIS 3.30
*/
void setDateTime( Qgis::MetadataDateType type, QDateTime date );

/**
* Sets state from DOM document.
*
Expand Down Expand Up @@ -572,6 +589,9 @@ class CORE_EXPORT QgsAbstractMetadataBase

QgsAbstractMetadataBase::LinkList mLinks;

//! Metadata dates
QMap< Qgis::MetadataDateType, QDateTime > mDates;

/*
* IMPORTANT!!!!!!
*
Expand Down
22 changes: 11 additions & 11 deletions src/core/metadata/qgsprojectmetadata.cpp
Expand Up @@ -29,9 +29,13 @@ bool QgsProjectMetadata::readMetadataXml( const QDomElement &metadataElement )
mnl = metadataElement.namedItem( QStringLiteral( "author" ) );
mAuthor = mnl.toElement().text();

// creation datetime
mnl = metadataElement.namedItem( QStringLiteral( "creation" ) );
mCreationDateTime = QDateTime::fromString( mnl.toElement().text(), Qt::ISODate );
if ( !mDates.contains( Qgis::MetadataDateType::Created ) )
{
// creation datetime -- old format
mnl = metadataElement.namedItem( QStringLiteral( "creation" ) );
const QDateTime creationDateTime = QDateTime::fromString( mnl.toElement().text(), Qt::ISODate );
mDates.insert( Qgis::MetadataDateType::Created, creationDateTime );
}

return true;
}
Expand All @@ -48,7 +52,7 @@ bool QgsProjectMetadata::writeMetadataXml( QDomElement &metadataElement, QDomDoc

// creation datetime
QDomElement creation = document.createElement( QStringLiteral( "creation" ) );
const QDomText creationText = document.createTextNode( mCreationDateTime.toString( Qt::ISODate ) );
const QDomText creationText = document.createTextNode( mDates.value( Qgis::MetadataDateType::Created ).toString( Qt::ISODate ) );
creation.appendChild( creationText );
metadataElement.appendChild( creation );

Expand All @@ -63,17 +67,13 @@ void QgsProjectMetadata::combine( const QgsAbstractMetadataBase *other )
{
if ( !otherProjectMetadata->author().isEmpty() )
mAuthor = otherProjectMetadata->author();

if ( otherProjectMetadata->creationDateTime().isValid() )
mCreationDateTime = otherProjectMetadata->creationDateTime();
}
}

bool QgsProjectMetadata::operator==( const QgsProjectMetadata &metadataOther ) const
{
return equals( metadataOther ) &&
mAuthor == metadataOther.mAuthor &&
mCreationDateTime == metadataOther.mCreationDateTime ;
mAuthor == metadataOther.mAuthor;
}

QgsProjectMetadata *QgsProjectMetadata::clone() const
Expand All @@ -93,10 +93,10 @@ void QgsProjectMetadata::setAuthor( const QString &author )

QDateTime QgsProjectMetadata::creationDateTime() const
{
return mCreationDateTime;
return mDates.value( Qgis::MetadataDateType::Created );
}

void QgsProjectMetadata::setCreationDateTime( const QDateTime &creationDateTime )
{
mCreationDateTime = creationDateTime;
mDates[ Qgis::MetadataDateType::Created ] = creationDateTime;
}
2 changes: 0 additions & 2 deletions src/core/metadata/qgsprojectmetadata.h
Expand Up @@ -103,8 +103,6 @@ class CORE_EXPORT QgsProjectMetadata : public QgsAbstractMetadataBase

QString mAuthor;

QDateTime mCreationDateTime;

/*
* IMPORTANT!!!!!!
*
Expand Down
14 changes: 14 additions & 0 deletions src/core/qgis.h
Expand Up @@ -2613,6 +2613,20 @@ class CORE_EXPORT Qgis
};
Q_ENUM( AttributeActionType )

/**
* Date types for metadata.
*
* \since QGIS 3.30
*/
enum class MetadataDateType
{
Created, //!< Date created
Published, //!< Date published
Revised, //!< Date revised
Superseded, //!< Date superseded
};
Q_ENUM( MetadataDateType )

/**
* Identify search radius in mm
* \since QGIS 2.3
Expand Down

0 comments on commit 6b65b42

Please sign in to comment.