summaryrefslogtreecommitdiff
path: root/grc/gui
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-02-23 21:47:52 +0100
committerSebastian Koslowski <koslowski@kit.edu>2016-04-05 08:39:02 +0200
commit3201557bfbed7ad81e0e5a34ece48bbd93ad709b (patch)
treedd213153dad1c146fa177a818b355341ed59edfb /grc/gui
parent7453e24321e6ca237ded87a6bbed8d645d2a6b53 (diff)
grc-refactor: move gui prefs to gui
Diffstat (limited to 'grc/gui')
-rw-r--r--grc/gui/ActionHandler.py59
-rw-r--r--grc/gui/CMakeLists.txt1
-rw-r--r--grc/gui/Constants.py10
-rw-r--r--grc/gui/Executor.py123
-rw-r--r--grc/gui/Platform.py12
5 files changed, 148 insertions, 57 deletions
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 41eb6f12b6..139bbedffd 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -17,15 +17,14 @@ 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 subprocess
-from threading import Thread
-import gtk
import gobject
+import gtk
+import os
+import subprocess
-from . import Dialogs, Preferences, Actions
-from .Constants import DEFAULT_CANVAS_SIZE, IMAGE_FILE_EXTENSION, GR_PREFIX
+from . import Dialogs, Preferences, Actions, Executor
+from .Constants import DEFAULT_CANVAS_SIZE, IMAGE_FILE_EXTENSION, GR_PREFIX, XTERM_EXECUTABLE
from .FileDialogs import (OpenFlowGraphFileDialog, SaveFlowGraphFileDialog,
SaveReportsFileDialog, SaveScreenShotDialog,
OpenQSSFileDialog)
@@ -34,7 +33,6 @@ from .ParserErrorsDialog import ParserErrorsDialog
from .PropsDialog import PropsDialog
from ..core import Constants, ParseXML
-from ..core.Constants import XTERM_EXECUTABLE
from ..core import Messages
gobject.threads_init()
@@ -547,7 +545,7 @@ class ActionHandler:
Dialogs.MissingXTermDialog(XTERM_EXECUTABLE)
Preferences.xterm_missing(XTERM_EXECUTABLE)
if self.get_page().get_saved() and self.get_page().get_file_path():
- ExecFlowGraphThread(self)
+ Executor.ExecFlowGraphThread(self)
elif action == Actions.FLOW_GRAPH_KILL:
if self.get_page().get_proc():
try:
@@ -654,48 +652,3 @@ class ActionHandler:
Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive)
Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive)
Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() is not None)
-
-class ExecFlowGraphThread(Thread):
- """Execute the flow graph as a new process and wait on it to finish."""
-
- def __init__ (self, action_handler):
- """
- ExecFlowGraphThread constructor.
-
- Args:
- action_handler: an instance of an ActionHandler
- """
- Thread.__init__(self)
- self.update_exec_stop = action_handler.update_exec_stop
- self.flow_graph = action_handler.get_flow_graph()
- #store page and dont use main window calls in run
- self.page = action_handler.get_page()
- #get the popen
- try:
- self.p = self.page.get_generator().get_popen()
- self.page.set_proc(self.p)
- #update
- self.update_exec_stop()
- self.start()
- except Exception, e:
- Messages.send_verbose_exec(str(e))
- Messages.send_end_exec()
-
- def run(self):
- """
- Wait on the executing process by reading from its stdout.
- Use gobject.idle_add when calling functions that modify gtk objects.
- """
- #handle completion
- r = "\n"
- while r:
- gobject.idle_add(Messages.send_verbose_exec, r)
- r = os.read(self.p.stdout.fileno(), 1024)
- self.p.poll()
- gobject.idle_add(self.done)
-
- def done(self):
- """Perform end of execution tasks."""
- Messages.send_end_exec(self.p.returncode)
- self.page.set_proc(None)
- self.update_exec_stop()
diff --git a/grc/gui/CMakeLists.txt b/grc/gui/CMakeLists.txt
index 99140df7c4..7e4355357b 100644
--- a/grc/gui/CMakeLists.txt
+++ b/grc/gui/CMakeLists.txt
@@ -25,6 +25,7 @@ GR_PYTHON_INSTALL(FILES
Constants.py
Connection.py
Element.py
+ Executor.py
FlowGraph.py
Param.py
Platform.py
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 741c6fda95..b891c5b313 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -29,6 +29,16 @@ from gnuradio import gr
prefs = gr.prefs()
GR_PREFIX = gr.prefix()
EDITOR = prefs.get_string('grc', 'editor', '')
+XTERM_EXECUTABLE = prefs.get_string('grc', 'xterm_executable', 'xterm')
+
+PREFS_FILE = os.environ.get(
+ 'GRC_PREFS_PATH',
+ os.path.expanduser('~/.gnuradio/grc.conf')
+)
+PREFS_FILE_OLD = os.environ.get(
+ 'GRC_PREFS_PATH',
+ os.path.expanduser('~/.grc')
+)
# default path for the open/save dialogs
DEFAULT_FILE_PATH = os.getcwd()
diff --git a/grc/gui/Executor.py b/grc/gui/Executor.py
new file mode 100644
index 0000000000..96b95f4c7a
--- /dev/null
+++ b/grc/gui/Executor.py
@@ -0,0 +1,123 @@
+# Copyright 2016 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 gobject
+import os
+import threading
+import shlex
+import subprocess
+import sys
+import re
+from distutils.spawn import find_executable
+
+from ..core import Messages
+from .Constants import XTERM_EXECUTABLE
+
+
+class ExecFlowGraphThread(threading.Thread):
+ """Execute the flow graph as a new process and wait on it to finish."""
+
+ def __init__(self, action_handler):
+ """
+ ExecFlowGraphThread constructor.
+
+ Args:
+ action_handler: an instance of an ActionHandler
+ """
+ threading.Thread.__init__(self)
+ self.update_exec_stop = action_handler.update_exec_stop
+ self.flow_graph = action_handler.get_flow_graph()
+ #store page and dont use main window calls in run
+ self.page = action_handler.get_page()
+ #get the popen
+ try:
+ self.p = self._popen()
+ self.page.set_proc(self.p)
+ #update
+ self.update_exec_stop()
+ self.start()
+ except Exception, e:
+ Messages.send_verbose_exec(str(e))
+ Messages.send_end_exec()
+
+ def _popen(self):
+ """
+ Execute this python flow graph.
+ """
+ run_command = self.flow_graph.get_option('run_command')
+ generator = self.page.get_generator()
+
+ try:
+ run_command = run_command.format(
+ python=shlex_quote(sys.executable),
+ filename=shlex_quote(generator.file_path))
+ run_command_args = shlex.split(run_command)
+ except Exception as e:
+ raise ValueError("Can't parse run command {!r}: {}".format(run_command, e))
+
+ # When in no gui mode on linux, use a graphical terminal (looks nice)
+ xterm_executable = find_executable(XTERM_EXECUTABLE)
+ if generator.generate_options == 'no_gui' and xterm_executable:
+ run_command_args = [xterm_executable, '-e', run_command]
+
+ # this does not reproduce a shell executable command string, if a graphical
+ # terminal is used. Passing run_command though shlex_quote would do it but
+ # it looks really ugly and confusing in the console panel.
+ Messages.send_start_exec(' '.join(run_command_args))
+
+ return subprocess.Popen(
+ args=run_command_args,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ shell=False, universal_newlines=True
+ )
+
+ def run(self):
+ """
+ Wait on the executing process by reading from its stdout.
+ Use gobject.idle_add when calling functions that modify gtk objects.
+ """
+ #handle completion
+ r = "\n"
+ while r:
+ gobject.idle_add(Messages.send_verbose_exec, r)
+ r = os.read(self.p.stdout.fileno(), 1024)
+ self.p.poll()
+ gobject.idle_add(self.done)
+
+ def done(self):
+ """Perform end of execution tasks."""
+ Messages.send_end_exec(self.p.returncode)
+ self.page.set_proc(None)
+ self.update_exec_stop()
+
+
+###########################################################
+# back-port from python3
+###########################################################
+_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
+
+
+def shlex_quote(s):
+ """Return a shell-escaped version of the string *s*."""
+ if not s:
+ return "''"
+ if _find_unsafe(s) is None:
+ return s
+
+ # use single quotes, and put single quotes into double quotes
+ # the string $'b is then quoted as '$'"'"'b'
+ return "'" + s.replace("'", "'\"'\"'") + "'"
diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py
index 85a6872027..cfd5ae3e3d 100644
--- a/grc/gui/Platform.py
+++ b/grc/gui/Platform.py
@@ -20,16 +20,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import sys
-from .Element import Element
-
from ..core.Platform import Platform as _Platform
-from ..core.Constants import PREFS_FILE, PREFS_FILE_OLD
from .Block import Block as _Block
+from .Connection import Connection as _Connection
+from .Constants import PREFS_FILE, PREFS_FILE_OLD
+from .Element import Element
from .FlowGraph import FlowGraph as _FlowGraph
from .Param import Param as _Param
from .Port import Port as _Port
-from .Connection import Connection as _Connection
class Platform(Element, _Platform):
@@ -37,6 +36,11 @@ class Platform(Element, _Platform):
def __init__(self):
Element.__init__(self)
_Platform.__init__(self)
+
+ # Ensure conf directories
+ if not os.path.exists(os.path.dirname(PREFS_FILE)):
+ os.mkdir(os.path.dirname(PREFS_FILE))
+
self._move_old_pref_file()
self._prefs_file = PREFS_FILE