예제 #1
0
def later(ms: int, command: str, win_id: int) -> None:
    """Execute a command after some time.

    Args:
        ms: How many milliseconds to wait.
        command: The command to run, with optional args.
    """
    if ms < 0:
        raise cmdutils.CommandError("I can't run something in the past!")
    commandrunner = runners.CommandRunner(win_id)
    app = objreg.get('app')
    timer = usertypes.Timer(name='later', parent=app)
    try:
        timer.setSingleShot(True)
        try:
            timer.setInterval(ms)
        except OverflowError:
            raise cmdutils.CommandError("Numeric argument is too large for "
                                        "internal int representation.")
        timer.timeout.connect(
            functools.partial(commandrunner.run_safely, command))
        timer.timeout.connect(timer.deleteLater)
        timer.start()
    except:
        timer.deleteLater()
        raise
예제 #2
0
def run_async(tab, cmd, *args, win_id, env, verbose=False):
    """Run a userscript after dumping page html/source.

    Raises:
        UnsupportedError if userscripts are not supported on the current
        platform.
        NotFoundError if the command could not be found.

    Args:
        tab: The WebKitTab/WebEngineTab to get the source from.
        cmd: The userscript binary to run.
        *args: The arguments to pass to the userscript.
        win_id: The window id the userscript is executed in.
        env: A dictionary of variables to add to the process environment.
        verbose: Show notifications when the command started/exited.
    """
    tabbed_browser = objreg.get('tabbed-browser',
                                scope='window',
                                window=win_id)
    commandrunner = runners.CommandRunner(win_id, parent=tabbed_browser)

    if utils.is_posix:
        runner = _POSIXUserscriptRunner(tabbed_browser)
    elif utils.is_windows:  # pragma: no cover
        runner = _WindowsUserscriptRunner(tabbed_browser)
    else:  # pragma: no cover
        raise UnsupportedError

    runner.got_cmd.connect(lambda cmd: log.commands.debug(
        "Got userscript command: {}".format(cmd)))
    runner.got_cmd.connect(commandrunner.run_safely)
    user_agent = config.val.content.headers.user_agent
    if user_agent is not None:
        env['QUTE_USER_AGENT'] = user_agent

    env['QUTE_CONFIG_DIR'] = standarddir.config()
    env['QUTE_DATA_DIR'] = standarddir.data()
    env['QUTE_DOWNLOAD_DIR'] = downloads.download_dir()
    env['QUTE_COMMANDLINE_TEXT'] = objreg.get('status-command',
                                              scope='window',
                                              window=win_id).text()

    cmd_path = os.path.expanduser(cmd)

    # if cmd is not given as an absolute path, look it up
    # ~/.local/share/glimpsebrowser/userscripts (or $XDG_DATA_HOME)
    if not os.path.isabs(cmd_path):
        log.misc.debug("{} is no absolute path".format(cmd_path))
        cmd_path = _lookup_path(cmd)
    elif not os.path.exists(cmd_path):
        raise NotFoundError(cmd_path)
    log.misc.debug("Userscript to run: {}".format(cmd_path))

    runner.finished.connect(commandrunner.deleteLater)
    runner.finished.connect(runner.deleteLater)

    runner.prepare_run(cmd_path, *args, env=env, verbose=verbose)
    tab.dump_async(runner.store_html)
    tab.dump_async(runner.store_text, plain=True)
    return runner
예제 #3
0
    def spawn(self, url, context):
        """Spawn a simple command from a hint.

        Args:
            url: The URL to open as a QUrl.
            context: The HintContext to use.
        """
        urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
        args = context.get_args(urlstr)
        commandrunner = runners.CommandRunner(self._win_id)
        commandrunner.run_safely('spawn ' + ' '.join(args))
예제 #4
0
    def run_cmd(self, url, context):
        """Run the command based on a hint URL.

        Args:
            url: The URL to open as a QUrl.
            context: The HintContext to use.
        """
        urlstr = url.toString(QUrl.FullyEncoded)
        args = context.get_args(urlstr)
        commandrunner = runners.CommandRunner(self._win_id)
        commandrunner.run_safely(' '.join(args))
예제 #5
0
def repeat_command(win_id, count=None):
    """Repeat the last executed command.

    Args:
        count: Which count to pass the command.
    """
    mode_manager = objreg.get('mode-manager', scope='window', window=win_id)
    if mode_manager.mode not in runners.last_command:
        raise cmdutils.CommandError("You didn't do anything yet.")
    cmd = runners.last_command[mode_manager.mode]
    commandrunner = runners.CommandRunner(win_id)
    commandrunner.run(cmd[0], count if count is not None else cmd[1])
예제 #6
0
def run_with_count(count_arg: int,
                   command: str,
                   win_id: int,
                   count: int = 1) -> None:
    """Run a command with the given count.

    If run_with_count itself is run with a count, it multiplies count_arg.

    Args:
        count_arg: The count to pass to the command.
        command: The command to run, with optional args.
        count: The count that run_with_count itself received.
    """
    runners.CommandRunner(win_id).run(command, count_arg * count)
예제 #7
0
    def run_macro(self, win_id, register):
        """Run a recorded macro."""
        if register == '@':
            if self._last_register is None:
                raise cmdutils.CommandError("No previous macro")
            register = self._last_register
        self._last_register = register

        if register not in self._macros:
            raise cmdutils.CommandError(
                "No macro recorded in '{}'!".format(register))

        commandrunner = runners.CommandRunner(win_id)
        for _ in range(self._macro_count[win_id]):
            for cmd in self._macros[register]:
                commandrunner.run_safely(*cmd)
