Blame gtk/gtk-builder-convert

Packit Service d193bd
#!/usr/bin/python3
Packit Service fb6fa5
#
Packit Service fb6fa5
# Copyright (C) 2006-2008 Async Open Source
Packit Service fb6fa5
#                         Henrique Romano <henrique@async.com.br>
Packit Service fb6fa5
#                         Johan Dahlin <jdahlin@async.com.br>
Packit Service fb6fa5
#
Packit Service fb6fa5
# This program is free software; you can redistribute it and/or
Packit Service fb6fa5
# modify it under the terms of the GNU Lesser General Public License
Packit Service fb6fa5
# as published by the Free Software Foundation; either version 2
Packit Service fb6fa5
# of the License, or (at your option) any later version.
Packit Service fb6fa5
#
Packit Service fb6fa5
# This program is distributed in the hope that it will be useful,
Packit Service fb6fa5
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fb6fa5
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fb6fa5
# GNU General Public License for more details.
Packit Service fb6fa5
#
Packit Service fb6fa5
# You should have received a copy of the GNU Lesser General Public License
Packit Service fb6fa5
# along with this program; if not, write to the Free Software
Packit Service fb6fa5
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Packit Service fb6fa5
#
Packit Service fb6fa5
# TODO:
Packit Service fb6fa5
#  Toolbars
Packit Service fb6fa5
Packit Service fb6fa5
"""Usage: gtk-builder-convert [OPTION] [INPUT] [OUTPUT]
Packit Service fb6fa5
Converts Glade files into XML files which can be loaded with GtkBuilder.
Packit Service fb6fa5
The [INPUT] file is
Packit Service fb6fa5
Packit Service fb6fa5
  -w, --skip-windows     Convert everything but GtkWindow subclasses.
Packit Service fb6fa5
  -r, --root             Convert only widget named root and its children
Packit Service fb6fa5
  -h, --help             display this help and exit
Packit Service fb6fa5
Packit Service fb6fa5
When OUTPUT is -, write to standard output.
Packit Service fb6fa5
Packit Service fb6fa5
Examples:
Packit Service fb6fa5
  gtk-builder-convert preference.glade preferences.ui
Packit Service fb6fa5
Packit Service fb6fa5
Report bugs to http://bugzilla.gnome.org/."""
Packit Service fb6fa5
Packit Service 51d9ba
from __future__ import print_function
Packit Service fb6fa5
import getopt
Packit Service fb6fa5
import os
Packit Service fb6fa5
import sys
Packit Service 51d9ba
import subprocess
Packit Service fb6fa5
from xml.dom import minidom, Node
Packit Service fb6fa5
Packit Service fb6fa5
DIALOGS = ['GtkDialog',
Packit Service fb6fa5
           'GtkFileChooserDialog',
Packit Service fb6fa5
           'GtkMessageDialog']
Packit Service fb6fa5
WINDOWS = ['GtkWindow'] + DIALOGS
Packit Service fb6fa5
Packit Service fb6fa5
def get_child_nodes(node):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    nodes = []
Packit Service fb6fa5
    for child in node.childNodes:
Packit Service fb6fa5
        if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if child.tagName != 'child':
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        nodes.append(child)
Packit Service fb6fa5
    return nodes
Packit Service fb6fa5
Packit Service fb6fa5
def get_properties(node):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    properties = {}
Packit Service fb6fa5
    for child in node.childNodes:
Packit Service fb6fa5
        if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if child.tagName != 'property':
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        value = child.childNodes[0].data
Packit Service fb6fa5
        properties[child.getAttribute('name')] = value
Packit Service fb6fa5
    return properties
Packit Service fb6fa5
Packit Service fb6fa5
def get_property(node, property_name):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    properties = get_properties(node)
Packit Service fb6fa5
    return properties.get(property_name)
Packit Service fb6fa5
Packit Service fb6fa5
def get_property_node(node, property_name):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    properties = {}
Packit Service fb6fa5
    for child in node.childNodes:
Packit Service fb6fa5
        if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if child.tagName != 'property':
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if child.getAttribute('name') == property_name:
Packit Service fb6fa5
            return child
Packit Service fb6fa5
Packit Service fb6fa5
def get_signal_nodes(node):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    signals = []
Packit Service fb6fa5
    for child in node.childNodes:
Packit Service fb6fa5
        if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if child.tagName == 'signal':
Packit Service fb6fa5
            signals.append(child)
Packit Service fb6fa5
    return signals
Packit Service fb6fa5
Packit Service fb6fa5
def get_property_nodes(node):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    properties = []
Packit Service fb6fa5
    for child in node.childNodes:
Packit Service fb6fa5
        if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        # FIXME: handle comments
Packit Service fb6fa5
        if child.tagName == 'property':
Packit Service fb6fa5
            properties.append(child)
Packit Service fb6fa5
    return properties
Packit Service fb6fa5
Packit Service fb6fa5
def get_accelerator_nodes(node):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    accelerators = []
Packit Service fb6fa5
    for child in node.childNodes:
Packit Service fb6fa5
        if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if child.tagName == 'accelerator':
Packit Service fb6fa5
            accelerators.append(child)
Packit Service fb6fa5
    return accelerators
Packit Service fb6fa5
Packit Service fb6fa5
def get_object_node(child_node):
Packit Service fb6fa5
    assert child_node.tagName == 'child', child_node
Packit Service fb6fa5
    nodes = []
Packit Service fb6fa5
    for node in child_node.childNodes:
Packit Service fb6fa5
        if node.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
            continue
Packit Service fb6fa5
        if node.tagName == 'object':
Packit Service fb6fa5
            nodes.append(node)
