def __init__(self, is_complete, editor=default_editor, **kwargs): """ Initialize :param is_complete: function str->(bool, str) that checks whether the input is complete code :param kwargs: arguments for LoggingConfigurable :return: """ QtGui.QSplitter.__init__(self, QtCore.Qt.Horizontal) LoggingConfigurable.__init__(self, **kwargs) # Layout overview: # pager_top # receiver | pager_right # | pager_inside # entry | self.editor = editor self._console_stack = QtGui.QWidget() self._console_stack_layout = QtGui.QStackedLayout() self._console_stack.setLayout(self._console_stack_layout) self.addWidget(self._console_stack) self._console_area = QtGui.QSplitter(QtCore.Qt.Vertical) self._console_stack_layout.addWidget(self._console_area) self.entry = entry_template(edit_class)(is_complete=is_complete, use_ansi=self.ansi_codes) self.entry.please_export.connect(self.please_export) self.history = self.entry.history self.receiver = receiver_template(edit_class)(use_ansi=self.ansi_codes, show_users=self.show_users) self.receiver.please_export.connect(self.please_export) self._console_area.addWidget(self.receiver) self._console_area.addWidget(self.entry) self.print_action = self.receiver.print_action self.export_action = self.receiver.export_action self.select_all_action = self.receiver.select_all_action self.increase_font_size = self.receiver.increase_font_size self.decrease_font_size = self.receiver.decrease_font_size self.reset_font_size = self.receiver.reset_font_size self._pager_targets = [ ('right', {'target': self, 'index': 1}), ('top', {'target': self._console_area, 'index': 0}), ('inside', {'target': self._console_stack_layout, 'index': 1}) ] self.pager = pager_template(edit_class)(self._pager_targets, self.default_pager_location, 'This is the pager!', use_ansi=self.ansi_codes) self.pager.hide() self.pager.release_focus.connect(self.entry.set_focus) self.receiver.release_focus.connect(self.entry.set_focus) self.entry.release_focus.connect(self.receiver.set_focus) self.line_prompt = LinePrompt() self.line_prompt.text_input.connect(self.on_text_input) self.show_users = self.receiver.text_register.get_visible()
class TabContent(MetaQObjectHasTraits('NewBase', (LoggingConfigurable, QtGui.QSplitter), {})): entry_proportion = Integer(8, config=True, help=""" 1/entry_size is the height of the whole console to height of the command entry field. """) ansi_codes = Bool(True, config=True, help="Whether to process ANSI escape codes.") clear_on_kernel_restart = Bool(True, config=True, help="Whether to clear the console when the kernel is restarted") default_pager_location = Unicode('inside', config=True, help='Default location of the pager: right, inside or top') receiver = None # Area of the console where chat messages, commands and outputs are shown entry = None # Area of the console to enter commands and chat pager = None # Pager object _pager_targets = {} # Dictionary of target widgets where the pager can reside; see Pager _console_stack = None # QWidget _console_stack_layout = None # QStackedLayout _console_area = None # QSplitter print_action = None # action for printing export_action = None # action for exporting select_all_action = None # action for selecting all increase_font_size = None # action for increasing font size decrease_font_size = None # action for decreasing font size reset_font_size = None # action for resetting font size # JupyterWidget: # If set, the 'custom_edit_requested(str, int)' signal will be emitted when # an editor is needed for a file. This overrides 'editor' and 'editor_line' # settings. custom_edit = Bool(False) custom_edit_requested = QtCore.Signal(object, object) editor = Unicode(default_editor, config=False, help=""" A command for invoking a system text editor. If the string contains a {filename} format specifier, it will be used. Otherwise, the filename will be appended to the end of the command. """) editor_line = Unicode(config=True, help=""" The editor command to use when a specific line number is requested. The string should contain two format specifiers: {line} and {filename}. If this parameter is not specified, the line number option to the %edit magic will be ignored. """) please_export = QtCore.Signal(ExportItem) # tasks for the kernel line_prompt = None # LinePrompt for entering input requested by the kernel history = None # History show_users = Bool(False, help='Whether to show the users in command input and output listings') def __init__(self, is_complete, editor=default_editor, **kwargs): """ Initialize :param is_complete: function str->(bool, str) that checks whether the input is complete code :param kwargs: arguments for LoggingConfigurable :return: """ QtGui.QSplitter.__init__(self, QtCore.Qt.Horizontal) LoggingConfigurable.__init__(self, **kwargs) # Layout overview: # pager_top # receiver | pager_right # | pager_inside # entry | self.editor = editor self._console_stack = QtGui.QWidget() self._console_stack_layout = QtGui.QStackedLayout() self._console_stack.setLayout(self._console_stack_layout) self.addWidget(self._console_stack) self._console_area = QtGui.QSplitter(QtCore.Qt.Vertical) self._console_stack_layout.addWidget(self._console_area) self.entry = entry_template(edit_class)(is_complete=is_complete, use_ansi=self.ansi_codes) self.entry.please_export.connect(self.please_export) self.history = self.entry.history self.receiver = receiver_template(edit_class)(use_ansi=self.ansi_codes, show_users=self.show_users) self.receiver.please_export.connect(self.please_export) self._console_area.addWidget(self.receiver) self._console_area.addWidget(self.entry) self.print_action = self.receiver.print_action self.export_action = self.receiver.export_action self.select_all_action = self.receiver.select_all_action self.increase_font_size = self.receiver.increase_font_size self.decrease_font_size = self.receiver.decrease_font_size self.reset_font_size = self.receiver.reset_font_size self._pager_targets = [ ('right', {'target': self, 'index': 1}), ('top', {'target': self._console_area, 'index': 0}), ('inside', {'target': self._console_stack_layout, 'index': 1}) ] self.pager = pager_template(edit_class)(self._pager_targets, self.default_pager_location, 'This is the pager!', use_ansi=self.ansi_codes) self.pager.hide() self.pager.release_focus.connect(self.entry.set_focus) self.receiver.release_focus.connect(self.entry.set_focus) self.entry.release_focus.connect(self.receiver.set_focus) self.line_prompt = LinePrompt() self.line_prompt.text_input.connect(self.on_text_input) self.show_users = self.receiver.text_register.get_visible() def _show_users_changed(self): self.receiver.text_register.set_visible(self.show_users) def clear_all(self): """ Clear all widgets. :return: """ self.entry.clear() self.receiver.clear() self.pager.clear() @property def _focus_text_component(self): """ Text component widget that has focus; none if there is no focus on the text components. :return: """ if self.pager.hasFocus(): return self.pager elif self.receiver.hasFocus(): return self.receiver elif self.entry.hasFocus(): return self.entry else: return None def call_focus_method(self, dotted): """ Execute method of the widget with focus if there is focus and the method exists; otherwise do nothing. :param dotted: dotted string representing the method None->None to be executed. :return: whatever the method returns. """ focus_method = get_member(self._focus_text_component, dotted) if focus_method: return focus_method() else: return None # JupyterWidget def external_edit(self, filename, line=None): """ Opens an external editor. Parameters ---------- filename : str A path to a local system file. line : int, optional A line of interest in the file. """ if self.custom_edit: self.custom_edit_requested.emit(filename, line) elif not self.editor: raise NoDefaultEditor() else: try: filename = '"%s"' % filename if line and self.editor_line: command = self.editor_line.format(filename=filename, line=line) else: try: command = self.editor.format() except KeyError: command = self.editor.format(filename=filename) else: command += ' ' + filename except KeyError: raise else: try: Popen(command, shell=True) except OSError: raise CommandError(command) @QtCore.Slot(SplitItem) def post(self, item): _post(item, self) @property def pager_locations(self): """ Available pager locations. :return: List of strings representing the available pager locations. """ return [t[0] for t in self._pager_targets] # Qt events def showEvent(self, event): if not event.spontaneous(): _resize_last(self._console_area, self.entry_proportion) # Qt slots @QtCore.Slot() def on_enter_clicked(self): """ After the user clicks enter, emit the source to be executed. :return: """ source = self.entry.source self.post(ClearCurrentEntry()) self.please_export.emit(Execute(source)) @QtCore.Slot() def on_frontend_clicked(self): """ After the user clicks message to frontend, emit the source to be sent to the receiver. :return: """ # print('Send clicked') self._importer.convert(KernelMessage(eval(self.entry.source.code), from_here=True)) @QtCore.Slot(str) def on_text_input(self, text): self.line_prompt.setEnabled(False) self.line_prompt.hide() self.please_export.emit(UserInput(text)) if self.line_prompt.password: text = '****' out = self.line_prompt.prompt + text +'\n' self.post(Stdout(out)) self.entry.set_focus() self.entry.set_read_only(False)