Add new QgsProjectMetadata metadata class

For storing QgsProject metadata. Contains all metadata items
from QgsMetadataBase, plus adds author and creation datetime
metadata items.
This commit is contained in:
Nyall Dawson 2018-03-19 13:21:28 +10:00
parent 1e05de049a
commit 09aca080ec
12 changed files with 996 additions and 8 deletions

View File

@ -173,6 +173,7 @@
%Include metadata/qgslayermetadatavalidator.sip
%Include metadata/qgslayermetadataformatter.sip
%Include metadata/qgsmetadatabase.sip
%Include metadata/qgsprojectmetadata.sip
%Include processing/qgsprocessing.sip
%Include processing/qgsprocessingalgorithm.sip
%Include processing/qgsprocessingcontext.sip

View File

@ -133,8 +133,6 @@ Constructor for Constraint.
Constructor for QgsLayerMetadata.
%End
virtual ~QgsLayerMetadata();
QString fees() const;
%Docstring
Returns any fees associated with using the resource.

View File

@ -58,7 +58,7 @@ class QgsNativeMetadataBaseValidator : QgsMetadataValidator
%Docstring
A validator for the native base QGIS metadata schema definition.
.. versionadded:: 3.20
.. versionadded:: 3.2
%End
%TypeHeaderCode
@ -81,7 +81,7 @@ Constructor for QgsNativeMetadataBaseValidator.
class QgsNativeMetadataValidator : QgsNativeMetadataBaseValidator
{
%Docstring
A validator for the native QGIS metadata schema definition.
A validator for the native QGIS layer metadata schema definition.
.. versionadded:: 3.0
%End
@ -99,6 +99,30 @@ Constructor for QgsNativeMetadataValidator.
virtual bool validate( const QgsMetadataBase *metadata, QList< QgsMetadataValidator::ValidationResult > &results /Out/ ) const;
};
class QgsNativeProjectMetadataValidator : QgsNativeMetadataBaseValidator
{
%Docstring
A validator for the native QGIS project metadata schema definition.
.. versionadded:: 3.2
%End
%TypeHeaderCode
#include "qgslayermetadatavalidator.h"
%End
public:
QgsNativeProjectMetadataValidator();
%Docstring
Constructor for QgsNativeProjectMetadataValidator.
%End
virtual bool validate( const QgsMetadataBase *metadata, QList< QgsMetadataValidator::ValidationResult > &results /Out/ ) const;
};
/************************************************************************

View File

@ -0,0 +1,107 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/metadata/qgsprojectmetadata.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsProjectMetadata : QgsMetadataBase
{
%Docstring
A structured metadata store for a map layer.
QgsProjectMetadata handles storage and management of the metadata
for a QgsProject. This class is an internal QGIS format with a common
metadata structure, which allows for code to access the metadata properties for
projects in a uniform way.
The metadata store is designed to be compatible with the Dublin Core metadata
specifications, and will be expanded to allow compatibility with ISO specifications
in future releases. However, the QGIS internal schema does not represent a superset
of all existing metadata schemas and accordingly conversion from specific
metadata formats to QgsProjectMetadata may result in a loss of information.
This class is designed to follow the specifications detailed in
the schema definition available at resources/qgis-resource-metadata.xsd
within the QGIS source code.
Metadata can be validated through the use of QgsLayerMetadataValidator
subclasses. E.g. validating against the native QGIS metadata schema can be performed
using QgsNativeProjectMetadataValidator.
.. versionadded:: 3.2
%End
%TypeHeaderCode
#include "qgsprojectmetadata.h"
%End
public:
QgsProjectMetadata();
%Docstring
Constructor for QgsProjectMetadata.
%End
QString author() const;
%Docstring
Returns the project author string.
.. seealso:: :py:func:`setAuthor`
%End
void setAuthor( const QString &author );
%Docstring
Sets the project ``author`` string
.. seealso:: :py:func:`author`
%End
QDateTime creationDateTime() const;
%Docstring
Returns the project's creation date/timestamp.
.. seealso:: :py:func:`setCreationDateTime`
%End
void setCreationDateTime( const QDateTime &creationDateTime );
%Docstring
Sets the project's creation date/timestamp.
.. seealso:: :py:func:`creationDateTime`
%End
bool readMetadataXml( const QDomElement &metadataElement );
%Docstring
Sets state from DOM document
:param metadataElement: The Dom element corresponding to ``resourceMetadata'' tag
:return: true if successful
%End
bool writeMetadataXml( QDomElement &metadataElement, QDomDocument &document ) const;
%Docstring
Stores state in DOM node
:param metadataElement: is a Dom element corresponding to ``resourceMetadata'' tag
:param document: is a the dom document being written
:return: true if successful
%End
bool operator==( const QgsProjectMetadata &metadataOther ) const;
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/metadata/qgsprojectmetadata.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -76,6 +76,7 @@ SET(QGIS_CORE_SRCS
metadata/qgslayermetadatavalidator.cpp
metadata/qgslayermetadataformatter.cpp
metadata/qgsmetadatabase.cpp
metadata/qgsprojectmetadata.cpp
auth/qgsauthcertutils.cpp
auth/qgsauthconfig.cpp
@ -993,6 +994,7 @@ SET(QGIS_CORE_HDRS
metadata/qgslayermetadatavalidator.h
metadata/qgslayermetadataformatter.h
metadata/qgsmetadatabase.h
metadata/qgsprojectmetadata.h
processing/qgsprocessing.h
processing/qgsprocessingalgorithm.h

View File

@ -217,8 +217,6 @@ class CORE_EXPORT QgsLayerMetadata : public QgsMetadataBase
*/
QgsLayerMetadata() = default;
virtual ~QgsLayerMetadata() = default;
/**
* Returns any fees associated with using the resource.
* An empty string will be returned if no fees are set.

View File

@ -17,7 +17,11 @@
#include "qgslayermetadatavalidator.h"
#include "qgslayermetadata.h"
#include "qgsprojectmetadata.h"
//
// QgsNativeMetadataBaseValidator
//
bool QgsNativeMetadataBaseValidator::validate( const QgsMetadataBase *metadata, QList<QgsMetadataValidator::ValidationResult> &results ) const
{
@ -125,6 +129,10 @@ bool QgsNativeMetadataBaseValidator::validate( const QgsMetadataBase *metadata,
return result;
}
//
// QgsNativeMetadataValidator
//
bool QgsNativeMetadataValidator::validate( const QgsMetadataBase *baseMetadata, QList<ValidationResult> &results ) const
{
results.clear();
@ -169,3 +177,34 @@ bool QgsNativeMetadataValidator::validate( const QgsMetadataBase *baseMetadata,
return result;
}
//
// QgsNativeProjectMetadataValidator
//
bool QgsNativeProjectMetadataValidator::validate( const QgsMetadataBase *baseMetadata, QList<QgsMetadataValidator::ValidationResult> &results ) const
{
results.clear();
const QgsProjectMetadata *metadata = dynamic_cast< const QgsProjectMetadata * >( baseMetadata );
if ( !metadata )
return false;
bool result = true;
if ( !QgsNativeMetadataBaseValidator::validate( metadata, results ) )
result = false;
if ( metadata->author().isEmpty() )
{
result = false;
results << ValidationResult( QObject::tr( "author" ), QObject::tr( "A project author is required." ) );
}
if ( !metadata->creationDateTime().isValid() )
{
result = false;
results << ValidationResult( QObject::tr( "creation" ), QObject::tr( "The project creation date/time is required." ) );
}
return result;
}

View File

@ -84,7 +84,7 @@ class CORE_EXPORT QgsMetadataValidator
* \ingroup core
* \class QgsNativeMetadataBaseValidator
* \brief A validator for the native base QGIS metadata schema definition.
* \since QGIS 3.20
* \since QGIS 3.2
*/
class CORE_EXPORT QgsNativeMetadataBaseValidator : public QgsMetadataValidator
@ -105,7 +105,7 @@ class CORE_EXPORT QgsNativeMetadataBaseValidator : public QgsMetadataValidator
/**
* \ingroup core
* \class QgsNativeMetadataValidator
* \brief A validator for the native QGIS metadata schema definition.
* \brief A validator for the native QGIS layer metadata schema definition.
* \since QGIS 3.0
*/
@ -123,4 +123,25 @@ class CORE_EXPORT QgsNativeMetadataValidator : public QgsNativeMetadataBaseValid
};
/**
* \ingroup core
* \class QgsNativeProjectMetadataValidator
* \brief A validator for the native QGIS project metadata schema definition.
* \since QGIS 3.2
*/
class CORE_EXPORT QgsNativeProjectMetadataValidator : public QgsNativeMetadataBaseValidator
{
public:
/**
* Constructor for QgsNativeProjectMetadataValidator.
*/
QgsNativeProjectMetadataValidator() = default;
bool validate( const QgsMetadataBase *metadata, QList< QgsMetadataValidator::ValidationResult > &results SIP_OUT ) const override;
};
#endif // QGSLAYERMETADATAVALIDATOR_H