Packit Service fb6fa5
    assert len(nodes) == 1, nodes
Packit Service fb6fa5
    return nodes[0]
Packit Service fb6fa5
Packit Service fb6fa5
def copy_properties(node, props, prop_dict):
Packit Service fb6fa5
    assert node.tagName == 'object'
Packit Service fb6fa5
    for prop_name in props:
Packit Service fb6fa5
        child = get_property_node(node, prop_name)
Packit Service fb6fa5
        if child is not None:
Packit Service fb6fa5
            prop_dict[prop_name] = child
Packit Service fb6fa5
Packit Service fb6fa5
    return node
Packit Service fb6fa5
Packit Service fb6fa5
class GtkBuilderConverter(object):
Packit Service fb6fa5
Packit Service fb6fa5
    def __init__(self, skip_windows, target_version, root):
Packit Service fb6fa5
        self.skip_windows = skip_windows
Packit Service fb6fa5
        self.target_version = target_version
Packit Service fb6fa5
        self.root = root
Packit Service fb6fa5
        self.root_objects = []
Packit Service fb6fa5
        self.objects = {}
Packit Service fb6fa5
Packit Service fb6fa5
    #
Packit Service fb6fa5
    # Public API
Packit Service fb6fa5
    #
Packit Service fb6fa5
Packit Service fb6fa5
    def parse_file(self, file):
Packit Service fb6fa5
        self._dom = minidom.parse(file)
Packit Service fb6fa5
        self._parse()
Packit Service fb6fa5
Packit Service fb6fa5
    def parse_buffer(self, buffer):
Packit Service fb6fa5
        self._dom = minidom.parseString(buffer)
Packit Service fb6fa5
        self._parse()
Packit Service fb6fa5
Packit Service fb6fa5
    def to_xml(self):
Packit Service fb6fa5
        xml = self._dom.toprettyxml("", "")
Packit Service 51d9ba
        if sys.version_info < (3, 0):
Packit Service 51d9ba
            # Python 2: convert with explicit encoding
Packit Service 51d9ba
            # (For Python 3, the result is left as text)
Packit Service 51d9ba
            xml = xml.encode('utf-8')
Packit Service 51d9ba
        return xml
Packit Service fb6fa5
Packit Service fb6fa5
    #
Packit Service fb6fa5
    # Private
Packit Service fb6fa5
    #
Packit Service fb6fa5
Packit Service fb6fa5
    def _get_object(self, name):
Packit Service fb6fa5
        return self.objects.get(name)
Packit Service fb6fa5
Packit Service fb6fa5
    def _get_objects_by_attr(self, attribute, value):
Packit Service fb6fa5
        return [w for w in self._dom.getElementsByTagName("object")
Packit Service fb6fa5
                      if w.getAttribute(attribute) == value]
Packit Service fb6fa5
Packit Service fb6fa5
    def _create_object(self, obj_class, obj_id, template=None, properties=None):
Packit Service fb6fa5
        """
Packit Service fb6fa5
        Creates a new <object> tag.
Packit Service fb6fa5
        Optionally a name template can be provided which will be used
Packit Service fb6fa5
        to avoid naming collisions.
Packit Service fb6fa5
        The properties dictionary can either contain string values or Node
Packit Service fb6fa5
        values. If a node is provided the name of the node will be overridden
Packit Service fb6fa5
        by the dictionary key.
Packit Service fb6fa5
Packit Service fb6fa5
        @param obj_class: class of the object (class tag)
Packit Service fb6fa5
        @param obj_id: identifier of the object (id tag)
Packit Service fb6fa5
        @param template: name template to use, for example 'button'
Packit Service fb6fa5
        @param properties: dictionary of properties
Packit Service fb6fa5
        @type properties: string or Node.
Packit Service fb6fa5
        @returns: Newly created node of the object
Packit Service fb6fa5
        """
Packit Service fb6fa5
        if template is not None:
Packit Service fb6fa5
            count = 1
Packit Service fb6fa5
            while True:
Packit Service fb6fa5
                obj_id = template + str(count)
Packit Service fb6fa5
                widget = self._get_object(obj_id)
Packit Service fb6fa5
                if widget is None:
Packit Service fb6fa5
                    break
Packit Service fb6fa5
Packit Service fb6fa5
                count += 1
Packit Service fb6fa5
Packit Service fb6fa5
        obj = self._dom.createElement('object')
Packit Service fb6fa5
        obj.setAttribute('class', obj_class)
Packit Service fb6fa5
        obj.setAttribute('id', obj_id)
Packit Service fb6fa5
        if properties:
Packit Service fb6fa5
            for name, value in properties.items():
Packit Service fb6fa5
                if isinstance(value, Node):
Packit Service fb6fa5
                    # Reuse the node, so translatable and context still will be
Packit Service fb6fa5
                    # set when converting nodes. See also #509153
Packit Service fb6fa5
                    prop = value
Packit Service fb6fa5
                else:
Packit Service fb6fa5
                    prop = self._dom.createElement('property')
Packit Service fb6fa5
                    prop.appendChild(self._dom.createTextNode(value))
Packit Service fb6fa5
Packit Service fb6fa5
                prop.setAttribute('name', str(name))
Packit Service fb6fa5
                obj.appendChild(prop)
Packit Service fb6fa5
        self.objects[obj_id] = obj
Packit Service fb6fa5
        return obj
Packit Service fb6fa5
Packit Service fb6fa5
    def _create_root_object(self, obj_class, template, properties=None):
Packit Service fb6fa5
        obj = self._create_object(obj_class, None, template, properties)
Packit Service fb6fa5
        self.root_objects.append(obj)