예제 #8
0
def repeat(times: int, command: str, win_id: int, count: int = None) -> None:
    """Repeat a given command.

    Args:
        times: How many times to repeat.
        command: The command to run, with optional args.
        count: Multiplies with 'times' when given.
    """
    if count is not None:
        times *= count

    if times < 0:
        raise cmdutils.CommandError("A negative count doesn't make sense.")
    commandrunner = runners.CommandRunner(win_id)
    for _ in range(times):
        commandrunner.run_safely(command)
예제 #9
0
def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
    """Process positional commandline args.

    URLs to open have no prefix, commands to execute begin with a colon.

    Args:
        args: A list of arguments to process.
        via_ipc: Whether the arguments were transmitted over IPC.
        cwd: The cwd to use for fuzzy_url.
        target_arg: Command line argument received by a running instance via
                    ipc. If the --target argument was not specified, target_arg
                    will be an empty string.
    """
    if via_ipc and not args:
        win_id = mainwindow.get_window(via_ipc, force_window=True)
        _open_startpage(win_id)
        return
    win_id = None
    for cmd in args:
        if cmd.startswith(':'):
            if win_id is None:
                win_id = mainwindow.get_window(via_ipc, force_tab=True)
            log.init.debug("Startup cmd {!r}".format(cmd))
            commandrunner = runners.CommandRunner(win_id)
            commandrunner.run_safely(cmd[1:])
        elif not cmd:
            log.init.debug("Empty argument")
            win_id = mainwindow.get_window(via_ipc, force_window=True)
        else:
            if via_ipc and target_arg and target_arg != 'auto':
                open_target = target_arg
            else:
                open_target = None
            if not cwd:  # could also be an empty string due to the PyQt signal
                cwd = None
            try:
                url = urlutils.fuzzy_url(cmd, cwd, relative=True)
            except urlutils.InvalidUrlError as e:
                message.error("Error in startup argument '{}': {}".format(
                    cmd, e))
            else:
                win_id = open_url(url, target=open_target, via_ipc=via_ipc)
예제 #10
0
    def __init__(self, *, private, geometry=None, parent=None):
        """Create a new main window.

        Args:
            geometry: The geometry to load, as a bytes-object (or None).
            private: Whether the window is in private browsing mode.
            parent: The parent the window should get.
        """
        super().__init__(parent)
        # Late import to avoid a circular dependency
        # - browsertab -> hints -> webelem -> mainwindow -> bar -> browsertab
        from glimpsebrowser.mainwindow import tabbedbrowser
        from glimpsebrowser.mainwindow.statusbar import bar

        self.setAttribute(Qt.WA_DeleteOnClose)
        self._commandrunner = None
        self._overlays = []
        self.win_id = next(win_id_gen)
        self.registry = objreg.ObjectRegistry()
        objreg.window_registry[self.win_id] = self
        objreg.register('main-window',
                        self,
                        scope='window',
                        window=self.win_id)
        tab_registry = objreg.ObjectRegistry()
        objreg.register('tab-registry',
                        tab_registry,
                        scope='window',
                        window=self.win_id)

        message_bridge = message.MessageBridge(self)
        objreg.register('message-bridge',
                        message_bridge,
                        scope='window',
                        window=self.win_id)

        self.setWindowTitle('glimpsebrowser')
        self._vbox = QVBoxLayout(self)
        self._vbox.setContentsMargins(0, 0, 0, 0)
        self._vbox.setSpacing(0)

        self._init_downloadmanager()
        self._downloadview = downloadview.DownloadView(self.win_id)

        if config.val.content.private_browsing:
            # This setting always trumps what's passed in.
            private = True
        else:
            private = bool(private)
        self._private = private
        self.tabbed_browser = tabbedbrowser.TabbedBrowser(win_id=self.win_id,
                                                          private=private,
                                                          parent=self)
        objreg.register('tabbed-browser',
                        self.tabbed_browser,
                        scope='window',
                        window=self.win_id)
        self._init_command_dispatcher()

        # We need to set an explicit parent for StatusBar because it does some
        # show/hide magic immediately which would mean it'd show up as a
        # window.
        self.status = bar.StatusBar(win_id=self.win_id,
                                    private=private,
                                    parent=self)

        self._add_widgets()
        self._downloadview.show()

        self._init_completion()

        log.init.debug("Initializing modes...")
        modeman.init(self.win_id, self)

        self._commandrunner = runners.CommandRunner(self.win_id,
                                                    partial_match=True)

        self._keyhint = keyhintwidget.KeyHintView(self.win_id, self)
        self._add_overlay(self._keyhint, self._keyhint.update_geometry)

        self._prompt_container = prompt.PromptContainer(self.win_id, self)
        self._add_overlay(self._prompt_container,
                          self._prompt_container.update_geometry,
                          centered=True,
                          padding=10)
        objreg.register('prompt-container',
                        self._prompt_container,
                        scope='window',
                        window=self.win_id)
        self._prompt_container.hide()

        self._messageview = messageview.MessageView(parent=self)
        self._add_overlay(self._messageview, self._messageview.update_geometry)

        self._init_geometry(geometry)
        self._connect_signals()

        # When we're here the statusbar might not even really exist yet, so
        # resizing will fail. Therefore, we use singleShot QTimers to make sure
        # we defer this until everything else is initialized.
        QTimer.singleShot(0, self._connect_overlay_signals)
        config.instance.changed.connect(self._on_config_changed)

        objreg.get("app").new_window.emit(self)
        self._set_decoration(config.val.window.hide_decoration)

        self.state_before_fullscreen = self.windowState()
        config.set_register_stylesheet(self)
예제 #11
0
 def __init__(self, win_id, parent=None, supports_count=None):
     super().__init__(win_id, parent, supports_count)
     self._commandrunner = runners.CommandRunner(win_id)