Example #1
0
 def __init__(self, buffer=None, width_in_chars=81, aspect_ratio=0.33, fdesc=None):
     _View.__init__(self, buffer=buffer if buffer else Buffer())
     self._fdesc = fdesc if fdesc is not None else pango.FontDescription("mono 10")
     self.modify_font(self._fdesc)
     self._width_in_chars = width_in_chars
     self._aspect_ratio = aspect_ratio
     self._adjust_size_request()
Example #2
0
	def __init__(self, manager, editor):
		View.__init__(self, Buffer())
		self.__init_attributes(manager, editor)
		self.__set_properties()
		self.__add_view_to_scrolled_window()
		self.__sigid1 = manager.connect("destroy", self.__destroy_cb)
		self.__sigid2 = manager.connect("description-treeview-sensitivity", self.__sensitive_cb)
		self.__sigid3 = manager.connect("description-treeview-cursor-changed", self.__changed_cb)
		self.__sigid4 = manager.connect("selected-templates-dictionary-key", self.__key_cb)
		self.__sigid5 = manager.connect("templates-dictionary", self.__dictionary_cb)
		self.__sigid6 = self.connect("button-press-event", self.__button_press_event_cb)
Example #3
0
 def __init__(self, manager, editor):
     View.__init__(self, Buffer())
     self.__init_attributes(manager, editor)
     self.__set_properties()
     self.__add_view_to_scrolled_window()
     self.__sigid1 = manager.connect("destroy", self.__destroy_cb)
     self.__sigid2 = manager.connect("description-treeview-sensitivity",
                                     self.__sensitive_cb)
     self.__sigid3 = manager.connect("description-treeview-cursor-changed",
                                     self.__changed_cb)
     self.__sigid4 = manager.connect("selected-templates-dictionary-key",
                                     self.__key_cb)
     self.__sigid5 = manager.connect("templates-dictionary",
                                     self.__dictionary_cb)
     self.__sigid6 = self.connect("button-press-event",
                                  self.__button_press_event_cb)
Example #4
0
    def _init (cls):
        def callback (widget, allocation):
            cls.widgets["enterGameNotationFrame"].set_size_request(
                    223, allocation.height-4)
        cls.widgets["enterGameNotationSidePanel"].connect_after("size-allocate", callback)

        flags = []
        if isInstalled():
            path = gettext.find("pychess")
        else:
            path = gettext.find("pychess", localedir=addDataPrefix("lang"))
        if path:
            loc = locale.getdefaultlocale()[0][-2:].lower()
            flags.append(addDataPrefix("flags/%s.png" % loc))

        flags.append(addDataPrefix("flags/us.png"))

        cls.ib = ImageButton(flags)
        cls.widgets["imageButtonDock"].add(cls.ib)
        cls.ib.show()

        cls.sourcebuffer = SourceBuffer()
        sourceview = SourceView(cls.sourcebuffer)
        cls.widgets["scrolledwindow6"].add(sourceview)
        sourceview.show()

        # Pgn format does not allow tabulator
        sourceview.set_insert_spaces_instead_of_tabs(True)
        sourceview.set_wrap_mode(gtk.WRAP_WORD)

        man = LanguageManager()
        # Init new version
        if hasattr(man.props, 'search_path'):
            path = os.path.join(getDataPrefix(),"gtksourceview-1.0/language-specs")
            man.props.search_path = man.props.search_path + [path]
            if 'pgn' in man.get_language_ids():
                lang = man.get_language('pgn')
                cls.sourcebuffer.set_language(lang)
            else:
                log.warn("Unable to load pgn syntax-highlighting.")
            cls.sourcebuffer.set_highlight_syntax(True)
        # Init old version
        else:
            os.environ["XDG_DATA_DIRS"] = getDataPrefix()+":/usr/share/"
            man = LanguageManager()
            for lang in man.get_available_languages():
                if lang.get_name() == "PGN":
                    cls.sourcebuffer.set_language(lang)
                    break
            else:
                log.warn("Unable to load pgn syntax-highlighting.")
            cls.sourcebuffer.set_highlight(True)
Example #5
0
    def __init__(self, filename=None, text=None, title="View"):
        # Defining the main window
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_resizable(True)
        window.connect("destroy", self.close_window, window)
        window.set_title(title)
        window.set_border_width(0)
        window.set_position(gtk.WIN_POS_CENTER)
        window.set_size_request(600, 400)

        #Creating a vertical box
        box = gtk.VBox(False, 10)
        box.set_border_width(10)
        window.add(box)
        box.show()

        # TODO add status bar where this message can be reported?
        if not HAVE_SOURCEVIEW or lang is None:
            print "UNABLE TO LOCATE ASCEND LANGUAGE DESCRIPTION for gtksourceview"

        #Creating a ScrolledWindow for the textview widget
        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        view = MyView()
        view.set_editable(False)
        buff = MyBuffer()
        if HAVE_SOURCEVIEW:
            buff.set_language(lang)
            buff.set_highlight_syntax(True)
        view.set_buffer(buff)
        scroll.add(view)

        scroll.show()
        view.show()
        box.pack_start(scroll)

        if filename is not None:
            #Get the content of the file
            model = open(filename, "r")
            if model:
                string = model.read()
                model.close()
                buff.set_text(string)
            else:
                self.reporter.reportError("Error opening the file")
        elif text is not None:
            buff.set_text(text)
        else:
            buff.set_text("Nothing was selected")

        window.show()
Example #6
0
	def __init__(self, filename=None, text=None, title="View"):
		# Defining the main window
		window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		window.set_resizable(True)  
		window.connect("destroy", self.close_window, window)
		window.set_title(title)
		window.set_border_width(0)
		window.set_position(gtk.WIN_POS_CENTER)
		window.set_size_request(600,400)

		#Creating a vertical box
		box = gtk.VBox(False, 10)
		box.set_border_width(10)
		window.add(box)
		box.show()
		
		# TODO add status bar where this message can be reported?
		if not HAVE_SOURCEVIEW or lang is None:
			print "UNABLE TO LOCATE ASCEND LANGUAGE DESCRIPTION for gtksourceview"

		#Creating a ScrolledWindow for the textview widget
		scroll = gtk.ScrolledWindow()
		scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		view = MyView()
		view.set_editable(False)
		buff = MyBuffer()
		if HAVE_SOURCEVIEW:
			buff.set_language(lang)
			buff.set_highlight_syntax(True)
		view.set_buffer(buff)
		scroll.add(view)

		scroll.show()
		view.show()
		box.pack_start(scroll)

		if filename is not None:
			#Get the content of the file
			model = open(filename, "r")
			if model:
				string = model.read()
				model.close()
				buff.set_text(string)
			else:
				self.reporter.reportError( "Error opening the file" )
		elif text is not None:
			buff.set_text(text)
		else:
			buff.set_text("Nothing was selected")

		window.show()
Example #7
0
	def __init__(self, manager, editor):
		View.__init__(self, Buffer())
		self.__init_attributes(manager, editor)
		self.__add_view_to_scrolled_window()
		self.__sigid1 = manager.connect("destroy", self.__destroy_cb)
		self.__sigid2 = manager.connect("valid-trigger", self.__valid_cb)
Example #8
0
    def __init__(self,
                 filename=None,
                 content=None,
                 title=None,
                 parent=None,
                 autosave=False):
        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
        vbox = gtk.VBox()
        self.add(vbox)
        self.__ui_string = """
<ui>
  <menubar name='Menubar'>
    <menu action='FileMenu'>
      <menuitem action='Save'/>
      <menuitem action='SaveAs'/>
      <separator/>
      <menuitem action='ReadOnly'/>
      <separator/>
      <menuitem action='Revert'/>
      <separator/>
      <menuitem action='Close'/>
    </menu>
    <menu action='EditMenu'>
      <menuitem action='Undo'/>
      <menuitem action='Redo'/>
      <separator/>
      <menuitem action='Find'/>
      <menuitem action='GotoLine'/>
    </menu>
    <menu action='ToolsMenu'>
      <menuitem action='About'/>
    </menu>
  </menubar>
</ui>
"""
        self.__create_ui()
        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)

        self.__filename = os.path.abspath(filename)
        self.__autosave = autosave
        self.__modified = False
        self.__last_len = 0

        self.__save_text_id = 0

        self.gtksourceview_mode = gtksourceview_avail

        if gtksourceview_avail:
            self.input = SourceBuffer()
            self.input_view = SourceView(self.input)
            if gtksourceview2_avail:
                self.input.connect('notify::can-undo',
                                   lambda *args: self.__sync_undoredo())
                self.input.connect('notify::can-redo',
                                   lambda *args: self.__sync_undoredo())
            else:
                self.input.connect('can-undo',
                                   lambda *args: self.__sync_undoredo())
                self.input.connect('can-redo',
                                   lambda *args: self.__sync_undoredo())
        else:
            self.input = gtk.TextBuffer()
            self.input_view = gtk.TextView(self.input)
        self.input_view.set_wrap_mode(gtk.WRAP_WORD)
        self.input_view.connect("key-press-event",
                                self.__handle_key_press_event)

        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
        scroll.add(self.input_view)

        vbox.pack_start(scroll, True, True)

        if filename and os.path.isfile(self.__filename):
            _logger.debug("reading %s", self.__filename)
            f = open_text_file(self.__filename, 'r')
            self.__original_text = f.read()
        else:
            self.__original_text = content

        if self.__original_text:
            if gtksourceview_avail:
                self.input.begin_not_undoable_action()
            self.input.set_property('text', self.__original_text)
            self.__last_len = self.input.get_char_count()
            if gtksourceview_avail:
                self.input.end_not_undoable_action()

        self.input.move_mark_by_name('insert', self.input.get_start_iter())
        self.input.move_mark_by_name('selection_bound',
                                     self.input.get_start_iter())

        self.input.connect('mark-set', self.__on_mark_set)

        self.__searcharea = InlineSearchArea(self.input_view)
        self.__searcharea.connect('close', self.__on_search_close)
        self.__searcharea.show_all()
        self.__searcharea.hide()
        self.__searcharea.set_no_show_all(True)
        vbox.pack_start(self.__searcharea, expand=False)

        self.__status_hbox = gtk.HBox()
        self.__statusbar = gtk.Statusbar()
        self.__status_hbox.pack_start(self.__statusbar, expand=True)
        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
        self.__pos_status = gtk.Statusbar()
        self.__pos_status.set_size_request(160, 10)  # Taken from GEdit
        self.__pos_context = self.__pos_status.get_context_id("HotEditor")
        self.__status_hbox.pack_start(self.__pos_status, expand=False)
        vbox.pack_start(self.__status_hbox, expand=False)
        self.__sync_undoredo()
        self.__sync_modified_sensitivity()

        self.input.connect("changed", self.__handle_text_changed)

        self.connect("delete-event", self.__handle_delete_event)
        self.__sync_title()
        if parent:
            self.set_transient_for(parent)
        self.set_size_request(800, 600)
Example #9
0
class HotEditorWindow(gtk.Window):
    def __init__(self,
                 filename=None,
                 content=None,
                 title=None,
                 parent=None,
                 autosave=False):
        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
        vbox = gtk.VBox()
        self.add(vbox)
        self.__ui_string = """
<ui>
  <menubar name='Menubar'>
    <menu action='FileMenu'>
      <menuitem action='Save'/>
      <menuitem action='SaveAs'/>
      <separator/>
      <menuitem action='ReadOnly'/>
      <separator/>
      <menuitem action='Revert'/>
      <separator/>
      <menuitem action='Close'/>
    </menu>
    <menu action='EditMenu'>
      <menuitem action='Undo'/>
      <menuitem action='Redo'/>
      <separator/>
      <menuitem action='Find'/>
      <menuitem action='GotoLine'/>
    </menu>
    <menu action='ToolsMenu'>
      <menuitem action='About'/>
    </menu>
  </menubar>
</ui>
"""
        self.__create_ui()
        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)

        self.__filename = os.path.abspath(filename)
        self.__autosave = autosave
        self.__modified = False
        self.__last_len = 0

        self.__save_text_id = 0

        self.gtksourceview_mode = gtksourceview_avail

        if gtksourceview_avail:
            self.input = SourceBuffer()
            self.input_view = SourceView(self.input)
            if gtksourceview2_avail:
                self.input.connect('notify::can-undo',
                                   lambda *args: self.__sync_undoredo())
                self.input.connect('notify::can-redo',
                                   lambda *args: self.__sync_undoredo())
            else:
                self.input.connect('can-undo',
                                   lambda *args: self.__sync_undoredo())
                self.input.connect('can-redo',
                                   lambda *args: self.__sync_undoredo())
        else:
            self.input = gtk.TextBuffer()
            self.input_view = gtk.TextView(self.input)
        self.input_view.set_wrap_mode(gtk.WRAP_WORD)
        self.input_view.connect("key-press-event",
                                self.__handle_key_press_event)

        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
        scroll.add(self.input_view)

        vbox.pack_start(scroll, True, True)

        if filename and os.path.isfile(self.__filename):
            _logger.debug("reading %s", self.__filename)
            f = open_text_file(self.__filename, 'r')
            self.__original_text = f.read()
        else:
            self.__original_text = content

        if self.__original_text:
            if gtksourceview_avail:
                self.input.begin_not_undoable_action()
            self.input.set_property('text', self.__original_text)
            self.__last_len = self.input.get_char_count()
            if gtksourceview_avail:
                self.input.end_not_undoable_action()

        self.input.move_mark_by_name('insert', self.input.get_start_iter())
        self.input.move_mark_by_name('selection_bound',
                                     self.input.get_start_iter())

        self.input.connect('mark-set', self.__on_mark_set)

        self.__searcharea = InlineSearchArea(self.input_view)
        self.__searcharea.connect('close', self.__on_search_close)
        self.__searcharea.show_all()
        self.__searcharea.hide()
        self.__searcharea.set_no_show_all(True)
        vbox.pack_start(self.__searcharea, expand=False)

        self.__status_hbox = gtk.HBox()
        self.__statusbar = gtk.Statusbar()
        self.__status_hbox.pack_start(self.__statusbar, expand=True)
        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
        self.__pos_status = gtk.Statusbar()
        self.__pos_status.set_size_request(160, 10)  # Taken from GEdit
        self.__pos_context = self.__pos_status.get_context_id("HotEditor")
        self.__status_hbox.pack_start(self.__pos_status, expand=False)
        vbox.pack_start(self.__status_hbox, expand=False)
        self.__sync_undoredo()
        self.__sync_modified_sensitivity()

        self.input.connect("changed", self.__handle_text_changed)

        self.connect("delete-event", self.__handle_delete_event)
        self.__sync_title()
        if parent:
            self.set_transient_for(parent)
        self.set_size_request(800, 600)

    def __on_search_close(self, sa):
        self.__searcharea.hide()

    def set_read_only(self, readonly):
        readonly_toggle = self.__actiongroup.get_action('ReadOnly')
        readonly_toggle.set_active(readonly)

    def set_code_mode(self, codemode):
        if not self.gtksourceview_mode:
            return
        # Non-code is the default
        if not codemode:
            return
        self.input_view.modify_font(pango.FontDescription("monospace"))
        fs = Filesystem.getInstance()
        try:
            mimetype = fs.get_file_sync(self.__filename).mimetype
        except FileStatError, e:
            mimetype = None
        target_lang = None
        if gtksourceview2_avail:
            import gtksourceview2
            langman = gtksourceview2.language_manager_get_default()
            for language_id in langman.get_language_ids():
                language = langman.get_language(language_id)
                for langmime in language.get_mime_types():
                    if mimetype == langmime:
                        target_lang = language
                        break
                if target_lang:
                    break
            self.input.set_highlight_syntax(True)
        else:
            import gtksourceview
            target_lang = gtksourceview.SourceLanguagesManager(
            ).get_language_from_mime_type(mimetype)
            self.input.set_highlight(True)
        if target_lang:
            self.input.set_language(target_lang)
Example #10
0
	def __init_attributes(self, editor):
		self.__editor = editor
		from gtksourceview2 import View, Buffer
		self.__view = View(Buffer())
		return
Example #11
0
class View(object):

	def __init__(self, editor):
		self.__init_attributes(editor)
		self.__add_view_to_scroll()
		self.__set_properties()
		self.__sigid1 = editor.connect("quit", self.__quit_cb)
		self.__sigid2 = editor.connect("checking-file", self.__update_cb)
		self.__sigid3 = editor.connect_after("load-error", self.__update_cb)
		self.__sigid4 = editor.connect("renamed-file", self.__update_cb)
		editor.register_object(self)

	def __init_attributes(self, editor):
		self.__editor = editor
		from gtksourceview2 import View, Buffer
		self.__view = View(Buffer())
		return

	def __destroy(self):
		self.__editor.disconnect_signal(self.__sigid1, self.__editor)
		self.__editor.disconnect_signal(self.__sigid2, self.__editor)
		self.__editor.disconnect_signal(self.__sigid3, self.__editor)
		self.__editor.disconnect_signal(self.__sigid4, self.__editor)
		self.__editor.unregister_object(self)
		del self
		return False

	def __set_properties(self):
		from gtk import DEST_DEFAULT_ALL
		targets = [("text/uri-list", 0, 80)]
		from gtk.gdk import ACTION_COPY
		self.__view.set_pixels_above_lines(2)
		self.__view.set_pixels_below_lines(2)
		self.__view.set_pixels_inside_wrap(2)
		self.__view.drag_dest_set(DEST_DEFAULT_ALL, targets, ACTION_COPY)
		self.__view.drag_dest_add_text_targets()
		self.__view.set_property("can-focus", True)
		self.__view.set_property("auto-indent", True)
		self.__view.set_property("highlight-current-line", True)
		self.__view.set_property("show-line-numbers", True)
		self.__view.set_property("indent-width", -1)
		from gtksourceview2 import SMART_HOME_END_BEFORE
		self.__view.set_property("smart-home-end", SMART_HOME_END_BEFORE)
		self.__update_view()
		self.__view.set_property("sensitive", True)
		return False

	def __update_view(self):
		language = self.__editor.language
		language = language	if language else "plain text"
		from SCRIBES.TabWidthMetadata import get_value as tab_width
		self.__view.set_property("tab-width", tab_width(language))
		from SCRIBES.MarginPositionMetadata import get_value as margin_position
		self.__view.set_property("right-margin-position", margin_position(language))
		from SCRIBES.DisplayRightMarginMetadata import get_value as show_margin
		self.__view.set_property("show-right-margin", show_margin(language))
		from SCRIBES.UseTabsMetadata import get_value as use_tabs
		self.__view.set_property("insert-spaces-instead-of-tabs",(not use_tabs(language)))
		from SCRIBES.FontMetadata import get_value as font_name
		from pango import FontDescription
		font = FontDescription(font_name(language))
		self.__view.modify_font(font)
		from gtk import WRAP_WORD_CHAR, WRAP_NONE
		from SCRIBES.TextWrappingMetadata import get_value as wrap_mode_bool
		wrap_mode = self.__view.set_wrap_mode
		wrap_mode(WRAP_WORD_CHAR) if wrap_mode_bool(language) else wrap_mode(WRAP_NONE)
		self.__view.grab_focus()
		return False

	def __add_view_to_scroll(self):
		swin = self.__editor.gui.get_widget("ScrolledWindow")
		swin.add(self.__view)
		swin.show_all()
		self.__view.grab_focus()
		return False

	def __quit_cb(self, *args):
		self.__destroy()
		return False

	def __update_cb(self, *args):
		from gobject import idle_add
		idle_add(self.__update_view)
		return False
Example #12
0
class HotEditorWindow(gtk.Window):
    def __init__(self, filename=None, content=None, title=None, parent=None, autosave=False):
        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
        vbox = gtk.VBox()
        self.add(vbox)
        self.__ui_string = """
<ui>
  <menubar name='Menubar'>
    <menu action='FileMenu'>
      <menuitem action='Save'/>
      <menuitem action='SaveAs'/>
      <separator/>
      <menuitem action='ReadOnly'/>
      <separator/>
      <menuitem action='Revert'/>
      <separator/>
      <menuitem action='Close'/>
    </menu>
    <menu action='EditMenu'>
      <menuitem action='Undo'/>
      <menuitem action='Redo'/>
      <separator/>
      <menuitem action='Find'/>
      <menuitem action='GotoLine'/>
    </menu>
    <menu action='ToolsMenu'>
      <menuitem action='About'/>
    </menu>
  </menubar>
</ui>
"""
        self.__create_ui()
        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)

        self.__filename = os.path.abspath(filename)
        self.__autosave = autosave
        self.__modified = False
        self.__last_len = 0
         
        self.__save_text_id = 0

        self.gtksourceview_mode = gtksourceview_avail

        if gtksourceview_avail:
            self.input = SourceBuffer()
            self.input_view = SourceView(self.input)
            if gtksourceview2_avail:
                self.input.connect('notify::can-undo', lambda *args: self.__sync_undoredo())
                self.input.connect('notify::can-redo', lambda *args: self.__sync_undoredo())
            else:
                self.input.connect('can-undo', lambda *args: self.__sync_undoredo())
                self.input.connect('can-redo', lambda *args: self.__sync_undoredo())
        else:
            self.input = gtk.TextBuffer()
            self.input_view = gtk.TextView(self.input)
        self.input_view.set_wrap_mode(gtk.WRAP_WORD)
        self.input_view.connect("key-press-event", self.__handle_key_press_event)
        
        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)        
        scroll.add(self.input_view)
        
        vbox.pack_start(scroll, True, True)

        if filename and os.path.isfile(self.__filename):
            _logger.debug("reading %s", self.__filename)
            f = open_text_file(self.__filename, 'r')
            self.__original_text = f.read()
        else:
            self.__original_text = content
            
        if self.__original_text:
            if gtksourceview_avail:
                self.input.begin_not_undoable_action()
            self.input.set_property('text', self.__original_text)
            self.__last_len = self.input.get_char_count()             
            if gtksourceview_avail:
                self.input.end_not_undoable_action()            
        
        self.input.move_mark_by_name('insert', self.input.get_start_iter())
        self.input.move_mark_by_name('selection_bound', self.input.get_start_iter())
        
        self.input.connect('mark-set', self.__on_mark_set)

        self.__searcharea = InlineSearchArea(self.input_view)
        self.__searcharea.connect('close', self.__on_search_close)
        self.__searcharea.show_all()
        self.__searcharea.hide()
        self.__searcharea.set_no_show_all(True)
        vbox.pack_start(self.__searcharea, expand=False)

        self.__status_hbox = gtk.HBox()
        self.__statusbar = gtk.Statusbar()
        self.__status_hbox.pack_start(self.__statusbar, expand=True)
        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
        self.__pos_status = gtk.Statusbar()
        self.__pos_status.set_size_request(160, 10) # Taken from GEdit
        self.__pos_context = self.__pos_status.get_context_id("HotEditor")
        self.__status_hbox.pack_start(self.__pos_status, expand=False)
        vbox.pack_start(self.__status_hbox, expand=False)
        self.__sync_undoredo()
        self.__sync_modified_sensitivity()

        self.input.connect("changed", self.__handle_text_changed)

        self.connect("delete-event", self.__handle_delete_event)
        self.__sync_title()
        if parent:
            self.set_transient_for(parent)
        self.set_size_request(800, 600)
        
    def __on_search_close(self, sa):
        self.__searcharea.hide()
        
    def set_read_only(self, readonly):
        readonly_toggle = self.__actiongroup.get_action('ReadOnly')
        readonly_toggle.set_active(readonly)
        
    def set_code_mode(self, codemode):
        if not self.gtksourceview_mode:
            return
        # Non-code is the default
        if not codemode:
            return
        self.input_view.modify_font(pango.FontDescription("monospace"))
        fs = Filesystem.getInstance()
        try:
            mimetype = fs.get_file_sync(self.__filename).mimetype
        except FileStatError, e:
            mimetype = None
        target_lang = None        
        if gtksourceview2_avail:
            import gtksourceview2
            langman = gtksourceview2.language_manager_get_default() 
            for language_id in langman.get_language_ids():
                language = langman.get_language(language_id)
                for langmime in language.get_mime_types():
                    if mimetype == langmime:
                        target_lang = language
                        break
                if target_lang:
                    break
            self.input.set_highlight_syntax(True)
        else:
            import gtksourceview
            target_lang = gtksourceview.SourceLanguagesManager().get_language_from_mime_type(mimetype)
            self.input.set_highlight(True)
        if target_lang:
            self.input.set_language(target_lang)