Packit Service fb6fa5
        return obj
Packit Service fb6fa5
Packit Service fb6fa5
    def _parse(self):
Packit Service fb6fa5
        glade_iface = self._dom.getElementsByTagName("glade-interface")
Packit Service fb6fa5
        assert glade_iface, ("Badly formed XML, there is "
Packit Service fb6fa5
                             "no <glade-interface> tag.")
Packit Service fb6fa5
        # Rename glade-interface to interface
Packit Service fb6fa5
        glade_iface[0].tagName = 'interface'
Packit Service fb6fa5
        self._interface = glade_iface[0]
Packit Service fb6fa5
Packit Service fb6fa5
        # Remove glade-interface doc type
Packit Service fb6fa5
        for node in self._dom.childNodes:
Packit Service fb6fa5
            if node.nodeType == Node.DOCUMENT_TYPE_NODE:
Packit Service fb6fa5
                if node.name == 'glade-interface':
Packit Service fb6fa5
                    self._dom.removeChild(node)
Packit Service fb6fa5
Packit Service fb6fa5
        # Strip unsupported tags
Packit Service fb6fa5
        for tag in ['requires', 'requires-version']:
Packit Service fb6fa5
            for child in self._dom.getElementsByTagName(tag):
Packit Service fb6fa5
                child.parentNode.removeChild(child)
Packit Service fb6fa5
Packit Service fb6fa5
        if self.root:
Packit Service fb6fa5
            self._strip_root(self.root)
Packit Service fb6fa5
Packit Service fb6fa5
        # Rename widget to object
Packit Service fb6fa5
        objects = self._dom.getElementsByTagName("widget")
Packit Service fb6fa5
        for node in objects:
Packit Service fb6fa5
            node.tagName = "object"
Packit Service fb6fa5
Packit Service fb6fa5
        for node in objects:
Packit Service fb6fa5
            self._convert(node.getAttribute("class"), node)
Packit Service fb6fa5
            if self._get_object(node.getAttribute('id')) is not None:
Packit Service 51d9ba
                print("WARNING: duplicate id \"" + node.getAttribute('id') + "\"")
Packit Service fb6fa5
            self.objects[node.getAttribute('id')] = node
Packit Service fb6fa5
Packit Service fb6fa5
        # Convert Gazpachos UI tag
Packit Service fb6fa5
        for node in self._dom.getElementsByTagName("ui"):
Packit Service fb6fa5
            self._convert_ui(node)
Packit Service fb6fa5
Packit Service fb6fa5
        # Convert accessibility tag
Packit Service fb6fa5
        for node in self._dom.getElementsByTagName("accessibility"):
Packit Service fb6fa5
            self._convert_accessibility(node)
Packit Service fb6fa5
Packit Service fb6fa5
        # Output the newly created root objects and sort them
Packit Service fb6fa5
        # by attribute id
Packit Service 51d9ba
        root_objects = sorted(self.root_objects,
Packit Service 51d9ba
                              key=lambda n: n.getAttribute('id'),
Packit Service 51d9ba
                              reverse=True)
Packit Service fb6fa5
        for obj in root_objects:
Packit Service fb6fa5
            self._interface.childNodes.insert(0, obj)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert(self, klass, node):
Packit Service fb6fa5
        if klass == 'GtkNotebook':
Packit Service fb6fa5
            self._packing_prop_to_child_attr(node, "type", "tab")
Packit Service fb6fa5
        elif klass in ['GtkExpander', 'GtkFrame']:
Packit Service fb6fa5
            self._packing_prop_to_child_attr(
Packit Service fb6fa5
                node, "type", "label_item", "label")
Packit Service fb6fa5
        elif klass == "GtkMenuBar":
Packit Service fb6fa5
            self._convert_menu(node)
Packit Service fb6fa5
        elif klass == "GtkMenu":
Packit Service fb6fa5
            # Only convert toplevel popups
Packit Service fb6fa5
            if node.parentNode == self._interface:
Packit Service fb6fa5
                self._convert_menu(node, popup=True)
Packit Service fb6fa5
        elif klass in WINDOWS and self.skip_windows:
Packit Service fb6fa5
            self._remove_window(node)
Packit Service fb6fa5
Packit Service fb6fa5
        if self.target_version == "3.0":
Packit Service fb6fa5
            if klass == "GtkComboBoxEntry":
Packit Service fb6fa5
                node.setAttribute("class","GtkComboBox")
Packit Service fb6fa5
                prop = self._dom.createElement("property")
Packit Service fb6fa5
                prop.setAttribute("name", "has-entry")
Packit Service fb6fa5
                prop.appendChild(self._dom.createTextNode("True"))
Packit Service fb6fa5
                node.appendChild(prop)
Packit Service fb6fa5
            elif klass == "GtkDialog":
Packit Service fb6fa5
                for child in node.childNodes:
Packit Service fb6fa5
                    if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
                        continue
Packit Service fb6fa5
                    if child.tagName != 'property':
Packit Service fb6fa5
                        continue
Packit Service fb6fa5
                    if (child.getAttribute("name") not in ("has-separator", "has_separator")):
Packit Service fb6fa5
                        continue;
Packit Service fb6fa5
                    node.removeChild(child)
Packit Service fb6fa5
                    break
Packit Service fb6fa5
Packit Service fb6fa5
        self._default_widget_converter(node)
Packit Service fb6fa5
Packit Service fb6fa5
    def _default_widget_converter(self, node):
Packit Service fb6fa5
        klass = node.getAttribute("class")
Packit Service fb6fa5
        for prop in get_property_nodes(node):
Packit Service fb6fa5
            prop_name = prop.getAttribute("name")
