From 1222f19ca4170b5c4f42b37b73ea6b0e1bce9ada Mon Sep 17 00:00:00 2001 From: "BrenBarn@BrenBarn-Ava.sd.cox.net" Date: Tue, 16 Apr 2013 11:42:26 -0700 Subject: [PATCH 1/5] Added option to swap pane position If the option is on, then vertical layout has code on top, output on bottom, and horizontal has code on left, output on right. Also, with code on top, changed notebook tabs to be on top too. --- dreampielib/data/dreampie.glade | 15 +++++++++++++++ dreampielib/gui/__init__.py | 23 ++++++++++++++++++++--- dreampielib/gui/config.py | 1 + dreampielib/gui/config_dialog.py | 4 ++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/dreampielib/data/dreampie.glade b/dreampielib/data/dreampie.glade index b063bc8..d15cd81 100644 --- a/dreampielib/data/dreampie.glade +++ b/dreampielib/data/dreampie.glade @@ -1195,6 +1195,21 @@ You can also set the __expects_str__ attribute of a function to True to achieve 5 + + + Swap panes + True + True + False + False + True + + + False + True + 5.5 + + Leave code in the code box after execution diff --git a/dreampielib/gui/__init__.py b/dreampielib/gui/__init__.py index f93d75b..3b77400 100644 --- a/dreampielib/gui/__init__.py +++ b/dreampielib/gui/__init__.py @@ -1266,9 +1266,13 @@ def configure(self): tags.apply_theme_source(sv.get_buffer(), theme) vertical_layout = self.config.get_bool('vertical-layout') + swap_panes = self.config.get_bool('swap-panes') if vertical_layout: pane = self.vpaned_main; other_pane = self.hpaned_main - self.notebook.props.tab_pos = gtk.POS_BOTTOM + if swap_panes: + self.notebook.props.tab_pos = gtk.POS_TOP + else: + self.notebook.props.tab_pos = gtk.POS_BOTTOM else: pane = self.hpaned_main; other_pane = self.vpaned_main self.notebook.props.tab_pos = gtk.POS_TOP @@ -1277,9 +1281,22 @@ def configure(self): if pane.get_child1() is None: child1 = other_pane.get_child1(); other_pane.remove(child1) child2 = other_pane.get_child2(); other_pane.remove(child2) - pane.pack1(child1, resize=True, shrink=False) - pane.pack2(child2, resize=not vertical_layout, shrink=False) + else: + child1 = pane.get_child1(); pane.remove(child1) + child2 = pane.get_child2(); pane.remove(child2) + + if child1.get_name() == 'scrolledwindow_textview': + editPane, outputPane = child1, child2 + else: + editPane, outputPane = child2, child1 + if swap_panes: + pane.pack1(outputPane, resize=not vertical_layout, shrink=False) + pane.pack2(editPane, resize=True, shrink=False) + else: + pane.pack1(editPane, resize=True, shrink=False) + pane.pack2(outputPane, resize=not vertical_layout, shrink=False) + # If the fonts were changed, we might need to enlarge the window last_font, last_vertical = self.last_configured_layout if last_font != font or last_vertical != vertical_layout: diff --git a/dreampielib/gui/config.py b/dreampielib/gui/config.py index 23606f0..ebde1a5 100644 --- a/dreampielib/gui/config.py +++ b/dreampielib/gui/config.py @@ -49,6 +49,7 @@ recall-1-char-commands = False hide-defs = False leave-code = False +swap-panes = False [Dark theme] is-active = True diff --git a/dreampielib/gui/config_dialog.py b/dreampielib/gui/config_dialog.py index bf34cdc..f33b683 100644 --- a/dreampielib/gui/config_dialog.py +++ b/dreampielib/gui/config_dialog.py @@ -65,6 +65,8 @@ def __init__(self, config, gladefile, parent): self.horizontal_layout_rad.props.active = not config.get_bool('vertical-layout') self.leave_code_chk.props.active = config.get_bool('leave-code') + + self.swap_panes_chk.props.active = config.get_bool('swap-panes') self.hide_defs_chk.props.active = config.get_bool('hide-defs') @@ -156,6 +158,8 @@ def run(self): config.set_bool('leave-code', self.leave_code_chk.props.active) + config.set_bool('swap-panes', self.swap_panes_chk.props.active) + config.set_bool('hide-defs', self.hide_defs_chk.props.active) if self.matplotlib_ia_switch_rad.props.active: From 40136501527f19bcaf7d4011da133369e4320bd0 Mon Sep 17 00:00:00 2001 From: "BrenBarn@BrenBarn-Ava.sd.cox.net" Date: Sat, 11 May 2013 17:44:57 -0700 Subject: [PATCH 2/5] Fixed autocomplete popup direction for swapped panes. When panes are swapped (edit on top), the autocomplete popup now stretches DOWN from the cursor, not up. This makes it so it won't extend up off the screen. --- dreampielib/gui/__init__.py | 17 ++++++++++++----- dreampielib/gui/autocomplete_window.py | 6 +++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/dreampielib/gui/__init__.py b/dreampielib/gui/__init__.py index 3b77400..639f82e 100644 --- a/dreampielib/gui/__init__.py +++ b/dreampielib/gui/__init__.py @@ -169,11 +169,6 @@ def __init__(self, pyexec, runfile): # A tuple (page_num, text) of the recently closed tab self.reopen_tab_data = None - # last (font, vertical_layout) configured. If they are changed, - # configure() will resize the window and place the paned. - self.last_configured_layout = (None, None) - self.configure() - self.output = Output(self.textview) self.folding = Folding(self.textbuffer, LINE_LEN) @@ -213,6 +208,14 @@ def __init__(self, pyexec, runfile): self.complete_dict_keys, INDENT_WIDTH) + # had to move this down below autocomplete in order to allow configuration of autocomplete popup direction + + # last (font, vertical_layout) configured. If they are changed, + # configure() will resize the window and place the paned. + self.last_configured_layout = (None, None) + self.configure() + + # Hack: we connect this signal here, so that it will have lower # priority than the key-press event of autocomplete, when active. self.sourceview_keypress_handler = self.sourceview.connect( @@ -1296,6 +1299,10 @@ def configure(self): else: pane.pack1(editPane, resize=True, shrink=False) pane.pack2(outputPane, resize=not vertical_layout, shrink=False) + + # if panes are swapped, the autocomplete window should pop up BELOW cursor + # (otherwise it will extend up off the screen) + self.autocomplete.window.align = "top" if swap_panes else "bottom" # If the fonts were changed, we might need to enlarge the window last_font, last_vertical = self.last_configured_layout diff --git a/dreampielib/gui/autocomplete_window.py b/dreampielib/gui/autocomplete_window.py index 0be49e8..61a4825 100644 --- a/dreampielib/gui/autocomplete_window.py +++ b/dreampielib/gui/autocomplete_window.py @@ -240,7 +240,11 @@ def place_window(self): self.window.show_all() self.window_height = self.window.get_size()[1] self.window.hide() - self.window.move(x, y-self.window_height) + #self.window.move(x, y-self.window_height) + # If panes are swapped, the TOP of the autocomplete will align with cursor; if not, the BOTTOM will align + # This prevents the window from extending off the screen. + offset = self.window_height if self.align == "bottom" else 0 + self.window.move(x, y-offset) def on_mark_set(self, sb, it, mark): if mark is sb.get_insert(): From 43ddd266471e974f9655bb10649d0a0b411b74c6 Mon Sep 17 00:00:00 2001 From: "BrenBarn@BrenBarn-Ava.sd.cox.net" Date: Sat, 11 May 2013 17:57:33 -0700 Subject: [PATCH 3/5] Another tweak to autocomplete box alignment Previous fix caused the autocomplete box to overlap the cursor. We adjust its position by lineheight to avoid this. --- dreampielib/gui/autocomplete_window.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dreampielib/gui/autocomplete_window.py b/dreampielib/gui/autocomplete_window.py index 61a4825..34df1c3 100644 --- a/dreampielib/gui/autocomplete_window.py +++ b/dreampielib/gui/autocomplete_window.py @@ -243,8 +243,11 @@ def place_window(self): #self.window.move(x, y-self.window_height) # If panes are swapped, the TOP of the autocomplete will align with cursor; if not, the BOTTOM will align # This prevents the window from extending off the screen. - offset = self.window_height if self.align == "bottom" else 0 - self.window.move(x, y-offset) + if self.align == "bottom": + offset = -self.window_height + else: + offset = sv.get_line_yrange(it)[1] + self.window.move(x, y+offset) def on_mark_set(self, sb, it, mark): if mark is sb.get_insert(): From d288e7e035f24efe3c22342c524a2adcf766d8fe Mon Sep 17 00:00:00 2001 From: "BrenBarn@BrenBarn-Ava.sd.cox.net" Date: Tue, 14 May 2013 10:59:19 -0700 Subject: [PATCH 4/5] Make calltip window word wrap --- dreampielib/gui/call_tip_window.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dreampielib/gui/call_tip_window.py b/dreampielib/gui/call_tip_window.py index 8748f44..9f60d7c 100644 --- a/dreampielib/gui/call_tip_window.py +++ b/dreampielib/gui/call_tip_window.py @@ -54,6 +54,7 @@ def __init__(self, sourceview, sv_changed): # Widgets self.textview = tv = gtk.TextView() + tv.set_wrap_mode(gtk.WRAP_WORD) self.hscrollbar = hs = gtk.HScrollbar() self.vscrollbar = vs = gtk.VScrollbar() self.resizegrip = rg = gtk.EventBox() From cd59da455e237609fdaf5cf218b79dd1e2256120 Mon Sep 17 00:00:00 2001 From: BrenBarn Date: Thu, 13 Oct 2016 11:39:58 -0700 Subject: [PATCH 5/5] Added "manual override" to get DreamPie out of its stuck state. The problem seems to be due to the _n_unclaimed_results counter somehow getting out of sync. At some point, this counter is incremeneted but not properly decremented. The result is that DreamPie keeps saying "subprocess is busy", thinking it is waiting for a result, but there really isn't any result coming, so it waits forever. (This waiting occurs in DreamPie.call_subp_noblock, which is called from execute_source.) The "solution" is to add a simple method to the DreamPie class that just decrements _n_unclaimed_results. I then added a menu item to call this function. If this "stuck" situation arises, you can clear it by using this manual override. Note that using this when the subprocess is *not* stuck could cause havoc, so be careful! --- dreampielib/data/dreampie.glade | 11 +++++++++++ dreampielib/gui/__init__.py | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/dreampielib/data/dreampie.glade b/dreampielib/data/dreampie.glade index d15cd81..30cfd92 100644 --- a/dreampielib/data/dreampie.glade +++ b/dreampielib/data/dreampie.glade @@ -1982,6 +1982,17 @@ You can also set the __expects_str__ attribute of a function to True to achieve + + + True + False + Try to unclog a stuck subprocess. Use with care! + False + Unclog subprocess + True + + + True diff --git a/dreampielib/gui/__init__.py b/dreampielib/gui/__init__.py index 639f82e..c71fefc 100644 --- a/dreampielib/gui/__init__.py +++ b/dreampielib/gui/__init__.py @@ -964,6 +964,16 @@ def on_interrupt(self, _widget): _("A command isn't being executed currently")) beep() + def on_unclog_subprocess(self, _widget): + # It seems that sometimes DreamPie thinks there is an unclaimed + # result when there really isn't. Here we try to clear the clog by + # decrementing the unclaimed result counter. This could blow up + # badly if used at the wrong time, so should only be used when it + # really seems like DreamPie thinks the subprocess is busy but it + # really isn't. + self._n_unclaimed_results -= 1 + + # History persistence def on_save_history(self, _widget):