xref: /trunk/test/odf-validate/fixtures/leak/make.py (revision 0e16a31d78a652c56c5c0fc79c752f48b9048df9)
1*0e16a31dSJim Jagielski#**************************************************************
2*0e16a31dSJim Jagielski#
3*0e16a31dSJim Jagielski#  Licensed to the Apache Software Foundation (ASF) under one
4*0e16a31dSJim Jagielski#  or more contributor license agreements.  See the NOTICE file
5*0e16a31dSJim Jagielski#  distributed with this work for additional information
6*0e16a31dSJim Jagielski#  regarding copyright ownership.  The ASF licenses this file
7*0e16a31dSJim Jagielski#  to you under the Apache License, Version 2.0 (the
8*0e16a31dSJim Jagielski#  "License"); you may not use this file except in compliance
9*0e16a31dSJim Jagielski#  with the License.  You may obtain a copy of the License at
10*0e16a31dSJim Jagielski#
11*0e16a31dSJim Jagielski#    http://www.apache.org/licenses/LICENSE-2.0
12*0e16a31dSJim Jagielski#
13*0e16a31dSJim Jagielski#  Unless required by applicable law or agreed to in writing,
14*0e16a31dSJim Jagielski#  software distributed under the License is distributed on an
15*0e16a31dSJim Jagielski#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*0e16a31dSJim Jagielski#  KIND, either express or implied.  See the License for the
17*0e16a31dSJim Jagielski#  specific language governing permissions and limitations
18*0e16a31dSJim Jagielski#  under the License.
19*0e16a31dSJim Jagielski#
20*0e16a31dSJim Jagielski# usage: runpy.sh fixtures/leak/make.py <port> <outdir>
21*0e16a31dSJim Jagielski# Documents for names that AOO's export code can emit but no ODF 1.2 schema pattern defines (runs/task12/gaps/strict-leak.txt).
22*0e16a31dSJim Jagielski# Saves with the office's configured ODF version. ODF packages go to <outdir>; the report-definition package and the
23*0e16a31dSJim Jagielski# old-format chart copies go to <outdir>/../other and <outdir>/../oldfmt so the ODF checkers do not see them.
24*0e16a31dSJim Jagielskiimport os, struct, sys, traceback, zlib, uno
25*0e16a31dSJim Jagielskifrom unohelp import connect, desktop, pv
26*0e16a31dSJim Jagielskifrom com.sun.star.awt import Rectangle, Size, Point
27*0e16a31dSJim Jagielskifrom com.sun.star.table import CellAddress, CellRangeAddress, BorderLine
28*0e16a31dSJim Jagielski
29*0e16a31dSJim Jagielskiport, out = int(sys.argv[1]), os.path.abspath(sys.argv[2])
30*0e16a31dSJim Jagielskibase = os.path.dirname(out)
31*0e16a31dSJim Jagielskiother, oldfmt, work = (os.path.join(base, d) for d in ("other", "oldfmt", "work"))
32*0e16a31dSJim Jagielskifor d in (out, other, oldfmt, work):
33*0e16a31dSJim Jagielski    os.makedirs(d, exist_ok=True)
34*0e16a31dSJim Jagielskictx = connect(port)
35*0e16a31dSJim Jagielskism = ctx.ServiceManager
36*0e16a31dSJim Jagielskidesk = desktop(ctx)
37*0e16a31dSJim Jagielskifailed = []
38*0e16a31dSJim JagielskiURL = uno.systemPathToFileUrl
39*0e16a31dSJim JagielskiANCHOR = uno.Enum("com.sun.star.text.TextContentAnchorType", "AS_CHARACTER")
40*0e16a31dSJim JagielskiTPL = "com.sun.star.chart2.template."
41*0e16a31dSJim Jagielski
42*0e16a31dSJim Jagielski
43*0e16a31dSJim Jagielskidef new(factory):
44*0e16a31dSJim Jagielski    return desk.loadComponentFromURL(factory, "_blank", 0, (pv("Hidden", True),))
45*0e16a31dSJim Jagielski
46*0e16a31dSJim Jagielski
47*0e16a31dSJim Jagielskidef save(doc, path, filt):
48*0e16a31dSJim Jagielski    doc.storeToURL(URL(path), (pv("FilterName", filt),))
49*0e16a31dSJim Jagielski    print("saved", os.path.basename(path), filt)
50*0e16a31dSJim Jagielski
51*0e16a31dSJim Jagielski
52*0e16a31dSJim Jagielskidef step(name, fn):
53*0e16a31dSJim Jagielski    try:
54*0e16a31dSJim Jagielski        fn()
55*0e16a31dSJim Jagielski    except Exception as e:
56*0e16a31dSJim Jagielski        failed.append(name)
57*0e16a31dSJim Jagielski        print("FAIL", name, repr(e)[:300])
58*0e16a31dSJim Jagielski        traceback.print_exc(limit=3)
59*0e16a31dSJim Jagielski
60*0e16a31dSJim Jagielski
61*0e16a31dSJim Jagielskidef make_png(path):
62*0e16a31dSJim Jagielski    w = h = 8
63*0e16a31dSJim Jagielski    raw = b"".join(b"\x00" + bytes([200, 30, 30] * w) for _ in range(h))
64*0e16a31dSJim Jagielski
65*0e16a31dSJim Jagielski    def chunk(t, b):
66*0e16a31dSJim Jagielski        return struct.pack(">I", len(b)) + t + b + struct.pack(">I", zlib.crc32(t + b) & 0xFFFFFFFF)
67*0e16a31dSJim Jagielski
68*0e16a31dSJim Jagielski    with open(path, "wb") as f:
69*0e16a31dSJim Jagielski        f.write(b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0))
70*0e16a31dSJim Jagielski                + chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b""))
71*0e16a31dSJim Jagielski
72*0e16a31dSJim Jagielski
73*0e16a31dSJim Jagielskidef set_all(obj, props):
74*0e16a31dSJim Jagielski    for k, v in props:
75*0e16a31dSJim Jagielski        try:
76*0e16a31dSJim Jagielski            uno.invoke(obj, "setPropertyValue", (k, v)) if isinstance(v, uno.Any) else obj.setPropertyValue(k, v)
77*0e16a31dSJim Jagielski        except Exception as e:
78*0e16a31dSJim Jagielski            print("note: cannot set", k, repr(e)[:80])
79*0e16a31dSJim Jagielski
80*0e16a31dSJim Jagielski
81*0e16a31dSJim Jagielskidef writer_fields():
82*0e16a31dSJim Jagielski    doc = new("private:factory/swriter")
83*0e16a31dSJim Jagielski    try:
84*0e16a31dSJim Jagielski        text = doc.Text
85*0e16a31dSJim Jagielski        cur = text.createTextCursor()
86*0e16a31dSJim Jagielski        text.insertString(cur, "fields: ", False)
87*0e16a31dSJim Jagielski
88*0e16a31dSJim Jagielski        def field(svc, **kw):
89*0e16a31dSJim Jagielski            f = doc.createInstance("com.sun.star.text.TextField." + svc)
90*0e16a31dSJim Jagielski            for k, v in kw.items():
91*0e16a31dSJim Jagielski                setattr(f, k, v)
92*0e16a31dSJim Jagielski            text.insertTextContent(cur, f, False)
93*0e16a31dSJim Jagielski            text.insertString(cur, " ", False)
94*0e16a31dSJim Jagielski
95*0e16a31dSJim Jagielski        field("Input", Content="x", Hint="hint", Help="help text", Tooltip="tooltip text")
96*0e16a31dSJim Jagielski        field("DropDown", Name="dd", Items=("a", "b", "c"), SelectedItem="b", Help="help dd", Tooltip="tip dd")
97*0e16a31dSJim Jagielski        pn = uno.Enum("com.sun.star.text.PageNumberType", "NEXT")
98*0e16a31dSJim Jagielski        field("PageNumber", SubType=pn, UserText="next page", NumberingType=6)
99*0e16a31dSJim Jagielski        pn = uno.Enum("com.sun.star.text.PageNumberType", "PREV")
100*0e16a31dSJim Jagielski        field("PageNumber", SubType=pn, UserText="prev page", NumberingType=6)
101*0e16a31dSJim Jagielski        fn = doc.createInstance("com.sun.star.text.Footnote")
102*0e16a31dSJim Jagielski        text.insertTextContent(cur, fn, False)
103*0e16a31dSJim Jagielski        fn.String = "note"
104*0e16a31dSJim Jagielski        fs = doc.FootnoteSettings
105*0e16a31dSJim Jagielski        fs.EndNotice = "continued on next page"
106*0e16a31dSJim Jagielski        fs.BeginNotice = "continued from previous page"
107*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "writer-fields.odt"), "writer8")
108*0e16a31dSJim Jagielski    finally:
109*0e16a31dSJim Jagielski        doc.close(True)
110*0e16a31dSJim Jagielski
111*0e16a31dSJim Jagielski
112*0e16a31dSJim Jagielskidef writer_toc_image():
113*0e16a31dSJim Jagielski    png = os.path.join(work, "red.png")
114*0e16a31dSJim Jagielski    make_png(png)
115*0e16a31dSJim Jagielski    doc = new("private:factory/swriter")
116*0e16a31dSJim Jagielski    try:
117*0e16a31dSJim Jagielski        text = doc.Text
118*0e16a31dSJim Jagielski        cur = text.createTextCursor()
119*0e16a31dSJim Jagielski        text.insertString(cur, "Heading one", False)
120*0e16a31dSJim Jagielski        cur.gotoStart(False)
121*0e16a31dSJim Jagielski        cur.gotoEndOfParagraph(True)
122*0e16a31dSJim Jagielski        cur.ParaStyleName = "Heading 1"
123*0e16a31dSJim Jagielski        cur.gotoEnd(False)
124*0e16a31dSJim Jagielski        text.insertControlCharacter(cur, uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK"), False)
125*0e16a31dSJim Jagielski        g = doc.createInstance("com.sun.star.text.GraphicObject")
126*0e16a31dSJim Jagielski        g.GraphicURL = URL(png)
127*0e16a31dSJim Jagielski        g.Width = g.Height = 3000
128*0e16a31dSJim Jagielski        g.AnchorType = ANCHOR
129*0e16a31dSJim Jagielski        text.insertTextContent(cur, g, False)
130*0e16a31dSJim Jagielski        g.GraphicRotation = 900
131*0e16a31dSJim Jagielski        toc = doc.createInstance("com.sun.star.text.ContentIndex")
132*0e16a31dSJim Jagielski        toc.CreateFromOutline = True
133*0e16a31dSJim Jagielski        lf = toc.LevelFormat
134*0e16a31dSJim Jagielski        new_level = []
135*0e16a31dSJim Jagielski        for tok in lf.getByIndex(1):
136*0e16a31dSJim Jagielski            tok = list(tok)
137*0e16a31dSJim Jagielski            for p in tok:
138*0e16a31dSJim Jagielski                if p.Name == "WithTab":
139*0e16a31dSJim Jagielski                    p.Value = False
140*0e16a31dSJim Jagielski            new_level.append(tuple(tok))
141*0e16a31dSJim Jagielski        uno.invoke(lf, "replaceByIndex", (1, uno.Any("[][]com.sun.star.beans.PropertyValue", tuple(new_level))))
142*0e16a31dSJim Jagielski        text.insertTextContent(cur, toc, False)
143*0e16a31dSJim Jagielski        toc.update()
144*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "writer-toc-image.odt"), "writer8")
145*0e16a31dSJim Jagielski    finally:
146*0e16a31dSJim Jagielski        doc.close(True)
147*0e16a31dSJim Jagielski
148*0e16a31dSJim Jagielski
149*0e16a31dSJim Jagielskidef writer_forms():
150*0e16a31dSJim Jagielski    doc = new("private:factory/swriter")
151*0e16a31dSJim Jagielski    try:
152*0e16a31dSJim Jagielski        dp = doc.DrawPage
153*0e16a31dSJim Jagielski        dp.Forms.insertByName("F1", doc.createInstance("com.sun.star.form.component.Form"))
154*0e16a31dSJim Jagielski        form = dp.Forms.getByName("F1")
155*0e16a31dSJim Jagielski        y = 300
156*0e16a31dSJim Jagielski        for kind in ("TextField", "FormattedField", "NumericField", "DateField", "TimeField", "CurrencyField", "PatternField",
157*0e16a31dSJim Jagielski                     "CheckBox", "ComboBox", "ListBox", "RadioButton"):
158*0e16a31dSJim Jagielski            m = doc.createInstance("com.sun.star.form.component." + kind)
159*0e16a31dSJim Jagielski            set_all(m, (("InputRequired", False), ("EnableVisible", False)))
160*0e16a31dSJim Jagielski            m.Name = kind
161*0e16a31dSJim Jagielski            form.insertByName(kind, m)
162*0e16a31dSJim Jagielski            s = doc.createInstance("com.sun.star.drawing.ControlShape")
163*0e16a31dSJim Jagielski            s.Size = Size(3000, 600)
164*0e16a31dSJim Jagielski            s.Position = Point(500, y)
165*0e16a31dSJim Jagielski            y += 800
166*0e16a31dSJim Jagielski            s.setControl(m)
167*0e16a31dSJim Jagielski            dp.add(s)
168*0e16a31dSJim Jagielski        for i, (n, v) in enumerate((("FontWidth", uno.Any("short", 20)), ("FontCharWidth", uno.Any("float", 90.0)),
169*0e16a31dSJim Jagielski                                    ("FontWordLineMode", True))):
170*0e16a31dSJim Jagielski            m = doc.createInstance("com.sun.star.form.component.TextField")
171*0e16a31dSJim Jagielski            set_all(m, ((n, v),))
172*0e16a31dSJim Jagielski            m.Name = "font_" + n
173*0e16a31dSJim Jagielski            form.insertByName(m.Name, m)
174*0e16a31dSJim Jagielski            s = doc.createInstance("com.sun.star.drawing.ControlShape")
175*0e16a31dSJim Jagielski            s.Size = Size(3000, 600)
176*0e16a31dSJim Jagielski            s.Position = Point(4500, 300 + i * 800)
177*0e16a31dSJim Jagielski            s.setControl(m)
178*0e16a31dSJim Jagielski            dp.add(s)
179*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "writer-forms.odt"), "writer8")
180*0e16a31dSJim Jagielski    finally:
181*0e16a31dSJim Jagielski        doc.close(True)
182*0e16a31dSJim Jagielski
183*0e16a31dSJim Jagielski
184*0e16a31dSJim Jagielskidef writer_redline():
185*0e16a31dSJim Jagielski    doc = new("private:factory/swriter")
186*0e16a31dSJim Jagielski    try:
187*0e16a31dSJim Jagielski        doc.Text.insertString(doc.Text.createTextCursor(), "first para\nsecond para\nthird para", False)
188*0e16a31dSJim Jagielski        t = doc.createInstance("com.sun.star.text.TextTable")
189*0e16a31dSJim Jagielski        t.initialize(2, 2)
190*0e16a31dSJim Jagielski        c = doc.Text.createTextCursor()
191*0e16a31dSJim Jagielski        c.gotoEnd(False)
192*0e16a31dSJim Jagielski        doc.Text.insertTextContent(c, t, False)
193*0e16a31dSJim Jagielski        doc.RecordChanges = True
194*0e16a31dSJim Jagielski        c = doc.Text.createTextCursor()
195*0e16a31dSJim Jagielski        c.gotoStart(False)
196*0e16a31dSJim Jagielski        c.goRight(3, False)
197*0e16a31dSJim Jagielski        c.gotoEndOfParagraph(True)
198*0e16a31dSJim Jagielski        c.goRight(1, True)
199*0e16a31dSJim Jagielski        c.setString("")
200*0e16a31dSJim Jagielski        c = doc.Text.createTextCursor()
201*0e16a31dSJim Jagielski        c.gotoEnd(False)
202*0e16a31dSJim Jagielski        c.goLeft(4, True)
203*0e16a31dSJim Jagielski        c.setString("")
204*0e16a31dSJim Jagielski        e = doc.Redlines.createEnumeration()
205*0e16a31dSJim Jagielski        while e.hasMoreElements():
206*0e16a31dSJim Jagielski            r = e.nextElement()
207*0e16a31dSJim Jagielski            print("redline", r.RedlineType, "MergeLastPara", r.getPropertyValue("MergeLastPara"))
208*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "writer-redline.odt"), "writer8")
209*0e16a31dSJim Jagielski    finally:
210*0e16a31dSJim Jagielski        doc.close(True)
211*0e16a31dSJim Jagielski
212*0e16a31dSJim Jagielski
213*0e16a31dSJim Jagielskidef writer_pagegrid():
214*0e16a31dSJim Jagielski    doc = new("private:factory/swriter")
215*0e16a31dSJim Jagielski    try:
216*0e16a31dSJim Jagielski        doc.Text.insertString(doc.Text.createTextCursor(), "grid", False)
217*0e16a31dSJim Jagielski        ps = doc.StyleFamilies.getByName("PageStyles").getByName("Standard")
218*0e16a31dSJim Jagielski        set_all(ps, (("GridMode", 2), ("GridLines", 20), ("GridBaseHeight", 600), ("GridBaseWidth", 500),
219*0e16a31dSJim Jagielski                     ("GridSnapToChars", True), ("StandardPageMode", True), ("GridDisplay", True), ("GridPrint", True)))
220*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "writer-pagegrid.odt"), "writer8")
221*0e16a31dSJim Jagielski    finally:
222*0e16a31dSJim Jagielski        doc.close(True)
223*0e16a31dSJim Jagielski
224*0e16a31dSJim Jagielski
225*0e16a31dSJim Jagielskidef fill_rows(sh, rows):
226*0e16a31dSJim Jagielski    for r, row in enumerate(rows):
227*0e16a31dSJim Jagielski        for c, v in enumerate(row):
228*0e16a31dSJim Jagielski            cell = sh.getCellByPosition(c, r)
229*0e16a31dSJim Jagielski            if isinstance(v, str):
230*0e16a31dSJim Jagielski                cell.String = v
231*0e16a31dSJim Jagielski            else:
232*0e16a31dSJim Jagielski                cell.Value = v
233*0e16a31dSJim Jagielski
234*0e16a31dSJim Jagielski
235*0e16a31dSJim Jagielskidef calc_misc():
236*0e16a31dSJim Jagielski    doc = new("private:factory/scalc")
237*0e16a31dSJim Jagielski    try:
238*0e16a31dSJim Jagielski        sh = doc.Sheets.getByIndex(0)
239*0e16a31dSJim Jagielski        sh.TabColor = 0xFF8000
240*0e16a31dSJim Jagielski        for i, mode in enumerate((0, 1, 2)):
241*0e16a31dSJim Jagielski            sh.getCellByPosition(12, i).Formula = '=DDE("soffice";"/tmp/x.ods";"Sheet1.A%d";%d)' % (i + 1, mode)
242*0e16a31dSJim Jagielski        fill_rows(sh, [("", "", "", "L0", 1, ""), ("", "", "", "L1", 2, ""), ("", "", "", "L2", 3, "")])
243*0e16a31dSJim Jagielski        for r in range(3):
244*0e16a31dSJim Jagielski            sh.getCellByPosition(1, r + 4).Value = r + 5
245*0e16a31dSJim Jagielski            sh.getCellByPosition(0, r + 4).String = "L%d" % r
246*0e16a31dSJim Jagielski        cd = doc.createConsolidationDescriptor(False)
247*0e16a31dSJim Jagielski        cd.Function = uno.Enum("com.sun.star.sheet.GeneralFunction", "SUM")
248*0e16a31dSJim Jagielski        cd.Sources = (CellRangeAddress(0, 0, 4, 1, 6), CellRangeAddress(0, 3, 0, 4, 2))
249*0e16a31dSJim Jagielski        cd.StartOutputPosition = CellAddress(0, 7, 7)
250*0e16a31dSJim Jagielski        cd.UseColumnHeaders = True
251*0e16a31dSJim Jagielski        cd.UseRowHeaders = True
252*0e16a31dSJim Jagielski        cd.InsertLinks = False
253*0e16a31dSJim Jagielski        doc.consolidate(cd)
254*0e16a31dSJim Jagielski        c = sh.getCellByPosition(10, 10)
255*0e16a31dSJim Jagielski        c.String = "diagonal"
256*0e16a31dSJim Jagielski        bl = BorderLine()
257*0e16a31dSJim Jagielski        bl.OuterLineWidth = 50
258*0e16a31dSJim Jagielski        bl.Color = 0xFF0000
259*0e16a31dSJim Jagielski        c.DiagonalBLTR = bl
260*0e16a31dSJim Jagielski        c.DiagonalTLBR = bl
261*0e16a31dSJim Jagielski        ps = doc.StyleFamilies.getByName("PageStyles").getByName(sh.PageStyle)
262*0e16a31dSJim Jagielski        set_all(ps, (("ScaleToPagesX", 2), ("ScaleToPagesY", 3)))
263*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "calc-misc.ods"), "calc8")
264*0e16a31dSJim Jagielski    finally:
265*0e16a31dSJim Jagielski        doc.close(True)
266*0e16a31dSJim Jagielski
267*0e16a31dSJim Jagielski
268*0e16a31dSJim Jagielskidef calc_pivot_group():
269*0e16a31dSJim Jagielski    doc = new("private:factory/scalc")
270*0e16a31dSJim Jagielski    try:
271*0e16a31dSJim Jagielski        sh = doc.Sheets.getByIndex(0)
272*0e16a31dSJim Jagielski        fill_rows(sh, [("Region", "Qty")] + [(r, i + 1) for i, r in enumerate(["North", "South", "East", "West", "North", "East"])])
273*0e16a31dSJim Jagielski        dps = sh.DataPilotTables
274*0e16a31dSJim Jagielski        desc = dps.createDataPilotDescriptor()
275*0e16a31dSJim Jagielski        desc.setSourceRange(CellRangeAddress(0, 0, 0, 1, 6))
276*0e16a31dSJim Jagielski        fl = desc.getDataPilotFields()
277*0e16a31dSJim Jagielski        ori = lambda n: uno.Enum("com.sun.star.sheet.DataPilotFieldOrientation", n)
278*0e16a31dSJim Jagielski        fl.getByName("Region").Orientation = ori("ROW")
279*0e16a31dSJim Jagielski        fl.getByName("Qty").Orientation = ori("DATA")
280*0e16a31dSJim Jagielski        dps.insertNewByName("pv", CellAddress(0, 4, 1), desc)
281*0e16a31dSJim Jagielski        f = dps.getByName("pv").getDataPilotFields().getByName("Region")
282*0e16a31dSJim Jagielski        f.createNameGroup(("North", "South"))
283*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "calc-pivot-group.ods"), "calc8")
284*0e16a31dSJim Jagielski    finally:
285*0e16a31dSJim Jagielski        doc.close(True)
286*0e16a31dSJim Jagielski
287*0e16a31dSJim Jagielski
288*0e16a31dSJim Jagielskidef calc_tracked():
289*0e16a31dSJim Jagielski    doc = new("private:factory/scalc")
290*0e16a31dSJim Jagielski    try:
291*0e16a31dSJim Jagielski        dh = sm.createInstanceWithContext("com.sun.star.frame.DispatchHelper", ctx)
292*0e16a31dSJim Jagielski        dh.executeDispatch(doc.CurrentController.Frame, ".uno:TraceChangeMode", "", 0, (pv("TraceChangeMode", True),))
293*0e16a31dSJim Jagielski        sh = doc.Sheets.getByIndex(0)
294*0e16a31dSJim Jagielski        for r in range(6):
295*0e16a31dSJim Jagielski            sh.getCellByPosition(0, r).Value = r
296*0e16a31dSJim Jagielski        for r in range(6):
297*0e16a31dSJim Jagielski            sh.getCellByPosition(0, r).Value = r * 10
298*0e16a31dSJim Jagielski        sh.Rows.insertByIndex(2, 2)
299*0e16a31dSJim Jagielski        sh.Rows.removeByIndex(3, 2)
300*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "calc-tracked.ods"), "calc8")
301*0e16a31dSJim Jagielski    finally:
302*0e16a31dSJim Jagielski        doc.close(True)
303*0e16a31dSJim Jagielski
304*0e16a31dSJim Jagielski
305*0e16a31dSJim Jagielskidef chart_doc(name, charts, post=None):
306*0e16a31dSJim Jagielski    doc = new("private:factory/scalc")
307*0e16a31dSJim Jagielski    try:
308*0e16a31dSJim Jagielski        sh = doc.Sheets.getByIndex(0)
309*0e16a31dSJim Jagielski        loc = uno.createUnoStruct("com.sun.star.lang.Locale", "en", "US", "")
310*0e16a31dSJim Jagielski        key = doc.NumberFormats.queryKey("YYYY-MM-DD", loc, False)
311*0e16a31dSJim Jagielski        if key == -1:
312*0e16a31dSJim Jagielski            key = doc.NumberFormats.addNew("YYYY-MM-DD", loc)
313*0e16a31dSJim Jagielski        for r in range(6):
314*0e16a31dSJim Jagielski            for c in range(5):
315*0e16a31dSJim Jagielski                if r == 0:
316*0e16a31dSJim Jagielski                    sh.getCellByPosition(c, r).String = "s%d" % c if c else "cat"
317*0e16a31dSJim Jagielski                else:
318*0e16a31dSJim Jagielski                    sh.getCellByPosition(c, r).Value = 40000 + r * 30 if c == 0 else r * 2 + c
319*0e16a31dSJim Jagielski        sh.getCellRangeByName("A2:A6").NumberFormat = key
320*0e16a31dSJim Jagielski        for i, (cname, ncols, tpl) in enumerate(charts):
321*0e16a31dSJim Jagielski            rng = CellRangeAddress(0, 0, 0, ncols, 5)
322*0e16a31dSJim Jagielski            sh.Charts.addNewByName(cname, Rectangle(500 + i * 9500, 8000, 9000, 6800), (rng,), True, True)
323*0e16a31dSJim Jagielski            ch = sh.Charts.getByName(cname).EmbeddedObject
324*0e16a31dSJim Jagielski            if tpl:
325*0e16a31dSJim Jagielski                dp = ch.getDataProvider()
326*0e16a31dSJim Jagielski                args = (pv("CellRangeRepresentation", "$Sheet1.$A$1:$%s$6" % "ABCDE"[ncols]),
327*0e16a31dSJim Jagielski                        pv("DataRowSource", uno.Enum("com.sun.star.chart.ChartDataRowSource", "COLUMNS")),
328*0e16a31dSJim Jagielski                        pv("FirstCellAsLabel", True), pv("HasCategories", True))
329*0e16a31dSJim Jagielski                t = ch.ChartTypeManager.createInstance(TPL + tpl)
330*0e16a31dSJim Jagielski                ch.setFirstDiagram(t.createDiagramByDataSource(dp.createDataSource(args), args))
331*0e16a31dSJim Jagielski            if post:
332*0e16a31dSJim Jagielski                post(ch)
333*0e16a31dSJim Jagielski        save(doc, os.path.join(out, name + ".ods"), "calc8")
334*0e16a31dSJim Jagielski        try:
335*0e16a31dSJim Jagielski            save(doc, os.path.join(oldfmt, name + ".sxc"), "StarOffice XML (Calc)")
336*0e16a31dSJim Jagielski        except Exception as e:
337*0e16a31dSJim Jagielski            print("note: old format save failed", repr(e)[:100])
338*0e16a31dSJim Jagielski    finally:
339*0e16a31dSJim Jagielski        doc.close(True)
340*0e16a31dSJim Jagielski
341*0e16a31dSJim Jagielski
342*0e16a31dSJim Jagielskidef label_and_date_axis(ch):
343*0e16a31dSJim Jagielski    cs = ch.getFirstDiagram().getCoordinateSystems()[0]
344*0e16a31dSJim Jagielski    for s in cs.getChartTypes()[0].getDataSeries():
345*0e16a31dSJim Jagielski        s.setPropertyValue("LabelSeparator", "a\tb\nc")
346*0e16a31dSJim Jagielski        s.setPropertyValue("Label", uno.createUnoStruct("com.sun.star.chart2.DataPointLabel", True, False, False, False))
347*0e16a31dSJim Jagielski    ax = cs.getAxisByDimension(0, 0)
348*0e16a31dSJim Jagielski    sd = ax.getScaleData()
349*0e16a31dSJim Jagielski    sd.AxisType = 4
350*0e16a31dSJim Jagielski    ti = uno.createUnoStruct("com.sun.star.chart.TimeIncrement")
351*0e16a31dSJim Jagielski    ti.TimeResolution = 1
352*0e16a31dSJim Jagielski    ti.MajorTimeInterval = uno.createUnoStruct("com.sun.star.chart.TimeInterval", 2, 1)
353*0e16a31dSJim Jagielski    ti.MinorTimeInterval = uno.createUnoStruct("com.sun.star.chart.TimeInterval", 1, 0)
354*0e16a31dSJim Jagielski    sd.TimeIncrement = ti
355*0e16a31dSJim Jagielski    ax.setScaleData(sd)
356*0e16a31dSJim Jagielski
357*0e16a31dSJim Jagielski
358*0e16a31dSJim Jagielskidef draw_fontwork():
359*0e16a31dSJim Jagielski    doc = new("private:factory/sdraw")
360*0e16a31dSJim Jagielski    try:
361*0e16a31dSJim Jagielski        page = doc.DrawPages.getByIndex(0)
362*0e16a31dSJim Jagielski        s = doc.createInstance("com.sun.star.drawing.RectangleShape")
363*0e16a31dSJim Jagielski        page.add(s)
364*0e16a31dSJim Jagielski        s.Size = Size(5000, 3000)
365*0e16a31dSJim Jagielski        s.Position = Point(500, 500)
366*0e16a31dSJim Jagielski        s.String = "fontwork"
367*0e16a31dSJim Jagielski        set_all(s, (("FontWorkStyle", 0), ("FontWorkAdjust", 1), ("FontWorkDistance", 100), ("FontWorkStart", 50),
368*0e16a31dSJim Jagielski                    ("FontWorkMirror", True), ("FontWorkOutline", True), ("FontWorkShadow", 1), ("FontWorkShadowColor", 0xFF0000),
369*0e16a31dSJim Jagielski                    ("FontWorkShadowOffsetX", 100), ("FontWorkShadowOffsetY", 100), ("FontWorkHideForm", True),
370*0e16a31dSJim Jagielski                    ("FontWorkShadowTransparence", 50)))
371*0e16a31dSJim Jagielski        for svc in ("RectangleShape", "TextShape", "PolyPolygonShape", "CustomShape"):
372*0e16a31dSJim Jagielski            o = doc.createInstance("com.sun.star.drawing." + svc)
373*0e16a31dSJim Jagielski            print("FontWorkForm on", svc, o.getPropertySetInfo().hasPropertyByName("FontWorkForm"))
374*0e16a31dSJim Jagielski        a = doc.createInstance("com.sun.star.drawing.AppletShape")
375*0e16a31dSJim Jagielski        page.add(a)
376*0e16a31dSJim Jagielski        a.Size = Size(3000, 2000)
377*0e16a31dSJim Jagielski        a.Position = Point(6000, 500)
378*0e16a31dSJim Jagielski        set_all(a, (("AppletName", "myapplet"), ("AppletCode", "Foo.class"), ("AppletCodeBase", "file:///tmp/"), ("AppletIsScript", True)))
379*0e16a31dSJim Jagielski        print("applet AppletName reads back", repr(a.getPropertyValue("AppletName")))
380*0e16a31dSJim Jagielski        t = doc.createInstance("com.sun.star.drawing.TextShape")
381*0e16a31dSJim Jagielski        page.add(t)
382*0e16a31dSJim Jagielski        t.Size = Size(5000, 3000)
383*0e16a31dSJim Jagielski        t.Position = Point(500, 4500)
384*0e16a31dSJim Jagielski        t.String = "one\ntwo"
385*0e16a31dSJim Jagielski        nr = t.getPropertyValue("NumberingRules")
386*0e16a31dSJim Jagielski        lvl = list(nr.getByIndex(0))
387*0e16a31dSJim Jagielski        for p in lvl:
388*0e16a31dSJim Jagielski            if p.Name == "NumberingType":
389*0e16a31dSJim Jagielski                p.Value = 4
390*0e16a31dSJim Jagielski        uno.invoke(nr, "replaceByIndex", (0, uno.Any("[]com.sun.star.beans.PropertyValue", tuple(lvl))))
391*0e16a31dSJim Jagielski        t.setPropertyValue("NumberingRules", nr)
392*0e16a31dSJim Jagielski        save(doc, os.path.join(out, "draw-fontwork.odg"), "draw8")
393*0e16a31dSJim Jagielski    finally:
394*0e16a31dSJim Jagielski        doc.close(True)
395*0e16a31dSJim Jagielski
396*0e16a31dSJim Jagielski
397*0e16a31dSJim Jagielskidef set_info(ds, **kw):
398*0e16a31dSJim Jagielski    bag = ds.Settings
399*0e16a31dSJim Jagielski    for k, v in kw.items():
400*0e16a31dSJim Jagielski        if bag.getPropertySetInfo().hasPropertyByName(k):
401*0e16a31dSJim Jagielski            uno.invoke(bag, "setPropertyValue", (k, v))
402*0e16a31dSJim Jagielski        else:
403*0e16a31dSJim Jagielski            uno.invoke(bag, "addProperty", (k, 128 | 1, v))
404*0e16a31dSJim Jagielski
405*0e16a31dSJim Jagielski
406*0e16a31dSJim Jagielskidef base_doc():
407*0e16a31dSJim Jagielski    dbc = sm.createInstanceWithContext("com.sun.star.sdb.DatabaseContext", ctx)
408*0e16a31dSJim Jagielski    path = os.path.join(out, "leak-base.odb")
409*0e16a31dSJim Jagielski    for p in (path, path + ".lck"):
410*0e16a31dSJim Jagielski        if os.path.exists(p):
411*0e16a31dSJim Jagielski            os.remove(p)
412*0e16a31dSJim Jagielski    ds = dbc.createInstance()
413*0e16a31dSJim Jagielski    ds.URL = "sdbc:embedded:hsqldb"
414*0e16a31dSJim Jagielski    ds.DatabaseDocument.storeAsURL(URL(path), ())
415*0e16a31dSJim Jagielski    try:
416*0e16a31dSJim Jagielski        q = ds.QueryDefinitions.createInstance()
417*0e16a31dSJim Jagielski        q.Command = 'SELECT "ID", "NAME" FROM "CUSTOMERS"'
418*0e16a31dSJim Jagielski        q.Filter = '"ID" > 0'
419*0e16a31dSJim Jagielski        q.ApplyFilter = True
420*0e16a31dSJim Jagielski        q.Order = '"NAME"'
421*0e16a31dSJim Jagielski        ds.QueryDefinitions.insertByName("Q", q)
422*0e16a31dSJim Jagielski        q = ds.QueryDefinitions.getByName("Q")
423*0e16a31dSJim Jagielski        print("ApplyOrder on query", q.getPropertySetInfo().hasPropertyByName("ApplyOrder"),
424*0e16a31dSJim Jagielski              "on table definition", ds.Tables.createInstance().getPropertySetInfo().hasPropertyByName("ApplyOrder"))
425*0e16a31dSJim Jagielski        set_all(q, (("FontWidth", uno.Any("short", 20)), ("FontCharWidth", uno.Any("float", 90.0))))
426*0e16a31dSJim Jagielski        for name, props in (("ID", dict(Hidden=True, HelpText="id column")), ("NAME", dict(HelpText="name", ControlDefault="x"))):
427*0e16a31dSJim Jagielski            d = q.Columns.createDataDescriptor()
428*0e16a31dSJim Jagielski            d.Name = name
429*0e16a31dSJim Jagielski            for k, v in props.items():
430*0e16a31dSJim Jagielski                d.setPropertyValue(k, v)
431*0e16a31dSJim Jagielski            q.Columns.appendByDescriptor(d)
432*0e16a31dSJim Jagielski        ds.DatabaseDocument.store()
433*0e16a31dSJim Jagielski    finally:
434*0e16a31dSJim Jagielski        ds.DatabaseDocument.close(True)
435*0e16a31dSJim Jagielski        if os.path.exists(path + ".lck"):
436*0e16a31dSJim Jagielski            os.remove(path + ".lck")
437*0e16a31dSJim Jagielski    print("saved", os.path.basename(path))
438*0e16a31dSJim Jagielski
439*0e16a31dSJim Jagielski
440*0e16a31dSJim Jagielskidef base_dbase():
441*0e16a31dSJim Jagielski    dbc = sm.createInstanceWithContext("com.sun.star.sdb.DatabaseContext", ctx)
442*0e16a31dSJim Jagielski    d = os.path.join(work, "dbase")
443*0e16a31dSJim Jagielski    os.makedirs(d, exist_ok=True)
444*0e16a31dSJim Jagielski    path = os.path.join(out, "leak-base-dbase.odb")
445*0e16a31dSJim Jagielski    for p in (path, path + ".lck"):
446*0e16a31dSJim Jagielski        if os.path.exists(p):
447*0e16a31dSJim Jagielski            os.remove(p)
448*0e16a31dSJim Jagielski    ds = dbc.createInstance()
449*0e16a31dSJim Jagielski    ds.URL = "sdbc:dbase:" + URL(d) + "/"
450*0e16a31dSJim Jagielski    set_info(ds, Extension="dbf", CharSet="utf-8")
451*0e16a31dSJim Jagielski    ds.DatabaseDocument.storeAsURL(URL(path), ())
452*0e16a31dSJim Jagielski    try:
453*0e16a31dSJim Jagielski        ds.DatabaseDocument.store()
454*0e16a31dSJim Jagielski    finally:
455*0e16a31dSJim Jagielski        ds.DatabaseDocument.close(True)
456*0e16a31dSJim Jagielski        if os.path.exists(path + ".lck"):
457*0e16a31dSJim Jagielski            os.remove(path + ".lck")
458*0e16a31dSJim Jagielski    print("saved", os.path.basename(path))
459*0e16a31dSJim Jagielski
460*0e16a31dSJim Jagielski
461*0e16a31dSJim Jagielskidef report_definition():
462*0e16a31dSJim Jagielski    r = sm.createInstanceWithContext("com.sun.star.report.ReportDefinition", ctx)
463*0e16a31dSJim Jagielski    r.Caption = "Leak report"
464*0e16a31dSJim Jagielski    r.Name = "rpt"
465*0e16a31dSJim Jagielski    r.ReportHeaderOn = True
466*0e16a31dSJim Jagielski    path = os.path.join(other, "report-definition.odr")
467*0e16a31dSJim Jagielski    stg = sm.createInstanceWithContext("com.sun.star.embed.StorageFactory", ctx).createInstanceWithArguments((URL(path), 7))
468*0e16a31dSJim Jagielski    r.storeToStorage(stg, ())
469*0e16a31dSJim Jagielski    stg.commit()
470*0e16a31dSJim Jagielski    stg.dispose()
471*0e16a31dSJim Jagielski    print("saved", os.path.basename(path), "(report definition)")
472*0e16a31dSJim Jagielski
473*0e16a31dSJim Jagielski
474*0e16a31dSJim Jagielskifor name, fn in (("writer-fields", writer_fields), ("writer-toc-image", writer_toc_image), ("writer-forms", writer_forms),
475*0e16a31dSJim Jagielski                 ("writer-redline", writer_redline), ("writer-pagegrid", writer_pagegrid), ("calc-misc", calc_misc),
476*0e16a31dSJim Jagielski                 ("calc-pivot-group", calc_pivot_group), ("calc-tracked", calc_tracked),
477*0e16a31dSJim Jagielski                 ("calc-chart-axis", lambda: chart_doc("calc-chart-axis", (("c1", 3, None),), label_and_date_axis)),
478*0e16a31dSJim Jagielski                 ("calc-chart-types", lambda: chart_doc("calc-chart-types", (("cl", 3, "ColumnWithLine"), ("sv", 4, "StockVolumeLowHighClose")))),
479*0e16a31dSJim Jagielski                 ("draw-fontwork", draw_fontwork), ("base", base_doc), ("base-dbase", base_dbase), ("report", report_definition)):
480*0e16a31dSJim Jagielski    step(name, fn)
481*0e16a31dSJim Jagielskiprint("FAILED:", failed if failed else "none")
482