2
# -*- coding: UTF-8 -*-
4
# [SNIPPET_NAME: GtkSourceView Example]
5
# [SNIPPET_CATEGORIES: PyGTK, PyGTKSourceView]
6
# [SNIPPET_DESCRIPTION: Demonstrates using Actions with a gtk.Action and gtk.AccelGroup]
8
# This script shows the use of pygtksourceview module, the python wrapper
9
# of gtksourceview C library.
10
# It has been directly translated from test-widget.c
12
# Copyright (C) 2004 - Iñigo Serna <inigoserna@telefonica.net>
14
# This program is free software; you can redistribute it and/or modify
15
# it under the terms of the GNU General Public License as published by
16
# the Free Software Foundation; either version 2 of the License, or
17
# (at your option) any later version.
19
# This program is distributed in the hope that it will be useful,
20
# but WITHOUT ANY WARRANTY; without even the implied warranty of
21
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
# GNU General Public License for more details.
24
# You should have received a copy of the GNU General Public License
25
# along with this program; if not, write to the Free Software
26
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35
if gtk.pygtk_version < (2,3,93):
36
print "PyGtk 2.3.93 or later required for this example"
45
######################################################################
47
windows = [] # this list contains all view windows
50
DATADIR = '/usr/share'
53
######################################################################
55
def error_dialog(parent, msg):
56
dialog = gtk.MessageDialog(parent,
57
gtk.DIALOG_DESTROY_WITH_PARENT,
65
######################################################################
66
##### remove all markers
67
def remove_all_markers(buffer):
68
begin, end = buffer.get_bounds()
69
markers = buffer.get_markers_in_region(begin, end)
70
map(buffer.delete_marker, markers)
73
######################################################################
75
def load_file(buffer, uri):
76
buffer.begin_not_undoable_action()
77
# TODO: use g_io_channel when pygtk supports it
79
txt = open(uri.path).read()
83
buffer.set_data('filename', uri.path)
84
buffer.end_not_undoable_action()
86
buffer.set_modified(False)
87
buffer.place_cursor(buffer.get_start_iter())
91
######################################################################
93
def open_file(buffer, filename):
94
# get the new language for the file mimetype
95
manager = buffer.get_data('languages-manager')
97
if os.path.isabs(filename):
100
path = os.path.abspath(filename)
101
uri = gnome.vfs.URI(path)
103
mime_type = gnome.vfs.get_mime_type(path) # needs ASCII filename, not URI
105
language = manager.get_language_from_mime_type(mime_type)
107
buffer.set_highlight(True)
108
buffer.set_language(language)
110
print 'No language found for mime type "%s"' % mime_type
111
buffer.set_highlight(False)
113
print 'Couldn\'t get mime type for file "%s"' % filename
114
buffer.set_highlight(False)
116
remove_all_markers(buffer)
117
load_file(buffer, uri) # TODO: check return
121
######################################################################
122
##### Printing callbacks
123
def page_cb(job, *args):
124
percent = 100 * job.get_page() / job.get_page_count()
125
print 'Printing %.2f%% \r' % percent,
128
def finished_cb(job, *args):
130
gjob = job.get_print_job()
131
preview = gnomeprint.ui.JobPreview(gjob, 'PyGtkSourceView Demo Print Preview')
135
######################################################################
136
##### Action callbacks
137
def numbers_toggled_cb(action, sourceview):
138
sourceview.set_show_line_numbers(action.get_active())
141
def markers_toggled_cb(action, sourceview):
142
sourceview.set_show_line_markers(action.get_active())
145
def margin_toggled_cb(action, sourceview):
146
sourceview.set_show_margin(action.get_active())
149
def auto_indent_toggled_cb(action, sourceview):
150
sourceview.set_auto_indent(action.get_active())
153
def insert_spaces_toggled_cb(action, sourceview):
154
sourceview.set_insert_spaces_instead_of_tabs(action.get_active())
157
def tabs_toggled_cb(action, action2, sourceview):
158
sourceview.set_tabs_width(action.get_current_value())
161
def new_view_cb(action, sourceview):
162
window = create_view_window(sourceview.get_buffer(), sourceview)
163
window.set_default_size(400, 400)
167
def print_preview_cb(action, sourceview):
168
buffer = sourceview.get_buffer()
169
job = gtksourceview.SourcePrintJob()
170
job.setup_from_view(sourceview)
171
job.set_wrap_mode(gtk.WRAP_CHAR)
172
job.set_highlight(True)
173
job.set_print_numbers(5)
174
job.set_header_format('Printed on %A', None, '%F', False)
175
filename = buffer.get_data('filename')
176
job.set_footer_format('%T', filename, 'Page %N/%Q', True)
177
job.set_print_header(True)
178
job.set_print_footer(True)
179
start, end = buffer.get_bounds()
180
if job.print_range_async(start, end):
181
job.connect('begin_page', page_cb)
182
job.connect('finished', finished_cb)
184
print 'Async print failed'
187
######################################################################
188
##### Buffer action callbacks
189
def open_file_cb(action, buffer):
190
chooser = gtk.FileChooserDialog('Open file...', None,
191
gtk.FILE_CHOOSER_ACTION_OPEN,
192
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
193
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
194
response = chooser.run()
195
if response == gtk.RESPONSE_OK:
196
filename = chooser.get_filename()
198
open_file(buffer, filename)
202
def update_cursor_position(buffer, view):
203
tabwidth = view.get_tabs_width()
204
pos_label = view.get_data('pos_label')
205
iter = buffer.get_iter_at_mark(buffer.get_insert())
206
nchars = iter.get_offset()
207
row = iter.get_line() + 1
209
start.set_line_offset(0)
211
while not start.equal(iter):
212
if start.get_char == '\t':
213
col += (tabwidth - (col % tabwidth))
216
start = start.forward_char()
217
pos_label.set_text('char: %d, line: %d, column: %d' % (nchars, row, col))
220
def move_cursor_cb (buffer, cursoriter, mark, view):
221
update_cursor_position(buffer, view)
224
def window_deleted_cb(widget, ev, view):
225
if windows[0] == widget:
228
# remove window from list
229
windows.remove(widget)
230
# we return False since we want the window destroyed
235
def button_press_cb(view, ev):
236
buffer = view.get_buffer()
237
if not view.get_show_line_markers():
239
# check that the click was on the left gutter
240
if ev.window == view.get_window(gtk.TEXT_WINDOW_LEFT):
242
marker_type = MARKER_TYPE_1
244
marker_type = MARKER_TYPE_2
245
x_buf, y_buf = view.window_to_buffer_coords(gtk.TEXT_WINDOW_LEFT,
246
int(ev.x), int(ev.y))
248
line_start = view.get_line_at_y(y_buf)[0]
249
line_end = line_start.copy()
250
line_end.forward_to_line_end()
252
# get the markers already in the line
253
marker_list = buffer.get_markers_in_region(line_start, line_end)
254
# search for the marker corresponding to the button pressed
255
for m in marker_list:
256
if m.get_marker_type() == marker_type:
263
# a marker was found, so delete it
264
buffer.delete_marker(marker)
266
# no marker found, create one
267
marker = buffer.create_marker(None, marker_type, line_start)
271
######################################################################
272
##### Actions & UI definition
274
('Open', gtk.STOCK_OPEN, '_Open', '<control>O', 'Open a file', open_file_cb),
275
('Quit', gtk.STOCK_QUIT, '_Quit', '<control>Q', 'Exit the application', gtk.main_quit)
279
('FileMenu', None, '_File'),
280
('ViewMenu', None, '_View'),
281
('PrintPreview', gtk.STOCK_PRINT, '_Print Preview', '<control>P', 'Preview printing of the file', print_preview_cb),
282
('NewView', gtk.STOCK_NEW, '_New View', None, 'Create a new view of the file', new_view_cb),
283
('TabsWidth', None, '_Tabs Width')
287
('ShowNumbers', None, 'Show _Line Numbers', None, 'Toggle visibility of line numbers in the left margin', numbers_toggled_cb, False),
288
('ShowMarkers', None, 'Show _Markers', None, 'Toggle visibility of markers in the left margin', markers_toggled_cb, False),
289
('ShowMargin', None, 'Show M_argin', None, 'Toggle visibility of right margin indicator', margin_toggled_cb, False),
290
('AutoIndent', None, 'Enable _Auto Indent', None, 'Toggle automatic auto indentation of text', auto_indent_toggled_cb, False),
291
('InsertSpaces', None, 'Insert _Spaces Instead of Tabs', None, 'Whether to insert space characters when inserting tabulations', insert_spaces_toggled_cb, False)
295
('TabsWidth4', None, '4', None, 'Set tabulation width to 4 spaces', 4),
296
('TabsWidth6', None, '6', None, 'Set tabulation width to 6 spaces', 6),
297
('TabsWidth8', None, '8', None, 'Set tabulation width to 8 spaces', 8),
298
('TabsWidth10', None, '10', None, 'Set tabulation width to 10 spaces', 10),
299
('TabsWidth12', None, '12', None, 'Set tabulation width to 12 spaces', 12)
302
view_ui_description = """
304
<menubar name='MainMenu'>
305
<menu action='FileMenu'>
306
<menuitem action='PrintPreview'/>
308
<menu action='ViewMenu'>
309
<menuitem action='NewView'/>
311
<menuitem action='ShowNumbers'/>
312
<menuitem action='ShowMarkers'/>
313
<menuitem action='ShowMargin'/>
315
<menuitem action='AutoIndent'/>
316
<menuitem action='InsertSpaces'/>
318
<menu action='TabsWidth'>
319
<menuitem action='TabsWidth4'/>
320
<menuitem action='TabsWidth6'/>
321
<menuitem action='TabsWidth8'/>
322
<menuitem action='TabsWidth10'/>
323
<menuitem action='TabsWidth12'/>
330
buffer_ui_description = """
332
<menubar name='MainMenu'>
333
<menu action='FileMenu'>
334
<menuitem action='Open'/>
336
<menuitem action='Quit'/>
338
<menu action='ViewMenu'>
345
######################################################################
346
##### create view window
347
def create_view_window(buffer, sourceview = None):
349
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
350
window.set_border_width(0)
351
window.set_title('PyGtkSourceView Demo')
352
windows.append(window) # this list contains all view windows
355
view = gtksourceview.SourceView(buffer)
356
buffer.connect('mark_set', move_cursor_cb, view)
357
buffer.connect('changed', update_cursor_position, view)
358
view.connect('button-press-event', button_press_cb)
359
window.connect('delete-event', window_deleted_cb, view)
361
# action group and UI manager
362
action_group = gtk.ActionGroup('ViewActions')
363
action_group.add_actions(view_actions, view)
364
action_group.add_toggle_actions(toggle_actions, view)
365
action_group.add_radio_actions(radio_actions, -1, tabs_toggled_cb, view)
367
ui_manager = gtk.UIManager()
368
ui_manager.insert_action_group(action_group, 0)
369
# save a reference to the ui manager in the window for later use
370
window.set_data('ui_manager', ui_manager)
371
accel_group = ui_manager.get_accel_group()
372
window.add_accel_group(accel_group)
373
ui_manager.add_ui_from_string(view_ui_description)
376
vbox = gtk.VBox(0, False)
377
sw = gtk.ScrolledWindow()
378
sw.set_shadow_type(gtk.SHADOW_IN)
379
pos_label = gtk.Label('Position')
380
view.set_data('pos_label', pos_label)
381
menu = ui_manager.get_widget('/MainMenu')
385
vbox.pack_start(menu, False, False, 0)
386
vbox.pack_start(sw, True, True, 0)
388
vbox.pack_start(pos_label, False, False, 0)
391
font_desc = pango.FontDescription('monospace 10')
393
view.modify_font(font_desc)
395
# change view attributes to match those of sourceview
397
action = action_group.get_action('ShowNumbers')
398
action.set_active(sourceview.get_show_line_numbers())
399
action = action_group.get_action('ShowMarkers')
400
action.set_active(sourceview.get_show_line_markers())
401
action = action_group.get_action('ShowMargin')
402
action.set_active(sourceview.get_margin())
403
action = action_group.get_action('AutoIndent')
404
action.set_active(sourceview.get_auto_indent())
405
action = action_group.get_action('InsertSpaces')
406
action.set_active(sourceview.get_insert_spaces_instead_of_tabs())
407
action = action_group.get_action('TabsWidth%d' % sourceview.get_tabs_width())
409
action.set_active(True)
412
pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(DATADIR,
413
'pixmaps/apple-green.png'))
415
view.set_marker_pixbuf(MARKER_TYPE_1, pixbuf)
417
print 'could not load marker 1 image. Spurious messages might get triggered'
418
pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(DATADIR,
419
'pixmaps/apple-red.png'))
421
view.set_marker_pixbuf(MARKER_TYPE_2, pixbuf)
423
print 'could not load marker 2 image. Spurious messages might get triggered'
430
######################################################################
431
##### create main window
432
def create_main_window(buffer):
433
window = create_view_window(buffer)
434
ui_manager = window.get_data('ui_manager')
436
# buffer action group
437
action_group = gtk.ActionGroup('BufferActions')
438
action_group.add_actions(buffer_actions, buffer)
439
ui_manager.insert_action_group(action_group, 1)
441
ui_manager.add_ui_from_string(buffer_ui_description)
443
# preselect menu checkitems
444
groups = ui_manager.get_action_groups()
445
# retrieve the view action group at position 0 in the list
446
action_group = groups[0]
447
action = action_group.get_action('ShowNumbers')
448
action.set_active(True)
449
action = action_group.get_action('ShowMarkers')
450
action.set_active(True)
451
action = action_group.get_action('ShowMargin')
452
action.set_active(True)
453
action = action_group.get_action('AutoIndent')
454
action.set_active(True)
455
action = action_group.get_action('InsertSpaces')
456
action.set_active(True)
457
action = action_group.get_action('TabsWidth8')
458
action.set_active(True)
463
######################################################################
467
lm = gtksourceview.SourceLanguagesManager()
468
buffer = gtksourceview.SourceBuffer()
469
buffer.set_data('languages-manager', lm)
473
open_file(buffer, args[1])
475
open_file(buffer, args[0])
477
# create first window
478
window = create_main_window(buffer)
479
window.set_default_size(500, 500)
486
if __name__ == '__main__':
487
if '--debug' in sys.argv:
489
pdb.run('main(sys.argv)')