Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
My Gimp 3.0 Plug-in (group_selected_layers)
#1
Plug-in: group-selected-layers
Description: nests all currently selected layers inside a new group layer.  

Tested and working on version 2.99.19 - commit fe6e1d7

Any feedback welcome Smile


Code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#  SAMPLE PLUG-IN USED AS REFERENCE/TEMPLATE: test-file-plug-ins.py 2021-2024 Jacob Boerema
#
# Tested and working on version 2.99.19 - commit fe6e1d7
#
# Script path:
# ~/.config/GIMP/2.99/plug-ins/group_selected_layers/group_selected_layers.py


import sys

import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp

from gi.repository import GLib

VERSION = "0.2"
AUTHORS = "newinput"
COPYRIGHT = "newinput"
YEARS   = "2023-2024"

class GroupSelectedLayers (Gimp.PlugIn):

   def __init__(self):
       Gimp.PlugIn.__init__(self)
       self.test_cfg = None
       self.log = None

   ## GimpPlugIn virtual methods ##
   def do_set_i18n(self, _name):
       # We don't support internationalization here...
       return False

   def do_query_procedures(self):
       return [ 'group-selected-layers' ]

   def do_create_procedure(self, name):

       if name == 'group-selected-layers':
           procedure = Gimp.ImageProcedure.new(self, name,
                                               Gimp.PDBProcType.PLUGIN,
                                               self.group_selected_layers, None)
           procedure.set_image_types("*")
           procedure.set_sensitivity_mask(Gimp.ProcedureSensitivityMask.ALWAYS)
           procedure.set_menu_label('group-selected-layers-label')
           procedure.add_menu_path('<Image>/Filters/Development/Python-Fu/')
           procedure.set_documentation('Run group-selected-layers',
                                       'Run group-selected-layers',
                                       name)

       else:
           return None

       procedure.set_attribution(AUTHORS, COPYRIGHT, YEARS)
       return procedure

   def group_selected_layers(self, procedure, run_mode, image,
                        n_drawables, config, run_data):

       # => create new group
       new_group = Gimp.GroupLayer.new(image, "my-new-group")

       # => record currently selected layers
       #
       #    (is needed since inserting a new layer replaces the current selection with just the newly inserted layer)
       #  
       selected_layers = image.get_selected_layers()
       parents = []

       for layer in selected_layers:
           parent = layer.get_parent()
           if parent not in parents:
               parents.append(parent)

       # if same parents
       #     if all selected layers are under the same parent layer, nest the new group layer inside of it
       if len(parents) == 1:                
           new_group_parent = parents[0]
           topmost_position = min([image.get_item_position(layer) for layer in selected_layers])

       # if different parents
       #     if selected layers are nested under different parent layers, insert group layer in the main stack, unnested
       elif len(parents) > 1:              
           new_group_parent = None
           topmost_position = 0

       # if no parents found (should not happen)
       #     use main stack as default here to try and not break anything. should not be able to reach this point ever though.
       else:
           new_group_parent = None
           topmost_position = 0
           print("ERROR: could not get any parents from selected layers")


       # => insert new group into image
       image.insert_layer(
               new_group,           # group to insert
               new_group_parent,    # parent nest group inside of. None = unnested
               topmost_position     # index/stack-postition within parent (0 = insert as topmost layer within parent)
       )

       for selected_layer in selected_layers:
           image.reorder_item(
                   selected_layer,  # layer to reorder
                   new_group,       # parent to nest inside
                   -1               # index/stack-postition within parent (-1 = insert as bottommost layer within parent)
           )

       return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())


Gimp.main(GroupSelectedLayers.__gtype__, sys.argv)
Reply
#2
Since you ask:
  • You should test it on 3.00 RC1 (and from my tests with my own code, do_set_i18n() has to return more that False. OTOH you can completely skip the definition, if you don't want to do I18N).
  • Sensitivity should be set to DRAWABLES (not plural) since you want more than one drawable selected
  • <Image>/Filters/Development/Python-Fu/ isn't where you put your script for general use. A much better place would be <Image>/Layer/Stack, or even <Layers> so that it appears in the right click menu of the Layers list. Also note the slight difference between set_menu_label() and add_menu_path() that hints that you can have the plugin in more than one menu (so, in both places mentioned above)(note: I didn't test this, but easy enough to try).
  • 'Run group-selected-layers' as a doc is a bit tautological. Something like Put selected layers in new group would be a bit more useful (same for the menu label...)
  • IMHO you should have a dialog to ask for a group name
  • selected_layers = image.get_selected_layers() is not really useful... all this data is in your n_drawables argument
  • Didn't run your script, but I wonder what happens when all layers are in the top level (parent is image). I think your script would try to insert the image under a group (or pass None as the layer to insert, that could catch the callee off-guard...)
  • print("ERROR: could not get any parents from selected layers") won't be visible to most users (have to be on Linux/OSX with Gimp started from a terminal, or on Windows using gimp-console). How about using Gimp.message()? But then since get_parent() always return something, this code will never be executed unless there are no layer as inputs, in which case see remark #2.
  • Gimp.PlugIn.__init__(self) should be super().__init__()