Packit Service fb6fa5
            if prop_name == "sizegroup":
Packit Service fb6fa5
                self._convert_sizegroup(node, prop)
Packit Service fb6fa5
            elif prop_name == "tooltip" and klass != "GtkAction":
Packit Service fb6fa5
                prop.setAttribute("name", "tooltip-text")
Packit Service fb6fa5
            elif prop_name in ["response_id", 'response-id']:
Packit Service fb6fa5
                # It does not make sense to convert responses when
Packit Service fb6fa5
                # we're not going to output dialogs
Packit Service fb6fa5
                if self.skip_windows:
Packit Service fb6fa5
                    continue
Packit Service fb6fa5
                object_id = node.getAttribute('id')
Packit Service fb6fa5
                response = prop.childNodes[0].data
Packit Service fb6fa5
                self._convert_dialog_response(node, object_id, response)
Packit Service fb6fa5
                prop.parentNode.removeChild(prop)
Packit Service fb6fa5
            elif prop_name == "adjustment":
Packit Service fb6fa5
                self._convert_adjustment(prop)
Packit Service fb6fa5
            elif prop_name == "items" and klass in ['GtkComboBox',
Packit Service fb6fa5
                                                    'GtkComboBoxEntry']:
Packit Service fb6fa5
                self._convert_combobox_items(node, prop)
Packit Service fb6fa5
            elif prop_name == "text" and klass == 'GtkTextView':
Packit Service fb6fa5
                self._convert_textview_text(prop)
Packit Service fb6fa5
Packit Service fb6fa5
    def _remove_window(self, node):
Packit Service fb6fa5
        object_node = get_object_node(get_child_nodes(node)[0])
Packit Service fb6fa5
        parent = node.parentNode
Packit Service fb6fa5
        parent.removeChild(node)
Packit Service fb6fa5
        parent.appendChild(object_node)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_menu(self, node, popup=False):
Packit Service fb6fa5
        if node.hasAttribute('constructor'):
Packit Service fb6fa5
            return
Packit Service fb6fa5
Packit Service fb6fa5
        uimgr = self._create_root_object('GtkUIManager',
Packit Service fb6fa5
                                         template='uimanager')
Packit Service fb6fa5
Packit Service fb6fa5
        if popup:
Packit Service fb6fa5
            name = 'popup'
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            name = 'menubar'
Packit Service fb6fa5
Packit Service fb6fa5
        menu = self._dom.createElement(name)
Packit Service fb6fa5
        menu.setAttribute('name', node.getAttribute('id'))
Packit Service fb6fa5
        node.setAttribute('constructor', uimgr.getAttribute('id'))
Packit Service fb6fa5
Packit Service fb6fa5
        for child in get_child_nodes(node):
Packit Service fb6fa5
            obj_node = get_object_node(child)
Packit Service fb6fa5
            item = self._convert_menuitem(uimgr, obj_node)
Packit Service fb6fa5
            menu.appendChild(item)
Packit Service fb6fa5
            child.removeChild(obj_node)
Packit Service fb6fa5
            child.parentNode.removeChild(child)
Packit Service fb6fa5
Packit Service fb6fa5
        ui = self._dom.createElement('ui')
Packit Service fb6fa5
        uimgr.appendChild(ui)
Packit Service fb6fa5
Packit Service fb6fa5
        ui.appendChild(menu)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_menuitem(self, uimgr, obj_node):
Packit Service fb6fa5
        children = get_child_nodes(obj_node)
Packit Service fb6fa5
        name = 'menuitem'
Packit Service fb6fa5
        if children:
Packit Service fb6fa5
            child_node = children[0]
Packit Service fb6fa5
            menu_node = get_object_node(child_node)
Packit Service fb6fa5
            # Can be GtkImage, which will take care of later.
Packit Service fb6fa5
            if menu_node.getAttribute('class') == 'GtkMenu':
Packit Service fb6fa5
                name = 'menu'
Packit Service fb6fa5
Packit Service fb6fa5
        object_class = obj_node.getAttribute('class')
Packit Service fb6fa5
        if object_class in ['GtkMenuItem',
Packit Service fb6fa5
                            'GtkImageMenuItem',
Packit Service fb6fa5
                            'GtkCheckMenuItem',
Packit Service fb6fa5
                            'GtkRadioMenuItem']:
Packit Service fb6fa5
            menu = self._dom.createElement(name)
Packit Service fb6fa5
        elif object_class == 'GtkSeparatorMenuItem':
Packit Service fb6fa5
            return self._dom.createElement('separator')
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            raise NotImplementedError(object_class)
Packit Service fb6fa5
Packit Service fb6fa5
        menu.setAttribute('action', obj_node.getAttribute('id'))
Packit Service fb6fa5
        self._add_action_from_menuitem(uimgr, obj_node)
Packit Service fb6fa5
        if children:
Packit Service fb6fa5
            for child in get_child_nodes(menu_node):
Packit Service fb6fa5
                obj_node = get_object_node(child)
Packit Service fb6fa5
                item = self._convert_menuitem(uimgr, obj_node)
Packit Service fb6fa5
                menu.appendChild(item)
Packit Service fb6fa5
                child.removeChild(obj_node)
Packit Service fb6fa5
                child.parentNode.removeChild(child)
Packit Service fb6fa5
        return menu
Packit Service fb6fa5
Packit Service fb6fa5
    def _menuitem_to_action(self, node, properties):
Packit Service fb6fa5
        copy_properties(node, ['label', 'tooltip'], properties)
Packit Service fb6fa5
Packit Service fb6fa5
    def _togglemenuitem_to_action(self, node, properties):
