U
    Įwh                     @   s   d dl Z d dlZd dl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Zd dlZd dlT d dlmZ d	Zd
Zee ZdZdZG dd dZdS )    N)Path)TemporaryDirectory)Dict)parse)datetime)*)RFilei  i  gHzG?100%c                   @   s  e Zd ZdZddddddgZeedd	d
ZedddZedddZ	eedddZ
eeedddZeeedddZedd ZedddZdnddZeddd d!Zeedd"d#Zd$d% Zddd&d'Zed(d) Zddd*d+Zeddd,d-Zeddd.d/Zeeeed0d1d2Zeedd3d4Zeed5d6d7Zeeedd8d9d:Zeeedd;d<d=Zeedd>d?d@ZeeddAdBdCZ eeddDdEdFZ!dddGdHZ"eeeeddIdJdKZ#doeeeedMdNdOZ$edpeeeeedPdQdRZ%eeedSdTdUZ&eddVdWZ'dXdY Z(dZd[ Z)d\d] Z*edd^d_Z+e,d`da Z-edqeddbdcZ.drdedfZ/ee0dgdhdddidjdk Z1ee0dgdhdddidldm Z2dS )sCmfPluginConvertMixinuO   
    Используется в классах CmfDocument, CmfAttachment
    save_to_pdfsave_to_docxexport_to_docxexport_to_pdfexport_obj_list_to_pdfexport_tree_to_pdf)content	extensionc              	   C   sp   ddl m} || jj d| j  d| }tjtj	|d}|
  |  W 5 Q R X |j|dd |jS )up  
        Метод сохраняет файл директорию объекта и возвращает путь для скачивания
        :param content: Контент в байт
        :param extension: Расширение файла
        :return: file_path: Строка пути с кодированием символов для URL
        r   )cmfutil_.parentnameF)make_preview)Zcmf.utilr   Ztranslit_stripr   valuecodemodelsCmfAttachmentgcurrent_userdisable_aclsaveZupload_fileurl)selfr   r   r   	file_name
attachment r&   +./common/models/cmf_plugin_convert_mixin.py_save_export_file'   s    $
z'CmfPluginConvertMixin._save_export_file)returnc                 O   sD   t d |  }| t|dddd}| |dd}| |d}|S )	u   
        Сохраняет HTML -> PDF
        Используется преобразование через DOCX, из-за этого нет разрыва страниц.

        :return: Данные pdf в виде строки base64
        !   УСТАРЕВШАЯ ВЕРСИЯutf-8encoding.htmldocx:MS Word 2007 XML.docxpdf:writer_pdf_Exportpdf	cmf_alert_handle_htmlobj_to_formatbytesr(   )r#   argskwargshtml
docx_bytes	pdf_bytesurl_file_pathr&   r&   r'   r   9   s    z!CmfPluginConvertMixin.save_to_pdfc                 O   s6   t d |  }| t|dddd}| |d}|S )uu   
        Сохраняет HTML -> DOCX

        :return: Данные docx в виде строки base64
        r*   r+   r,   r.   r/   docxr3   )r#   r8   r9   r:   r;   r=   r&   r&   r'   r   I   s
    z"CmfPluginConvertMixin.save_to_docx)	html_textr)   c           	   
   C   s~   ddl m} ddlm} | }| }t J}| ||}||| t }|	| |
d | W  5 Q R  S Q R X dS )ud   
        Преобразует HTML -> DOCX

        :return: Данные в байтах
        r   )Document)
HtmlToDocxN)r>   r@   ZhtmldocxrA   r   _handle_view_htmlZadd_html_to_documentioBytesIOr!   seekgetvalue)	r#   r?   r@   rA   ZdocumentZ
new_parsertmp_dir_namer:   	docx_filer&   r&   r'   html_to_docxW   s    

z"CmfPluginConvertMixin.html_to_docx)r   r)   c                 C   s   t |  S )up   
        Преобразует байты в строку base64

        :return: Строка base64
        )base64Z	b64encodedecode)r   r&   r&   r'   _get_base64k   s    z!CmfPluginConvertMixin._get_base64)r   r)   c                 C   s   |  dr(td t|  dd }n\|  drPt|  ddt t }n4|  drtt|  ddt }ntdt t }|S )u?  
        Метод масштабирует значение ширины под формат А4 и переводит его в пиксели
        :param value: Строка значения ширины в % или пикселях
        :return: pixels: Число с плавающей точкой
        %d    ptpx)endswithA4_PAGE_WIDTH_PXfloatstripreplacePT_TO_PXSCALE_A4)r   Zpixelsr&   r&   r'   _get_value_in_pixelst   s    