Example #13
0
 def __init_attributes(self, editor):
     self.__editor = editor
     from gtksourceview2 import View, Buffer
     self.__view = View(Buffer())
     return
Example #14
0
class View(object):
    def __init__(self, editor):
        self.__init_attributes(editor)
        self.__add_view_to_scroll()
        self.__set_properties()
        self.__sigid1 = editor.connect("quit", self.__quit_cb)
        self.__sigid2 = editor.connect("checking-file", self.__update_cb)
        self.__sigid3 = editor.connect_after("load-error", self.__update_cb)
        self.__sigid4 = editor.connect("renamed-file", self.__update_cb)
        editor.register_object(self)

    def __init_attributes(self, editor):
        self.__editor = editor
        from gtksourceview2 import View, Buffer
        self.__view = View(Buffer())
        return

    def __destroy(self):
        self.__editor.disconnect_signal(self.__sigid1, self.__editor)
        self.__editor.disconnect_signal(self.__sigid2, self.__editor)
        self.__editor.disconnect_signal(self.__sigid3, self.__editor)
        self.__editor.disconnect_signal(self.__sigid4, self.__editor)
        self.__editor.unregister_object(self)
        del self
        return False

    def __set_properties(self):
        from gtk import DEST_DEFAULT_ALL
        targets = [("text/uri-list", 0, 80)]
        from gtk.gdk import ACTION_COPY
        self.__view.set_pixels_above_lines(2)
        self.__view.set_pixels_below_lines(2)
        self.__view.set_pixels_inside_wrap(2)
        self.__view.drag_dest_set(DEST_DEFAULT_ALL, targets, ACTION_COPY)
        self.__view.drag_dest_add_text_targets()
        self.__view.set_property("can-focus", True)
        self.__view.set_property("auto-indent", True)
        self.__view.set_property("highlight-current-line", True)
        self.__view.set_property("show-line-numbers", True)
        self.__view.set_property("indent-width", -1)
        from gtksourceview2 import SMART_HOME_END_BEFORE
        self.__view.set_property("smart-home-end", SMART_HOME_END_BEFORE)
        self.__update_view()
        self.__view.set_property("sensitive", True)
        return False

    def __update_view(self):
        language = self.__editor.language
        language = language if language else "plain text"
        from SCRIBES.TabWidthMetadata import get_value as tab_width
        self.__view.set_property("tab-width", tab_width(language))
        from SCRIBES.MarginPositionMetadata import get_value as margin_position
        self.__view.set_property("right-margin-position",
                                 margin_position(language))
        from SCRIBES.DisplayRightMarginMetadata import get_value as show_margin
        self.__view.set_property("show-right-margin", show_margin(language))
        from SCRIBES.UseTabsMetadata import get_value as use_tabs
        self.__view.set_property("insert-spaces-instead-of-tabs",
                                 (not use_tabs(language)))
        from SCRIBES.FontMetadata import get_value as font_name
        from pango import FontDescription
        font = FontDescription(font_name(language))
        self.__view.modify_font(font)
        from gtk import WRAP_WORD_CHAR, WRAP_NONE
        from SCRIBES.TextWrappingMetadata import get_value as wrap_mode_bool
        wrap_mode = self.__view.set_wrap_mode
        wrap_mode(WRAP_WORD_CHAR) if wrap_mode_bool(language) else wrap_mode(
            WRAP_NONE)
        self.__view.grab_focus()
        return False

    def __add_view_to_scroll(self):
        swin = self.__editor.gui.get_widget("ScrolledWindow")
        swin.add(self.__view)
        swin.show_all()
        self.__view.grab_focus()
        return False

    def __quit_cb(self, *args):
        self.__destroy()
        return False

    def __update_cb(self, *args):
        from gobject import idle_add
        idle_add(self.__update_view)
        return False
