Beispiel #1
0
 def test_normal_exec(self):
     """Test exec_ without double-executing."""
     self.loop = qtutils.EventLoop()
     QTimer.singleShot(100, self._assert_executing)
     QTimer.singleShot(200, self.loop.quit)
     self.loop.exec_()
     assert not self.loop._executing
Beispiel #2
0
def _execute_fileselect_command(
    command: List[str],
    qb_mode: FileSelectionMode,
    tmpfilename: Optional[str] = None
) -> List[str]:
    """Execute external command to choose file.

    Args:
        multiple: Should selecting multiple files be allowed.
        tmpfilename: Path to the temporary file if used, otherwise None.

    Return:
        A list of selected file paths, or empty list if no file is selected.
        If multiple is False, the return value will have at most 1 item.
    """
    proc = guiprocess.GUIProcess(what='choose-file')
    proc.start(command[0], command[1:])

    loop = qtutils.EventLoop()
    proc.finished.connect(lambda _code, _status: loop.exit())
    loop.exec()

    if tmpfilename is None:
        selected_files = proc.stdout.splitlines()
    else:
        try:
            with open(tmpfilename, mode='r', encoding=sys.getfilesystemencoding()) as f:
                selected_files = f.read().splitlines()
        except OSError as e:
            message.error(f"Failed to open tempfile {tmpfilename} ({e})!")
            selected_files = []

    return list(_validated_selected_files(
        qb_mode=qb_mode, selected_files=selected_files))
Beispiel #3
0
 def test_double_exec(self):
     """Test double-executing."""
     self.loop = qtutils.EventLoop()
     QTimer.singleShot(100, self._assert_executing)
     QTimer.singleShot(200, self._double_exec)
     QTimer.singleShot(300, self._assert_executing)
     QTimer.singleShot(400, self.loop.quit)
     self.loop.exec_()
     assert not self.loop._executing
Beispiel #4
0
    def ask_question(self, question, blocking):
        """Dispkay a question in the statusbar.

        Args:
            question: The Question object to ask.
            blocking: If True, this function blocks and returns the result.

        Return:
            The answer of the user when blocking=True.
            None if blocking=False.
        """
        log.statusbar.debug("Asking question {}, blocking {}, loops {}, queue "
                            "{}".format(question, blocking, self._loops,
                                        self._queue))

        if self._shutting_down:
            # If we're currently shutting down we have to ignore this question
            # to avoid segfaults - see
            # https://github.com/The-Compiler/qutebrowser/issues/95
            log.statusbar.debug("Ignoring question because we're shutting "
                                "down.")
            question.abort()
            return None

        if self._busy and not blocking:
            # We got an async question, but we're already busy with one, so we
            # just queue it up for later.
            log.statusbar.debug("Adding {} to queue.".format(question))
            self._queue.append(question)
            return

        if blocking:
            # If we're blocking we save the old state on the stack, so we can
            # restore it after exec, if exec gets called multiple times.
            context = self._get_ctx()

        self._question = question
        self._display_question()
        mode = self.KEY_MODES[self._question.mode]
        question.aborted.connect(
            lambda: modeman.maybe_leave(self._win_id, mode, 'aborted'))
        modeman.enter(self._win_id, mode, 'question asked')
        if blocking:
            loop = qtutils.EventLoop()
            self._loops.append(loop)
            loop.destroyed.connect(lambda: self._loops.remove(loop))
            question.completed.connect(loop.quit)
            question.completed.connect(loop.deleteLater)
            loop.exec_()
            if not self._restore_ctx(context):
                # Nothing left to restore, so we can go back to popping async
                # questions.
                if self._queue:
                    self._pop_later()
            return self._question.answer
        else:
            question.completed.connect(self._pop_later)
Beispiel #5
0
    def ask_question(self, question, blocking):
        """Dispkay a question in the statusbar.

        Args:
            question: The Question object to ask.
            blocking: If True, this function blocks and returns the result.

        Return:
            The answer of the user when blocking=True.
            None if blocking=False.
        """
        log.statusbar.debug("Asking question {}, blocking {}, loops {}, queue "
                            "{}".format(question, blocking, self._loops,
                                        self._queue))

        if self._busy and not blocking:
            # We got an async question, but we're already busy with one, so we
            # just queue it up for later.
            log.statusbar.debug("Adding {} to queue.".format(question))
            self._queue.append(question)
            return

        if blocking:
            # If we're blocking we save the old state on the stack, so we can
            # restore it after exec, if exec gets called multiple times.
            context = self._get_ctx()

        self._question = question
        mode = self._display_question()
        question.aborted.connect(
            lambda: modeman.maybe_leave(self._win_id, mode, 'aborted'))
        mode_manager = objreg.get('mode-manager',
                                  scope='window',
                                  window=self._win_id)
        try:
            modeman.enter(self._win_id, mode, 'question asked', override=True)
        except modeman.ModeLockedError:
            if mode_manager.mode() != usertypes.KeyMode.prompt:
                question.abort()
                return None
        mode_manager.locked = True
        if blocking:
            loop = qtutils.EventLoop()
            self._loops.append(loop)
            loop.destroyed.connect(lambda: self._loops.remove(loop))
            question.completed.connect(loop.quit)
            question.completed.connect(loop.deleteLater)
            loop.exec_()
            if not self._restore_ctx(context):
                # Nothing left to restore, so we can go back to popping async
                # questions.
                if self._queue:
                    self._pop_later()
            return self._question.answer
        else:
            question.completed.connect(self._pop_later)
