ó
dòôdc           @` sí  d  Z  d d l m Z m Z m Z m Z d d l Td d l Z d d l Z d d l	 Z	 d d l
 Z
 d d l m Z d d l m Z d e f d „  ƒ  YZ d	 „  Z d
 „  Z d „  Z d „  Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e
 j f d „  ƒ  YZ d d „ Z d d „ Z d d d d „ Z d „  Z d d „ Z d d „ Z d „  Z  i e d 6d d  6e! d! ƒ d" 6d# d$ 6d% d& g d' d( g d) d* g e! d+ ƒ g d, d& g e! d- ƒ g e! d. ƒ g d/ d0 g d1 d2 g g	 d3 6i e d 6d4 d  6e d5 6e! d6 ƒ d" 6d7 d$ 6e! d8 ƒ g d7 d9 g d: d; g d< d; g e! d= ƒ g d7 d9 g d: d> g d< d9 g g d3 6i e d 6d? d  6e d5 6e! d@ ƒ d" 6dA d$ 6e! dB ƒ g dA dC g dD dE g g d3 6i e d 6dF d  6e d5 6e! dG ƒ d" 6dH d$ 6e! dI ƒ g dH dJ g dK dL g dM dN g e! dO ƒ g dH dJ g dP dQ g dR dJ g g d3 6i e d 6dS d  6e  d5 6e! dT ƒ d" 6dU d$ 6e! dV ƒ g dW dX g e! dY ƒ g dZ d[ g e! d\ ƒ g d] d^ g g d3 6i e d 6d_ d  6e d5 6e! d` ƒ d" 6da d$ 6e! db ƒ g da dc g dd de g df dg g dh di g g d3 6i e d 6dj d  6e d5 6e! dk ƒ d" 6dl d$ 6dl dm g e! dn ƒ g do dp g g d3 6i e d 6dq d  6e d5 6e! dr ƒ d" 6ds d$ 6e! dt ƒ g du dv g dw dx g dy dz g d{ d| g g d3 6g Z" e j# g  e" D] Z$ e$ d  e$ f ^ qÊƒ Z% d S(}   u~   Renaming layer names according to the specified pattern.

