source: trunk/third/libglade2/libglade-convert.in @ 18268

Revision 18268, 45.1 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18267, which included commits to RCS files with non-trunk default branches.
Line 
1#!@PYTHON@
2# -*- mode: python -*-
3
4# yes, this requires python 2.x and an XML parser module (eg. PyExpat)
5
6import re
7import sys
8import string
9import getopt
10import xml.dom.minidom
11
12translatable_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
19upgrade = 1
20verbose = 0
21
22class 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
189def totext(nodelist):
190    return string.join(map(lambda node: node.toxml(), nodelist), '')
191
192def 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
210def 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
226def 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
240def 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
266name_counter = 0
267def 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
273global_obsolete_props = [
274    'child_min_width',
275    'child_min_height',
276    'child_ipad_x',
277    'child_ipad_y'
278]
279global_renamed_props = [
280    ('width', 'width-request'),
281    ('height', 'height-request'),
282]
283
284# properties to change on specific widgets
285obsolete_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
308renamed_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
344global_renamed_child_props = [
345    ('pack', 'pack_type'),
346    ('child_ipad_x', 'child_internal_pad_x'),
347    ('child_ipad_y', 'child_internal_pad_y')
348]
349obsolete_child_props = {
350}
351renamed_child_props = {
352    'GtkTable' : [ ('xpad', 'x_padding'), ('ypad', 'y_padding') ],
353}
354
355def 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
387parent_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
413global_group_map = { }
414
415def 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.
421def 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
430def 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
447stock_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
512def 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
523def 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
534def 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
543stock_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}
586def 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
592def translate_color (color):
593    c = string.split (color, ',')
594    return '#%.2x%.2x%.2x' % (int (c[0]), int (c[1]), int (c[2]))
595
596
597def 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
1030def 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
1104bad_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}
1124def 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
1147def 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
1180usage = 'usage: libglade-convert [--no-upgrade] [--verbose] oldfile.glade'
1181
1182def 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
1200if __name__ == '__main__':
1201    main()
Note: See TracBrowser for help on using the repository browser.