2 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
4 # This file is part of the LibreOffice project.
6 # This Source Code Form is subject to the terms of the Mozilla Public
7 # License, v. 2.0. If a copy of the MPL was not distributed with this
8 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 # this should parse a .ui and overwrite it with the same content
11 # for a in `git ls-files "*.ui"`; do bin/ui-converter-skeleton.py $a; done
13 import lxml
.etree
as etree
16 def add_truncate_multiline(current
):
17 use_truncate_multiline
= False
18 istarget
= current
.get('class') == "GtkEntry" or current
.get('class') == "GtkSpinButton"
21 add_truncate_multiline(child
)
22 insertpos
= insertpos
+ 1;
25 if child
.tag
== "property":
26 attributes
= child
.attrib
27 if attributes
.get("name") == "truncate_multiline" or attributes
.get("name") == "truncate-multiline":
28 use_truncate_multiline
= True
30 if istarget
and not use_truncate_multiline
:
31 truncate_multiline
= etree
.Element("property")
32 attributes
= truncate_multiline
.attrib
33 attributes
["name"] = "truncate-multiline"
34 truncate_multiline
.text
= "True"
35 current
.insert(insertpos
- 1, truncate_multiline
)
37 def do_replace_button_use_stock(current
, use_stock
, use_underline
, label
, insertpos
):
39 underline
= etree
.Element("property")
40 attributes
= underline
.attrib
41 attributes
["name"] = "use-underline"
42 underline
.text
= "True"
43 current
.insert(insertpos
- 1, underline
)
44 current
.remove(use_stock
)
45 attributes
= label
.attrib
46 attributes
["translatable"] = "yes"
47 attributes
["context"] = "stock"
48 if label
.text
== 'gtk-add':
50 elif label
.text
== 'gtk-apply':
52 elif label
.text
== 'gtk-cancel':
53 label
.text
= "_Cancel"
54 elif label
.text
== 'gtk-close':
56 elif label
.text
== 'gtk-delete':
57 label
.text
= "_Delete"
58 elif label
.text
== 'gtk-edit':
60 elif label
.text
== 'gtk-help':
62 elif label
.text
== 'gtk-new':
64 elif label
.text
== 'gtk-no':
66 elif label
.text
== 'gtk-ok':
68 elif label
.text
== 'gtk-remove':
69 label
.text
= "_Remove"
70 elif label
.text
== 'gtk-revert-to-saved':
72 elif label
.text
== 'gtk-yes':
75 raise Exception(sys
.argv
[1] + ': unknown label', label
.text
)
77 def replace_button_use_stock(current
):
81 isbutton
= current
.get('class') == "GtkButton"
84 replace_button_use_stock(child
)
85 insertpos
= insertpos
+ 1;
88 if child
.tag
== "property":
89 attributes
= child
.attrib
90 if attributes
.get("name") == "use_underline" or attributes
.get("name") == "use-underline":
92 if attributes
.get("name") == "use_stock" or attributes
.get("name") == "use-stock":
94 if attributes
.get("name") == "label":
97 if isbutton
and use_stock
!= None:
98 do_replace_button_use_stock(current
, use_stock
, use_underline
, label
, insertpos
)
100 def do_replace_image_stock(current
, stock
):
101 attributes
= stock
.attrib
102 attributes
["name"] = "icon-name"
103 if stock
.text
== 'gtk-add':
104 stock
.text
= "list-add"
105 elif stock
.text
== 'gtk-remove':
106 stock
.text
= "list-remove"
107 elif stock
.text
== 'gtk-paste':
108 stock
.text
= "edit-paste"
109 elif stock
.text
== 'gtk-index':
110 stock
.text
= "vcl/res/index.png"
111 elif stock
.text
== 'gtk-refresh':
112 stock
.text
= "view-refresh"
113 elif stock
.text
== 'gtk-dialog-error':
114 stock
.text
= "dialog-error"
115 elif stock
.text
== 'gtk-apply':
116 stock
.text
= "sw/res/sc20558.png"
117 elif stock
.text
== 'gtk-missing-image':
118 stock
.text
= "missing-image"
119 elif stock
.text
== 'gtk-copy':
120 stock
.text
= "edit-copy"
121 elif stock
.text
== 'gtk-go-back':
122 stock
.text
= "go-previous"
123 elif stock
.text
== 'gtk-go-forward':
124 stock
.text
= "go-next"
125 elif stock
.text
== 'gtk-go-down':
126 stock
.text
= "go-down"
127 elif stock
.text
== 'gtk-go-up':
129 elif stock
.text
== 'gtk-goto-first':
130 stock
.text
= "go-first"
131 elif stock
.text
== 'gtk-goto-last':
132 stock
.text
= "go-last"
133 elif stock
.text
== 'gtk-new':
134 stock
.text
= "document-new"
135 elif stock
.text
== 'gtk-media-stop':
136 stock
.text
= "media-playback-stop"
137 elif stock
.text
== 'gtk-media-play':
138 stock
.text
= "media-playback-start"
139 elif stock
.text
== 'gtk-media-next':
140 stock
.text
= "media-skip-forward"
141 elif stock
.text
== 'gtk-media-previous':
142 stock
.text
= "media-skip-backward"
143 elif stock
.text
== 'gtk-close':
144 stock
.text
= "window-close"
145 elif stock
.text
== 'gtk-help':
146 stock
.text
= "help-browser"
148 raise Exception(sys
.argv
[1] + ': unknown stock name', stock
.text
)
150 def replace_image_stock(current
):
152 isimage
= current
.get('class') == "GtkImage"
153 for child
in current
:
154 replace_image_stock(child
)
157 if child
.tag
== "property":
158 attributes
= child
.attrib
159 if attributes
.get("name") == "stock":
162 if isimage
and stock
!= None:
163 do_replace_image_stock(current
, stock
)
165 def remove_check_button_align(current
):
168 ischeckorradiobutton
= current
.get('class') == "GtkCheckButton" or current
.get('class') == "GtkRadioButton"
169 for child
in current
:
170 remove_check_button_align(child
)
171 if not ischeckorradiobutton
:
173 if child
.tag
== "property":
174 attributes
= child
.attrib
175 if attributes
.get("name") == "xalign":
177 if attributes
.get("name") == "yalign":
180 if ischeckorradiobutton
:
182 if xalign
.text
!= "0":
183 raise Exception(sys
.argv
[1] + ': non-default xalign', xalign
.text
)
184 current
.remove(xalign
)
186 if yalign
.text
!= "0.5":
187 raise Exception(sys
.argv
[1] + ': non-default yalign', yalign
.text
)
188 current
.remove(yalign
)
190 with
open(sys
.argv
[1], encoding
="utf-8") as f
:
191 header
= f
.readline()
192 firstline
= f
.readline()
193 # the comment after the xml declaration goes missing unless we provide a
194 # custom doctype with tostring that contains the comment as a line after
196 if firstline
.startswith("<!--"):
197 header
= header
+ firstline
199 # remove_blank_text so pretty-printed input doesn't disrupt pretty-printed
200 # output if nodes are added or removed
201 parser
= etree
.XMLParser(remove_blank_text
=True)
202 tree
= etree
.parse(f
, parser
)
203 # make sure <property name="label" translatable="no"></property> stays like that
204 # and doesn't change to <property name="label" translatable="no"/>
205 for status_elem
in tree
.xpath("//property[@name='label' and string() = '']"):
206 status_elem
.text
= ""
207 root
= tree
.getroot()
209 # do some targeted conversion here
210 # tdf#138848 Copy-and-Paste in input box should not append an ENTER character
211 if not sys
.argv
[1].endswith('/multiline.ui'): # let this one alone not truncate multiline pastes
212 add_truncate_multiline(root
)
213 replace_button_use_stock(root
)
214 replace_image_stock(root
)
215 remove_check_button_align(root
)
217 with
open(sys
.argv
[1], 'wb') as o
:
218 # without encoding='unicode' (and the matching encode("utf8")) we get &#XXXX replacements for non-ascii characters
219 # which we don't want to see changed in the output
220 o
.write(etree
.tostring(root
, pretty_print
=True, method
='xml', encoding
='unicode', doctype
=header
[0:-1]).encode("utf8"))
222 # vim: set shiftwidth=4 softtabstop=4 expandtab: