home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 March / PCWELT_3_2006.ISO / base / 04_xap_libs.mo / usr / bin / libglade-convert < prev    next >
Encoding:
Text File  |  2005-03-26  |  45.5 KB  |  1,213 lines

  1. #!/usr/bin/python
  2. # -*- mode: python -*-
  3.  
  4. # yes, this requires python 2.x and an XML parser module (eg. PyExpat)
  5.  
  6. import re
  7. import sys
  8. import string
  9. import getopt
  10. import xml.dom.minidom
  11.  
  12. translatable_properties = [
  13.     'label', 'title', 'text', 'format', 'copyright', 'comments',
  14.     'preview_text', 'tooltip'
  15. ]
  16.  
  17. # --- Code to represent a widget in memory, and dump it to stdout ---
  18.  
  19. upgrade = 1
  20. verbose = 0
  21.  
  22. class WidgetDef:
  23.     def __init__(self, parent=None):
  24.         self.wclass = None
  25.         self.name = None
  26.         self.property_names = [ ]
  27.         self.properties = { }
  28.         self.signals = []
  29.         self.accels = []
  30.         self.children = []
  31.         self.parent = parent
  32.  
  33.     def __getitem__(self, name):
  34.         if name == 'name':
  35.             return self.name
  36.         if name == 'class':
  37.             return self.wclass
  38.         if name == 'parent':
  39.             return self.parent
  40.         return self.properties[name]
  41.     def __setitem__(self, name, value):
  42.         if name == 'name':
  43.             self.name = value
  44.             return
  45.         if name == 'class':
  46.             self.wclass = value
  47.             return
  48.         if self.properties.has_key(name):
  49.             self.property_names.remove(name)
  50.             del self.properties[name]
  51.         if value == 'True': value = 'yes'
  52.         if value == 'False': value = 'no'
  53.         self.property_names.append(name)
  54.         self.properties[name] = value
  55.     def __delitem__(self, name):
  56.         if self.properties.has_key(name):
  57.             self.property_names.remove(name)
  58.             del self.properties[name]
  59.         else:
  60.             raise KeyError, "unknown property `%s'" % name
  61.     def has_prop(self, name):
  62.         return self.properties.has_key(name)
  63.     def rename_prop(self, old_name, new_name):
  64.         if self.has_prop(old_name):
  65.             self[new_name] = self[old_name]
  66.             del self[old_name]
  67.     def remove_prop(self, name):
  68.         if self.properties.has_key(name):
  69.             self.property_names.remove(name)
  70.             del self.properties[name]
  71.             
  72.     def mark_obsolete (self):
  73.         self.properties ['obsolete'] = 'yes'
  74.     def add_signal(self, name, handler, object=None, after=0):
  75.         self.signals.append((name, handler, object, after))
  76.     def add_accel(self, key, modifiers, signal):
  77.         self.accels.append((key, modifiers, signal))
  78.  
  79.     class ChildDef:
  80.         def __init__(self, widget, internal_child=None):
  81.             self.internal_child = internal_child
  82.             self.property_names = []
  83.             self.properties = {}
  84.             self.widget = widget
  85.         def __getitem__(self, name):
  86.             return self.properties[name]
  87.         def __setitem__(self, name, value):
  88.             if self.properties.has_key(name):
  89.                 self.property_names.remove(name)
  90.                 del self.properties[name]
  91.             if value == 'True': value = 'yes'
  92.             if value == 'False': value = 'no'
  93.             self.property_names.append(name)
  94.             self.properties[name] = value
  95.         def __delitem__(self, name):
  96.             if self.properties.has_key(name):
  97.                 self.property_names.remove(name)
  98.                 del self.properties[name]
  99.             else:
  100.                 raise KeyError, "unknown property `%s'" % name
  101.         def has_prop(self, name):
  102.             return self.properties.has_key(name)
  103.         def rename_prop(self, old_name, new_name):
  104.             if self.has_prop(old_name):
  105.                 self[new_name] = self[old_name]
  106.                 del self[old_name]
  107.         def remove_prop(self, name):
  108.             if self.properties.has_key(name):
  109.                 self.property_names.remove(name)
  110.                 del self.properties[name]
  111.                 
  112.         def dump(self, indent):
  113.             if self.widget.has_prop('obsolete'):
  114.                 return
  115.  
  116.             if self.internal_child:
  117.                 print '%s<child internal-child="%s">' % \
  118.                       (indent, self.internal_child)
  119.             else:
  120.                 print '%s<child>' % indent
  121.             if self.widget.wclass == 'Placeholder':
  122.                 print '%s  <placeholder />' % indent
  123.             else:
  124.                 self.widget.dump(indent + '  ')
  125.             if self.properties:
  126.                 print '%s  <packing>' % indent
  127.                 for name in self.property_names:
  128.                     attrs = ''
  129.                     if name in translatable_properties:
  130.                         attrs += ' translatable="yes"'
  131.                     if name[:3] == 'cxx':
  132.                         attrs += ' agent="glademm"'
  133.                     print '%s    <property name="%s"%s>%s</property>' % \
  134.                           (indent, name, attrs,
  135.                            self.properties[name].encode('utf-8'))
  136.                 print '%s  </packing>' % indent
  137.             print '%s</child>' % indent
  138.  
  139.     def add_child(self, widget, internal_child=None):
  140.         child = self.ChildDef(widget, internal_child)
  141.         self.children.append(child)
  142.         return child
  143.  
  144.     def dump(self, indent):        
  145.         print '%s<widget class="%s" id="%s">' %(indent, self.wclass, self.name)
  146.         want_newline = 0
  147.         for name in self.property_names:
  148.             attrs = ''
  149.             translatable = name in translatable_properties
  150.             if name == 'label' and \
  151.                self.has_prop('use_stock') and self['use_stock'] == 'yes':
  152.                 translatable = 0
  153.             if translatable:
  154.                 attrs += ' translatable="yes"'
  155.             if name[:3] == 'cxx':
  156.                 attrs += ' agent="glademm"'
  157.             print '%s  <property name="%s"%s>%s</property>' % \
  158.                   (indent, name, attrs, self.properties[name].encode('utf-8'))
  159.             want_newline = 1
  160.         if want_newline and (self.signals or self.accels or self.children):
  161.             print
  162.  
  163.         want_newline = 0
  164.         for name, handler, object, after in self.signals:
  165.             print '%s  <signal name="%s" handler="%s"' % (indent, name,
  166.                                                           handler),
  167.             if object: print 'object="%s"' % object,
  168.             if after: print 'after="yes"',
  169.             print '/>'
  170.             want_newline = 1
  171.         if want_newline and (self.accels or self.children): print
  172.  
  173.         want_newline = 0
  174.         for key, modifiers, signal in self.accels:
  175.             print '%s  <accelerator key="%s" modifiers="%s" signal="%s" />' % \
  176.                   (indent, key, modifiers, signal)
  177.             want_newline = 1
  178.         if want_newline and self.children: print
  179.  
  180.         want_newline = 0
  181.         for child in self.children:
  182.             if want_newline: print
  183.             child.dump(indent + '  ')
  184.             want_newline = 1
  185.         print '%s</widget>' % indent
  186.  
  187.  
  188. # --- Code to parse the glade1 XML files into WidgetDef instances ---
  189.  
  190. def totext(nodelist):
  191.     return string.join(map(lambda node: node.toxml(), nodelist), '')
  192.  
  193. def handle_signal(widget, signalnode):
  194.     name = None
  195.     handler = None
  196.     object = None
  197.     after = 0
  198.     for node in signalnode.childNodes:
  199.     if node.nodeType != node.ELEMENT_NODE:
  200.         continue
  201.     if node.nodeName == 'name':
  202.         name = totext(node.childNodes)
  203.     elif node.nodeName == 'handler':
  204.         handler = totext(node.childNodes)
  205.     elif node.nodeName == 'object':
  206.         object = totext(node.childNodes)
  207.     elif node.nodeName == 'after':
  208.         after = (totext(node.childNodes) == 'True')
  209.     widget.add_signal(name, handler, object, after)
  210.  
  211. def handle_accel(widget, accelnode):
  212.     key = None
  213.     modifiers = None
  214.     signal = None
  215.     for node in accelnode.childNodes:
  216.     if node.nodeType != node.ELEMENT_NODE:
  217.         continue
  218.     if node.nodeName == 'key':
  219.         key = totext(node.childNodes)
  220.         if key[:4] == 'GDK_': key = key[4:]
  221.     elif node.nodeName == 'modifiers':
  222.         modifiers = totext(node.childNodes)
  223.     elif node.nodeName == 'signal':
  224.         signal = totext(node.childNodes)
  225.     widget.add_accel(key, modifiers, signal)
  226.  
  227. def get_child_props(childdef, widgetnode):
  228.     for node in widgetnode.childNodes:
  229.     if node.nodeType != node.ELEMENT_NODE:
  230.         continue
  231.     if node.nodeName == 'child':
  232.         child = node
  233.         break
  234.     else:
  235.     return []
  236.     for node in child.childNodes:
  237.     if node.nodeType != node.ELEMENT_NODE:
  238.         continue
  239.         childdef[node.nodeName] = totext(node.childNodes)
  240.  
  241. def handle_widget(widgetnode, parent=None):
  242.     widget = WidgetDef(parent)
  243.     properties = []
  244.     signals = []
  245.     accels = []
  246.     children = []
  247.     for node in widgetnode.childNodes:
  248.     if node.nodeType != node.ELEMENT_NODE:
  249.         continue
  250.     if node.nodeName == 'widget':
  251.             child_widget = handle_widget(node, widget)
  252.             childdef = widget.add_child(child_widget)
  253.             get_child_props(childdef, node)
  254.     elif node.nodeName in ('signal', 'Signal'):
  255.         handle_signal(widget, node)
  256.     elif node.nodeName in ('accelerator', 'Accelerator'):
  257.         handle_accel(widget, node)
  258.     elif node.nodeName == 'child':
  259.         pass # handled by the parent widget
  260.     else:
  261.             widget[node.nodeName] = totext(node.childNodes)
  262.     return widget
  263.  
  264.  
  265. # --- Code to do widget type specific cleanups ---
  266.  
  267. name_counter = 0
  268. def make_name():
  269.     global name_counter
  270.     name_counter = name_counter + 1
  271.     return 'convertwidget' + str(name_counter)
  272.  
  273. # properties to change on all widgets
  274. global_obsolete_props = [
  275.     'child_min_width',
  276.     'child_min_height',
  277.     'child_ipad_x',
  278.     'child_ipad_y'
  279. ]
  280. global_renamed_props = [
  281.     ('width', 'width-request'),
  282.     ('height', 'height-request'),
  283. ]
  284.  
  285. # properties to change on specific widgets
  286. obsolete_props = {
  287.     'GtkWindow': [ 'auto_shrink' ],
  288.     'GnomePropertyBox': [ 'auto_shrink' ],
  289.     'GtkMenuItem': [ 'right_justify' ],
  290.     'GtkGammaCurve': [ 'curve_type', 'min_x', 'max_x', 'min_y', 'max_y' ],
  291.     'GtkHPaned': [ 'handle_size', 'gutter_size' ],
  292.     'GtkVPaned': [ 'handle_size', 'gutter_size' ],
  293.     'GtkHScale': [ 'policy' ],
  294.     'GtkVScale': [ 'policy' ],
  295.     'GtkHScrollbar': [ 'policy' ],
  296.     'GtkVScrollbar': [ 'policy' ],
  297.     'GtkHRuler': [ 'metric' ],
  298.     'GtkVRuler': [ 'metric' ],
  299.     'GnomeFileEntry' : [ 'max_saved' ],
  300.     'GnomeEntry' : [ 'max_saved' ],
  301.     'GtkMenuBar' : [ 'shadow_type' ],
  302.     'GtkToolbar' : [ 'space_size', 'space_style', 'relief', 'tooltips' ],
  303.     'GtkImage' : [ 'image_width', 'image_height', 'image_visual', 'image_type'],
  304.     'GtkColorSelection' : [ 'policy' ],
  305.     'GtkColorSelectionDialog' : [ 'policy' ],
  306.     'GnomeIconEntry': [ 'max_saved' ],
  307. }
  308.  
  309. renamed_props = {
  310.     'GtkWindow': [ ('position', 'window-position') ],    
  311.     'GtkEntry': [ ('text_max_length', 'max-length'),
  312.                   ('text_visible', 'visibility') ],
  313.     'GtkFrame': [ ('shadow_type', 'shadow') ],
  314.     'GtkHandleBox': [ ('shadow_type', 'shadow') ],
  315.     'GtkNotebook': [ ('popup_enable', 'enable-popup') ],
  316.     'GtkRange': [ ('policy', 'update-policy') ],
  317.     'GtkTable': [ ('rows', 'n-rows'), ('columns', 'n-columns') ],
  318.     'GtkSpinButton' : [ ('snap', 'snap_to_ticks') ],
  319.     'GtkCombo' : [ ('use_arrows', 'enable_arrow_keys'),
  320.                    ('use_arrows_always', 'enable_arrows_always'),
  321.                    ('ok_if_empty', 'allow_empty') ],
  322.     'GnomeFileEntry' : [ ('directory', 'directory_entry'),
  323.                          ('title', 'browse_dialog_title'),
  324.                          ],
  325.     'GnomeIconEntry' : [ ('title', 'browse_dialog_title') ],
  326.     'GnomePixmapEntry' : [ ('title', 'browse_dialog_title') ],
  327.     'GtkLabel' : [ ('default_focus_target', 'mnemonic_widget'), ('focus_target', 'mnemonic_widget')],
  328.     'GtkCList' : [ ('columns', 'n_columns') ],
  329.     'GtkCTree' : [ ('columns', 'n_columns') ],
  330.     'GtkToolbar': [ ('type', 'toolbar-style') ],
  331.     'GtkOptionMenu' : [ ('initial_choice', 'history') ],
  332.     'GtkLayout' : [ ('area_width', 'width'), ('area_height', 'height') ],
  333.     'GtkFileSelection' : [ ('show_file_op_buttons', 'show-fileops') ],
  334.     'GnomeDruidPageStandard' : [ ('title_color', 'title_foreground'),
  335.                                  ('background_color', 'background'),
  336.                                  ('logo_background_color', 'logo_background'),
  337.                                  ('logo_image', 'logo'),
  338.                                  ],
  339.     'GnomeFontPicker': [ ('use_font_size', 'label-font-size'),
  340.                          ('use_font', 'use-font-in-label'),
  341.                          ],
  342. }
  343.  
  344. # child properties to change on specific widgets
  345. global_renamed_child_props = [
  346.     ('pack', 'pack_type'),
  347.     ('child_ipad_x', 'child_internal_pad_x'),
  348.     ('child_ipad_y', 'child_internal_pad_y')
  349. ]
  350. obsolete_child_props = {
  351. }
  352. renamed_child_props = {
  353.     'GtkTable' : [ ('xpad', 'x_padding'), ('ypad', 'y_padding') ],
  354. }
  355.  
  356. def collect_adjustment(widgetdef, prop_prefix, new_name):
  357.     value, lower, upper, step, page, page_size = (0, 0, 100, 1, 10, 10)
  358.     adj_set = 0
  359.     if widgetdef.has_prop(prop_prefix + 'value'):
  360.         value = widgetdef[prop_prefix + 'value']
  361.         del widgetdef[prop_prefix + 'value']
  362.         adj_set = 1
  363.     if widgetdef.has_prop(prop_prefix + 'lower'):
  364.         lower = widgetdef[prop_prefix + 'lower']
  365.         del widgetdef[prop_prefix + 'lower']
  366.         adj_set = 1
  367.     if widgetdef.has_prop(prop_prefix + 'upper'):
  368.         upper = widgetdef[prop_prefix + 'upper']
  369.         del widgetdef[prop_prefix + 'upper']
  370.         adj_set = 1
  371.     if widgetdef.has_prop(prop_prefix + 'step'):
  372.         step = widgetdef[prop_prefix + 'step']
  373.         del widgetdef[prop_prefix + 'step']
  374.         adj_set = 1
  375.     if widgetdef.has_prop(prop_prefix + 'page'):
  376.         page = widgetdef[prop_prefix + 'page']
  377.         del widgetdef[prop_prefix + 'page']
  378.         adj_set = 1
  379.     if widgetdef.has_prop(prop_prefix + 'page_size'):
  380.         page_size = widgetdef[prop_prefix + 'page_size']
  381.         del widgetdef[prop_prefix + 'page_size']
  382.         adj_set = 1
  383.     if adj_set:
  384.         widgetdef[new_name] = '%s %s %s %s %s %s' % (value, lower, upper,
  385.                                                      step, page, page_size)
  386.  
  387.  
  388. parent_table = {
  389.     'GtkContainer'      : 'GtkWidget',
  390.     'GtkBin'            : 'GtkContainer',
  391.     'GtkDialog'         : 'GtkWindow',
  392.     'GnomePropertyBox'  : 'GnomeDialog',
  393.     'GnomeAbout'        : 'GtkDialog',
  394.     'GnomeApp'          : 'GtkWindow',
  395.     'GnomeScores'       : 'GnomeDialog',
  396.     'GnomeDialog'       : 'GtkWindow',
  397.     'GnomeMessageBox'   : 'GnomeDialog',
  398.     'GnomeDruid'        : 'GtkContainer',
  399.     'GnomeEntry'        : 'GtkCombo',
  400.     'GtkCheckMenuItem'  : 'GtkMenuItem',
  401.     'GtkRadioMenuItem'  : 'GtkMenuItem',
  402.     'GtkImageMenuItem'  : 'GtkMenuItem',
  403.     'GtkFileSelection'  : 'GtkDialog',
  404.     'GtkFontSelectionDialog' : 'GtkDialog',
  405.     'GnomeColorPicker'  : 'GtkButton',
  406.     'GtkToggleButton'   : 'GtkButton',
  407.     'GtkCheckButton'    : 'GtkToggleButton',
  408.     'GtkRadioButton'    : 'GtkToggleButton',
  409.     'GtkColorSelectionDialog': 'GtkDialog',
  410.     'GtkFontSelectionDialog': 'GtkDialog',
  411.  
  412. }
  413.  
  414. global_group_map = { }
  415.  
  416. def find_parent(type):
  417.     if parent_table.has_key(type):
  418.         return parent_table[type]
  419.     return ''
  420.  
  421. # fix up attribute naming, and possibly adding missing children.
  422. def fixup_widget(widget):
  423.  
  424.     type = widget['class']
  425.     while (type and not fixup_as_type (widget, type)):
  426.         type = find_parent (type)
  427.         
  428.     for childdef in widget.children:
  429.         fixup_widget(childdef.widget)
  430.  
  431. def new_label(class_type, text, accel_object):
  432.     label = WidgetDef()
  433.     label['class'] = class_type
  434.     label['name'] = make_name()
  435.     label['label'] = text;
  436.     if '_' in text:
  437.         label['use-underline'] = 'yes'
  438.  
  439.     if not class_type == 'GtkMenuItem':
  440.         label['xalign'] = '0.0'
  441.  
  442.     if class_type == 'GtkAccelLabel':
  443.         label['accel-widget'] = accel_object
  444.         label['use-underline'] = 'yes'        
  445.  
  446.     return label
  447.  
  448. stock_pixmaps = {
  449.     'REVERT':      'gtk-revert-to-saved',
  450.     'SCORES':      'gnome-stock-scores',
  451.     'SEARCH':      'gtk-find',
  452.     'SEARCHRPL':   'gtk-find-and-replace',
  453.     'BACK':        'gtk-go-back',
  454.     'FORWARD':     'gtk-go-forward',
  455.     'FIRST':       'gtk-goto-first',
  456.     'LAST':        'gtk-goto-last',
  457.     'TIMER':       'gnome-stock-timer',
  458.     'TIMER_STOP':  'gnome-stock-timer-stop',
  459.     'MAIL':        'gnome-stock-mail',
  460.     'MAIL_RCV':    'gnome-stock-mail-rcv',
  461.     'MAIL_SND':    'gnome-stock-mail-send',
  462.     'MAIL_RPL':    'gnome-stock-mail-rply',
  463.     'MAIL_FWD':    'gnome-stock-mail-fwd',
  464.     'MAIL_NEW':    'gnome-stock-mail-new',
  465.     'TRASH':       'gnome-stock-trash',
  466.     'TRASH_FULL':  'gnome-stock-trash-full',
  467.     'SPELLCHECK':  'gtk-spell-check',
  468.     'MIC':         'gnome-stock-mic',
  469.     'LINE_IN':     'gnome-stock-line-in',
  470.     'VOLUME':      'gnome-stock-volume',
  471.     'MIDI':        'gnome-stock-midi',
  472.     'BOOK_RED':    'gnome-stock-book-red',
  473.     'BOOK_GREEN':  'gnome-stock-book-green',
  474.     'BOOK_BLUE':   'gnome-stock-book-blue',
  475.     'BOOK_YELLOW': 'gnome-stock-book-yellow',
  476.     'BOOK_OPEN':   'gnome-stock-book-open',
  477.     'ABOUT':       'gnome-stock-about',
  478.     'MULTIPLE':    'gnome-stock-multiple-file',
  479.     'NOT':         'gnome-stock-not',
  480.     'UP':          'gtk-go-up',
  481.     'DOWN':        'gtk-go-down',
  482.     'TOP':         'gtk-goto-top',
  483.     'BOTTOM':      'gtk-goto-bottom',
  484.     'ATTACH':      'gnome-stock-attach',
  485.     'FONT':        'gtk-select-font',
  486.     'EXEC':        'gtk-execute',
  487.  
  488.     'ALIGN_LEFT':    'gtk-justify-left',
  489.     'ALIGN_RIGHT':   'gtk-justify-right',
  490.     'ALIGN_CENTER':  'gtk-justify-center',
  491.     'ALIGN_JUSTIFY': 'gtk-justify-fill',
  492.  
  493.     'TEXT_BOLD':      'gtk-bold',
  494.     'TEXT_ITALIC':    'gtk-italic',
  495.     'TEXT_UNDERLINE': 'gtk-underline',
  496.     'TEXT_STRIKEOUT': 'gtk-strikethrough',
  497.  
  498.     'TEXT_INDENT':    'gnome-stock-text-indent',
  499.     'TEXT_UNINDENT':  'gnome-stock-text-unindent',
  500.     'EXIT':           'gtk-quit',
  501.     'COLORSELECTOR':  'gtk-select-color',
  502.  
  503.     'TABLE_BORDERS':  'gnome-stock-table-borders',
  504.     'TABLE_FILL':     'gnome-stock-table-fill',
  505.  
  506.     'TEXT_BULLETED_LIST': 'gnome-stock-text-bulleted-list',
  507.     'TEXT_NUMBERED_LIST': 'gnome-stock-text-numbered-list',
  508.  
  509.     'NEXT': 'gtk-go-forward',
  510.     'PREV': 'gtk-go-back'
  511.     }
  512.  
  513. def stock_icon_translate(old_name):
  514.     if re.match ('GNOME_STOCK_MENU_.*', old_name):
  515.         name = re.sub('GNOME_STOCK_MENU_', '', old_name, 1)
  516.         try:
  517.             return stock_pixmaps[name]
  518.         except KeyError:
  519.             name = re.sub('_', '-', name)
  520.             return 'gtk-' + name.lower ()
  521.     else:
  522.         return old_name
  523.  
  524. def stock_button_translate(old_name):
  525.     if re.match ('GNOME_STOCK_BUTTON_.*', old_name):
  526.         name = re.sub('GNOME_STOCK_BUTTON_', '', old_name)
  527.         try:
  528.             return stock_pixmaps[name]
  529.         except KeyError:
  530.             name = re.sub('_', '-', name)
  531.             return 'gtk-' + name.lower ()
  532.     else:
  533.         return old_name
  534.  
  535. def stock_pixmap_translate(old_name):
  536.     if re.match ('GNOME_STOCK_PIXMAP_.*', old_name):
  537.         name = re.sub('GNOME_STOCK_PIXMAP_', '', old_name)
  538.         try:
  539.             return stock_pixmaps[name]
  540.         except KeyError:
  541.             name = re.sub('_', '-', name)
  542.             return 'gtk-' + name.lower ()
  543.  
  544. stock_menu_items = {
  545.     'GNOMEUIINFO_MENU_NEW_ITEM': (1, 'gtk-new'),
  546.     'GNOMEUIINFO_MENU_NEW_SUBTREE': (1, 'gtk-new'),
  547.     'GNOMEUIINFO_MENU_OPEN_ITEM': (1, 'gtk-open'),
  548.     'GNOMEUIINFO_MENU_SAVE_ITEM': (1, 'gtk-save'),
  549.     'GNOMEUIINFO_MENU_SAVE_AS_ITEM': (1, 'gtk-save-as'),
  550.     'GNOMEUIINFO_MENU_REVERT_ITEM': (1, 'gtk-revert-to-saved'),
  551.     'GNOMEUIINFO_MENU_PRINT_ITEM': (1, 'gtk-print'),
  552.     'GNOMEUIINFO_MENU_PRINT_SETUP_ITEM': (0, 'Print S_etup...'),
  553.     'GNOMEUIINFO_MENU_CLOSE_ITEM': (1, 'gtk-close'),
  554.     'GNOMEUIINFO_MENU_EXIT_ITEM': (1, 'gtk-quit'),
  555.     'GNOMEUIINFO_MENU_CUT_ITEM': (1, 'gtk-cut'),
  556.     'GNOMEUIINFO_MENU_COPY_ITEM': (1, 'gtk-copy'),
  557.     'GNOMEUIINFO_MENU_PASTE_ITEM': (1, 'gtk-paste'),
  558.     'GNOMEUIINFO_MENU_SELECT_ALL_ITEM': (0, '_Select All'),
  559.     'GNOMEUIINFO_MENU_CLEAR_ITEM': (1, 'gtk-clear'),
  560.     'GNOMEUIINFO_MENU_UNDO_ITEM': (1, 'gtk-undo'),
  561.     'GNOMEUIINFO_MENU_REDO_ITEM': (1, 'gtk-redo'),
  562.     'GNOMEUIINFO_MENU_FIND_ITEM': (1, 'gtk-find'),
  563.     'GNOMEUIINFO_MENU_FIND_AGAIN_ITEM': (0, 'Find _Again'),
  564.     'GNOMEUIINFO_MENU_REPLACE_ITEM': (1, 'gtk-find-and-replace'),
  565.     'GNOMEUIINFO_MENU_PROPERTIES_ITEM': (1, 'gtk-properties'),
  566.     'GNOMEUIINFO_MENU_PREFERENCES_ITEM': (1, 'gtk-preferences'),
  567.     'GNOMEUIINFO_MENU_NEW_WINDOW_ITEM': (0, 'Create New _Window'),
  568.     'GNOMEUIINFO_MENU_CLOSE_WINDOW_ITEM': (0, '_Close This Window'),
  569.     'GNOMEUIINFO_MENU_ABOUT_ITEM': (1, 'gnome-stock-about'),
  570.     'GNOMEUIINFO_MENU_NEW_GAME_ITEM': (0, '_New game'),
  571.     'GNOMEUIINFO_MENU_PAUSE_GAME_ITEM': (0, '_Pause game'),
  572.     'GNOMEUIINFO_MENU_RESTART_GAME_ITEM': (0, '_Restart game'),
  573.     'GNOMEUIINFO_MENU_UNDO_MOVE_ITEM': (0, '_Undo move'),
  574.     'GNOMEUIINFO_MENU_REDO_MOVE_ITEM': (0, '_Redo move'),
  575.     'GNOMEUIINFO_MENU_HINT_ITEM': (0, '_Hint'),
  576.     'GNOMEUIINFO_MENU_SCORES_ITEM': (0, '_Scores...'),
  577.     'GNOMEUIINFO_MENU_END_GAME_ITEM': (0, '_End game'),
  578.     'GNOMEUIINFO_MENU_FILE_TREE': (0, '_File'),
  579.     'GNOMEUIINFO_MENU_EDIT_TREE': (0, '_Edit'),
  580.     'GNOMEUIINFO_MENU_VIEW_TREE': (0, '_View'),
  581.     'GNOMEUIINFO_MENU_SETTINGS_TREE': (0, '_Settings'),
  582.     'GNOMEUIINFO_MENU_FILES_TREE': (0, 'Fi_les'),
  583.     'GNOMEUIINFO_MENU_WINDOWS_TREE': (0, '_Windows'),
  584.     'GNOMEUIINFO_MENU_HELP_TREE': (0, '_Help'),
  585.     'GNOMEUIINFO_MENU_GAME_TREE': (0, '_Game'),
  586. }
  587. def stock_menu_translate(old_name):
  588.     if stock_menu_items.has_key(old_name):
  589.         return stock_menu_items[old_name]
  590.     else:
  591.         return (0, old_name)
  592.  
  593. def translate_color (color):
  594.     c = string.split (color, ',')
  595.     return '#%.2x%.2x%.2x' % (int (c[0]), int (c[1]), int (c[2]))
  596.  
  597.  
  598. def fixup_as_type(widget, type):
  599.  
  600.     if verbose:
  601.         print >> sys.stderr, 'Fixing', widget['name'], 'up as', type
  602.  
  603.     # table based property removals/renames
  604.     for name in global_obsolete_props:
  605.         widget.remove_prop(name)
  606.     for old, new in global_renamed_props:
  607.         widget.rename_prop(old, new)
  608.  
  609.     if obsolete_props.has_key(type):
  610.         for name in obsolete_props[type]:
  611.             widget.remove_prop(name)
  612.  
  613.     if renamed_props.has_key(type):
  614.         for old, new in renamed_props[type]:
  615.             widget.rename_prop(old, new)
  616.  
  617.     for old, new in global_renamed_child_props:
  618.         for childdef in widget.children:
  619.             childdef.rename_prop(old, new)
  620.  
  621.     if obsolete_child_props.has_key(type):
  622.         for name in obsolete_child_props[type]:
  623.             for childdef in widget.children:
  624.                 childdef.remove_prop(name)
  625.  
  626.     if renamed_child_props.has_key(type):
  627.         for old, new in renamed_child_props[type]:
  628.             for childdef in widget.children:
  629.                 childdef.rename_prop(old, new)
  630.  
  631.     # add the visible property if missing:
  632.     if not widget.has_prop('visible'):
  633.         widget['visible'] = 'yes'
  634.  
  635.     # fix up child packing properties for tables
  636.     if type == 'GtkTable':
  637.         for childdef in widget.children:
  638.             options = []
  639.             if childdef.has_prop('xexpand'):
  640.                 if childdef['xexpand'] == 'yes':
  641.                     options.append('expand')
  642.                 del childdef['xexpand']
  643.             if childdef.has_prop('xshrink'):
  644.                 if childdef['xshrink'] == 'yes':
  645.                     options.append('shrink')
  646.                 del childdef['xshrink']
  647.             if childdef.has_prop('xfill'):
  648.                 if childdef['xfill'] == 'yes':
  649.                     options.append('fill')
  650.                 del childdef['xfill']
  651.             if options:
  652.                 childdef['x_options'] = string.join(options,'|')
  653.             else: # Gtk+ has some wierd defaults here clobber them
  654.                 childdef['x_options'] = ''
  655.             
  656.             options = []
  657.             if childdef.has_prop('yexpand'):
  658.                 if childdef['yexpand'] == 'yes':
  659.                     options.append('expand')
  660.                 del childdef['yexpand']
  661.             if childdef.has_prop('yshrink'):
  662.                 if childdef['yshrink'] == 'yes':
  663.                     options.append('shrink')
  664.                 del childdef['yshrink']
  665.             if childdef.has_prop('yfill'):
  666.                 if childdef['yfill'] == 'yes':
  667.                     options.append('fill')
  668.                 del childdef['yfill']
  669.             if options:
  670.                 childdef['y_options'] = string.join(options,'|')
  671.             else: # Gtk+ has some wierd defaults here clobber them
  672.                 childdef['y_options'] = ''
  673.  
  674.     # fixup GtkFixed child packing options
  675.     if type == 'GtkFixed':
  676.         for childdef in widget.children:
  677.             if childdef.widget.has_prop ('x'):
  678.                 childdef['x'] = childdef.widget['x']
  679.                 del childdef.widget['x']
  680.             if childdef.widget.has_prop ('y'):
  681.                 childdef['y'] = childdef.widget['y']
  682.                 del childdef.widget['y']
  683.  
  684.     # fixup GtkNotebook child tab widgets.
  685.     if type == 'GtkNotebook':
  686.         for childdef in widget.children:
  687.             if childdef.widget.has_prop ('child_name'):
  688.                 if childdef.widget['child_name'] == 'Notebook:tab':
  689.                     del childdef.widget['child_name']
  690.                     childdef['type'] = 'tab'
  691.                 else:
  692.                     print >> sys.stderr , 'Unknown child_name', \
  693.                           childdef.widget['child_name']
  694.  
  695.     if type == 'GtkFileSelection':
  696.         for childdef in widget.children:
  697.             if childdef.widget.has_prop ('child_name'):
  698.                 if re.match ('FileSel:.*', childdef.widget['child_name']):
  699.                     name = re.sub ('FileSel:', '', childdef.widget['child_name'])
  700.                     del childdef.widget['child_name']
  701.                     childdef.internal_child = name
  702.  
  703.     if type == 'GtkColorSelectionDialog':
  704.         for childdef in widget.children:
  705.             if childdef.widget.has_prop ('child_name'):
  706.                 if re.match ('ColorSel:.*', childdef.widget['child_name']):
  707.                     name = re.sub ('ColorSel:', '', childdef.widget['child_name'])
  708.                     del childdef.widget['child_name']
  709.                     childdef.internal_child = name
  710.  
  711.     if type == 'GtkFontSelectionDialog':
  712.         for childdef in widget.children:
  713.             if childdef.widget.has_prop ('child_name'):
  714.                 if re.match ('FontSel:.*', childdef.widget['child_name']):
  715.                     name = re.sub ('FontSel:', '', childdef.widget['child_name'])
  716.                     del childdef.widget['child_name']
  717.                     childdef.internal_child = name
  718.  
  719.     # fix up adjustment properties
  720.     if type in ('GtkHScale', 'GtkHScrollbar',
  721.                            'GtkVScale', 'GtkVScrollbar',
  722.                            'GtkSpinButton'):
  723.         collect_adjustment(widget, 'h', 'adjustment') # compat
  724.         collect_adjustment(widget, 'v', 'adjustment') # compat
  725.         collect_adjustment(widget, '', 'adjustment')
  726.     if type in ('GtkViewport', 'GtkLayout', 'GtkScrolledWindow'):
  727.         collect_adjustment(widget, 'h', 'hadjustment')
  728.         collect_adjustment(widget, 'v', 'vadjustment')
  729.         if widget.has_prop('width'):
  730.             width = widget['width']
  731.             del widget['width']
  732.             widget['width'] = width
  733.         if widget.has_prop('height'):
  734.             height = widget['height']
  735.             del widget['height']
  736.             widget['height'] = height
  737.     if type in ('GtkProgressBar', ):
  738.         collect_adjustment(widget, '', 'adjustment')
  739.  
  740.     # add label children to menu items.
  741.     if type == 'GtkMenuItem':
  742.         if widget.has_prop('stock_item'):
  743.             use_stock, stock = stock_menu_translate(widget['stock_item'])
  744.             widget['label'] = stock
  745.             widget['use_stock'] = use_stock and 'yes' or 'no'
  746.             widget['use_underline'] = 'yes'
  747.             del widget['stock_item']
  748.  
  749.     if type == 'GtkImageMenuItem':
  750.         if widget.has_prop('stock_icon'):
  751.             icon = WidgetDef()
  752.             icon['class'] = 'GtkImage'
  753.             icon['name'] = make_name ()
  754.             icon['stock'] = stock_icon_translate (widget['stock_icon'])
  755.             widget.add_child (icon, 'image')
  756.             del widget['stock_icon']
  757.  
  758.     if type == 'GtkButton':
  759.         if widget.has_prop('stock_button'):
  760.             widget['label'] = stock_button_translate (widget['stock_button'])
  761.             widget['use_stock'] = 'yes'
  762.             widget['use_underline'] = 'yes'
  763.             del widget['stock_button']
  764.  
  765.         # GnomeDialog sucks, and this is tricky to get right so just
  766.         # ignore the pixmap for now
  767.         if widget.has_prop('stock_pixmap'):
  768.             del widget['stock_pixmap']
  769.  
  770.     if type == 'GtkDialog':
  771.         if widget.children:
  772.             childdef = widget.children[0]
  773.             if childdef.widget.has_prop ('child_name'):
  774.                 childdef.internal_child = 'vbox'
  775.                 del childdef.widget['child_name']
  776.                 
  777.                 try:
  778.                     childdef = filter(lambda x: x.widget.has_prop('child_name'),
  779.                                       childdef.widget.children)[0]
  780.                 except IndexError:
  781.                     return 0
  782.                 childdef.widget['class'] = 'GtkHButtonBox'
  783.                 childdef.internal_child = 'action_area'
  784.                 del childdef.widget['child_name']
  785.  
  786.     if type == 'GnomeDialog':
  787.         if widget.children:
  788.             childdef = widget.children[0]
  789.             if childdef.widget.has_prop ('child_name'):
  790.                 childdef.internal_child = 'vbox'
  791.                 del childdef.widget['child_name']
  792.                 
  793.             try:
  794.                 childdef = filter(lambda x: x.widget.has_prop('child_name'),
  795.                                   childdef.widget.children)[0]
  796.             except IndexError:
  797.                 return 0
  798.             childdef.widget['class'] = 'GtkHButtonBox'
  799.             childdef.internal_child = 'action_area'
  800.             del childdef.widget['child_name']
  801.  
  802.     if type == 'GtkOptionMenu':
  803.         menu = WidgetDef()
  804.         menu['class'] = 'GtkMenu'
  805.         menu['name'] = make_name ()
  806.         widget.add_child (menu, 'menu')
  807.  
  808.         if widget.has_prop('items'):
  809.             # FIXME: this needs continuing, we need a GtkMenu
  810.             # item, and a hacked up special case to do the
  811.             # set_menu on the optionmenu with it, then we need
  812.             # to pack these ( working ) MenuItems into it
  813.             if not widget['items'] == '':
  814.                 items = widget['items'].split ('\n')
  815.                 for item in items:
  816.                     if not item == '':
  817.                         menu.add_child ( \
  818.                             new_label ('GtkMenuItem', \
  819.                                        item, widget['name']))
  820.             del widget['items']
  821.             
  822.  
  823.     if type == 'GtkScrolledWindow':
  824.         if widget.has_prop ('hupdate_policy'):
  825.             scroll = WidgetDef ()
  826.             scroll['class'] = 'GtkHScrollbar'
  827.             scroll['name'] = make_name ()
  828.             scroll['update_policy'] = widget['hupdate_policy']
  829.             widget.add_child(scroll, 'hscrollbar')
  830.             del widget['hupdate_policy']
  831.         if widget.has_prop ('vupdate_policy'):
  832.             scroll = WidgetDef ()
  833.             scroll['class'] = 'GtkVScrollbar'
  834.             scroll['name'] = make_name ()
  835.             scroll['update_policy'] = widget['vupdate_policy']
  836.             widget.add_child(scroll, 'vscrollbar')
  837.             del widget['vupdate_policy']
  838.  
  839.  
  840.     if type == 'GtkCombo':
  841.         childdef = widget.children[0]
  842.         childdef.internal_child = 'entry'
  843.         del childdef.widget['child_name']
  844.  
  845.         if widget.has_prop('items'):
  846.             items = widget['items'].split('\n')
  847.             del widget['items']
  848.             list = WidgetDef()
  849.             list['class'] = 'GtkList'
  850.             list['name'] = make_name()
  851.             widget.add_child(list, 'list')
  852.             for item in items:
  853.                 listitem = WidgetDef()
  854.                 listitem['class'] = 'GtkListItem'
  855.                 listitem['name'] = make_name()
  856.                 list.add_child(listitem)
  857.                 listitem.add_child (new_label ('GtkLabel', item, ''))
  858.  
  859.     if type in ('GtkCList', 'GtkCTree'):
  860.         for childdef in widget.children:
  861.             del childdef.widget['child_name']
  862.  
  863.     if type in ('GtkLabel', 'GtkButton', 'GtkMenuItem'):
  864.         if widget.has_prop('label'):
  865.             if re.match('.*_.*', widget['label']):
  866.                 widget['use_underline'] = 'yes'
  867.  
  868.     if type == 'GnomeFileEntry':
  869.         childdef = widget.children[0]
  870.         childdef.internal_child = 'entry'
  871.         del childdef.widget['child_name']
  872.  
  873.     if type == 'GnomePropertyBox':
  874.         childdef = widget.children[0]
  875.         childdef.internal_child = 'notebook'
  876.         del childdef.widget['child_name']
  877.         fixup_as_type (widget, 'GtkWindow')
  878.         return 1
  879.  
  880.     # Fixup radio groups, the 'group' property has to
  881.     # have the glade id of the root group widget.
  882.     if type == 'GtkRadioButton' or type == 'GtkRadioMenuItem':
  883.         if widget.has_prop ('group'):
  884.             if global_group_map.has_key (widget['group']):
  885.                 widget['group'] = global_group_map[widget['group']]
  886.             else:
  887.                 global_group_map[widget['group']] = widget['name']
  888.                 del widget['group']
  889.  
  890.     if type == 'GtkToolbar':
  891.         for childdef in widget.children:
  892.             if childdef.widget.has_prop('child_name'):
  893.                 if childdef.widget['child_name'] == 'Toolbar:button':
  894.                     if childdef.widget['class'] == 'GtkButton':
  895.                         childdef.widget['class'] = 'button'
  896.                     elif childdef.widget['class'] == 'GtkToggleButton':
  897.                         childdef.widget['class'] = 'toggle'
  898.                     elif childdef.widget['class'] == 'GtkRadioButton':
  899.                         childdef.widget['class'] = 'radio'
  900.                         if childdef.widget.has_prop('group'):
  901.                             if global_group_map.has_key (childdef.widget['group']):
  902.                                 childdef.widget['group'] = global_group_map[childdef.widget['group']]
  903.                             else:
  904.                                 global_group_map[childdef.widget['group']] = childdef.widget['name']
  905.                                 del childdef.widget['group']
  906.                     del childdef.widget['child_name']
  907.                 if childdef.widget.has_prop('stock_pixmap'):
  908.                     name = stock_pixmap_translate (childdef.widget['stock_pixmap'])
  909.                     childdef.widget['stock_pixmap'] = name
  910.  
  911.     if type == 'GtkCalendar':
  912.         options = []
  913.         if widget.has_prop('show_heading'):
  914.             if widget['show_heading'] == 'yes':
  915.                 options.append('GTK_CALENDAR_SHOW_HEADING')
  916.             del widget['show_heading']
  917.         if widget.has_prop('show_day_names'):
  918.             if widget['show_day_names'] == 'yes':
  919.                 options.append('GTK_CALENDAR_SHOW_DAY_NAMES')
  920.             del widget['show_day_names']
  921.         if widget.has_prop('no_month_change'):
  922.             if widget['no_month_change'] == 'yes':
  923.                 options.append('GTK_CALENDAR_NO_MONTH_CHANGE')
  924.             del widget['no_month_change']
  925.         if widget.has_prop('show_week_numbers'):
  926.             if widget['show_week_numbers'] == 'yes':
  927.                 options.append('GTK_CALENDAR_SHOW_WEEK_NUMBERS')
  928.             del widget['show_week_numbers']
  929.         if widget.has_prop('week_start_monday'):
  930.             if widget['week_start_monday'] == 'yes':
  931.                 options.append('GTK_CALENDAR_WEEK_START_MONDAY')
  932.             del widget['week_start_monday']
  933.         if options:
  934.             widget['display_options'] = string.join(options, '|')
  935.         else:
  936.             widget['display_options'] = ''
  937.  
  938.     if type == 'GnomeApp':
  939.         for childdef in widget.children:
  940.             if childdef.widget.has_prop('child_name'):
  941.                 if childdef.widget['child_name'] == 'GnomeApp:dock':
  942.                     del childdef.widget['child_name']
  943.                     childdef.internal_child = 'dock'
  944.                 elif childdef.widget['child_name'] == 'GnomeApp:appbar':
  945.                     del childdef.widget['child_name']
  946.                     childdef.internal_child = 'appbar'
  947.                     
  948.     if type == 'BonoboDock':
  949.         for childdef in widget.children:
  950.             if childdef.widget.has_prop('child_name'):
  951.                 if childdef.widget['child_name'] == 'GnomeDock:contents':
  952.                     del childdef.widget['child_name']
  953.  
  954.             if childdef.widget['class'] == 'BonoboDockItem':
  955.                 behavior = []
  956.                 if childdef.widget.has_prop('placement'):
  957.                     name = childdef.widget['placement']
  958.                     if re.match ('GNOME_.*', name):
  959.                         name = re.sub('GNOME_', 'BONOBO_', name, 1)
  960.                     childdef['placement'] = name
  961.                     del childdef.widget['placement']
  962.                 if childdef.widget.has_prop('band'):
  963.                     childdef['band'] = childdef.widget['band']
  964.                     del childdef.widget['band']
  965.                 if childdef.widget.has_prop ('position'):
  966.                     childdef['position'] = childdef.widget['position']
  967.                     del childdef.widget['position']
  968.                 if childdef.widget.has_prop ('offset'):
  969.                     childdef['offset'] = childdef.widget['offset']
  970.                     del childdef.widget['offset']
  971.                                     
  972.                 if childdef.widget.has_prop ('locked'):
  973.                     if childdef.widget['locked'] == 'yes':
  974.                         behavior.append ('BONOBO_DOCK_ITEM_BEH_LOCKED')
  975.                     del childdef.widget['locked']
  976.                 if childdef.widget.has_prop ('exclusive'):
  977.                     if childdef.widget['exclusive'] == 'yes':
  978.                         behavior.append ('BONOBO_DOCK_ITEM_BEH_EXCLUSIVE')
  979.                     del childdef.widget['exclusive']
  980.                 if childdef.widget.has_prop ('never_floating'):
  981.                     if childdef.widget['never_floating'] == 'yes':
  982.                         behavior.append ('BONOBO_DOCK_ITEM_BEH_NEVER_FLOATING')
  983.                     del childdef.widget['never_floating']
  984.                 if childdef.widget.has_prop ('never_vertical'):
  985.                     if childdef.widget['never_vertical'] == 'yes':
  986.                         behavior.append ('BONOBO_DOCK_ITEM_BEH_NEVER_VERTICAL')
  987.                     del childdef.widget['never_vertical']
  988.                 if childdef.widget.has_prop ('never_horizontal'):
  989.                     if childdef.widget['never_horizontal'] == 'yes':
  990.                         behavior.append ('BONOBO_DOCK_ITEM_BEH_NEVER_HORIZONTAL')
  991.                     del childdef.widget['never_horizontal']
  992.                 if behavior:
  993.                     childdef['behavior'] = string.join(behavior, '|')
  994.                 else:
  995.                     childdef['behavior'] = 'BONOBO_DOCK_ITEM_BEH_NORMAL'
  996.  
  997.     if type == 'GnomeDateEdit':
  998.         flags = []
  999.         if widget.has_prop('show_time'):
  1000.             if widget['show_time'] == 'yes':
  1001.                 flags.append ('GNOME_DATE_EDIT_SHOW_TIME')
  1002.             del widget['show_time']
  1003.         if widget.has_prop('use_24_format'):
  1004.             if widget['use_24_format'] == 'yes':
  1005.                 flags.append ('GNOME_DATE_EDIT_24_HR')
  1006.             del widget['use_24_format']
  1007.         if widget.has_prop('week_start_monday'):
  1008.             if widget['week_start_monday'] == 'yes':
  1009.                 flags.append ('GNOME_DATE_EDIT_WEEK_STARTS_ON_MONDAY')
  1010.             del widget['week_start_monday']
  1011.         if flags:
  1012.             widget['dateedit_flags'] = string.join(flags, '|')
  1013.         else:
  1014.             widget['dateedit_flags'] = '0'
  1015.  
  1016.     if type == 'GnomeMessageBox':
  1017.         try:
  1018.             name = widget['message_box_type']
  1019.         except KeyError:
  1020.             name = 'GNOME_MESSAGE_BOX_GENERIC'
  1021.         name = re.sub ('GNOME_MESSAGE_BOX_', '', name)
  1022.         widget['message_box_type'] = name.lower ()
  1023.  
  1024.     if type == 'GnomeDruidPageEdge':
  1025.         for color in ( 'title_color', 'text_color', 'background_color', 'logo_background_color', 'textbox_color' ):
  1026.             if widget.has_prop (color):
  1027.                 widget[color] = translate_color (widget[color])
  1028.  
  1029.     if type == 'GnomeDruidPageStandard':
  1030.         for color in ( 'title_foreground', 'background', 'logo_background' ):
  1031.             if widget.has_prop (color):
  1032.                 widget[color] = translate_color (widget[color])
  1033.         if widget.children:
  1034.             if widget.children[0].widget.has_prop ('child_name'):
  1035.                 widget.children[0].internal_child = 'vbox'
  1036.                 del widget.children[0].widget['child_name']
  1037.  
  1038.     return 0
  1039.  
  1040. # upgrade widgets to their gtk/gnome 2.0 equivalents
  1041. def upgrade_widget(widget):
  1042.     do_children = 1
  1043.  
  1044.     # some widgets are totally removed, so upgrade anyway
  1045.     if widget['class'] == 'GnomeDockItem':
  1046.         widget['class'] = 'BonoboDockItem'
  1047.     elif widget['class'] == 'GnomeDock':
  1048.         widget['class'] = 'BonoboDock'
  1049.     elif widget['class'] == 'GnomeAnimator':
  1050.         widget['class'] = 'GtkImage'
  1051.         if widget.has_prop ('loop_type'):
  1052.             del widget['loop_type']
  1053.         if widget.has_prop ('playback_direction'):
  1054.             del widget['playback_direction']
  1055.         if widget.has_prop ('playback_speed'):
  1056.             del widget['playback_speed']
  1057.     elif widget['class'] == 'GnomeDruidPageStart':
  1058.         widget['class'] = 'GnomeDruidPageEdge'
  1059.         widget['position'] = 'GNOME_EDGE_START'
  1060.     elif widget['class'] == 'GnomeDruidPageFinish':
  1061.         widget['class'] = 'GnomeDruidPageEdge'
  1062.         widget['position'] = 'GNOME_EDGE_FINISH'
  1063.     elif widget['class'] == 'GtkPixmapMenuItem':
  1064.         widget['class'] = 'GtkImageMenuItem'
  1065.  
  1066.     if not upgrade:
  1067.         if do_children:
  1068.             for childdef in widget.children:
  1069.                 upgrade_widget(childdef.widget)
  1070.         return
  1071.  
  1072.     # use GtkImage for image display now.
  1073.     if widget['class'] == 'GtkPixmap':
  1074.         widget['class'] = 'GtkImage'
  1075.         widget.rename_prop('filename', 'pixbuf')
  1076.         widget.remove_prop('build_insensitive')
  1077.     elif widget['class'] == 'GnomeFontSelector':
  1078.         widget['class'] = 'GtkFontSelectionDialog'
  1079.     elif widget['class'] == 'GnomePixmap':
  1080.         widget['class'] = 'GtkImage'
  1081.         widget.rename_prop('filename', 'pixbuf')
  1082.  
  1083.     elif widget['class'] == 'GtkText':
  1084.         widget['class'] = 'GtkTextView'
  1085.         widget['wrap_mode'] = 'GTK_WRAP_WORD'
  1086.         parent = widget['parent']
  1087.         if parent['class'] == 'GtkScrolledWindow':
  1088.             parent['shadow_type'] = 'GTK_SHADOW_IN'
  1089.  
  1090.     elif widget['class'] in ('GtkCList', 'GtkCTree', 'GtkList', 'GtkTree'):
  1091.         widget['class'] = 'GtkTreeView'
  1092.         parent = widget['parent']
  1093.         if parent['class'] == 'GtkScrolledWindow':
  1094.             parent['shadow_type'] = widget['shadow_type']
  1095.             widget.remove_prop('shadow_type')
  1096.         widget.rename_prop('show_titles', 'headers-visible')
  1097.         widget.remove_prop('columns')
  1098.         widget.remove_prop('column_widths')
  1099.         widget.remove_prop('selection_mode')
  1100.         widget.remove_prop('view_mode')
  1101.         widget.remove_prop('view_line')
  1102.  
  1103.     elif widget['class'] == 'GnomeDialog':
  1104.         widget['class'] = 'GtkDialog'
  1105.         if widget.has_prop ('auto_close'):
  1106.             del widget['auto_close']
  1107.         if widget.has_prop ('hide_on_close'):
  1108.             del widget['hide_on_close']
  1109.  
  1110.     if do_children:
  1111.         for childdef in widget.children:
  1112.             upgrade_widget(childdef.widget)
  1113.  
  1114. # warn about removed widgets, and build a list of libraries used
  1115. bad_widgets = {
  1116.     'GtkText': 'broken',
  1117.     'GtkList': 'broken',
  1118.     'GtkTree': 'broken',
  1119.     'GtkTreeItem': 'broken',
  1120.     'GtkCList': 'deprecated',
  1121.     'GtkCTree': 'deprecated',
  1122.     'GtkPixmap': 'deprecated',
  1123.     'GnomePixmap': 'deprecated',
  1124. #    'GnomeFontPicker': 'removed',
  1125.     'GtkPixmapMenuItem': 'removed',
  1126.     'GtkPacker': 'removed',
  1127.     'GnomeDialog': 'deprecated',
  1128.     'GnomeNumberEntry': 'removed',
  1129.     'GtkDial': 'removed',
  1130.     'GtkClock': 'removed',
  1131.     'GnomeCalculator': 'removed',
  1132.     'GnomeLess': 'removed',
  1133.     'GnomeSpell': 'removed',
  1134. }
  1135. def check_widget(widget, requirelist=[]):
  1136.     try:
  1137.         error = bad_widgets[widget['class']]
  1138.         print >> sys.stderr , 'widget %s of class %s is %s.' % \
  1139.               (widget['name'], widget['class'], error)
  1140.         if error == 'removed':
  1141.                 widget.mark_obsolete ()
  1142.     except KeyError:
  1143.         pass
  1144.  
  1145.     if widget['class'] == 'GnomeCanvas':
  1146.         if 'canvas' not in requirelist:
  1147.             requirelist.append('canvas')
  1148.     elif widget['class'][:5] == 'Gnome' and 'gnome' not in requirelist:
  1149.         requirelist.append('gnome')
  1150.     elif widget['class'][:6] == 'Bonobo' and 'bonobo' not in requirelist:
  1151.         requirelist.append('bonobo')
  1152.  
  1153.     for childdef in widget.children:
  1154.         check_widget(childdef.widget, requirelist)
  1155.  
  1156. # --- parse the file for widget definitions, fixup problems and dump.
  1157.  
  1158. def handle_file(filename):
  1159.     document = xml.dom.minidom.parse(filename)
  1160.     
  1161.     widgets = []
  1162.     for node in document.documentElement.childNodes:
  1163.     if node.nodeType == node.ELEMENT_NODE and \
  1164.        node.nodeName == 'widget':
  1165.             widgets.append(handle_widget(node))
  1166.  
  1167.     requireslist = []
  1168.  
  1169.     for widgetdef in widgets:
  1170.         upgrade_widget(widgetdef)
  1171.         fixup_widget(widgetdef)
  1172.         check_widget(widgetdef, requireslist)
  1173.  
  1174.     print '<?xml version="1.0" standalone="no"?> <!--*- mode: nxml -*-->'
  1175.     print '<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd" >'
  1176.     print
  1177.     print '<glade-interface>'
  1178.  
  1179.     for requirement in requireslist:
  1180.         print '  <requires lib="%s" />' % requirement
  1181.     if requireslist:
  1182.         print
  1183.  
  1184.     indent = '  '
  1185.     for widgetdef in widgets:
  1186.         widgetdef.dump(indent)
  1187.  
  1188.     print '</glade-interface>'
  1189.     document.unlink() # only needed for python interpreters without cyclic gc
  1190.  
  1191. usage = 'usage: libglade-convert [--no-upgrade] [--verbose] oldfile.glade'
  1192.  
  1193. def main():
  1194.     global upgrade, verbose
  1195.     opts, args = getopt.getopt(sys.argv[1:], '',
  1196.                                ['no-upgrade', 'verbose', 'help'])
  1197.     
  1198.     for opt, arg in opts:
  1199.         if opt == '--no-upgrade':
  1200.             upgrade = 0
  1201.         elif opt == '--verbose':
  1202.             verbose = 1
  1203.         elif opt == '--help':
  1204.             print usage
  1205.             sys.exit(0)
  1206.     if len(args) != 1:
  1207.     print >> sys.stderr, usage
  1208.     sys.exit(1)
  1209.     handle_file(args[0])
  1210.  
  1211. if __name__ == '__main__':
  1212.     main()
  1213.