z*CmfPluginConvertMixin._get_value_in_pixelsc                 C   s   | j dr| j dsdS t| j d dd}t| j d dd}||kr|| }|d }| d| j d< ||  d| j d< dS )u   
        Метод масштабирует изображение под ширину ячейки таблицы
        :param img: Тег изображения
        :param cell_width: Ширина ячейки
        widthheightNrQ   rO   g)\(@)attrsgetrT   rU   rV   )imgZ
cell_widthZ	img_widthZ
img_heightproportion_ratior&   r&   r'   _auto_size_img_for_cell   s    z-CmfPluginConvertMixin._auto_size_img_for_cellc                 C   s  |   }|jddD ]}||d q|dD ]"}t|jdk r4||d q4| | | | | 	| | 
| | | | | | | |jddd}|jd	d
d}d|_|d|d |j|jddd |j| ||d |j| t|S )u   
        Обработка страницы html для сохранения

        :param html_text: Страница html
        :return: Обработанная страница html
        spoiler-iconclass_p   brr:   zru-RU)langstyletext/csstypea  
        @page { size: 21.0cm 29.7cm; margin: 1cm }
        body {
            font-family: Arial, Helvetica, FreeSans, 'Liberation Sans', sans-serif;
            font-size: 10pt;
            line-height: 1.2;
        }
        td { page-break-inside: avoid !important; }
        tr { page-break-after: avoid !important; }
        td p { margin-top: 0.2cm; margin-bottom: 0.2cm }
        r   headmetazUTF-8)charsetbody)handle_include_pagefind_allreplace_withnew_taglencontentsappend_handle_html_card_preview_handle_html_svg_to_png_handle_html_img_handle_html_infopanel_handle_html_layout_handle_html_table_handle_html_cleanstringinsertrl   ro   str)r#   soupspanrd   r:   rh   r&   r&   r'   r5      s,    






z"CmfPluginConvertMixin._handle_htmlNc           
      C   s   ddl m} |dkrt }| dg | jjr6| jjnd}||d}|}|| jj |jddD ]V}|j	
d	}|r||krtjj
|d
}|r||}	||	 q|  qb|  qb|S )u  
        Подгружает html text из Include страницы
        :param parent_pages: ID родителей страницы для проверки на зацикливание
        :return: bs4.BeautifulSoup soup: Объект библиотеки
        r   BeautifulSoupNtext_renderrO   html.parserzmacros-include-pagerb   zdata-param-pageid)id)bs4r   setload_fieldsr   r   addr   rq   r\   r]   r   CmfDocumentrp   rr   	decompose)
r#   Zparent_pagesr   r?   r   ZpagesZinclude_pageZpage_idZinclude_documentZinclude_htmlr&   r&   r'   rp      s$    



z)CmfPluginConvertMixin.handle_include_pagec                 C   s   | j ddD ]z}|d}d|jd< |jdd| d}|jdd| d}| d}|| || || || qd	S )
u  
        Метод парсит DIV вложения и оставляет в нем только нужные теги: изображение, имя файла и дата

        :param bs4.BeautifulSoup soup: Объект библиотеки
        zapp-tinymce-card-previewrb   r^   Z150pxrZ   zapp-tinymce-file-name-viewdivzapp-tinymce-file-create-viewN)rq   findr\   wraprs   rv   rr   )r   Zpreviewr^   r$   Zfile_creater   r&   r&   r'   rw      s    





z/CmfPluginConvertMixin._handle_html_card_previewc                 C   sR   | j ddd}|D ]:}|jddd}|r| d}|t|j || q| S )uq   
        Метод очищает markdown макрос от лишних тегов для libreoffice
        r   zmacros-panel wikimarkdownrb   zbody-previewrd   )rq   r   rs   extendlistru   rr   )r   Zmacros_panelspanelZpreview_divZnew_pr&   r&   r'   _handle_html_markdown   s    
z+CmfPluginConvertMixin._handle_html_markdownc              	   C   s  ddl }ddlm} |dD ]}zhd}|jdd }rz|jd}dd	d
| jjgdd
| dgg}t	j
j|dgd}|r|jd|jjd}	n|jd}
|jd}|jd}|r| }|d |jd< |d |jd< d}|jdt|idD ](}|jd}d}t||||jd< q|jt|d}| |}|
rH|sb|t|}	|	j\}
}|jdd| t|
t|d}	||	 W q tk
r   dt| }t| Y qX qdS )ud  
        Метод заменяет тег SVG тегом IMG с изображением в PNG.
        Конвертирует SVG в PNG, если SVG в диаграммах DrawIO, то сначала пытается найти готовый PNG диаграммы
        :param bs4.BeautifulSoup soup: Объект библиотеки
        r   NImagesvgzdrawio-contentrb   zdata-drawio-titleZANDZ	parent_id==r   z.pngr"   filterfieldsr^   )srcrZ   r[   viewbox      z"rgb\((\d+)[\s,]+(\d+)[\s,]+(\d+)\)fillr\   zrgb(\1, \2, \3))Z