Packit Service fb6fa5
        self._menuitem_to_action(node, properties)
Packit Service fb6fa5
        copy_properties(node, ['active'], properties)
Packit Service fb6fa5
Packit Service fb6fa5
    def _radiomenuitem_to_action(self, node, properties):
Packit Service fb6fa5
        self._togglemenuitem_to_action(node, properties)
Packit Service fb6fa5
        copy_properties(node, ['group'], properties)
Packit Service fb6fa5
Packit Service fb6fa5
    def _add_action_from_menuitem(self, uimgr, node):
Packit Service fb6fa5
        properties = {}
Packit Service fb6fa5
        object_class = node.getAttribute('class')
Packit Service fb6fa5
        object_id = node.getAttribute('id')
Packit Service fb6fa5
        if object_class == 'GtkMenuItem':
Packit Service fb6fa5
            name = 'GtkAction'
Packit Service fb6fa5
            self._menuitem_to_action(node, properties)
Packit Service fb6fa5
        elif object_class == 'GtkCheckMenuItem':
Packit Service fb6fa5
            name = 'GtkToggleAction'
Packit Service fb6fa5
            self._togglemenuitem_to_action(node, properties)
Packit Service fb6fa5
        elif object_class == 'GtkRadioMenuItem':
Packit Service fb6fa5
            name = 'GtkRadioAction'
Packit Service fb6fa5
            self._radiomenuitem_to_action(node, properties)
Packit Service fb6fa5
        elif object_class == 'GtkImageMenuItem':
Packit Service fb6fa5
            name = 'GtkAction'
Packit Service fb6fa5
            children = get_child_nodes(node)
Packit Service fb6fa5
            if (children and
Packit Service fb6fa5
                children[0].getAttribute('internal-child') == 'image'):
Packit Service fb6fa5
                image = get_object_node(children[0])
Packit Service fb6fa5
                child = get_property_node(image, 'stock')
Packit Service fb6fa5
                if child is not None:
Packit Service fb6fa5
                    properties['stock_id'] = child
Packit Service fb6fa5
            self._menuitem_to_action(node, properties)
Packit Service fb6fa5
        elif object_class == 'GtkSeparatorMenuItem':
Packit Service fb6fa5
            return
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            raise NotImplementedError(object_class)
Packit Service fb6fa5
Packit Service fb6fa5
        if get_property(node, 'use_stock') == 'True':
Packit Service fb6fa5
            if 'label' in properties:
Packit Service fb6fa5
                properties['stock_id'] = properties['label']
Packit Service fb6fa5
                del properties['label']
Packit Service fb6fa5
Packit Service fb6fa5
        properties['name'] = object_id
Packit Service fb6fa5
        action = self._create_object(name,
Packit Service fb6fa5
                                     object_id,
Packit Service fb6fa5
                                     properties=properties)
Packit Service fb6fa5
        for signal in get_signal_nodes(node):
Packit Service fb6fa5
            signal_name = signal.getAttribute('name')
Packit Service fb6fa5
            if signal_name in ['activate', 'toggled']:
Packit Service fb6fa5
                action.appendChild(signal)
Packit Service fb6fa5
            else:
Packit Service 51d9ba
                print('Unhandled signal %s::%s' % (node.getAttribute('class'),
Packit Service 51d9ba
                                                   signal_name))
Packit Service fb6fa5
Packit Service fb6fa5
        if not uimgr.childNodes:
Packit Service fb6fa5
            child = self._dom.createElement('child')
Packit Service fb6fa5
            uimgr.appendChild(child)
Packit Service fb6fa5
Packit Service fb6fa5
            group = self._create_object('GtkActionGroup', None,
Packit Service fb6fa5
                                        template='actiongroup')
Packit Service fb6fa5
            child.appendChild(group)
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            group = uimgr.childNodes[0].childNodes[0]
Packit Service fb6fa5
Packit Service fb6fa5
        child = self._dom.createElement('child')
Packit Service fb6fa5
        group.appendChild(child)
Packit Service fb6fa5
        child.appendChild(action)
Packit Service fb6fa5
Packit Service fb6fa5
        for accelerator in get_accelerator_nodes(node):
Packit Service fb6fa5
            signal_name = accelerator.getAttribute('signal')
Packit Service fb6fa5
            if signal_name != 'activate':
Packit Service 51d9ba
                print('Unhandled accelerator signal for %s::%s' % (
Packit Service 51d9ba
                    node.getAttribute('class'), signal_name))
Packit Service fb6fa5
                continue
Packit Service fb6fa5
            accelerator.removeAttribute('signal')
Packit Service fb6fa5
            child.appendChild(accelerator)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_sizegroup(self, node, prop):
Packit Service fb6fa5
        # This is Gazpacho only
Packit Service fb6fa5
        node.removeChild(prop)
Packit Service fb6fa5
        obj = self._get_object(prop.childNodes[0].data)
Packit Service fb6fa5
        if obj is None:
Packit Service fb6fa5
            widgets = self._get_objects_by_attr("class", "GtkSizeGroup")
Packit Service fb6fa5
            if widgets:
Packit Service fb6fa5
                obj = widgets[-1]
Packit Service fb6fa5
            else:
Packit Service fb6fa5
                obj = self._create_root_object('GtkSizeGroup',
Packit Service fb6fa5
                                               template='sizegroup')
Packit Service fb6fa5
Packit Service fb6fa5
        widgets = obj.getElementsByTagName("widgets")
Packit Service fb6fa5
        if widgets:
Packit Service fb6fa5
            assert len(widgets) == 1
