コード例 #1
0
ファイル: styles.py プロジェクト: sanjayankur31/vimiv-qt
def get(name: str) -> str:
    """Return style option for a given name."""
    try:
        return _style["{%s}" % (name)]
    except KeyError:
        log.error("Style option '%s' not found, falling back to default", name)
        return ""
コード例 #2
0
 def enter(self) -> None:
     """Override enter to ensure we are not in read-only mode when manipulating."""
     if settings.read_only:
         log.error(
             "Manipulate mode is disabled due to read-only being active")
     else:
         super().enter()
コード例 #3
0
ファイル: runners.py プロジェクト: jkrass1/vimiv-qt
def _run_command(count: str, cmdname: str, args: List[str],
                 mode: api.modes.Mode) -> None:
    """Run a given command.

    Args:
        count: Count to use for the command.
        cmdname: Name of the command passed.
        args: Arguments passed.
        mode: Mode to run the command in.
    """
    try:
        cmd = api.commands.get(cmdname, mode)
        if cmd.store:
            _last_command[mode] = LastCommand(count, cmdname, args)
        cmd(args, count=count)
        api.status.update("ran command")
    except api.commands.CommandNotFound as e:
        log.error(str(e))
        raise CommandPartFailed from e
    except (
            api.commands.ArgumentError,
            api.commands.CommandError,
            api.modes.InvalidMode,
    ) as e:
        log.error("%s: %s", cmdname, e)
        raise CommandPartFailed from e
    except api.commands.CommandWarning as w:
        log.warning("%s: %s", cmdname, str(w))
        raise CommandPartFailed from w
    except api.commands.CommandInfo as i:
        log.info("%s: %s", cmdname, i)
        raise CommandPartFailed from i
コード例 #4
0
ファイル: thumbnail.py プロジェクト: sanjayankur31/vimiv-qt
    def _on_new_images_opened(self, paths: List[str]):
        """Load new paths into thumbnail widget.

        Args:
            paths: List of new paths to load.
        """
        if paths == self._paths:  # Nothing to do
            _logger.debug("No new images to load")
            return
        _logger.debug("Loading %d new images", len(paths))
        # Delete paths that are no longer here
        # We must go in reverse order as otherwise the indexing changes on the
        # fly
        for i, path in enumerate(self._paths[::-1]):
            if path not in paths:
                _logger.debug("Removing existing thumbnail '%s'", path)
                if not self.takeItem(len(self._paths) - 1 - i):
                    log.error("Error removing thumbnail for %s", path)
        # Add new paths
        size_hint = QSize(self.item_size(), self.item_size())
        for i, path in enumerate(paths):
            if path not in self._paths:
                _logger.debug("Adding new thumbnail '%s'", path)
                marked = path in api.mark.paths
                ThumbnailItem(self, i, marked=marked, size_hint=size_hint)
        # Update paths and create thumbnails
        self._paths = paths
        self._manager.create_thumbnails_async(paths)
コード例 #5
0
ファイル: exif.py プロジェクト: sanjayankur31/vimiv-qt
    def __init__(self, filename):
        super().__init__()
        self._exif = None

        if piexif is None:
            log.error("%s relies on exif support", self.__class__.__qualname__)
        else:
            self._load_exif(filename)
コード例 #6
0
 def _monitor(self, directory: str) -> None:
     """Monitor the directory by adding it to QFileSystemWatcher."""
     if not settings.monitor_fs.value:
         return
     if not self.addPath(directory):
         log.error("Cannot monitor %s", directory)
     else:
         _logger.debug("Monitoring %s", directory)
コード例 #7
0
def _add_aliases(configsection):
    """Add optional aliases defined in the alias section to AliasRunner.

    Args:
        configsection: ALIASES section in the config file.
    """
    for name, command in configsection.items():
        try:
            aliases.alias(name, [command], "global")
        except api.commands.CommandError as e:
            log.error("Reading aliases from config: %s", str(e))
コード例 #8
0
 def _on_finished(self, exitcode, exitstatus):
     """Check exit status and possibly process standard output on completion."""
     if exitstatus != QProcess.NormalExit or exitcode != 0:
         log.error(
             "Error running external process '%s':\n%s",
             self.program(),
             qbytearray_to_str(self.readAllStandardError()).strip(),
         )
     elif self._pipe:
         self._process_pipe()
     else:
         _logger.debug("Finished external process '%s' succesfully", self.program())