bytestringzdata:image/png;base64,)r   rZ   r[   u3   Не удалось заменить SVG на PNG: )cairosvgPILr   rq   find_parentr\   r]   r   r   r   r   rs   r"   splitrecompilesubZsvg2pngr   rL   openrC   rD   sizerr   	Exceptionlogging	exception)r#   r   r   r   r   r%   ZdrawioZdrawio_titler   r^   rZ   r[   r   Zsvg_sizepatternZtag_with_fillZrgbreplZimg_byteZ
img_base64err_msgr&   r&   r'   rx     sH     

 z-CmfPluginConvertMixin._handle_html_svg_to_pngc           "      C   s  ddl m} ddl}| h}|dD ]T}|jd}|jd}|rtdd|	d	d
}|
drtd t|	dd }nt|}|rtdd|	d	d
}|
drtd t|	dd }nt|}|jd}|sq*|dtj s|dtj dr:|	dtj d}|	dtj dd}|dsR|dr|jd}	|	dd}t|}
t|
j}|	rtjj|	dgd}n*ddd|gdd|
jgg}tjj|dgd}|rt|j}nt|	dtj}| s ttjd }z\||}|j\}}t|d4}| | }|j  }d| d| |jd< W 5 Q R X W n8 t!k
r   |"|j# t$%d | d! Y q*Y nX |d"rzt&j|d#d$}|j'd%kst(d&|j' ||)d
d' d }|d(krd)}| |j*}d| d| |jd< t| d*t+, d+d
| }t|d,}|-|j* W 5 Q R X ||}|j\}}W nh t!k
r } zH|.d-}d.d/i|_d0|_/|"| t$%d1 t0d2|  W Y q*W 5 d}~X Y nX |d3rz6td4d|}t12|}|t34|}|j\}}W nh t!k
r~ } zH|.d-}d.d/i|_d0|_/|"| t$%d5 t0d6|  W Y q*W 5 d}~X Y nX |r|s|| }|| }|r|s|| }|| }|s|s|}|}|| }|t5 }|| }|t6ks|dkr|rt6| nd'}t6}|t7|9 }| d7|jd< | d7|jd< |d.r*d8|d. kr*|j.d9d:d;} |j.d<|j}!| 8|! |"|  q*W 5 Q R X dS )=u#  
        Метод заменяет адрес картинки на base64 и масштабирует размер изображения под формат А4 относительно исходного

        :param bs4.BeautifulSoup soup: Объект библиотеки
        r   r   Nr^   rZ   r[   z[^0-9|%|\.]rO   ,r   rM   rN   r   zhttps://zhttp://z:8080/z	files/objzdata-attach-idz%25r   )r   r   ORr"   r   r   /files/common/static/file-outline.pngrbdata:image/z;base64,u	   Файл u/    не является изображениемhttp)re      )timeout   u2   Код статуса ответа сервера re   )ZpngZbmpZgifZtiffZtifZjpegZjpgz/imgz%Y%m%d-%H%M%Szwb+rd   rh   z0color: red; font-style: italic; font-size: 10pt;u?   Не удалось отобразить изображениеuL   Не удалось скачать изображения документаuN   Не удалось скачать изображения документа: 
data:imagez^data:image/.+;base64,uG   Не удалось конвертировать изображениеuI   Не удалось конвертировать изображение: rQ   zmargin-left: auto;r   z text-align: center; width: 100%;rh   )r^   )9r   r   tempfiler   rq   r\   r]   r   r   rV   rR   WEB_PAGE_WIDTH_PXrT   
startswithconfigZAPP_FQDNr   urlparseunquotepathr   r   r   full_path_file
UPLOAD_DIRexistsPROJECT_DIRr   r   rL   readformatlowerr   rr   r   r   r   requestsstatus_codeAssertionErrorrfindr   r   Znowwriters   r~   r4   rJ   	b64decoderC   rD   rX   rS   absrv   )"r#   r   r   r   tmp_dirZimg_tagrZ   r[   r   Z	attach_idr"   Zurl_path_unquoter%   Z_filterZattach_pathr^   Zwidth_originalZheight_originalZattachment_byteZattach_base64Z	mime_typeresZextension_imgZ	file_pathfpeZtag_iZimg_base64_dataZimg_byte_dataZscaler_   coefficientZimg_wrapperZ	clone_imgr&   r&   r'   ry   >  s    

*




