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