main.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #   * Redistributions of source code must retain the above copyright
00011 #     notice, this list of conditions and the following disclaimer.
00012 #   * Redistributions in binary form must reproduce the above
00013 #     copyright notice, this list of conditions and the following
00014 #     disclaimer in the documentation and/or other materials provided
00015 #     with the distribution.
00016 #   * Neither the name of the TU Darmstadt nor the names of its
00017 #     contributors may be used to endorse or promote products derived
00018 #     from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 
00033 from __future__ import print_function
00034 
00035 from argparse import ArgumentParser, SUPPRESS
00036 import os
00037 import platform
00038 import signal
00039 import sys
00040 
00041 
00042 class Main(object):
00043 
00044     main_filename = None
00045 
00046     def __init__(self, qtgui_path, invoked_filename=None, settings_filename=None):
00047         self._qtgui_path = qtgui_path
00048         if invoked_filename is None:
00049             invoked_filename = os.path.abspath(__file__)
00050         Main.main_filename = invoked_filename
00051         if settings_filename is None:
00052             settings_filename = 'qt_gui'
00053         self._settings_filename = settings_filename
00054 
00055         self.plugin_providers = []
00056         self._options = None
00057 
00058         # check if DBus is available
00059         self._dbus_available = False
00060         try:
00061             # use qt/glib mainloop integration to get dbus mainloop working
00062             from dbus.mainloop.glib import DBusGMainLoop
00063             DBusGMainLoop(set_as_default=True)
00064             import dbus
00065             try:
00066                 # before being able to check if a session bus is available the dbus mainloop must be set up
00067                 dbus.SessionBus()
00068                 self._dbus_available = True
00069             except dbus.exceptions.DBusException:
00070                 pass
00071         except ImportError:
00072             pass
00073 
00074     def add_arguments(self, parser, standalone=False, plugin_argument_provider=None):
00075         common_group = parser.add_argument_group('Options for GUI instance')
00076         common_group.add_argument('-b', '--qt-binding', dest='qt_binding', type=str, metavar='BINDING',
00077             help='choose Qt bindings to be used [pyqt|pyside]')
00078         common_group.add_argument('--clear-config', dest='clear_config', default=False, action='store_true',
00079             help='clear the configuration (including all perspectives and plugin settings)')
00080         if not standalone:
00081             common_group.add_argument('-f', '--freeze-layout', dest='freeze_layout', action='store_true',
00082                 help='freeze the layout of the GUI (prevent rearranging widgets, disable undock/redock)')
00083         common_group.add_argument('--force-discover', dest='force_discover', default=False, action='store_true',
00084             help='force a rediscover of plugins')
00085         common_group.add_argument('-h', '--help', action='help',
00086             help='show this help message and exit')
00087         if not standalone:
00088             common_group.add_argument('-l', '--lock-perspective', dest='lock_perspective', action='store_true',
00089                 help='lock the GUI to the used perspective (hide menu bar and close buttons of plugins)')
00090             common_group.add_argument('-m', '--multi-process', dest='multi_process', default=False, action='store_true',
00091                 help='use separate processes for each plugin instance (currently only supported under X11)')
00092             common_group.add_argument('-p', '--perspective', dest='perspective', type=str, metavar='PERSPECTIVE',
00093                 help='start with this named perspective')
00094             common_group.add_argument('--perspective-file', dest='perspective_file', type=str, metavar='PERSPECTIVE_FILE',
00095                 help='start with a perspective loaded from a file')
00096         common_group.add_argument('--reload-import', dest='reload_import', default=False, action='store_true',
00097             help='reload every imported module')
00098         if not standalone:
00099             common_group.add_argument('-s', '--standalone', dest='standalone_plugin', type=str, metavar='PLUGIN',
00100                 help='start only this plugin (implies -l). To pass arguments to the plugin use --args')
00101         common_group.add_argument('-t', '--on-top', dest='on_top', default=False, action='store_true',
00102             help='set window mode to always on top')
00103         common_group.add_argument('-v', '--verbose', dest='verbose', default=False, action='store_true',
00104             help='output qDebug messages')
00105 
00106         if not standalone:
00107             common_group.add_argument('--args', dest='plugin_args', nargs='*', type=str,
00108                 help='arbitrary arguments which are passes to the plugin (only with -s, --command-start-plugin or --embed-plugin). It must be the last option since it collects all following options.')
00109 
00110             group = parser.add_argument_group('Options to query information without starting a GUI instance',
00111                 'These options can be used to query information about valid arguments for various options.')
00112             group.add_argument('--list-perspectives', dest='list_perspectives', action='store_true',
00113                 help='list available perspectives')
00114             group.add_argument('--list-plugins', dest='list_plugins', action='store_true',
00115                 help='list available plugins')
00116             parser.add_argument_group(group)
00117 
00118             group = parser.add_argument_group('Options to operate on a running GUI instance',
00119                 'These options can be used to perform actions on a running GUI instance.')
00120             group.add_argument('--command-pid', dest='command_pid', type=int, metavar='PID',
00121                 help='pid of the GUI instance to operate on, defaults to oldest running GUI instance')
00122             group.add_argument('--command-start-plugin', dest='command_start_plugin', type=str, metavar='PLUGIN',
00123                 help='start plugin')
00124             group.add_argument('--command-switch-perspective', dest='command_switch_perspective', type=str, metavar='PERSPECTIVE',
00125                 help='switch perspective')
00126             if not self._dbus_available:
00127                 group.description = 'These options are not available since DBus is available!'
00128                 for o in group._group_actions:
00129                     o.help = SUPPRESS
00130             parser.add_argument_group(group)
00131 
00132             group = parser.add_argument_group('Special options for embedding widgets from separate processes',
00133                 'These options should never be used on the CLI but only from the GUI code itself.')
00134             group.add_argument('--embed-plugin', dest='embed_plugin', type=str, metavar='PLUGIN',
00135                 help='embed a plugin into an already running GUI instance (requires all other --embed-* options)')
00136             group.add_argument('--embed-plugin-serial', dest='embed_plugin_serial', type=int, metavar='SERIAL',
00137                 help='serial number of plugin to be embedded (requires all other --embed-* options)')
00138             group.add_argument('--embed-plugin-address', dest='embed_plugin_address', type=str, metavar='ADDRESS',
00139                 help='dbus server address of the GUI instance to embed plugin into (requires all other --embed-* options)')
00140             for o in group._group_actions:
00141                 o.help = SUPPRESS
00142             parser.add_argument_group(group)
00143 
00144         if plugin_argument_provider:
00145             plugin_argument_provider(parser)
00146 
00147         return common_group
00148 
00149     def _add_plugin_providers(self):
00150         pass
00151 
00152     def _add_reload_paths(self, reload_importer):
00153         reload_importer.add_reload_path(os.path.join(os.path.dirname(__file__), *('..',) * 4))
00154 
00155     def _check_icon_theme_compliance(self):
00156         from python_qt_binding.QtGui import QIcon
00157         # TODO find a better way to verify Theme standard compliance
00158         if QIcon.themeName() == '' or \
00159            QIcon.fromTheme('document-save').isNull() or \
00160            QIcon.fromTheme('document-open').isNull() or \
00161            QIcon.fromTheme('edit-cut').isNull() or \
00162            QIcon.fromTheme('object-flip-horizontal').isNull():
00163             if 'darwin' in platform.platform().lower() and '/usr/local/share/icons' not in QIcon.themeSearchPaths():
00164                 QIcon.setThemeSearchPaths(QIcon.themeSearchPaths() + ['/usr/local/share/icons'])
00165             original_theme = QIcon.themeName()
00166             QIcon.setThemeName('Tango')
00167             if QIcon.fromTheme('document-save').isNull():
00168                 QIcon.setThemeName(original_theme)
00169 
00170     def create_application(self, argv):
00171         from python_qt_binding.QtCore import Qt
00172         from python_qt_binding.QtGui import QApplication
00173         app = QApplication(argv)
00174         app.setAttribute(Qt.AA_DontShowIconsInMenus, False)
00175         return app
00176 
00177     def main(self, argv=None, standalone=None, plugin_argument_provider=None, plugin_manager_settings_prefix=''):
00178         if argv is None:
00179             argv = sys.argv
00180 
00181         # extract --args and everything behind manually since argparse can not handle that
00182         arguments = argv[1:]
00183 
00184         # extract plugin specific args when not being invoked in standalone mode programmatically
00185         if not standalone:
00186             plugin_args = []
00187             if '--args' in arguments:
00188                 index = arguments.index('--args')
00189                 plugin_args = arguments[index + 1:]
00190                 arguments = arguments[0:index + 1]
00191 
00192         parser = ArgumentParser(os.path.basename(Main.main_filename), add_help=False)
00193         self.add_arguments(parser, standalone=bool(standalone), plugin_argument_provider=plugin_argument_provider)
00194         self._options = parser.parse_args(arguments)
00195 
00196         if standalone:
00197             # rerun parsing to separate common arguments from plugin specific arguments
00198             parser = ArgumentParser(os.path.basename(Main.main_filename), add_help=False)
00199             self.add_arguments(parser, standalone=bool(standalone))
00200             self._options, plugin_args = parser.parse_known_args(arguments)
00201         self._options.plugin_args = plugin_args
00202 
00203         # set default values for options not available in standalone mode
00204         if standalone:
00205             self._options.freeze_layout = False
00206             self._options.lock_perspective = False
00207             self._options.multi_process = False
00208             self._options.perspective = None
00209             self._options.perspective_file = None
00210             self._options.standalone_plugin = standalone
00211             self._options.list_perspectives = False
00212             self._options.list_plugins = False
00213             self._options.command_pid = None
00214             self._options.command_start_plugin = None
00215             self._options.command_switch_perspective = None
00216             self._options.embed_plugin = None
00217             self._options.embed_plugin_serial = None
00218             self._options.embed_plugin_address = None
00219 
00220         # check option dependencies
00221         try:
00222             if self._options.plugin_args and not self._options.standalone_plugin and not self._options.command_start_plugin and not self._options.embed_plugin:
00223                 raise RuntimeError('Option --args can only be used together with either --standalone, --command-start-plugin or --embed-plugin option')
00224 
00225             if self._options.freeze_layout and not self._options.lock_perspective:
00226                 raise RuntimeError('Option --freeze_layout can only be used together with the --lock_perspective option')
00227 
00228             list_options = (self._options.list_perspectives, self._options.list_plugins)
00229             list_options_set = [opt for opt in list_options if opt is not False]
00230             if len(list_options_set) > 1:
00231                 raise RuntimeError('Only one --list-* option can be used at a time')
00232 
00233             command_options = (self._options.command_start_plugin, self._options.command_switch_perspective)
00234             command_options_set = [opt for opt in command_options if opt is not None]
00235             if len(command_options_set) > 0 and not self._dbus_available:
00236                 raise RuntimeError('Without DBus support the --command-* options are not available')
00237             if len(command_options_set) > 1:
00238                 raise RuntimeError('Only one --command-* option can be used at a time (except --command-pid which is optional)')
00239             if len(command_options_set) == 0 and self._options.command_pid is not None:
00240                 raise RuntimeError('Option --command_pid can only be used together with an other --command-* option')
00241 
00242             embed_options = (self._options.embed_plugin, self._options.embed_plugin_serial, self._options.embed_plugin_address)
00243             embed_options_set = [opt for opt in embed_options if opt is not None]
00244             if len(command_options_set) > 0 and not self._dbus_available:
00245                 raise RuntimeError('Without DBus support the --embed-* options are not available')
00246             if len(embed_options_set) > 0 and len(embed_options_set) < len(embed_options):
00247                 raise RuntimeError('Missing option(s) - all \'--embed-*\' options must be set')
00248 
00249             if len(embed_options_set) > 0 and self._options.clear_config:
00250                 raise RuntimeError('Option --clear-config can only be used without any --embed-* option')
00251 
00252             groups = (list_options_set, command_options_set, embed_options_set)
00253             groups_set = [opt for opt in groups if len(opt) > 0]
00254             if len(groups_set) > 1:
00255                 raise RuntimeError('Options from different groups (--list, --command, --embed) can not be used together')
00256 
00257             perspective_options = (self._options.perspective, self._options.perspective_file)
00258             perspective_options_set = [opt for opt in perspective_options if opt is not None]
00259             if len(perspective_options_set) > 1:
00260                 raise RuntimeError('Only one --perspective-* option can be used at a time')
00261 
00262             if self._options.perspective_file is not None and not os.path.isfile(self._options.perspective_file):
00263                 raise RuntimeError('Option --perspective-file must reference existing file')
00264 
00265         except RuntimeError as e:
00266             print(str(e))
00267             #parser.parse_args(['--help'])
00268             # calling --help will exit
00269             return 1
00270 
00271         # set implicit option dependencies
00272         if self._options.standalone_plugin is not None:
00273             self._options.lock_perspective = True
00274 
00275         # create application context containing various relevant information
00276         from .application_context import ApplicationContext
00277         context = ApplicationContext()
00278         context.qtgui_path = self._qtgui_path
00279         context.options = self._options
00280 
00281         if self._dbus_available:
00282             from dbus import DBusException, Interface, SessionBus
00283 
00284         # non-special applications provide various dbus interfaces
00285         if self._dbus_available:
00286             context.provide_app_dbus_interfaces = len(groups_set) == 0
00287             context.dbus_base_bus_name = 'org.ros.qt_gui'
00288             if context.provide_app_dbus_interfaces:
00289                 context.dbus_unique_bus_name = context.dbus_base_bus_name + '.pid%d' % os.getpid()
00290 
00291                 # provide pid of application via dbus
00292                 from .application_dbus_interface import ApplicationDBusInterface
00293                 _dbus_server = ApplicationDBusInterface(context.dbus_base_bus_name)
00294 
00295         # determine host bus name, either based on pid given on command line or via dbus application interface if any other instance is available
00296         if len(command_options_set) > 0 or len(embed_options_set) > 0:
00297             host_pid = None
00298             if self._options.command_pid is not None:
00299                 host_pid = self._options.command_pid
00300             else:
00301                 try:
00302                     remote_object = SessionBus().get_object(context.dbus_base_bus_name, '/Application')
00303                 except DBusException:
00304                     pass
00305                 else:
00306                     remote_interface = Interface(remote_object, context.dbus_base_bus_name + '.Application')
00307                     host_pid = remote_interface.get_pid()
00308             if host_pid is not None:
00309                 context.dbus_host_bus_name = context.dbus_base_bus_name + '.pid%d' % host_pid
00310 
00311         # execute command on host application instance
00312         if len(command_options_set) > 0:
00313             if self._options.command_start_plugin is not None:
00314                 try:
00315                     remote_object = SessionBus().get_object(context.dbus_host_bus_name, '/PluginManager')
00316                 except DBusException:
00317                     (rc, msg) = (1, 'unable to communicate with GUI instance "%s"' % context.dbus_host_bus_name)
00318                 else:
00319                     remote_interface = Interface(remote_object, context.dbus_base_bus_name + '.PluginManager')
00320                     (rc, msg) = remote_interface.start_plugin(self._options.command_start_plugin, ' '.join(self._options.plugin_args))
00321                 if rc == 0:
00322                     print('qt_gui_main() started plugin "%s" in GUI "%s"' % (msg, context.dbus_host_bus_name))
00323                 else:
00324                     print('qt_gui_main() could not start plugin "%s" in GUI "%s": %s' % (self._options.command_start_plugin, context.dbus_host_bus_name, msg))
00325                 return rc
00326             elif self._options.command_switch_perspective is not None:
00327                 remote_object = SessionBus().get_object(context.dbus_host_bus_name, '/PerspectiveManager')
00328                 remote_interface = Interface(remote_object, context.dbus_base_bus_name + '.PerspectiveManager')
00329                 remote_interface.switch_perspective(self._options.command_switch_perspective)
00330                 print('qt_gui_main() switched to perspective "%s" in GUI "%s"' % (self._options.command_switch_perspective, context.dbus_host_bus_name))
00331                 return 0
00332             raise RuntimeError('Unknown command not handled')
00333 
00334         # choose selected or default qt binding
00335         setattr(sys, 'SELECT_QT_BINDING', self._options.qt_binding)
00336         from python_qt_binding import QT_BINDING
00337 
00338         from python_qt_binding.QtCore import qDebug, qInstallMsgHandler, QSettings, Qt, QtCriticalMsg, QtDebugMsg, QtFatalMsg, QTimer, QtWarningMsg
00339         from python_qt_binding.QtGui import QAction, QIcon, QMenuBar
00340 
00341         from .about_handler import AboutHandler
00342         from .composite_plugin_provider import CompositePluginProvider
00343         from .container_manager import ContainerManager
00344         from .help_provider import HelpProvider
00345         from .main_window import MainWindow
00346         from .minimized_dock_widgets_toolbar import MinimizedDockWidgetsToolbar
00347         from .perspective_manager import PerspectiveManager
00348         from .plugin_manager import PluginManager
00349 
00350         def message_handler(type_, msg):
00351             colored_output = 'TERM' in os.environ and 'ANSI_COLORS_DISABLED' not in os.environ
00352             cyan_color = '\033[36m' if colored_output else ''
00353             red_color = '\033[31m' if colored_output else ''
00354             reset_color = '\033[0m' if colored_output else ''
00355             if type_ == QtDebugMsg and self._options.verbose:
00356                 print(msg, file=sys.stderr)
00357             elif type_ == QtWarningMsg:
00358                 print(cyan_color + msg + reset_color, file=sys.stderr)
00359             elif type_ == QtCriticalMsg:
00360                 print(red_color + msg + reset_color, file=sys.stderr)
00361             elif type_ == QtFatalMsg:
00362                 print(red_color + msg + reset_color, file=sys.stderr)
00363                 sys.exit(1)
00364         qInstallMsgHandler(message_handler)
00365 
00366         app = self.create_application(argv)
00367 
00368         self._check_icon_theme_compliance()
00369 
00370         settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'ros.org', self._settings_filename)
00371         if len(embed_options_set) == 0:
00372             if self._options.clear_config:
00373                 settings.clear()
00374 
00375             main_window = MainWindow()
00376             if self._options.on_top:
00377                 main_window.setWindowFlags(Qt.WindowStaysOnTopHint)
00378 
00379             main_window.statusBar()
00380 
00381             def sigint_handler(*args):
00382                 qDebug('\nsigint_handler()')
00383                 main_window.close()
00384             signal.signal(signal.SIGINT, sigint_handler)
00385             # the timer enables triggering the sigint_handler
00386             timer = QTimer()
00387             timer.start(500)
00388             timer.timeout.connect(lambda: None)
00389 
00390             # create own menu bar to share one menu bar on Mac
00391             menu_bar = QMenuBar()
00392             if 'darwin' in platform.platform().lower():
00393                 menu_bar.setNativeMenuBar(True)
00394             else:
00395                 menu_bar.setNativeMenuBar(False)
00396             if not self._options.lock_perspective:
00397                 main_window.setMenuBar(menu_bar)
00398 
00399             file_menu = menu_bar.addMenu(menu_bar.tr('&File'))
00400             action = QAction(file_menu.tr('&Quit'), file_menu)
00401             action.setIcon(QIcon.fromTheme('application-exit'))
00402             action.triggered.connect(main_window.close)
00403             file_menu.addAction(action)
00404 
00405         else:
00406             app.setQuitOnLastWindowClosed(False)
00407 
00408             main_window = None
00409             menu_bar = None
00410 
00411         self._add_plugin_providers()
00412 
00413         # setup plugin manager
00414         plugin_provider = CompositePluginProvider(self.plugin_providers)
00415         plugin_manager = PluginManager(plugin_provider, settings, context, settings_prefix=plugin_manager_settings_prefix)
00416 
00417         if self._options.list_plugins:
00418             # output available plugins
00419             print('\n'.join(sorted(plugin_manager.get_plugins().values())))
00420             return 0
00421 
00422         help_provider = HelpProvider()
00423         plugin_manager.plugin_help_signal.connect(help_provider.plugin_help_request)
00424 
00425         # setup perspective manager
00426         if main_window is not None:
00427             perspective_manager = PerspectiveManager(settings, context)
00428 
00429             if self._options.list_perspectives:
00430                 # output available perspectives
00431                 print('\n'.join(sorted(perspective_manager.perspectives)))
00432                 return 0
00433         else:
00434             perspective_manager = None
00435 
00436         if main_window is not None:
00437             container_manager = ContainerManager(main_window, plugin_manager)
00438             plugin_manager.set_main_window(main_window, menu_bar, container_manager)
00439 
00440             if not self._options.freeze_layout:
00441                 minimized_dock_widgets_toolbar = MinimizedDockWidgetsToolbar(container_manager, main_window)
00442                 main_window.addToolBar(Qt.BottomToolBarArea, minimized_dock_widgets_toolbar)
00443                 plugin_manager.set_minimized_dock_widgets_toolbar(minimized_dock_widgets_toolbar)
00444 
00445         if menu_bar is not None:
00446             perspective_menu = menu_bar.addMenu(menu_bar.tr('P&erspectives'))
00447             perspective_manager.set_menu(perspective_menu)
00448 
00449         # connect various signals and slots
00450         if perspective_manager is not None and main_window is not None:
00451             # signal changed perspective to update window title
00452             perspective_manager.perspective_changed_signal.connect(main_window.perspective_changed)
00453             # signal new settings due to changed perspective
00454             perspective_manager.save_settings_signal.connect(main_window.save_settings)
00455             perspective_manager.restore_settings_signal.connect(main_window.restore_settings)
00456             perspective_manager.restore_settings_without_plugin_changes_signal.connect(main_window.restore_settings)
00457 
00458         if perspective_manager is not None and plugin_manager is not None:
00459             perspective_manager.save_settings_signal.connect(plugin_manager.save_settings)
00460             plugin_manager.save_settings_completed_signal.connect(perspective_manager.save_settings_completed)
00461             perspective_manager.restore_settings_signal.connect(plugin_manager.restore_settings)
00462             perspective_manager.restore_settings_without_plugin_changes_signal.connect(plugin_manager.restore_settings_without_plugins)
00463 
00464         if plugin_manager is not None and main_window is not None:
00465             # signal before changing plugins to save window state
00466             plugin_manager.plugins_about_to_change_signal.connect(main_window.save_setup)
00467             # signal changed plugins to restore window state
00468             plugin_manager.plugins_changed_signal.connect(main_window.restore_state)
00469             # signal save settings to store plugin setup on close
00470             main_window.save_settings_before_close_signal.connect(plugin_manager.close_application)
00471             # signal save and shutdown called for all plugins, trigger closing main window again
00472             plugin_manager.close_application_signal.connect(main_window.close, type=Qt.QueuedConnection)
00473 
00474         if main_window is not None and menu_bar is not None:
00475             about_handler = AboutHandler(context.qtgui_path, main_window)
00476             help_menu = menu_bar.addMenu(menu_bar.tr('&Help'))
00477             action = QAction(file_menu.tr('&About'), help_menu)
00478             action.setIcon(QIcon.fromTheme('help-about'))
00479             action.triggered.connect(about_handler.show)
00480             help_menu.addAction(action)
00481 
00482         # set initial size - only used without saved configuration
00483         if main_window is not None:
00484             main_window.resize(600, 450)
00485             main_window.move(100, 100)
00486 
00487         # ensure that qt_gui/src is in sys.path
00488         src_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
00489         if src_path not in sys.path:
00490             sys.path.append(src_path)
00491 
00492         # load specific plugin
00493         plugin = None
00494         plugin_serial = None
00495         if self._options.embed_plugin is not None:
00496             plugin = self._options.embed_plugin
00497             plugin_serial = self._options.embed_plugin_serial
00498         elif self._options.standalone_plugin is not None:
00499             plugin = self._options.standalone_plugin
00500             plugin_serial = 0
00501         if plugin is not None:
00502             plugins = plugin_manager.find_plugins_by_name(plugin)
00503             if len(plugins) == 0:
00504                 print('qt_gui_main() found no plugin matching "%s"' % plugin)
00505                 return 1
00506             elif len(plugins) > 1:
00507                 print('qt_gui_main() found multiple plugins matching "%s"\n%s' % (plugin, '\n'.join(plugins.values())))
00508                 return 1
00509             plugin = plugins.keys()[0]
00510 
00511         qDebug('QtBindingHelper using %s' % QT_BINDING)
00512 
00513         plugin_manager.discover()
00514 
00515         if self._options.reload_import:
00516             qDebug('ReloadImporter() automatically reload all subsequent imports')
00517             from .reload_importer import ReloadImporter
00518             _reload_importer = ReloadImporter()
00519             self._add_reload_paths(_reload_importer)
00520             _reload_importer.enable()
00521 
00522         # switch perspective
00523         if perspective_manager is not None:
00524             if plugin:
00525                 perspective_manager.set_perspective(plugin, hide_and_without_plugin_changes=True)
00526             elif self._options.perspective_file:
00527                 perspective_manager.import_perspective_from_file(self._options.perspective_file, perspective_manager.HIDDEN_PREFIX + '__cli_perspective_from_file')
00528             else:
00529                 perspective_manager.set_perspective(self._options.perspective)
00530 
00531         # load specific plugin
00532         if plugin:
00533             plugin_manager.load_plugin(plugin, plugin_serial, self._options.plugin_args)
00534             running = plugin_manager.is_plugin_running(plugin, plugin_serial)
00535             if not running:
00536                 return 1
00537 
00538         if main_window is not None:
00539             main_window.show()
00540             if sys.platform == 'darwin':
00541                 main_window.raise_()
00542 
00543         return app.exec_()
00544 
00545 
00546 if __name__ == '__main__':
00547     main = Main()
00548     sys.exit(main.main())


qt_gui
Author(s): Dirk Thomas
autogenerated on Mon Oct 6 2014 03:57:52