jdum / odfdo

python library for OpenDocument format (ODF)
Apache License 2.0
58 stars 11 forks source link

Default Paragraph is inserted into body before any other element #15

Closed telkamp closed 3 years ago

telkamp commented 3 years ago

In my code at the bottom of this issue I'm appending an image_frame directly to the body of the document. When Iopen the resulting odt file in LibreOffice, the image is not shown, because odfdo inserts a paragraph before the draw:frame element

<text:p text:style-name="Standard"/>
<draw:frame draw:style-name="fr1" draw:name="Bild1" text:anchor-type="page" text:anchor-page-number="1" svg:x="3cm" svg:y="3cm" svg:width="4.001cm" svg:height="2.379cm" draw:z-index="0">
  <draw:image xlink:href="Pictures/10000000000001D800000119335792A6F1966427.png" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" draw:mime-type="image/png"/>
</draw:frame>

I suggest that the default paragraph should be inserted behind the elements appended to the body. Workaround: When I remove the default paragraph, the image will be shown in LibreOffice:

# Remove Standard paragraph before draw:frame
p = body.get_paragraph()
if not p==None:
  body.delete(p)

Python code to append an image_frame directly to the body of the document

from odfdo import Document, Paragraph, Frame, Style
doc = Document("text")

doc.insert_style(Style(name="fr1", family="graphic", parent_style="Graphics", vertical_pos="from-top", vertical_rel="page", 
                       horizontal_pos="from-left", horizontal_rel="page"), automatic=True)

body = doc.body
uri = doc.add_file("10000000000001D800000119335792A6F1966427.png")
image_frame = Frame.image_frame(uri, size=("4cm", "2.38cm"), anchor_type="page", anchor_page=1, position=("14.7cm", "1.23cm"), style="fr1")
body.append(image_frame)

doc.save(target='test_picture.odt', pretty=True)
jdum commented 3 years ago

Thx for the report. The proposed way to insert an image in odfdo is to put the image inside a paragraph. See how_to_add_a_picture_to_a_text_document.py :

image_frame = Frame.image_frame(uri, size=("6cm", "4cm"), position=("5cm", "10cm"))
# put image frame in a paragraph:
para = Paragraph("")
para.append(image_frame)
body.append(para)

However, I don't remember if it is a requirement of ODF standard or for compatibility with some text processors, I'll check this.

jdum commented 3 years ago

The reason to put the frame inside a paragraph is probably to permit to edit the document, especially allowing to change the anchor to either paragraph or page.

telkamp commented 3 years ago

Thank you for your response! I can confirm that my example works when I insert the image into the paragraph instead of the document's body. BTW, LibreOffice inserts the image into the document's body. But the result is the same.