def __init__(self, application):
        self.qt_application = application
        #self.qt_application.aboutToQuit.connect(self.destroy)
        self._relaunch = False
        self.exiting = False
        self.exit_complete = False

        logger.info('Loading BLACS ui')
        #self.ui = BLACSWindow(self).ui
        loader = UiLoader()
        loader.registerCustomWidget(QueueTreeview)
        #loader.registerCustomPromotion('BLACS',BLACSWindow)
        self.ui = loader.load(
            os.path.join(os.path.dirname(os.path.realpath(__file__)),
                         'main.ui'), BLACSWindow())
        logger.info('BLACS ui loaded')
        self.ui.blacs = self
        self.tab_widgets = {}
        self.exp_config = exp_config  # Global variable
        self.settings_path = settings_path  # Global variable
        self.connection_table = connection_table  # Global variable
        self.connection_table_h5file = self.exp_config.get(
            'paths', 'connection_table_h5')
        self.connection_table_labscript = self.exp_config.get(
            'paths', 'connection_table_py')

        # Setup the UI
        self.ui.main_splitter.setStretchFactor(0, 0)
        self.ui.main_splitter.setStretchFactor(1, 1)

        self.tablist = {}
        self.panes = {}
        self.settings_dict = {}

        # Setup progressbar monitoring status queue
        self.ui.TimeNext_progressBar.setRange(0, 100)

        self._countdown_queue = Queue.Queue()
        Queue_Receiver = QueueToSignal(self._countdown_queue)
        Queue_Receiver.mysignal.connect(self.ui.TimeNext_progressBar.setValue)
        thread = QThread()
        Queue_Receiver.moveToThread(thread)
        thread.started.connect(Queue_Receiver.run)
        thread.start()

        # Find which devices are connected to BLACS, and what their labscript class names are:
        logger.info('finding connected devices in connection table')
        self.attached_devices = self.connection_table.get_attached_devices()

        # Store the panes in a dictionary for easy access
        self.panes[
            'tab_top_vertical_splitter'] = self.ui.tab_top_vertical_splitter
        self.panes[
            'tab_bottom_vertical_splitter'] = self.ui.tab_bottom_vertical_splitter
        self.panes['tab_horizontal_splitter'] = self.ui.tab_horizontal_splitter
        self.panes['main_splitter'] = self.ui.main_splitter

        # Get settings to restore
        logger.info('Loading front panel settings')
        self.front_panel_settings = FrontPanelSettings(self.settings_path,
                                                       self.connection_table)
        self.front_panel_settings.setup(self)
        settings, question, error, tab_data = self.front_panel_settings.restore(
        )

        # TODO: handle question/error cases

        logger.info('restoring window data')
        self.restore_window(tab_data)

        #splash.update_text('Creating the device tabs...')
        # Create the notebooks
        logger.info('Creating tab widgets')
        for i in range(4):
            self.tab_widgets[i] = DragDropTabWidget(self.tab_widget_ids)
            getattr(self.ui,
                    'tab_container_%d' % i).addWidget(self.tab_widgets[i])

        logger.info('Instantiating devices')
        for device_name, labscript_device_class_name in self.attached_devices.items(
        ):
            self.settings_dict.setdefault(device_name,
                                          {"device_name": device_name})
            # add common keys to settings:
            self.settings_dict[device_name][
                "connection_table"] = self.connection_table
            self.settings_dict[device_name]["front_panel_settings"] = settings[
                device_name] if device_name in settings else {}
            self.settings_dict[device_name]["saved_data"] = tab_data[
                device_name]['data'] if device_name in tab_data else {}
            # Instantiate the device
            logger.info('instantiating %s' % device_name)
            TabClass = labscript_devices.get_BLACS_tab(
                labscript_device_class_name)
            self.tablist[device_name] = TabClass(
                self.tab_widgets[0], self.settings_dict[device_name])

        logger.info('reordering tabs')
        self.order_tabs(tab_data)

        logger.info('starting analysis submission thread')
        # setup analysis submission
        self.analysis_submission = AnalysisSubmission(self, self.ui)
        if 'analysis_data' not in tab_data['BLACS settings']:
            tab_data['BLACS settings']['analysis_data'] = {}
        else:
            tab_data['BLACS settings']['analysis_data'] = eval(
                tab_data['BLACS settings']['analysis_data'])
        self.analysis_submission.restore_save_data(
            tab_data['BLACS settings']["analysis_data"])

        logger.info('starting queue manager thread')
        # Setup the QueueManager
        self.queue = QueueManager(self, self.ui)
        if 'queue_data' not in tab_data['BLACS settings']:
            tab_data['BLACS settings']['queue_data'] = {}
        else:
            tab_data['BLACS settings']['queue_data'] = eval(
                tab_data['BLACS settings']['queue_data'])
        self.queue.restore_save_data(tab_data['BLACS settings']['queue_data'])

        logger.info('instantiating plugins')
        # setup the plugin system
        settings_pages = []
        self.plugins = {}
        plugin_settings = eval(
            tab_data['BLACS settings']['plugin_data']
        ) if 'plugin_data' in tab_data['BLACS settings'] else {}
        for module_name, module in plugins.modules.items():
            try:
                # instantiate the plugin
                self.plugins[module_name] = module.Plugin(
                    plugin_settings[module_name] if module_name in
                    plugin_settings else {})
            except Exception:
                logger.exception(
                    'Could not instantiate plugin \'%s\'. Skipping')

        blacs_data = {
            'exp_config': self.exp_config,
            'ui': self.ui,
            'set_relaunch': self.set_relaunch,
            'plugins': self.plugins,
            'connection_table_h5file': self.connection_table_h5file,
            'connection_table_labscript': self.connection_table_labscript,
            'experiment_queue': self.queue
        }

        def create_menu(parent, menu_parameters):
            if 'name' in menu_parameters:
                if 'menu_items' in menu_parameters:
                    child = parent.addMenu(menu_parameters['name'])
                    for child_menu_params in menu_parameters['menu_items']:
                        create_menu(child, child_menu_params)
                else:
                    child = parent.addAction(menu_parameters['name'])

                if 'action' in menu_parameters:
                    child.triggered.connect(menu_parameters['action'])

            elif 'separator' in menu_parameters:
                parent.addSeparator()

        # setup the Notification system
        logger.info('setting up notification system')
        self.notifications = Notifications(blacs_data)

        settings_callbacks = []
        for module_name, plugin in self.plugins.items():
            try:
                # Setup settings page
                settings_pages.extend(plugin.get_setting_classes())
                # Setup menu
                if plugin.get_menu_class():
                    # must store a reference or else the methods called when the menu actions are triggered
                    # (contained in this object) will be garbaged collected
                    menu = plugin.get_menu_class()(blacs_data)
                    create_menu(self.ui.menubar, menu.get_menu_items())
                    plugin.set_menu_instance(menu)

                # Setup notifications
                plugin_notifications = {}
                for notification_class in plugin.get_notification_classes():
                    self.notifications.add_notification(notification_class)
                    plugin_notifications[
                        notification_class] = self.notifications.get_instance(
                            notification_class)
                plugin.set_notification_instances(plugin_notifications)

                # Register callbacks
                callbacks = plugin.get_callbacks()
                # save the settings_changed callback in a separate list for setting up later
                if isinstance(callbacks,
                              dict) and 'settings_changed' in callbacks:
                    settings_callbacks.append(callbacks['settings_changed'])

            except Exception:
                logger.exception(
                    'Plugin \'%s\' error. Plugin may not be functional.' %
                    module_name)

        # setup the BLACS preferences system
        logger.info('setting up preferences system')
        self.settings = Settings(file=self.settings_path,
                                 parent=self.ui,
                                 page_classes=settings_pages)
        for callback in settings_callbacks:
            self.settings.register_callback(callback)

        # update the blacs_data dictionary with the settings system
        blacs_data['settings'] = self.settings

        for module_name, plugin in self.plugins.items():
            try:
                plugin.plugin_setup_complete(blacs_data)
            except Exception:
                # backwards compatibility for old plugins
                try:
                    plugin.plugin_setup_complete()
                    logger.warning(
                        'Plugin \'%s\' using old API. Please update Plugin.plugin_setup_complete method to accept a dictionary of blacs_data as the only argument.'
                        % module_name)
                except Exception:
                    logger.exception(
                        'Plugin \'%s\' error. Plugin may not be functional.' %
                        module_name)

        # Connect menu actions
        self.ui.actionOpenPreferences.triggered.connect(
            self.on_open_preferences)
        self.ui.actionSave.triggered.connect(self.on_save_front_panel)
        self.ui.actionOpen.triggered.connect(self.on_load_front_panel)

        # Connect the windows AppId stuff:
        if os.name == 'nt':
            self.ui.newWindow.connect(set_win_appusermodel)

        logger.info('showing UI')
        self.ui.show()
