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#************************************************************** 21*0e16a31dSJim Jagielski# 22*0e16a31dSJim Jagielski# usage: runpy.sh fixtures/t13/make.py <port> <outdir> 23*0e16a31dSJim Jagielski# Documents for the features ODF 1.3 changes in the writer: drop-down fields, annotation initials, Calc tab colour, 24*0e16a31dSJim Jagielski# Calc page scale-to, chart inner plot position and legend size. Saves with the office's configured ODF version: run 25*0e16a31dSJim Jagielski# it with fixtures/gen-run.sh (strict, ext, v13, x13). The committed copies in this folder were generated in ext mode, 26*0e16a31dSJim Jagielski# which keeps all of the features. Everything is fixed (no dates taken from the clock, nothing random). 27*0e16a31dSJim Jagielskiimport sys, os, traceback, uno 28*0e16a31dSJim Jagielskifrom unohelp import connect, desktop, pv 29*0e16a31dSJim Jagielski 30*0e16a31dSJim Jagielskiport, out = int(sys.argv[1]), os.path.abspath(sys.argv[2]) 31*0e16a31dSJim Jagielskios.makedirs(out, exist_ok=True) 32*0e16a31dSJim Jagielskidesk = desktop(connect(port)) 33*0e16a31dSJim Jagielskifailed = [] 34*0e16a31dSJim Jagielski 35*0e16a31dSJim Jagielski 36*0e16a31dSJim Jagielskidef new(factory): 37*0e16a31dSJim Jagielski return desk.loadComponentFromURL(factory, "_blank", 0, (pv("Hidden", True),)) 38*0e16a31dSJim Jagielski 39*0e16a31dSJim Jagielski 40*0e16a31dSJim Jagielskidef save(doc, name, filt): 41*0e16a31dSJim Jagielski try: 42*0e16a31dSJim Jagielski doc.storeToURL(uno.systemPathToFileUrl(os.path.join(out, name)), (pv("FilterName", filt),)) 43*0e16a31dSJim Jagielski print("saved", name, filt) 44*0e16a31dSJim Jagielski except Exception as e: 45*0e16a31dSJim Jagielski failed.append(name) 46*0e16a31dSJim Jagielski print("FAIL", name, filt, type(e).__name__, str(e)[:200], repr(e)[:200]) 47*0e16a31dSJim Jagielski 48*0e16a31dSJim Jagielski 49*0e16a31dSJim Jagielskidef attempt(label, fn): 50*0e16a31dSJim Jagielski try: 51*0e16a31dSJim Jagielski fn() 52*0e16a31dSJim Jagielski except Exception as e: 53*0e16a31dSJim Jagielski failed.append(label) 54*0e16a31dSJim Jagielski print("FAIL", label, type(e).__name__, str(e)[:100], repr(e)[:200], "line", traceback.extract_tb(e.__traceback__)[-1].lineno) 55*0e16a31dSJim Jagielski 56*0e16a31dSJim Jagielski 57*0e16a31dSJim Jagielskidef dt(y, mo, d, h, mi): 58*0e16a31dSJim Jagielski return uno.createUnoStruct("com.sun.star.util.DateTime", 0, 0, mi, h, d, mo, y) 59*0e16a31dSJim Jagielski 60*0e16a31dSJim Jagielski 61*0e16a31dSJim Jagielskidef ensure_sheets(doc, n): 62*0e16a31dSJim Jagielski sheets = doc.Sheets 63*0e16a31dSJim Jagielski while sheets.Count > n: 64*0e16a31dSJim Jagielski sheets.removeByName(sheets.getByIndex(sheets.Count - 1).Name) 65*0e16a31dSJim Jagielski while sheets.Count < n: 66*0e16a31dSJim Jagielski sheets.insertNewByName("Sheet%d" % (sheets.Count + 1), sheets.Count) 67*0e16a31dSJim Jagielski return sheets 68*0e16a31dSJim Jagielski 69*0e16a31dSJim Jagielski 70*0e16a31dSJim Jagielskidef put_text(doc, cur, s): 71*0e16a31dSJim Jagielski doc.Text.insertString(cur, s, False) 72*0e16a31dSJim Jagielski 73*0e16a31dSJim Jagielski 74*0e16a31dSJim Jagielskidef put_field(doc, cur, kind, **props): 75*0e16a31dSJim Jagielski f = doc.createInstance("com.sun.star.text.TextField." + kind) 76*0e16a31dSJim Jagielski for k, v in props.items(): 77*0e16a31dSJim Jagielski setattr(f, k, v) 78*0e16a31dSJim Jagielski doc.Text.insertTextContent(cur, f, False) 79*0e16a31dSJim Jagielski return f 80*0e16a31dSJim Jagielski 81*0e16a31dSJim Jagielski 82*0e16a31dSJim Jagielskidef doc_dropdown(): 83*0e16a31dSJim Jagielski doc = new("private:factory/swriter") 84*0e16a31dSJim Jagielski cur = doc.Text.createTextCursor() 85*0e16a31dSJim Jagielski put_text(doc, cur, "First: ") 86*0e16a31dSJim Jagielski put_field(doc, cur, "DropDown", Name="dd1", Items=("one", "two", "three"), SelectedItem="two", Help="help one", Tooltip="tip one") 87*0e16a31dSJim Jagielski doc.Text.insertControlCharacter(cur, 0, False) 88*0e16a31dSJim Jagielski put_text(doc, cur, "Second: ") 89*0e16a31dSJim Jagielski # SwDropDownField accepts only a listed SelectedItem: "zzz" reads back as "" (nothing selected, the field shows "a") 90*0e16a31dSJim Jagielski put_field(doc, cur, "DropDown", Name="dd2", Items=("a", "b"), SelectedItem="zzz", Help="help two", Tooltip="tip two") 91*0e16a31dSJim Jagielski save(doc, "dropdown.odt", "writer8") 92*0e16a31dSJim Jagielski doc.close(True) 93*0e16a31dSJim Jagielski 94*0e16a31dSJim Jagielski 95*0e16a31dSJim Jagielskidef doc_annot(): 96*0e16a31dSJim Jagielski doc = new("private:factory/swriter") 97*0e16a31dSJim Jagielski cur = doc.Text.createTextCursor() 98*0e16a31dSJim Jagielski put_text(doc, cur, "with initials ") 99*0e16a31dSJim Jagielski put_field(doc, cur, "Annotation", Author="Ann Author", Initials="AB", Content="first note", DateTimeValue=dt(2024, 7, 8, 9, 10)) 100*0e16a31dSJim Jagielski doc.Text.insertControlCharacter(cur, 0, False) 101*0e16a31dSJim Jagielski put_text(doc, cur, "without initials ") 102*0e16a31dSJim Jagielski put_field(doc, cur, "Annotation", Author="Bob Author", Content="second note", DateTimeValue=dt(2024, 7, 9, 9, 10)) 103*0e16a31dSJim Jagielski save(doc, "annot.odt", "writer8") 104*0e16a31dSJim Jagielski doc.close(True) 105*0e16a31dSJim Jagielski 106*0e16a31dSJim Jagielski 107*0e16a31dSJim Jagielskidef doc_tabcolor(): 108*0e16a31dSJim Jagielski doc = new("private:factory/scalc") 109*0e16a31dSJim Jagielski sheets = ensure_sheets(doc, 3) 110*0e16a31dSJim Jagielski for i, color in ((0, 0xFF0000), (2, 0x3366CC)): 111*0e16a31dSJim Jagielski sheets.getByIndex(i).TabColor = color 112*0e16a31dSJim Jagielski for i in range(3): 113*0e16a31dSJim Jagielski sheets.getByIndex(i).getCellByPosition(0, 0).setString("sheet %d" % i) 114*0e16a31dSJim Jagielski save(doc, "tabcolor.ods", "calc8") 115*0e16a31dSJim Jagielski doc.close(True) 116*0e16a31dSJim Jagielski 117*0e16a31dSJim Jagielski 118*0e16a31dSJim Jagielskidef doc_scaleto(): 119*0e16a31dSJim Jagielski doc = new("private:factory/scalc") 120*0e16a31dSJim Jagielski ps = doc.StyleFamilies.getByName("PageStyles") 121*0e16a31dSJim Jagielski sheets = ensure_sheets(doc, 4) 122*0e16a31dSJim Jagielski # setting ScaleToPagesX/Y clears ScaleToPages and PageScale in the style (sc/source/ui/unoobj/styleuno.cxx) 123*0e16a31dSJim Jagielski for name, props in (("PS_xy", {"ScaleToPagesX": 2, "ScaleToPagesY": 3}), 124*0e16a31dSJim Jagielski ("PS_x", {"ScaleToPagesX": 2}), 125*0e16a31dSJim Jagielski ("PS_pages", {"ScaleToPages": 4}), 126*0e16a31dSJim Jagielski ("PS_scale", {"PageScale": 80})): 127*0e16a31dSJim Jagielski ps.insertByName(name, doc.createInstance("com.sun.star.style.PageStyle")) 128*0e16a31dSJim Jagielski st = ps.getByName(name) 129*0e16a31dSJim Jagielski for k, v in props.items(): 130*0e16a31dSJim Jagielski setattr(st, k, v) 131*0e16a31dSJim Jagielski for i, name in enumerate(("PS_xy", "PS_x", "PS_pages", "PS_scale")): 132*0e16a31dSJim Jagielski sh = sheets.getByIndex(i) 133*0e16a31dSJim Jagielski sh.PageStyle = name 134*0e16a31dSJim Jagielski sh.getCellByPosition(0, 0).setString(name) 135*0e16a31dSJim Jagielski save(doc, "scaleto.ods", "calc8") 136*0e16a31dSJim Jagielski doc.close(True) 137*0e16a31dSJim Jagielski 138*0e16a31dSJim Jagielski 139*0e16a31dSJim Jagielskidef doc_chart(): 140*0e16a31dSJim Jagielski doc = new("private:factory/scalc") 141*0e16a31dSJim Jagielski sh = doc.Sheets.getByIndex(0) 142*0e16a31dSJim Jagielski for r in range(3): 143*0e16a31dSJim Jagielski sh.getCellByPosition(0, r).setString("c%d" % r) 144*0e16a31dSJim Jagielski sh.getCellByPosition(1, r).setValue(r + 1) 145*0e16a31dSJim Jagielski rect = uno.createUnoStruct("com.sun.star.awt.Rectangle", 1000, 1000, 12000, 9000) 146*0e16a31dSJim Jagielski sh.Charts.addNewByName("C1", rect, (sh.getCellRangeByName("A1:B3").RangeAddress,), True, True) 147*0e16a31dSJim Jagielski ch = sh.Charts.getByName("C1").EmbeddedObject 148*0e16a31dSJim Jagielski ch.HasLegend = True 149*0e16a31dSJim Jagielski dg = ch.Diagram 150*0e16a31dSJim Jagielski # inner plot position in 1/100 mm; the legend is positioned and given a custom size 151*0e16a31dSJim Jagielski dg.setDiagramPositionExcludingAxes(uno.createUnoStruct("com.sun.star.awt.Rectangle", 1500, 1200, 6000, 4500)) 152*0e16a31dSJim Jagielski lg = ch.Legend 153*0e16a31dSJim Jagielski lg.Expansion = uno.Enum("com.sun.star.chart.ChartLegendExpansion", "CUSTOM") 154*0e16a31dSJim Jagielski lg.setSize(uno.createUnoStruct("com.sun.star.awt.Size", 2500, 1800)) 155*0e16a31dSJim Jagielski lg.setPosition(uno.createUnoStruct("com.sun.star.awt.Point", 8800, 1500)) 156*0e16a31dSJim Jagielski r = dg.calculateDiagramPositionExcludingAxes() 157*0e16a31dSJim Jagielski print("diagram excl. axes", r.X, r.Y, r.Width, r.Height, "auto", dg.isAutomaticDiagramPositioning(), "excl", dg.isExcludingDiagramPositioning()) 158*0e16a31dSJim Jagielski print("legend", lg.Expansion.value, lg.getPosition().X, lg.getPosition().Y, lg.getSize().Width, lg.getSize().Height) 159*0e16a31dSJim Jagielski save(doc, "chart.ods", "calc8") 160*0e16a31dSJim Jagielski doc.close(True) 161*0e16a31dSJim Jagielski 162*0e16a31dSJim Jagielski 163*0e16a31dSJim Jagielskifor n, fn in (("dropdown", doc_dropdown), ("annot", doc_annot), ("tabcolor", doc_tabcolor), ("scaleto", doc_scaleto), ("chart", doc_chart)): 164*0e16a31dSJim Jagielski attempt(n, fn) 165*0e16a31dSJim Jagielskisys.exit(1 if failed else 0) 166