GtkSourceViewのビューとバッファに関する色々な設定に関して(例)
「GtkSourceViewのビューとバッファに関する色々な設定に関して(メモ・前半)」「GtkSourceViewのビューとバッファに関する色々な設定に関して(メモ・後半)」の内容を踏まえた例を貼り付ける。
[任意]ファイル名: gtksourceviewtest3.py
#! /usr/bin/python # -*- coding: utf-8 -*- import sys try: import pygtk pygtk.require('2.0') except: pass try: import pango import gtk except: print >> sys.stderr, 'Error: PyGTK is not installed' sys.exit(1) try: import gtksourceview2 except: print >> sys.stderr, 'Error: PyGtkSourceView is not installed' sys.exit(1) class LabelWithMnemonic(gtk.Label): """ ニーモニック・ウィジェットを初期化時に指定するラベル """ def __init__(self, str, widget): gtk.Label.__init__(self, str) self.props.use_underline = True self.props.mnemonic_widget = widget class MainWindow(gtk.Window): """ メインウィンドウ """ def __init__(self, *args, **kwargs): gtk.Window.__init__(self, *args, **kwargs) # 既定のフォント self.__default_font = 'Monospace 8' # ショートカットキー(アクセラレータ) self.__accelgroup = gtk.AccelGroup() self.add_accel_group(self.__accelgroup) # メニュー項目 self.__item_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.__accelgroup) self.__menu_file = gtk.Menu() self.__menu_file.add(self.__item_quit) self.__item_file = gtk.MenuItem('_File') self.__item_file.props.submenu = self.__menu_file self.__menubar = gtk.MenuBar() self.__menubar.append(self.__item_file) # 高度な設定向けGUI部品 self.__check_auto_indent = gtk.CheckButton('Auto _indent') self.__check_highlight_current_line = gtk.CheckButton('_Highlight current line') self.__check_indent_on_tab = gtk.CheckButton('Indent on _tab') self.__check_insert_spaces_instead_of_tabs = gtk.CheckButton('Insert _spaces instead of tabs') self.__check_show_line_numbers = gtk.CheckButton('Show line _numbers') self.__check_show_line_marks = gtk.CheckButton('Show line ma_rks') self.__check_show_right_margin = gtk.CheckButton('Show right _margin') self.__check_show_space = gtk.CheckButton('Show s_pace') self.__check_show_tab = gtk.CheckButton('Show t_ab') self.__check_show_newline = gtk.CheckButton('Show n_ewline') self.__check_highlight_matching_brackets = gtk.CheckButton('Highlight matching _brackets') self.__check_indent_width_use_tab_width = gtk.CheckButton('_Use tab width') self.__check_indent_width_use_tab_width.props.active = True self.__check_highlight_matching_brackets.props.active = True self.__spbtn_right_margin = gtk.SpinButton(gtk.Adjustment(lower=1, upper=200, step_incr=1, page_incr=2)) self.__spbtn_indent_width = gtk.SpinButton(gtk.Adjustment(value=2, lower=1, upper=32, step_incr=1, page_incr=2)) # 既定値ではないがユーザ設定の初期値として「value=2」 self.__spbtn_indent_width.props.sensitive = False # 既定では-1(手動設定なし) self.__spbtn_tab_width = gtk.SpinButton(gtk.Adjustment(lower=1, upper=32, step_incr=1, page_incr=2)) self.__spbtn_max_undo_levels = gtk.SpinButton(gtk.Adjustment(value=1000, lower=-1, upper=99999, step_incr=1, page_incr=2)) self.__label_indent_width = LabelWithMnemonic('In_dent width:', self.__spbtn_indent_width) self.__label_tab_width = LabelWithMnemonic('Tab _width:', self.__spbtn_tab_width) self.__label_max_undo_levels = LabelWithMnemonic('Ma_x undo levels:', self.__spbtn_max_undo_levels) # ソースビュー関係 # 言語マネージャとスタイルスキームマネージャ # 言語マネージャオブジェクトには言語の判別をするguess_language()もある self.__lm = gtksourceview2.language_manager_get_default() self.__ssm = gtksourceview2.style_scheme_manager_get_default() # 言語一覧 # Pythonを初期値にするためにその番号を調べる index_python = -1; i = 0 for lang_id in self.__lm.props.language_ids: if lang_id == 'python': index_python = i i += 1 # tangoを初期値にするためにその番号を調べる index_tango = -1; i = 0 for scheme_id in self.__ssm.props.scheme_ids: if scheme_id == 'tango': index_tango = i i += 1 self.__combo_lang = gtk.combo_box_new_text() for lang_id in self.__lm.props.language_ids: self.__combo_lang.append_text(lang_id) self.__combo_lang.props.active = index_python self.__combo_scheme = gtk.combo_box_new_text() for scheme_id in self.__ssm.props.scheme_ids: self.__combo_scheme.append_text(scheme_id) self.__combo_scheme.props.active = index_tango self.__combo_home_end = gtk.combo_box_new_text() # Home/Endの項目 for item in ['DISABLED', 'BEFORE', 'AFTER', 'ALWAYS']: self.__combo_home_end.append_text(item) self.__combo_home_end.props.active = 0 # DISABLED self.__label_lang = LabelWithMnemonic('_Language:', self.__combo_lang) self.__label_scheme = LabelWithMnemonic('S_cheme:', self.__combo_scheme) self.__fontbtn = gtk.FontButton(self.__default_font) self.__label_font = LabelWithMnemonic('F_ont:', self.__fontbtn) self.__label_home_end = LabelWithMnemonic('Smart Home/En_d:', self.__combo_home_end) self.__sourcebuf = gtksourceview2.Buffer(language=self.__lm.get_language(self.__combo_lang.get_active_text())) self.__sourcebuf.set_style_scheme(self.__ssm.get_scheme(self.__combo_scheme.get_active_text())) f_in = open(__file__, 'r') # begin_not_undoable_action()からnot_undoable_action()までの間の操作は # 取り消し(undo)可能なものとして記録されないようになる self.__sourcebuf.begin_not_undoable_action() self.__sourcebuf.props.text = f_in.read() self.__sourcebuf.end_not_undoable_action() f_in.close() self.__sourceview = gtksourceview2.View(self.__sourcebuf) self.__sourceview.props.auto_indent = self.__check_auto_indent.props.active = True self.__sourceview.props.highlight_current_line = self.__check_highlight_current_line.props.active = True self.__sourceview.props.show_line_numbers = self.__check_show_line_numbers.props.active = True self.__sourceview.props.show_right_margin = self.__check_show_right_margin.props.active = True self.__sourceview.props.indent_on_tab = self.__check_indent_on_tab.props.active = True self.__sourceview.props.insert_spaces_instead_of_tabs = self.__check_insert_spaces_instead_of_tabs.props.active = True self.__sourceview.props.right_margin_position = self.__spbtn_right_margin.props.value = 80 self.__sourceview.props.indent_width = -1 self.__sourceview.props.tab_width = self.__spbtn_tab_width.props.value = 8 self.__sourceview.props.wrap_mode = gtk.WRAP_CHAR self.__sourceview.modify_font(pango.FontDescription(self.__default_font)) self.__sw = gtk.ScrolledWindow() self.__sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.__sw.add(self.__sourceview) # ツールバー self.__toolbtn_undo = gtk.ToolButton(gtk.STOCK_UNDO) self.__toolbtn_undo.props.sensitive = False self.__toolbtn_undo.props.tooltip_text = 'undo' self.__toolbtn_redo = gtk.ToolButton(gtk.STOCK_REDO) self.__toolbtn_redo.props.sensitive = False self.__toolbtn_redo.props.tooltip_text = 'redo' self.__toolbar = gtk.Toolbar() self.__toolbar.insert(self.__toolbtn_undo, 0) self.__toolbar.insert(self.__toolbtn_redo, 1) # レイアウト用コンテナ self.__hbox = gtk.HBox() self.__hbox.pack_start(self.__label_lang, expand=False, fill=False) self.__hbox.pack_start(self.__combo_lang) self.__hbox.pack_start(self.__label_scheme, expand=False, fill=False) self.__hbox.pack_start(self.__combo_scheme) self.__hbox.pack_start(self.__label_font, expand=False, fill=False) self.__hbox.pack_end(self.__fontbtn, expand=False, fill=False) self.__hbox_right_margin = gtk.HBox() self.__hbox_right_margin.pack_start(self.__check_show_right_margin, expand=False, fill=False) self.__hbox_right_margin.pack_start(self.__spbtn_right_margin, expand=False, fill=False) self.__hbox_width = gtk.HBox() self.__hbox_width.pack_start(self.__label_indent_width, expand=False, fill=False) self.__hbox_width.pack_start(self.__spbtn_indent_width, expand=False, fill=False) self.__hbox_width.pack_start(self.__check_indent_width_use_tab_width, expand=False, fill=False) self.__hbox_width.pack_start(self.__label_tab_width, expand=False, fill=False) self.__hbox_width.pack_start(self.__spbtn_tab_width, expand=False, fill=False) self.__hbox_width.pack_start(self.__label_max_undo_levels, expand=False, fill=False) self.__hbox_width.pack_start(self.__spbtn_max_undo_levels, expand=False, fill=False) self.__hbox_home_end = gtk.HBox() self.__hbox_home_end.pack_start(self.__label_home_end, expand=False, fill=False) self.__hbox_home_end.pack_start(self.__combo_home_end, expand=False, fill=False) self.__vbox_advanced_left = gtk.VBox() self.__vbox_advanced_left.pack_start(self.__check_auto_indent, expand=False, fill=False) self.__vbox_advanced_left.pack_start(self.__check_highlight_current_line, expand=False, fill=False) self.__vbox_advanced_left.pack_start(self.__check_indent_on_tab, expand=False, fill=False) self.__vbox_advanced_left.pack_start(self.__check_insert_spaces_instead_of_tabs, expand=False, fill=False) self.__vbox_advanced_left.pack_start(self.__check_show_line_numbers, expand=False, fill=False) self.__vbox_advanced_left.pack_start(self.__check_show_line_marks, expand=False, fill=False) self.__vbox_advanced_left.pack_start(self.__hbox_right_margin, expand=False, fill=False) self.__vbox_advanced_right = gtk.VBox() self.__vbox_advanced_right.pack_start(self.__check_show_space, expand=False, fill=False) self.__vbox_advanced_right.pack_start(self.__check_show_tab, expand=False, fill=False) self.__vbox_advanced_right.pack_start(self.__check_show_newline, expand=False, fill=False) self.__vbox_advanced_right.pack_start(self.__check_highlight_matching_brackets, expand=False, fill=False) self.__vbox_advanced_right.pack_start(self.__hbox_home_end, expand=False, fill=False) self.__hbox_advanced = gtk.HBox() self.__hbox_advanced.pack_start(self.__vbox_advanced_left) self.__hbox_advanced.pack_start(self.__vbox_advanced_right) self.__vbox_advanced = gtk.VBox() self.__vbox_advanced.pack_start(self.__hbox_advanced) self.__vbox_advanced.pack_start(self.__hbox_width) self.__expander = gtk.Expander('Ad_vanced settings') self.__expander.props.use_underline = True self.__expander.add(self.__vbox_advanced) self.__vbox = gtk.VBox() self.__vbox.pack_start(self.__menubar, expand=False, fill=False) self.__vbox.pack_start(self.__toolbar, expand=False, fill=False) self.__vbox.pack_start(self.__hbox, expand=False, fill=False) self.__vbox.pack_start(self.__expander, expand=False, fill=False) self.__vbox.pack_start(self.__sw) # シグナル self.connect('delete_event', gtk.main_quit) self.__item_quit.connect('activate', gtk.main_quit) # undo/redo可否のツールバーボタンの状態は # can-undo/can-redoのGObjectプロパティの変更の通知を受け取って変更する self.__sourcebuf.connect('notify::can-undo', lambda gobj, property: self.__toolbtn_undo.set_sensitive(self.__sourcebuf.props.can_undo)) self.__sourcebuf.connect('notify::can-redo', lambda gobj, property: self.__toolbtn_redo.set_sensitive(self.__sourcebuf.props.can_redo)) # undo/redoのボタンが押されたときの処理 self.__toolbtn_undo.connect('clicked', lambda widget: self.__sourcebuf.undo()) self.__toolbtn_redo.connect('clicked', lambda widget: self.__sourcebuf.redo()) # 高度な設定の適用処理 self.__check_auto_indent.connect('toggled', lambda widget: self.__sourceview.set_auto_indent(widget.props.active)) self.__check_highlight_current_line.connect('toggled', lambda widget: self.__sourceview.set_highlight_current_line(widget.props.active)) self.__check_indent_on_tab.connect('toggled', lambda widget: self.__sourceview.set_indent_on_tab(widget.props.active)) self.__check_insert_spaces_instead_of_tabs.connect('toggled', lambda widget: self.__sourceview.set_insert_spaces_instead_of_tabs(widget.props.active)) self.__check_show_line_numbers.connect('toggled', lambda widget: self.__sourceview.set_show_line_numbers(widget.props.active)) self.__check_show_line_marks.connect('toggled', lambda widget: self.__sourceview.set_show_line_marks(widget.props.active)) self.__check_show_right_margin.connect('toggled', lambda widget: self.__sourceview.set_show_right_margin(widget.props.active)) self.__check_show_space.connect('toggled', self.__on_check_draw_spaces_toggled) self.__check_show_tab.connect('toggled', self.__on_check_draw_spaces_toggled) self.__check_show_newline.connect('toggled', self.__on_check_draw_spaces_toggled) self.__check_indent_width_use_tab_width.connect('toggled', self.__on_check_indent_width_use_tab_width_toggled) self.__check_highlight_matching_brackets.connect('toggled', lambda widget: self.__sourcebuf.set_highlight_matching_brackets(widget.props.active)) self.__spbtn_right_margin.connect('value-changed', lambda widget: self.__sourceview.set_right_margin_position(int(widget.props.value))) self.__spbtn_indent_width.connect('value-changed', lambda widget: self.__sourceview.set_indent_width(int(widget.props.value))) self.__spbtn_tab_width.connect('value-changed', lambda widget: self.__sourceview.set_tab_width(int(widget.props.value))) self.__spbtn_max_undo_levels.connect('value-changed', lambda widget: self.__sourcebuf.set_max_undo_levels(int(widget.props.value))) # 言語の切り替えは # バッファオブジェクトのset_language()に言語オブジェクトを入れることで行うか # GObjectプロパティlanguageへ言語オブジェクトを代入する # 言語オブジェクトは言語マネージャからget_language()に文字列名を入れて得る self.__combo_lang.connect('changed', lambda widget: self.__sourcebuf.set_language(self.__lm.get_language(widget.get_active_text()))) # スキームの切り替えもスキームマネージャオブジェクトを用いて # 似たような流れで行う self.__combo_scheme.connect('changed', lambda widget: self.__sourcebuf.set_style_scheme(self.__ssm.get_scheme(widget.get_active_text()))) # Home/End self.__combo_home_end.connect('changed', lambda widget: self.__sourceview.set_smart_home_end([gtksourceview2.SMART_HOME_END_DISABLED, gtksourceview2.SMART_HOME_END_BEFORE, gtksourceview2.SMART_HOME_END_AFTER, gtksourceview2.SMART_HOME_END_ALWAYS][widget.props.active])) self.__fontbtn.connect('font-set', lambda widget: self.__sourceview.modify_font(pango.FontDescription(widget.props.font_name))) # ウィンドウ self.add(self.__vbox) self.set_size_request(500, 300) self.resize(600, 400) self.props.title = 'Python GtkSourceView Test 3' def __on_check_draw_spaces_toggled(self, widget): """ スペース描画に関するチェックが操作された """ flags = 0 if self.__check_show_space.props.active: flags |= gtksourceview2.DRAW_SPACES_SPACE if self.__check_show_tab.props.active: flags |= gtksourceview2.DRAW_SPACES_TAB if self.__check_show_newline.props.active: flags |= gtksourceview2.DRAW_SPACES_NEWLINE self.__sourceview.set_draw_spaces(flags) # この他、gtksourceview2.DRAW_SPACES_ALLで全てを表示するようにもできる def __on_check_indent_width_use_tab_width_toggled(self, widget): """ 「インデント幅にタブ幅を用いる」チェックが操作された """ if widget.props.active: self.__spbtn_indent_width.set_sensitive(False) # GObjectプロパティindent-widthに-1を入れると # タブ幅(GObjectプロパティtab-width)の値が用いられる self.__sourceview.props.indent_width = -1 else: self.__spbtn_indent_width.set_sensitive(True) # スピンボタンから値を読み込んで適用 self.__sourceview.props.indent_width = self.__spbtn_indent_width.props.value class PyGtkSourceViewTest3: """ GtkSourceViewのテスト3 """ def main(self): """ アプリケーションのメイン処理 """ win = MainWindow() win.show_all() gtk.main() if __name__ == '__main__': app = PyGtkSourceViewTest3() app.main()
高度な設定を展開すると下のようになる。メモで扱った細かい設定はこの中のものとなる。ただし、「Line marks」についてはデータを用意していないため、場所は確保されるが何も表示はされない。
関連記事:
- PyGObject/PyGTKにおけるGObjectプロパティの操作について
- PyGObjectで gobject.GObjectクラスを継承してGObjectプロパティを用いる(前半)
- PyGObjectで gobject.GObjectクラスを継承してGObjectプロパティを用いる(後半)
- GtkSourceViewの色付き表示(シンタックス・ハイライティング)機能の動作について(ページ1/3)
- GtkSourceViewの色付き表示(シンタックス・ハイライティング)機能の動作について(ページ2/3)
- GtkSourceViewの色付き表示(シンタックス・ハイライティング)機能の動作について(ページ3/3)
- GtkSourceViewのビューとバッファに関する色々な設定に関して(メモ・前半)
- GtkSourceViewのビューとバッファに関する色々な設定に関して(メモ・後半)
使用したバージョン:
- Python 2.6.4
- PyGTK 2.16.0
- PyGtkSourceView 2.8.0