Reply
#3
Just on the basis of, does it work ?  Gimp 3.0RC1 appimage , Some random layers, then a second time inside the new layer group.

   
Reply
#4
(Yesterday, 10:33 AM)Ofnuts Wrote: Since you ask:
  • You should test it on 3.00 RC1 (and from my tests with my own code, do_set_i18n() has to return more that False. OTOH you can completely skip the definition, if you don't want to do I18N).
  • Sensitivity should be set to DRAWABLES (not plural) since you want more than one drawable selected
  • <Image>/Filters/Development/Python-Fu/ isn't where you put your script for general use. A much better place would be <Image>/Layer/Stack, or even <Layers> so that it appears in the right click menu of the Layers list. Also note the slight difference between set_menu_label() and add_menu_path() that hints that you can have the plugin in more than one menu (so, in both places mentioned above)(note: I didn't test this, but easy enough to try).
  • 'Run group-selected-layers' as a doc is a bit tautological. Something like Put selected layers in new group would be a bit more useful (same for the menu label...)
  • IMHO you should have a dialog to ask for a group name
  • selected_layers = image.get_selected_layers() is not really useful... all this data is in your n_drawables argument
  • Didn't run your script, but I wonder what happens when all layers are in the top level (parent is image). I think your script would try to insert the image under a group (or pass None as the layer to insert, that could catch the callee off-guard...)
  • print("ERROR: could not get any parents from selected layers") won't be visible to most users (have to be on Linux/OSX with Gimp started from a terminal, or on Windows using gimp-console). How about using Gimp.message()? But then since get_parent() always return something, this code will never be executed unless there are no layer as inputs, in which case see remark #2.
  • Gimp.PlugIn.__init__(self) should be super().__init__()

Wow, really big thanks for taking the time to write these points. This is really good feedback. I will start work on these as soon as I can and update the script. I do have a couple of questions for now though, if you are able to answer them:

I may be misunderstanding this one but I assumed that [ 2.99.19 - commit fe6e1d7 ] was 3.0RC1

I'm using the flatpak version and running 
Code:
flatpak list | grep gimp

gives the following output:
Code:
GNU Image Manipulation Program  org.gimp.GIMP   3.0.0~rc1       master  gnome-nightly   system
I got the version number [ 2.99.19 - commit fe6e1d7 ] from the /help/about menu while using gimp assuming it was a more specific version number while 3.0RC1 represented the broader stage that development was in or something of that sort. I also get the new pink welcome window popup with 3.0RC1 in the bottom right and assumed that meant everything was right and up to date. 

Also, just to make sure, is this the right place for me to share this kind of WIP script for feedback? I was contemplating whether it should go in the Extending-the-GIMP section or here.

Thanks again, 
Newman 

(Yesterday, 11:13 AM)rich2005 Wrote: Just on the basis of, does it work ?  Gimp 3.0RC1 appimage , Some random layers, then a second time inside the new layer group.

Cool, thanks a lot for testing it. Would you say it worked as you would expect it to or did any specific part of it feel unintuitive or any behaviors catch you off guard? 

Thanks, 
Newman
Reply
#5
Quote:gives the following output:
Code:
Code:
GNU Image Manipulation Program  org.gimp.GIMP   3.0.0~rc1       master  gnome-nightly   system
I got the version number [ 2.99.19 - commit fe6e1d7 ] from the /help/about menu while using gimp assuming it was a more specific version number while 3.0RC1 represented the broader stage that development was in or something of that sort. I also get the new pink welcome window popup with 3.0RC1 in the bottom right and assumed that meant everything was right and up to date.

No ... fe6e1d7 is behind the RC1. Unfortunately, the flatpak hasn't been updated for 2 or 3 weeks now.
Something got stuck there, and they probably didn't have the time to fix it.

Next run is scheduled for Sunday Morning GMT
Reply
#6
(Yesterday, 03:01 PM)MrsP-from-C Wrote:
Quote:gives the following output:
Code:
Code:
GNU Image Manipulation Program  org.gimp.GIMP   3.0.0~rc1       master  gnome-nightly   system
I got the version number [ 2.99.19 - commit fe6e1d7 ] from the /help/about menu while using gimp assuming it was a more specific version number while 3.0RC1 represented the broader stage that development was in or something of that sort. I also get the new pink welcome window popup with 3.0RC1 in the bottom right and assumed that meant everything was right and up to date.

No ... fe6e1d7 is behind the RC1. Unfortunately, the flatpak hasn't been updated for 2 or 3 weeks now.
Something got stuck there, and they probably didn't have the time to fix it.

Next run is scheduled for Sunday Morning GMT

Oh wow I'm way off then. Does that mean the flatpak version is mislabelled if I'm seeing 3.0RC1 now? Anyways thanks for pointing that out though, I'll see if I can build if from source and check out the real RC1 maybe.
Reply
#7
Quote:Does that mean the flatpak version is mislabelled if I'm seeing 3.0RC1

Same for me.
I've asked on IRC the other day why that is so.
They thought that it was released just before it was tagged 3.0.
I guess that the next version will be tagged properly then. We'll see.
Reply
#8
(Yesterday, 12:07 PM)Newman Wrote: Also, just to make sure, is this the right place for me to share this kind of WIP script for feedback? I was contemplating whether it should go in the Extending-the-GIMP section or here.
Here is better, as long as we are still talking about the release candidates. When 3.0 becomes mainstream, I can move the relevant threads to "Scripting questions" .
Reply


Forum Jump: