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