$











 
z&CmfPluginConvertMixin._handle_html_imgc                 C   s  | j ddD ]t}| jddddd}|jd}|dkrDd	|jd
< nb|dkrXd|jd
< nN|dkrld|jd
< n:|dkrd|jd
< n&|dkrd|jd
< n|dkrd|jd
< || jddd |j| jdddd |jdd}|dk	r|jrd|jjd< d|jjd< |jj	|jd g |jd!d}| jddd"d}| jd#d$d%d&}|	d'd( |j
D  |	|g |j	|g || qdS ))u   
        Подменяет инфопанели. Создает панели в виде table вместо div
        :param bs4.BeautifulSoup soup: Объект библиотеки
        :return:
        zak-editor-panelrb   tabler	   0)rZ   cellpaddingcellspacingzdata-panel-typeZnotez/background: #eae6ff; border: none; padding: 0cmrh   infoz/background: #deebff; border: none; padding: 0cmsuccessz/background: #e3fcef; border: none; padding: 0cmalarmz/background: #feece5; border: none; padding: 0cmerrorZwarningz/background: #fffae6; border: none; padding: 0cmtrzbackground: transparentr   tdtopz1width: 36px; orphans: 0; widows: 0; margin: 0.2cm)Zvalignrh   zak-editor-panel__iconNZ	absmiddleZalignborder zak-editor-panel__contentz$orphans: 0; widows: 0; margin: 0.2cmZfont3zfont-size: 12pt)r   rh   c                 S   s   g | ]}|d kr|qS )
r&   ).0r   r&   r&   r'   
<listcomp>  s      z@CmfPluginConvertMixin._handle_html_infopanel.<locals>.<listcomp>)rq   rs   r\   r]   rv   r   r   r^   r   r   ru   rr   )r   r   r   Z
panel_typeZiconZpanel_contentZtd_tagZtag_fontr&   r&   r'   rz     s>    
z,CmfPluginConvertMixin._handle_html_infopanelc                  C   s  dd l }dddddddd	d
ddddddddddd}|dD ]n}i }|jddd}|rd|| |dddD ]&}|rv|d\}}	|	 || < qv|dr|ddtkr|dt}
|dttkr|
|d< n
t |d< d|d< |dsd |d< |d!sd |d!< |d"s,d#|d"< |d$sH|d$d%|d$< i }|j	d k	rfg }| 
|d}
t|j	d&}t|j	jd'd(D ]\}}i }t||jjsq|jdddD ]*}|r|d\}}	|	 || < q|d }	r| 
|	}|||< |
|8 }
nd ||< || qt|dkr\|
t| }|D ]}|||< qL|j	  tt| }|d)D ]*}d'}d}| 
|d}
|d*d+gD ]}i }d,|d"< |d-r|jd-}|||d.< |dddD ]*}|r|d\}}	|	 || < q|tkr2d/}n|s`|dpL|d }r| 
|}np||}|d0}|r|rt|d' t|| D ]"}||kr q||| 7 }q|t|7 }n|d'7 }|rF| }d1}|D ](}|jrt|jd2kr|} qq| d3|d< |
|8 }
|d4D ]}| || q0n|d'7 }q|dkr|
| }|jd*dd id5D ]2}| d3|d< |d4D ]}| || qqvqq>d S )6Nr   z#e3fcefz#e6fcffz#b3d4ffz#fffae6z#feece5z#eae6ffz#f4f5f7z#b3f5ffz#abf5d1z#ffc400z#fff0b3z#ffbdadz#c0b6f2z#b3bac5z#4c9affz#79e2f2z#57d9a3z#ff8f73z#998dd9)zLight greenz
Light tealZBluezLight yellowz	Light redzLight purplez
Light grayZTealZGreenzDark yellowZYellowZRedZPurpleZGrayz	Dark Bluez	Dark tealz
Dark greenzDark redzDark purpler   r   ztableView-content-wraprb   rh   rO   ;:rZ   r   r   r   Zbordercolorz#eeeeeer   1colre   )startr   r   thZnonezdata-highlight-colorZbgcolor   colspan
   z[<br/>]rQ   r^   r   )r   rq   r   rr   r]   r   rU   FULL_SCREEN_VALUErS   ZcolgrouprY   rt   	enumeratechildren
