Class: Cosmos::QtTool
- Defined in:
- lib/cosmos/gui/qt_tool.rb
Overview
Base class of all COSMOS GUI Tools based on QT. It creates the help menu which contains the About menu option. It provides configuration to all tools to remember both the application window location and size across executions. It also redirects all I/O from the application (any printing to stdout or stderr) and creates popups.
Direct Known Subclasses
CmdExtractor, CmdSender, CmdTlmServerGui, DataViewer, HandbookCreator, Launcher, LimitsMonitor, OpenGLBuilder, PacketViewer, Replay, ScriptRunner, TabbedPlotsTool, TableManager, TestRunner, TlmExtractor, TlmViewer
Constant Summary collapse
- @@redirect_io_thread =
nil
Class Method Summary collapse
-
.create_default_options ⇒ OptionParser, OpenStruct
Creates the default application options in a OpenStruct instance.
- .graceful_kill ⇒ Object
-
.post_options_parsed_hook(options) ⇒ Boolean
Called after parsing all the command line options passed to the application.
-
.pre_window_new_hook(options) ⇒ Object
Called after the Qt::Application has been created but before the application itself has been created.
-
.redirect_io(stdout = true, stderr = true) ⇒ Object
Redirect stdout and stderr to a stringIO and monitor it for text.
-
.restore_io(stdout = true, stderr = true) ⇒ Object
Restore stdout and stderr so text will not be captured and generate a popup.
-
.run(option_parser = nil, options = nil) ⇒ Object
Create the default application options and parse the command line options.
Instance Method Summary collapse
-
#about ⇒ Object
Display the AboutDialog with the @about_string.
-
#closeEvent(event) ⇒ Object
The closeEvent is sent to the application when it is about to close.
-
#complete_initialize ⇒ Object
This should be called after the tool has been completely laid out and all widgets added.
-
#initialize(options) ⇒ QtTool
constructor
A new instance of QtTool.
-
#initialize_actions ⇒ Object
Create the @exit_action and the @about_action.
-
#initialize_help_menu ⇒ Object
Creates the Help menu and adds the @about_action to it.
Constructor Details
#initialize(options) ⇒ QtTool
Returns a new instance of QtTool.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/cosmos/gui/qt_tool.rb', line 32 def initialize() # Call QT::MainWindow constructor super() # MUST BE FIRST - All code before super is executed twice in RubyQt Based classes # Add Path for plugins Qt::Application.instance.addLibraryPath(Qt::PLUGIN_PATH) if Kernel.is_windows? # Prevent killing the parent process from killing this GUI application Process.setpgrp unless Kernel.is_windows? self.class.redirect_io if .redirect_io # Configure instance variables @options = @about_string = nil self.window_title = .title Cosmos.load_cosmos_icon end |
Class Method Details
.create_default_options ⇒ OptionParser, OpenStruct
Creates the default application options in a OpenStruct instance. These options include the window size and position. Options also exist to automatically size and position the window and whether to remember the previous size and position.
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/cosmos/gui/qt_tool.rb', line 214 def self. = OpenStruct.new .auto_position = true .x = 0 .y = 0 .auto_size = true .width = 800 .height = 600 .command_line_geometry = false .remember_geometry = true .restore_position = true .restore_size = true .redirect_io = true .title = "COSMOS Tool" parser = OptionParser.new do |option_parser| option_parser. = "Usage: ruby #{option_parser.program_name} [options]" option_parser.separator("") # Create the help option option_parser.on("-h", "--help", "Show this message") do puts option_parser exit end # Create the version option option_parser.on("-v", "--version", "Show version") do puts "COSMOS Version: #{COSMOS_VERSION}" puts "User Version: #{USER_VERSION}" if defined? USER_VERSION exit end # Create the system option option_parser.on("--system VALUE", "Use an alternative system.txt file") do |arg| System.instance(File.join(USERPATH, 'config', 'system', arg)) end # Create the minimized option option_parser.on("--minimized", "Start the tool minimized") do |arg| .startup_state = :MINIMIZED end # Create the maximized option option_parser.on("--maximized", "Start the tool maximized") do |arg| .startup_state = :MAXIMIZED end # Create the defaultsize option option_parser.on("--defaultsize", "Start the tool in its default size") do |arg| .startup_state = :DEFAULT end # Create the x and y position options option_parser.separator("") option_parser.separator("Window X & Y Position Options:") option_parser.separator(" Positive values indicate a position from the top and left of the screen.") option_parser.separator(" Negative values indicate a position from the bottom and right of the screen.") option_parser.separator(" A value of -1 indicates to place the right or bottom side of the window") option_parser.separator(" next to the right or bottom edge of the screen.") option_parser.on("-x VALUE", "--xpos VALUE", Integer, "Window X position") do |arg| .x = arg .auto_position = false .command_line_geometry = true end option_parser.on("-y VALUE", "--ypos VALUE", Integer, "Window Y position") do |arg| .y = arg .auto_position = false .command_line_geometry = true end # Create the width and height options option_parser.separator("") option_parser.separator("Window Width and Height Options:") option_parser.separator(" Specifing width and height will force the specified dimension.") option_parser.separator(" Otherwise the window will layout according to its defaults.") option_parser.on("-w VALUE", "--width VALUE", Integer, "Window width") do |arg| .width = arg .auto_size = false .command_line_geometry = true end option_parser.on("-t VALUE", "--height VALUE", Integer, "Window height") do |arg| .height = arg .auto_size = false .command_line_geometry = true end option_parser.separator "" end return parser, end |
.graceful_kill ⇒ Object
374 375 376 |
# File 'lib/cosmos/gui/qt_tool.rb', line 374 def self.graceful_kill # Just to remove warning end |
.post_options_parsed_hook(options) ⇒ Boolean
Called after parsing all the command line options passed to the application. Users can re-implement this method to return false which will cause the application to exit without being shown. Return true to contine creating the window and execing the application.
160 161 162 |
# File 'lib/cosmos/gui/qt_tool.rb', line 160 def self.() true end |
.pre_window_new_hook(options) ⇒ Object
Called after the Qt::Application has been created but before the application itself has been created. This is the last chance to execute custom code before the application executes.
170 171 |
# File 'lib/cosmos/gui/qt_tool.rb', line 170 def self.pre_window_new_hook() end |
.redirect_io(stdout = true, stderr = true) ⇒ Object
Redirect stdout and stderr to a stringIO and monitor it for text. If text is found create a popup titled “Unexpected STD output”. Thus applications should not print to standard output or standard error in their applications unless they are trying to warn the user.
NOTE: This is automatically called in #initialize if the redirect_io option is set which it is by default.
NOTE: For debugging purposes use STDOUT.puts “Message” which will print to the command line when run from the command line. If run from the COSMOS Launcher the output will be lost.
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
# File 'lib/cosmos/gui/qt_tool.rb', line 319 def self.redirect_io(stdout = true, stderr = true) if stdout stdout_stringio = StringIO.new('', 'r+') $stdout = stdout_stringio end if stderr stderr_stringio = StringIO.new('', 'r+') $stderr = stderr_stringio if stderr end # Monitor for text to be written @@redirect_io_thread = Thread.new do @@redirect_io_thread_sleeper = Sleeper.new begin loop do if stdout and stdout_stringio.string.length > 0 saved_string = stdout_stringio.string.dup stdout_stringio.string = '' Qt.execute_in_main_thread(true) do ScrollTextDialog.new(Qt::CoreApplication.instance.activeWindow, 'Unexpected STDOUT output', saved_string) end end if stderr and stderr_stringio.string.length > 0 saved_string = stderr_stringio.string.dup stderr_stringio.string = '' Qt.execute_in_main_thread(true) do ScrollTextDialog.new(Qt::CoreApplication.instance.activeWindow, 'Unexpected STDERR output', saved_string) end end break if @@redirect_io_thread_sleeper.sleep(1) end rescue Exception => error Qt.execute_in_main_thread(true) { || ExceptionDialog.new(Qt::CoreApplication.instance.activeWindow, error, 'Exception in Redirect IO Thread') } end end end |
.restore_io(stdout = true, stderr = true) ⇒ Object
Restore stdout and stderr so text will not be captured and generate a popup. This should be called if redirect_io was called.
NOTE: #closeEvent automatically calls restore_io if the redirect_io option is set (which means redirect_io was called upon startup).
365 366 367 368 369 370 371 372 |
# File 'lib/cosmos/gui/qt_tool.rb', line 365 def self.restore_io(stdout = true, stderr = true) $stdout = STDOUT if stdout $stderr = STDERR if stderr @@redirect_io_thread_sleeper.cancel Qt::CoreApplication.processEvents() Cosmos.kill_thread(self, @@redirect_io_thread) @@redirect_io_thread = nil end |
.run(option_parser = nil, options = nil) ⇒ Object
Create the default application options and parse the command line options. Create the application instance and call exec on the Qt::Application.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/cosmos/gui/qt_tool.rb', line 176 def self.run(option_parser = nil, = nil) Cosmos.set_working_dir do option_parser, = () unless option_parser and option_parser.parse!(ARGV) if () @@application = nil begin @@application = Qt::Application.new(ARGV) @@application.addLibraryPath(Qt::PLUGIN_PATH) if Kernel.is_windows? pre_window_new_hook() @@window = self.new() #Qt.debug_level = Qt::DebugLevel::High #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_ALL) #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_AMBIGUOUS) #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_CALLS) #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_GC) #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_METHOD_MISSING) #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_VERBOSE) #Qt::Internal::setDebug(Qt::QtDebugChannel::QTDB_VIRTUAL) @@application.exec rescue Exception => error unless error.class == SystemExit or error.class == Interrupt Cosmos.handle_fatal_exception(error, false) end end end end end |
Instance Method Details
#about ⇒ Object
Display the AboutDialog with the @about_string. The @about_string should be set by the user in the constructor of their application.
148 149 150 |
# File 'lib/cosmos/gui/qt_tool.rb', line 148 def about AboutDialog.new(self, @about_string) end |
#closeEvent(event) ⇒ Object
The closeEvent is sent to the application when it is about to close. We re-implement it in order to remember the position and size of the window for subsequent launches of the application.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/cosmos/gui/qt_tool.rb', line 126 def closeEvent(event) if @options.remember_geometry and not @options.command_line_geometry settings = Qt::Settings.new('Ball Aerospace', self.class.to_s) settings.setValue('position', Qt::Variant.new(pos())) settings.setValue('size', Qt::Variant.new(size())) end self.class.restore_io if @options.redirect_io # Close any remaining dialogs qt_version_split = Qt::qVersion.split('.') # Only closeAllWindows on Qt versions greater than 4.6 if qt_version_split[0].to_i > 4 or (qt_version_split[0].to_i == 4 and qt_version_split[1].to_i > 6) Qt::Application.closeAllWindows() end super(event) end |
#complete_initialize ⇒ Object
This should be called after the tool has been completely laid out and all widgets added. It resizes the application if necessary and positions the window on the screen if necessary. It also remembers the size and position of the windows for subsequent launches of the application. Finally it can initally show the application as minimized or maximized.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/cosmos/gui/qt_tool.rb', line 79 def complete_initialize # Handle manually sizing the window resize(@options.width, @options.height) unless @options.auto_size # Handle manually positioning the window unless @options.auto_position # Get the desktop's geometry desktop = Qt::Application.desktop # Handle position relative to right edge @options.x = desktop.width - frameGeometry().width + @options.x + 1 if @options.x < 0 # Handle position relative to bottom edge @options.y = desktop.height - frameGeometry().height + @options.y + 1 if @options.y < 0 # Move to the desired position move(@options.x, @options.y) end if @options.remember_geometry and !@options.command_line_geometry settings = Qt::Settings.new('Ball Aerospace', self.class.to_s) if settings.contains('size') and @options.restore_size and @options.startup_state != :DEFAULT size = settings.value('size').toSize resize(size) end if settings.contains('position') and @options.restore_position position = settings.value('position').toPoint move(position) end end case @options.startup_state when :MINIMIZED showMinimized() when :MAXIMIZED showMaximized() else show() end self.raise() end |
#initialize_actions ⇒ Object
Create the @exit_action and the @about_action. The @exit_action is not placed in the File menu and must be manually added by the user. The
55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/cosmos/gui/qt_tool.rb', line 55 def initialize_actions @exit_action = Qt::Action.new(Cosmos.get_icon('close.png'), tr('E&xit'), self) @exit_keyseq = Qt::KeySequence.new(tr('Ctrl+Q')) @exit_action.shortcut = @exit_keyseq @exit_action.statusTip = tr('Exit the application') connect(@exit_action, SIGNAL('triggered()'), self, SLOT('close()')) @about_action = Qt::Action.new(Cosmos.get_icon('help.png'), tr('&About'), self) @about_action.statusTip = tr('About the application') connect(@about_action, SIGNAL('triggered()'), self, SLOT('about()')) end |
#initialize_help_menu ⇒ Object
Creates the Help menu and adds the @about_action to it. Thus this MUST be called after initialize_actions.
69 70 71 72 |
# File 'lib/cosmos/gui/qt_tool.rb', line 69 def @help_menu = ().addMenu(tr('&Help')) @help_menu.addAction(@about_action) end |