Example #15
0
class HotEditorWindow(gtk.Window):
    def __init__(self, filename=None, content=None, title=None, parent=None, autosave=False):
        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
        vbox = gtk.VBox()
        self.add(vbox)
        self.__ui_string = """
<ui>
  <menubar name='Menubar'>
    <menu action='FileMenu'>
      <menuitem action='Save'/>
      <menuitem action='SaveAs'/>
      <separator/>
      <menuitem action='ReadOnly'/>
      <separator/>
      <menuitem action='Revert'/>
      <separator/>
      <menuitem action='Close'/>
    </menu>
    <menu action='EditMenu'>
      <menuitem action='Undo'/>
      <menuitem action='Redo'/>
      <separator/>
      <menuitem action='Find'/>
      <menuitem action='GotoLine'/>
    </menu>
    <menu action='ToolsMenu'>
      <menuitem action='About'/>
    </menu>
  </menubar>
</ui>
"""
        self.__create_ui()
        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)

        self.__filename = os.path.abspath(filename)
        self.__autosave = autosave
        self.__modified = False
        self.__last_len = 0
         
        self.__save_text_id = 0

        self.gtksourceview_mode = gtksourceview_avail

        if gtksourceview_avail:
            self.input = SourceBuffer()
            self.input_view = SourceView(self.input)
            if gtksourceview2_avail:
                self.input.connect('notify::can-undo', lambda *args: self.__sync_undoredo())
                self.input.connect('notify::can-redo', lambda *args: self.__sync_undoredo())
            else:
                self.input.connect('can-undo', lambda *args: self.__sync_undoredo())
                self.input.connect('can-redo', lambda *args: self.__sync_undoredo())
        else:
            self.input = gtk.TextBuffer()
            self.input_view = gtk.TextView(self.input)
        self.input_view.set_wrap_mode(gtk.WRAP_WORD)
        self.input_view.connect("key-press-event", self.__handle_key_press_event)
        
        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)        
        scroll.add(self.input_view)
        
        vbox.pack_start(scroll, True, True)

        if filename and os.path.isfile(self.__filename):
            _logger.debug("reading %s", self.__filename)
            f = open_text_file(self.__filename, 'r')
            self.__original_text = f.read()
        else:
            self.__original_text = content
            
        if self.__original_text:
            if gtksourceview_avail:
                self.input.begin_not_undoable_action()
            self.input.set_property('text', self.__original_text)
            self.__last_len = self.input.get_char_count()             
            if gtksourceview_avail:
                self.input.end_not_undoable_action()            
        
        self.input.move_mark_by_name('insert', self.input.get_start_iter())
        self.input.move_mark_by_name('selection_bound', self.input.get_start_iter())
        
        self.input.connect('mark-set', self.__on_mark_set)

        self.__searcharea = InlineSearchArea(self.input_view)
        self.__searcharea.connect('close', self.__on_search_close)
        self.__searcharea.show_all()
        self.__searcharea.hide()
        self.__searcharea.set_no_show_all(True)
        vbox.pack_start(self.__searcharea, expand=False)

        self.__status_hbox = gtk.HBox()
        self.__statusbar = gtk.Statusbar()
        self.__status_hbox.pack_start(self.__statusbar, expand=True)
        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
        self.__pos_status = gtk.Statusbar()
        self.__pos_status.set_size_request(160, 10) # Taken from GEdit
        self.__pos_context = self.__pos_status.get_context_id("HotEditor")
        self.__status_hbox.pack_start(self.__pos_status, expand=False)
        vbox.pack_start(self.__status_hbox, expand=False)
        self.__sync_undoredo()
        self.__sync_modified_sensitivity()

        self.input.connect("changed", self.__handle_text_changed)

        self.connect("delete-event", self.__handle_delete_event)
        self.__sync_title()
        if parent:
            self.set_transient_for(parent)
        self.set_size_request(800, 600)
        
    def __on_search_close(self, sa):
        self.__searcharea.hide()
        
    def set_read_only(self, readonly):
        readonly_toggle = self.__actiongroup.get_action('ReadOnly')
        readonly_toggle.set_active(readonly)
        
    def set_code_mode(self, codemode):
        if not self.gtksourceview_mode:
            return
        # Non-code is the default
        if not codemode:
            return
        self.input_view.modify_font(pango.FontDescription("monospace"))
        fs = Filesystem.getInstance()
        try:
            mimetype = fs.get_file_sync(self.__filename).mimetype
        except FileStatError as e:
            mimetype = None
        target_lang = None        
        if gtksourceview2_avail:
            import gtksourceview2
            langman = gtksourceview2.language_manager_get_default() 
            for language_id in langman.get_language_ids():
                language = langman.get_language(language_id)
                for langmime in language.get_mime_types():
                    if mimetype == langmime:
                        target_lang = language
                        break
                if target_lang:
                    break
            self.input.set_highlight_syntax(True)
        else:
            import gtksourceview
            target_lang = gtksourceview.SourceLanguagesManager().get_language_from_mime_type(mimetype)
            self.input.set_highlight(True)
        if target_lang:
            self.input.set_language(target_lang)

    def goto_line(self, lineno):
        iter = self.input.get_iter_at_line(lineno)
        self.input.place_cursor(iter)
        
    def __sync_title(self):
        if self.__filename:
            (dn, bn) = os.path.split(self.__filename)
            self.set_title('%s (%s)' % (bn,dn))
        else:
            self.set_title('Untitled')          

    def __show_msg(self, text):
        id = self.__statusbar.push(self.__statusbar_ctx, text)
        gobject.timeout_add(3000, lambda: self.__statusbar.remove(self.__statusbar_ctx, id))        

    def __do_save(self, status):
        if self.__save_text_id > 0:
            gobject.source_remove(self.__save_text_id)
        if not self.__modified:
            self.__show_msg(_("Already saved"))
            return            
        self.__idle_save_text(status)

    @log_except(_logger)
    def __idle_save_text(self, status):
        self.__save_text_id = 0
        _logger.debug("autosaving to %s", self.__filename)
        dn,bn = os.path.split(self.__filename)
        try:
            perms = os.stat(self.__filename).st_mode
        except:
            perms = None
        (tempfd, temppath) = tempfile.mkstemp('.tmp', self.__filename, dn)
        os.close(tempfd)
        f = open_text_file(temppath, 'w')
        text = self.input.get_property("text")
        utext = str(text)
        f.write(utext)
        f.flush()
        os.fsync(tempfd)
        f.close()
        if perms is not None:
            os.chmod(temppath, perms)
        atomic_rename(temppath, self.__filename)
        self.__show_msg(status + _("...done"))
        self.__modified = False
        self.__sync_modified_sensitivity()
        _logger.debug("autosave complete")
        return False

    def __handle_key_press_event(self, input_view, event):
        # <Control>Return is the most natural keybinding for save-and-close, but support
        # <Control>w for compat. This doesn't replicate all the complicated multiple-groups
        # handling that would goes on inside GTK+, but that's OK for a compatibility crutch
        if event.state & gtk.gdk.CONTROL_MASK != 0 and event.keyval in (gtk.keysyms.w, gtk.keysyms.W):
            self.__handle_close()
            return True

        if event.keyval == gtk.keysyms.Escape:
            self.__handle_close()
            return True

        return False
    
    def __on_mark_set(self, buf, iter, mark):
        cursor = buf.get_insert()
        if cursor != mark:
            return
        self.__pos_status.pop(self.__pos_context)
        ln = iter.get_line()
        col = iter.get_line_offset()        
        self.__pos_status.push(self.__pos_context, _('Ln %d, Col %d') % (ln, col))
    
    def __handle_text_changed(self, text):
        _logger.debug("handling text changed")
        self.__modified = True
        self.__sync_modified_sensitivity()
        if not (self.__filename and self.__autosave):
            return
        charcount = text.get_char_count()
        # Don't autosave on deletions
        if charcount < self.__last_len:
            return
        self.__last_len = charcount
        if self.__save_text_id != 0:
            gobject.source_remove(self.__save_text_id)
        self.__save_text_id = gobject.timeout_add(15000, self.__idle_save_text, _("Autosaving"))

    @log_except(_logger)
    def __revert_cb(self, action):
        self.__handle_revert()

    def __handle_revert(self):
        self.input.set_property('text', self.__original_text)
        
    @log_except(_logger)        
    def __save_cb(self, action):
        self.__do_save(_("Saving..."))
        
    @log_except(_logger)        
    def __save_as_cb(self, action):
        chooser = gtk.FileChooserDialog(_("Save As..."), self, gtk.FILE_CHOOSER_ACTION_SAVE,
                                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                         gtk.STOCK_SAVE,   gtk.RESPONSE_OK))
        chooser.set_default_response(gtk.RESPONSE_OK)
        response = chooser.run()
        filename = None
        if response == gtk.RESPONSE_OK:
            filename = chooser.get_filename()
        self.__filename = filename
        chooser.destroy()

    def __handle_delete_event(self, w, e):
        return self.__handle_close()

    @log_except(_logger)
    def __close_cb(self, action):
        self.__handle_close()
        
    def __sync_modified_sensitivity(self):
        self.__actiongroup.get_action('Save').set_sensitive(self.__modified)

    @log_except(_logger)
    def __handle_close(self):
        _logger.debug("got close")
        if not self.__modified:
            self.destroy()
        elif self.__filename and self.__autosave:
            self.__save_cb(None)
            self.destroy()   
        else:
            dialog = gtk.MessageDialog(parent=self, buttons=gtk.BUTTONS_NONE,
                                       type=gtk.MESSAGE_QUESTION,
                                       message_format=_("Save changes before closing?"))
            dialog.add_button(_('Close without saving'), gtk.RESPONSE_REJECT)
            dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
            dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_APPLY)            
            dialog.set_default_response(gtk.RESPONSE_CANCEL)
            resp = dialog.run()
            dialog.destroy()
            if resp == gtk.RESPONSE_REJECT:
                self.destroy()
            elif resp == gtk.RESPONSE_CANCEL:
                pass
            elif resp == gtk.RESPONSE_APPLY:
                self.__save_cb(None)
                self.destroy()
        return True                     

    @log_except(_logger)
    def __undo_cb(self, action):
        self.input.undo()

    @log_except(_logger)
    def __redo_cb(self, action):
        self.input.redo()

    def __sync_undoredo(self):
        self.__actiongroup.get_action('Redo').set_sensitive(gtksourceview_avail and self.input.can_redo())
        self.__actiongroup.get_action('Undo').set_sensitive(gtksourceview_avail and self.input.can_undo())
        
    @log_except(_logger)        
    def __search_cb(self, a):
        self.__searcharea.show()
        self.__searcharea.focus()

    @log_except(_logger)        
    def __goto_line_cb(self, a):
        dlg = GotoLineDialog(self)
        line_num = dlg.run_get_line()
        dlg.destroy()        
        if line_num is None:
            return
        iter = self.input.get_iter_at_line(line_num)
        self.input.place_cursor(iter)
        self.input_view.scroll_mark_onscreen(self.input.get_mark('insert')) 
        
    @log_except(_logger)
    def __toggle_read_only_cb(self, a):
        active = a.get_active()
        self.input_view.set_editable(not active)

    def __create_ui(self):
        self.__actiongroup = ag = gtk.ActionGroup('WindowActions')
        actions = [
            ('FileMenu', None, _('_File')),
            ('Save', gtk.STOCK_SAVE, _('_Save'), '<control>s', _('Save to current file'), self.__save_cb),
            ('SaveAs', gtk.STOCK_SAVE, _('Save _As'), '<control><shift>s', _('Save to a new file'), self.__save_as_cb),             
            ('Revert', None, '_Revert', None, _('Revert to saved text'), self.__revert_cb),
            ('Close', gtk.STOCK_CLOSE, _('_Close'), '<control>Return', _('Save and close'), self.__close_cb),
            ('EditMenu', None, '_Edit'),
            ('Undo', gtk.STOCK_UNDO, _('_Undo'), '<control>z', _('Undo previous action'), self.__undo_cb),
            ('Redo', gtk.STOCK_REDO, _('_Redo'), '<control><shift>Z', _('Redo action'), self.__redo_cb),
            ('Find', gtk.STOCK_FIND, _('_Find'), '<control>f', _('Find text'), self.__search_cb),
            ('GotoLine', gtk.STOCK_JUMP_TO, _('_Go to Line'), '<control>l', _('Jump to line number'), self.__goto_line_cb),
            ('ToolsMenu', None, _('_Tools')),                    
            ('About', gtk.STOCK_ABOUT, _('_About'), None, _('About Hotwire'), self.__help_about_cb),            
            ]
        toggle_actions = [
            ('ReadOnly', None, _('Read _Only'), None, _('Toggle read-only mode'), self.__toggle_read_only_cb),                          
        ]
        ag.add_actions(actions)
        ag.add_toggle_actions(toggle_actions)
        self._ui = gtk.UIManager()
        self._ui.insert_action_group(ag, 0)
        self._ui.add_ui_from_string(self.__ui_string)
        self.add_accel_group(self._ui.get_accel_group())

    def __help_about_cb(self, action):
        dialog = HotwireAboutDialog()
        dialog.run()
        dialog.destroy()
 def _on_document_added(self, model, idx, content):
     
     view = View()
     view.show()
 
     lang = self._language_manager.get_language("gobject-creator")
     buf = Buffer(language=lang)
     buf.set_highlight_syntax(True)
     view.set_buffer(buf)
     
     view.set_auto_indent(True)
     view.set_show_line_numbers(Settings.get().show_line_numbers)
     
     font_desc = pango.FontDescription(Settings.get().font_name)
     view.modify_font(font_desc)
     
     doc_container = gtk.ScrolledWindow()
     doc_container.show()
     doc_container.add(view)
         
     hbox = gtk.HBox()
     hbox.show()
         
     label = gtk.Label("")
     label.show()
     hbox.pack_start(label)
         
     close_button = gtk.Button()
     image = gtk.Image()
     image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
     close_button.set_image(image)
     close_button.set_relief(gtk.RELIEF_NONE)
     close_button.show()
     hbox.pack_start(close_button)
     
     self._notebook.insert_page(doc_container,
                                hbox,
                                idx
                                )
     self._notebook.set_current_page(idx)
     
     view.connect("button_press_event",
                  self._on_button_pressed
                  )
         
     close_button.connect(
         "clicked", 
         self._on_close_button_clicked
     )
   
     buf = view.get_buffer()
     buf.connect(
         "changed",
         self._on_buffer_changed
         )
     
     self._set_document_title(idx)
     
     buf.set_text(content)