isinstanceelementTagr\   rv   r   roundsumvaluesZhas_attrrangeintru   r   r`   ) r#   r   r   Zcell_colorsr   Zstyle_table_dictr   paramsr   r   Ztable_widthZ
cols_widthZcol_without_widthZ	col_countZcol_numr   Zstyle_col_dictZwidth_pxcZcols_sumr   	nums_colsZ
table_cellZtd_styleZtable_cell_color_nameZtd_widthr   iZtable_cell_childrenZtable_cell_widthZtable_cell_childr^   r&   r&   r'   r|     s    











z(CmfPluginConvertMixin._handle_html_tablec                    s   ddl m  | dddiD ]}d|d< d|_| d	} fd
d|jD }t|}td| d}|D ]*}d|_|d| d|d< |	| qf|	| qdS )u   
        Функция добавляет стиль для макета, используем table, так как flex не поддерживается в LibreOffice

        :param bs4.BeautifulSoup soup: Объект библиотеки
        r   r   r   zdata-layout-sectiontruer	   rZ   r   r   c                    s   g | ]}t | r|qS r&   )r   r   elr  r&   r'   r     s     
 z=CmfPluginConvertMixin._handle_html_layout.<locals>.<listcomp>rN   r   r   zdata-column-widthrM   N)
r   r   rq   r   rs   r   rt   r   r]   rv   )r   Zlayoutr   columnsr   Zwidth_columncolumnr&   r  r'   r{   ~  s    
z)CmfPluginConvertMixin._handle_html_layoutc                 C   s"   | j ddgdD ]}|  qdS )u   
        Метод очищает HTML от лишних тегов

        :param bs4.BeautifulSoup soup: Объект библиотеки
        ztable-context-menuzcell-dropbox-buttonrb   N)rq   r   )r   tagr&   r&   r'   r}     s    z(CmfPluginConvertMixin._handle_html_clean)r?   tmp_pathr)   c           !   
   C   s  ddl m}m} ddlm} || }g }|dD ]>}d|jddkrZ|t	|dd	 |jd
s2d|jd
< q2|dD ]}|t	|dd	 q||dD ]}|
  q|dD ]}|
  qt|D ]\}}	|	d }|jdd}
|jdd}|jd}|dr|d\}}|dd}|dd}t|d| d|  }t|d$}|t| t||jd< W 5 Q R X |dr
t|}tjjddtjgdgd}|rt|j}nt|dtj}| r
t||jd< |
s
||}|j\}
}d}tdd d! t|
D }|d"rBttj d# }|!d$d%kr\t"|n|!d$}||!d| }t#|}|j$d&kr4t|}|d'| |  % }t|d}||j& W 5 Q R X z>||}|j\}
}t||jd< |r|n|
r|
n|}W n$ |k
r0   t||jd< Y nX nt||jd< ||krP|n|}|r|| rj|| nd(}||jd< tdd)d! t|D } t| | |jd< qt|S )*u   
        Функция заменяет адрес картинки, файла на фактический

        :return: HTML с фактическими адресами картинок, файлов
        r   )r   UnidentifiedImageErrorr   azcmf-fileclassrO   file)objrk   Zhrefr^   Zimagerh   titler  rZ   r[   r   r   r   r   z;base64Zfile_r   wbr   r"   r   r   r   i  c                 s   s   | ]}|  r|V  qd S Nisdigitr  r&   r&   r'   	<genexpr>  s      z:CmfPluginConvertMixin._handle_view_html.<locals>.<genexpr>r   r   ?r   Zname_re   c                 s   s   | ]}|  r|V  qd S r  r  r  r&   r&   r'   r    s      )'r   r   r	  r   r   rq   r\   r]   rv   dictr   r   r   r   rV   r   r   r   rJ   r   r   r   r   r   r   r   r   r   r   r   r   joinr   r   rt   r   r   resolver   )!r?   r  r   r	  r   r   filesr  indexZ_filerZ   r[   Zfull_urlZtype_imgZb64dataZ	name_fileZfile_imgZurl_pathr%   Zattachment_pathr^   Zwidth_defaultZwidth_valueZpath_defaultZend_nameZfile_extensionZresponser   filepathr  Z	width_newr   Zheight_valuer&   r&   r'   rB     s    





"



z'CmfPluginConvertMixin._handle_view_htmlc              
   C   s  ddl m}m} ddlm} tjd||fd}tj	tj
tjtdd}tj
|ddd	d
dd}| }d|_|  |dd| |d ||}|dD ]}	d|	jd< q|dD ]}	d|	jd< d|	jd< qt 0}
|| | |
 t| W  5 Q R  S Q R X dS )uw   
        Конвертирует HTML -> PDF

        :return: Возвращает байты PDF файла
        r   )FPDF	HTMLMixinr   	_HTML2PDF)basesz..modulesZappZassetsZfontsz	noto-sanszNotoSans-Regular.ttfr+   ZNotoSansrO   r   r	   rZ   r   Z100r   r   N)Zfpdfr  r  r   r   types	new_classosr   abspathr  dirname__file__Zcore_fonts_encodingZadd_pageZadd_fontZset_fontZfindAllr\   r   Z
write_htmlrB   Zprettifyr7   output)r#   r?   r  r  r   r  Z	path_fontr2   r   r  rG   r&   r&   r'   html_to_pdf  s&     

z!CmfPluginConvertMixin.html_to_pdf)	path_docxr)   c              
   C   sH   ddl m} tj|rDt|d}||}|jW  5 Q R  S Q R X dS )u7   
        Конвертирует DOCX -> HTML
        r   )convert_to_htmlr   N)Zmammothr*  r#  r   r   r   r   )r#   r)  r*  rH   resultr&   r&   r'   docx_to_html  s
    z"CmfPluginConvertMixin.docx_to_html)path_imgr<   r)   c                 C   s   t | | dS u5   
        Конвертирует PDF -> PNG
        N)r   pdf_bytes_to_imgr-  r<   r&   r&   r'   r/  %  s    z&CmfPluginConvertMixin.pdf_bytes_to_img)path_pdfr-  r)   c                 C   s   dS r.  r&   )r1  r-  r&   r&   r'   
pdf_to_img,  s    z CmfPluginConvertMixin.pdf_to_img)	path_htmlr-  r)   c              	   C   sB   t j|r>t|d"}| | }| j||d W 5 Q R X dS )u6   
        Конвертирует HTML -> PNG
        rr0  N)r#  r   r   r   r(  r   r/  )r#   r3  r-  	file_htmlr<   r&   r&   r'   html_to_img4  s    z!CmfPluginConvertMixin.html_to_img)	path_xlsxr3  r)   c                 C   s   ddl m } ||| dS )u7   
        Конвертирует XLSX -> HTML
        r   	xlsx2htmlNr8  )r#   r7  r3  r9  r&   r&   r'   xlsx_to_html=  s    z"CmfPluginConvertMixin.xlsx_to_html)r-  path_pngr)   c                 C   s$   ddl m} ||}|| dS )u<   
        Сохранение в формате PNG
        r   r   N)r   r   r   r!   )r#   r-  r;  r   r^   r&   r&   r'   save_imgE  s    
zCmfPluginConvertMixin.save_imgc              
      s  ddl m} ddlm} ddlm  ddlm ||ddd}| }| }tt	|D ]}|
|| }	|dkr|j}
|| |
_n|j|| d}
|	jD ]*}|\}}}}|
j|d	 ||d	 |d
 q fddt|	jD ],}|
fdd|	j||	|dD  qqZ|| dS )u6   
        Конвертирует XLS -> XLSX
        r   )workbook)open_workbook)XL_CELL_DATE)xldate_as_tupleT)Zformatting_infoZragged_rows)r  re   )Z	start_rowZend_rowZstart_columnZ
end_columnc                    sJ   | j }| j krF|d}|dd dkr>tj|dd   }nt| }|S )Nr   r   )r   r   r   )r   Zctyper   time)cellr   Zdatetime_tup)r?  r@  r&   r'   _get_xlrd_cell_valueh  s    

z?CmfPluginConvertMixin.xls_to_xlsx.<locals>._get_xlrd_cell_valuec                 3   s   | ]} |V  qd S r  r&   )r   rB  )rC  r&   r'   r  s  s   z4CmfPluginConvertMixin.xls_to_xlsx.<locals>.<genexpr>)Zend_colxN)Zopenpyxlr=  Zxlrdr>  r?  r@  ZWorkbooksheet_namesr   rt   Zsheet_by_nameZactiver  Zcreate_sheetZmerged_cellsZmerge_cellsZnrowsrv   Z	row_sliceZrow_lenr!   )r#   Zpath_xlsr7  r=  r>  Zbook_xlsZ	book_xlsxrD  Zsheet_indexZ	sheet_xlsZ
sheet_xlsxZcrangeZrloZrhiZcloZchirowr&   )r?  rC  r@  r'   xls_to_xlsxN  s2    
 
z!CmfPluginConvertMixin.xls_to_xlsx)dataoutput_pathsuffixr)   c                 C   s   dS )u(  
        Конвертация данных в PDF через libreoffice
        :param data: Данные файла в виде байт
        :param output_path: Путь сохранения итогового pdf файла
        :param suffix: Расширение файла
        Nr&   )rG  rH  rI  r&   r&   r'   
obj_to_pdfy  s    	z CmfPluginConvertMixin.obj_to_pdfrO   )rG  rI  mimetyper)   c              
   C   sZ  ddl }ddlm} | ||d|}| @}t|d }t|d}	|	| | t	|}
W 5 Q R X W 5 Q R X |j
|
ddd	d
}|dd}||}|d}|rR|d}|rR| }|jddD ]}|dd}d}|d D ]T}|d| }|||d d d }|||d d }|||| 7 }q||  |d< qt	|S )u  
        Конвертация данных в HTML через libreoffice

        :param data: Данные файла источника в виде байт
        :param suffix: Расширение файла источника

        :return: Строка HTML
        r   Nr   r:   z	file.htmlr  ignore)errors u   �u   rO   rl   rh   Trb   r  r   {re   })r   r   r   r6   r   r   r   r   get_encoding_typer   rK   rV   r   Zget_textrq   r]   )r#   rG  rI  rK  r   r   Z
bytes_htmlr  Zfull_path_htmlr5  r-   r?   r   rl   rh   Z
style_textr  	style_tagZstyle_classZ	class_tagZstart_pos_classZstyle_startZ	style_endr&   r&   r'   obj_to_html  s4    	

"

z!CmfPluginConvertMixin.obj_to_html)rG  rI  	to_formatrK  r)   c              
   C   sH   zt | |||}W n. tk
rB } zt|  W 5 d}~X Y nX |S )u*  
        Конвертация данных в HTML через libreoffice
        :param data: Данные файла в виде байт
        :param suffix: Расширение файла
        :param to_format: Формат файла который хотим получить
        N)r   r6   r   r   debug)rG  rI  rT  rK  Zconverted_dataerrr&   r&   r'   r6     s    
z#CmfPluginConvertMixin.obj_to_format)	path_filer)   c              
   C   s   ddl m} | }t| d8}|D ]$}|| |jr"|jdr" qHq"|  W 5 Q R X |jd}|sddddd	d
dg}|D ]d}zFtj| d|d,}|	  |
d |}W 5 Q R  W  qW 5 Q R X W q tk
r   d}Y qX q|S )u   
        Определяем кодировку файла

        :param path_file: Путь к файлу
        :return: Кодировка файла
        r   )UniversalDetectorr   r-   r+   zwindows-1251zwindows-1250zwindows-1252asciiz
iso-8859-1latin1r4  r,   )Zchardet.universaldetectorrX  r   ZfeedZdoner+  r]   closerC   	readlinesrE   UnicodeDecodeError)rW  rX  Zdetectorr  liner-   	encodingsZformat_encodingr&   r&   r'   rQ    s*    

z'CmfPluginConvertMixin.get_encoding_typec                 C   s
  ddl m} | dg || jjp$d}|d}|jddd}d	|_|jd| |jj	
| |jd
dD ]}||d qn|dD ]"}t|jdk r|
|d q| | | | | | | | | | | | | | | | t|S )Nr   r   r   <p></p>rl   rh   ri   rj   zg@page { size: 21.0cm 29.7cm } td,th { padding: 0.45cm; } td p,th p { margin: 0;word-break: break-all; }ra   rb   rd   re   rf   )r   r   r   r   r   rs   r~   r:   r   rl   rv   rq   rr   rt   ru   rw   r   rx   ry   rz   r{   r|   r}   r   )r#   r   r   head_tagrR  r   rd   r&   r&   r'   prepare_document_to_docx  s,    








z.CmfPluginConvertMixin.prepare_document_to_docxc                 C   s"   |  dg | jrtddd d S )Nperm_encryptu`   Зашифрованный документ не может быть экспортирован.T)abort)r   rc  r4   )r#   r&   r&   r'   check_encrypt   s    z#CmfPluginConvertMixin.check_encryptc                 C   sD   |    |  }| t|dddd}| |dd}| |d}|S )Nr+   r,   r.   r/   r0   r1   r2   re  rb  r6   r7   r(   )r#   prepared_htmlr;   r<   r=   r&   r&   r'   r     s    z#CmfPluginConvertMixin.export_to_pdfc                 C   s6   |    |  }| t|dddd}| |d}|S )Nr+   r,   r.   r/   r>   rf  )r#   rg  r;   r=   r&   r&   r'   r     s
    z$CmfPluginConvertMixin.export_to_docxc                 C   sz   |  ddg ddlm} || jjp&dd}|d}| jj|_|d| | 	| |jdd	d
id}|
| t|S )Nr   Zprojectr   r   r`  r   Zh1r   rh   zpage-break-after: always;r   )r   r   r   r   r   rs   r   r~   r   ry   rv   r   )r#   r   r   Zname_tagZ	break_tagr&   r&   r'   prepare_document_to_export  s    



z0CmfPluginConvertMixin.prepare_document_to_exportc           
      C   st   dg}|D ]d}t |}dd | D }|D ]@}t|d,}| }|d}	||	_|jj|	 W 5 Q R X q,q
|S )Nz&/opt/eva-app/dist/cmf-angular/tinymce/c                 S   s"   g | ]}t |d rt |qS )z.css)r   rR   )r   css_filer&   r&   r'   r   +  s      z:CmfPluginConvertMixin._append_css_tags.<locals>.<listcomp>r4  rh   )	r   iterdirr   r   rs   r~   r:   rl   rv   )
clsr   ZfoldersZfolder_nameZfolderZcss_listri  r  ZcssZcss_tagr&   r&   r'   _append_css_tags&  s    
z&CmfPluginConvertMixin._append_css_tagsc              
   C   s  ddl m} dd l}t  tjd tjj	  W 5 Q R X || pHdd}|
d}|jd| |j
ddd	id
}|jj| tj|}d|jjjd< t }|sd}| d}| d| d}	t|d}
|
t| W 5 Q R X |jdddddd|	 | gdd}tjtj| dd}t|	d}|j|ddd |  W 5 Q R X t  tj| W 5 Q R X tjjtjd|ddd  W 5 Q R X d S )!Nr   r   i,  r`  Zlxmlrl   rm   rn   r+   r   z%mce-content-body mce-content-readonlyr  Zexportz/export.htmlr   z.pdfwZchromiumz
--headlessz--disable-gpuz--no-pdf-header-footerz--no-sandboxz--print-to-pdf=T)checkr   r   F)Zbackupr   u&   Закончен экспорт в PDFuf   Файл доступен для скачивания в разделе "Фоновые задачи".)Zpersonr   r  Zforce_notify_current_personmsg) r   r   
subprocessr   r    r   ZCmfDeferredJobZset_estimate_durationZdpZcommitrs   r:   r   rl   rv   r   rl  ro   r\   r   r   r   r   runr   r   r   Zupload_stream_filer!   Zset_result_attachmentZ	CmfNotifyZplace_notify)r:   r$   r   rp  r   ra  Zcharset_tagr   Zhtml_file_nameZpdf_file_namer  procZ
new_attachfr&   r&   r'   _export_html_to_pdf7  sV    