Packit Service fb6fa5
            widgets = widgets[0]
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            widgets = self._dom.createElement("widgets")
Packit Service fb6fa5
            obj.appendChild(widgets)
Packit Service fb6fa5
Packit Service fb6fa5
        member = self._dom.createElement("widget")
Packit Service fb6fa5
        member.setAttribute("name", node.getAttribute("id"))
Packit Service fb6fa5
        widgets.appendChild(member)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_dialog_response(self, node, object_name, response):
Packit Service fb6fa5
        # 1) Get parent dialog node
Packit Service fb6fa5
        while True:
Packit Service fb6fa5
            # If we can't find the parent dialog, give up
Packit Service fb6fa5
            if node == self._dom:
Packit Service fb6fa5
                return
Packit Service fb6fa5
Packit Service fb6fa5
            if (node.tagName == 'object' and
Packit Service fb6fa5
                node.getAttribute('class') in DIALOGS):
Packit Service fb6fa5
                dialog = node
Packit Service fb6fa5
                break
Packit Service fb6fa5
            node = node.parentNode
Packit Service fb6fa5
            assert node
Packit Service fb6fa5
Packit Service fb6fa5
        # 2) Get dialogs action-widgets tag, create if not found
Packit Service fb6fa5
        for child in dialog.childNodes:
Packit Service fb6fa5
            if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
                continue
Packit Service fb6fa5
            if child.tagName == 'action-widgets':
Packit Service fb6fa5
                actions = child
Packit Service fb6fa5
                break
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            actions = self._dom.createElement("action-widgets")
Packit Service fb6fa5
            dialog.appendChild(actions)
Packit Service fb6fa5
Packit Service fb6fa5
        # 3) Add action-widget tag for the response
Packit Service fb6fa5
        action = self._dom.createElement("action-widget")
Packit Service fb6fa5
        action.setAttribute("response", response)
Packit Service fb6fa5
        action.appendChild(self._dom.createTextNode(object_name))
Packit Service fb6fa5
        actions.appendChild(action)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_adjustment(self, prop):
Packit Service fb6fa5
        properties = {}
Packit Service fb6fa5
        if prop.childNodes:
Packit Service fb6fa5
            data = prop.childNodes[0].data
Packit Service fb6fa5
            value, lower, upper, step, page, page_size = data.split(' ')
Packit Service fb6fa5
            properties.update(value=value,
Packit Service fb6fa5
                              lower=lower,
Packit Service fb6fa5
                              upper=upper,
Packit Service fb6fa5
                              step_increment=step,
Packit Service fb6fa5
                              page_increment=page,
Packit Service fb6fa5
                              page_size=page_size)
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            prop.appendChild(self._dom.createTextNode(""))
Packit Service fb6fa5
Packit Service fb6fa5
        adj = self._create_root_object("GtkAdjustment",
Packit Service fb6fa5
                                       template='adjustment',
Packit Service fb6fa5
                                       properties=properties)
Packit Service fb6fa5
        prop.childNodes[0].data = adj.getAttribute('id')
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_combobox_items(self, node, prop):
Packit Service fb6fa5
        parent = prop.parentNode
Packit Service fb6fa5
        if not prop.childNodes:
Packit Service fb6fa5
            parent.removeChild(prop)
Packit Service fb6fa5
            return
Packit Service fb6fa5
Packit Service fb6fa5
        translatable_attr = prop.attributes.get('translatable')
Packit Service fb6fa5
        translatable = translatable_attr is not None and translatable_attr.value == 'yes'
Packit Service fb6fa5
        has_context_attr = prop.attributes.get('context')
Packit Service fb6fa5
        has_context = has_context_attr is not None and has_context_attr.value == 'yes'
Packit Service fb6fa5
        comments_attr = prop.attributes.get('comments')
Packit Service fb6fa5
        comments = comments_attr is not None and comments_attr.value or None
Packit Service fb6fa5
Packit Service fb6fa5
        value = prop.childNodes[0].data
Packit Service fb6fa5
        model = self._create_root_object("GtkListStore",
Packit Service fb6fa5
                                         template="model")
Packit Service fb6fa5
Packit Service fb6fa5
        columns = self._dom.createElement('columns')
Packit Service fb6fa5
        model.appendChild(columns)
Packit Service fb6fa5
Packit Service fb6fa5
        column = self._dom.createElement('column')
Packit Service fb6fa5
        column.setAttribute('type', 'gchararray')
Packit Service fb6fa5
        columns.appendChild(column)
Packit Service fb6fa5
Packit Service fb6fa5
        data = self._dom.createElement('data')
Packit Service fb6fa5
        model.appendChild(data)
Packit Service fb6fa5
Packit Service fb6fa5
        if value.endswith('\n'):
Packit Service fb6fa5
            value = value[:-1]
Packit Service fb6fa5
        for item in value.split('\n'):
Packit Service fb6fa5
            row = self._dom.createElement('row')
Packit Service fb6fa5
            data.appendChild(row)
Packit Service fb6fa5
Packit Service fb6fa5
            col = self._dom.createElement('col')
Packit Service fb6fa5
            col.setAttribute('id', '0')
Packit Service fb6fa5
            if translatable:
Packit Service fb6fa5
                col.setAttribute('translatable', 'yes')
Packit Service fb6fa5
            if has_context:
Packit Service fb6fa5
                splitting = item.split('|', 1)
Packit Service fb6fa5
                if len(splitting) == 2:
Packit Service fb6fa5
                    context, item = splitting
Packit Service fb6fa5
                    col.setAttribute('context', context)
Packit Service fb6fa5
            if comments is not None:
Packit Service fb6fa5
                col.setAttribute('comments', comments)
