Skip to content
Permalink
Browse files

Add abstraction of project's absolute file path, base name, last modi…

…fied
  • Loading branch information
wonder-sk committed Apr 7, 2018
1 parent 47d5b7f commit 15f7ec7854f957d273ce2bffb65d5bbeadcbff7e
@@ -101,9 +101,37 @@ representation.
%Docstring
Returns QFileInfo object for the project's associated file.

.. note::

The use of this method is discouraged since QGIS 3.2 as it only works with project files stored
in the file system. It is recommended to use absoluteFilePath(), baseName(), lastModifiedTime() as
replacements that are aware of the fact that projects may be saved in other project storages.

.. seealso:: :py:func:`fileName`

.. versionadded:: 2.9
%End

QDateTime lastModified() const;
%Docstring
Returns last modified time of the project file as returned by the file system (or other project storage).

.. versionadded:: 3.2
%End

QString absoluteFilePath() const;
%Docstring
Returns full absolute path to the project file if the project is stored in a file system - derived from fileName().
Returns empty string when the project is stored in a project storage (there is no concept of paths for custom project storages).

.. versionadded:: 3.2
%End

QString baseName() const;
%Docstring
Returns the base name of the project file without the path and without extension - derived from fileName().

.. versionadded:: 3.2
%End

QgsCoordinateReferenceSystem crs() const;
@@ -35,6 +35,7 @@ Metadata associated with a project
#include "qgsprojectstorage.h"
%End
public:
QString name;
QDateTime lastModified;
};

@@ -13571,14 +13571,28 @@ void QgisApp::populateProjectStorageMenu( QMenu *menu, bool saving )
QAction *action = menu->addAction( name );
if ( saving )
{
connect( action, &QAction::triggered, [storage]
connect( action, &QAction::triggered, [this, storage]
{
QString uri = storage->showSaveGui();
if ( !uri.isEmpty() )
{
// TODO: merge with QgisApp::fileSaveAs()
QgsProject::instance()->setFileName( uri );
QgsProject::instance()->write();
if ( QgsProject::instance()->write() )
{
setTitleBarText_( *this ); // update title bar
mStatusBar->showMessage( tr( "Saved project to: %1" ).arg( uri ), 5000 );
// add this to the list of recently used project files
saveRecentProjectPath( uri );
mProjectLastModified = QgsProject::instance()->lastModified();
}
else
{
QMessageBox::critical( this,
tr( "Unable to save project %1" ).arg( uri ),
QgsProject::instance()->error(),
QMessageBox::Ok,
Qt::NoButton );
}
}
} );
}
@@ -462,6 +462,45 @@ QFileInfo QgsProject::fileInfo() const
return QFileInfo( mFile );
}

QDateTime QgsProject::lastModified() const
{
QgsProjectStorage *storage = QgsApplication::projectStorageRegistry()->projectStorageFromUri( mFile.fileName() );
if ( storage )
{
QgsProjectStorage::Metadata metadata;
storage->readProjectMetadata( mFile.fileName(), metadata );
return metadata.lastModified;
}
else
{
return QFileInfo( mFile.fileName() ).lastModified();
}
}

QString QgsProject::absoluteFilePath() const
{
QgsProjectStorage *storage = QgsApplication::projectStorageRegistry()->projectStorageFromUri( mFile.fileName() );
if ( storage )
return QString();

return QFileInfo( mFile.fileName() ).absoluteFilePath();
}

QString QgsProject::baseName() const
{
QgsProjectStorage *storage = QgsApplication::projectStorageRegistry()->projectStorageFromUri( mFile.fileName() );
if ( storage )
{
QgsProjectStorage::Metadata metadata;
storage->readProjectMetadata( mFile.fileName(), metadata );
return metadata.name;
}
else
{
return QFileInfo( mFile.fileName() ).baseName();
}
}

QgsCoordinateReferenceSystem QgsProject::crs() const
{
return mCrs;
@@ -151,11 +151,35 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera

/**
* Returns QFileInfo object for the project's associated file.
*
* \note The use of this method is discouraged since QGIS 3.2 as it only works with project files stored
* in the file system. It is recommended to use absoluteFilePath(), baseName(), lastModifiedTime() as
* replacements that are aware of the fact that projects may be saved in other project storages.
*
* \see fileName()
* \since QGIS 2.9
*/
QFileInfo fileInfo() const;

/**
* Returns last modified time of the project file as returned by the file system (or other project storage).
* \since QGIS 3.2
*/
QDateTime lastModified() const;

/**
* Returns full absolute path to the project file if the project is stored in a file system - derived from fileName().
* Returns empty string when the project is stored in a project storage (there is no concept of paths for custom project storages).
* \since QGIS 3.2
*/
QString absoluteFilePath() const;

/**
* Returns the base name of the project file without the path and without extension - derived from fileName().
* \since QGIS 3.2
*/
QString baseName() const;

/**
* Returns the project's native coordinate reference system.
* \since QGIS 3.0
@@ -41,6 +41,9 @@ class CORE_EXPORT QgsProjectStorage
class Metadata
{
public:
//! Name of the project - equivalent to a file's base name (i.e. without path and extension).
QString name;
//! Date and local time when the file was last modified.
QDateTime lastModified;
};

@@ -208,6 +208,7 @@ bool QgsPostgresProjectStorage::readProjectMetadata( const QString &uri, QgsProj
{
if ( result.PQntuples() == 1 )
{
metadata.name = projectUri.projectName;
QString metadataStr = result.PQgetvalue( 0, 0 );
QJsonDocument doc( QJsonDocument::fromJson( metadataStr.toUtf8() ) );
ok = _parseMetadataDocument( doc, metadata );
@@ -106,6 +106,11 @@ class MemoryStorage : public QgsProjectStorage
QString projectName = lst[1];

mProjects[projectName] = ioDevice->readAll();

QgsProjectStorage::Metadata meta;
meta.name = projectName;
meta.lastModified = QDateTime::currentDateTime();
mProjectsMetadata[projectName] = meta;
return true;
}

@@ -119,11 +124,25 @@ class MemoryStorage : public QgsProjectStorage
return false;

mProjects.remove( projectName );
mProjectsMetadata.remove( projectName );
return true;
}

virtual bool readProjectMetadata( const QString &uri, QgsProjectStorage::Metadata &metadata ) override
{
QStringList lst = uri.split( ":" );
Q_ASSERT( lst.count() == 2 );
QString projectName = lst[1];
if ( !mProjects.contains( projectName ) )
return false;

metadata = mProjectsMetadata[projectName];
return true;
}

private:
QHash<QString, QByteArray> mProjects;
QHash<QString, QgsProjectStorage::Metadata> mProjectsMetadata;
};


@@ -151,6 +170,12 @@ void TestQgsProjectStorage::testMemoryStorage()
QVERIFY( writeOk );
QCOMPARE( memStorage->listProjects( QString() ).count(), 1 );

QVERIFY( prj1.absoluteFilePath().isEmpty() );
QCOMPARE( prj1.baseName(), QString( "project1" ) );
QVERIFY( prj1.lastModified().secsTo( QDateTime::currentDateTime() ) < 1 );

// read the project back

QgsProject prj2;
prj2.setFileName( "memory:project1" );
bool readOk = prj2.read();
@@ -166,6 +191,18 @@ void TestQgsProjectStorage::testMemoryStorage()
bool readInvalidOk = prj3.read();
QVERIFY( !readInvalidOk );

// test metadata access

QgsProjectStorage::Metadata meta1;
bool readMetaOk = memStorage->readProjectMetadata( "memory:project1", meta1 );
QVERIFY( readMetaOk );
QCOMPARE( meta1.name, QString( "project1" ) );
QVERIFY( meta1.lastModified.secsTo( QDateTime::currentDateTime() ) < 1 );

QgsProjectStorage::Metadata metaX;
bool readMetaInvalidOk = memStorage->readProjectMetadata( "memory:projectXYZ", metaX );
QVERIFY( !readMetaInvalidOk );

// test removal

bool removeInvalidOk = memStorage->removeProject( "memory:projectXYZ" );
@@ -102,10 +102,15 @@ def testSaveLoadProject(self):

self.assertEqual(len(prj2.mapLayers()), 1)

self.assertEqual(prj2.baseName(), "abc")
self.assertEqual(prj2.absoluteFilePath(), "") # path not supported for project storages
self.assertTrue(abs(prj2.lastModified().secsTo(QDateTime.currentDateTime())) < 10)

# try to see project's metadata

res, metadata = prj_storage.readProjectMetadata(project_uri)
self.assertTrue(res)
self.assertEqual(metadata.name, "abc")
time_project = metadata.lastModified
time_now = QDateTime.currentDateTime()
time_diff = time_now.secsTo(time_project)

0 comments on commit 15f7ec7

Please sign in to comment.
You can’t perform that action at this time.