[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 04/08: grc: open and update params from ext
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 04/08: grc: open and update params from external editor |
Date: |
Wed, 11 Nov 2015 23:08:07 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit 2fee267dfee11bd687b4d780cb6b82924d59af3c
Author: Sebastian Koslowski <address@hidden>
Date: Thu Jul 23 16:36:22 2015 +0200
grc: open and update params from external editor
---
grc/gui/ActionHandler.py | 4 ++
grc/gui/Actions.py | 1 +
grc/gui/CMakeLists.txt | 1 +
grc/gui/Constants.py | 14 ++++---
grc/gui/Dialogs.py | 23 +++++++++++-
grc/gui/FlowGraph.py | 37 +++++++++++++++++-
grc/gui/Param.py | 67 ++++++++++++++++++++++++++++++++-
grc/gui/external_editor.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 228 insertions(+), 12 deletions(-)
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index ee01595..6273178 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -441,6 +441,10 @@ class ActionHandler:
# null action, that updates the main window
Actions.ELEMENT_SELECT()
dialog.destroy()
+ elif action == Actions.EXTERNAL_UPDATE:
+
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_flow_graph().update()
+ self.get_page().set_saved(False)
##################################################
# View Parser Errors
##################################################
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index 2092934..c3ae6c9 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -170,6 +170,7 @@ class ToggleAction(gtk.ToggleAction, _ActionBase):
# Actions
########################################################################
PAGE_CHANGE = Action()
+EXTERNAL_UPDATE = Action()
FLOW_GRAPH_NEW = Action(
label='_New',
tooltip='Create a new flow graph',
diff --git a/grc/gui/CMakeLists.txt b/grc/gui/CMakeLists.txt
index 08aaf3e..99140df 100644
--- a/grc/gui/CMakeLists.txt
+++ b/grc/gui/CMakeLists.txt
@@ -19,6 +19,7 @@
########################################################################
GR_PYTHON_INSTALL(FILES
+ external_editor.py
Block.py
Colors.py
Constants.py
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 980396f..741c6fd 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -17,16 +17,18 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import pygtk
+import os
+import sys
+import pygtk
pygtk.require('2.0')
import gtk
-import os
-import sys
+
from gnuradio import gr
-_gr_prefs = gr.prefs()
+prefs = gr.prefs()
GR_PREFIX = gr.prefix()
+EDITOR = prefs.get_string('grc', 'editor', '')
# default path for the open/save dialogs
DEFAULT_FILE_PATH = os.getcwd()
@@ -49,7 +51,7 @@ DEFAULT_BLOCKS_WINDOW_WIDTH = 100
DEFAULT_REPORTS_WINDOW_WIDTH = 100
try: # ugly, but matches current code style
- raw = _gr_prefs.get_string('grc', 'canvas_default_size', '1280, 1024')
+ raw = prefs.get_string('grc', 'canvas_default_size', '1280, 1024')
DEFAULT_CANVAS_SIZE = tuple(int(x.strip('() ')) for x in raw.split(','))
if len(DEFAULT_CANVAS_SIZE) != 2 or not all(300 < x < 4096 for x in
DEFAULT_CANVAS_SIZE):
raise Exception()
@@ -59,7 +61,7 @@ except:
# flow-graph canvas fonts
try: # ugly, but matches current code style
- FONT_SIZE = _gr_prefs.get_long('grc', 'canvas_font_size', 8)
+ FONT_SIZE = prefs.get_long('grc', 'canvas_font_size', 8)
if FONT_SIZE <= 0:
raise Exception()
except:
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
index 6c01219..631dc0f 100644
--- a/grc/gui/Dialogs.py
+++ b/grc/gui/Dialogs.py
@@ -20,8 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA
import pygtk
pygtk.require('2.0')
import gtk
-import Utils
-import Actions
+
+from . import Utils, Actions, Constants
class SimpleTextDisplay(gtk.TextView):
@@ -234,3 +234,22 @@ def MissingXTermDialog(xterm):
"\n"
"(This message is shown only once)").format(xterm)
)
+
+
+def ChooseEditorDialog():
+ file_dialog = gtk.FileChooserDialog(
+ 'Open a Data File...', None,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
+ ('gtk-cancel', gtk.RESPONSE_CANCEL, 'gtk-open', gtk.RESPONSE_OK)
+ )
+ file_dialog.set_select_multiple(False)
+ file_dialog.set_local_only(True)
+ file_dialog.set_current_folder('/usr/bin')
+ response = file_dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ file_path = file_dialog.get_filename()
+ Constants.prefs.set_string('grc', 'editor', file_path)
+ Constants.prefs.save()
+ Constants.EDITOR = file_path
+ file_dialog.destroy()
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index fc6a711..b27f015 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -18,12 +18,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA
"""
import random
+import functools
from itertools import chain
from operator import methodcaller
+import gobject
+
from . import Actions, Colors, Utils, Messages, Bars
-from .Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
-from .Element import Element
+from . Element import Element
+from . Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
+from . external_editor import ExternalEditor
class FlowGraph(Element):
@@ -55,6 +59,35 @@ class FlowGraph(Element):
self._context_menu = Bars.ContextMenu()
self.get_context_menu = lambda: self._context_menu
+ self._external_updaters = {}
+
+ def install_external_editor(self, param):
+ target = (param.get_parent().get_id(), param.get_key())
+
+ if target in self._external_updaters:
+ editor = self._external_updaters[target]
+ else:
+ updater = functools.partial(
+ self.handle_external_editor_change, target=target)
+ editor = self._external_updaters[target] = ExternalEditor(
+ name=target[0], value=param.get_value(),
+ callback=functools.partial(gobject.idle_add, updater)
+ )
+ editor.start()
+ editor.open_editor()
+
+ def handle_external_editor_change(self, new_value, target):
+ try:
+ block_id, param_key = target
+ self.get_block(block_id).get_param(param_key).set_value(new_value)
+
+ except (IndexError, ValueError): # block no longer exists
+ self._external_updaters[target].stop()
+ del self._external_updaters[target]
+ return
+ Actions.EXTERNAL_UPDATE()
+
+
###########################################################################
# Access Drawing Area
###########################################################################
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index 6bd45fa..3588b81 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -23,7 +23,7 @@ import pygtk
pygtk.require('2.0')
import gtk
-from . import Colors, Utils, Constants
+from . import Colors, Utils, Constants, Dialogs
from . Element import Element
@@ -173,6 +173,66 @@ class MultiLineEntryParam(InputParam):
pass # no tooltips for old GTK
+# try:
+# import gtksourceview
+# lang_manager = gtksourceview.SourceLanguagesManager()
+# py_lang = lang_manager.get_language_from_mime_type('text/x-python')
+#
+# class PythonEditorParam(InputParam):
+# expand = True
+#
+# def __init__(self, *args, **kwargs):
+# InputParam.__init__(self, *args, **kwargs)
+#
+# buf = self._buffer = gtksourceview.SourceBuffer()
+# buf.set_language(py_lang)
+# buf.set_highlight(True)
+# buf.set_text(self.param.get_value())
+# buf.connect('changed', self._mark_changed)
+#
+# view = self._view = gtksourceview.SourceView(self._buffer)
+# view.connect('focus-out-event', self._apply_change)
+# view.connect('key-press-event', self._handle_key_press)
+# view.set_tabs_width(4)
+# view.set_insert_spaces_instead_of_tabs(True)
+# view.set_auto_indent(True)
+# view.set_border_width(2)
+#
+# scroll = gtk.ScrolledWindow()
+# scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+# scroll.add_with_viewport(view)
+# self.pack_start(scroll, True)
+#
+# def get_text(self):
+# buf = self._buffer
+# return buf.get_text(buf.get_start_iter(),
+# buf.get_end_iter()).strip()
+#
+# except ImportError:
+# print "Package 'gtksourceview' not found. No Syntax highlighting."
+# PythonEditorParam = MultiLineEntryParam
+
+class PythonEditorParam(InputParam):
+
+ def __init__(self, *args, **kwargs):
+ InputParam.__init__(self, *args, **kwargs)
+ input = gtk.Button('Open in Editor')
+ input.connect('clicked', self.open_editor)
+ self.pack_start(input, True)
+
+ def open_editor(self, widget=None):
+ if not os.path.exists(Constants.EDITOR):
+ Dialogs.ChooseEditorDialog()
+ flowgraph = self.param.get_parent().get_parent()
+ flowgraph.install_external_editor(self.param)
+
+ def get_text(self):
+ pass # we never update the value from here
+
+ def _apply_change(self, *args):
+ pass
+
+
class EnumParam(InputParam):
"""Provide an entry box for Enum types with a drop down menu."""
@@ -341,9 +401,12 @@ class Param(Element):
elif self.get_options():
input_widget = EnumEntryParam(self, *args, **kwargs)
- elif self.get_type() in ('_multiline', '_multiline_python_external'):
+ elif self.get_type() == '_multiline':
input_widget = MultiLineEntryParam(self, *args, **kwargs)
+ elif self.get_type() == '_multiline_python_external':
+ input_widget = PythonEditorParam(self, *args, **kwargs)
+
else:
input_widget = EntryParam(self, *args, **kwargs)
diff --git a/grc/gui/external_editor.py b/grc/gui/external_editor.py
new file mode 100644
index 0000000..3322556
--- /dev/null
+++ b/grc/gui/external_editor.py
@@ -0,0 +1,93 @@
+"""
+Copyright 2015 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+import os
+import sys
+import time
+import threading
+import tempfile
+import subprocess
+
+import Constants
+
+
+class ExternalEditor(threading.Thread):
+
+ def __init__(self, name, value, callback):
+ threading.Thread.__init__(self)
+ self.daemon = True
+ self._stop_event = threading.Event()
+
+ self.callback = callback
+ self.tempfile = self._create_tempfile(name, value)
+
+ def _create_tempfile(self, name, value):
+ fp = tempfile.NamedTemporaryFile(mode='w', suffix='.py',
+ prefix=name + '_')
+ fp.write(value)
+ fp.flush()
+ return fp
+
+ @property
+ def filename(self):
+ return self.tempfile.name
+
+ def open_editor(self):
+ proc = subprocess.Popen(
+ args=(Constants.EDITOR, self.filename)
+ )
+ proc.poll()
+ return proc
+
+ def stop(self):
+ self._stop_event.set()
+
+ def run(self):
+ filename = self.filename
+ # print "file monitor: started for", filename
+ last_change = os.path.getmtime(filename)
+ try:
+ while not self._stop_event.is_set():
+ mtime = os.path.getmtime(filename)
+ if mtime > last_change:
+ # print "file monitor: reload trigger for", filename
+ last_change = mtime
+ with open(filename) as fp:
+ data = fp.read()
+ self.callback(data)
+ time.sleep(1)
+
+ except Exception as e:
+ print >> sys.stderr, "file monitor crashed:", str(e)
+ else:
+ # print "file monitor: done with", filename
+ pass
+
+
+if __name__ == '__main__':
+ def p(data):
+ print data
+
+ Constants.EDITOR = '/usr/bin/gedit'
+ editor = ExternalEditor("test", "content", p)
+ editor.open_editor()
+ editor.start()
+ time.sleep(15)
+ editor.stop()
+ editor.join()
- [Commit-gnuradio] [gnuradio] branch master updated (6a88efb -> a18e480), git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 01/08: runtime: add accessors for in_sig and out_sig in python blocks, git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 04/08: grc: open and update params from external editor,
git <=
- [Commit-gnuradio] [gnuradio] 02/08: grc: mark param type multiline as protected, git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 05/08: grc: update PropsDialog on external param change, git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 03/08: grc: add embedded python block definition and support in GRC, git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 06/08: grc: fix output file encoding, git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 08/08: Merge remote-tracking branch 'gnuradio-wg-grc/master_grcwg', git, 2015/11/11
- [Commit-gnuradio] [gnuradio] 07/08: Merge branch 'maint', git, 2015/11/11