Skip to content

Commit 3432bf8

Browse files
Gustrynyalldawson
authored andcommittedJan 7, 2018
load and save metadata to a QMD file
1 parent a343570 commit 3432bf8

12 files changed

+844
-69
lines changed
 

‎python/core/qgsmaplayer.sip

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ This is the base class for all map layer types (vector, raster).
5555
PluginLayer
5656
};
5757

58+
enum PropertyType
59+
{
60+
Style,
61+
Metadata,
62+
};
63+
5864
QgsMapLayer( QgsMapLayer::LayerType type = VectorLayer, const QString &name = QString(), const QString &source = QString() );
5965
%Docstring
6066
Constructor for QgsMapLayer
@@ -80,6 +86,15 @@ is still unique.
8086
QgsMapLayer::LayerType type() const;
8187
%Docstring
8288
Returns the type of the layer.
89+
%End
90+
91+
static QString extensionPropertyType( PropertyType type );
92+
%Docstring
93+
Returns the extension of a Property.
94+
95+
:return: The extension
96+
97+
.. versionadded:: 3.0
8398
%End
8499

85100
QString id() const;
@@ -545,6 +560,118 @@ Sets layer's spatial reference system
545560
%Docstring
546561
A convenience function to capitalize and format a layer ``name``.
547562

563+
.. versionadded:: 3.0
564+
%End
565+
566+
virtual QString metadataUri() const;
567+
%Docstring
568+
Retrieve the metadata URI for this layer
569+
(either as a .qmd file on disk or as a
570+
record in the users style table in their personal qgis.db)
571+
572+
:return: a QString with the metadata file name
573+
574+
.. versionadded:: 3.0
575+
%End
576+
577+
void exportNamedMetadata( QDomDocument &doc, QString &errorMsg ) const;
578+
%Docstring
579+
Export the current metadata of this layer as named metadata in a QDomDocument
580+
581+
:param doc: the target QDomDocument
582+
:param errorMsg: this QString will be initialized on error
583+
584+
.. versionadded:: 3.0
585+
%End
586+
587+
virtual QString saveDefaultMetadata( bool &resultFlag /Out/ );
588+
%Docstring
589+
Save the current metadata of this layer as the default metadata
590+
(either as a .qmd file on disk or as a
591+
record in the users style table in their personal qgis.db)
592+
593+
:param resultFlag: a reference to a flag that will be set to false if
594+
we did not manage to save the default metadata.
595+
596+
:return: a QString with any status messages
597+
598+
.. versionadded:: 3.0
599+
%End
600+
601+
QString saveNamedMetadata( const QString &uri, bool &resultFlag );
602+
%Docstring
603+
Save the current metadata of this layer as a named metadata
604+
(either as a .qmd file on disk or as a
605+
record in the users style table in their personal qgis.db)
606+
607+
:param uri: the file name or other URI for the
608+
metadata file. First an attempt will be made to see if this
609+
is a file and save to that, if that fails the qgis.db metadata
610+
table will be used to create a metadata entry who's
611+
key matches the URI.
612+
:param resultFlag: a reference to a flag that will be set to false if
613+
we did not manage to save the default metadata.
614+
615+
:return: a QString with any status messages
616+
617+
.. versionadded:: 3.0
618+
%End
619+
620+
virtual QString loadNamedMetadata( const QString &uri, bool &resultFlag /Out/ );
621+
%Docstring
622+
Retrieve a named metadata for this layer if one
623+
exists (either as a .qmd file on disk or as a
624+
record in the users style table in their personal qgis.db)
625+
626+
:param uri: - the file name or other URI for the
627+
metadata file. First an attempt will be made to see if this
628+
is a file and load that, if that fails the qgis.db metadata
629+
table will be consulted to see if there is a metadata who's
630+
key matches the URI.
631+
:param resultFlag: a reference to a flag that will be set to false if
632+
we did not manage to load the default metadata.
633+
634+
:return: a QString with any status messages
635+
636+
.. versionadded:: 3.0
637+
%End
638+
639+
QString loadDefaultMetadata( bool &resultFlag );
640+
%Docstring
641+
Retrieve the default metadata for this layer if one
642+
exists (either as a .qmd file on disk or as a
643+
record in the users metadata table in their personal qgis.db)
644+
645+
:param resultFlag: a reference to a flag that will be set to false if
646+
we did not manage to load the default metadata.
647+
648+
:return: a QString with any status messages
649+
650+
.. versionadded:: 3.0
651+
%End
652+
653+
bool loadNamedMetadataFromDatabase( const QString &db, const QString &uri, QString &qmd );
654+
%Docstring
655+
Retrieve a named metadata for this layer from a sqlite database.
656+
657+
:param db: path to sqlite database
658+
:param uri: uri for table
659+
:param qmd: will be set to QMD xml metadata content from database
660+
661+
:return: true if style was successfully loaded
662+
663+
.. versionadded:: 3.0
664+
%End
665+
666+
bool importNamedMetadata( QDomDocument &document, QString &errorMessage );
667+
%Docstring
668+
Import the metadata of this layer from a QDomDocument
669+
670+
:param document: source QDomDocument
671+
:param errorMessage: this QString will be initialized on error
672+
673+
:return: true on success
674+
548675
.. versionadded:: 3.0
549676
%End
550677

