Drawing a line in Writer fails after update

Hi all!

Merry Christmas!

Following example has worked until half a year ago.
Now it fails at “cursor.add(oShape)”.

The code draws a line in writer and saves the document.

Note: I am aware that there are some other ways to invoke and control LO.
I was like if it ain’t broke don’t try to fix it.

Best regards,
dr488

#!/bin/python
# -*- coding: utf-8 -*-
# coding: utf8

def rgb(r, g, b):
    return 256*256*r + 256*g + b

import sys
import os
import time
import codecs
from subprocess import call
import xml.etree.ElementTree as et
import argparse

import uno
import unohelper

from com.sun.star.beans import PropertyValue
from com.sun.star.awt import Size
from com.sun.star.awt import Point

localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext )

smgr = None
while smgr is None:
    try:
        os.system("libreoffice --headless --accept='socket,host=localhost,port=2002,tcpNoDelay=1;urp' --nodefault --nofirststartwizard --nolockcheck --nologo --norestore --invisible &")
        time.sleep(1)
        smgr = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager" )
    except:
        smgr = None
        os.system("killall soffice.bin 2>/dev/null &")

remoteContext = smgr.getPropertyValue( "DefaultContext" )
desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",remoteContext)
dispatcher = smgr.createInstanceWithContext("com.sun.star.frame.DispatchHelper", remoteContext)
doc = desktop.loadComponentFromURL( "private:factory/swriter","_blank", 0, () )
text = doc.Text
cursor = text.createTextCursor()

cLine = doc.createInstance( "com.sun.star.drawing.LineShape" )
ppbz_s = uno.createUnoStruct("com.sun.star.drawing.PolyPolygonBezierCoords")
ppbz_e = uno.createUnoStruct("com.sun.star.drawing.PolyPolygonBezierCoords")

oShape = doc.createInstance( "com.sun.star.drawing.PolyPolygonShape" )
oShape.LineStyle = 1
oShape.LineWidth = 200
oShape.LineColor = rgb(0,0,0)
pts = []
p1 = uno.createUnoStruct("com.sun.star.awt.Point")
p1.X = 1000
p1.Y = 1000
p2 = uno.createUnoStruct("com.sun.star.awt.Point")
p1.X = 11000
p1.Y = 11000
pts.append(p1)
pts.append(p2)
ppbz_s.Coordinates = [pts]
ppbz_s.Flags = []
ppbz_e.Coordinates = [pts]
ppbz_e.Flags = []
oShape.LineStart = ppbz_s
oShape.LineEnd   = ppbz_e
oPage = doc.DrawPages[0]
cursor.add(oShape)

properties = (PropertyValue("FilterName", 0, "writer8", 0), PropertyValue("Overwrite", 0, True, 0),)
doc.storeToURL('file:///tmp/test.odt', properties )
properties = (PropertyValue("FilterName", 0, "writer_pdf_Export", 0), PropertyValue("Overwrite", 0, True, 0),)
doc.storeToURL('file:///tmp/test.pdf', properties )

# close the document
dispatcher.executeDispatch(doc.CurrentController.Frame, ".uno:Quit", "", 0, ())

Hello!

Are you sure this thing worked before? I just don’t see Add(graphic shape) among the text cursor methods

image

Perhaps this was previously in the DrawPage? Yes, there is definitely an Add() method

image

Indeed. Nice tool, I was unfamiliar with it.
Replacing:
cursor.add(oShape)
with

dp = doc.getDrawPage()
dp.add(oShape)

results in

Unspecified Application Error
Fatal exception: Signal 6

Am I using a wrong DrawPage here?

I didn’t discover why your macro isn’t running (I don’t know Python well), but here is macro that inserts the shape (number 2) to document.
I ran LibreOffice with these parameters for Python: “–accept=socket,host=localhost,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext” --norestore

import uno

from com.sun.star.awt import Point

def rgb(r, g, b):
    return 256*256*r + 256*g + b

def createPoint(x, y):
    return Point(x,y)

localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext )
smgr = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager" )
remoteContext = smgr.getPropertyValue( "DefaultContext" )

desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",remoteContext)
doc = desktop.loadComponentFromURL( "private:factory/swriter","_blank", 0, () )
oPage=doc.DrawPages[0]

