about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/__init__.py1
-rw-r--r--ranger/config/rc.conf2
-rw-r--r--ranger/container/file.py3
-rw-r--r--ranger/core/actions.py38
-rw-r--r--ranger/core/main.py6
-rwxr-xr-xranger/data/scope.sh5
-rw-r--r--ranger/gui/widgets/browsercolumn.py5
7 files changed, 54 insertions, 6 deletions
diff --git a/ranger/__init__.py b/ranger/__init__.py
index 05e6cdd5..f6b17b10 100644
--- a/ranger/__init__.py
+++ b/ranger/__init__.py
@@ -25,6 +25,7 @@ MAX_RESTORABLE_TABS = 3
 MACRO_DELIMITER = '%'
 DEFAULT_PAGER = 'less'
 LOGFILE = '/tmp/ranger_errorlog'
+CACHEDIR = os.path.expanduser("~/.cache/ranger")
 USAGE = '%prog [options] [path]'
 VERSION = 'ranger-master %s\n\nPython %s' % (__version__, sys.version)
 
diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf
index 47ed9a91..e5d68926 100644
--- a/ranger/config/rc.conf
+++ b/ranger/config/rc.conf
@@ -38,7 +38,7 @@ set confirm_on_delete multiple
 # README for dependencies) to preview images, archives, etc.
 set preview_script ~/.config/ranger/scope.sh
 
-# Use the external preview script or display simple plain text previews?
+# Use the external preview script or display simple plain text or image previews?
 set use_preview_script true
 
 # Open all images in this directory when running certain image viewers
diff --git a/ranger/container/file.py b/ranger/container/file.py
index 86e83a92..b1245647 100644
--- a/ranger/container/file.py
+++ b/ranger/container/file.py
@@ -90,3 +90,6 @@ class File(FileSystemObject):
 
     def get_preview_source(self, width, height):
         return self.fm.get_preview(self, width, height)
+
+    def is_image_preview(self):
+        return 'imagepreview' in self.fm.previews[self.realpath]
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index eb9169a6..08b998eb 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -11,6 +11,8 @@ from os.path import join, isdir, realpath, exists
 from os import link, symlink, getcwd, listdir, stat
 from inspect import cleandoc
 from stat import S_IEXEC
+from hashlib import sha1
+from sys import version_info
 
 import ranger
 from ranger.ext.direction import Direction
@@ -789,7 +791,11 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
         if self.settings.preview_images and self.thisfile.image:
             pager.set_image(self.thisfile.realpath)
         else:
-            pager.set_source(self.thisfile.get_preview_source(pager.wid, pager.hei))
+            f = self.thisfile.get_preview_source(pager.wid, pager.hei)
+            if self.thisfile.is_image_preview:
+                pager.set_image(f)
+            else:
+                pager.set_source(f)
 
     # --------------------------
     # -- Previews
@@ -801,6 +807,15 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
         except:
             return False
 
+    if version_info[0] == 3:
+        def sha1_encode(self, path):
+            return os.path.join(ranger.CACHEDIR,
+                    sha1(path.encode('utf-8')).hexdigest()) + '.jpg'
+    else:
+        def sha1_encode(self, path):
+            return os.path.join(ranger.CACHEDIR,
+                    sha1(path).hexdigest()) + '.jpg'
+
     def get_preview(self, file, width, height):
         pager = self.ui.get_pager()
         path = file.realpath
@@ -843,8 +858,17 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
                     return None
 
                 data['loading'] = True
+
+                cacheimg = os.path.join(ranger.CACHEDIR, self.sha1_encode(path))
+                if (os.path.isfile(cacheimg) and os.path.getmtime(cacheimg) > os.path.getmtime(path)):
+                    data['foundpreview'] = True
+                    data['imagepreview'] = True
+                    pager.set_image(cacheimg)
+                    data['loading'] = False
+                    return cacheimg
+
                 loadable = CommandLoader(args=[self.settings.preview_script,
-                    path, str(width), str(height)], read=True,
+                    path, str(width), str(height), cacheimg], read=True,
                     silent=True, descr="Getting preview of %s" % path)
                 def on_after(signal):
                     exit = signal.process.poll()
@@ -858,6 +882,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
                         data[(width, -1)] = content
                     elif exit == 5:
                         data[(-1, -1)] = content
+                    elif exit == 6:
+                        data['imagepreview'] = True
                     elif exit == 1:
                         data[(-1, -1)] = None
                         data['foundpreview'] = False
@@ -878,8 +904,12 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
                     data['loading'] = False
                     pager = self.ui.get_pager()
                     if self.thisfile and self.thisfile.is_file:
-                        pager.set_source(self.thisfile.get_preview_source(
-                            pager.wid, pager.hei))
+                        if 'imagepreview' in data:
+                            pager.set_image(cacheimg)
+                            return cacheimg
+                        else:
+                            pager.set_source(self.thisfile.get_preview_source(
+                                pager.wid, pager.hei))
                 def on_destroy(signal):
                     try:
                         del self.previews[path]
diff --git a/ranger/core/main.py b/ranger/core/main.py
index e03e95ba..b0ae4a26 100644
--- a/ranger/core/main.py
+++ b/ranger/core/main.py
@@ -110,6 +110,12 @@ def main():
             from ranger.ext import curses_interrupt_handler
             curses_interrupt_handler.install_interrupt_handler()
 
+        # Create cache directory
+        if fm.settings.preview_images and fm.settings.use_preview_script:
+            from ranger import CACHEDIR
+            if not os.path.exists(CACHEDIR):
+                os.makedirs(CACHEDIR)
+
         # Run the file manager
         fm.initialize()
         ranger.api.hook_init(fm)
diff --git a/ranger/data/scope.sh b/ranger/data/scope.sh
index 9f7aaf1c..ce9ee574 100755
--- a/ranger/data/scope.sh
+++ b/ranger/data/scope.sh
@@ -16,11 +16,13 @@
 # 3    | fix width  | success. Don't reload when width changes
 # 4    | fix height | success. Don't reload when height changes
 # 5    | fix both   | success. Don't ever reload
+# 6    | image      | success. display the image $cached points to as an image preview
 
 # Meaningful aliases for arguments:
 path="$1"    # Full path of the selected file
 width="$2"   # Width of the preview pane (number of fitting characters)
 height="$3"  # Height of the preview pane (number of fitting characters)
+cached="$4"  # Path that should be used to cache image previews
 
 maxln=200    # Stop after $maxln lines.  Can be used like ls | head -n $maxln
 
@@ -74,6 +76,9 @@ case "$mimetype" in
     # Ascii-previews of images:
     image/*)
         img2txt --gamma=0.6 --width="$width" "$path" && exit 4 || exit 1;;
+    # Image preview for videos, disabled by default:
+    # video/*)
+    #     ffmpegthumbnailer -i "$path" -o "$cached" -s 0 && exit 6 || exit 1;;
     # Display information about media files:
     video/* | audio/*)
         exiftool "$path" && exit 5
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index c178474b..0edb9c8d 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -186,7 +186,10 @@ class BrowserColumn(Pager):
             if f is None:
                 Pager.close(self)
             else:
-                self.set_source(f)
+                if self.target.is_image_preview():
+                    self.set_image(f)
+                else:
+                    self.set_source(f)
                 Pager.draw(self)
 
     def _draw_directory(self):