‎python/gui/qgsmetadatawidget.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ If the CRS is updated.
4646
void acceptMetadata();
4747
%Docstring
4848
Saves the metadata to the layer.
49+
%End
50+
51+
virtual void setMetadata( const QgsLayerMetadata &metadata );
52+
%Docstring
53+
Sets the layer's ``metadata`` store.
4954
%End
5055

5156
static QMap<QString, QString> parseLanguages();

‎src/app/qgisapp.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4321,6 +4321,7 @@ bool QgisApp::addVectorLayers( const QStringList &layerQStringList, const QStrin
43214321
{
43224322
bool ok;
43234323
l->loadDefaultStyle( ok );
4324+
l->loadDefaultMetadata( ok );
43244325
}
43254326
activateDeactivateLayerRelatedActions( activeLayer() );
43264327

@@ -4747,6 +4748,7 @@ void QgisApp::askUserForOGRSublayers( QgsVectorLayer *layer )
47474748
{
47484749
bool ok;
47494750
l->loadDefaultStyle( ok );
4751+
l->loadDefaultMetadata( ok );
47504752
if ( addToGroup )
47514753
group->addLayer( l );
47524754
}
@@ -4839,6 +4841,7 @@ void QgisApp::addDatabaseLayers( QStringList const &layerPathList, QString const
48394841
{
48404842
bool ok;
48414843
l->loadDefaultStyle( ok );
4844+
l->loadDefaultMetadata( ok );
48424845
}
48434846

48444847
// draw the map
@@ -10249,6 +10252,7 @@ QgsVectorLayer *QgisApp::addVectorLayer( const QString &vectorLayerPath, const Q
1024910252
QgsProject::instance()->addMapLayers( myList );
1025010253
bool ok;
1025110254
layer->loadDefaultStyle( ok );
10255+
layer->loadDefaultMetadata( ok );
1025210256
}
1025310257
}
1025410258
else

‎src/app/qgsrasterlayerproperties.cpp

Lines changed: 121 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,26 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanv
104104

105105
connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsRasterLayerProperties::showHelp );
106106

107-
QPushButton *b = new QPushButton( tr( "Style" ) );
108-
QMenu *m = new QMenu( this );
109-
m->addAction( tr( "Load Style..." ), this, SLOT( loadStyle_clicked() ) );
110-
m->addAction( tr( "Save Style..." ), this, SLOT( saveStyleAs_clicked() ) );
111-
m->addSeparator();
112-
m->addAction( tr( "Save as Default" ), this, SLOT( saveDefaultStyle_clicked() ) );
113-
m->addAction( tr( "Restore Default" ), this, SLOT( loadDefaultStyle_clicked() ) );
114-
b->setMenu( m );
115-
connect( m, &QMenu::aboutToShow, this, &QgsRasterLayerProperties::aboutToShowStyleMenu );
116-
buttonBox->addButton( b, QDialogButtonBox::ResetRole );
107+
mBtnStyle = new QPushButton( tr( "Style" ) );
108+
QMenu *menuStyle = new QMenu( this );
109+
menuStyle->addAction( tr( "Load Style..." ), this, SLOT( loadStyle_clicked() ) );
110+
menuStyle->addAction( tr( "Save Style..." ), this, SLOT( saveStyleAs_clicked() ) );
111+
menuStyle->addSeparator();
112+
menuStyle->addAction( tr( "Save as Default" ), this, SLOT( saveDefaultStyle_clicked() ) );
113+
menuStyle->addAction( tr( "Restore Default" ), this, SLOT( loadDefaultStyle_clicked() ) );
114+
mBtnStyle->setMenu( menuStyle );
115+
connect( menuStyle, &QMenu::aboutToShow, this, &QgsRasterLayerProperties::aboutToShowStyleMenu );
116+
buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
117+
118+
mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
119+
QMenu *menuMetadata = new QMenu( this );
120+
mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata" ), this, SLOT( loadMetadata() ) );
121+
mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata" ), this, SLOT( saveMetadataAs() ) );
122+
menuMetadata->addSeparator();
123+
menuMetadata->addAction( tr( "Save as Default" ), this, SLOT( saveDefaultMetadata() ) );
124+
menuMetadata->addAction( tr( "Restore Default" ), this, SLOT( loadDefaultMetadata() ) );
125+
mBtnMetadata->setMenu( menuMetadata );
126+
buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
117127

118128
connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsRasterLayerProperties::syncToLayer );
119129

@@ -436,6 +446,7 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanv
436446

437447
QString title = QString( tr( "Layer Properties - %1" ) ).arg( lyr->name() );
438448
restoreOptionsBaseUi( title );
449+
optionsStackedWidget_CurrentChanged( mOptionsStackedWidget->currentIndex() );
439450
} // QgsRasterLayerProperties ctor
440451

441452

