diff options
author | Sebastian Koslowski <koslowski@kit.edu> | 2016-02-23 21:47:52 +0100 |
---|---|---|
committer | Sebastian Koslowski <koslowski@kit.edu> | 2016-04-05 08:39:02 +0200 |
commit | 3201557bfbed7ad81e0e5a34ece48bbd93ad709b (patch) | |
tree | dd213153dad1c146fa177a818b355341ed59edfb /grc/gui | |
parent | 7453e24321e6ca237ded87a6bbed8d645d2a6b53 (diff) |
grc-refactor: move gui prefs to gui
Diffstat (limited to 'grc/gui')
-rw-r--r-- | grc/gui/ActionHandler.py | 59 | ||||
-rw-r--r-- | grc/gui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | grc/gui/Constants.py | 10 | ||||
-rw-r--r-- | grc/gui/Executor.py | 123 | ||||
-rw-r--r-- | grc/gui/Platform.py | 12 |
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 |