Example #17
0
    def __init__(self, filename=None, content=None, title=None, parent=None, autosave=False):
        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
        vbox = gtk.VBox()
        self.add(vbox)
        self.__ui_string = """
<ui>
  <menubar name='Menubar'>
    <menu action='FileMenu'>
      <menuitem action='Save'/>
      <menuitem action='SaveAs'/>
      <separator/>
      <menuitem action='ReadOnly'/>
      <separator/>
      <menuitem action='Revert'/>
      <separator/>
      <menuitem action='Close'/>
    </menu>
    <menu action='EditMenu'>
      <menuitem action='Undo'/>
      <menuitem action='Redo'/>
      <separator/>
      <menuitem action='Find'/>
      <menuitem action='GotoLine'/>
    </menu>
    <menu action='ToolsMenu'>
      <menuitem action='About'/>
    </menu>
  </menubar>
</ui>
"""
        self.__create_ui()
        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)

        self.__filename = os.path.abspath(filename)
        self.__autosave = autosave
        self.__modified = False
        self.__last_len = 0
         
        self.__save_text_id = 0

        self.gtksourceview_mode = gtksourceview_avail

        if gtksourceview_avail:
            self.input = SourceBuffer()
            self.input_view = SourceView(self.input)
            if gtksourceview2_avail:
                self.input.connect('notify::can-undo', lambda *args: self.__sync_undoredo())
                self.input.connect('notify::can-redo', lambda *args: self.__sync_undoredo())
            else:
                self.input.connect('can-undo', lambda *args: self.__sync_undoredo())
                self.input.connect('can-redo', lambda *args: self.__sync_undoredo())
        else:
            self.input = gtk.TextBuffer()
            self.input_view = gtk.TextView(self.input)
        self.input_view.set_wrap_mode(gtk.WRAP_WORD)
        self.input_view.connect("key-press-event", self.__handle_key_press_event)
        
        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)        
        scroll.add(self.input_view)
        
        vbox.pack_start(scroll, True, True)

        if filename and os.path.isfile(self.__filename):
            _logger.debug("reading %s", self.__filename)
            f = open_text_file(self.__filename, 'r')
            self.__original_text = f.read()
        else:
            self.__original_text = content
            
        if self.__original_text:
            if gtksourceview_avail:
                self.input.begin_not_undoable_action()
            self.input.set_property('text', self.__original_text)
            self.__last_len = self.input.get_char_count()             
            if gtksourceview_avail:
                self.input.end_not_undoable_action()            
        
        self.input.move_mark_by_name('insert', self.input.get_start_iter())
        self.input.move_mark_by_name('selection_bound', self.input.get_start_iter())
        
        self.input.connect('mark-set', self.__on_mark_set)

        self.__searcharea = InlineSearchArea(self.input_view)
        self.__searcharea.connect('close', self.__on_search_close)
        self.__searcharea.show_all()
        self.__searcharea.hide()
        self.__searcharea.set_no_show_all(True)
        vbox.pack_start(self.__searcharea, expand=False)

        self.__status_hbox = gtk.HBox()
        self.__statusbar = gtk.Statusbar()
        self.__status_hbox.pack_start(self.__statusbar, expand=True)
        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
        self.__pos_status = gtk.Statusbar()
        self.__pos_status.set_size_request(160, 10) # Taken from GEdit
        self.__pos_context = self.__pos_status.get_context_id("HotEditor")
        self.__status_hbox.pack_start(self.__pos_status, expand=False)
        vbox.pack_start(self.__status_hbox, expand=False)
        self.__sync_undoredo()
        self.__sync_modified_sensitivity()

        self.input.connect("changed", self.__handle_text_changed)

        self.connect("delete-event", self.__handle_delete_event)
        self.__sync_title()
        if parent:
            self.set_transient_for(parent)
        self.set_size_request(800, 600)