@@ -1488,6 +1499,10 @@ void QgsRasterLayerProperties::optionsStackedWidget_CurrentChanged( int index )
14881499
{
14891500
QgsOptionsDialogBase::optionsStackedWidget_CurrentChanged( index );
14901501

1502+
bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
1503+
mBtnStyle->setVisible( ! isMetadataPanel );
1504+
mBtnMetadata->setVisible( isMetadataPanel );
1505+
14911506
if ( !mHistogramWidget )
14921507
return;
14931508

@@ -1856,6 +1871,102 @@ void QgsRasterLayerProperties::saveStyleAs_clicked()
18561871
QMessageBox::information( this, tr( "Saved Style" ), message );
18571872
}
18581873

1874+
//
1875+
//
1876+
// Next four methods for saving and restoring QMD metadata
1877+
//
1878+
//
1879+
1880+
void QgsRasterLayerProperties::loadMetadata()
1881+
{
1882+
QgsSettings myQSettings; // where we keep last used filter in persistent state
1883+
QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1884+
1885+
QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer metadata from metadata file" ), myLastUsedDir,
1886+
tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1887+
if ( myFileName.isNull() )
1888+
{
1889+
return;
1890+
}
1891+
1892+
QString myMessage;
1893+
bool defaultLoadedFlag = false;
1894+
myMessage = mRasterLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1895+
1896+
//reset if the default style was loaded OK only
1897+
if ( defaultLoadedFlag )
1898+
{
1899+
mMetadataWidget->setMetadata( mRasterLayer->metadata() );
1900+
}
1901+
else
1902+
{
1903+
//let the user know what went wrong
1904+
QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1905+
}
1906+
1907+
QFileInfo myFI( myFileName );
1908+
QString myPath = myFI.path();
1909+
myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1910+
1911+
activateWindow(); // set focus back to properties dialog
1912+
}
1913+
1914+
void QgsRasterLayerProperties::saveMetadataAs()
1915+
{
1916+
QgsSettings myQSettings; // where we keep last used filter in persistent state
1917+
QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1918+
1919+
QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save layer metadata as QMD" ),
1920+
myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1921+
if ( myOutputFileName.isNull() ) //dialog canceled
1922+
{
1923+
return;
1924+
}
1925+
1926+
mMetadataWidget->acceptMetadata();
1927+
1928+
//ensure the user never omitted the extension from the file name
1929+
if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
1930+
{
1931+
myOutputFileName += QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata );
1932+
}
1933+
1934+
bool defaultLoadedFlag = false;
1935+
QString message = mRasterLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
1936+
if ( defaultLoadedFlag )
1937+
myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( myOutputFileName ).absolutePath() );
1938+
else
1939+
QMessageBox::information( this, tr( "Saved Metadata" ), message );
1940+
}
1941+
1942+
void QgsRasterLayerProperties::saveDefaultMetadata()
1943+
{
1944+
mMetadataWidget->acceptMetadata();
1945+
1946+
bool defaultSavedFlag = false;
1947+
QString errorMsg = mRasterLayer->saveDefaultMetadata( defaultSavedFlag );
1948+
if ( !defaultSavedFlag )
1949+
{
1950+
QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
1951+
}
1952+
}
1953+
1954+
void QgsRasterLayerProperties::loadDefaultMetadata()
1955+
{
1956+
bool defaultLoadedFlag = false;
1957+
QString myMessage = mRasterLayer->loadNamedMetadata( mRasterLayer->metadataUri(), defaultLoadedFlag );
1958+
//reset if the default metadata was loaded OK only
1959+
if ( defaultLoadedFlag )
1960+
{
1961+
mMetadataWidget->setMetadata( mRasterLayer->metadata() );
1962+
}
1963+
else
1964+
{
1965+
QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
1966+
}
1967+
}
1968+
1969+
18591970
void QgsRasterLayerProperties::toggleBuildPyramidsButton()
18601971
{
18611972
if ( lbxPyramidResolutions->selectedItems().empty() )

‎src/app/qgsrasterlayerproperties.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ class APP_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
103103
void loadStyle_clicked();
104104
//! Save a style when appriate button is pressed.
105105
void saveStyleAs_clicked();
106+
107+
//! Load a saved metadata file.
108+
void loadMetadata();
109+
//! Save a metadata.
110+
void saveMetadataAs();
111+
//! Save the default metadata.
112+
void saveDefaultMetadata();
113+
//! Load the default metadata.
114+
void loadDefaultMetadata();
115+
106116
//! Help button
107117
void showHelp();
108118

@@ -131,6 +141,11 @@ class APP_EXPORT QgsRasterLayerProperties : public QgsOptionsDialogBase, private
131141
void refreshLegend( const QString &layerID, bool expandItem );
132142

133143
private:
144+
QPushButton *mBtnStyle = nullptr;
145+
QPushButton *mBtnMetadata = nullptr;
146+
QAction *mActionLoadMetadata = nullptr;
147+
QAction *mActionSaveMetadataAs = nullptr;
148+
134149
//! \brief A constant that signals property not used
135150
const QString TRSTRING_NOT_SET;
136151

0 commit comments

Comments
 (0)