pgconsole/editor.py
changeset 76 3a41b351b122
parent 10 f3a1b9792cc9
equal deleted inserted replaced
75:39f777341db4 76:3a41b351b122
     1 import gtk, pango
     1 from gi.repository import Gtk
     2 import gtksourceview2 as gtksourceview
     2 from gi.repository import Pango
       
     3 from gi.repository import GtkSource
       
     4 
     3 from lxml import etree
     5 from lxml import etree
     4 
     6 
     5 from panedext import HPanedExt
     7 from pgconsole.panedext import HPanedExt
     6 from config import cfg
     8 from pgconsole.config import cfg
     7 
     9 
     8 
    10 
     9 class Editor(HPanedExt):
    11 class Editor(HPanedExt):
    10     def __init__(self):
    12     def __init__(self):
    11         super(Editor, self).__init__()
    13         super(Editor, self).__init__()
    12 
    14 
    13         self.view = gtksourceview.View()
    15         self.view = GtkSource.View()
    14         self.view.connect('toggle-overwrite', self.on_toggle_overwrite)
    16         self.view.connect('toggle-overwrite', self.on_toggle_overwrite)
    15 
    17 
    16         vbox = gtk.VBox()
    18         vbox = Gtk.VBox()
    17         self.vbox1 = vbox
    19         self.vbox1 = vbox
    18         self.add1(vbox)
    20         self.add1(vbox)
    19 
    21 
    20         sw = gtk.ScrolledWindow()
    22         sw = Gtk.ScrolledWindow()
    21         sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
    23         sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
    22         sw.set_shadow_type(gtk.SHADOW_IN)
    24         sw.set_shadow_type(Gtk.ShadowType.IN)
    23         vbox.pack_start(sw)
    25         vbox.pack_start(sw, expand=True, fill=True, padding=0)
    24         tree = gtk.TreeView()
    26         tree = Gtk.TreeView()
    25         tree.set_headers_visible(False)
    27         tree.set_headers_visible(False)
    26         tree.get_selection().set_mode(gtk.SELECTION_BROWSE)
    28         tree.get_selection().set_mode(Gtk.SelectionMode.BROWSE)
    27         sw.add(tree)
    29         sw.add(tree)
    28 
    30 
    29         model = gtk.ListStore(str, str, object, bool)  # title, filename, buffer, modified
    31         model = Gtk.ListStore(str, str, object, bool)  # title, filename, buffer, modified
    30         tree.set_model(model)
    32         tree.set_model(model)
    31         cell = gtk.CellRendererPixbuf()
    33         cell = Gtk.CellRendererPixbuf()
    32         cell.set_property('stock-id', gtk.STOCK_SAVE)
    34         cell.set_property('stock-id', Gtk.STOCK_SAVE)
    33         column = gtk.TreeViewColumn("File", cell, visible=3)
    35         column = Gtk.TreeViewColumn("File", cell, visible=3)
    34         tree.append_column(column)
    36         tree.append_column(column)
    35         column = gtk.TreeViewColumn("File", gtk.CellRendererText(), text=0)
    37         column = Gtk.TreeViewColumn("File", Gtk.CellRendererText(), text=0)
    36         tree.append_column(column)
    38         tree.append_column(column)
    37         tree.get_selection().connect('changed', self.item_change)
    39         tree.get_selection().connect('changed', self.item_change)
    38         tree.set_property('can-focus', False)
    40         tree.set_property('can-focus', False)
    39         self.filelist = tree
    41         self.filelist = tree
    40 
    42 
    41 
    43 
    42         hbox = gtk.HBox()
    44         hbox = Gtk.HBox()
    43 
    45 
    44         img = gtk.Image()
    46         img = Gtk.Image()
    45         img.set_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_SMALL_TOOLBAR)
    47         img.set_from_stock(Gtk.STOCK_NEW, Gtk.IconSize.SMALL_TOOLBAR)
    46         btn = gtk.Button()
    48         btn = Gtk.Button()
    47         btn.set_relief(gtk.RELIEF_NONE)
    49         btn.set_relief(Gtk.ReliefStyle.NONE)
    48         btn.set_focus_on_click(False)
    50         btn.set_focus_on_click(False)
    49         btn.set_image(img)
    51         btn.set_image(img)
    50         btn.connect('clicked', self.item_new)
    52         btn.connect('clicked', self.item_new)
    51         hbox.pack_start(btn, expand=False)
    53         hbox.pack_start(btn, expand=False, fill=True, padding=0)
    52 
    54 
    53         img = gtk.Image()
    55         img = Gtk.Image()
    54         img.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_SMALL_TOOLBAR)
    56         img.set_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.SMALL_TOOLBAR)
    55         btn = gtk.Button()
    57         btn = Gtk.Button()
    56         btn.set_relief(gtk.RELIEF_NONE)
    58         btn.set_relief(Gtk.ReliefStyle.NONE)
    57         btn.set_focus_on_click(False)
    59         btn.set_focus_on_click(False)
    58         btn.set_image(img)
    60         btn.set_image(img)
    59         btn.connect('clicked', self.item_open)
    61         btn.connect('clicked', self.item_open)
    60         hbox.pack_start(btn, expand=False)
    62         hbox.pack_start(btn, expand=False, fill=True, padding=0)
    61 
    63 
    62         img = gtk.Image()
    64         img = Gtk.Image()
    63         img.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_SMALL_TOOLBAR)
    65         img.set_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.SMALL_TOOLBAR)
    64         btn = gtk.Button()
    66         btn = Gtk.Button()
    65         btn.set_relief(gtk.RELIEF_NONE)
    67         btn.set_relief(Gtk.ReliefStyle.NONE)
    66         btn.set_focus_on_click(False)
    68         btn.set_focus_on_click(False)
    67         btn.set_image(img)
    69         btn.set_image(img)
    68         btn.connect('clicked', self.item_close)
    70         btn.connect('clicked', self.item_close)
    69         hbox.pack_start(btn, expand=False)
    71         hbox.pack_start(btn, expand=False, fill=True, padding=0)
    70         hbox.connect('size-request', self.leftbuttons_size_request)
    72         hbox.connect('size-allocate', self.leftbuttons_size_request)
    71 
    73 
    72         vbox.pack_start(hbox, expand=False)
    74         vbox.pack_start(hbox, expand=False, fill=True, padding=0)
    73 
    75 
    74         vbox = gtk.VBox()
    76         vbox = Gtk.VBox()
    75         vbox.set_property("width-request", 200)
    77         vbox.set_property("width-request", 200)
    76         self.add2(vbox)
    78         self.add2(vbox)
    77         self.child_set_property(vbox, 'shrink', False)
    79         self.child_set_property(vbox, 'shrink', False)
    78 
    80 
    79 
    81 
    80         # scroll
    82         # scroll
    81         sw = gtk.ScrolledWindow()
    83         sw = Gtk.ScrolledWindow()
    82         sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
    84         sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
    83         sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
    85         sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
    84         sw.add(self.view)
    86         sw.add(self.view)
    85         vbox.pack_start(sw)
    87         vbox.pack_start(sw, expand=True, fill=True, padding=0)
    86 
    88 
    87 
    89 
    88         self.view.set_show_line_numbers(True)
    90         self.view.set_show_line_numbers(True)
    89         self.view.set_smart_home_end(True)
    91         self.view.set_smart_home_end(True)
    90         #self.view.set_insert_spaces_instead_of_tabs(True)
    92         #self.view.set_insert_spaces_instead_of_tabs(True)
    91         self.view.set_property("tab-width", 4)
    93         self.view.set_property("tab-width", 4)
    92         self.view.set_auto_indent(True)
    94         self.view.set_auto_indent(True)
    93 
    95 
    94         # font
    96         # font
    95         font_desc = pango.FontDescription('monospace')
    97         font_desc = Pango.FontDescription('monospace')
    96         if font_desc:
    98         if font_desc:
    97             self.view.modify_font(font_desc)
    99             self.view.modify_font(font_desc)
    98 
   100 
    99         # status bar
   101         # status bar
   100         hbox = gtk.HBox()
   102         hbox = Gtk.HBox()
   101 
   103 
   102         self.st_file, fr1 = self.construct_status('SQL snippet')
   104         self.st_file, fr1 = self.construct_status('SQL snippet')
   103         self.st_file.set_ellipsize(pango.ELLIPSIZE_START)
   105         self.st_file.set_ellipsize(Pango.EllipsizeMode.START)
   104         self.st_insovr, fr2 = self.construct_status('INS')
   106         self.st_insovr, fr2 = self.construct_status('INS')
   105         self.st_linecol, fr3 = self.construct_status('Line: 0 Col: 0')
   107         self.st_linecol, fr3 = self.construct_status('Line: 0 Col: 0')
   106 
   108 
   107 
   109 
   108         img = gtk.Image()
   110         img = Gtk.Image()
   109         img.set_from_stock(gtk.STOCK_SAVE, gtk.ICON_SIZE_SMALL_TOOLBAR)
   111         img.set_from_stock(Gtk.STOCK_SAVE, Gtk.IconSize.SMALL_TOOLBAR)
   110         #save = img
   112         #save = img
   111         save = gtk.Button()
   113         save = Gtk.Button()
   112         save.set_relief(gtk.RELIEF_NONE)
   114         save.set_relief(Gtk.ReliefStyle.NONE)
   113         save.set_focus_on_click(False)
   115         save.set_focus_on_click(False)
   114         save.set_image(img)
   116         save.set_image(img)
   115         save.connect('clicked', self.item_save)
   117         save.connect('clicked', self.item_save)
   116         hbox.pack_start(save, expand=False)
   118         hbox.pack_start(save, expand=False, fill=True, padding=0)
   117 
   119 
   118         hbox.pack_start(fr1, expand=True)
   120         hbox.pack_start(fr1, expand=True, fill=True, padding=0)
   119         hbox.pack_start(fr2, expand=False)
   121         hbox.pack_start(fr2, expand=False, fill=True, padding=0)
   120         hbox.pack_start(fr3, expand=False)
   122         hbox.pack_start(fr3, expand=False, fill=True, padding=0)
   121 
   123 
   122         #sep = gtk.HSeparator()
   124         #sep = Gtk.HSeparator()
   123         #vbox.pack_start(sep, expand=False, fill=False, padding=0)
   125         #vbox.pack_start(sep, expand=False, fill=False, padding=0)
   124 
   126 
   125         #align = gtk.Alignment()
   127         #align = Gtk.Alignment()
   126         #align.set_property("bottom-padding", 3)
   128         #align.set_property("bottom-padding", 3)
   127         #align.set_property("xscale", 1.0)
   129         #align.set_property("xscale", 1.0)
   128         #align.add(hbox)
   130         #align.add(hbox)
   129 
   131 
   130         #frame = gtk.Frame()
   132         #frame = Gtk.Frame()
   131         #frame.add(hbox)
   133         #frame.add(hbox)
   132         #frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
   134         #frame.set_shadow_type(Gtk.SHADOW_ETCHED_IN)
   133         vbox.pack_start(hbox, expand=False, padding=0)
   135         vbox.pack_start(hbox, expand=False, fill=True, padding=0)
   134 
   136 
   135         self.load_nodes()
   137         self.load_nodes()
   136         self.build_context_menu()
   138         self.build_context_menu()
   137 
   139 
   138 
   140 
   139     def build_context_menu(self):
   141     def build_context_menu(self):
   140         menu = gtk.Menu()
   142         menu = Gtk.Menu()
   141         item = gtk.ImageMenuItem(gtk.STOCK_SAVE, "Save")
   143         item = Gtk.ImageMenuItem(use_stock=True, label=Gtk.STOCK_SAVE)
   142         item.connect("activate", self.item_save)
   144         item.connect("activate", self.item_save)
   143         item.show()
   145         item.show()
   144         menu.append(item)
   146         menu.append(item)
   145 
   147 
   146         item = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS, "Save as")
   148         item = Gtk.ImageMenuItem(use_stock=True, label=Gtk.STOCK_SAVE_AS)
   147         item.connect("activate", self.item_save_as)
   149         item.connect("activate", self.item_save_as)
   148         item.show()
   150         item.show()
   149         menu.append(item)
   151         menu.append(item)
   150 
   152 
   151         item = gtk.ImageMenuItem(gtk.STOCK_CLOSE, "Close")
   153         item = Gtk.ImageMenuItem(use_stock=True, label=Gtk.STOCK_CLOSE)
   152         item.connect("activate", self.item_close)
   154         item.connect("activate", self.item_close)
   153         item.show()
   155         item.show()
   154         menu.append(item)
   156         menu.append(item)
   155 
   157 
   156         item = gtk.SeparatorMenuItem()
   158         item = Gtk.SeparatorMenuItem()
   157         item.show()
   159         item.show()
   158         menu.append(item)
   160         menu.append(item)
   159 
   161 
   160         item = gtk.ImageMenuItem(gtk.STOCK_GO_UP, "Move up")
   162         item = Gtk.ImageMenuItem(use_stock=True, label=Gtk.STOCK_GO_UP)
   161         item.show()
   163         item.show()
   162         menu.append(item)
   164         menu.append(item)
   163 
   165 
   164         item = gtk.ImageMenuItem(gtk.STOCK_GO_DOWN, "Move down")
   166         item = Gtk.ImageMenuItem(use_stock=True, label=Gtk.STOCK_GO_DOWN)
   165         item.show()
   167         item.show()
   166         menu.append(item)
   168         menu.append(item)
   167 
   169 
   168         self.filelist_menu = menu
   170         self.filelist_menu = menu
   169 
   171 
   177             pathinfo = self.filelist.get_path_at_pos(x, y)
   179             pathinfo = self.filelist.get_path_at_pos(x, y)
   178             if pathinfo is not None:
   180             if pathinfo is not None:
   179                 path, col, cellx, celly = pathinfo
   181                 path, col, cellx, celly = pathinfo
   180                 self.filelist.grab_focus()
   182                 self.filelist.grab_focus()
   181                 self.filelist.set_cursor(path, col, 0)
   183                 self.filelist.set_cursor(path, col, 0)
   182                 self.filelist_menu.popup(None, None, None, event.button, event.time)
   184                 self.filelist_menu.popup(None, None, None, None, event.button, event.time)
   183             return True
   185             return True
   184 
   186 
   185 
   187 
   186 
   188 
   187     def make_buffer(self):
   189     def make_buffer(self):
   188         buffer = gtksourceview.Buffer()
   190         buffer = GtkSource.Buffer()
   189         buffer.connect('mark-set', self.buffer_mark_set)
   191         buffer.connect('mark-set', self.buffer_mark_set)
   190         buffer.connect('changed', self.buffer_changed)
   192         buffer.connect('changed', self.buffer_changed)
   191 
   193 
   192         # style
   194         # style
   193         mgr = gtksourceview.style_scheme_manager_get_default()
   195         mgr = GtkSource.StyleSchemeManager.get_default()
   194         style_scheme = mgr.get_scheme('kate')
   196         style_scheme = mgr.get_scheme('kate')
   195         if style_scheme:
   197         if style_scheme:
   196             buffer.set_style_scheme(style_scheme)
   198             buffer.set_style_scheme(style_scheme)
   197 
   199 
   198         # syntax
   200         # syntax
   199         lngman = gtksourceview.language_manager_get_default()
   201         lngman = GtkSource.LanguageManager.get_default()
   200         langsql = lngman.get_language('sql')
   202         langsql = lngman.get_language('sql')
   201         buffer.set_language(langsql)
   203         buffer.set_language(langsql)
   202         buffer.set_highlight_syntax(True)
   204         buffer.set_highlight_syntax(True)
   203 
   205 
   204         return buffer
   206         return buffer
   214             filename = None
   216             filename = None
   215             if type == 'text' and node.text:
   217             if type == 'text' and node.text:
   216                 buffer.set_text(node.text)
   218                 buffer.set_text(node.text)
   217             if type == 'file':
   219             if type == 'file':
   218                 filename = node.text
   220                 filename = node.text
   219                 content = open(filename).read()
   221                 try:
       
   222                     content = open(filename).read()
       
   223                 except IOError:
       
   224                     content = ''
   220                 buffer.set_text(content)
   225                 buffer.set_text(content)
   221             iter = model.append([name, filename, buffer, False])
   226             iter = model.append([name, filename, buffer, False])
   222             if sel == name:
   227             if sel == name:
   223                 self.filelist.get_selection().select_iter(iter)
   228                 self.filelist.get_selection().select_iter(iter)
   224 
   229 
   238             return None
   243             return None
   239         return self.buffer.get_text(*bounds)
   244         return self.buffer.get_text(*bounds)
   240 
   245 
   241 
   246 
   242     def construct_status(self, text):
   247     def construct_status(self, text):
   243         st = gtk.Label(text)
   248         st = Gtk.Label(text)
   244         st.set_property("single-line-mode", True)
   249         st.set_property("single-line-mode", True)
   245         st.set_property("xpad", 3)
   250         st.set_property("xpad", 3)
   246         st.set_alignment(0.0, 0.5)
   251         st.set_alignment(0.0, 0.5)
   247         fr = gtk.Frame()
   252         fr = Gtk.Frame()
   248         fr.set_shadow_type(gtk.SHADOW_ETCHED_OUT)
   253         fr.set_shadow_type(Gtk.ShadowType.ETCHED_OUT)
   249         fr.add(st)
   254         fr.add(st)
   250         return st, fr
   255         return st, fr
   251 
   256 
   252 
   257 
   253     def on_toggle_overwrite(self, w):
   258     def on_toggle_overwrite(self, w):
   317         cfg.root.editor.nodes.set('selected', title)
   322         cfg.root.editor.nodes.set('selected', title)
   318         cfg.save()
   323         cfg.save()
   319 
   324 
   320 
   325 
   321     def item_open(self, w):
   326     def item_open(self, w):
   322         dialog = gtk.FileChooserDialog(title='Open file', action=gtk.FILE_CHOOSER_ACTION_OPEN,
   327         dialog = Gtk.FileChooserDialog(title='Open file', action=Gtk.FileChooserAction.OPEN,
   323             buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
   328             buttons=(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL,Gtk.STOCK_OPEN,Gtk.ResponseType.OK))
   324         dialog.set_default_response(gtk.RESPONSE_OK)
   329         dialog.set_default_response(Gtk.ResponseType.OK)
   325         dialog.set_select_multiple(True)
   330         dialog.set_select_multiple(True)
   326 
   331 
   327         filter = gtk.FileFilter()
   332         filter = Gtk.FileFilter()
   328         filter.set_name("SQL files")
   333         filter.set_name("SQL files")
   329         filter.add_pattern("*.sql")
   334         filter.add_pattern("*.sql")
   330         dialog.add_filter(filter)
   335         dialog.add_filter(filter)
   331 
   336 
   332         filter = gtk.FileFilter()
   337         filter = Gtk.FileFilter()
   333         filter.set_name("All files")
   338         filter.set_name("All files")
   334         filter.add_pattern("*")
   339         filter.add_pattern("*")
   335         dialog.add_filter(filter)
   340         dialog.add_filter(filter)
   336 
   341 
   337         response = dialog.run()
   342         response = dialog.run()
   338         if response == gtk.RESPONSE_OK:
   343         if response == Gtk.ResponseType.OK:
   339             filenames = dialog.get_filenames()
   344             filenames = dialog.get_filenames()
   340             for fname in filenames:
   345             for fname in filenames:
   341                 self.open_file(fname)
   346                 self.open_file(fname)
   342 
   347 
   343         dialog.destroy()
   348         dialog.destroy()
   391 
   396 
   392         filename, buffer = model.get(iter, 1, 2)
   397         filename, buffer = model.get(iter, 1, 2)
   393 
   398 
   394         path, file = filename.rsplit('/',1)
   399         path, file = filename.rsplit('/',1)
   395 
   400 
   396         dialog = gtk.FileChooserDialog(title='Save as', action=gtk.FILE_CHOOSER_ACTION_SAVE,
   401         dialog = Gtk.FileChooserDialog(title='Save as', action=Gtk.FileChooserAction.SAVE,
   397             buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
   402             buttons=(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL,Gtk.STOCK_SAVE,Gtk.ResponseType.OK))
   398         dialog.set_default_response(gtk.RESPONSE_OK)
   403         dialog.set_default_response(Gtk.ResponseType.OK)
   399         dialog.set_current_folder(path)
   404         dialog.set_current_folder(path)
   400         dialog.set_current_name(file)
   405         dialog.set_current_name(file)
   401 
   406 
   402         filter = gtk.FileFilter()
   407         filter = Gtk.FileFilter()
   403         filter.set_name("SQL files")
   408         filter.set_name("SQL files")
   404         filter.add_pattern("*.sql")
   409         filter.add_pattern("*.sql")
   405         dialog.add_filter(filter)
   410         dialog.add_filter(filter)
   406 
   411 
   407         filter = gtk.FileFilter()
   412         filter = Gtk.FileFilter()
   408         filter.set_name("All files")
   413         filter.set_name("All files")
   409         filter.add_pattern("*")
   414         filter.add_pattern("*")
   410         dialog.add_filter(filter)
   415         dialog.add_filter(filter)
   411 
   416 
   412         response = dialog.run()
   417         response = dialog.run()
   413         if response == gtk.RESPONSE_OK:
   418         if response == Gtk.ResponseType.OK:
   414             filename = dialog.get_filename()
   419             filename = dialog.get_filename()
   415             data = buffer.get_text(*buffer.get_bounds())
   420             data = buffer.get_text(*buffer.get_bounds())
   416             open(filename, 'w').write(data)
   421             open(filename, 'w').write(data)
   417 
   422 
   418             title = filename.rsplit('/',1)[1]
   423             title = filename.rsplit('/',1)[1]
   428         model, sel = self.filelist.get_selection().get_selected_rows()
   433         model, sel = self.filelist.get_selection().get_selected_rows()
   429         if not sel:
   434         if not sel:
   430             return
   435             return
   431         iter = model.get_iter(sel[0])
   436         iter = model.get_iter(sel[0])
   432         newiter = model.iter_next(iter)
   437         newiter = model.iter_next(iter)
   433         if newiter is None and sel[0][0] > 0:
   438         if newiter is None and sel[0].get_indices()[0] > 0:
   434             newiter = model.get_iter((sel[0][0]-1,))
   439             newiter = model.get_iter((sel[0].get_indices()[0]-1,))
   435 
   440 
   436         title, buffer = model.get(iter, 0, 2)
   441         title, buffer = model.get(iter, 0, 2)
   437         #buffer.destroy()
   442         #buffer.destroy()
   438 
   443 
   439         model.remove(iter)
   444         model.remove(iter)
   448         el.getparent().remove(el)
   453         el.getparent().remove(el)
   449         cfg.save()
   454         cfg.save()
   450 
   455 
   451 
   456 
   452     def leftbuttons_size_request(self, w, request):
   457     def leftbuttons_size_request(self, w, request):
   453         self.set_snap1(request[0])
   458         self.set_snap1(request.width)
   454         return True
   459         return True
   455 
   460