r6836 - in bigboard/trunk: . bigboard bigboard/libbig



Author: walters
Date: 2007-10-26 14:06:22 -0500 (Fri, 26 Oct 2007)
New Revision: 6836

Added:
   bigboard/trunk/bigboard/editor.py
   bigboard/trunk/bigboard/pyshell.py
Modified:
   bigboard/trunk/bigboard/big_widgets.py
   bigboard/trunk/bigboard/libbig/http.py
   bigboard/trunk/configure.ac
   bigboard/trunk/main.py
Log:
Rebase current shell on Hotwire SVN version.



Modified: bigboard/trunk/bigboard/big_widgets.py
===================================================================
--- bigboard/trunk/bigboard/big_widgets.py	2007-10-26 18:16:55 UTC (rev 6835)
+++ bigboard/trunk/bigboard/big_widgets.py	2007-10-26 19:06:22 UTC (rev 6836)
@@ -404,77 +404,4 @@
         if not gconf.client_get_default().get_bool(self.__strut_key):
             kwargs['remove'] = True
         super(Sidebar, self).do_set_wm_strut(**kwargs)
-            
-class CommandShell(gtk.Window):
-    """Every application needs a development shell."""
-    def __init__(self, locals={}):
-        gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
-        
-        self._locals = locals
-        
-        self._history_path = libbig.get_bigboard_config_file('cmdshell_history')
-        self._save_text_id = 0        
-        
-        box = gtk.VBox()
-        paned = gtk.VPaned()
-        self.output = gtk.TextBuffer()
-        self.output_view = gtk.TextView(self.output)
-        self.output_view.set_wrap_mode(gtk.WRAP_WORD)
-        self.output_view.set_property("editable", False)
-        scroll = gtk.ScrolledWindow()
-        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
-        scroll.add(self.output_view)
-        paned.pack1(scroll, True, True)
 
-        self.input = gtk.TextBuffer()
-        self.input_view = gtk.TextView(self.input)
-        self.input_view.set_wrap_mode(gtk.WRAP_WORD)        
-        self.input.connect("changed", self._handle_text_changed)
-        scroll = gtk.ScrolledWindow()
-        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)        
-        scroll.add(self.input_view)        
-        paned.pack2(scroll, True, True)
-        
-        box.pack_start(paned, True, True)
-        
-        eval_button = gtk.Button("Eval")
-        eval_button.connect("clicked", self.do_eval)
-        box.pack_start(eval_button, False)
-        self.add(box)
-
-        try:
-            history = file(self._history_path).read()
-            self.input.set_property("text", history)
-        except IOError, e:
-            pass
-
-        self.set_size_request(400, 600)
-        self.set_focus(self.input_view)
-    
-    def _idle_save_text(self):
-        history_file = file(self._history_path, 'w+')
-        text = self.input.get_property("text")
-        history_file.write(text)
-        history_file.close()
-        self._save_text_id = 0
-        return False
-    
-    def _handle_text_changed(self, text):
-        if self._save_text_id == 0:
-            self._save_text_id = gobject.timeout_add(3000, self._idle_save_text)
-    
-    def do_eval(self, entry):
-        try:
-            output_stream = StringIO.StringIO()
-            text = self.input.get_property("text")
-            code_obj = compile(text, '<input>', 'exec')
-            locals = {}
-            for k, v in self._locals.items():
-                locals[k] = v
-            locals['output'] = output_stream
-            exec code_obj in locals
-            logging.debug("execution complete with %d output characters" % (len(output_stream.getvalue())),)
-            self.output.set_property("text", output_stream.getvalue())
-        except:
-            logging.debug("caught exception executing")
-            self.output.set_property("text", traceback.format_exc())