Packit Service fb6fa5
            col.appendChild(self._dom.createTextNode(item))
Packit Service fb6fa5
            row.appendChild(col)
Packit Service fb6fa5
Packit Service fb6fa5
        model_prop = self._dom.createElement('property')
Packit Service fb6fa5
        model_prop.setAttribute('name', 'model')
Packit Service fb6fa5
        model_prop.appendChild(
Packit Service fb6fa5
            self._dom.createTextNode(model.getAttribute('id')))
Packit Service fb6fa5
        parent.appendChild(model_prop)
Packit Service fb6fa5
Packit Service fb6fa5
        parent.removeChild(prop)
Packit Service fb6fa5
Packit Service fb6fa5
        child = self._dom.createElement('child')
Packit Service fb6fa5
        node.appendChild(child)
Packit Service fb6fa5
        cell_renderer = self._create_object('GtkCellRendererText', None,
Packit Service fb6fa5
                                            template='renderer')
Packit Service fb6fa5
        child.appendChild(cell_renderer)
Packit Service fb6fa5
Packit Service fb6fa5
        attributes = self._dom.createElement('attributes')
Packit Service fb6fa5
        child.appendChild(attributes)
Packit Service fb6fa5
Packit Service fb6fa5
        attribute = self._dom.createElement('attribute')
Packit Service fb6fa5
        attributes.appendChild(attribute)
Packit Service fb6fa5
        attribute.setAttribute('name', 'text')
Packit Service fb6fa5
        attribute.appendChild(self._dom.createTextNode('0'))
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_textview_text(self, prop):
Packit Service fb6fa5
        if not prop.childNodes:
Packit Service fb6fa5
            prop.parentNode.removeChild(prop)
Packit Service fb6fa5
            return
Packit Service fb6fa5
Packit Service fb6fa5
        data = prop.childNodes[0].data
Packit Service fb6fa5
        if prop.hasAttribute('translatable'):
Packit Service fb6fa5
            prop.removeAttribute('translatable')
Packit Service fb6fa5
        tbuffer = self._create_root_object("GtkTextBuffer",
Packit Service fb6fa5
                                           template='textbuffer',
Packit Service fb6fa5
                                           properties=dict(text=data))
Packit Service fb6fa5
        prop.childNodes[0].data = tbuffer.getAttribute('id')
Packit Service fb6fa5
        prop.setAttribute('name', 'buffer')
Packit Service fb6fa5
Packit Service fb6fa5
    def _packing_prop_to_child_attr(self, node, prop_name, prop_val,
Packit Service fb6fa5
                                   attr_val=None):
Packit Service fb6fa5
        for child in get_child_nodes(node):
Packit Service fb6fa5
            packing_props = [p for p in child.childNodes if p.nodeName == "packing"]
Packit Service fb6fa5
            if not packing_props:
Packit Service fb6fa5
                continue
Packit Service fb6fa5
            assert len(packing_props) == 1
Packit Service fb6fa5
            packing_prop = packing_props[0]
Packit Service fb6fa5
            properties = packing_prop.getElementsByTagName("property")
Packit Service fb6fa5
            for prop in properties:
Packit Service fb6fa5
                if (prop.getAttribute("name") != prop_name or
Packit Service fb6fa5
                    prop.childNodes[0].data != prop_val):
Packit Service fb6fa5
                    continue
Packit Service fb6fa5
                packing_prop.removeChild(prop)
Packit Service fb6fa5
                child.setAttribute(prop_name, attr_val or prop_val)
Packit Service fb6fa5
            if len(properties) == 1:
Packit Service fb6fa5
                child.removeChild(packing_prop)
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_ui(self, node):
Packit Service fb6fa5
        cdata = node.childNodes[0]
Packit Service fb6fa5
        data = cdata.toxml().strip()
Packit Service fb6fa5
        if not data.startswith(""):
Packit Service fb6fa5
            return
Packit Service fb6fa5
        data = data[9:-3]
Packit Service fb6fa5
        child = minidom.parseString(data).childNodes[0]
Packit Service fb6fa5
        nodes = child.childNodes[:]
Packit Service fb6fa5
        for child_node in nodes:
Packit Service fb6fa5
            node.appendChild(child_node)
Packit Service fb6fa5
        node.removeChild(cdata)
Packit Service fb6fa5
        if not node.hasAttribute("id"):
Packit Service fb6fa5
            return
Packit Service fb6fa5
Packit Service fb6fa5
        # Updating references made by widgets
Packit Service fb6fa5
        parent_id = node.parentNode.getAttribute("id")
Packit Service fb6fa5
        for widget in self._get_objects_by_attr("constructor",
Packit Service fb6fa5
                                                node.getAttribute("id")):
Packit Service fb6fa5
            widget.getAttributeNode("constructor").value = parent_id
Packit Service fb6fa5
        node.removeAttribute("id")
Packit Service fb6fa5
Packit Service fb6fa5
    def _convert_accessibility(self, node):
Packit Service fb6fa5
        objectNode = node.parentNode
Packit Service fb6fa5
        parent_id = objectNode.getAttribute("id")
Packit Service fb6fa5
Packit Service fb6fa5
        properties = {}
Packit Service fb6fa5
        for node in node.childNodes:
Packit Service fb6fa5
            if node.nodeName == 'atkproperty':
Packit Service fb6fa5
                node.tagName = 'property'
Packit Service fb6fa5
                properties[node.getAttribute('name')] = node
Packit Service fb6fa5
                node.parentNode.removeChild(node)
Packit Service fb6fa5
            elif node.nodeName == 'atkrelation':
Packit Service fb6fa5
                node.tagName = 'relation'