Example #18
0
class HotEditorWindow(gtk.Window):
    def __init__(self,
                 filename=None,
                 content=None,
                 title=None,
                 parent=None,
                 autosave=False):
        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
        vbox = gtk.VBox()
        self.add(vbox)
        self.__ui_string = """
<ui>
  <menubar name='Menubar'>
    <menu action='FileMenu'>
      <menuitem action='Save'/>
      <menuitem action='SaveAs'/>
      <separator/>
      <menuitem action='ReadOnly'/>
      <separator/>
      <menuitem action='Revert'/>
      <separator/>
      <menuitem action='Close'/>
    </menu>
    <menu action='EditMenu'>
      <menuitem action='Undo'/>
      <menuitem action='Redo'/>
      <separator/>
      <menuitem action='Find'/>
      <menuitem action='GotoLine'/>
    </menu>
    <menu action='ToolsMenu'>
      <menuitem action='About'/>
    </menu>
  </menubar>
</ui>
"""
        self.__create_ui()
        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)

        self.__filename = os.path.abspath(filename)
        self.__autosave = autosave
        self.__modified = False
        self.__last_len = 0

        self.__save_text_id = 0

        self.gtksourceview_mode = gtksourceview_avail

        if gtksourceview_avail:
            self.input = SourceBuffer()
            self.input_view = SourceView(self.input)
            if gtksourceview2_avail:
                self.input.connect('notify::can-undo',
                                   lambda *args: self.__sync_undoredo())
                self.input.connect('notify::can-redo',
                                   lambda *args: self.__sync_undoredo())
            else:
                self.input.connect('can-undo',
                                   lambda *args: self.__sync_undoredo())
                self.input.connect('can-redo',
                                   lambda *args: self.__sync_undoredo())
        else:
            self.input = gtk.TextBuffer()
            self.input_view = gtk.TextView(self.input)
        self.input_view.set_wrap_mode(gtk.WRAP_WORD)
        self.input_view.connect("key-press-event",
                                self.__handle_key_press_event)

        scroll = gtk.ScrolledWindow()
        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
        scroll.add(self.input_view)

        vbox.pack_start(scroll, True, True)

        if filename and os.path.isfile(self.__filename):
            _logger.debug("reading %s", self.__filename)
            f = open_text_file(self.__filename, 'r')
            self.__original_text = f.read()
        else:
            self.__original_text = content

        if self.__original_text:
            if gtksourceview_avail:
                self.input.begin_not_undoable_action()
            self.input.set_property('text', self.__original_text)
            self.__last_len = self.input.get_char_count()
            if gtksourceview_avail:
                self.input.end_not_undoable_action()

        self.input.move_mark_by_name('insert', self.input.get_start_iter())
        self.input.move_mark_by_name('selection_bound',
                                     self.input.get_start_iter())

        self.input.connect('mark-set', self.__on_mark_set)

        self.__searcharea = InlineSearchArea(self.input_view)
        self.__searcharea.connect('close', self.__on_search_close)
        self.__searcharea.show_all()
        self.__searcharea.hide()
        self.__searcharea.set_no_show_all(True)
        vbox.pack_start(self.__searcharea, expand=False)

        self.__status_hbox = gtk.HBox()
        self.__statusbar = gtk.Statusbar()
        self.__status_hbox.pack_start(self.__statusbar, expand=True)
        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
        self.__pos_status = gtk.Statusbar()
        self.__pos_status.set_size_request(160, 10)  # Taken from GEdit
        self.__pos_context = self.__pos_status.get_context_id("HotEditor")
        self.__status_hbox.pack_start(self.__pos_status, expand=False)
        vbox.pack_start(self.__status_hbox, expand=False)
        self.__sync_undoredo()
        self.__sync_modified_sensitivity()

        self.input.connect("changed", self.__handle_text_changed)

        self.connect("delete-event", self.__handle_delete_event)
        self.__sync_title()
        if parent:
            self.set_transient_for(parent)
        self.set_size_request(800, 600)

    def __on_search_close(self, sa):
        self.__searcharea.hide()

    def set_read_only(self, readonly):
        readonly_toggle = self.__actiongroup.get_action('ReadOnly')
        readonly_toggle.set_active(readonly)

    def set_code_mode(self, codemode):
        if not self.gtksourceview_mode:
            return
        # Non-code is the default
        if not codemode:
            return
        self.input_view.modify_font(pango.FontDescription("monospace"))
        fs = Filesystem.getInstance()
        try:
            mimetype = fs.get_file_sync(self.__filename).mimetype
        except FileStatError as e:
            mimetype = None
        target_lang = None
        if gtksourceview2_avail:
            import gtksourceview2
            langman = gtksourceview2.language_manager_get_default()
            for language_id in langman.get_language_ids():
                language = langman.get_language(language_id)
                for langmime in language.get_mime_types():
                    if mimetype == langmime:
                        target_lang = language
                        break
                if target_lang:
                    break
            self.input.set_highlight_syntax(True)
        else:
            import gtksourceview
            target_lang = gtksourceview.SourceLanguagesManager(
            ).get_language_from_mime_type(mimetype)
            self.input.set_highlight(True)
        if target_lang:
            self.input.set_language(target_lang)

    def goto_line(self, lineno):
        iter = self.input.get_iter_at_line(lineno)
        self.input.place_cursor(iter)

    def __sync_title(self):
        if self.__filename:
            (dn, bn) = os.path.split(self.__filename)
            self.set_title('%s (%s)' % (bn, dn))
        else:
            self.set_title('Untitled')

    def __show_msg(self, text):
        id = self.__statusbar.push(self.__statusbar_ctx, text)
        gobject.timeout_add(
            3000, lambda: self.__statusbar.remove(self.__statusbar_ctx, id))

    def __do_save(self, status):
        if self.__save_text_id > 0:
            gobject.source_remove(self.__save_text_id)
        if not self.__modified:
            self.__show_msg(_("Already saved"))
            return
        self.__idle_save_text(status)

    @log_except(_logger)
    def __idle_save_text(self, status):
        self.__save_text_id = 0
        _logger.debug("autosaving to %s", self.__filename)
        dn, bn = os.path.split(self.__filename)
        try:
            perms = os.stat(self.__filename).st_mode
        except:
            perms = None
        (tempfd, temppath) = tempfile.mkstemp('.tmp', self.__filename, dn)
        os.close(tempfd)
        f = open_text_file(temppath, 'w')
        text = self.input.get_property("text")
        utext = str(text)
        f.write(utext)
        f.flush()
        os.fsync(tempfd)
        f.close()
        if perms is not None:
            os.chmod(temppath, perms)
        atomic_rename(temppath, self.__filename)
        self.__show_msg(status + _("...done"))
        self.__modified = False
        self.__sync_modified_sensitivity()
        _logger.debug("autosave complete")
        return False

    def __handle_key_press_event(self, input_view, event):
        # <Control>Return is the most natural keybinding for save-and-close, but support
        # <Control>w for compat. This doesn't replicate all the complicated multiple-groups
        # handling that would goes on inside GTK+, but that's OK for a compatibility crutch
        if event.state & gtk.gdk.CONTROL_MASK != 0 and event.keyval in (
                gtk.keysyms.w, gtk.keysyms.W):
            self.__handle_close()
            return True

        if event.keyval == gtk.keysyms.Escape:
            self.__handle_close()
            return True

        return False

    def __on_mark_set(self, buf, iter, mark):
        cursor = buf.get_insert()
        if cursor != mark:
            return
        self.__pos_status.pop(self.__pos_context)
        ln = iter.get_line()
        col = iter.get_line_offset()
        self.__pos_status.push(self.__pos_context,
                               _('Ln %d, Col %d') % (ln, col))

    def __handle_text_changed(self, text):
        _logger.debug("handling text changed")
        self.__modified = True
        self.__sync_modified_sensitivity()
        if not (self.__filename and self.__autosave):
            return
        charcount = text.get_char_count()
        # Don't autosave on deletions
        if charcount < self.__last_len:
            return
        self.__last_len = charcount
        if self.__save_text_id != 0:
            gobject.source_remove(self.__save_text_id)
        self.__save_text_id = gobject.timeout_add(15000, self.__idle_save_text,
                                                  _("Autosaving"))

    @log_except(_logger)
    def __revert_cb(self, action):
        self.__handle_revert()

    def __handle_revert(self):
        self.input.set_property('text', self.__original_text)

    @log_except(_logger)
    def __save_cb(self, action):
        self.__do_save(_("Saving..."))

    @log_except(_logger)
    def __save_as_cb(self, action):
        chooser = gtk.FileChooserDialog(_("Save As..."), self,
                                        gtk.FILE_CHOOSER_ACTION_SAVE,
                                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                         gtk.STOCK_SAVE, gtk.RESPONSE_OK))
        chooser.set_default_response(gtk.RESPONSE_OK)
        response = chooser.run()
        filename = None
        if response == gtk.RESPONSE_OK:
            filename = chooser.get_filename()
        self.__filename = filename
        chooser.destroy()

    def __handle_delete_event(self, w, e):
        return self.__handle_close()

    @log_except(_logger)
    def __close_cb(self, action):
        self.__handle_close()

    def __sync_modified_sensitivity(self):
        self.__actiongroup.get_action('Save').set_sensitive(self.__modified)

    @log_except(_logger)
    def __handle_close(self):
        _logger.debug("got close")
        if not self.__modified:
            self.destroy()
        elif self.__filename and self.__autosave:
            self.__save_cb(None)
            self.destroy()
        else:
            dialog = gtk.MessageDialog(
                parent=self,
                buttons=gtk.BUTTONS_NONE,
                type=gtk.MESSAGE_QUESTION,
                message_format=_("Save changes before closing?"))
            dialog.add_button(_('Close without saving'), gtk.RESPONSE_REJECT)
            dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
            dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_APPLY)
            dialog.set_default_response(gtk.RESPONSE_CANCEL)
            resp = dialog.run()
            dialog.destroy()
            if resp == gtk.RESPONSE_REJECT:
                self.destroy()
            elif resp == gtk.RESPONSE_CANCEL:
                pass
            elif resp == gtk.RESPONSE_APPLY:
                self.__save_cb(None)
                self.destroy()
        return True

    @log_except(_logger)
    def __undo_cb(self, action):
        self.input.undo()

    @log_except(_logger)
    def __redo_cb(self, action):
        self.input.redo()

    def __sync_undoredo(self):
        self.__actiongroup.get_action('Redo').set_sensitive(
            gtksourceview_avail and self.input.can_redo())
        self.__actiongroup.get_action('Undo').set_sensitive(
            gtksourceview_avail and self.input.can_undo())

    @log_except(_logger)
    def __search_cb(self, a):
        self.__searcharea.show()
        self.__searcharea.focus()

    @log_except(_logger)
    def __goto_line_cb(self, a):
        dlg = GotoLineDialog(self)
        line_num = dlg.run_get_line()
        dlg.destroy()
        if line_num is None:
            return
        iter = self.input.get_iter_at_line(line_num)
        self.input.place_cursor(iter)
        self.input_view.scroll_mark_onscreen(self.input.get_mark('insert'))

    @log_except(_logger)
    def __toggle_read_only_cb(self, a):
        active = a.get_active()
        self.input_view.set_editable(not active)

    def __create_ui(self):
        self.__actiongroup = ag = gtk.ActionGroup('WindowActions')
        actions = [
            ('FileMenu', None, _('_File')),
            ('Save', gtk.STOCK_SAVE, _('_Save'), '<control>s',
             _('Save to current file'), self.__save_cb),
            ('SaveAs', gtk.STOCK_SAVE, _('Save _As'), '<control><shift>s',
             _('Save to a new file'), self.__save_as_cb),
            ('Revert', None, '_Revert', None, _('Revert to saved text'),
             self.__revert_cb),
            ('Close', gtk.STOCK_CLOSE, _('_Close'), '<control>Return',
             _('Save and close'), self.__close_cb),
            ('EditMenu', None, '_Edit'),
            ('Undo', gtk.STOCK_UNDO, _('_Undo'), '<control>z',
             _('Undo previous action'), self.__undo_cb),
            ('Redo', gtk.STOCK_REDO, _('_Redo'), '<control><shift>Z',
             _('Redo action'), self.__redo_cb),
            ('Find', gtk.STOCK_FIND, _('_Find'), '<control>f', _('Find text'),
             self.__search_cb),
            ('GotoLine', gtk.STOCK_JUMP_TO, _('_Go to Line'), '<control>l',
             _('Jump to line number'), self.__goto_line_cb),
            ('ToolsMenu', None, _('_Tools')),
            ('About', gtk.STOCK_ABOUT, _('_About'), None, _('About Hotwire'),
             self.__help_about_cb),
        ]
        toggle_actions = [
            ('ReadOnly', None, _('Read _Only'), None,
             _('Toggle read-only mode'), self.__toggle_read_only_cb),
        ]
        ag.add_actions(actions)
        ag.add_toggle_actions(toggle_actions)
        self._ui = gtk.UIManager()
        self._ui.insert_action_group(ag, 0)
        self._ui.add_ui_from_string(self.__ui_string)
        self.add_accel_group(self._ui.get_accel_group())

    def __help_about_cb(self, action):
        dialog = HotwireAboutDialog()
        dialog.run()
        dialog.destroy()