コード例 #9
0
ファイル: _modules.py プロジェクト: jcjgraf/vimiv-qt
def copy_image(
    primary: bool = False,
    width: int = None,
    height: int = None,
    size: int = None,
    count: int = None,
) -> None:
    """Copy currently selected image to system clipboard.

    **syntax:** ``:copy-image [--primary] [--width=WIDTH] [--height=HEIGHT]
    [--size=SIZE]``

    optional arguments:
        * ``--primary``: Copy to primary selection.
        * ``--width``: Scale width to the specified value.
        * ``--height``: Scale height to the specified value.
        * ``--size``: Scale longer side to the specified value.

    **count:** Equivalent to the ``--size`` option
    """
    clipboard = QGuiApplication.clipboard()
    mode = QClipboard.Selection if primary else QClipboard.Clipboard
    path = api.current_path()

    try:
        reader = imagereader.get_reader(path)
        pixmap = reader.get_pixmap()
    except ValueError as e:
        log.error(str(e))
        return

    if size or count:
        pix_size = pixmap.size()

        size = count if count is not None else size

        if pix_size.height() >= pix_size.width():
            _logger.debug(f"Copy image with size {size} restricting height")
            pixmap = pixmap.scaledToHeight(size)  # type: ignore[arg-type]
        else:
            _logger.debug(f"Copy image with size {size} restricting width")
            pixmap = pixmap.scaledToWidth(size)  # type: ignore[arg-type]

    elif width:
        _logger.debug(f"Copy image with width {width}")
        pixmap = pixmap.scaledToWidth(width)

    elif height:
        _logger.debug(f"Copy image with height {height}")
        pixmap = pixmap.scaledToHeight(height)

    clipboard.setPixmap(pixmap, mode=mode)
コード例 #10
0
 def chdir(self, directory: str, reload_current: bool = False) -> None:
     """Change the current working directory to directory."""
     directory = os.path.abspath(directory)
     if directory != self._dir or reload_current:
         _logger.debug("Changing directory to '%s'", directory)
         if self.directories():  # Unmonitor old directories
             self.removePaths(self.directories())
         try:
             os.chdir(directory)
             self._load_directory(directory)
             self._monitor(directory)
         except PermissionError as e:
             log.error("%s: Cannot access '%s'", str(e), directory)
         else:
             _logger.debug("Directory change completed")
コード例 #11
0
ファイル: startup.py プロジェクト: jkrass1/vimiv-qt
def update_settings(args: argparse.Namespace) -> None:
    """Update default settings with command line arguments and configfiles.

    Args:
        args: Arguments returned from parser.parse_args().
    """
    configfile.parse(args.config)
    for option, value in args.cmd_settings:
        try:
            setting = api.settings.get(option)
            setting.value = value
        except KeyError:
            log.error("Unknown setting %s", option)
        except ValueError as e:
            log.error(str(e))
    keyfile.parse(args.keyfile)
    styles.parse()
コード例 #12
0
ファイル: runners.py プロジェクト: jkrass1/vimiv-qt
def command(text: str, mode: api.modes.Mode = None) -> None:
    """Run internal command when called.

    Splits the given text into count, name and arguments. Then runs the
    command corresponding to name with count and arguments. Emits the
    exited signal when done.

    Args:
        text: String passed as command.
        mode: Mode in which the command is supposed to run.
    """
    try:
        count, cmdname, args = _parse(text)
    except ValueError as e:  # E.g. raised by shlex on unclosed quotation
        log.error("Error parsing command: %s", e)
        return
    mode = mode if mode is not None else api.modes.current()
    _run_command(count, cmdname, args, mode)
    _logger.debug("Ran '%s' succesfully", text)
コード例 #13
0
ファイル: styles.py プロジェクト: sanjayankur31/vimiv-qt
def parse():
    """Setup the style.

    Checks for a style name and reads it from file. If the name is default, the
    defaults are simply used and the default style file is written to disk for
    reference.
    """
    global _style
    name = api.settings.style.value
    _logger.debug("Parsing style '%s'", name)
    filename = abspath(name)
    if name == NAME_DEFAULT:
        _style = create_default()
    elif name == NAME_DEFAULT_DARK:
        _style = create_default(dark=True)
    elif os.path.exists(filename):
        _style = read(filename)
    else:
        log.error("Style file '%s' not found, falling back to default", filename)
        _style = create_default()
コード例 #14
0
ファイル: __init__.py プロジェクト: karlch/vimiv-qt
def _load_plugin(name: str, info: str, directory: str) -> None:
    """Load a single plugin.

    Args:
        name: Name of the plugin as python module.
        info: Additional information string passed to the plugin's init.
        directory: Directory in which the python module is located.
    """
    _logger.debug("Loading plugin '%s' from '%s'", name, directory)
    try:
        module = importlib.import_module(name, directory)
    except (ImportError, SyntaxError) as e:
        log.error("Importing plugin '%s': %s", name, str(e))
        return
    try:
        module.init(info)
        _logger.debug("Initialized '%s'", name)
    except AttributeError:
        _logger.debug("Plugin '%s' does not define init()", name)
    _logger.debug("Loaded '%s' successfully", name)
    _loaded_plugins[name] = module