The pattern can contain one or more fields provided in this module.
i    (   t   absolute_importt   divisiont   print_functiont   unicode_literals(   t   *N(   t	   pygimplib(   t   actionst   ItemRenamerc           B` s    e  Z d d  „ Z d d „ Z RS(   c         C` s.   t  j j d | d t t | ƒ ƒ ƒ |  _ d  S(   Nt   patternt   fields(   t   pgt   patht   StringPatternt    _get_fields_and_substitute_funcst   _init_fieldst   _filename_pattern(   t   selfR   t
   fields_raw(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   __init__   s    c         C` s+   | d  k r | j } n  |  j j | | ƒ S(   N(   t   Nonet   current_itemR   t
   substitute(   R   t   batchert   item(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   rename   s    N(   t   __name__t
   __module__R   R   R   (    (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR      s   c         C` s   d „  |  Dƒ S(   Nc         S` s.   i  |  ]$ } | j  d  k	 r | j  | j “ q S(   N(   t   substitute_funcR   t   regex(   t   .0t   field(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pys
   <dictcomp>%   s   	(    (   R	   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR   #   s    c         C` s^   |  d  k r t }  n  g  } x< |  D]4 } | j ƒ  } | j d ƒ } | j | |   ƒ q" W| S(   Nu   type(   R   t   _FIELDS_LISTt   copyt   popt   append(   R   R	   t	   field_rawt   field_raw_copyt
   field_type(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR   )   s    	c         C` sŠ   g  } x} |  j  ƒ  D]o } t | t ƒ rS | j | j | j | j t | ƒ f ƒ q | j | d | d | d t | d ƒ f ƒ q W| S(   Nu   display_nameu   str_to_insertu   regexu   examples_lines(	   t   valuest
   isinstancet   FieldR"   t   display_namet   str_to_insertR   t   strt   _get_formatted_examples(   R	   t   descriptionsR   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   get_field_descriptions9   s    %c         C` s|   |  s
 d Sg  } xF |  D]> } t  | ƒ d k rH | j d j | ƒ ƒ q | j | Œ  q Wd j d j t d ƒ ƒ g | ƒ S(   Nu    i   u    â†’ u   
u	   <b>{}</b>u   Examples(   t   lenR"   t   joint   formatt   _(   t   examples_linest   formatted_examples_linest   example_line(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR,   H   s    R(   c           B` st   e  Z d  „  Z d „  Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z	 e d „  ƒ Z
 RS(   c         C` s1   | |  _  | |  _ | |  _ | |  _ | |  _ d  S(   N(   t   _regext   _substitute_funct   _display_namet   _str_to_insertt   _examples_lines(   R   R   R   R)   R*   R3   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR   Y   s
    				c         C` s   |  j  S(   N(   t   examples(   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   __str__f   s    c         C` s   |  j  S(   N(   R6   (   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR   i   s    c         C` s   |  j  S(   N(   R7   (   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR   m   s    c         C` s   |  j  S(   N(   R8   (   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR)   q   s    c         C` s   |  j  S(   N(   R9   (   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR*   u   s    c         C` s   |  j  S(   N(   R:   (   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR3   y   s    c         C` s   t  |  j ƒ S(   N(   R,   R:   (   R   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR;   }   s    (   R   R   R   R<   t   propertyR   R   R)   R*   R3   R;   (    (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR(   W   s   		t   NumberFieldc           B` s,   e  Z d  „  Z e e d „ ƒ Z d „  Z RS(   c         C` s5   t  ƒ  j | |  j | | | ƒ t j t ƒ |  _ d  S(   N(   t   superR   t   _get_numbert   collectionst   defaultdictt   dictt   _global_number_generators(   R   R   R)   R*   R3   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR   „   s    	c         c` st   |  } | r d } n d } xR t  ro t | ƒ } t | ƒ | k  r] d | t | ƒ | } n  | V| | 7} q Wd  S(   Ni   iÿÿÿÿu   0(   t   TrueR+   R/   (   t   initial_numbert   paddingt	   ascendingt   it	   incrementt   str_i(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   generate_number–   s    		c         G` sù  t  } t  } d  } xi | D]a } | d k r4 t } q | j d ƒ r t } y t | t d ƒ ƒ } Wqz t k
 rv qz Xq q W| rÃ | j d  k	 rœ | j n d  }	 |	 d  k	 rº |	 j j	 n d  }
 n d  }	 d  }
 |
 |  j
 | k rä| d  k	 rô | n	 t | ƒ } t | ƒ } | d k rÁ| rÁ| r¯|	 d  k	 r{t g  | j D]1 } | j |	 j d k r>| j |	 k r>| ^ q>ƒ } q¾t g  | j D] } | j d k rˆ| ^ qˆƒ } qÁt | j ƒ } n  |  j | | | ƒ |  j
 | |
 <n  t |  j
 | |
 ƒ S(   Nu   %nu   %di    i   (   RE   R   t   Falset
   startswitht   intR/   t
   ValueErrort   parentt   rawt   IDRD   t	   item_treet   depthRL   t   next(   R   R   R   t   field_valuet   argst   reset_numbering_on_parentRH   RG   t   argt   parent_itemt	   parent_idRF   t	   tree_item(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR@   §   s@    	!71(   R   R   R   t   staticmethodRE   RL   R@   (    (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR>   ‚   s   	t   _PercentTemplatec           B` s   e  Z d  Z RS(   u   %(   R   R   t	   delimiter(    (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyR_   Ô   s   u    c         C` sl   | d k rY t  j j | j ƒ } | rY | d k rL | |  j k rS | j SqV | j SqY n  t  j j | j ƒ S(   Nu   %eu   %i(   u   %eu   %i(   R
   R   t   get_file_extensiont	   orig_namet   file_extensiont   namet   get_filename_root(   R   R   RW   t   file_extension_strip_modeRc   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _get_layer_nameÙ   s    
c         C` sc   |  j  d  k	 r0 |  j  j d  k	 r0 |  j  j } n t d ƒ } | d k rL | St j j | d ƒ Sd  S(   Nu   Untitledu   %eu    (   t   current_imageR   Rd   R2   R
   R   t$   get_filename_with_new_file_extension(   R   R   RW   t   keep_extension_strt
   image_name(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _get_image_nameæ   s    !u   -c   
      C` s¦   d } | d  k r d } n' | | k r< | j | d ƒ } n d } g  | j D] } | j ^ qL } | t |  | | | ƒ g 7} | j g  | D] }	 | j |	 ƒ ^ qŠ ƒ S(   Nu   %cu   {}(   R   t   replacet   parentsRd   Rg   R0   R1   (
   R   R   RW   t	   separatort   wrapperRf   t   path_component_tokenRQ   t   path_componentst   path_component(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _get_layer_pathò   s    	c   
      ` s  g  ‰ ‡ f d †  ‰ d „  ‰  ‡ ‡ ‡ f d †  } ‡  ‡ ‡ f d †  } d } d } d } | sj | ƒ  n† t  | ƒ d k  r‰ | | ƒ ng | | d	 k ræ | d
 } | d	 j | d ƒ } t  | ƒ d k rÜ | | d ƒ qð | ƒ  n
 | | ƒ | j g  ˆ D] }	 | j |	 ƒ ^ qý ƒ S(   Nc         ` s6   |  t  j k r t  j |  } n |  } ˆ  j | ƒ d  S(   N(   R   t   BUILTIN_TAGSR"   (   t   tagt   tag_display_name(   t   tags_to_insert(    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _insert_tag  s    c         S` s5   t  t j ƒ } t  t j j ƒ  ƒ } | | j |  ƒ S(   N(   t   listR   Ru   R&   t   index(   Rw   t   builtin_tags_keyst   builtin_tags_values(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _get_tag_from_tag_display_name  s    c          ` s5   x ˆ j  D] }  ˆ  |  ƒ q
 Wˆ j d d „  ƒ d  S(   Nt   keyc         S` s
   |  j  ƒ  S(   N(   t   lower(   Rv   (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   <lambda>  t    (   t   tagst   sort(   Rv   (   Ry   R   Rx   (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _insert_all_tags  s    c         ` sj   xc |  D][ } | t  j k r" q n  | t  j j ƒ  k rF ˆ  | ƒ } n  | ˆ j k r ˆ | ƒ q q Wd  S(   N(   R   Ru   R&   Rƒ   (   Rƒ   Rv   (   R~   Ry   R   (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _insert_specified_tags  s    u   -u   {}u   %ti   i   i    (   R/   Rm   R0   R1   (
   R   R   RW   RX   R…   R†   t   tag_separatort   tag_wrappert	   tag_tokenRv   (    (   R~   Ry   R   Rx   s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt	   _get_tags  s(    		



u   %Y-%m-%dc         C` s   t  j  j ƒ  j | ƒ S(   N(   t   datetimet   nowt   strftime(   R   R   RW   t   date_format(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _get_current_date:  s    u   %pxc   
      C` s  |  j  } i | j d 6| j d 6} i  } | d k rz i | j j d 6| j j d 6| j j d d 6| j j d d	 6} nó | j d
 ƒ rmt j d t j d
 ƒ d | ƒ } | d  k	 rm| j
 d ƒ rß t | j
 d ƒ ƒ }	 n d }	 i t | j j | j |	 ƒ d 6t | j j | j |	 ƒ d 6t | j j d | j |	 ƒ d 6t | j j d | j |	 ƒ d	 6} qmn  | j | ƒ t | ƒ j | ƒ S(   Nu   iwu   ihu   %pxu   wu   hi    u   xi   u   yu   %pcu   ^u	   ([0-9]*)$i   (   Rh   t   widtht   heightRR   t   offsetsRN   t   ret   matcht   escapeR   t   groupRO   t   roundt   updateR_   t   safe_substitute(
   R   R   RW   R   t   measuret   imageR	   t   layer_fieldsR”   t   round_digits(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _get_attributes>  s0    	
#!*c         G` sí   t  j j j | ƒ \ } } y t | d }	 Wn t k
 rA d SX|	 |  | | | Œ }
 d } d } t | ƒ d k r  y t | d ƒ } Wq  t k
 rœ q  Xn  x+ | d D] } | t	 t
 | j ƒ  ƒ O} q« Wt
 j | | |
 d | d | ƒS(   Nu   substitute_funcu    i    i   t   countt   flags(   R
   R   R   t   parse_fieldt   FIELDSt   KeyErrorR/   RO   RP   t   getattrR“   t   uppert   sub(   R   R   RW   t   field_to_replace_strR   t   replacementt   count_and_flagst
   field_namet
   field_argst
   field_funct   str_to_processRŸ   R    t	   flag_name(    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   _replaced  s     u   typeu   ^[0-9]+$u   regexu   image001u   display_nameu
   image[001]u   str_to_insertu   [001]u   001, 002, ...u   [1]u	   1, 2, ...u   [005]u   005, 006, ...u2   To continue numbering across layer groups, use %n.u	   [001, %n]u"   To use descending numbers, use %d.u'   Suppose that the number of layers is 5:u	   [000, %d]u   005, 004, ...u	   [10, %d2]u   10, 09, ...u   examples_linesu
   layer nameu   substitute_funcu
   Layer nameu   [layer name]uJ   Suppose that a layer is named "Frame.png" and the file extension is "png".u   Frameu   [layer name, %e]u	   Frame.pngu   [layer name, %i]u*   Suppose that a layer is named "Frame.jpg".u	   Frame.jpgu
   image nameu
   Image nameu   [image name]u,   Suppose that the image is named "Image.xcf".u   Imageu   [image name, %e]u	   Image.xcfu
   layer pathu
   Layer pathu   [layer path]uM   Suppose that a layer named "Left" has parent groups named "Hands" and "Body".u   Body-Hands-Leftu   [layer path, _]u   Body_Hands_Leftu   [layer path, _, (%c)]u   (Body)_(Hands)_(Left)uK   Suppose that the layer is named "Left.jpg" and the file extension is "png".u   [layer path, -, %c, %e]u   Body-Hands-Left.jpgu   [layer path, -, %c, %i]u   replaceu   Replaceu	   [replace]u/   Suppose that a layer is named "Animal copy #1".u"   [replace, [layer name], [a], [b] ]u   Animbl copy #1uS   You can use the regular expression syntax as defined in the "re" module for Python.u5   [replace, [layer name], [ copy(?: #[[0-9]]+)*$], [] ]u   Animalu^   You can specify the number of replacements and flags as defined in the "re" module for Python.u0   [replace, [layer name], [a], [b], 1, ignorecase]u   bnimal copy #1u   tagsu   Tagsu   [tags]u;   Suppose that a layer has tags "left", "middle" and "right".u   left-middle-rightu   [tags, left, right]u
   left-rightu   [tags, _, (%t)]u   (left)_(middle)_(right)u   [tags, _, (%t), left, right]u   (left)_(right)u   current dateu   Current dateu   [current date]u
   2019-01-28uL   Custom date format uses formatting as per the "strftime" function in Python.u   [current date, %m.%d.%Y_%H-%M]u   28.01.2019_19-04u
   attributesu
   Attributesu   [attributes]uÁ   Suppose that a layer has width, height, <i>x</i>-offset and <i>y</i>-offset
of 1000, 270, 0 and 40 pixels, respectively,
and the image has width and height of 1000 and 500 pixels, respectively.u   [attributes, %w-%h-%x-%y]u   1000-270-0-40u   [attributes, %w-%h-%x-%y, %pc]u   1.0-0.54-0.0-0.08u   [attributes, %w-%h-%x-%y, %pc1]u   1.0-0.5-0.0-0.1u   [attributes, %iw-%ih]u   1000-500(&   t   __doc__t
   __future__R    R   R   R   t   future.builtinsRA   R‹   R“   t   stringt   export_layersR   R
   R   t   objectR   R   R   R.   R,   R(   R>   t   TemplateR_   Rg   Rl   R   Rt   RŠ   R   Rž   R¯   R2   R   t   OrderedDictR   R¢   (    (    (    s?   /home/josie/.config/GIMP/2.10/plug-ins/export_layers/renamer.pyt   <module>   sì   "
				+R	6&																										                 # -*- coding: utf-8 -*-

"""Custom setting classes specific to the plug-in."""

from __future__ import absolute_import, division, print_function, unicode_literals
from future.builtins import *

import collections
import os
import types

import gimp

from export_layers import pygimplib as pg

from export_layers import renamer as renamer_


class FilenamePatternEntryPresenter(pg.setting.presenters_gtk.ExtendedEntryPresenter):
  """`pygimplib.setting.Presenter` subclass for
  `pygimplib.gui.FilenamePatternEntry` elements.
  
  Value: Text in the entry.
  """
  
  def _create_gui_element(self, setting):
    return pg.gui.FilenamePatternEntry(renamer_.get_field_descriptions(renamer_.FIELDS))


class FilenamePatternSetting(pg.setting.StringSetting):
  
  _ALLOWED_GUI_TYPES = [
    FilenamePatternEntryPresenter,
    pg.SettingGuiTypes.extended_entry,
    pg.SettingGuiTypes.entry,
  ]
  
  def _assign_value(self, value):
    if not value:
      self._value = self._default_value
    else:
      self._value = value


class ImagesAndGimpItemsSetting(pg.setting.Setting):
  """Class for settings representing a mapping of (GIMP image ID, GIMP item IDs)
  pairs.
  
  The mapping is implemented as `collections.defaultdict(set)`.
  
  A GIMP item ID can be represented as an integer or an (ID, FOLDER_KEY) tuple,
  where `FOLDER_KEY` is a string literal defined in `pygimplib.itemtree`.
  
  When storing this setting to a persistent source, images are stored as file
  paths and items are stored as (item class name, item path) or (item class
  name, item path, FOLDER_KEY) tuples. Item class name and item path are
  described in `pygimplib.pdbutils.get_item_from_image_and_item_path()`.
  
  Default value: `collections.defaultdict(set)`
  """
  
  _ALLOWED_PDB_TYPES = []
  _ALLOWED_GUI_TYPES = []
  _DEFAULT_DEFAULT_VALUE = lambda self: collections.defaultdict(set)
  
  def _raw_to_value(self, raw_value):
    if isinstance(raw_value, dict):
      value = collections.defaultdict(set)
      
      for key, items in raw_value.items():
        if isinstance(key, types.StringTypes):
          image = pg.pdbutils.find_image_by_filepath(key)
        else:
          image = pg.pdbutils.find_image_by_id(key)
        
        if image is None:
          continue
        
        image_id = image.ID
        
        if not isinstance(items, collections.Iterable) or isinstance(items, types.StringTypes):
          raise TypeError('expected a list-like, found {}'.format(items))
        
        processed_items = set()
        
        for item in items:
          if isinstance(item, (list, tuple)):
            if len(item) not in [2, 3]:
              raise ValueError(
                'list-likes representing items must contain exactly 2 or 3 elements'
                ' (has {})'.format(len(item)))
            
            if isinstance(item[0], int):  # (item ID, item type)
              item_object = gimp.Item.from_id(item[0])
              if item_object is not None:
                processed_items.add(tuple(item))
            else:
              if len(item) == 3:
                item_type = item[2]
                item_class_name_and_path = item[:2]
              else:
                item_type = None
                item_class_name_and_path = item
              
              item_object = pg.pdbutils.get_item_from_image_and_item_path(
                image, *item_class_name_and_path)
              
              if item_object is not None:
                if item_type is None:
                  processed_items.add(item_object.ID)
                else:
                  processed_items.add((item_object.ID, item_type))
          else:
            item_object = gimp.Item.from_id(item)
            if item_object is not None:
              processed_items.add(item)
        
        value[image_id] = processed_items
    else:
      value = raw_value
    
    return value
  
  def _value_to_raw(self, value, source_type):
    raw_value = {}
    
    if source_type == 'session':
      for image_id, item_ids in value.items():
        raw_value[image_id] = list(
          item_id if isinstance(item_id, int) else list(item_id) for item_id in item_ids)
    else:
      for image_id, item_ids in value.items():
        image = pg.pdbutils.find_image_by_id(image_id)
        
        if image is None or image.filename is None:
          continue
        
        image_filepath = pg.utils.safe_decode_gimp(image.filename)
        
        raw_value[image_filepath] = []
        
        for item_id in item_ids:
          if isinstance(item_id, (list, tuple)):
            if len(item_id) != 2:
              raise ValueError(
                'list-likes representing items must contain exactly 2 elements'
                ' (has {})'.format(len(item_id)))
            
            item = gimp.Item.from_id(item_id[0])
            item_type = item_id[1]
          else:
            item = gimp.Item.from_id(item_id)
            item_type = None
          
          if item is None:
            continue
          
          item_as_path = pg.pdbutils.get_item_as_path(item, include_image=False)
          
          if item_as_path is not None:
            if item_type is None:
              raw_value[image_filepath].append(item_as_path)
            else:
              raw_value[image_filepath].append(item_as_path + [item_type])
    
    return raw_value
  
  def _init_error_messages(self):
    self.error_messages['value_must_be_dict'] = _('Value must be a dictionary.')
  
  def _validate(self, value):
    if not isinstance(value, dict):
      raise pg.setting.SettingValueError(
        pg.setting.value_to_str_prefix(value) + self.error_messages['value_must_be_dict'])


class ImageIdsAndDirectoriesSetting(pg.setting.Setting):
  """Class for settings the list of currently opened images and their import
  directory paths.
  
  The setting value is a dictionary of (image ID, import directory path) pairs.
  The import directory path is `None` if the image does not have any.
  
  This setting cannot be registered to the PDB as no corresponding PDB type
  exists.
  
  Default value: `{}`
  """
  
  _DEFAULT_DEFAULT_VALUE = {}
  
  @property
  def value(self):
    # Return a copy to prevent modifying the dictionary indirectly by assigning
    # to individual items (`setting.value[image.ID] = dirpath`).
    return dict(self._value)
  
  def update_image_ids_and_dirpaths(self):
    """Removes all (image ID, import directory path) pairs for images no longer
    opened in GIMP. Adds (image ID, import directory path) pairs for new images
    opened in GIMP.
    """
    current_images, current_image_ids = self._get_currently_opened_images()
    self._filter_images_no_longer_opened(current_image_ids)
    self._add_new_opened_images(current_images)
  
  def update_dirpath(self, image_id, dirpath):
    """Assigns a new directory path to the specified image ID.
    
    If the image ID does not exist in the setting, `KeyError` is raised.
    """
    if image_id not in self._value:
      raise KeyError(image_id)
    
    self._value[image_id] = dirpath
  
  def _get_currently_opened_images(self):
    current_images = gimp.image_list()
    current_image_ids = set([image.ID for image in current_images])
    
    return current_images, current_image_ids
  
  def _filter_images_no_longer_opened(self, current_image_ids):
    self._value = {
      image_id: self._value[image_id] for image_id in self._value
      if image_id in current_image_ids}
  
  def _add_new_opened_images(self, current_images):
    for image in current_images:
      if image.ID not in self._value:
        self._value[image.ID] = self._get_image_import_dirpath(image)
  
  def _get_image_import_dirpath(self, image):
    if image.filename is not None:
      return os.path.dirname(pg.utils.safe_decode_gimp(image.filename))
    else:
      return None
                                                                         