Class: Ruber::ExternalProgramPlugin
- Defined in:
- lib/ruber/external_program_plugin.rb
Overview
Base class for plugins whose main task is to run an external program and maybe (not necessarily) to display the output in a tool widget.
Basically, this class is a wrapper for KDE::Process
providing a more integrated API for the most common functions. In particular, it provides the following functionality:
-
automatic creation of the process
-
automatic cleanup at shutdown
-
automatic managing of buffered output
-
nicer API to read from standard output and standard error
-
simplified API to start the process
-
automatic display of standard output and standard error in a tool widget (if required)
-
display of the command line and of the process status in a tool widget (if required)
To start the process, you simply call the run_process
method, passing it the name of the program to run, the working directory and the arguments.
When the process emits the readyReadStandardOutput()
or the readyReadStandardError()
, the contents of the appropriate stream are read and split into lines. The resulting array are passed to the process_standard_output
or process_standard_error
method. Derived classes can override these methods to do what they want with the output.
In general, you can’t be sure whether the data contained read from standard output or error contains complete lines. To deal with this issue, whenob reading from a stream, only full lines (that is, lines which end in “n”) are passed to process_standard_output
or process_standard_error
. If the last line isn’t complete, it is stored in a buffer. The next time characters are read from the process, if they came from the same channel, the buffer is added at the beginning of the new stream; if they came from the other channel, they’re passed to the appropriate process_standard_*
method. This behaviour can be changed by passing the appropriate arguments to the constructor.
Some methods in this class have the ability to insert data in a OutputWidget. They will do so if the @output_widget
instance variable (which is created in the constructor, if it doesn’t already exist) is not nil. Note that those methods don’t check if @output_widget
actually is an OutputWidget or not. If it is something else, you’ll get errors. In all the following documentation it is assumed that:
-
the expression the output widget refers to the object the
@output_widget
instance variable refers to, unless it’s nil -
everything concerning the output widget will be ignored (without giving any error) if the output widget doesn’t exist
Signals
process_finished(int code, QString reason)
Signal emitted when the process finishes. code is the exit code of the process, while reason is a string which can have one of the values “killed”, “crash” or be empty. If it’s empty, it means that the program finished normally; “killed” means that it was killed by the user and “crash” means that the program crashed.
process_started()
Signal emitted when the process has started
process_failed_to_start()
Signal emitted if the process couldn’t be started (for example, because the given program doesn’t exist)
Slots
-
slot_process_finished(int, QProcess::ExitStatus)
-
stop_process()
Constant Summary
Constants inherited from Plugin
Instance Attribute Summary collapse
-
#process ⇒ Object
readonly
The
KDE::Process
used by the plugin.
Attributes included from PluginLike
Instance Method Summary collapse
-
#initialize(pdf, line_buffered = true) ⇒ ExternalProgramPlugin
constructor
Creates a new ExternalProgramPlugin.
-
#run_process(prog, dir, args, title = '') ⇒ Object
Starts the program.
-
#shutdown ⇒ Object
Prepares the plugin to be unloaded by killing the process (no signal will be emitted from the process or the plugin from now on).
-
#stop_process ⇒ Object
Stops the process.
Methods inherited from GuiPlugin
#action_collection, #execute_action, #unload
Methods inherited from Plugin
Methods included from PluginLike
#add_extensions_to_project, #add_options_to_project, #add_widgets_to_project, #plugin_name, #query_close, #register_with_project, #remove_extensions_from_project, #remove_from_project, #remove_options_from_project, #remove_widgets_from_project, #restore_session, #save_settings, #session_data, #unload, #update_project
Constructor Details
#initialize(pdf, line_buffered = true) ⇒ ExternalProgramPlugin
Creates a new ExternalProgramPlugin.
pdf is the plugin info object for the plugin. If line_buffered is false, buffering won’t be used (all the characters read from the process will be passed to process_standard_output
or process_standard_error
even if they don’t end in a newline).
Note: the process’ channel mode will be set to Qt::Process::SeparateChannels
. You can set it to any value you want later
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/ruber/external_program_plugin.rb', line 108 def initialize pdf, line_buffered = true super pdf @buffer = nil @buffer_content_channel = nil @line_buffered = line_buffered @output_widget = nil unless defined? @output_widget @process = KDE::Process.new self @process.process_channel_mode = Qt::Process::SeparateChannels @process.output_channel_mode = KDE::Process::SeparateChannels @process.connect SIGNAL(:readyReadStandardOutput) do do_stdout @process.read_all_standard_output.to_s end @process.connect SIGNAL(:readyReadStandardError) do do_stderr @process.read_all_standard_error.to_s end connect @process, SIGNAL('finished(int, QProcess::ExitStatus)'), self, SLOT('slot_process_finished(int, QProcess::ExitStatus)') connect self, SIGNAL('process_finished(int, QString)'), self, SLOT('display_exit_message(int, QString)') @process.connect SIGNAL('error(QProcess::ProcessError)') do |e| failed_to_start if e == Qt::Process::FailedToStart end connect @process, SIGNAL('started()'), self, SIGNAL('process_started()') end |
Instance Attribute Details
#process ⇒ Object (readonly)
The KDE::Process
used by the plugin
95 96 97 |
# File 'lib/ruber/external_program_plugin.rb', line 95 def process @process end |
Instance Method Details
#run_process(prog, dir, args, title = '') ⇒ Object
Starts the program.
prog is the name of the program (you don’t need to specify the absolute path if it’s in PATH). args is an array containing the arguments. dir is the working directory.
title is the string to display in the output widget. If it is an empty string, the name of the program followed by its arguments will be used. If it is nil or false, the title won’t be set.
142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/ruber/external_program_plugin.rb', line 142 def run_process prog, dir, args, title = '' @buffer = nil @buffer_content_channel = nil @process.clear_program @process.working_directory = dir program = [prog] + args @process.program = program if @output_widget and title title = program.join ' ' if title.empty? @output_widget.title = title end @process.start end |
#shutdown ⇒ Object
Prepares the plugin to be unloaded by killing the process (no signal will be emitted from the process or the plugin from now on).
If you reimplement this method, don’t forget to call super. If you don’t you might cause a crash when Ruber is closed
172 173 174 175 176 |
# File 'lib/ruber/external_program_plugin.rb', line 172 def shutdown @process.block_signals true @process.kill super end |
#stop_process ⇒ Object
Stops the process.
It’s a shortcut for process.kill
161 162 163 |
# File 'lib/ruber/external_program_plugin.rb', line 161 def stop_process @process.kill end |