z)CmfPluginConvertMixin._export_html_to_pdfFc              	   C   s   d}|d krt  }|r(| g| j  }n
| j }t|dd d}t|D ]\}}|jdsj|jdrJ|jdrxqJ||krJ|| nqJ|jdrz|jdd	 ||	 7 }W n t
k
r   Y nX ||j|d
7 }qJ|S )NrO   c                 S   s
   | j  S r  )Zordernoload)xr&   r&   r'   <lambda>~      z;CmfPluginConvertMixin.collect_html_nested.<locals>.<lambda>)keyCmfDocument:z
CmfFolder:zCmfProject:TZTEXKOM_skip_failread_audit)	processed)r   Z
tree_nodesru  sortedr   r   r   r   _acl_check_readrh  CmfPermissionErrorcollect_html_nested)r#   export_selfr|  Z	html_bodyZnodesZsorted_nodesr   Znoder&   r&   r'   r  t  s.    

z)CmfPluginConvertMixin.collect_html_nestedu   Экспорт PDF-файлаT)descriptionZshow_bg_progressbarZ
system_jobc                 C   s,   t | }|jdd}tjj||jd dS )u\   
        Выгружает объект и всех его потомков в pdf
        T)r  )r$   N)r   get_obj_by_idr  r   r   rt  r   )obj_idr  Zhtml_nestedr&   r&   r'   r     s    
