Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add depth option to 'Create groups based on directory names' #24

Open
cratcliff opened this issue Jul 14, 2020 · 5 comments
Open

Add depth option to 'Create groups based on directory names' #24

cratcliff opened this issue Jul 14, 2020 · 5 comments

Comments

@cratcliff
Copy link

Is it possible to add a depth option to the 'Create groups based on directory names' in the configuration tab.

This would enable the user to control how many nested groups are created. For example, I have a directory structure like MyProject/Site1/project_data/Terrain. A depth option of 2 would create a single group called 'Site1' .

I can then quickly load data for all my sites without excess subgroups.

@gacarrillor
Copy link
Owner

gacarrillor commented Jul 14, 2020

That's a nice suggestion. Sometimes I've also ended up with too many subgroups.

There might be many possibilities here, @cratcliff.
Could you explain a little bit your use case? Perhaps we can figure out a generic solution.

@cratcliff
Copy link
Author

cratcliff commented Jul 15, 2020

@gacarrillor before I found your plugin I had a script which would loop through and load known extensions. To help explain look at the following picture which shows the folder/data structure on the left and the resulting QGIS layer groupings on the right.

image

I used the following code with depths of 1 & 3 for the shapefiles and 1 & 4 for the tif files to produce the groupings on the right.
I started using Load Them all for the the bounding box and alphanumeric filters.

import glob
import os
base_folder = r"C:\_data\MyProject"
load_ext = ['*.shp','*.tif']
depth_list = [2]

root = QgsProject.instance().layerTreeRoot()

for eaExt in load_ext:
    # find the list of files to load
    file_list = glob.glob(os.path.join(base_folder,'**',eaExt),recursive=True)
    file_list = sorted(file_list)
    print ('Found {} of file types {} to load'.format(len(file_list), eaExt))
    
    #loop through each file
    for eaFile in file_list:
        
        eaFile = os.path.normpath(eaFile)
        
        # break the folder structure into a list omiting the base folder
        sub = os.path.dirname(eaFile).replace(base_folder,'').split(os.path.sep)
        
        nested_groups=[]   # stores nested groups
        thisGroup=None
        for eaDepth in depth_list:
            if eaDepth <= len(sub)-1:       # make sure the depth folder is valid
                if len(nested_groups) == 0:  # ie top level group
                    # see if group already exists, if not create it
                    thisGroup = root.findGroup( sub[eaDepth])
                    if thisGroup is None:
                          thisGroup = root.addGroup(sub[eaDepth])
                else:
                    #same for further sub groups starting with the last in the list
                    thisGroup = nested_groups[-1].findGroup(sub[eaDepth])
                    if thisGroup is None:
                        thisGroup = nested_groups[-1].addGroup( sub[eaDepth])
                
                nested_groups+=[thisGroup]    # Track nested group layers

        if eaExt == '*.shp':
            layer = QgsVectorLayer( eaFile, os.path.basename(eaFile), "ogr" )
        else:
            layer = QgsRasterLayer(eaFile, os.path.basename(eaFile))
        
        if thisGroup is not None:
            QgsProject.instance().addMapLayer(layer, False)
            thisGroup.addLayer(layer)
        else:
            QgsProject.instance().addMapLayer(layer, True)
        
        if len(nested_groups) > 0:
            print ('Added layer {} to {}'.format(layer.name(),os.path.join (*[gp.name() for gp in nested_groups])))
        else:
            print ('Added layer {} to {}'.format(layer.name(),'Top'))

@gacarrillor
Copy link
Owner

In your example, what happened to modified_data/Site_Extent.shp? Since it has also a depth of 3, how was it filtered out?

On the other hand, how should we handle files that lie in between of the specified depths? For instance, let's imagine that SpatialData had a Shapefile (out of Transport and Hidrology folders). Would you load to QGIS Layer Tree with Site1 as its parent folder?

And finally, but very related, what if Transport had a subfolder (say, Subfolder) with another Shapefile. Would you load it to QGIS Layer Tree with Transport as its parent folder?

@cratcliff
Copy link
Author

@gacarrillor sorry I forgot the modified_data/Site_Extent.shp when creating the picture.

On all your other points I would be putting the layers into the parent group. If there isn't a parent group then just load the layer. Using the updated code above if depth_list=[] just loads the layers without any grouping and depth_list=[0] a parent group called '' (blank) is created. You could also use the base folder name (ie MyProject) instead of blank.

I have updated the file structure and created couple of other variations as shown in the picture. The order of the layers will vary depending on how the file_list is sorted. These were created using the updated code above.

image

@gacarrillor
Copy link
Owner

gacarrillor commented Jul 17, 2020

Now, that makes sense. And I think it is the expected behavior.

Consider joining efforts and contributing in terms of code (as a Pull Request, since you have a script already) or even funding the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants