From 2b4b532179725e69c8df7deceae9158b9beed560 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Wed, 12 May 2021 16:36:09 +0100 Subject: rename ui-converter-skeleton to ui-rules-enforcer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I1cc0fd704be075a7c387363a49bd84b159831aca Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115493 Tested-by: Jenkins Reviewed-by: Caolán McNamara --- bin/ui-converter-skeleton.py | 216 ------------------------------------------ bin/ui-rules-enforcer.py | 221 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+), 216 deletions(-) delete mode 100755 bin/ui-converter-skeleton.py create mode 100755 bin/ui-rules-enforcer.py (limited to 'bin') diff --git a/bin/ui-converter-skeleton.py b/bin/ui-converter-skeleton.py deleted file mode 100755 index 49c23669e800..000000000000 --- a/bin/ui-converter-skeleton.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/python -# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- -# -# This file is part of the LibreOffice project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -# this should parse a .ui and overwrite it with the same content -# for a in `git ls-files "*.ui"`; do bin/ui-converter-skeleton.py $a; done - -import lxml.etree as etree -import sys - -def add_truncate_multiline(current): - use_truncate_multiline = False - istarget = current.get('class') == "GtkEntry" or current.get('class') == "GtkSpinButton" - insertpos = 0 - for child in current: - add_truncate_multiline(child) - insertpos = insertpos + 1; - if not istarget: - continue - if child.tag == "property": - attributes = child.attrib - if attributes.get("name") == "truncate_multiline" or attributes.get("name") == "truncate-multiline": - use_truncate_multiline = True - - if istarget and not use_truncate_multiline: - truncate_multiline = etree.Element("property") - attributes = truncate_multiline.attrib - attributes["name"] = "truncate-multiline" - truncate_multiline.text = "True" - current.insert(insertpos - 1, truncate_multiline) - -def do_replace_button_use_stock(current, use_stock, use_underline, label, insertpos): - if not use_underline: - underline = etree.Element("property") - attributes = underline.attrib - attributes["name"] = "use-underline" - underline.text = "True" - current.insert(insertpos - 1, underline) - current.remove(use_stock) - attributes = label.attrib - attributes["translatable"] = "yes" - attributes["context"] = "stock" - if label.text == 'gtk-add': - label.text = "_Add" - elif label.text == 'gtk-apply': - label.text = "_Apply" - elif label.text == 'gtk-cancel': - label.text = "_Cancel" - elif label.text == 'gtk-close': - label.text = "_Close" - elif label.text == 'gtk-delete': - label.text = "_Delete" - elif label.text == 'gtk-edit': - label.text = "_Edit" - elif label.text == 'gtk-help': - label.text = "_Help" - elif label.text == 'gtk-new': - label.text = "_New" - elif label.text == 'gtk-no': - label.text = "_No" - elif label.text == 'gtk-ok': - label.text = "_OK" - elif label.text == 'gtk-remove': - label.text = "_Remove" - elif label.text == 'gtk-revert-to-saved': - label.text = "_Reset" - elif label.text == 'gtk-yes': - label.text = "_Yes" - else: - raise Exception(sys.argv[1] + ': unknown label', label.text) - -def replace_button_use_stock(current): - use_underline = False - use_stock = None - label = None - isbutton = current.get('class') == "GtkButton" - insertpos = 0 - for child in current: - replace_button_use_stock(child) - insertpos = insertpos + 1; - if not isbutton: - continue - if child.tag == "property": - attributes = child.attrib - if attributes.get("name") == "use_underline" or attributes.get("name") == "use-underline": - use_underline = True - if attributes.get("name") == "use_stock" or attributes.get("name") == "use-stock": - use_stock = child - if attributes.get("name") == "label": - label = child - - if isbutton and use_stock != None: - do_replace_button_use_stock(current, use_stock, use_underline, label, insertpos) - -def do_replace_image_stock(current, stock): - attributes = stock.attrib - attributes["name"] = "icon-name" - if stock.text == 'gtk-add': - stock.text = "list-add" - elif stock.text == 'gtk-remove': - stock.text = "list-remove" - elif stock.text == 'gtk-paste': - stock.text = "edit-paste" - elif stock.text == 'gtk-index': - stock.text = "vcl/res/index.png" - elif stock.text == 'gtk-refresh': - stock.text = "view-refresh" - elif stock.text == 'gtk-dialog-error': - stock.text = "dialog-error" - elif stock.text == 'gtk-apply': - stock.text = "sw/res/sc20558.png" - elif stock.text == 'gtk-missing-image': - stock.text = "missing-image" - elif stock.text == 'gtk-copy': - stock.text = "edit-copy" - elif stock.text == 'gtk-go-back': - stock.text = "go-previous" - elif stock.text == 'gtk-go-forward': - stock.text = "go-next" - elif stock.text == 'gtk-go-down': - stock.text = "go-down" - elif stock.text == 'gtk-go-up': - stock.text = "go-up" - elif stock.text == 'gtk-goto-first': - stock.text = "go-first" - elif stock.text == 'gtk-goto-last': - stock.text = "go-last" - elif stock.text == 'gtk-new': - stock.text = "document-new" - elif stock.text == 'gtk-media-stop': - stock.text = "media-playback-stop" - elif stock.text == 'gtk-media-play': - stock.text = "media-playback-start" - elif stock.text == 'gtk-media-next': - stock.text = "media-skip-forward" - elif stock.text == 'gtk-media-previous': - stock.text = "media-skip-backward" - elif stock.text == 'gtk-close': - stock.text = "window-close" - elif stock.text == 'gtk-help': - stock.text = "help-browser" - else: - raise Exception(sys.argv[1] + ': unknown stock name', stock.text) - -def replace_image_stock(current): - stock = None - isimage = current.get('class') == "GtkImage" - for child in current: - replace_image_stock(child) - if not isimage: - continue - if child.tag == "property": - attributes = child.attrib - if attributes.get("name") == "stock": - stock = child - - if isimage and stock != None: - do_replace_image_stock(current, stock) - -def remove_check_button_align(current): - xalign = None - yalign = None - ischeckorradiobutton = current.get('class') == "GtkCheckButton" or current.get('class') == "GtkRadioButton" - for child in current: - remove_check_button_align(child) - if not ischeckorradiobutton: - continue - if child.tag == "property": - attributes = child.attrib - if attributes.get("name") == "xalign": - xalign = child - if attributes.get("name") == "yalign": - yalign = child - - if ischeckorradiobutton: - if xalign != None: - if xalign.text != "0": - raise Exception(sys.argv[1] + ': non-default xalign', xalign.text) - current.remove(xalign) - if yalign != None: - if yalign.text != "0.5": - raise Exception(sys.argv[1] + ': non-default yalign', yalign.text) - current.remove(yalign) - -with open(sys.argv[1], encoding="utf-8") as f: - header = f.readline() - f.seek(0) - # remove_blank_text so pretty-printed input doesn't disrupt pretty-printed - # output if nodes are added or removed - parser = etree.XMLParser(remove_blank_text=True) - tree = etree.parse(f, parser) - # make sure stays like that - # and doesn't change to - for status_elem in tree.xpath("//property[@name='label' and string() = '']"): - status_elem.text = "" - root = tree.getroot() - -# do some targeted conversion here -# tdf#138848 Copy-and-Paste in input box should not append an ENTER character -if not sys.argv[1].endswith('/multiline.ui'): # let this one alone not truncate multiline pastes - add_truncate_multiline(root) -replace_button_use_stock(root) -replace_image_stock(root) -remove_check_button_align(root) - -with open(sys.argv[1], 'wb') as o: - # without encoding='unicode' (and the matching encode("utf8")) we get &#XXXX replacements for non-ascii characters - # which we don't want to see changed in the output - o.write(etree.tostring(tree, pretty_print=True, method='xml', encoding='unicode', doctype=header[0:-1]).encode("utf8")) - -# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/bin/ui-rules-enforcer.py b/bin/ui-rules-enforcer.py new file mode 100755 index 000000000000..e981ade27b26 --- /dev/null +++ b/bin/ui-rules-enforcer.py @@ -0,0 +1,221 @@ +#!/bin/python +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# ui-rules-enforcer enforces the .ui rules and properties used by LibreOffice +# mostly the deprecations of +# https://developer.gnome.org/gtk4/stable/gtk-migrating-3-to-4.html +# and a few other home cooked rules + +# for any existing .ui this should parse it and overwrite it with the same content +# e.g. for a in `git ls-files "*.ui"`; do bin/ui-rules-enforcer.py $a; done + +import lxml.etree as etree +import sys + +def add_truncate_multiline(current): + use_truncate_multiline = False + istarget = current.get('class') == "GtkEntry" or current.get('class') == "GtkSpinButton" + insertpos = 0 + for child in current: + add_truncate_multiline(child) + insertpos = insertpos + 1; + if not istarget: + continue + if child.tag == "property": + attributes = child.attrib + if attributes.get("name") == "truncate_multiline" or attributes.get("name") == "truncate-multiline": + use_truncate_multiline = True + + if istarget and not use_truncate_multiline: + truncate_multiline = etree.Element("property") + attributes = truncate_multiline.attrib + attributes["name"] = "truncate-multiline" + truncate_multiline.text = "True" + current.insert(insertpos - 1, truncate_multiline) + +def do_replace_button_use_stock(current, use_stock, use_underline, label, insertpos): + if not use_underline: + underline = etree.Element("property") + attributes = underline.attrib + attributes["name"] = "use-underline" + underline.text = "True" + current.insert(insertpos - 1, underline) + current.remove(use_stock) + attributes = label.attrib + attributes["translatable"] = "yes" + attributes["context"] = "stock" + if label.text == 'gtk-add': + label.text = "_Add" + elif label.text == 'gtk-apply': + label.text = "_Apply" + elif label.text == 'gtk-cancel': + label.text = "_Cancel" + elif label.text == 'gtk-close': + label.text = "_Close" + elif label.text == 'gtk-delete': + label.text = "_Delete" + elif label.text == 'gtk-edit': + label.text = "_Edit" + elif label.text == 'gtk-help': + label.text = "_Help" + elif label.text == 'gtk-new': + label.text = "_New" + elif label.text == 'gtk-no': + label.text = "_No" + elif label.text == 'gtk-ok': + label.text = "_OK" + elif label.text == 'gtk-remove': + label.text = "_Remove" + elif label.text == 'gtk-revert-to-saved': + label.text = "_Reset" + elif label.text == 'gtk-yes': + label.text = "_Yes" + else: + raise Exception(sys.argv[1] + ': unknown label', label.text) + +def replace_button_use_stock(current): + use_underline = False + use_stock = None + label = None + isbutton = current.get('class') == "GtkButton" + insertpos = 0 + for child in current: + replace_button_use_stock(child) + insertpos = insertpos + 1; + if not isbutton: + continue + if child.tag == "property": + attributes = child.attrib + if attributes.get("name") == "use_underline" or attributes.get("name") == "use-underline": + use_underline = True + if attributes.get("name") == "use_stock" or attributes.get("name") == "use-stock": + use_stock = child + if attributes.get("name") == "label": + label = child + + if isbutton and use_stock != None: + do_replace_button_use_stock(current, use_stock, use_underline, label, insertpos) + +def do_replace_image_stock(current, stock): + attributes = stock.attrib + attributes["name"] = "icon-name" + if stock.text == 'gtk-add': + stock.text = "list-add" + elif stock.text == 'gtk-remove': + stock.text = "list-remove" + elif stock.text == 'gtk-paste': + stock.text = "edit-paste" + elif stock.text == 'gtk-index': + stock.text = "vcl/res/index.png" + elif stock.text == 'gtk-refresh': + stock.text = "view-refresh" + elif stock.text == 'gtk-dialog-error': + stock.text = "dialog-error" + elif stock.text == 'gtk-apply': + stock.text = "sw/res/sc20558.png" + elif stock.text == 'gtk-missing-image': + stock.text = "missing-image" + elif stock.text == 'gtk-copy': + stock.text = "edit-copy" + elif stock.text == 'gtk-go-back': + stock.text = "go-previous" + elif stock.text == 'gtk-go-forward': + stock.text = "go-next" + elif stock.text == 'gtk-go-down': + stock.text = "go-down" + elif stock.text == 'gtk-go-up': + stock.text = "go-up" + elif stock.text == 'gtk-goto-first': + stock.text = "go-first" + elif stock.text == 'gtk-goto-last': + stock.text = "go-last" + elif stock.text == 'gtk-new': + stock.text = "document-new" + elif stock.text == 'gtk-media-stop': + stock.text = "media-playback-stop" + elif stock.text == 'gtk-media-play': + stock.text = "media-playback-start" + elif stock.text == 'gtk-media-next': + stock.text = "media-skip-forward" + elif stock.text == 'gtk-media-previous': + stock.text = "media-skip-backward" + elif stock.text == 'gtk-close': + stock.text = "window-close" + elif stock.text == 'gtk-help': + stock.text = "help-browser" + else: + raise Exception(sys.argv[1] + ': unknown stock name', stock.text) + +def replace_image_stock(current): + stock = None + isimage = current.get('class') == "GtkImage" + for child in current: + replace_image_stock(child) + if not isimage: + continue + if child.tag == "property": + attributes = child.attrib + if attributes.get("name") == "stock": + stock = child + + if isimage and stock != None: + do_replace_image_stock(current, stock) + +def remove_check_button_align(current): + xalign = None + yalign = None + ischeckorradiobutton = current.get('class') == "GtkCheckButton" or current.get('class') == "GtkRadioButton" + for child in current: + remove_check_button_align(child) + if not ischeckorradiobutton: + continue + if child.tag == "property": + attributes = child.attrib + if attributes.get("name") == "xalign": + xalign = child + if attributes.get("name") == "yalign": + yalign = child + + if ischeckorradiobutton: + if xalign != None: + if xalign.text != "0": + raise Exception(sys.argv[1] + ': non-default xalign', xalign.text) + current.remove(xalign) + if yalign != None: + if yalign.text != "0.5": + raise Exception(sys.argv[1] + ': non-default yalign', yalign.text) + current.remove(yalign) + +with open(sys.argv[1], encoding="utf-8") as f: + header = f.readline() + f.seek(0) + # remove_blank_text so pretty-printed input doesn't disrupt pretty-printed + # output if nodes are added or removed + parser = etree.XMLParser(remove_blank_text=True) + tree = etree.parse(f, parser) + # make sure stays like that + # and doesn't change to + for status_elem in tree.xpath("//property[@name='label' and string() = '']"): + status_elem.text = "" + root = tree.getroot() + +# do some targeted conversion here +# tdf#138848 Copy-and-Paste in input box should not append an ENTER character +if not sys.argv[1].endswith('/multiline.ui'): # let this one alone not truncate multiline pastes + add_truncate_multiline(root) +replace_button_use_stock(root) +replace_image_stock(root) +remove_check_button_align(root) + +with open(sys.argv[1], 'wb') as o: + # without encoding='unicode' (and the matching encode("utf8")) we get &#XXXX replacements for non-ascii characters + # which we don't want to see changed in the output + o.write(etree.tostring(tree, pretty_print=True, method='xml', encoding='unicode', doctype=header[0:-1]).encode("utf8")) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: -- cgit