z(CmfPluginConvertMixin.export_tree_to_pdfc              	   C   sj   d}| D ]P}| dsqt|}|rz|jdd || 7 }W q tk
rV   Y qX qtj| dS )u   
        Выгружает все объекты из списка в pdf
        obj_list -- список id выгружаемых объектов
        rO   rz  Tr{  N)	r   r   r  r~  rh  r  r   r   rt  )Zobj_listr:   r  r  r&   r&   r'   r     s    

z,CmfPluginConvertMixin.export_obj_list_to_pdf)N)rO   )rO   )N)FN)3__name__
__module____qualname____doc__Zapi_methodsr7   r   r(   r   r   rI   staticmethodrL   rT   rY   r`   r5   rp   rw   r   rx   ry   rz   r|   r{   r}   rB   r(  r,  r/  r2  r6  r:  r<  rF  rJ  rS  r6   rQ  rb  re  r   r   rh  classmethodrl  rt  r  Zcmf_deferred_jobr   r   r&   r&   r&   r'   r
      s   	
2
!/ 
* 	[		+
(!#
<
"	r
   )rJ   ZhashlibrC   pathlibr   r   r   typingr   Zurllibr   r   r!  r   Zcmf.includerdiskr   r   rS   rX   rW   r   r
   r&   r&   r&   r'   <module>   s"   