2

I am working on some revision tracking and would like to present information about when layers saved in a GeoPackage were last edited using an expression. I can create a custom function if necessary.

I have had a look in the QGIS Python API but can't find anything. Is there a way to find when a layer was last edited?

enter image description here

5
  • 3
    You could add a date-time-field to the layer, containing now() as default value, and force update that field upon feature creation or edit.
    – Erik
    Commented Dec 5 at 15:29
  • @Erik yep I am progressing with EditTime and EditUsr field for my main layers but am trying to avoid it for every layer that can be edited and has an impact on the output
    – Sethinacan
    Commented Dec 5 at 15:32
  • 2
    The "Last modified" info seem to depend on data type (for exemple data stored in a file gdb seem to show the last time look at it (so now...), shapefile seem to show the spatial index (.sbn) last change, geopackage store it in the "gpkg_contents" table while other data source don't give any information). So you should state with witch format you work as the solution may be quite different...
    – J.R
    Commented Dec 5 at 16:22
  • As you work in a geopackage (so a spatialite database) you may create an history table and populate it using trigger. This will let you not only record when last editing happen but also what edit has been made (an exemple : souptonuts.sourceforge.net/readme_sqlite_tutorial.html)
    – J.R
    Commented Dec 9 at 16:59
  • @J.R Thats a handy looking resource which I will hopefully get some time to review but its a little abstract for now, it did however get me to do some searching and I found the gpkg_contents table in standard geopackages created by QGIS which can be accessed through the database manager but I can't add the table to a qgis project.
    – Sethinacan
    Commented Dec 10 at 9:52

1 Answer 1

2

For now, I can only suggest Python solutions that can be turned into a custom function via the Function Editor.

So, there is a polygon layer called 'polygon', which was the last modified on: 2024-12-03 09:31:33

input

There are several of them:

  1. Through the getmtime() function from the os.path Python module:

    Return the time of last modification of path. The return value is a floating-point number giving the number of seconds since the epoch (see the time module). Raise OSError if the file does not exist or is inaccessible.

    # imports
    from os.path import isfile, getmtime
    from datetime import datetime
    from qgis.core import QgsProject
    
    # getting the vector layer by its name
    layer = QgsProject.instance().mapLayersByName("polygon")[0]
    
    # getting the file path of the data source
    source_path = layer.dataProvider().dataSourceUri().split('|')[0]
    
    # checking if the source is a file and get its last modified time
    if isfile(source_path):
        # getting the last modified time using getmtime
        modified_time = getmtime(source_path)
        # formating the timestamp for readability
        formatted_time = datetime.fromtimestamp(modified_time).strftime('%A, %d. %B %Y %H:%M:%S')
        print(f"Last modified: {formatted_time}")
    else:
        print("The layer source is not a file or its modification date cannot be determined.")
    
  2. Utilizing the st_mtime() function from the os Python module:

    Get the status of a file or a file descriptor. Perform the equivalent of a stat() system call on the given path. path may be specified as either a string or bytes – directly or indirectly through the PathLike interface – or as an open file descriptor. Return a stat_result object.

    # imports
    from os import stat 
    from os.path import isfile
    from datetime import datetime
    from qgis.core import QgsProject
    
    # getting the vector layer by its name
    layer = QgsProject.instance().mapLayersByName("polygon")[0]
    
    # getting the file path of the data source
    source_path = layer.dataProvider().dataSourceUri().split('|')[0]
    
    # checking if the source is a file and get its last modified time
    if isfile(source_path):
        # using os.stat to get file metadata
        file_stats = stat(source_path)
        # getting the last modified time using st_mtime
        modified_time = file_stats.st_mtime
        # formating the timestamp for readability
        formatted_time = datetime.fromtimestamp(modified_time).strftime('%A, %d. %B %Y %H:%M:%S')
        print(f"Last modified: {formatted_time}")
    else:
        print("The layer source is not a file or its modification date cannot be determined.")
    

The output is: Last modified: Tuesday, 03. December 2024 09:31:33

  1. As @J.R mentioned in their comment, information about the last modification could be data-type dependent, see for example Vector Drivers for more details. So, when one uses the ogr module, it could provide you with the DBF_DATE_LAST_UPDATE parameter for a shapefile:

    DBF_DATE_LAST_UPDATE=YYYY-MM-DD: Modification date to write in DBF header with year-month-day format. If not specified, current date is used.

    # imports
    from qgis.core import QgsProject
    from datetime import datetime
    from osgeo import ogr
    
    # getting the vector layer by its name
    layer = QgsProject.instance().mapLayersByName("polygon")[0]
    
    # getting the file path of the data source
    source_path = layer.dataProvider().dataSourceUri().split('|')[0]
    
    # openning the vector layer with ogr module
    dataSource = ogr.Open(source_path)
    daLayer = dataSource.GetLayer(0)
    
    # getting the last modified time
    modified_time = daLayer.GetMetadata_Dict().get('DBF_DATE_LAST_UPDATE')
    
    print(f"Last modified: {modified_time}")
    

The output is: Last modified: 2024-12-03.

1
  • Not sure about no 3, but no 2 works fine for finding when any layer in a geopackage was edited which is pretty handy for what I am doing
    – Sethinacan
    Commented Dec 9 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.