コード例 #2
0
    def __init__(self, application):
        splash.update_text('loading graphical interface')
        self.qt_application = application
        #self.qt_application.aboutToQuit.connect(self.destroy)
        self._relaunch = False
        self.exiting = False
        self.exit_complete = False

        logger.info('Loading BLACS ui')
        #self.ui = BLACSWindow(self).ui
        loader = UiLoader()
        loader.registerCustomWidget(QueueTreeview)
        #loader.registerCustomPromotion('BLACS',BLACSWindow)
        self.ui = loader.load(os.path.join(BLACS_DIR, 'main.ui'),
                              BLACSWindow())
        logger.info('BLACS ui loaded')
        self.ui.blacs = self
        self.tab_widgets = {}
        self.exp_config = exp_config  # Global variable
        self.settings_path = settings_path  # Global variable
        self.connection_table = connection_table  # Global variable
        self.connection_table_h5file = self.exp_config.get(
            'paths', 'connection_table_h5')
        self.connection_table_labscript = self.exp_config.get(
            'paths', 'connection_table_py')

        # Setup the UI
        self.ui.main_splitter.setStretchFactor(0, 0)
        self.ui.main_splitter.setStretchFactor(1, 1)

        self.tablist = {}
        self.panes = {}
        self.settings_dict = {}

        splash.update_text('loading device front panel settings')
        # Find which devices are connected to BLACS, and what their labscript class names are:
        logger.info('finding connected devices in connection table')
        self.attached_devices = self.connection_table.get_attached_devices()

        # Store the panes in a dictionary for easy access
        self.panes[
            'tab_top_vertical_splitter'] = self.ui.tab_top_vertical_splitter
        self.panes[
            'tab_bottom_vertical_splitter'] = self.ui.tab_bottom_vertical_splitter
        self.panes['tab_horizontal_splitter'] = self.ui.tab_horizontal_splitter
        self.panes['main_splitter'] = self.ui.main_splitter

        # Get settings to restore
        logger.info('Loading front panel settings')
        self.front_panel_settings = FrontPanelSettings(self.settings_path,
                                                       self.connection_table)
        self.front_panel_settings.setup(self)
        settings, question, error, tab_data = self.front_panel_settings.restore(
        )

        # TODO: handle question/error cases

        logger.info('restoring window data')
        self.restore_window(tab_data)

        splash.update_text('creating device tabs...')
        # Create the notebooks
        logger.info('Creating tab widgets')
        for i in range(4):
            self.tab_widgets[i] = DragDropTabWidget(self.tab_widget_ids)
            self.tab_widgets[i].setElideMode(Qt.ElideRight)
            getattr(self.ui,
                    'tab_container_%d' % i).addWidget(self.tab_widgets[i])

        logger.info('Instantiating devices')
        self.failed_device_settings = {}
        for device_name, labscript_device_class_name in list(
                self.attached_devices.items()):
            try:
                self.settings_dict.setdefault(device_name,
                                              {"device_name": device_name})
                # add common keys to settings:
                self.settings_dict[device_name][
                    "connection_table"] = self.connection_table
                self.settings_dict[device_name][
                    "front_panel_settings"] = settings[
                        device_name] if device_name in settings else {}
                self.settings_dict[device_name]["saved_data"] = tab_data[
                    device_name]['data'] if device_name in tab_data else {}
                # Instantiate the device
                logger.info('instantiating %s' % device_name)
                TabClass = labscript_devices.get_BLACS_tab(
                    labscript_device_class_name)
                self.tablist[device_name] = TabClass(
                    self.tab_widgets[0], self.settings_dict[device_name])
            except Exception:
                self.failed_device_settings[device_name] = {
                    "front_panel":
                    self.settings_dict[device_name]["front_panel_settings"],
                    "save_data":
                    self.settings_dict[device_name]["saved_data"]
                }
                del self.settings_dict[device_name]
                del self.attached_devices[device_name]
                self.connection_table.remove_device(device_name)
                raise_exception_in_thread(sys.exc_info())

        splash.update_text('instantiating plugins')
        logger.info('Instantiating plugins')
        # setup the plugin system
        settings_pages = []
        self.plugins = {}
        plugin_settings = eval(
            tab_data['BLACS settings']['plugin_data']
        ) if 'plugin_data' in tab_data['BLACS settings'] else {}
        for module_name, module in plugins.modules.items():
            try:
                # instantiate the plugin
                self.plugins[module_name] = module.Plugin(
                    plugin_settings[module_name] if module_name in
                    plugin_settings else {})
            except Exception:
                logger.exception(
                    'Could not instantiate plugin \'%s\'. Skipping' %
                    module_name)

        logger.info('creating plugin tabs')
        # setup the plugin tabs
        for module_name, plugin in self.plugins.items():
            try:
                if hasattr(plugin, 'get_tab_classes'):
                    tab_dict = {}

                    for tab_name, TabClass in plugin.get_tab_classes().items():
                        settings_key = "{}: {}".format(module_name, tab_name)
                        self.settings_dict.setdefault(settings_key,
                                                      {"tab_name": tab_name})
                        self.settings_dict[settings_key]["front_panel_settings"] = settings[
                            settings_key] if settings_key in settings else {}
                        self.settings_dict[settings_key][
                            "saved_data"] = tab_data[settings_key][
                                'data'] if settings_key in tab_data else {}

                        self.tablist[settings_key] = TabClass(
                            self.tab_widgets[0],
                            self.settings_dict[settings_key])
                        tab_dict[tab_name] = self.tablist[settings_key]

                    if hasattr(plugin, 'tabs_created'):
                        plugin.tabs_created(tab_dict)

            except Exception:
                logger.exception(
                    'Could not instantiate tab for plugin \'%s\'. Skipping')

        logger.info('reordering tabs')
        self.order_tabs(tab_data)

        splash.update_text("initialising analysis submission")
        logger.info('starting analysis submission thread')
        # setup analysis submission
        self.analysis_submission = AnalysisSubmission(self, self.ui)
        if 'analysis_data' not in tab_data['BLACS settings']:
            tab_data['BLACS settings']['analysis_data'] = {}
        else:
            tab_data['BLACS settings']['analysis_data'] = eval(
                tab_data['BLACS settings']['analysis_data'])
        self.analysis_submission.restore_save_data(
            tab_data['BLACS settings']["analysis_data"])

        splash.update_text("starting queue manager")
        logger.info('starting queue manager thread')
        # Setup the QueueManager
        self.queue = QueueManager(self, self.ui)
        if 'queue_data' not in tab_data['BLACS settings']:
            tab_data['BLACS settings']['queue_data'] = {}
        else:
            # quick fix for qt objects not loading that were saved before qtutil 2 changes
            try:
                tab_data['BLACS settings']['queue_data'] = eval(
                    tab_data['BLACS settings']['queue_data'])
            except NameError:
                tab_data['BLACS settings']['queue_data'] = {}
        self.queue.restore_save_data(tab_data['BLACS settings']['queue_data'])

        blacs_data = {
            'exp_config': self.exp_config,
            'ui': self.ui,
            'set_relaunch': self.set_relaunch,
            'plugins': self.plugins,
            'connection_table_h5file': self.connection_table_h5file,
            'connection_table_labscript': self.connection_table_labscript,
            'experiment_queue': self.queue
        }

        def create_menu(parent, menu_parameters):
            if 'name' in menu_parameters:
                if 'menu_items' in menu_parameters:
                    child = parent.addMenu(menu_parameters['name'])
                    for child_menu_params in menu_parameters['menu_items']:
                        create_menu(child, child_menu_params)
                else:
                    if 'icon' in menu_parameters:
                        child = parent.addAction(
                            QIcon(menu_parameters['icon']),
                            menu_parameters['name'])
                    else:
                        child = parent.addAction(menu_parameters['name'])

                if 'action' in menu_parameters:
                    child.triggered.connect(menu_parameters['action'])

            elif 'separator' in menu_parameters:
                parent.addSeparator()

        # setup the Notification system
        logger.info('setting up notification system')
        splash.update_text('setting up notification system')
        self.notifications = Notifications(blacs_data)

        settings_callbacks = []
        for module_name, plugin in self.plugins.items():
            try:
                # Setup settings page
                settings_pages.extend(plugin.get_setting_classes())
                # Setup menu
                if plugin.get_menu_class():
                    # must store a reference or else the methods called when the menu actions are triggered
                    # (contained in this object) will be garbaged collected
                    menu = plugin.get_menu_class()(blacs_data)
                    create_menu(self.ui.menubar, menu.get_menu_items())
                    plugin.set_menu_instance(menu)

                # Setup notifications
                plugin_notifications = {}
                for notification_class in plugin.get_notification_classes():
                    self.notifications.add_notification(notification_class)
                    plugin_notifications[
                        notification_class] = self.notifications.get_instance(
                            notification_class)
                plugin.set_notification_instances(plugin_notifications)

                # Register callbacks
                callbacks = plugin.get_callbacks()
                # save the settings_changed callback in a separate list for setting up later
                if isinstance(callbacks,
                              dict) and 'settings_changed' in callbacks:
                    settings_callbacks.append(callbacks['settings_changed'])

            except Exception:
                logger.exception(
                    'Plugin \'%s\' error. Plugin may not be functional.' %
                    module_name)

        # setup the BLACS preferences system
        splash.update_text('setting up preferences system')
        logger.info('setting up preferences system')
        self.settings = Settings(file=self.settings_path,
                                 parent=self.ui,
                                 page_classes=settings_pages)
        for callback in settings_callbacks:
            self.settings.register_callback(callback)

        # update the blacs_data dictionary with the settings system
        blacs_data['settings'] = self.settings

        for module_name, plugin in self.plugins.items():
            try:
                plugin.plugin_setup_complete(blacs_data)
            except Exception:
                logger.exception(
                    'Error in plugin_setup_complete() for plugin \'%s\'. Trying again with old call signature...'
                    % module_name)
                # backwards compatibility for old plugins
                try:
                    plugin.plugin_setup_complete()
                    logger.warning(
                        'Plugin \'%s\' using old API. Please update Plugin.plugin_setup_complete method to accept a dictionary of blacs_data as the only argument.'
                        % module_name)
                except Exception:
                    logger.exception(
                        'Plugin \'%s\' error. Plugin may not be functional.' %
                        module_name)

        # Connect menu actions
        self.ui.actionOpenPreferences.triggered.connect(
            self.on_open_preferences)
        self.ui.actionSave.triggered.connect(self.on_save_front_panel)
        self.ui.actionOpen.triggered.connect(self.on_load_front_panel)
        self.ui.actionExit.triggered.connect(self.ui.close)

        # Connect the windows AppId stuff:
        if os.name == 'nt':
            self.ui.newWindow.connect(set_win_appusermodel)

        # Add hidden easter egg button to a random tab:
        logger.info('hiding easter eggs')
        import random
        if self.tablist:
            random_tab = random.choice(list(self.tablist.values()))
            self.easter_egg_button = EasterEggButton()
            # Add the button before the other buttons in the tab's header:
            header = random_tab._ui.horizontalLayout
            for i in range(header.count()):
                if isinstance(header.itemAt(i).widget(), QToolButton):
                    header.insertWidget(i, self.easter_egg_button)
                    break

        splash.update_text('done')
        logger.info('showing UI')
        self.ui.show()