class ConsoleInitThread(QObject): initialized = Signal(object, object) def __init__(self, *args, **kwargs): super(ConsoleInitThread, self).__init__(*args, **kwargs) self.mutex = QMutex() self.wait_condition = QWaitCondition() def run(self): self.mutex.lock() kernel_manager = QtKernelManager(kernel_name='python3') kernel_manager.start_kernel() kernel_client = kernel_manager.client() kernel_client.start_channels() # notify to update ui self.initialized.emit(kernel_manager, kernel_client) # wait for exit self.wait_condition.wait(self.mutex) self.mutex.unlock() # stop channels and kernel kernel_client.stop_channels() kernel_manager.shutdown_kernel( now=True) # add now=True; Fix exit error; 200924 liugang def stop(self): self.wait_condition.wakeAll()
class PMGThreadWorker(QObject): """ 利用mutex加锁 """ signal_print = Signal(str) def __init__(self, worker_id: int): super(PMGThreadWorker, self).__init__() self.quit = False self.id = worker_id self.mutex = QMutex() self.wait_condition = QWaitCondition() def work(self): i = 0 while (1): self.mutex.lock() print(self.thread()) self.wait_condition.wait(self.mutex) for i in range(3): self.signal_print.emit(str(self.id) + ',' + str(i + 1)) i += 1 if self.quit: break self.mutex.unlock() def on_exit(self): self.quit = True self.wait_condition.wakeAll() def wake_all(self): self.wait_condition.wakeAll()
def __init__(self, algorithm: SegmentationAlgorithm): super().__init__() self.finished.connect(self.finished_task) self.algorithm = algorithm self.clean_later = False self.cache = None self.mutex = QMutex() self.rerun = False, QThread.InheritPriority
def __init__(self, cam_id, image_width, image_height): super(UpdateThread, self).__init__() self._width = 640 self._height = 480 self._stopped = False self._update_mutex = QMutex() self._cam_id = cam_id self._image_width = image_width self._image_height = image_height
def __init__(self, parent, plugins=['lsp', 'kite', 'fallback']): SpyderCompletionPlugin.__init__(self, parent) self.clients = {} self.requests = {} self.language_status = {} self.started = False self.first_completion = False self.req_id = 0 self.completion_first_time = 500 self.waiting_time = 1000 self.collection_mutex = QMutex() self.plugin_priority = { LSPRequestTypes.DOCUMENT_COMPLETION: 'lsp', LSPRequestTypes.DOCUMENT_SIGNATURE: 'lsp', LSPRequestTypes.DOCUMENT_HOVER: 'lsp', 'all': 'lsp' } self.response_priority = ['lsp', 'kite', 'fallback'] for plugin in plugins: if plugin in self.BASE_PLUGINS: Plugin = self.BASE_PLUGINS[plugin] plugin_client = Plugin(self.main) self.register_completion_plugin(plugin_client)
def __init__(self): EditorExtension.__init__(self) self.is_snippet_active = False self.active_snippet = -1 self.node_number = 0 self.index = None self.ast = None self.starting_position = None self.modification_lock = QMutex() self.event_lock = QMutex() self.node_position = {} self.snippets_map = {} self.undo_stack = [] self.redo_stack = [] if rtree_available: self.index = index.Index()
def __init__(self, parent, configuration=None): super().__init__(parent, configuration) # Available completion providers self._available_providers = {} # Instantiated completion providers self.providers = {} # Mapping that indicates if there are completion services available # for a given language self.language_status = {} # Mapping that contains the ids and the current completion/linting # requests in progress self.requests = {} # Current request sequence identifier self.req_id = 0 # Lock to prevent concurrent access to requests mapping self.collection_mutex = QMutex(QMutex.Recursive) # Completion request priority self.source_priority = {} # Completion provider speed: slow or fast self.provider_speed = {} # Timeout limit for a response to be received self.wait_for_ms = self.get_conf('completions_wait_for_ms') # Save application menus to create if/when MainMenu is available. self.application_menus_to_create = [] # Save items to add to application menus if/when MainMenu is # available. self.items_to_add_to_application_menus = [] # Find and instantiate all completion providers registered via # entrypoints for entry_point in iter_entry_points(COMPLETION_ENTRYPOINT): try: logger.debug(f'Loading entry point: {entry_point}') Provider = entry_point.resolve() self._instantiate_and_register_provider(Provider) except Exception as e: logger.warning('Failed to load completion provider from entry ' f'point {entry_point}') raise e # Register statusbar widgets self.register_statusbar_widgets(plugin_loaded=False) # Define configuration page and tabs (conf_providers, conf_tabs) = self.gather_providers_and_configtabs() self.CONF_WIDGET_CLASS = partialclass(CompletionConfigPage, providers=conf_providers) self.ADDITIONAL_CONF_TABS = {'completions': conf_tabs}
class BaseThread(QThread, metaclass=QABCMeta): """Base thread of Cython functions.""" @abstractmethod def __init__(self, parent: QWidget) -> None: super(BaseThread, self).__init__(parent) self.finished.connect(self.deleteLater) self.is_stop = False self.mutex = QMutex() @Slot() def stop(self) -> None: """Stop the algorithm.""" self.mutex.unlock() self.is_stop = True self.mutex.lock()
def __init__(self, parent): QThread.__init__(self, parent) self.mailbox = Queue() self.stopped = False self.daemon = True self.mutex = QMutex() self.file_tokens = {} self.diff_patch = diff_match_patch()
def __init__(self, presenter, plot_number, parent=None): super(PlotNameWidget, self).__init__(parent) self.presenter = presenter self.plot_number = plot_number self.mutex = QMutex() self.line_edit = QLineEdit( self.presenter.get_plot_name_from_number(plot_number)) self.line_edit.setReadOnly(True) self.line_edit.setFrame(False) self.line_edit.setStyleSheet( "* { background-color: rgba(0, 0, 0, 0); }") self.line_edit.setAttribute(Qt.WA_TransparentForMouseEvents, True) self.line_edit.editingFinished.connect(self.rename_plot) shown_icon = get_icon('fa.eye') self.hide_button = QPushButton(shown_icon, "") self.hide_button.setToolTip('Hide') self.hide_button.setFlat(True) self.hide_button.setMaximumWidth(self.hide_button.iconSize().width() * 5 / 3) self.hide_button.clicked.connect(self.toggle_visibility) rename_icon = get_icon('fa.edit') self.rename_button = QPushButton(rename_icon, "") self.rename_button.setToolTip('Rename') self.rename_button.setFlat(True) self.rename_button.setMaximumWidth( self.rename_button.iconSize().width() * 5 / 3) self.rename_button.setCheckable(True) self.rename_button.toggled.connect(self.rename_button_toggled) close_icon = get_icon('fa.close') self.close_button = QPushButton(close_icon, "") self.close_button.setToolTip('Delete') self.close_button.setFlat(True) self.close_button.setMaximumWidth( self.close_button.iconSize().width() * 5 / 3) self.close_button.clicked.connect( lambda: self.close_pressed(self.plot_number)) self.layout = QHBoxLayout() # Get rid of the top and bottom margins - the button provides # some natural margin anyway. Get rid of right margin and # reduce spacing to get buttons closer together. self.layout.setContentsMargins(5, 0, 0, 0) self.layout.setSpacing(0) self.layout.addWidget(self.line_edit) self.layout.addWidget(self.hide_button) self.layout.addWidget(self.rename_button) self.layout.addWidget(self.close_button) self.layout.sizeHint() self.setLayout(self.layout)
def __init__(self, presenter, plot_number, parent=None): super(PlotNameWidget, self).__init__(parent) self.presenter = presenter self.plot_number = plot_number self.mutex = QMutex() self.line_edit = QLineEdit(self.presenter.get_plot_name_from_number(plot_number)) self.line_edit.setReadOnly(True) self.line_edit.setFrame(False) # changes the line edit to look like normal even when self.line_edit.setStyleSheet("""* { background-color: rgba(0, 0, 0, 0); } QLineEdit:disabled { color: black; }""") self.line_edit.setAttribute(Qt.WA_TransparentForMouseEvents, True) self.line_edit.editingFinished.connect(self.rename_plot) # Disabling the line edit prevents it from temporarily # grabbing focus when changing code editors - this triggered # the editingFinished signal, which was causing #26305 self.line_edit.setDisabled(True) shown_icon = get_icon('mdi.eye') self.hide_button = QPushButton(shown_icon, "") self.hide_button.setToolTip('Hide') self.hide_button.setFlat(True) self.hide_button.setMaximumWidth(self.hide_button.iconSize().width() * 5 / 3) self.hide_button.clicked.connect(self.toggle_visibility) rename_icon = get_icon('mdi.square-edit-outline') self.rename_button = QPushButton(rename_icon, "") self.rename_button.setToolTip('Rename') self.rename_button.setFlat(True) self.rename_button.setMaximumWidth(self.rename_button.iconSize().width() * 5 / 3) self.rename_button.setCheckable(True) self.rename_button.toggled.connect(self.rename_button_toggled) close_icon = get_icon('mdi.close') self.close_button = QPushButton(close_icon, "") self.close_button.setToolTip('Delete') self.close_button.setFlat(True) self.close_button.setMaximumWidth(self.close_button.iconSize().width() * 5 / 3) self.close_button.clicked.connect(lambda: self.close_pressed(self.plot_number)) self.layout = QHBoxLayout() # Get rid of the top and bottom margins - the button provides # some natural margin anyway. Get rid of right margin and # reduce spacing to get buttons closer together. self.layout.setContentsMargins(5, 0, 0, 0) self.layout.setSpacing(0) self.layout.addWidget(self.line_edit) self.layout.addWidget(self.hide_button) self.layout.addWidget(self.rename_button) self.layout.addWidget(self.close_button) self.layout.sizeHint() self.setLayout(self.layout)
def work(p): global i, j j += 1 mutex = QMutex() print('start') while (1): mutex.lock() # print(self.thread()) # self.wait_condition.wait(self.mutex) # for j in range(3): # print(j) i += 1 p.signal_print.emit(repr(('thread:%d' % p.id, i))) # print('thread:%d' % p.id, i, '\n') p.thread().msleep(10) # mutex.unlock() if i > 100: break
def __init__(self, serl, codegen, que): self.pressureque = que self.serl = serl self.codegen = codegen self.codegen.GenerateCMV() self.codelist = self.codegen.gcodestr.splitlines() self.linecount = len(self.codelist) self.flagStop = False self.pause = True self.gcode_exec_state = GcodeStates.READY_TO_SEND self.gcode_move_count = 0 self.presentPosition = (0,0) self.Tic = 0 self.Toc = 0 self.xyIncr = self.codegen.Dt self.gstr = "" self.sremsg = "" self.serialmutex = QMutex() self.startdelay = -1 super().__init__()
def __init__(self, parent): QObject.__init__(self) self.stopped = False self.daemon = True self.mutex = QMutex() self.language_snippets = {} self.thread = QThread() self.moveToThread(self.thread) self.thread.started.connect(self.started) self.sig_mailbox.connect(self.handle_msg) self.sig_update_snippets.connect(self.update_snippets)
def __init__(self): self._mutex = QMutex() self.parser_collection = ParserCollection() self.element_collection = ElementCollection() self.factory = ElementFactory() self.add_parser('dxf', DXFParser()) self.add_parser('off', OFFParser()) self.add_parser('h5m', H5MParser()) self.add_parser('h5p', H5PParser()) self.add_parser('csv', CSVParser()) self.add_parser('out', GSLibParser())
def __init__(self, parent): QObject.__init__(self, parent) self.endpoint = None self.requests = {} self.languages = [] self.mutex = QMutex() self.opened_files = {} self.thread_started = False self.thread = QThread() self.moveToThread(self.thread) self.thread.started.connect(self.started) self.sig_perform_request.connect(self.perform_request)
def __init__(self, parent): QObject.__init__(self) self.stopped = False self.daemon = True self.mutex = QMutex() self.file_tokens = {} self.diff_patch = diff_match_patch() self.thread = QThread() self.moveToThread(self.thread) self.thread.started.connect(self.started) self.sig_mailbox.connect(self.handle_msg)
def __init__(self, parent, plugins=['lsp', 'kite', 'fallback']): SpyderCompletionPlugin.__init__(self, parent) self.clients = {} self.requests = {} self.language_status = {} self.started = False self.req_id = 0 self.collection_mutex = QMutex(QMutex.Recursive) for plugin in plugins: if plugin in self.BASE_PLUGINS: Plugin = self.BASE_PLUGINS[plugin] plugin_client = Plugin(self.main) self.register_completion_plugin(plugin_client)
def __init__(self, parent, enable_code_snippets=True): QObject.__init__(self, parent) self.endpoint = None self.requests = {} self.languages = [] self.mutex = QMutex() self.opened_files = {} self.opened_files_status = {} self.thread_started = False self.enable_code_snippets = enable_code_snippets self.thread = QThread() self.moveToThread(self.thread) self.thread.started.connect(self.started) self.sig_perform_request.connect(self.perform_request) self.sig_perform_status_request.connect(self.get_status)
def __init__(self, parent, plugins=ALL_COMPLETION_PLUGINS): SpyderCompletionPlugin.__init__(self, parent) self.clients = {} self.requests = {} self.language_status = {} self.started = False self.req_id = 0 self.collection_mutex = QMutex(QMutex.Recursive) self.wait_for_ms = self.get_option('completions_wait_for_ms', section='editor') for plugin in plugins: if plugin in self.BASE_PLUGINS: Plugin = self.BASE_PLUGINS[plugin] plugin_client = Plugin(self.main) self.register_completion_plugin(plugin_client)
def __init__(self, parent): QThread.__init__(self, parent) self.mutex = QMutex() self.stopped = None self.results = None self.pathlist = None self.total_matches = None self.error_flag = None self.rootpath = None self.exclude = None self.texts = None self.text_re = None self.completed = None self.case_sensitive = True self.results = {} self.total_matches = 0 self.is_file = False
def __init__(self, parent): QThread.__init__(self, parent) self.mutex = QMutex() self.stopped = None self.results = None self.pathlist = None self.nb = None self.error_flag = None self.rootpath = None self.python_path = None self.hg_manifest = None self.include = None self.exclude = None self.texts = None self.text_re = None self.completed = None self.get_pythonpath_callback = None
def __init__(self, parent, search_text, text_color=None): super().__init__(parent) self.mutex = QMutex() self.stopped = None self.search_text = search_text self.text_color = text_color self.pathlist = None self.total_matches = None self.error_flag = None self.rootpath = None self.exclude = None self.texts = None self.text_re = None self.completed = None self.case_sensitive = True self.total_matches = 0 self.is_file = False self.results = {} self.num_files = 0 self.files = [] self.partial_results = []
def __init__(self): self.buffer = [] self.mutex = QMutex()
def __init__(self, presenter, parent=None): """ Initialise a new instance of PlotSelectorWidget :param presenter: The presenter controlling this view :param parent: Optional - the parent QWidget running as a unit test, in which case skip file dialogs """ super(PlotSelectorView, self).__init__(parent) self.presenter = presenter # This mutex prevents multiple operations on the table at the # same time. Wrap code in - with QMutexLocker(self.mutex): self.mutex = QMutex() self.active_plot_number = -1 self.show_button = QPushButton('Show') self.hide_button = QPushButton('Hide') # Note this button is labeled delete, but for consistency # with matplotlib 'close' is used in the code self.close_button = QPushButton('Delete') self.select_all_button = QPushButton('Select All') self.sort_button = self._make_sort_button() self.export_button = self._make_export_button() self.filter_box = self._make_filter_box() self.table_widget = self._make_table_widget() # Add the context menu self.table_widget.setContextMenuPolicy(Qt.CustomContextMenu) self.context_menu, self.export_menu = self._make_context_menu() self.table_widget.customContextMenuRequested.connect( self.context_menu_opened) buttons_layout = FlowLayout() buttons_layout.setSpacing(1) buttons_layout.addWidget(self.show_button) buttons_layout.addWidget(self.hide_button) buttons_layout.addWidget(self.close_button) buttons_layout.addWidget(self.select_all_button) buttons_layout.addWidget(self.sort_button) buttons_layout.addWidget(self.export_button) filter_layout = QHBoxLayout() filter_layout.addWidget(self.filter_box) layout = QVBoxLayout() layout.addLayout(buttons_layout) layout.addLayout(filter_layout) layout.addWidget(self.table_widget) # todo: Without the sizeHint() call the minimum size is not set correctly # This needs some investigation as to why this is. layout.sizeHint() self.setLayout(layout) # Any updates that originate from the matplotlib figure # windows must be wrapped in a QAppThreadCall. Not doing this # WILL result in segfaults. self.set_plot_list_orig = self.set_plot_list self.set_plot_list = QAppThreadCall(self.set_plot_list_orig) self.append_to_plot_list_orig = self.append_to_plot_list self.append_to_plot_list = QAppThreadCall( self.append_to_plot_list_orig) self.remove_from_plot_list_orig = self.remove_from_plot_list self.remove_from_plot_list = QAppThreadCall( self.remove_from_plot_list_orig) self.rename_in_plot_list_orig = self.rename_in_plot_list self.rename_in_plot_list = QAppThreadCall( self.rename_in_plot_list_orig) self.set_active_font_orig = self.set_active_font self.set_active_font = QAppThreadCall(self.set_active_font_orig) self.set_visibility_icon_orig = self.set_visibility_icon self.set_visibility_icon = QAppThreadCall( self.set_visibility_icon_orig) self.set_last_active_values_orig = self.set_last_active_values self.set_last_active_values = QAppThreadCall( self.set_last_active_values_orig) self.sort_type_orig = self.sort_type self.sort_type = QAppThreadCall(self.sort_type_orig) # Connect presenter methods to things in the view self.show_button.clicked.connect(self.presenter.show_multiple_selected) self.hide_button.clicked.connect(self.presenter.hide_selected_plots) self.close_button.clicked.connect(self.presenter.close_action_called) self.select_all_button.clicked.connect(self.table_widget.selectAll) self.table_widget.doubleClicked.connect( self.presenter.show_single_selected) self.filter_box.textChanged.connect(self.presenter.filter_text_changed) self.deleteKeyPressed.connect(self.presenter.close_action_called) if DEBUG_MODE: self.table_widget.clicked.connect(self.show_debug_info)
def __init__(self): QThread.__init__(self) self.app = QApplication.instance() self.app.aboutToQuit.connect(self.requestInterruption) self.map_lock = QMutex() self.widget_map = dict()
class UpdateThread(QThread): pixmapReady = Signal(QImage) stopped = Signal() errored = Signal(str) def __init__(self, cam_id, image_width, image_height): super(UpdateThread, self).__init__() self._width = 640 self._height = 480 self._stopped = False self._update_mutex = QMutex() self._cam_id = cam_id self._image_width = image_width self._image_height = image_height @property def width(self): return self._width @width.setter def width(self, value): self._update_mutex.lock() self._width = value self._update_mutex.unlock() @property def height(self): return self._height @height.setter def height(self, value): self._update_mutex.lock() self._height = value self._update_mutex.unlock() def stop(self): self._update_mutex.lock() self._stopped = True self._update_mutex.unlock() def run(self): try: import cv2 except ImportError as e: self.errored.emit(str(e)) self.stopped.emit() return try: ueye = UEye(self._cam_id, self._image_width, self._image_height) except CameraException as e: self.errored.emit(str(e)) self.stopped.emit() return self._ueye.start_video_capture() while True: try: self._update_mutex.lock() if self._stopped: ueye.close() del ueye self.stopped.emit() return finally: self._update_mutex.unlock() frame = ueye.get_video_frame() if frame is None: ueye.close() del ueye self.stopped.emit() return rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgb_image.shape bytes_per_line = ch * w convert_to_qt_format = QImage( rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888 ) try: self._update_mutex.lock() p = convert_to_qt_format.scaled( self._width, self._height, Qt.KeepAspectRatio ) finally: self._update_mutex.unlock() self.pixmapReady.emit(p)
def __init__(self, *args, **kwargs): super(ConsoleInitThread, self).__init__(*args, **kwargs) self.mutex = QMutex() self.wait_condition = QWaitCondition()
def __init__(self, parent=None, fname=None, wdir=None, history_filename=None, show_icontext=True, light_background=True, menu_actions=None, show_buttons_inside=True, show_elapsed_time=True): QWidget.__init__(self, parent) self.menu_actions = menu_actions self.write_lock = QMutex() self.buffer_lock = QMutex() self.buffer = [] self.run_button = None self.kill_button = None self.options_button = None self.icontext_action = None self.show_elapsed_time = show_elapsed_time self.fname = fname if wdir is None: wdir = osp.dirname(osp.abspath(fname)) self.wdir = wdir if osp.isdir(wdir) else None self.arguments = "" self.shell = self.SHELL_CLASS(parent, get_conf_path(history_filename)) self.shell.set_light_background(light_background) self.shell.execute.connect(self.send_to_process) self.shell.sig_keyboard_interrupt.connect(self.keyboard_interrupt) # Redirecting some SIGNALs: self.shell.redirect_stdio.connect( lambda state: self.redirect_stdio.emit(state)) self.state_label = None self.time_label = None vlayout = QVBoxLayout() toolbar_buttons = self.get_toolbar_buttons() if show_buttons_inside: self.state_label = QLabel() hlayout = QHBoxLayout() hlayout.addWidget(self.state_label) hlayout.addStretch(0) hlayout.addWidget(self.create_time_label()) hlayout.addStretch(0) for button in toolbar_buttons: hlayout.addWidget(button) vlayout.addLayout(hlayout) else: vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addWidget(self.get_shell_widget()) self.setLayout(vlayout) self.resize(640, 480) if parent is None: self.setWindowIcon(self.get_icon()) self.setWindowTitle(_("Console")) self.t0 = None self.timer = QTimer(self) self.process = None self.is_closing = False if show_buttons_inside: self.update_time_label_visibility()
class ExternalShellBase(QWidget): """External Shell widget: execute Python script in a separate process""" SHELL_CLASS = None redirect_stdio = Signal(bool) sig_finished = Signal() def __init__(self, parent=None, fname=None, wdir=None, history_filename=None, show_icontext=True, light_background=True, menu_actions=None, show_buttons_inside=True, show_elapsed_time=True): QWidget.__init__(self, parent) self.menu_actions = menu_actions self.write_lock = QMutex() self.buffer_lock = QMutex() self.buffer = [] self.run_button = None self.kill_button = None self.options_button = None self.icontext_action = None self.show_elapsed_time = show_elapsed_time self.fname = fname if wdir is None: wdir = osp.dirname(osp.abspath(fname)) self.wdir = wdir if osp.isdir(wdir) else None self.arguments = "" self.shell = self.SHELL_CLASS(parent, get_conf_path(history_filename)) self.shell.set_light_background(light_background) self.shell.execute.connect(self.send_to_process) self.shell.sig_keyboard_interrupt.connect(self.keyboard_interrupt) # Redirecting some SIGNALs: self.shell.redirect_stdio.connect( lambda state: self.redirect_stdio.emit(state)) self.state_label = None self.time_label = None vlayout = QVBoxLayout() toolbar_buttons = self.get_toolbar_buttons() if show_buttons_inside: self.state_label = QLabel() hlayout = QHBoxLayout() hlayout.addWidget(self.state_label) hlayout.addStretch(0) hlayout.addWidget(self.create_time_label()) hlayout.addStretch(0) for button in toolbar_buttons: hlayout.addWidget(button) vlayout.addLayout(hlayout) else: vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addWidget(self.get_shell_widget()) self.setLayout(vlayout) self.resize(640, 480) if parent is None: self.setWindowIcon(self.get_icon()) self.setWindowTitle(_("Console")) self.t0 = None self.timer = QTimer(self) self.process = None self.is_closing = False if show_buttons_inside: self.update_time_label_visibility() @Slot(bool) def set_elapsed_time_visible(self, state): self.show_elapsed_time = state if self.time_label is not None: self.time_label.setVisible(state) def create_time_label(self): """Create elapsed time label widget (if necessary) and return it""" if self.time_label is None: self.time_label = QLabel() return self.time_label def update_time_label_visibility(self): self.time_label.setVisible(self.show_elapsed_time) def is_running(self): if self.process is not None: return self.process.state() == QProcess.Running def get_toolbar_buttons(self): if self.run_button is None: self.run_button = create_toolbutton( self, text=_("Run"), icon=ima.icon('run'), tip=_("Run again this program"), triggered=self.start_shell) if self.kill_button is None: self.kill_button = create_toolbutton( self, text=_("Kill"), icon=ima.icon('kill'), tip=_("Kills the current process, " "causing it to exit immediately")) buttons = [self.run_button] if self.options_button is None: options = self.get_options_menu() if options: self.options_button = create_toolbutton( self, text=_('Options'), icon=ima.icon('tooloptions')) self.options_button.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) add_actions(menu, options) self.options_button.setMenu(menu) if self.options_button is not None: buttons.append(self.options_button) buttons.append(self.kill_button) return buttons def set_icontext_visible(self, state): """Set icon text visibility""" for widget in self.get_toolbar_buttons(): if state: widget.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) else: widget.setToolButtonStyle(Qt.ToolButtonIconOnly) def get_options_menu(self): self.show_time_action = create_action( self, _("Show elapsed time"), toggled=self.set_elapsed_time_visible) self.show_time_action.setChecked(self.show_elapsed_time) actions = [self.show_time_action] if self.menu_actions is not None: actions += [None] + self.menu_actions return actions def get_shell_widget(self): return self.shell def get_icon(self): raise NotImplementedError def show_time(self, end=False): if self.time_label is None: return elapsed_time = time() - self.t0 if elapsed_time > 24 * 3600: # More than a day...! format = "%d %H:%M:%S" else: format = "%H:%M:%S" if end: color = "#AAAAAA" else: color = "#AA6655" text = "<span style=\'color: %s\'><b>%s" \ "</b></span>" % (color, strftime(format, gmtime(elapsed_time))) self.time_label.setText(text) def closeEvent(self, event): if self.process is not None: self.is_closing = True self.process.kill() self.process.waitForFinished(100) try: self.timer.timeout.disconnect(self.show_time) except (RuntimeError, TypeError): pass def set_running_state(self, state=True): self.set_buttons_runnning_state(state) self.shell.setReadOnly(not state) if state: if self.state_label is not None: self.state_label.setText( _("<span style=\'color: #44AA44\'><b>Running...</b></span>" )) self.t0 = time() self.timer.timeout.connect(self.show_time) self.timer.start(1000) else: if self.state_label is not None: self.state_label.setText(_('Terminated.')) try: self.timer.timeout.disconnect(self.show_time) except (RuntimeError, TypeError): pass def set_buttons_runnning_state(self, state): self.run_button.setVisible(not state) self.kill_button.setVisible(state) @Slot(bool) def start_shell(self, ask_for_arguments=False): """Start shell""" if ask_for_arguments and not self.get_arguments(): self.set_running_state(False) return try: self.terminate_button.clicked.disconnect(self.process.terminate) self.kill_button.clicked.disconnect(self.process.terminate) except (AttributeError, RuntimeError, TypeError): pass self.create_process() @Slot() def get_arguments(self): arguments, valid = QInputDialog.getText(self, _('Arguments'), _('Command line arguments:'), QLineEdit.Normal, self.arguments) if valid: self.arguments = to_text_string(arguments) return valid def create_process(self): raise NotImplementedError def finished(self, exit_code, exit_status): self.shell.flush() self.sig_finished.emit() if self.is_closing: return self.set_running_state(False) self.show_time(end=True) #=============================================================================== # Input/Output #=============================================================================== def transcode(self, qba): try: return to_text_string(qba.data(), 'utf8') except UnicodeDecodeError: return qba.data() def get_stdout(self): self.process.setReadChannel(QProcess.StandardOutput) qba = QByteArray() while self.process.bytesAvailable(): qba += self.process.readAllStandardOutput() return self.transcode(qba) def get_stderr(self): self.process.setReadChannel(QProcess.StandardError) qba = QByteArray() while self.process.bytesAvailable(): qba += self.process.readAllStandardError() return self.transcode(qba) def write_output(self): # if we are already writing something else, # store the present message in a buffer if not self.write_lock.tryLock(): self.buffer_lock.lock() self.buffer.append(self.get_stdout()) self.buffer_lock.unlock() if not self.write_lock.tryLock(): return self.shell.write(self.get_stdout(), flush=True) while True: self.buffer_lock.lock() messages = self.buffer self.buffer = [] if not messages: self.write_lock.unlock() self.buffer_lock.unlock() return self.buffer_lock.unlock() self.shell.write("\n".join(messages), flush=True) def send_to_process(self, qstr): raise NotImplementedError def send_ctrl_to_process(self, letter): char = chr("abcdefghijklmnopqrstuvwxyz".index(letter) + 1) byte_array = QByteArray() byte_array.append(char) self.process.write(byte_array) self.process.waitForBytesWritten(-1) self.shell.write(LOCALE_CODEC.toUnicode(byte_array), flush=True) def keyboard_interrupt(self): raise NotImplementedError
class ExternalShellBase(QWidget): """External Shell widget: execute Python script in a separate process""" SHELL_CLASS = None redirect_stdio = Signal(bool) sig_finished = Signal() def __init__(self, parent=None, fname=None, wdir=None, history_filename=None, show_icontext=True, light_background=True, menu_actions=None, show_buttons_inside=True, show_elapsed_time=True): QWidget.__init__(self, parent) self.menu_actions = menu_actions self.write_lock = QMutex() self.buffer_lock = QMutex() self.buffer = [] self.run_button = None self.kill_button = None self.options_button = None self.icontext_action = None self.show_elapsed_time = show_elapsed_time self.fname = fname if wdir is None: wdir = osp.dirname(osp.abspath(fname)) self.wdir = wdir if osp.isdir(wdir) else None self.arguments = "" self.shell = self.SHELL_CLASS(parent, get_conf_path(history_filename)) self.shell.set_light_background(light_background) self.shell.execute.connect(self.send_to_process) self.shell.sig_keyboard_interrupt.connect(self.keyboard_interrupt) # Redirecting some SIGNALs: self.shell.redirect_stdio.connect( lambda state: self.redirect_stdio.emit(state)) self.state_label = None self.time_label = None vlayout = QVBoxLayout() toolbar_buttons = self.get_toolbar_buttons() if show_buttons_inside: self.state_label = QLabel() hlayout = QHBoxLayout() hlayout.addWidget(self.state_label) hlayout.addStretch(0) hlayout.addWidget(self.create_time_label()) hlayout.addStretch(0) for button in toolbar_buttons: hlayout.addWidget(button) vlayout.addLayout(hlayout) else: vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addWidget(self.get_shell_widget()) self.setLayout(vlayout) self.resize(640, 480) if parent is None: self.setWindowIcon(self.get_icon()) self.setWindowTitle(_("Console")) self.t0 = None self.timer = QTimer(self) self.process = None self.is_closing = False if show_buttons_inside: self.update_time_label_visibility() @Slot(bool) def set_elapsed_time_visible(self, state): self.show_elapsed_time = state if self.time_label is not None: self.time_label.setVisible(state) def create_time_label(self): """Create elapsed time label widget (if necessary) and return it""" if self.time_label is None: self.time_label = QLabel() return self.time_label def update_time_label_visibility(self): self.time_label.setVisible(self.show_elapsed_time) def is_running(self): if self.process is not None: return self.process.state() == QProcess.Running def get_toolbar_buttons(self): if self.run_button is None: self.run_button = create_toolbutton(self, text=_("Run"), icon=ima.icon('run'), tip=_("Run again this program"), triggered=self.start_shell) if self.kill_button is None: self.kill_button = create_toolbutton(self, text=_("Kill"), icon=ima.icon('kill'), tip=_("Kills the current process, " "causing it to exit immediately")) buttons = [self.run_button] if self.options_button is None: options = self.get_options_menu() if options: self.options_button = create_toolbutton(self, text=_('Options'), icon=ima.icon('tooloptions')) self.options_button.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) add_actions(menu, options) self.options_button.setMenu(menu) if self.options_button is not None: buttons.append(self.options_button) buttons.append(self.kill_button) return buttons def set_icontext_visible(self, state): """Set icon text visibility""" for widget in self.get_toolbar_buttons(): if state: widget.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) else: widget.setToolButtonStyle(Qt.ToolButtonIconOnly) def get_options_menu(self): self.show_time_action = create_action(self, _("Show elapsed time"), toggled=self.set_elapsed_time_visible) self.show_time_action.setChecked(self.show_elapsed_time) actions = [self.show_time_action] if self.menu_actions is not None: actions += [None]+self.menu_actions return actions def get_shell_widget(self): return self.shell def get_icon(self): raise NotImplementedError def show_time(self, end=False): if self.time_label is None: return elapsed_time = time()-self.t0 if elapsed_time > 24*3600: # More than a day...! format = "%d %H:%M:%S" else: format = "%H:%M:%S" if end: color = "#AAAAAA" else: color = "#AA6655" text = "<span style=\'color: %s\'><b>%s" \ "</b></span>" % (color, strftime(format, gmtime(elapsed_time))) self.time_label.setText(text) def closeEvent(self, event): if self.process is not None: self.is_closing = True self.process.kill() self.process.waitForFinished(100) try: self.timer.timeout.disconnect(self.show_time) except (RuntimeError, TypeError): pass def set_running_state(self, state=True): self.set_buttons_runnning_state(state) self.shell.setReadOnly(not state) if state: if self.state_label is not None: self.state_label.setText(_( "<span style=\'color: #44AA44\'><b>Running...</b></span>")) self.t0 = time() self.timer.timeout.connect(self.show_time) self.timer.start(1000) else: if self.state_label is not None: self.state_label.setText(_('Terminated.')) try: self.timer.timeout.disconnect(self.show_time) except (RuntimeError, TypeError): pass def set_buttons_runnning_state(self, state): self.run_button.setVisible(not state and not self.is_ipykernel) self.kill_button.setVisible(state) @Slot(bool) def start_shell(self, ask_for_arguments=False): """Start shell""" if ask_for_arguments and not self.get_arguments(): self.set_running_state(False) return try: self.terminate_button.clicked.disconnect(self.process.terminate) self.kill_button.clicked.disconnect(self.process.terminate) except (AttributeError, RuntimeError, TypeError): pass self.create_process() @Slot() def get_arguments(self): arguments, valid = QInputDialog.getText(self, _('Arguments'), _('Command line arguments:'), QLineEdit.Normal, self.arguments) if valid: self.arguments = to_text_string(arguments) return valid def create_process(self): raise NotImplementedError def finished(self, exit_code, exit_status): self.shell.flush() self.sig_finished.emit() if self.is_closing: return self.set_running_state(False) self.show_time(end=True) #=============================================================================== # Input/Output #=============================================================================== def transcode(self, qba): try: return to_text_string(qba.data(), 'utf8') except UnicodeDecodeError: return qba.data() def get_stdout(self): self.process.setReadChannel(QProcess.StandardOutput) qba = QByteArray() while self.process.bytesAvailable(): qba += self.process.readAllStandardOutput() return self.transcode(qba) def get_stderr(self): self.process.setReadChannel(QProcess.StandardError) qba = QByteArray() while self.process.bytesAvailable(): qba += self.process.readAllStandardError() return self.transcode(qba) def write_output(self): # if we are already writing something else, # store the present message in a buffer if not self.write_lock.tryLock(): self.buffer_lock.lock() self.buffer.append(self.get_stdout()) self.buffer_lock.unlock() if not self.write_lock.tryLock(): return self.shell.write(self.get_stdout(), flush=True) while True: self.buffer_lock.lock() messages = self.buffer self.buffer = [] if not messages: self.write_lock.unlock() self.buffer_lock.unlock() return self.buffer_lock.unlock() self.shell.write("\n".join(messages), flush=True) def send_to_process(self, qstr): raise NotImplementedError def send_ctrl_to_process(self, letter): char = chr("abcdefghijklmnopqrstuvwxyz".index(letter) + 1) byte_array = QByteArray() byte_array.append(char) self.process.write(byte_array) self.process.waitForBytesWritten(-1) self.shell.write(LOCALE_CODEC.toUnicode(byte_array), flush=True) def keyboard_interrupt(self): raise NotImplementedError