View File

@ -0,0 +1,337 @@
/***************************************************************************
qgsprojectmetadata.cpp
--------------------
begin : March 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsprojectmetadata.h"
bool QgsProjectMetadata::readMetadataXml( const QDomElement &metadataElement )
{
QDomNode mnl;
QDomElement mne;
// set identifier
mnl = metadataElement.namedItem( QStringLiteral( "identifier" ) );
mIdentifier = mnl.toElement().text();
// set parent identifier
mnl = metadataElement.namedItem( QStringLiteral( "parentidentifier" ) );
mParentIdentifier = mnl.toElement().text();
// set language
mnl = metadataElement.namedItem( QStringLiteral( "language" ) );
mLanguage = mnl.toElement().text();
// set type
mnl = metadataElement.namedItem( QStringLiteral( "type" ) );
mType = mnl.toElement().text();
// set title
mnl = metadataElement.namedItem( QStringLiteral( "title" ) );
mTitle = mnl.toElement().text();
// set abstract
mnl = metadataElement.namedItem( QStringLiteral( "abstract" ) );
mAbstract = mnl.toElement().text();
// set keywords
QDomNodeList keywords = metadataElement.elementsByTagName( QStringLiteral( "keywords" ) );
mKeywords.clear();
for ( int i = 0; i < keywords.size(); i++ )
{
QStringList keywordsList;
mnl = keywords.at( i );
mne = mnl.toElement();
QDomNodeList el = mne.elementsByTagName( QStringLiteral( "keyword" ) );
for ( int j = 0; j < el.size(); j++ )
{
keywordsList.append( el.at( j ).toElement().text() );
}
addKeywords( mne.attribute( QStringLiteral( "vocabulary" ) ), keywordsList );
}
// contact
QDomNodeList contactsList = metadataElement.elementsByTagName( QStringLiteral( "contact" ) );
mContacts.clear();
for ( int i = 0; i < contactsList.size(); i++ )
{
mnl = contactsList.at( i );
mne = mnl.toElement();
QgsMetadataBase::Contact oneContact;
oneContact.name = mne.namedItem( QStringLiteral( "name" ) ).toElement().text();
oneContact.organization = mne.namedItem( QStringLiteral( "organization" ) ).toElement().text();
oneContact.position = mne.namedItem( QStringLiteral( "position" ) ).toElement().text();
oneContact.voice = mne.namedItem( QStringLiteral( "voice" ) ).toElement().text();
oneContact.fax = mne.namedItem( QStringLiteral( "fax" ) ).toElement().text();
oneContact.email = mne.namedItem( QStringLiteral( "email" ) ).toElement().text();
oneContact.role = mne.namedItem( QStringLiteral( "role" ) ).toElement().text();
QList< QgsMetadataBase::Address > addresses;
QDomNodeList addressList = mne.elementsByTagName( QStringLiteral( "contactAddress" ) );
for ( int j = 0; j < addressList.size(); j++ )
{
QDomElement addressElement = addressList.at( j ).toElement();
QgsMetadataBase::Address oneAddress;
oneAddress.address = addressElement.namedItem( QStringLiteral( "address" ) ).toElement().text();
oneAddress.administrativeArea = addressElement.namedItem( QStringLiteral( "administrativearea" ) ).toElement().text();
oneAddress.city = addressElement.namedItem( QStringLiteral( "city" ) ).toElement().text();
oneAddress.country = addressElement.namedItem( QStringLiteral( "country" ) ).toElement().text();
oneAddress.postalCode = addressElement.namedItem( QStringLiteral( "postalcode" ) ).toElement().text();
oneAddress.type = addressElement.namedItem( QStringLiteral( "type" ) ).toElement().text();
addresses << oneAddress;
}
oneContact.addresses = addresses;
QgsMetadataBase::addContact( oneContact );
}
// links
mnl = metadataElement.namedItem( QStringLiteral( "links" ) );
mne = mnl.toElement();
mLinks.clear();
QDomNodeList el = mne.elementsByTagName( QStringLiteral( "link" ) );
for ( int i = 0; i < el.size(); i++ )
{
mne = el.at( i ).toElement();
QgsMetadataBase::Link oneLink;
oneLink.name = mne.attribute( QStringLiteral( "name" ) );
oneLink.type = mne.attribute( QStringLiteral( "type" ) );
oneLink.url = mne.attribute( QStringLiteral( "url" ) );
oneLink.description = mne.attribute( QStringLiteral( "description" ) );
oneLink.format = mne.attribute( QStringLiteral( "format" ) );
oneLink.mimeType = mne.attribute( QStringLiteral( "mimeType" ) );
oneLink.size = mne.attribute( QStringLiteral( "size" ) );
QgsMetadataBase::addLink( oneLink );
}
// history
QDomNodeList historyNodeList = metadataElement.elementsByTagName( QStringLiteral( "history" ) );
QStringList historyList;
for ( int i = 0; i < historyNodeList.size(); i++ )
{
mnl = historyNodeList.at( i );
mne = mnl.toElement();
historyList.append( mne.text() );
}
setHistory( historyList );
// set author
mnl = metadataElement.namedItem( QStringLiteral( "author" ) );
mAuthor = mnl.toElement().text();
// creation datetime
mnl = metadataElement.namedItem( QStringLiteral( "creation" ) );
mCreationDateTime = QDateTime::fromString( mnl.toElement().text(), Qt::ISODate );
return true;
}
bool QgsProjectMetadata::writeMetadataXml( QDomElement &metadataElement, QDomDocument &document ) const
{
// identifier
QDomElement identifier = document.createElement( QStringLiteral( "identifier" ) );
QDomText identifierText = document.createTextNode( mIdentifier );
identifier.appendChild( identifierText );
metadataElement.appendChild( identifier );
// parent identifier
QDomElement parentIdentifier = document.createElement( QStringLiteral( "parentidentifier" ) );
QDomText parentIdentifierText = document.createTextNode( mParentIdentifier );
parentIdentifier.appendChild( parentIdentifierText );
metadataElement.appendChild( parentIdentifier );
// language
QDomElement language = document.createElement( QStringLiteral( "language" ) );
QDomText languageText = document.createTextNode( mLanguage );
language.appendChild( languageText );
metadataElement.appendChild( language );
// type
QDomElement type = document.createElement( QStringLiteral( "type" ) );
QDomText typeText = document.createTextNode( mType );
type.appendChild( typeText );
metadataElement.appendChild( type );
// title
QDomElement title = document.createElement( QStringLiteral( "title" ) );
QDomText titleText = document.createTextNode( mTitle );
title.appendChild( titleText );
metadataElement.appendChild( title );
// abstract
QDomElement abstract = document.createElement( QStringLiteral( "abstract" ) );
QDomText abstractText = document.createTextNode( mAbstract );
abstract.appendChild( abstractText );
metadataElement.appendChild( abstract );
// keywords
QMapIterator<QString, QStringList> i( mKeywords );
while ( i.hasNext() )
{
i.next();
QDomElement keywordsElement = document.createElement( QStringLiteral( "keywords" ) );
keywordsElement.setAttribute( QStringLiteral( "vocabulary" ), i.key() );
const QStringList values = i.value();
for ( const QString &kw : values )
{
QDomElement keyword = document.createElement( QStringLiteral( "keyword" ) );
QDomText keywordText = document.createTextNode( kw );
keyword.appendChild( keywordText );
keywordsElement.appendChild( keyword );
}
metadataElement.appendChild( keywordsElement );
}
// contact
for ( const QgsMetadataBase::Contact &contact : mContacts )
{
QDomElement contactElement = document.createElement( QStringLiteral( "contact" ) );
QDomElement nameElement = document.createElement( QStringLiteral( "name" ) );
QDomElement organizationElement = document.createElement( QStringLiteral( "organization" ) );
QDomElement positionElement = document.createElement( QStringLiteral( "position" ) );
QDomElement voiceElement = document.createElement( QStringLiteral( "voice" ) );
QDomElement faxElement = document.createElement( QStringLiteral( "fax" ) );
QDomElement emailElement = document.createElement( QStringLiteral( "email" ) );
QDomElement roleElement = document.createElement( QStringLiteral( "role" ) );
QDomText nameText = document.createTextNode( contact.name );
QDomText orgaText = document.createTextNode( contact.organization );
QDomText positionText = document.createTextNode( contact.position );
QDomText voiceText = document.createTextNode( contact.voice );
QDomText faxText = document.createTextNode( contact.fax );
QDomText emailText = document.createTextNode( contact.email );
QDomText roleText = document.createTextNode( contact.role );
for ( const QgsMetadataBase::Address &oneAddress : contact.addresses )
{
QDomElement addressElement = document.createElement( QStringLiteral( "contactAddress" ) );
QDomElement typeElement = document.createElement( QStringLiteral( "type" ) );
QDomElement addressDetailedElement = document.createElement( QStringLiteral( "address" ) );
QDomElement cityElement = document.createElement( QStringLiteral( "city" ) );
QDomElement administrativeAreaElement = document.createElement( QStringLiteral( "administrativearea" ) );
QDomElement postalCodeElement = document.createElement( QStringLiteral( "postalcode" ) );
QDomElement countryElement = document.createElement( QStringLiteral( "country" ) );
typeElement.appendChild( document.createTextNode( oneAddress.type ) );
addressDetailedElement.appendChild( document.createTextNode( oneAddress.address ) );
cityElement.appendChild( document.createTextNode( oneAddress.city ) );
administrativeAreaElement.appendChild( document.createTextNode( oneAddress.administrativeArea ) );
postalCodeElement.appendChild( document.createTextNode( oneAddress.postalCode ) );
countryElement.appendChild( document.createTextNode( oneAddress.country ) );
addressElement.appendChild( typeElement );
addressElement.appendChild( addressDetailedElement );
addressElement.appendChild( cityElement );
addressElement.appendChild( administrativeAreaElement );
addressElement.appendChild( postalCodeElement );
addressElement.appendChild( countryElement );
contactElement.appendChild( addressElement );
}
nameElement.appendChild( nameText );
organizationElement.appendChild( orgaText );
positionElement.appendChild( positionText );
voiceElement.appendChild( voiceText );
faxElement.appendChild( faxText );
emailElement.appendChild( emailText );
roleElement.appendChild( roleText );
contactElement.appendChild( nameElement );
contactElement.appendChild( organizationElement );
contactElement.appendChild( positionElement );
contactElement.appendChild( voiceElement );
contactElement.appendChild( faxElement );
contactElement.appendChild( emailElement );
contactElement.appendChild( roleElement );
metadataElement.appendChild( contactElement );
}
// links
QDomElement links = document.createElement( QStringLiteral( "links" ) );
for ( const QgsMetadataBase::Link &link : mLinks )
{
QDomElement linkElement = document.createElement( QStringLiteral( "link" ) );
linkElement.setAttribute( QStringLiteral( "name" ), link.name );
linkElement.setAttribute( QStringLiteral( "type" ), link.type );
linkElement.setAttribute( QStringLiteral( "url" ), link.url );
linkElement.setAttribute( QStringLiteral( "description" ), link.description );
linkElement.setAttribute( QStringLiteral( "format" ), link.format );
linkElement.setAttribute( QStringLiteral( "mimeType" ), link.mimeType );
linkElement.setAttribute( QStringLiteral( "size" ), link.size );
links.appendChild( linkElement );
}
metadataElement.appendChild( links );
// history
for ( const QString &history : mHistory )
{
QDomElement historyElement = document.createElement( QStringLiteral( "history" ) );
QDomText historyText = document.createTextNode( history );
historyElement.appendChild( historyText );
metadataElement.appendChild( historyElement );
}
// author
QDomElement author = document.createElement( QStringLiteral( "author" ) );
QDomText authorText = document.createTextNode( mAuthor );
author.appendChild( authorText );
metadataElement.appendChild( author );
// creation datetime
QDomElement creation = document.createElement( QStringLiteral( "creation" ) );
QDomText creationText = document.createTextNode( mCreationDateTime.toString( Qt::ISODate ) );
creation.appendChild( creationText );
metadataElement.appendChild( creation );
return true;
}
bool QgsProjectMetadata::operator==( const QgsProjectMetadata &metadataOther ) const
{
return ( ( mIdentifier == metadataOther.mIdentifier ) &&
( mParentIdentifier == metadataOther.mParentIdentifier ) &&
( mLanguage == metadataOther.mLanguage ) &&
( mType == metadataOther.mType ) &&
( mTitle == metadataOther.mTitle ) &&
( mAbstract == metadataOther.mAbstract ) &&
( mAuthor == metadataOther.mAuthor ) &&
( mCreationDateTime == metadataOther.mCreationDateTime ) &&
( mHistory == metadataOther.mHistory ) &&
( mKeywords == metadataOther.mKeywords ) &&
( mContacts == metadataOther.mContacts ) &&
( mLinks == metadataOther.mLinks ) );
}
QString QgsProjectMetadata::author() const
{
return mAuthor;
}
void QgsProjectMetadata::setAuthor( const QString &author )
{
mAuthor = author;
}
QDateTime QgsProjectMetadata::creationDateTime() const
{
return mCreationDateTime;
}
void QgsProjectMetadata::setCreationDateTime( const QDateTime &creationDateTime )
{
mCreationDateTime = creationDateTime;
}

View File

@ -0,0 +1,128 @@
/***************************************************************************
qgsprojectmetadata.h
-------------------
begin : March 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPROJECTMETADATA_H
#define QGSPROJECTMETADATA_H
#include "qgis.h"
#include "qgis_core.h"
#include "qgsmetadatabase.h"
/**
* \ingroup core
* \class QgsProjectMetadata
* \brief A structured metadata store for a map layer.
*
* QgsProjectMetadata handles storage and management of the metadata
* for a QgsProject. This class is an internal QGIS format with a common
* metadata structure, which allows for code to access the metadata properties for
* projects in a uniform way.
*
* The metadata store is designed to be compatible with the Dublin Core metadata
* specifications, and will be expanded to allow compatibility with ISO specifications
* in future releases. However, the QGIS internal schema does not represent a superset
* of all existing metadata schemas and accordingly conversion from specific
* metadata formats to QgsProjectMetadata may result in a loss of information.
*
* This class is designed to follow the specifications detailed in
* the schema definition available at resources/qgis-resource-metadata.xsd
* within the QGIS source code.
*
* Metadata can be validated through the use of QgsLayerMetadataValidator
* subclasses. E.g. validating against the native QGIS metadata schema can be performed
* using QgsNativeProjectMetadataValidator.
*
* \since QGIS 3.2
*/
class CORE_EXPORT QgsProjectMetadata : public QgsMetadataBase
{
public:
/**
* Constructor for QgsProjectMetadata.
*/
QgsProjectMetadata() = default;
/**
* Returns the project author string.
* \see setAuthor()
*/
QString author() const;
/**
* Sets the project \a author string
* \see author()
*/
void setAuthor( const QString &author );
/**
* Returns the project's creation date/timestamp.
* \see setCreationDateTime()
*/
QDateTime creationDateTime() const;
/**
* Sets the project's creation date/timestamp.
* \see creationDateTime()
*/
void setCreationDateTime( const QDateTime &creationDateTime );
/**
* Sets state from DOM document
* \param metadataElement The Dom element corresponding to ``resourceMetadata'' tag
*
* \returns true if successful
*/
bool readMetadataXml( const QDomElement &metadataElement );
/**
* Stores state in DOM node
* \param metadataElement is a Dom element corresponding to ``resourceMetadata'' tag
* \param document is a the dom document being written
*
* \returns true if successful
*/
bool writeMetadataXml( QDomElement &metadataElement, QDomDocument &document ) const;
bool operator==( const QgsProjectMetadata &metadataOther ) const;
private:
/*
* IMPORTANT!!!!!!
*
* Do NOT add anything to this class without also updating the schema
* definition located at resources/qgis-resource-metadata.xsd
*
*/
QString mAuthor;
QDateTime mCreationDateTime;
/*
* IMPORTANT!!!!!!
*
* Do NOT add anything to this class without also updating the schema
* definition located at resources/qgis-resource-metadata.xsd
*
*/
};
#endif // QGSPROJECTMETADATA_H

