home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / doc / python-gtksourceview2 / examples / test-widget.py
Encoding:
Python Source  |  2008-11-10  |  14.6 KB  |  453 lines

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. # This script shows the use of pygtksourceview2 module, the python wrapper
  5. # of gtksourceview2 C library.
  6. # It has been directly translated from test-widget.c
  7. #
  8. # Copyright (C) 2004 - I√±igo Serna <inigoserna@telefonica.net>
  9. #
  10. # This program is free software; you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as published by
  12. # the Free Software Foundation; either version 2 of the License, or
  13. # (at your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with this program; if not, write to the Free Software
  22. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  
  24.  
  25. import os, os.path
  26. import sys
  27. import gtk
  28. import gtksourceview2 as gtksourceview
  29. import gio
  30. import pango
  31.  
  32.  
  33. ######################################################################
  34. ##### global vars
  35. windows = []    # this list contains all view windows
  36. MARK_TYPE_1 = 'one'
  37. MARK_TYPE_2 = 'two'
  38. DATADIR = '/usr/share'
  39.  
  40.  
  41. ######################################################################
  42. ##### error dialog
  43. def error_dialog(parent, msg):
  44.     dialog = gtk.MessageDialog(parent,
  45.                                gtk.DIALOG_DESTROY_WITH_PARENT,
  46.                                gtk.MESSAGE_ERROR,
  47.                                gtk.BUTTONS_OK,
  48.                    msg)
  49.     dialog.run()
  50.     dialog.destroy()
  51.  
  52.  
  53. ######################################################################
  54. ##### remove all source marks
  55. def remove_all_marks(buffer):
  56.     begin, end = buffer.get_bounds()
  57.     marks = buffer.remove_source_marks(begin, end)
  58.  
  59.  
  60. ######################################################################
  61. ##### load file
  62. def load_file(buffer, path):
  63.     buffer.begin_not_undoable_action()
  64.     # TODO: use g_io_channel when pygtk supports it
  65.     try:
  66.         txt = open(path).read()
  67.     except:
  68.         return False
  69.     buffer.set_text(txt)
  70.     buffer.set_data('filename', path)
  71.     buffer.end_not_undoable_action()
  72.  
  73.     buffer.set_modified(False)
  74.     buffer.place_cursor(buffer.get_start_iter())
  75.     return True
  76.  
  77.  
  78. ######################################################################
  79. ##### Note this function is silly and wrong, because it ignores mime
  80. ##### parent types and subtypes.
  81. def get_language_for_mime_type(mime):
  82.     lang_manager = gtksourceview.language_manager_get_default()
  83.     lang_ids = lang_manager.get_language_ids()
  84.     for i in lang_ids:
  85.         lang = lang_manager.get_language(i)
  86.         for m in lang.get_mime_types():
  87.             if m == mime:
  88.                 return lang
  89.     return None
  90.  
  91. ######################################################################
  92. ##### buffer creation
  93. def open_file(buffer, filename):
  94.     # get the new language for the file mimetype
  95.  
  96.     if os.path.isabs(filename):
  97.         path = filename
  98.     else:
  99.         path = os.path.abspath(filename)
  100.     f = gio.File(path)
  101.  
  102.     path = f.get_path()
  103.  
  104.     info = f.query_info("*")
  105.  
  106.     mime_type = info.get_content_type()
  107.     language = None
  108.  
  109.     if mime_type:
  110.         language = get_language_for_mime_type(mime_type)
  111.         if not language:
  112.             print 'No language found for mime type "%s"' % mime_type
  113.     else:
  114.         print 'Couldn\'t get mime type for file "%s"' % filename
  115.  
  116.     buffer.set_language(language)
  117.     buffer.set_highlight_syntax(True)
  118.     remove_all_marks(buffer)
  119.     load_file(buffer, path) # TODO: check return
  120.     return True
  121.  
  122.  
  123. ######################################################################
  124. ##### Action callbacks
  125. def numbers_toggled_cb(action, sourceview):
  126.     sourceview.set_show_line_numbers(action.get_active())
  127.  
  128.  
  129. def marks_toggled_cb(action, sourceview):
  130.     sourceview.set_show_line_marks(action.get_active())
  131.  
  132.  
  133. def margin_toggled_cb(action, sourceview):
  134.     sourceview.set_show_right_margin(action.get_active())
  135.  
  136.  
  137. def auto_indent_toggled_cb(action, sourceview):
  138.     sourceview.set_auto_indent(action.get_active())
  139.  
  140.  
  141. def insert_spaces_toggled_cb(action, sourceview):
  142.     sourceview.set_insert_spaces_instead_of_tabs(action.get_active())
  143.  
  144.  
  145. def tabs_toggled_cb(action, action2, sourceview):
  146.     sourceview.set_tab_width(action.get_current_value())
  147.  
  148.  
  149. def new_view_cb(action, sourceview):
  150.     window = create_view_window(sourceview.get_buffer(), sourceview)
  151.     window.set_default_size(400, 400)
  152.     window.show()
  153.  
  154.  
  155. ######################################################################
  156. ##### Buffer action callbacks
  157. def open_file_cb(action, buffer):
  158.     chooser = gtk.FileChooserDialog('Open file...', None,
  159.                                     gtk.FILE_CHOOSER_ACTION_OPEN,
  160.                                     (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
  161.                                     gtk.STOCK_OPEN, gtk.RESPONSE_OK))
  162.     response = chooser.run()
  163.     if response == gtk.RESPONSE_OK:
  164.         filename = chooser.get_filename()
  165.         if filename:
  166.             open_file(buffer, filename)
  167.     chooser.destroy()
  168.  
  169.  
  170. def update_cursor_position(buffer, view):
  171.     tabwidth = view.get_tab_width()
  172.     pos_label = view.get_data('pos_label')
  173.     iter = buffer.get_iter_at_mark(buffer.get_insert())
  174.     nchars = iter.get_offset()
  175.     row = iter.get_line() + 1
  176.     start = iter
  177.     start.set_line_offset(0)
  178.     col = 0
  179.     while not start.equal(iter):
  180.         if start.get_char == '\t':
  181.             col += (tabwidth - (col % tabwidth))
  182.         else:
  183.             col += 1
  184.             start = start.forward_char()
  185.     pos_label.set_text('char: %d, line: %d, column: %d' % (nchars, row, col))
  186.  
  187.  
  188. def move_cursor_cb (buffer, cursoriter, mark, view):
  189.     update_cursor_position(buffer, view)
  190.  
  191.  
  192. def window_deleted_cb(widget, ev, view):
  193.     if windows[0] == widget:
  194.         gtk.main_quit()
  195.     else:
  196.         # remove window from list
  197.         windows.remove(widget)
  198.         # we return False since we want the window destroyed
  199.         return False
  200.     return True
  201.  
  202.  
  203. def button_press_cb(view, ev):
  204.     buffer = view.get_buffer()
  205.     if not view.get_show_line_marks():
  206.         return False
  207.     # check that the click was on the left gutter
  208.     if ev.window == view.get_window(gtk.TEXT_WINDOW_LEFT):
  209.         if ev.button == 1:
  210.             mark_type = MARK_TYPE_1
  211.         else:
  212.             mark_type = MARK_TYPE_2
  213.         x_buf, y_buf = view.window_to_buffer_coords(gtk.TEXT_WINDOW_LEFT,
  214.                                                     int(ev.x), int(ev.y))
  215.         # get line bounds
  216.         line_start = view.get_line_at_y(y_buf)[0]
  217.  
  218.         # get the markers already in the line
  219.         mark_list = buffer.get_source_marks_at_line(line_start.get_line(),
  220.                                                     mark_type)
  221.  
  222.         if mark_list:
  223.             # just take the first and delete it
  224.             buffer.delete_mark (mark_list[0])
  225.         else:
  226.             # no mark found: create one
  227.             buffer.create_source_mark (None, mark_type, line_start)
  228.  
  229.     return False
  230.  
  231.  
  232. ######################################################################
  233. ##### Actions & UI definition
  234. buffer_actions = [
  235.     ('Open', gtk.STOCK_OPEN, '_Open', '<control>O', 'Open a file', open_file_cb),
  236.     ('Quit', gtk.STOCK_QUIT, '_Quit', '<control>Q', 'Exit the application', gtk.main_quit)
  237. ]
  238.  
  239. view_actions = [
  240.     ('FileMenu', None, '_File'),
  241.     ('ViewMenu', None, '_View'),
  242.     ('NewView', gtk.STOCK_NEW, '_New View', None, 'Create a new view of the file', new_view_cb),
  243.     ('TabWidth', None, '_Tab Width')
  244. ]
  245.  
  246. toggle_actions = [
  247.     ('ShowNumbers', None, 'Show _Line Numbers', None, 'Toggle visibility of line numbers in the left margin', numbers_toggled_cb, False),
  248.     ('ShowMarks', None, 'Show Line _Marks', None, 'Toggle visibility of marks in the left margin', marks_toggled_cb, False),
  249.     ('ShowMargin', None, 'Show M_argin', None, 'Toggle visibility of right margin indicator', margin_toggled_cb, False),
  250.     ('AutoIndent', None, 'Enable _Auto Indent', None, 'Toggle automatic auto indentation of text', auto_indent_toggled_cb, False),
  251.     ('InsertSpaces', None, 'Insert _Spaces Instead of Tabs', None, 'Whether to insert space characters when inserting tabulations', insert_spaces_toggled_cb, False)
  252. ]
  253.  
  254. radio_actions = [
  255.     ('TabWidth4', None, '4', None, 'Set tabulation width to 4 spaces', 4),
  256.     ('TabWidth6', None, '6', None, 'Set tabulation width to 6 spaces', 6),
  257.     ('TabWidth8', None, '8', None, 'Set tabulation width to 8 spaces', 8),
  258.     ('TabWidth10', None, '10', None, 'Set tabulation width to 10 spaces', 10),
  259.     ('TabWidth12', None, '12', None, 'Set tabulation width to 12 spaces', 12)
  260. ]
  261.  
  262. view_ui_description = """
  263. <ui>
  264.   <menubar name='MainMenu'>
  265.     <menu action='ViewMenu'>
  266.       <menuitem action='NewView'/>
  267.       <separator/>
  268.       <menuitem action='ShowNumbers'/>
  269.       <menuitem action='ShowMarks'/>
  270.       <menuitem action='ShowMargin'/>
  271.       <separator/>
  272.       <menuitem action='AutoIndent'/>
  273.       <menuitem action='InsertSpaces'/>
  274.       <separator/>
  275.       <menu action='TabWidth'>
  276.         <menuitem action='TabWidth4'/>
  277.         <menuitem action='TabWidth6'/>
  278.         <menuitem action='TabWidth8'/>
  279.         <menuitem action='TabWidth10'/>
  280.         <menuitem action='TabWidth12'/>
  281.       </menu>
  282.     </menu>
  283.   </menubar>
  284. </ui>
  285. """
  286.  
  287. buffer_ui_description = """
  288. <ui>
  289.   <menubar name='MainMenu'>
  290.     <menu action='FileMenu'>
  291.       <menuitem action='Open'/>
  292.       <separator/>
  293.       <menuitem action='Quit'/>
  294.     </menu>
  295.     <menu action='ViewMenu'>
  296.     </menu>
  297.   </menubar>
  298. </ui>
  299. """
  300.  
  301.  
  302. ######################################################################
  303. ##### create view window
  304. def create_view_window(buffer, sourceview = None):
  305.     # window
  306.     window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  307.     window.set_border_width(0)
  308.     window.set_title('PyGtkSourceView Demo')
  309.     windows.append(window) # this list contains all view windows
  310.  
  311.     # view
  312.     view = gtksourceview.View(buffer)
  313.     buffer.connect('mark-set', move_cursor_cb, view)
  314.     buffer.connect('changed', update_cursor_position, view)
  315.     view.connect('button-press-event', button_press_cb)
  316.     window.connect('delete-event', window_deleted_cb, view)
  317.  
  318.     # action group and UI manager
  319.     action_group = gtk.ActionGroup('ViewActions')
  320.     action_group.add_actions(view_actions, view)
  321.     action_group.add_toggle_actions(toggle_actions, view)
  322.     action_group.add_radio_actions(radio_actions, -1, tabs_toggled_cb, view)
  323.  
  324.     ui_manager = gtk.UIManager()
  325.     ui_manager.insert_action_group(action_group, 0)
  326.     # save a reference to the ui manager in the window for later use
  327.     window.set_data('ui_manager', ui_manager)
  328.     accel_group = ui_manager.get_accel_group()
  329.     window.add_accel_group(accel_group)
  330.     ui_manager.add_ui_from_string(view_ui_description)
  331.  
  332.     # misc widgets
  333.     vbox = gtk.VBox(0, False)
  334.     sw = gtk.ScrolledWindow()
  335.     sw.set_shadow_type(gtk.SHADOW_IN)
  336.     pos_label = gtk.Label('Position')
  337.     view.set_data('pos_label', pos_label)
  338.     menu = ui_manager.get_widget('/MainMenu')
  339.  
  340.     # layout widgets
  341.     window.add(vbox)
  342.     vbox.pack_start(menu, False, False, 0)
  343.     vbox.pack_start(sw, True, True, 0)
  344.     sw.add(view)
  345.     vbox.pack_start(pos_label, False, False, 0)
  346.  
  347.     # setup view
  348.     font_desc = pango.FontDescription('monospace')
  349.     if font_desc:
  350.         view.modify_font(font_desc)
  351.  
  352.     # change view attributes to match those of sourceview
  353.     if sourceview:
  354.         action = action_group.get_action('ShowNumbers')
  355.         action.set_active(sourceview.get_show_line_numbers())
  356.         action = action_group.get_action('ShowMarks')
  357.         action.set_active(sourceview.get_show_line_marks())
  358.         action = action_group.get_action('ShowMargin')
  359.         action.set_active(sourceview.get_show_right_margin())
  360.         action = action_group.get_action('AutoIndent')
  361.         action.set_active(sourceview.get_auto_indent())
  362.         action = action_group.get_action('InsertSpaces')
  363.         action.set_active(sourceview.get_insert_spaces_instead_of_tabs())
  364.         action = action_group.get_action('TabWidth%d' % sourceview.get_tab_width())
  365.         if action:
  366.             action.set_active(True)
  367.  
  368.     # add source mark pixbufs
  369.     pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(DATADIR,
  370.                                                        'pixmaps/apple-green.png'))
  371.     if pixbuf:
  372.         view.set_mark_category_pixbuf (MARK_TYPE_1, pixbuf)
  373.         view.set_mark_category_priority (MARK_TYPE_1, 1)
  374.     else:
  375.         print 'could not load mark 1 image.  Spurious messages might get triggered'
  376.  
  377.     pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(DATADIR,
  378.                                                        'pixmaps/apple-red.png'))
  379.     if pixbuf:
  380.         view.set_mark_category_pixbuf (MARK_TYPE_2, pixbuf)
  381.         view.set_mark_category_priority (MARK_TYPE_2, 2)
  382.     else:
  383.         print 'could not load mark 2 image.  Spurious messages might get triggered'
  384.  
  385.     vbox.show_all()
  386.  
  387.     return window
  388.  
  389.  
  390. ######################################################################
  391. ##### create main window
  392. def create_main_window(buffer):
  393.     window = create_view_window(buffer)
  394.     ui_manager = window.get_data('ui_manager')
  395.  
  396.     # buffer action group
  397.     action_group = gtk.ActionGroup('BufferActions')
  398.     action_group.add_actions(buffer_actions, buffer)
  399.     ui_manager.insert_action_group(action_group, 1)
  400.     # merge buffer ui
  401.     ui_manager.add_ui_from_string(buffer_ui_description)
  402.  
  403.     # preselect menu checkitems
  404.     groups = ui_manager.get_action_groups()
  405.     # retrieve the view action group at position 0 in the list
  406.     action_group = groups[0]
  407.     action = action_group.get_action('ShowNumbers')
  408.     action.set_active(True)
  409.     action = action_group.get_action('ShowMarks')
  410.     action.set_active(True)
  411.     action = action_group.get_action('ShowMargin')
  412.     action.set_active(True)
  413.     action = action_group.get_action('AutoIndent')
  414.     action.set_active(True)
  415.     action = action_group.get_action('InsertSpaces')
  416.     action.set_active(True)
  417.     action = action_group.get_action('TabWidth8')
  418.     action.set_active(True)
  419.  
  420.     return window
  421.  
  422.  
  423. ######################################################################
  424. ##### main
  425. def main(args = []):
  426.     # create buffer
  427.     buffer = gtksourceview.Buffer()
  428.     mgr = gtksourceview.style_scheme_manager_get_default()
  429.     style_scheme = mgr.get_scheme('classic')
  430.     if style_scheme:
  431.         buffer.set_style_scheme(style_scheme)
  432.  
  433.     # parse arguments
  434.     if len(args) > 2:
  435.         open_file(buffer, args[1])
  436.     else:
  437.         open_file(buffer, args[0])
  438.  
  439.     # create first window
  440.     window = create_main_window(buffer)
  441.     window.set_default_size(500, 500)
  442.     window.show()
  443.  
  444.     # main loop
  445.     gtk.main()
  446.  
  447. if __name__ == '__main__':
  448.     if '--debug' in sys.argv:
  449.         import pdb
  450.         pdb.run('main(sys.argv)')
  451.     else:
  452.         main(sys.argv)
  453.