o
    h                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ G dd dejZeddddfddZdd ZdS )zForms for treebeard.    )forms)QuerySet)	ErrorList)modelform_factory)escape)	mark_safe)gettext_lazy)AL_Node)MP_Node)NS_Nodec                	       s   e Zd ZdZdedfdedffZdedfded	fd
edffZejdeddZ	ejdeddZ
dd Zdddddedddf	 fdd	Zdd Zd$ fdd	Zedd Zedd Zed d! Zed%d"d#Z  ZS )&MoveNodeForma<  
    Form to handle moving a node in a tree.

    Handles sorted/unsorted trees.

    It adds two fields to the form:

    - Relative to: The target node where the current node will
                   be moved to.
    - Position: The position relative to the target node that
                will be used to move the node. These can be:

                - For sorted trees: ``Child of`` and ``Sibling of``
                - For unsorted trees: ``First child of``, ``Before`` and
                  ``After``

    .. warning::

        Subclassing :py:class:`MoveNodeForm` directly is
        discouraged, since special care is needed to handle
        excluded fields, and these change depending on the
        tree type.

        It is recommended that the :py:func:`movenodeform_factory`
        function is used instead.

    sorted-childzChild ofsorted-siblingz
Sibling offirst-childzFirst child ofleftBeforerightAfterTPosition)requiredlabelFzRelative toc                 C   sb   | j rd}| }|r|j}nd}n| }|rd}|j}nd}| r'd}n| j}||dS )Nr    r   r   )_ref_node_id	_position)	is_sorted
get_parentpkget_prev_siblingis_root)selfinstancepositionnode_parentref_node_idprev_sibling r%   O/var/www/html/ndineBlogger/venv/lib/python3.10/site-packages/treebeard/forms.py_get_position_ref_node<   s"   
z#MoveNodeForm._get_position_ref_nodeNzid_%s:c
                    s   | j }|jd u rtdt|jdd| _| jr| jj}n| jj}|| jd _	| j
|j|	d}|| jd _	|jj j }|r@|jnt| jd _|	d u rMi }n| |	}|d ur[|| t jd|||||||||	d	|
 d S )	Nz&ModelForm has no model class specifiednode_order_byFr   )for_noder   )	datafilesauto_idprefixinitialerror_classlabel_suffixempty_permittedr    r%   )_metamodel
ValueErrorgetattrr   	__class__&_MoveNodeForm__position_choices_sorted(_MoveNodeForm__position_choices_unsorteddeclared_fieldschoicesmk_dropdown_treer   	formfield	to_pythonintcoercer'   updatesuper__init__)r   r+   r,   r-   r.   r/   r0   r1   r2   r    kwargsoptschoices_sort_moder;   pkFormFieldinitial_r7   r%   r&   rC   R   s2   




zMoveNodeForm.__init__c                 C   sX   d}d| j v r| j d dkr| j d }| rt|}| j d= | j d }| j d= ||fS )z4 delete auxilary fields not belonging to node model Nr   0r   )cleaned_dataisdigitr?   )r   reference_node_idposition_typer%   r%   r&   _clean_cleaned_datay   s   


z MoveNodeForm._clean_cleaned_datac                    s   |   \}}| jjjr2|r'| jjjj|d}|j| jd| _| jj	||d n7| jjj
| jd| _n,| j  |rK| jjjj|d}| jj	||d n| jrQd}nd}| j	| jj | | j  t j|d | jS )N)r   )r    )posr   zfirst-sibling)commit)rO   r    _stateaddingr3   r4   objectsget	add_childmoveadd_rootsaver   get_first_root_noderefresh_from_dbrB   )r   rQ   rN   rM   reference_noderP   rI   r%   r&   rY      s,   




zMoveNodeForm.savec                 C   s    | d ur|| k p| | S dS )NT)is_descendant_of)r*   possible_parentr%   r%   r&   is_loop_safe   s   zMoveNodeForm.is_loop_safec                 C   s   d| d  S )Nz&nbsp;&nbsp;&nbsp;&nbsp;   r%   )levelr%   r%   r&   	mk_indent   s   zMoveNodeForm.mk_indentc              	   C   sN   |  ||r#||D ]\}}||jt| | t| f qdS dS )z! Recursively build options tree. N)r_   get_annotated_listappendr   r   rb   	get_depthr   )clsr*   nodeoptionsitem_r%   r%   r&   add_subtree   s
   (zMoveNodeForm.add_subtreec                 C   s.   dt dfg}| D ]	}| ||| q|S )z% Creates a tree-like list of choices Nz
-- root --)rj   get_root_nodesrk   )rf   r4   r*   rh   rg   r%   r%   r&   r<      s   zMoveNodeForm.mk_dropdown_tree)T)N)__name__
__module____qualname____doc__rj   r8   r9   r   ChoiceFieldr   r   r'   r   rC   rO   rY   staticmethodr_   rb   classmethodrk   r<   __classcell__r%   r%   rI   r&   r      s4    




'


r   Nc                 C   s   t | |}t| |||||S )ad  Dynamically build a MoveNodeForm subclass with the proper Meta.

    :param Node model:

        The subclass of :py:class:`Node` that will be handled
        by the form.

    :param form:

        The form class that will be used as a base. By
        default, :py:class:`MoveNodeForm` will be used.

    :return: A :py:class:`MoveNodeForm` subclass
    )_get_exclude_for_modeldjango_modelform_factory)r4   formfieldsexcludeformfield_callbackwidgets_excluder%   r%   r&   movenodeform_factory   s   
r}   c                 C   sT   |rt |}nd}t| tr|d7 }|S t| tr|d7 }|S t| tr(|d7 }|S )Nr%   )	sib_orderparent)depthnumchildpath)r   lftrgttree_id)tuple
issubclassr	   r
   r   )r4   ry   r|   r%   r%   r&   ru      s   



ru   )rp   djangor   django.db.models.queryr   django.forms.modelsr   r   rv   django.utils.htmlr   django.utils.safestringr   django.utils.translationr   rj   treebeard.al_treer	   treebeard.mp_treer
   treebeard.ns_treer   	ModelFormr   r}   ru   r%   r%   r%   r&   <module>   s"     3