Beispiel #6
0
def choose_file(multiple: bool) -> List[str]:
    """Select file(s) for uploading, using external command defined in config.

    Args:
        multiple: Should selecting multiple files be allowed.

    Return:
        A list of selected file paths, or empty list if no file is selected.
        If multiple is False, the return value will have at most 1 item.
    """
    handle = tempfile.NamedTemporaryFile(prefix='qutebrowser-fileselect-', delete=False)
    handle.close()
    tmpfilename = handle.name
    with utils.cleanup_file(tmpfilename):
        if multiple:
            command = config.val.fileselect.multiple_files.command
        else:
            command = config.val.fileselect.single_file.command

        proc = guiprocess.GUIProcess(what='choose-file')
        proc.start(command[0],
                   [arg.replace('{}', tmpfilename) for arg in command[1:]])

        loop = qtutils.EventLoop()
        proc.finished.connect(lambda _code, _status: loop.exit())
        loop.exec()

        try:
            with open(tmpfilename, mode='r', encoding=sys.getfilesystemencoding()) as f:
                selected_files = f.read().splitlines()
        except OSError as e:
            message.error(f"Failed to open tempfile {tmpfilename} ({e})!")
            selected_files = []

    if not multiple:
        if len(selected_files) > 1:
            message.warning("More than one file chosen, using only the first")
            return selected_files[:1]
    return selected_files
Beispiel #7
0
    def ask_question(self, question, blocking):
        """Display a prompt for a given question.

        Args:
            question: The Question object to ask.
            blocking: If True, this function blocks and returns the result.

        Return:
            The answer of the user when blocking=True.
            None if blocking=False.
        """
        log.prompt.debug("Asking question {}, blocking {}, loops {}, queue "
                         "{}".format(question, blocking, self._loops,
                                     self._queue))

        if self._shutting_down:
            # If we're currently shutting down we have to ignore this question
            # to avoid segfaults - see
            # https://github.com/qutebrowser/qutebrowser/issues/95
            log.prompt.debug("Ignoring question because we're shutting down.")
            question.abort()
            return None

        if self._question is not None and not blocking:
            # We got an async question, but we're already busy with one, so we
            # just queue it up for later.
            log.prompt.debug("Adding {} to queue.".format(question))
            self._queue.append(question)
            return None

        if blocking:
            # If we're blocking we save the old question on the stack, so we
            # can restore it after exec, if exec gets called multiple times.
            log.prompt.debug("New question is blocking, saving {}".format(
                self._question))
            old_question = self._question
            if old_question is not None:
                old_question.interrupted = True

        self._question = question
        self.show_prompts.emit(question)

        if blocking:
            loop = qtutils.EventLoop()
            self._loops.append(loop)
            loop.destroyed.connect(lambda: self._loops.remove(loop))
            question.completed.connect(loop.quit)
            question.completed.connect(loop.deleteLater)
            log.prompt.debug("Starting loop.exec_() for {}".format(question))
            flags = cast(QEventLoop.ProcessEventsFlags,
                         QEventLoop.ExcludeSocketNotifiers)
            loop.exec_(flags)
            log.prompt.debug("Ending loop.exec_() for {}".format(question))

            log.prompt.debug("Restoring old question {}".format(old_question))
            self._question = old_question
            self.show_prompts.emit(old_question)
            if old_question is None:
                # Nothing left to restore, so we can go back to popping async
                # questions.
                if self._queue:
                    self._pop_later()

            return question.answer
        else:
            question.completed.connect(self._pop_later)
            return None
Beispiel #8
0
 def _wait(self):
     """Wait until a reply from the remote server is received."""
     if self._manager is not None:
         loop = qtutils.EventLoop()
         self.finished.connect(loop.quit)
         loop.exec_()