oCoords = uno.createUnoStruct("com.sun.star.drawing.PolyPolygonBezierCoords")
oCoords.Coordinates = [ [createPoint(0,295), createPoint(0,255), createPoint(14,224), createPoint(42,191), createPoint(85,157), createPoint(105,140), createPoint(120,127), createPoint(128,116), createPoint(136,105), createPoint(140,95), createPoint(140,84), createPoint(140,59), createPoint(128,46), createPoint(102,46), createPoint(90,46), createPoint(80,50), createPoint(74,56), createPoint(67,63), createPoint(63,73), createPoint(61,86), createPoint(2,83), createPoint(6,56), createPoint(16,35), createPoint(33,21), createPoint(50,7), createPoint(73,0), createPoint(103,0), createPoint(134,0), createPoint(157,7), createPoint(174,21), createPoint(191,36), createPoint(199,56), createPoint(199,82), createPoint(199,114), createPoint(180,145), createPoint(142,175), createPoint(114,198), createPoint(95,214), createPoint(87,222), createPoint(79,230), createPoint(72,239), createPoint(69,248), createPoint(204,248), createPoint(204,295), createPoint(0,295) ] ]
oCoords.Flags = [ [0, 0, 2, 2, 0, 2, 2, 3, 2, 2, 1, 2, 2, 1, 2, 2, 3, 2, 2, 0, 0, 2, 2, 3, 2, 2, 3, 2, 2, 3, 2, 2, 1, 2, 2, 0, 2, 2, 3, 2, 2, 0, 0, 0, 0] ]

oShape = doc.createInstance("com.sun.star.drawing.ClosedBezierShape")
oPage.add(oShape)

oShape.FillStyle = 1
oShape.LineStyle = 0
oShape.FillColor = rgb(255, 120, 30)
oShape.PolyPolygonBezier = oCoords

Thank you, your answer is definitely a priceless contribution to the Writer shape drawing topic! Perfect!

Here is still angular polygon (only with straight edges), there are only coordinates of points and no flags. Small improvement is only the Point(…) instead def createPoint

import uno

from com.sun.star.awt import Point

def rgb(r, g, b):
    return 256*256*r + 256*g + b

localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext )
smgr = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager" )
remoteContext = smgr.getPropertyValue( "DefaultContext" )

desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",remoteContext)
doc = desktop.loadComponentFromURL( "private:factory/swriter","_blank", 0, () )
oPage=doc.DrawPages[0]

oShape=doc.createInstance("com.sun.star.drawing.PolyPolygonShape")
oPage.add(oShape)
oShape.PolyPolygon=[ [Point(0,291), Point(0,248), Point(72,248), Point(72,49), Point(2,93), Point(2,47), Point(75,0), Point(130,0), Point(130,248), Point(196,248), Point(196,291)] ]
oShape.LineStyle=0
oShape.FillColor=rgb(255, 0, 0)
1 Like

Figured it out. Needed redo the entire thing. Working code below.

#!/bin/python
# -*- coding: utf-8 -*-
# coding: utf8

def rgb(r, g, b):
    return 256*256*r + 256*g + b

import sys
import os
import time
import codecs
from subprocess import call
import xml.etree.ElementTree as et
import argparse

import uno
import unohelper

from com.sun.star.beans import PropertyValue
from com.sun.star.awt import Size
from com.sun.star.awt import Point
from com.sun.star.style.BreakType import PAGE_AFTER as BreakTypePAGE_AFTER
from com.sun.star.drawing.LineStyle import SOLID as SOLIDLINE
from com.sun.star.drawing.LineCap import BUTT as FLATCAP
from com.sun.star.drawing.LineJoint import MIDDLE as MIDDLEJOIN

localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext )

smgr = None
while smgr is None:
    try:
        os.system("libreoffice --headless --accept='socket,host=localhost,port=2002,tcpNoDelay=1;urp' --nodefault --nofirststartwizard --nolockcheck --nologo --norestore --invisible &")
        time.sleep(1)
        smgr = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager" )
    except:
        smgr = None
        os.system("killall soffice.bin 2>/dev/null &")

remoteContext = smgr.getPropertyValue( "DefaultContext" )
desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",remoteContext)
dispatcher = smgr.createInstanceWithContext("com.sun.star.frame.DispatchHelper", remoteContext)
doc = desktop.loadComponentFromURL( "private:factory/swriter","_blank", 0, () )
text = doc.Text
cursor = text.createTextCursor()

cLine = doc.createInstance("com.sun.star.drawing.LineShape")
cLine.LineStyle = SOLIDLINE
cLine.LineWidth = 10  # Width of the line in 1/100 mm
cLine.LineColor = 0x000000  # RGB color (black)
cLine.setPosition(uno.createUnoStruct("com.sun.star.awt.Point", 15350, 4800))
cLine.setSize(uno.createUnoStruct("com.sun.star.awt.Size", 0, 20500))
text.insertTextContent(cursor, cLine, False)

properties = (PropertyValue("FilterName", 0, "writer8", 0), PropertyValue("Overwrite", 0, True, 0),)
doc.storeToURL('file:///tmp/test.odt', properties )
properties = (PropertyValue("FilterName", 0, "writer_pdf_Export", 0), PropertyValue("Overwrite", 0, True, 0),)
doc.storeToURL('file:///tmp/test.pdf', properties )

# close the document
dispatcher.executeDispatch(doc.CurrentController.Frame, ".uno:Quit", "", 0, ())