コード例 #15
0
    def _load(self, path: str, keep_zoom: bool):
        """Load proper displayable QWidget for a path.

        This reads the image using QImageReader and then emits the appropriate
        *_loaded signal to tell the image to display a new object.
        """
        try:
            reader = imagereader.get_reader(path)
        except ValueError as e:
            log.error(str(e))
            return
        # SVG
        if reader.is_vectorgraphic and QtSvg is not None:
            # Do not store image and only emit with the path as the
            # VectorGraphic widget needs the path in the constructor
            api.signals.svg_loaded.emit(path, keep_zoom)
            self._edit_handler.clear()
        # Gif
        elif reader.is_animation:
            movie = QMovie(path)
            if not movie.isValid() or movie.frameCount() == 0:
                log.error("Error reading animation %s: invalid data", path)
                return
            api.signals.movie_loaded.emit(movie, keep_zoom)
            self._edit_handler.clear()
        # Regular image
        else:
            try:
                pixmap = reader.get_pixmap()
            except ValueError as e:
                log.error("%s", e)
                return
            self._edit_handler.pixmap = pixmap
            api.signals.pixmap_loaded.emit(pixmap, keep_zoom)
        self._path = path
コード例 #16
0
ファイル: crash_handler.py プロジェクト: karlch/vimiv-qt
    def handle_exception(
        self,
        initial_handler: ExceptionHandler,
        exc_type: Type[BaseException],
        exc_value: BaseException,
        traceback: types.TracebackType,
    ) -> None:
        """Custom exception handler for uncaught exceptions.

        In addition to the standard python exception handler a log message is called and
        the application tries to exit gracefully.
        """
        log.error("Uncaught exception! Exiting gracefully and printing stack...")
        initial_handler(exc_type, exc_value, traceback)
        try:
            self._app.exit(customtypes.Exit.err_exception)
        # We exit immediately by killing the application if an error in the graceful
        # exit occurs
        except Exception as e:  # pylint: disable=broad-except
            log.fatal("Uncaught exception in graceful exit... Committing suicide :(")
            log.fatal("Exception: %r", e)
            sys.exit(customtypes.Exit.err_suicide)
コード例 #17
0
def write_pixmap(pixmap, path, original_path):
    """Write pixmap to file.

    This requires both the path to write to and the original path as Exif data
    may be copied from the original path to the new copy. The procedure is to
    write the path to a temporary file first, transplant the Exif data to the
    temporary file if possible and finally rename the temporary file to the
    final path. The renaming is done as it is an atomic operation and we may be
    overriding the existing file.

    Args:
        pixmap: The QPixmap to write.
        path: Path to write the pixmap to.
        original_path: Original path of the opened pixmap to retrieve exif information.
    """
    try:
        _can_write(pixmap, path)
        _logger.debug("Image is writable")
        _write(pixmap, path, original_path)
        log.info("Saved %s", path)
    except WriteError as e:
        log.error(str(e))
コード例 #18
0
    def _load(self, path: str, reload_only: bool):
        """Load proper displayable QWidget for a path.

        This reads the image using QImageReader and then emits the appropriate
        *_loaded signal to tell the image to display a new object.
        """
        # Pass file format explicitly as imghdr does a much better job at this than the
        # file name based approach of QImageReader
        file_format = files.imghdr.what(path)
        if file_format is None:
            log.error("%s is not a valid image", path)
            return
        reader = QImageReader(path, file_format.encode("utf-8"))
        reader.setAutoTransform(True)  # Automatically apply exif orientation
        if not reader.canRead():
            log.error("Cannot read image %s", path)
            return
        # SVG
        if file_format == "svg" and QSvgWidget:
            # Do not store image and only emit with the path as the
            # VectorGraphic widget needs the path in the constructor
            self.original = None
            api.signals.svg_loaded.emit(path, reload_only)
            self._image_type = ImageType.Svg
        # Gif
        elif reader.supportsAnimation():
            movie = QMovie(path)
            if not movie.isValid() or movie.frameCount() == 0:
                log.error("Error reading animation %s: invalid data", path)
                return
            self.original = movie
            api.signals.movie_loaded.emit(self.current, reload_only)
            self._image_type = ImageType.Movie
        # Regular image
        else:
            pixmap = QPixmap.fromImageReader(reader)
            if reader.error():
                log.error("Error reading image %s: %s", path, reader.errorString())
                return
            self.original = pixmap
            api.signals.pixmap_loaded.emit(self.current, reload_only)
            self._image_type = ImageType.Pixmap
        self._path = path
コード例 #19
0
 def _on_error(self, error):
     log.error("Error running '%s': %s", self.program(), self.error_messages[error])