Packit Service fb6fa5
                relation_type = node.getAttribute('type')
Packit Service fb6fa5
                relation_type = relation_type.replace('_', '-')
Packit Service fb6fa5
                node.setAttribute('type', relation_type)
Packit Service fb6fa5
            elif node.nodeName == 'atkaction':
Packit Service fb6fa5
                node.tagName = 'action'
Packit Service fb6fa5
Packit Service fb6fa5
        if properties:
Packit Service fb6fa5
            child = self._dom.createElement('child')
Packit Service fb6fa5
            child.setAttribute("internal-child", "accessible")
Packit Service fb6fa5
Packit Service fb6fa5
            atkobject = self._create_object(
Packit Service fb6fa5
                "AtkObject", None,
Packit Service fb6fa5
                template='a11y-%s' % (parent_id,),
Packit Service fb6fa5
                properties=properties)
Packit Service fb6fa5
            child.appendChild(atkobject)
Packit Service fb6fa5
            objectNode.appendChild(child)
Packit Service fb6fa5
Packit Service fb6fa5
    def _strip_root(self, root_name):
Packit Service fb6fa5
        for widget in self._dom.getElementsByTagName("widget"):
Packit Service fb6fa5
            if widget.getAttribute('id') == root_name:
Packit Service fb6fa5
                break
Packit Service fb6fa5
        else:
Packit Service fb6fa5
            raise SystemExit("Could not find an object called `%s'" % (
Packit Service fb6fa5
                root_name))
Packit Service fb6fa5
Packit Service fb6fa5
        for child in self._interface.childNodes[:]:
Packit Service fb6fa5
            if child.nodeType != Node.ELEMENT_NODE:
Packit Service fb6fa5
                continue
Packit Service fb6fa5
            child.parentNode.removeChild(child)
Packit Service fb6fa5
Packit Service fb6fa5
        self._interface.appendChild(widget)
Packit Service fb6fa5
Packit Service fb6fa5
Packit Service fb6fa5
def _indent(output):
Packit Service fb6fa5
    if not subprocess:
Packit Service fb6fa5
        return output
Packit Service fb6fa5
Packit Service fb6fa5
    for directory in os.environ['PATH'].split(os.pathsep):
Packit Service fb6fa5
        filename = os.path.join(directory, 'xmllint')
Packit Service fb6fa5
        if os.path.exists(filename):
Packit Service fb6fa5
            break
Packit Service fb6fa5
    else:
Packit Service fb6fa5
        return output
Packit Service fb6fa5
Packit Service fb6fa5
    s = subprocess.Popen([filename, '--format', '-'],
Packit Service fb6fa5
                         stdin=subprocess.PIPE,
Packit Service 51d9ba
                         stdout=subprocess.PIPE,
Packit Service 51d9ba
                         universal_newlines=True)
Packit Service fb6fa5
    s.stdin.write(output)
Packit Service fb6fa5
    s.stdin.close()
Packit Service fb6fa5
    return s.stdout.read()
Packit Service fb6fa5
Packit Service fb6fa5
def usage():
Packit Service 51d9ba
    print(__doc__)
Packit Service fb6fa5
Packit Service fb6fa5
def main(args):
Packit Service fb6fa5
    try:
Packit Service fb6fa5
        opts, args = getopt.getopt(args[1:], "hwr:",
Packit Service fb6fa5
                                   ["help",
Packit Service fb6fa5
                                    "skip-windows",
Packit Service fb6fa5
                                    "target-version=",
Packit Service fb6fa5
                                    "root="])
Packit Service fb6fa5
    except getopt.GetoptError:
Packit Service fb6fa5
        usage()
Packit Service fb6fa5
        return 2
Packit Service fb6fa5
Packit Service fb6fa5
    if len(args) != 2:
Packit Service fb6fa5
        usage()
Packit Service fb6fa5
        return 2
Packit Service fb6fa5
Packit Service fb6fa5
    input_filename, output_filename = args
Packit Service fb6fa5
Packit Service fb6fa5
    skip_windows = False
Packit Service fb6fa5
    split = False
Packit Service fb6fa5
    root = None
Packit Service fb6fa5
    target_version = "2.0"
Packit Service fb6fa5
    for o, a in opts:
Packit Service fb6fa5
        if o in ("-h", "--help"):
Packit Service fb6fa5
            usage()
Packit Service fb6fa5
            sys.exit()
Packit Service fb6fa5
        elif o in ("-r", "--root"):
Packit Service fb6fa5
            root = a
Packit Service fb6fa5
        elif o in ("-w", "--skip-windows"):
Packit Service fb6fa5
            skip_windows = True
Packit Service fb6fa5
        elif o in ("-t", "--target-version"):
Packit Service fb6fa5
            target_version = a
Packit Service fb6fa5
Packit Service fb6fa5
    conv = GtkBuilderConverter(skip_windows=skip_windows,
Packit Service fb6fa5
                               target_version=target_version,
Packit Service fb6fa5
                               root=root)
Packit Service fb6fa5
    conv.parse_file(input_filename)
Packit Service fb6fa5
Packit Service fb6fa5
    xml = _indent(conv.to_xml())
Packit Service fb6fa5
    if output_filename == "-":
Packit Service 51d9ba
        print(xml)
Packit Service fb6fa5
    else:
Packit Service fb6fa5
        open(output_filename, 'w').write(xml)
Packit Service 51d9ba
        print("Wrote", output_filename)
Packit Service fb6fa5
Packit Service fb6fa5
    return 0
Packit Service fb6fa5
Packit Service fb6fa5
if __name__ == "__main__":
Packit Service fb6fa5
    sys.exit(main(sys.argv))