View File

@ -132,6 +132,7 @@ ADD_PYTHON_TEST(PyQgsPointClusterRenderer test_qgspointclusterrenderer.py)
ADD_PYTHON_TEST(PyQgsPointDisplacementRenderer test_qgspointdisplacementrenderer.py)
ADD_PYTHON_TEST(PyQgsPostgresDomain test_qgspostgresdomain.py)
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidgets.py)
ADD_PYTHON_TEST(PyQgsProjectMetadata test_qgsprojectmetadata.py)
ADD_PYTHON_TEST(PyQgsRange test_qgsrange.py)
ADD_PYTHON_TEST(PyQgsRangeWidgets test_qgsrangewidgets.py)
ADD_PYTHON_TEST(PyQgsRasterBandComboBox test_qgsrasterbandcombobox.py)

View File

@ -0,0 +1,332 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsProjectMetadata.
Run with: ctest -V -R PyQgsProjectMetadata
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '19/03/2018'
__copyright__ = 'Copyright 2018, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.PyQt.QtXml import QDomDocument
from qgis.core import (QgsProjectMetadata,
QgsMetadataBase,
QgsNativeProjectMetadataValidator)
from qgis.PyQt.QtCore import (QDate,
QTime,
QDateTime)
from qgis.testing import start_app, unittest
start_app()
class TestQgsProjectMetadata(unittest.TestCase):
def testGettersSetters(self):
m = QgsProjectMetadata()
m.setIdentifier('identifier')
self.assertEqual(m.identifier(), 'identifier')
m.setParentIdentifier('parent identifier')
self.assertEqual(m.parentIdentifier(), 'parent identifier')
m.setLanguage('en-us')
self.assertEqual(m.language(), 'en-us')
m.setType('type')
self.assertEqual(m.type(), 'type')
m.setTitle('title')
self.assertEqual(m.title(), 'title')
m.setCategories(['category'])
self.assertEqual(m.categories(), ['category'])
m.setAbstract('abstract')
self.assertEqual(m.abstract(), 'abstract')
m.setHistory(['loaded into QGIS'])
self.assertEqual(m.history(), ['loaded into QGIS'])
m.setHistory(['accidentally deleted some features'])
self.assertEqual(m.history(), ['accidentally deleted some features'])
m.addHistoryItem('panicked and deleted more')
self.assertEqual(m.history(), ['accidentally deleted some features', 'panicked and deleted more'])
m.setAuthor('my author')
self.assertEqual(m.author(), 'my author')
m.setCreationDateTime(QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)))
self.assertEqual(m.creationDateTime(), QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)))
def createTestMetadata(self):
"""
Returns a standard metadata which can be tested with checkExpectedMetadata
"""
m = QgsProjectMetadata()
m.setIdentifier('1234')
m.setParentIdentifier('xyz')
m.setLanguage('en-CA')
m.setType('project')
m.setTitle('roads')
m.setAbstract('my roads')
m.setHistory(['history a', 'history b'])
m.setKeywords({
'GEMET': ['kw1', 'kw2'],
'gmd:topicCategory': ['natural'],
})
c = QgsMetadataBase.Contact()
c.name = 'John Smith'
c.organization = 'ACME'
c.position = 'staff'
c.voice = '1500 515 555'
c.fax = 'xx.xxx.xxx.xxxx'
c.email = 'foo@example.org'
c.role = 'pointOfContact'
address = QgsMetadataBase.Address()
address.type = 'postal'
address.address = '123 Main Street'
address.city = 'anycity'
address.administrativeArea = 'anyprovince'
address.postalCode = '90210'
address.country = 'Canada'
c.addresses = [address]
m.setContacts([c])
l = QgsMetadataBase.Link()
l.name = 'geonode:roads'
l.type = 'OGC:WMS'
l.description = 'my GeoNode road layer'
l.url = 'http://example.org/wms'
l2 = QgsMetadataBase.Link()
l2.name = 'geonode:roads'
l2.type = 'OGC:WFS'
l2.description = 'my GeoNode road layer'
l2.url = 'http://example.org/wfs'
l3 = QgsMetadataBase.Link()
l3.name = 'roads'
l3.type = 'WWW:LINK'
l3.description = 'full dataset download'
l3.url = 'http://example.org/roads.tgz'
l3.format = 'ESRI Shapefile'
l3.mimeType = 'application/gzip'
l3.size = '283676'
m.setLinks([l, l2, l3])
m.setAuthor('my author')
m.setCreationDateTime(QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)))
return m
def testEquality(self):
md = self.createTestMetadata()
md2 = self.createTestMetadata()
self.assertEqual(md, md2)
md2.setAuthor('xx')
self.assertNotEqual(md, md2)
md2 = self.createTestMetadata()
md2.setCreationDateTime(QDateTime(QDate(2003, 12, 17), QTime(9, 30, 47)))
self.assertNotEqual(md, md2)
def checkExpectedMetadata(self, m):
"""
Checks that a metadata object matches that returned by createTestMetadata
"""
self.assertEqual(m.identifier(), '1234')
self.assertEqual(m.parentIdentifier(), 'xyz')
self.assertEqual(m.language(), 'en-CA')
self.assertEqual(m.type(), 'project')
self.assertEqual(m.title(), 'roads')
self.assertEqual(m.abstract(), 'my roads')
self.assertEqual(m.history(), ['history a', 'history b'])
self.assertEqual(
m.keywords(),
{'GEMET': ['kw1', 'kw2'], 'gmd:topicCategory': ['natural']})
self.assertEqual(m.contacts()[0].name, 'John Smith')
self.assertEqual(m.contacts()[0].organization, 'ACME')
self.assertEqual(m.contacts()[0].position, 'staff')
self.assertEqual(m.contacts()[0].voice, '1500 515 555')
self.assertEqual(m.contacts()[0].fax, 'xx.xxx.xxx.xxxx')
self.assertEqual(m.contacts()[0].email, 'foo@example.org')
self.assertEqual(m.contacts()[0].role, 'pointOfContact')
self.assertEqual(m.contacts()[0].addresses[0].type, 'postal')
self.assertEqual(m.contacts()[0].addresses[0].address, '123 Main Street')
self.assertEqual(m.contacts()[0].addresses[0].city, 'anycity')
self.assertEqual(m.contacts()[0].addresses[0].administrativeArea, 'anyprovince')
self.assertEqual(m.contacts()[0].addresses[0].postalCode, '90210')
self.assertEqual(m.contacts()[0].addresses[0].country, 'Canada')
self.assertEqual(m.links()[0].name, 'geonode:roads')
self.assertEqual(m.links()[0].type, 'OGC:WMS')
self.assertEqual(m.links()[0].description, 'my GeoNode road layer')
self.assertEqual(m.links()[0].url, 'http://example.org/wms')
self.assertEqual(m.links()[1].name, 'geonode:roads')
self.assertEqual(m.links()[1].type, 'OGC:WFS')
self.assertEqual(m.links()[1].description, 'my GeoNode road layer')
self.assertEqual(m.links()[1].url, 'http://example.org/wfs')
self.assertEqual(m.links()[2].name, 'roads')
self.assertEqual(m.links()[2].type, 'WWW:LINK')
self.assertEqual(m.links()[2].description, 'full dataset download')
self.assertEqual(m.links()[2].url, 'http://example.org/roads.tgz')
self.assertEqual(m.links()[2].format, 'ESRI Shapefile')
self.assertEqual(m.links()[2].mimeType, 'application/gzip')
self.assertEqual(m.links()[2].size, '283676')
self.assertEqual(m.author(), 'my author')
self.assertEqual(m.creationDateTime(), QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)))
def testStandard(self):
m = self.createTestMetadata()
self.checkExpectedMetadata(m)
def testSaveReadFromXml(self):
"""
Test saving and reading metadata from a XML.
"""
# save metadata to XML
m = self.createTestMetadata()
doc = QDomDocument("testdoc")
elem = doc.createElement("metadata")
self.assertTrue(m.writeMetadataXml(elem, doc))
# read back from XML and check result
m2 = QgsProjectMetadata()
m2.readMetadataXml(elem)
self.checkExpectedMetadata(m2)
def testValidateNative(self): # spellok
"""
Test validating metadata against QGIS native schema
"""
m = self.createTestMetadata()
v = QgsNativeProjectMetadataValidator()
res, list = v.validate(m)
self.assertTrue(res)
self.assertFalse(list)
# corrupt metadata piece by piece...
m = self.createTestMetadata()
m.setIdentifier('')
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'identifier')
m = self.createTestMetadata()
m.setLanguage('')
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'language')
m = self.createTestMetadata()
m.setType('')
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'type')
m = self.createTestMetadata()
m.setTitle('')
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'title')
m = self.createTestMetadata()
m.setAbstract('')
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'abstract')
m = self.createTestMetadata()
m.setContacts([])
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'contacts')
m = self.createTestMetadata()
m.setLinks([])
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'links')
m = self.createTestMetadata()
m.setKeywords({'': ['kw1', 'kw2']})
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'keywords')
self.assertEqual(list[0].identifier, 0)
m = self.createTestMetadata()
m.setKeywords({'AA': []})
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'keywords')
self.assertEqual(list[0].identifier, 0)
m = self.createTestMetadata()
c = m.contacts()[0]
c.name = ''
m.setContacts([c])
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'contacts')
self.assertEqual(list[0].identifier, 0)
m = self.createTestMetadata()
l = m.links()[0]
l.name = ''
m.setLinks([l])
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'links')
self.assertEqual(list[0].identifier, 0)
m = self.createTestMetadata()
l = m.links()[0]
l.type = ''
m.setLinks([l])
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'links')
self.assertEqual(list[0].identifier, 0)
m = self.createTestMetadata()
l = m.links()[0]
l.url = ''
m.setLinks([l])
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'links')
self.assertEqual(list[0].identifier, 0)
m = self.createTestMetadata()
m.setAuthor('')
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'author')
m = self.createTestMetadata()
m.setCreationDateTime(QDateTime())
res, list = v.validate(m)
self.assertFalse(res)
self.assertEqual(list[0].section, 'creation')
if __name__ == '__main__':
unittest.main()