Added: bigboard/trunk/bigboard/editor.py
===================================================================
--- bigboard/trunk/bigboard/editor.py	2007-10-26 18:16:55 UTC (rev 6835)
+++ bigboard/trunk/bigboard/editor.py	2007-10-26 19:06:22 UTC (rev 6836)
@@ -0,0 +1,178 @@
+import os, sys, logging, StringIO, traceback
+
+import cairo, gtk, gobject, pango
+
+_logger = logging.getLogger("hotwire.Editor")
+
+try:
+    import gtksourceview
+    gtksourceview_avail = True
+    _logger.debug("gtksourceview available")
+except ImportError, e:
+    gtksourceview_avail = False
+    _logger.debug("gtksourceview not available")
+
+class HotEditorWindow(gtk.Window):
+    def __init__(self, filename=None, content=None, title=None):
+        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='Revert'/>
+      <menuitem action='Close'/>
+    </menu>
+    <menu action='EditMenu'>
+      <menuitem action='Undo'/>
+      <menuitem action='Redo'/>
+    </menu>
+  </menubar>
+</ui>
+"""
+        self.__create_ui()
+        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)
+
+        self.__filename = filename
+        self.__modified = False
+         
+        self.__save_text_id = 0
+
+        self.gtksourceview_mode = gtksourceview_avail
+
+        if gtksourceview_avail:
+            self.input = gtksourceview.SourceBuffer()
+            self.input_view = gtksourceview.SourceView(self.input)
+            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(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)
+            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.__statusbar = gtk.Statusbar()
+        self.__statusbar_ctx = self.__statusbar.get_context_id("HotEditor")
+        vbox.pack_start(self.__statusbar, expand=False)
+        self.__sync_undoredo()
+
+        # do this later to avoid autosaving initially
+        if filename:
+            self.input.connect("changed", self.__handle_text_changed)
+
+        self.connect("delete-event", lambda w, e: False)
+        self.set_title(title or (filename and self.__filename) or 'Untitled Editor')
+        self.set_size_request(640, 480)
+
+    def __idle_save_text(self):
+        self.__save_text_id = 0
+        _logger.debug("autosaving to %s", self.__filename)
+        f = open(self.__filename, 'w')
+        text = self.input.get_property("text")
+        f.write(text)
+        f.close()
+        autosaved_id = self.__statusbar.push(self.__statusbar_ctx, 'Autosaving...done')
+        gobject.timeout_add(3000, lambda: self.__statusbar.remove(self.__statusbar_ctx, autosaved_id))
+        _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:
+            if self.__modified:
+                dialog = gtk.MessageDialog(parent=self, buttons=gtk.BUTTONS_NONE,
+                                           type=gtk.MESSAGE_QUESTION,
+                                           message_format="Revert changes and quit?")
+                dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL,
+                                   "Revert", gtk.RESPONSE_OK)
+                dialog.set_default_response(gtk.RESPONSE_OK)
+                if dialog.run() == gtk.RESPONSE_OK:
+                    self.__handle_revert()
+                    self.__handle_close()
+            else:
+                self.__handle_close()
+                
+            return True
+
+        return False
+    
+    def __handle_text_changed(self, text):
+        self.__modified = True
+        if self.__save_text_id == 0:
+            self.__save_text_id = gobject.timeout_add(800, self.__idle_save_text)
+
+    def __revert_cb(self, action):
+        self.__handle_revert()
+
+    def __handle_revert(self):
+        self.input.set_property('text', self.__original_text)        
+
+    def __close_cb(self, action):
+        self.__handle_close()
+
+    def __handle_close(self):
+        _logger.debug("got close")
+        if self.__filename:
+            self.__idle_save_text()
+        self.destroy()
+
+    def __undo_cb(self, action):
+        self.input.undo()
+
+    def __redo_cb(self, action):
+        self.input.redo()
+
+    def __sync_undoredo(self):
+        if not gtksourceview_avail:
+            return
+        self.__actiongroup.get_action('Redo').set_sensitive(self.input.can_redo())
+        self.__actiongroup.get_action('Undo').set_sensitive(self.input.can_undo())
+
+    def __create_ui(self):
+        self.__actiongroup = ag = gtk.ActionGroup('WindowActions')
+        actions = [
+            ('FileMenu', None, '_File'),
+            ('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')]
+
+        if gtksourceview_avail:
+            actions.extend([
+            ('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),
+            ])
+        ag.add_actions(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())

Modified: bigboard/trunk/bigboard/libbig/http.py
===================================================================
--- bigboard/trunk/bigboard/libbig/http.py	2007-10-26 18:16:55 UTC (rev 6835)
+++ bigboard/trunk/bigboard/libbig/http.py	2007-10-26 19:06:22 UTC (rev 6836)
@@ -161,7 +161,11 @@
             headers['Cache-Control'] = 'no-store'
         (response, content) = h.request(url, **http_kwargs)
         if response.status == 200:
-            gobject.idle_add(lambda: self.__emit_results(url, kwargs['cb'], content, is_refetch=is_refetch))
+            resultfn = lambda: self.__emit_results(url, kwargs['cb'], content, is_refetch=is_refetch)
+            if is_refetch:
+                resultfn()
+            else:
+                gobject.idle_add(resultfn)
         elif 'response_errcb' in kwargs:
             gobject.idle_add(lambda: kwargs['response_errcb'](url, response, content))
         elif 'refetch' not in kwargs:

Added: bigboard/trunk/bigboard/pyshell.py
===================================================================
--- bigboard/trunk/bigboard/pyshell.py	2007-10-26 18:16:55 UTC (rev 6835)
+++ bigboard/trunk/bigboard/pyshell.py	2007-10-26 19:06:22 UTC (rev 6836)
@@ -0,0 +1,115 @@
+import os, sys, logging, StringIO, traceback
+
+import cairo, gtk, gobject, pango
+
+from bigboard.editor import HotEditorWindow
+
+_logger = logging.getLogger("hotwire.PyShell")
+
+class OutputWindow(gtk.Window):
+    def __init__(self, content):
+        super(OutputWindow, self).__init__(gtk.WINDOW_TOPLEVEL)
+        vbox = gtk.VBox()
+        self.add(vbox)
+        self.__ui_string = """
+<ui>
+  <menubar name='Menubar'>
+    <menu action='FileMenu'>
+      <menuitem action='Close'/>
+    </menu>
+  </menubar>
+</ui>
+"""
+        self.__create_ui()
+        vbox.pack_start(self._ui.get_widget('/Menubar'), expand=False)        
+        self.output = gtk.TextBuffer()
+        self.output_view = gtk.TextView(self.output)
+        self.output_view.set_wrap_mode(gtk.WRAP_WORD)
+        self.output_view.set_property("editable", False)
+        self.output.set_property('text', content)
+        scroll = gtk.ScrolledWindow()
+        scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
+        scroll.add(self.output_view)
+        vbox.pack_start(scroll, True, True)
+        self.set_size_request(640, 480)        
+        
+    def __create_ui(self):
+        self.__actiongroup = ag = gtk.ActionGroup('OutputWindowActions')
+        actions = [
+            ('FileMenu', None, 'File'),
+            ('Close', gtk.STOCK_CLOSE, '_Close', 'Return', 'Close window', self.__close_cb),
+            ]
+        ag.add_actions(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 __close_cb(self, action):
+        self.destroy()               
+        
+class CommandShell(HotEditorWindow):
+    DEFAULT_CONTENT = '''## Hotwire Python Pad
+## Global values:
+##   outln(value): (Function) Print a value and a newline to output stream
+##   hotwin: (Value) The global Hotwire window
+import os,sys,re
+import gtk, gobject
+
+outln('''
+    def __init__(self, locals={}, savepath=None):
+        super(CommandShell, self).__init__(content=self.DEFAULT_CONTENT, filename=savepath)
+        self._locals = locals
+        self.__ui_string = """
+<ui>
+  <menubar name='Menubar'>
+    <menu action='ToolsMenu'>
+      <menuitem action='Eval'/>
+    </menu>
+  </menubar>
+</ui>        
+"""    
+        actions = [
+            ('ToolsMenu', None, 'Tools'),
+            ('Eval', None, '_Eval', '<control>Return', 'Evaluate current input', self.__eval_cb),
+            ]
+        self.__actiongroup = ag = gtk.ActionGroup('ShellActions')        
+        ag.add_actions(actions)
+        self._ui.insert_action_group(ag, 0)
+        self._ui.add_ui_from_string(self.__ui_string)
+
+        if self.gtksourceview_mode:
+            import gtksourceview            
+            pylang = gtksourceview.SourceLanguagesManager().get_language_from_mime_type("text/x-python")
+            self.input.set_language(pylang)
+            self.input.set_highlight(True)
+            
+        self.input.move_mark_by_name("insert", self.input.get_end_iter())
+        self.input.move_mark_by_name("selection_bound", self.input.get_end_iter())        
+            
+        self.set_title('Hotwire Command Shell')
+
+    def __eval_cb(self, a):
+        try:
+            output_stream = StringIO.StringIO()
+            text = self.input.get_property("text")
+            code_obj = compile(text, '<input>', 'exec')
+            locals = {}
+            for k, v in self._locals.items():
+                locals[k] = v
+            locals['output'] = output_stream
+            locals['outln'] = lambda v: self.__outln(output_stream, v)
+            exec code_obj in locals
+            _logger.debug("execution complete with %d output characters" % (len(output_stream.getvalue())),)
+            output_str = output_stream.getvalue()
+            if output_str:
+                owin = OutputWindow(output_str)
+                owin.show_all()
+        except:
+            _logger.debug("caught exception executing", exc_info=True)
+            owin = OutputWindow(traceback.format_exc())
+            owin.show_all()
+            
+    def __outln(self, stream, v):
+        stream.write(str(v))
+        stream.write('\n')

Modified: bigboard/trunk/configure.ac
===================================================================
--- bigboard/trunk/configure.ac	2007-10-26 18:16:55 UTC (rev 6835)
+++ bigboard/trunk/configure.ac	2007-10-26 19:06:22 UTC (rev 6836)
@@ -1,4 +1,4 @@
-AC_INIT(bigboard, 0.5.23, feedback mugshot org)
+AC_INIT(bigboard, 0.5.24, feedback mugshot org)
 AC_CONFIG_SRCDIR(main.py)
 AC_CONFIG_MACRO_DIR([m4])
 

Modified: bigboard/trunk/main.py
===================================================================
--- bigboard/trunk/main.py	2007-10-26 18:16:55 UTC (rev 6835)
+++ bigboard/trunk/main.py	2007-10-26 19:06:22 UTC (rev 6836)
@@ -18,7 +18,7 @@
 
 import bigboard
 import bigboard.big_widgets
-from bigboard.big_widgets import Sidebar, CommandShell, CanvasHBox, CanvasVBox, ActionLink, Button
+from bigboard.big_widgets import Sidebar, CanvasHBox, CanvasVBox, ActionLink, Button
 from bigboard.stock import Stock
 import bigboard.libbig
 try:
@@ -657,8 +657,10 @@
     def Shell(self):
         if self.__shell:
             self.__shell.destroy()
-        self.__shell = CommandShell({'panel': self,
-                                     'scratch_window': self.__create_scratch_window})
+        import bigboard.pyshell
+        self.__shell = bigboard.pyshell.CommandShell({'panel': self,
+                                     '               scratch_window': self.__create_scratch_window},
+                                                     savepath=os.path.expanduser('~/.bigboard/pyshell.py'))
         self.__shell.show_all()
         self.__shell.present_with_time(gtk.get_current_event_time())
         



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]