self.my_tab.destroy() self.are_we_closed = True QTimer.singleShot(1000, self.close) else: if not self.my_tab.destroy_complete: QTimer.singleShot(1000, self.close) else: event.accept() def add_my_tab(self, tab): self.my_tab = tab app = QApplication(sys.argv) window = MyWindow() layout = QVBoxLayout(window) notebook = DragDropTabWidget() layout.addWidget(notebook) tab1 = MyTab(notebook, settings={ 'device_name': 'ni_pcie_6363_0', 'connection_table': connection_table }) window.add_my_tab(tab1) window.show() def run(): app.exec_() sys.exit(run())
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()
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()