#!/usr/bin/env python # -*- mode: python -*- # yes, this requires python 2.x and an XML parser module (eg. PyExpat) import re import sys import string import getopt import xml.dom.minidom translatable_properties = [ 'label', 'title', 'text', 'format', 'copyright', 'comments', 'preview_text', 'tooltip' ] # --- Code to represent a widget in memory, and dump it to stdout --- upgrade = 1 verbose = 0 class WidgetDef: def __init__(self, parent=None): self.wclass = None self.name = None self.property_names = [ ] self.properties = { } self.signals = [] self.accels = [] self.children = [] self.parent = parent def __getitem__(self, name): if name == 'name': return self.name if name == 'class': return self.wclass if name == 'parent': return self.parent return self.properties[name] def __setitem__(self, name, value): if name == 'name': self.name = value return if name == 'class': self.wclass = value return if self.properties.has_key(name): self.property_names.remove(name) del self.properties[name] if value == 'True': value = 'yes' if value == 'False': value = 'no' self.property_names.append(name) self.properties[name] = value def __delitem__(self, name): if self.properties.has_key(name): self.property_names.remove(name) del self.properties[name] else: raise KeyError, "unknown property `%s'" % name def has_prop(self, name): return self.properties.has_key(name) def rename_prop(self, old_name, new_name): if self.has_prop(old_name): self[new_name] = self[old_name] del self[old_name] def remove_prop(self, name): if self.properties.has_key(name): self.property_names.remove(name) del self.properties[name] def mark_obsolete (self): self.properties ['obsolete'] = 'yes' def add_signal(self, name, handler, object=None, after=0): self.signals.append((name, handler, object, after)) def add_accel(self, key, modifiers, signal): self.accels.append((key, modifiers, signal)) class ChildDef: def __init__(self, widget, internal_child=None): self.internal_child = internal_child self.property_names = [] self.properties = {} self.widget = widget def __getitem__(self, name): return self.properties[name] def __setitem__(self, name, value): if self.properties.has_key(name): self.property_names.remove(name) del self.properties[name] if value == 'True': value = 'yes' if value == 'False': value = 'no' self.property_names.append(name) self.properties[name] = value def __delitem__(self, name): if self.properties.has_key(name): self.property_names.remove(name) del self.properties[name] else: raise KeyError, "unknown property `%s'" % name def has_prop(self, name): return self.properties.has_key(name) def rename_prop(self, old_name, new_name): if self.has_prop(old_name): self[new_name] = self[old_name] del self[old_name] def remove_prop(self, name): if self.properties.has_key(name): self.property_names.remove(name) del self.properties[name] def dump(self, indent): if self.widget.has_prop('obsolete'): return if self.internal_child: print '%s' % \ (indent, self.internal_child) else: print '%s' % indent if self.widget.wclass == 'Placeholder': print '%s ' % indent else: self.widget.dump(indent + ' ') if self.properties: print '%s ' % indent for name in self.property_names: attrs = '' if name in translatable_properties: attrs += ' translatable="yes"' if name[:3] == 'cxx': attrs += ' agent="glademm"' print '%s %s' % \ (indent, name, attrs, self.properties[name].encode('utf-8')) print '%s ' % indent print '%s' % indent def add_child(self, widget, internal_child=None): child = self.ChildDef(widget, internal_child) self.children.append(child) return child def dump(self, indent): print '%s' %(indent, self.wclass, self.name) want_newline = 0 for name in self.property_names: attrs = '' translatable = name in translatable_properties if name == 'label' and \ self.has_prop('use_stock') and self['use_stock'] == 'yes': translatable = 0 if translatable: attrs += ' translatable="yes"' if name[:3] == 'cxx': attrs += ' agent="glademm"' print '%s %s' % \ (indent, name, attrs, self.properties[name].encode('utf-8')) want_newline = 1 if want_newline and (self.signals or self.accels or self.children): print want_newline = 0 for name, handler, object, after in self.signals: print '%s ' want_newline = 1 if want_newline and (self.accels or self.children): print want_newline = 0 for key, modifiers, signal in self.accels: print '%s ' % \ (indent, key, modifiers, signal) want_newline = 1 if want_newline and self.children: print want_newline = 0 for child in self.children: if want_newline: print child.dump(indent + ' ') want_newline = 1 print '%s' % indent # --- Code to parse the glade1 XML files into WidgetDef instances --- def totext(nodelist): return string.join(map(lambda node: node.toxml(), nodelist), '') def handle_signal(widget, signalnode): name = None handler = None object = None after = 0 for node in signalnode.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.nodeName == 'name': name = totext(node.childNodes) elif node.nodeName == 'handler': handler = totext(node.childNodes) elif node.nodeName == 'object': object = totext(node.childNodes) elif node.nodeName == 'after': after = (totext(node.childNodes) == 'True') widget.add_signal(name, handler, object, after) def handle_accel(widget, accelnode): key = None modifiers = None signal = None for node in accelnode.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.nodeName == 'key': key = totext(node.childNodes) if key[:4] == 'GDK_': key = key[4:] elif node.nodeName == 'modifiers': modifiers = totext(node.childNodes) elif node.nodeName == 'signal': signal = totext(node.childNodes) widget.add_accel(key, modifiers, signal) def get_child_props(childdef, widgetnode): for node in widgetnode.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.nodeName == 'child': child = node break else: return [] for node in child.childNodes: if node.nodeType != node.ELEMENT_NODE: continue childdef[node.nodeName] = totext(node.childNodes) def handle_widget(widgetnode, parent=None): widget = WidgetDef(parent) properties = [] signals = [] accels = [] children = [] for node in widgetnode.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.nodeName == 'widget': child_widget = handle_widget(node, widget) childdef = widget.add_child(child_widget) get_child_props(childdef, node) elif node.nodeName in ('signal', 'Signal'): handle_signal(widget, node) elif node.nodeName in ('accelerator', 'Accelerator'): handle_accel(widget, node) elif node.nodeName == 'child': pass # handled by the parent widget else: widget[node.nodeName] = totext(node.childNodes) return widget # --- Code to do widget type specific cleanups --- name_counter = 0 def make_name(): global name_counter name_counter = name_counter + 1 return 'convertwidget' + str(name_counter) # properties to change on all widgets global_obsolete_props = [ 'child_min_width', 'child_min_height', 'child_ipad_x', 'child_ipad_y' ] global_renamed_props = [ ('width', 'width-request'), ('height', 'height-request'), ] # properties to change on specific widgets obsolete_props = { 'GtkWindow': [ 'auto_shrink' ], 'GnomePropertyBox': [ 'auto_shrink' ], 'GtkMenuItem': [ 'right_justify' ], 'GtkGammaCurve': [ 'curve_type', 'min_x', 'max_x', 'min_y', 'max_y' ], 'GtkHPaned': [ 'handle_size', 'gutter_size' ], 'GtkVPaned': [ 'handle_size', 'gutter_size' ], 'GtkHScale': [ 'policy' ], 'GtkVScale': [ 'policy' ], 'GtkHScrollbar': [ 'policy' ], 'GtkVScrollbar': [ 'policy' ], 'GtkHRuler': [ 'metric' ], 'GtkVRuler': [ 'metric' ], 'GnomeFileEntry' : [ 'max_saved' ], 'GnomeEntry' : [ 'max_saved' ], 'GtkMenuBar' : [ 'shadow_type' ], 'GtkToolbar' : [ 'space_size', 'space_style', 'relief', 'tooltips' ], 'GtkImage' : [ 'image_width', 'image_height', 'image_visual', 'image_type'], 'GtkColorSelection' : [ 'policy' ], 'GtkColorSelectionDialog' : [ 'policy' ], 'GnomeIconEntry': [ 'max_saved' ], } renamed_props = { 'GtkWindow': [ ('position', 'window-position') ], 'GtkEntry': [ ('text_max_length', 'max-length'), ('text_visible', 'visibility') ], 'GtkFrame': [ ('shadow_type', 'shadow') ], 'GtkHandleBox': [ ('shadow_type', 'shadow') ], 'GtkNotebook': [ ('popup_enable', 'enable-popup') ], 'GtkRange': [ ('policy', 'update-policy') ], 'GtkTable': [ ('rows', 'n-rows'), ('columns', 'n-columns') ], 'GtkSpinButton' : [ ('snap', 'snap_to_ticks') ], 'GtkCombo' : [ ('use_arrows', 'enable_arrow_keys'), ('use_arrows_always', 'enable_arrows_always'), ('ok_if_empty', 'allow_empty') ], 'GnomeFileEntry' : [ ('directory', 'directory_entry'), ('title', 'browse_dialog_title'), ], 'GnomeIconEntry' : [ ('title', 'browse_dialog_title') ], 'GnomePixmapEntry' : [ ('title', 'browse_dialog_title') ], 'GtkLabel' : [ ('default_focus_target', 'mnemonic_widget'), ('focus_target', 'mnemonic_widget')], 'GtkCList' : [ ('columns', 'n_columns') ], 'GtkCTree' : [ ('columns', 'n_columns') ], 'GtkToolbar': [ ('type', 'toolbar-style') ], 'GtkOptionMenu' : [ ('initial_choice', 'history') ], 'GtkLayout' : [ ('area_width', 'width'), ('area_height', 'height') ], 'GtkFileSelection' : [ ('show_file_op_buttons', 'show-fileops') ], 'GnomeDruidPageStandard' : [ ('title_color', 'title_foreground'), ('background_color', 'background'), ('logo_background_color', 'logo_background'), ('logo_image', 'logo'), ], 'GnomeFontPicker': [ ('use_font_size', 'label-font-size'), ('use_font', 'use-font-in-label'), ], } # child properties to change on specific widgets global_renamed_child_props = [ ('pack', 'pack_type'), ('child_ipad_x', 'child_internal_pad_x'), ('child_ipad_y', 'child_internal_pad_y') ] obsolete_child_props = { } renamed_child_props = { 'GtkTable' : [ ('xpad', 'x_padding'), ('ypad', 'y_padding') ], } def collect_adjustment(widgetdef, prop_prefix, new_name): value, lower, upper, step, page, page_size = (0, 0, 100, 1, 10, 10) adj_set = 0 if widgetdef.has_prop(prop_prefix + 'value'): value = widgetdef[prop_prefix + 'value'] del widgetdef[prop_prefix + 'value'] adj_set = 1 if widgetdef.has_prop(prop_prefix + 'lower'): lower = widgetdef[prop_prefix + 'lower'] del widgetdef[prop_prefix + 'lower'] adj_set = 1 if widgetdef.has_prop(prop_prefix + 'upper'): upper = widgetdef[prop_prefix + 'upper'] del widgetdef[prop_prefix + 'upper'] adj_set = 1 if widgetdef.has_prop(prop_prefix + 'step'): step = widgetdef[prop_prefix + 'step'] del widgetdef[prop_prefix + 'step'] adj_set = 1 if widgetdef.has_prop(prop_prefix + 'page'): page = widgetdef[prop_prefix + 'page'] del widgetdef[prop_prefix + 'page'] adj_set = 1 if widgetdef.has_prop(prop_prefix + 'page_size'): page_size = widgetdef[prop_prefix + 'page_size'] del widgetdef[prop_prefix + 'page_size'] adj_set = 1 if adj_set: widgetdef[new_name] = '%s %s %s %s %s %s' % (value, lower, upper, step, page, page_size) parent_table = { 'GtkContainer' : 'GtkWidget', 'GtkBin' : 'GtkContainer', 'GtkDialog' : 'GtkWindow', 'GnomePropertyBox' : 'GnomeDialog', 'GnomeAbout' : 'GtkDialog', 'GnomeApp' : 'GtkWindow', 'GnomeScores' : 'GnomeDialog', 'GnomeDialog' : 'GtkWindow', 'GnomeMessageBox' : 'GnomeDialog', 'GnomeDruid' : 'GtkContainer', 'GnomeEntry' : 'GtkCombo', 'GtkCheckMenuItem' : 'GtkMenuItem', 'GtkRadioMenuItem' : 'GtkMenuItem', 'GtkImageMenuItem' : 'GtkMenuItem', 'GtkFileSelection' : 'GtkDialog', 'GtkFontSelectionDialog' : 'GtkDialog', 'GnomeColorPicker' : 'GtkButton', 'GtkToggleButton' : 'GtkButton', 'GtkCheckButton' : 'GtkToggleButton', 'GtkRadioButton' : 'GtkToggleButton', 'GtkColorSelectionDialog': 'GtkDialog', 'GtkFontSelectionDialog': 'GtkDialog', } global_group_map = { } def find_parent(type): if parent_table.has_key(type): return parent_table[type] return '' # fix up attribute naming, and possibly adding missing children. def fixup_widget(widget): type = widget['class'] while (type and not fixup_as_type (widget, type)): type = find_parent (type) for childdef in widget.children: fixup_widget(childdef.widget) def new_label(class_type, text, accel_object): label = WidgetDef() label['class'] = class_type label['name'] = make_name() label['label'] = text; if '_' in text: label['use-underline'] = 'yes' if not class_type == 'GtkMenuItem': label['xalign'] = '0.0' if class_type == 'GtkAccelLabel': label['accel-widget'] = accel_object label['use-underline'] = 'yes' return label stock_pixmaps = { 'REVERT': 'gtk-revert-to-saved', 'SCORES': 'gnome-stock-scores', 'SEARCH': 'gtk-find', 'SEARCHRPL': 'gtk-find-and-replace', 'BACK': 'gtk-go-back', 'FORWARD': 'gtk-go-forward', 'FIRST': 'gtk-goto-first', 'LAST': 'gtk-goto-last', 'TIMER': 'gnome-stock-timer', 'TIMER_STOP': 'gnome-stock-timer-stop', 'MAIL': 'gnome-stock-mail', 'MAIL_RCV': 'gnome-stock-mail-rcv', 'MAIL_SND': 'gnome-stock-mail-send', 'MAIL_RPL': 'gnome-stock-mail-rply', 'MAIL_FWD': 'gnome-stock-mail-fwd', 'MAIL_NEW': 'gnome-stock-mail-new', 'TRASH': 'gnome-stock-trash', 'TRASH_FULL': 'gnome-stock-trash-full', 'SPELLCHECK': 'gtk-spell-check', 'MIC': 'gnome-stock-mic', 'LINE_IN': 'gnome-stock-line-in', 'VOLUME': 'gnome-stock-volume', 'MIDI': 'gnome-stock-midi', 'BOOK_RED': 'gnome-stock-book-red', 'BOOK_GREEN': 'gnome-stock-book-green', 'BOOK_BLUE': 'gnome-stock-book-blue', 'BOOK_YELLOW': 'gnome-stock-book-yellow', 'BOOK_OPEN': 'gnome-stock-book-open', 'ABOUT': 'gnome-stock-about', 'MULTIPLE': 'gnome-stock-multiple-file', 'NOT': 'gnome-stock-not', 'UP': 'gtk-go-up', 'DOWN': 'gtk-go-down', 'TOP': 'gtk-goto-top', 'BOTTOM': 'gtk-goto-bottom', 'ATTACH': 'gnome-stock-attach', 'FONT': 'gtk-select-font', 'EXEC': 'gtk-execute', 'ALIGN_LEFT': 'gtk-justify-left', 'ALIGN_RIGHT': 'gtk-justify-right', 'ALIGN_CENTER': 'gtk-justify-center', 'ALIGN_JUSTIFY': 'gtk-justify-fill', 'TEXT_BOLD': 'gtk-bold', 'TEXT_ITALIC': 'gtk-italic', 'TEXT_UNDERLINE': 'gtk-underline', 'TEXT_STRIKEOUT': 'gtk-strikethrough', 'TEXT_INDENT': 'gnome-stock-text-indent', 'TEXT_UNINDENT': 'gnome-stock-text-unindent', 'EXIT': 'gtk-quit', 'COLORSELECTOR': 'gtk-select-color', 'TABLE_BORDERS': 'gnome-stock-table-borders', 'TABLE_FILL': 'gnome-stock-table-fill', 'TEXT_BULLETED_LIST': 'gnome-stock-text-bulleted-list', 'TEXT_NUMBERED_LIST': 'gnome-stock-text-numbered-list', 'NEXT': 'gtk-go-forward', 'PREV': 'gtk-go-back' } def stock_icon_translate(old_name): if re.match ('GNOME_STOCK_MENU_.*', old_name): name = re.sub('GNOME_STOCK_MENU_', '', old_name, 1) try: return stock_pixmaps[name] except KeyError: name = re.sub('_', '-', name) return 'gtk-' + name.lower () else: return old_name def stock_button_translate(old_name): if re.match ('GNOME_STOCK_BUTTON_.*', old_name): name = re.sub('GNOME_STOCK_BUTTON_', '', old_name) try: return stock_pixmaps[name] except KeyError: name = re.sub('_', '-', name) return 'gtk-' + name.lower () else: return old_name def stock_pixmap_translate(old_name): if re.match ('GNOME_STOCK_PIXMAP_.*', old_name): name = re.sub('GNOME_STOCK_PIXMAP_', '', old_name) try: return stock_pixmaps[name] except KeyError: name = re.sub('_', '-', name) return 'gtk-' + name.lower () stock_menu_items = { 'GNOMEUIINFO_MENU_NEW_ITEM': (1, 'gtk-new'), 'GNOMEUIINFO_MENU_NEW_SUBTREE': (1, 'gtk-new'), 'GNOMEUIINFO_MENU_OPEN_ITEM': (1, 'gtk-open'), 'GNOMEUIINFO_MENU_SAVE_ITEM': (1, 'gtk-save'), 'GNOMEUIINFO_MENU_SAVE_AS_ITEM': (1, 'gtk-save-as'), 'GNOMEUIINFO_MENU_REVERT_ITEM': (1, 'gtk-revert-to-saved'), 'GNOMEUIINFO_MENU_PRINT_ITEM': (1, 'gtk-print'), 'GNOMEUIINFO_MENU_PRINT_SETUP_ITEM': (0, 'Print S_etup...'), 'GNOMEUIINFO_MENU_CLOSE_ITEM': (1, 'gtk-close'), 'GNOMEUIINFO_MENU_EXIT_ITEM': (1, 'gtk-quit'), 'GNOMEUIINFO_MENU_CUT_ITEM': (1, 'gtk-cut'), 'GNOMEUIINFO_MENU_COPY_ITEM': (1, 'gtk-copy'), 'GNOMEUIINFO_MENU_PASTE_ITEM': (1, 'gtk-paste'), 'GNOMEUIINFO_MENU_SELECT_ALL_ITEM': (0, '_Select All'), 'GNOMEUIINFO_MENU_CLEAR_ITEM': (1, 'gtk-clear'), 'GNOMEUIINFO_MENU_UNDO_ITEM': (1, 'gtk-undo'), 'GNOMEUIINFO_MENU_REDO_ITEM': (1, 'gtk-redo'), 'GNOMEUIINFO_MENU_FIND_ITEM': (1, 'gtk-find'), 'GNOMEUIINFO_MENU_FIND_AGAIN_ITEM': (0, 'Find _Again'), 'GNOMEUIINFO_MENU_REPLACE_ITEM': (1, 'gtk-find-and-replace'), 'GNOMEUIINFO_MENU_PROPERTIES_ITEM': (1, 'gtk-properties'), 'GNOMEUIINFO_MENU_PREFERENCES_ITEM': (1, 'gtk-preferences'), 'GNOMEUIINFO_MENU_NEW_WINDOW_ITEM': (0, 'Create New _Window'), 'GNOMEUIINFO_MENU_CLOSE_WINDOW_ITEM': (0, '_Close This Window'), 'GNOMEUIINFO_MENU_ABOUT_ITEM': (1, 'gnome-stock-about'), 'GNOMEUIINFO_MENU_NEW_GAME_ITEM': (0, '_New game'), 'GNOMEUIINFO_MENU_PAUSE_GAME_ITEM': (0, '_Pause game'), 'GNOMEUIINFO_MENU_RESTART_GAME_ITEM': (0, '_Restart game'), 'GNOMEUIINFO_MENU_UNDO_MOVE_ITEM': (0, '_Undo move'), 'GNOMEUIINFO_MENU_REDO_MOVE_ITEM': (0, '_Redo move'), 'GNOMEUIINFO_MENU_HINT_ITEM': (0, '_Hint'), 'GNOMEUIINFO_MENU_SCORES_ITEM': (0, '_Scores...'), 'GNOMEUIINFO_MENU_END_GAME_ITEM': (0, '_End game'), 'GNOMEUIINFO_MENU_FILE_TREE': (0, '_File'), 'GNOMEUIINFO_MENU_EDIT_TREE': (0, '_Edit'), 'GNOMEUIINFO_MENU_VIEW_TREE': (0, '_View'), 'GNOMEUIINFO_MENU_SETTINGS_TREE': (0, '_Settings'), 'GNOMEUIINFO_MENU_FILES_TREE': (0, 'Fi_les'), 'GNOMEUIINFO_MENU_WINDOWS_TREE': (0, '_Windows'), 'GNOMEUIINFO_MENU_HELP_TREE': (0, '_Help'), 'GNOMEUIINFO_MENU_GAME_TREE': (0, '_Game'), } def stock_menu_translate(old_name): if stock_menu_items.has_key(old_name): return stock_menu_items[old_name] else: return (0, old_name) def translate_color (color): c = string.split (color, ',') return '#%.2x%.2x%.2x' % (int (c[0]), int (c[1]), int (c[2])) def fixup_as_type(widget, type): if verbose: print >> sys.stderr, 'Fixing', widget['name'], 'up as', type # table based property removals/renames for name in global_obsolete_props: widget.remove_prop(name) for old, new in global_renamed_props: widget.rename_prop(old, new) if obsolete_props.has_key(type): for name in obsolete_props[type]: widget.remove_prop(name) if renamed_props.has_key(type): for old, new in renamed_props[type]: widget.rename_prop(old, new) for old, new in global_renamed_child_props: for childdef in widget.children: childdef.rename_prop(old, new) if obsolete_child_props.has_key(type): for name in obsolete_child_props[type]: for childdef in widget.children: childdef.remove_prop(name) if renamed_child_props.has_key(type): for old, new in renamed_child_props[type]: for childdef in widget.children: childdef.rename_prop(old, new) # add the visible property if missing: if not widget.has_prop('visible'): widget['visible'] = 'yes' # fix up child packing properties for tables if type == 'GtkTable': for childdef in widget.children: options = [] if childdef.has_prop('xexpand'): if childdef['xexpand'] == 'yes': options.append('expand') del childdef['xexpand'] if childdef.has_prop('xshrink'): if childdef['xshrink'] == 'yes': options.append('shrink') del childdef['xshrink'] if childdef.has_prop('xfill'): if childdef['xfill'] == 'yes': options.append('fill') del childdef['xfill'] if options: childdef['x_options'] = string.join(options,'|') else: # Gtk+ has some wierd defaults here clobber them childdef['x_options'] = '' options = [] if childdef.has_prop('yexpand'): if childdef['yexpand'] == 'yes': options.append('expand') del childdef['yexpand'] if childdef.has_prop('yshrink'): if childdef['yshrink'] == 'yes': options.append('shrink') del childdef['yshrink'] if childdef.has_prop('yfill'): if childdef['yfill'] == 'yes': options.append('fill') del childdef['yfill'] if options: childdef['y_options'] = string.join(options,'|') else: # Gtk+ has some wierd defaults here clobber them childdef['y_options'] = '' # fixup GtkFixed child packing options if type == 'GtkFixed': for childdef in widget.children: if childdef.widget.has_prop ('x'): childdef['x'] = childdef.widget['x'] del childdef.widget['x'] if childdef.widget.has_prop ('y'): childdef['y'] = childdef.widget['y'] del childdef.widget['y'] # fixup GtkNotebook child tab widgets. if type == 'GtkNotebook': for childdef in widget.children: if childdef.widget.has_prop ('child_name'): if childdef.widget['child_name'] == 'Notebook:tab': del childdef.widget['child_name'] childdef['type'] = 'tab' else: print >> sys.stderr , 'Unknown child_name', \ childdef.widget['child_name'] if type == 'GtkFileSelection': for childdef in widget.children: if childdef.widget.has_prop ('child_name'): if re.match ('FileSel:.*', childdef.widget['child_name']): name = re.sub ('FileSel:', '', childdef.widget['child_name']) del childdef.widget['child_name'] childdef.internal_child = name if type == 'GtkColorSelectionDialog': for childdef in widget.children: if childdef.widget.has_prop ('child_name'): if re.match ('ColorSel:.*', childdef.widget['child_name']): name = re.sub ('ColorSel:', '', childdef.widget['child_name']) del childdef.widget['child_name'] childdef.internal_child = name if type == 'GtkFontSelectionDialog': for childdef in widget.children: if childdef.widget.has_prop ('child_name'): if re.match ('FontSel:.*', childdef.widget['child_name']): name = re.sub ('FontSel:', '', childdef.widget['child_name']) del childdef.widget['child_name'] childdef.internal_child = name # fix up adjustment properties if type in ('GtkHScale', 'GtkHScrollbar', 'GtkVScale', 'GtkVScrollbar', 'GtkSpinButton'): collect_adjustment(widget, 'h', 'adjustment') # compat collect_adjustment(widget, 'v', 'adjustment') # compat collect_adjustment(widget, '', 'adjustment') if type in ('GtkViewport', 'GtkLayout', 'GtkScrolledWindow'): collect_adjustment(widget, 'h', 'hadjustment') collect_adjustment(widget, 'v', 'vadjustment') if widget.has_prop('width'): width = widget['width'] del widget['width'] widget['width'] = width if widget.has_prop('height'): height = widget['height'] del widget['height'] widget['height'] = height if type in ('GtkProgressBar', ): collect_adjustment(widget, '', 'adjustment') # add label children to menu items. if type == 'GtkMenuItem': if widget.has_prop('stock_item'): use_stock, stock = stock_menu_translate(widget['stock_item']) widget['label'] = stock widget['use_stock'] = use_stock and 'yes' or 'no' widget['use_underline'] = 'yes' del widget['stock_item'] if type == 'GtkImageMenuItem': if widget.has_prop('stock_icon'): icon = WidgetDef() icon['class'] = 'GtkImage' icon['name'] = make_name () icon['stock'] = stock_icon_translate (widget['stock_icon']) widget.add_child (icon, 'image') del widget['stock_icon'] if type == 'GtkButton': if widget.has_prop('stock_button'): widget['label'] = stock_button_translate (widget['stock_button']) widget['use_stock'] = 'yes' widget['use_underline'] = 'yes' del widget['stock_button'] # GnomeDialog sucks, and this is tricky to get right so just # ignore the pixmap for now if widget.has_prop('stock_pixmap'): del widget['stock_pixmap'] if type == 'GtkDialog': if widget.children: childdef = widget.children[0] if childdef.widget.has_prop ('child_name'): childdef.internal_child = 'vbox' del childdef.widget['child_name'] try: childdef = filter(lambda x: x.widget.has_prop('child_name'), childdef.widget.children)[0] except IndexError: return 0 childdef.widget['class'] = 'GtkHButtonBox' childdef.internal_child = 'action_area' del childdef.widget['child_name'] if type == 'GnomeDialog': if widget.children: childdef = widget.children[0] if childdef.widget.has_prop ('child_name'): childdef.internal_child = 'vbox' del childdef.widget['child_name'] try: childdef = filter(lambda x: x.widget.has_prop('child_name'), childdef.widget.children)[0] except IndexError: return 0 childdef.widget['class'] = 'GtkHButtonBox' childdef.internal_child = 'action_area' del childdef.widget['child_name'] if type == 'GtkOptionMenu': menu = WidgetDef() menu['class'] = 'GtkMenu' menu['name'] = make_name () widget.add_child (menu, 'menu') if widget.has_prop('items'): # FIXME: this needs continuing, we need a GtkMenu # item, and a hacked up special case to do the # set_menu on the optionmenu with it, then we need # to pack these ( working ) MenuItems into it if not widget['items'] == '': items = widget['items'].split ('\n') for item in items: if not item == '': menu.add_child ( \ new_label ('GtkMenuItem', \ item, widget['name'])) del widget['items'] if type == 'GtkScrolledWindow': if widget.has_prop ('hupdate_policy'): scroll = WidgetDef () scroll['class'] = 'GtkHScrollbar' scroll['name'] = make_name () scroll['update_policy'] = widget['hupdate_policy'] widget.add_child(scroll, 'hscrollbar') del widget['hupdate_policy'] if widget.has_prop ('vupdate_policy'): scroll = WidgetDef () scroll['class'] = 'GtkVScrollbar' scroll['name'] = make_name () scroll['update_policy'] = widget['vupdate_policy'] widget.add_child(scroll, 'vscrollbar') del widget['vupdate_policy'] if type == 'GtkCombo': childdef = widget.children[0] childdef.internal_child = 'entry' del childdef.widget['child_name'] if widget.has_prop('items'): items = widget['items'].split('\n') del widget['items'] list = WidgetDef() list['class'] = 'GtkList' list['name'] = make_name() widget.add_child(list, 'list') for item in items: listitem = WidgetDef() listitem['class'] = 'GtkListItem' listitem['name'] = make_name() list.add_child(listitem) listitem.add_child (new_label ('GtkLabel', item, '')) if type in ('GtkCList', 'GtkCTree'): for childdef in widget.children: del childdef.widget['child_name'] if type in ('GtkLabel', 'GtkButton', 'GtkMenuItem'): if widget.has_prop('label'): if re.match('.*_.*', widget['label']): widget['use_underline'] = 'yes' if type == 'GnomeFileEntry': childdef = widget.children[0] childdef.internal_child = 'entry' del childdef.widget['child_name'] if type == 'GnomePropertyBox': childdef = widget.children[0] childdef.internal_child = 'notebook' del childdef.widget['child_name'] fixup_as_type (widget, 'GtkWindow') return 1 # Fixup radio groups, the 'group' property has to # have the glade id of the root group widget. if type == 'GtkRadioButton' or type == 'GtkRadioMenuItem': if widget.has_prop ('group'): if global_group_map.has_key (widget['group']): widget['group'] = global_group_map[widget['group']] else: global_group_map[widget['group']] = widget['name'] del widget['group'] if type == 'GtkToolbar': for childdef in widget.children: if childdef.widget.has_prop('child_name'): if childdef.widget['child_name'] == 'Toolbar:button': if childdef.widget['class'] == 'GtkButton': childdef.widget['class'] = 'button' elif childdef.widget['class'] == 'GtkToggleButton': childdef.widget['class'] = 'toggle' elif childdef.widget['class'] == 'GtkRadioButton': childdef.widget['class'] = 'radio' if childdef.widget.has_prop('group'): if global_group_map.has_key (childdef.widget['group']): childdef.widget['group'] = global_group_map[childdef.widget['group']] else: global_group_map[childdef.widget['group']] = childdef.widget['name'] del childdef.widget['group'] del childdef.widget['child_name'] if childdef.widget.has_prop('stock_pixmap'): name = stock_pixmap_translate (childdef.widget['stock_pixmap']) childdef.widget['stock_pixmap'] = name if type == 'GtkCalendar': options = [] if widget.has_prop('show_heading'): if widget['show_heading'] == 'yes': options.append('GTK_CALENDAR_SHOW_HEADING') del widget['show_heading'] if widget.has_prop('show_day_names'): if widget['show_day_names'] == 'yes': options.append('GTK_CALENDAR_SHOW_DAY_NAMES') del widget['show_day_names'] if widget.has_prop('no_month_change'): if widget['no_month_change'] == 'yes': options.append('GTK_CALENDAR_NO_MONTH_CHANGE') del widget['no_month_change'] if widget.has_prop('show_week_numbers'): if widget['show_week_numbers'] == 'yes': options.append('GTK_CALENDAR_SHOW_WEEK_NUMBERS') del widget['show_week_numbers'] if widget.has_prop('week_start_monday'): if widget['week_start_monday'] == 'yes': options.append('GTK_CALENDAR_WEEK_START_MONDAY') del widget['week_start_monday'] if options: widget['display_options'] = string.join(options, '|') else: widget['display_options'] = '' if type == 'GnomeApp': for childdef in widget.children: if childdef.widget.has_prop('child_name'): if childdef.widget['child_name'] == 'GnomeApp:dock': del childdef.widget['child_name'] childdef.internal_child = 'dock' elif childdef.widget['child_name'] == 'GnomeApp:appbar': del childdef.widget['child_name'] childdef.internal_child = 'appbar' if type == 'BonoboDock': for childdef in widget.children: if childdef.widget.has_prop('child_name'): if childdef.widget['child_name'] == 'GnomeDock:contents': del childdef.widget['child_name'] if childdef.widget['class'] == 'BonoboDockItem': behavior = [] if childdef.widget.has_prop('placement'): name = childdef.widget['placement'] if re.match ('GNOME_.*', name): name = re.sub('GNOME_', 'BONOBO_', name, 1) childdef['placement'] = name del childdef.widget['placement'] if childdef.widget.has_prop('band'): childdef['band'] = childdef.widget['band'] del childdef.widget['band'] if childdef.widget.has_prop ('position'): childdef['position'] = childdef.widget['position'] del childdef.widget['position'] if childdef.widget.has_prop ('offset'): childdef['offset'] = childdef.widget['offset'] del childdef.widget['offset'] if childdef.widget.has_prop ('locked'): if childdef.widget['locked'] == 'yes': behavior.append ('BONOBO_DOCK_ITEM_BEH_LOCKED') del childdef.widget['locked'] if childdef.widget.has_prop ('exclusive'): if childdef.widget['exclusive'] == 'yes': behavior.append ('BONOBO_DOCK_ITEM_BEH_EXCLUSIVE') del childdef.widget['exclusive'] if childdef.widget.has_prop ('never_floating'): if childdef.widget['never_floating'] == 'yes': behavior.append ('BONOBO_DOCK_ITEM_BEH_NEVER_FLOATING') del childdef.widget['never_floating'] if childdef.widget.has_prop ('never_vertical'): if childdef.widget['never_vertical'] == 'yes': behavior.append ('BONOBO_DOCK_ITEM_BEH_NEVER_VERTICAL') del childdef.widget['never_vertical'] if childdef.widget.has_prop ('never_horizontal'): if childdef.widget['never_horizontal'] == 'yes': behavior.append ('BONOBO_DOCK_ITEM_BEH_NEVER_HORIZONTAL') del childdef.widget['never_horizontal'] if behavior: childdef['behavior'] = string.join(behavior, '|') else: childdef['behavior'] = 'BONOBO_DOCK_ITEM_BEH_NORMAL' if type == 'GnomeDateEdit': flags = [] if widget.has_prop('show_time'): if widget['show_time'] == 'yes': flags.append ('GNOME_DATE_EDIT_SHOW_TIME') del widget['show_time'] if widget.has_prop('use_24_format'): if widget['use_24_format'] == 'yes': flags.append ('GNOME_DATE_EDIT_24_HR') del widget['use_24_format'] if widget.has_prop('week_start_monday'): if widget['week_start_monday'] == 'yes': flags.append ('GNOME_DATE_EDIT_WEEK_STARTS_ON_MONDAY') del widget['week_start_monday'] if flags: widget['dateedit_flags'] = string.join(flags, '|') else: widget['dateedit_flags'] = '0' if type == 'GnomeMessageBox': try: name = widget['message_box_type'] except KeyError: name = 'GNOME_MESSAGE_BOX_GENERIC' name = re.sub ('GNOME_MESSAGE_BOX_', '', name) widget['message_box_type'] = name.lower () if type == 'GnomeDruidPageEdge': for color in ( 'title_color', 'text_color', 'background_color', 'logo_background_color', 'textbox_color' ): if widget.has_prop (color): widget[color] = translate_color (widget[color]) if type == 'GnomeDruidPageStandard': for color in ( 'title_foreground', 'background', 'logo_background' ): if widget.has_prop (color): widget[color] = translate_color (widget[color]) if widget.children: if widget.children[0].widget.has_prop ('child_name'): widget.children[0].internal_child = 'vbox' del widget.children[0].widget['child_name'] return 0 # upgrade widgets to their gtk/gnome 2.0 equivalents def upgrade_widget(widget): do_children = 1 # some widgets are totally removed, so upgrade anyway if widget['class'] == 'GnomeDockItem': widget['class'] = 'BonoboDockItem' elif widget['class'] == 'GnomeDock': widget['class'] = 'BonoboDock' elif widget['class'] == 'GnomeAnimator': widget['class'] = 'GtkImage' if widget.has_prop ('loop_type'): del widget['loop_type'] if widget.has_prop ('playback_direction'): del widget['playback_direction'] if widget.has_prop ('playback_speed'): del widget['playback_speed'] elif widget['class'] == 'GnomeDruidPageStart': widget['class'] = 'GnomeDruidPageEdge' widget['position'] = 'GNOME_EDGE_START' elif widget['class'] == 'GnomeDruidPageFinish': widget['class'] = 'GnomeDruidPageEdge' widget['position'] = 'GNOME_EDGE_FINISH' elif widget['class'] == 'GtkPixmapMenuItem': widget['class'] = 'GtkImageMenuItem' if not upgrade: if do_children: for childdef in widget.children: upgrade_widget(childdef.widget) return # use GtkImage for image display now. if widget['class'] == 'GtkPixmap': widget['class'] = 'GtkImage' widget.rename_prop('filename', 'pixbuf') widget.remove_prop('build_insensitive') elif widget['class'] == 'GnomeFontSelector': widget['class'] = 'GtkFontSelectionDialog' elif widget['class'] == 'GnomePixmap': widget['class'] = 'GtkImage' widget.rename_prop('filename', 'pixbuf') elif widget['class'] == 'GtkText': widget['class'] = 'GtkTextView' widget['wrap_mode'] = 'GTK_WRAP_WORD' parent = widget['parent'] if parent['class'] == 'GtkScrolledWindow': parent['shadow_type'] = 'GTK_SHADOW_IN' elif widget['class'] in ('GtkCList', 'GtkCTree', 'GtkList', 'GtkTree'): widget['class'] = 'GtkTreeView' parent = widget['parent'] if parent['class'] == 'GtkScrolledWindow': parent['shadow_type'] = widget['shadow_type'] widget.remove_prop('shadow_type') widget.rename_prop('show_titles', 'headers-visible') widget.remove_prop('columns') widget.remove_prop('column_widths') widget.remove_prop('selection_mode') widget.remove_prop('view_mode') widget.remove_prop('view_line') elif widget['class'] == 'GnomeDialog': widget['class'] = 'GtkDialog' if widget.has_prop ('auto_close'): del widget['auto_close'] if widget.has_prop ('hide_on_close'): del widget['hide_on_close'] if do_children: for childdef in widget.children: upgrade_widget(childdef.widget) # warn about removed widgets, and build a list of libraries used bad_widgets = { 'GtkText': 'broken', 'GtkList': 'broken', 'GtkTree': 'broken', 'GtkTreeItem': 'broken', 'GtkCList': 'deprecated', 'GtkCTree': 'deprecated', 'GtkPixmap': 'deprecated', 'GnomePixmap': 'deprecated', # 'GnomeFontPicker': 'removed', 'GtkPixmapMenuItem': 'removed', 'GtkPacker': 'removed', 'GnomeDialog': 'deprecated', 'GnomeNumberEntry': 'removed', 'GtkDial': 'removed', 'GtkClock': 'removed', 'GnomeCalculator': 'removed', 'GnomeLess': 'removed', 'GnomeSpell': 'removed', } def check_widget(widget, requirelist=[]): try: error = bad_widgets[widget['class']] print >> sys.stderr , 'widget %s of class %s is %s.' % \ (widget['name'], widget['class'], error) if error == 'removed': widget.mark_obsolete () except KeyError: pass if widget['class'] == 'GnomeCanvas': if 'canvas' not in requirelist: requirelist.append('canvas') elif widget['class'][:5] == 'Gnome' and 'gnome' not in requirelist: requirelist.append('gnome') elif widget['class'][:6] == 'Bonobo' and 'bonobo' not in requirelist: requirelist.append('bonobo') for childdef in widget.children: check_widget(childdef.widget, requirelist) # --- parse the file for widget definitions, fixup problems and dump. def handle_file(filename): document = xml.dom.minidom.parse(filename) widgets = [] for node in document.documentElement.childNodes: if node.nodeType == node.ELEMENT_NODE and \ node.nodeName == 'widget': widgets.append(handle_widget(node)) requireslist = [] for widgetdef in widgets: upgrade_widget(widgetdef) fixup_widget(widgetdef) check_widget(widgetdef, requireslist) print ' ' print '' print print '' for requirement in requireslist: print ' ' % requirement if requireslist: print indent = ' ' for widgetdef in widgets: widgetdef.dump(indent) print '' document.unlink() # only needed for python interpreters without cyclic gc usage = 'usage: libglade-convert [--no-upgrade] [--verbose] oldfile.glade' def main(): global upgrade, verbose opts, args = getopt.getopt(sys.argv[1:], '', ['no-upgrade', 'verbose', 'help']) for opt, arg in opts: if opt == '--no-upgrade': upgrade = 0 elif opt == '--verbose': verbose = 1 elif opt == '--help': print usage sys.exit(0) if len(args) != 1: print >> sys.stderr, usage sys.exit(1) handle_file(args[0]) if __name__ == '__main__': main()