summary refs log tree commit diff stats
path: root/ranger/gui/widgets/browsercolumn.py
diff options
context:
space:
mode:
Diffstat (limited to 'ranger/gui/widgets/browsercolumn.py')
-rw-r--r--ranger/gui/widgets/browsercolumn.py758
1 files changed, 379 insertions, 379 deletions
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index 3324d9a8..a6653070 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -13,382 +13,382 @@ from ranger.fsobject import BAD_INFO
 from ranger.ext.widestring import WideString
 
 class BrowserColumn(Pager):
-	main_column = False
-	display_infostring = False
-	scroll_begin = 0
-	target = None
-	last_redraw_time = -1
-	ellipsis = { False: '~', True: '…' }
-
-	old_dir = None
-	old_thisfile = None
-
-	def __init__(self, win, level):
-		"""
-		win = the curses window object of the BrowserView
-		level = what to display?
-
-		level >0 => previews
-		level 0 => current file/directory
-		level <0 => parent directories
-		"""
-		Pager.__init__(self, win)
-		Widget.__init__(self, win)
-		self.level = level
-		self.original_level = level
-
-		self.settings.signal_bind('setopt.display_size_in_main_column',
-				self.request_redraw, weak=True)
-
-	def request_redraw(self):
-		self.need_redraw = True
-
-	def resize(self, y, x, hei, wid):
-		Widget.resize(self, y, x, hei, wid)
-
-	def click(self, event):
-		"""Handle a MouseEvent"""
-		direction = event.mouse_wheel_direction()
-		if not (event.pressed(1) or event.pressed(3) or direction):
-			return False
-
-		if self.target is None:
-			pass
-
-		elif self.target.is_directory:
-			if self.target.accessible and self.target.content_loaded:
-				index = self.scroll_begin + event.y - self.y
-
-				if direction:
-					if self.level == -1:
-						self.fm.move_parent(direction)
-					else:
-						return False
-				elif event.pressed(1):
-					if not self.main_column:
-						self.fm.enter_dir(self.target.path)
-
-					if index < len(self.target):
-						self.fm.move(to=index)
-				elif event.pressed(3):
-					try:
-						clicked_file = self.target.files[index]
-						if clicked_file.is_directory:
-							self.fm.enter_dir(clicked_file.path)
-						elif self.level == 0:
-							self.fm.thisdir.move_to_obj(clicked_file)
-							self.fm.execute_file(clicked_file)
-					except:
-						pass
-
-		else:
-			if self.level > 0 and not direction:
-				self.fm.move(right=0)
-
-		return True
-
-	def execute_curses_batch(self, line, commands):
-		"""
-		Executes a list of "commands" which can be easily cached.
-
-		"commands" is a list of lists.  Each element contains
-		a text and an attribute.  First, the attribute will be
-		set with attrset, then the text is printed.
-
-		Example:
-		execute_curses_batch(0, [["hello ", 0], ["world", curses.A_BOLD]])
-		"""
-		try:
-			self.win.move(line, 0)
-		except:
-			return
-		for entry in commands:
-			text, attr = entry
-			self.addstr(text, attr)
-
-	def has_preview(self):
-		if self.target is None:
-			return False
-
-		if self.target.is_file:
-			if not self.target.has_preview():
-				return False
-
-		if self.target.is_directory:
-			if self.level > 0 and not self.settings.preview_directories:
-				return False
-
-		return True
-
-	def level_shift(self, amount):
-		self.level = self.original_level + amount
-
-	def level_restore(self):
-		self.level = self.original_level
-
-	def poke(self):
-		Widget.poke(self)
-		self.target = self.fm.thistab.at_level(self.level)
-
-	def draw(self):
-		"""Call either _draw_file() or _draw_directory()"""
-		if self.target != self.old_dir:
-			self.need_redraw = True
-			self.old_dir = self.target
-
-		if self.target:  # don't garbage collect this directory please
-			self.target.use()
-
-		if self.target and self.target.is_directory \
-				and (self.level <= 0 or self.settings.preview_directories):
-			if self.target.pointed_obj != self.old_thisfile:
-				self.need_redraw = True
-				self.old_thisfile = self.target.pointed_obj
-
-			if self.target.load_content_if_outdated() \
-			or self.target.sort_if_outdated() \
-			or self.last_redraw_time < self.target.last_update_time:
-				self.need_redraw = True
-
-		if self.need_redraw:
-			self.win.erase()
-			if self.target is None:
-				pass
-			elif self.target.is_file:
-				Pager.open(self)
-				self._draw_file()
-			elif self.target.is_directory:
-				self._draw_directory()
-				Widget.draw(self)
-			self.need_redraw = False
-			self.last_redraw_time = time()
-
-	def _draw_file(self):
-		"""Draw a preview of the file, if the settings allow it"""
-		self.win.move(0, 0)
-		if not self.target.accessible:
-			self.addnstr("not accessible", self.wid)
-			Pager.close(self)
-			return
-
-		if self.target is None or not self.target.has_preview():
-			Pager.close(self)
-			return
-
-		if self.fm.settings.preview_images and self.target.image:
-			self.set_image(self.target.realpath)
-			Pager.draw(self)
-		else:
-			f = self.target.get_preview_source(self.wid, self.hei)
-			if f is None:
-				Pager.close(self)
-			else:
-				self.set_source(f)
-				Pager.draw(self)
-
-	def _draw_directory(self):
-		"""Draw the contents of a directory"""
-		if self.image:
-			self.image = None
-			self.need_clear_image = True
-			Pager.clear_image(self)
-
-		if self.level > 0 and not self.settings.preview_directories:
-			return
-
-		base_color = ['in_browser']
-
-		self.win.move(0, 0)
-
-		if not self.target.content_loaded:
-			self.color(tuple(base_color))
-			self.addnstr("...", self.wid)
-			self.color_reset()
-			return
-
-		if self.main_column:
-			base_color.append('main_column')
-
-		if not self.target.accessible:
-			self.color(tuple(base_color + ['error']))
-			self.addnstr("not accessible", self.wid)
-			self.color_reset()
-			return
-
-		if self.target.empty():
-			self.color(tuple(base_color + ['empty']))
-			self.addnstr("empty", self.wid)
-			self.color_reset()
-			return
-
-		self._set_scroll_begin()
-
-		copied = [f.path for f in self.fm.copy_buffer]
-		ellipsis = self.ellipsis[self.settings.unicode_ellipsis]
-
-		selected_i = self.target.pointer
-		for line in range(self.hei):
-			i = line + self.scroll_begin
-			if line > self.hei:
-				break
-
-			try:
-				drawn = self.target.files[i]
-			except IndexError:
-				break
-
-			tagged = self.fm.tags and drawn.realpath in self.fm.tags
-			if tagged:
-				tagged_marker = self.fm.tags.marker(drawn.realpath)
-			else:
-				tagged_marker = " "
-
-			key = (self.wid, selected_i == i, drawn.marked, self.main_column,
-					drawn.path in copied, tagged_marker, drawn.infostring,
-					self.fm.do_cut)
-
-			if key in drawn.display_data:
-				self.execute_curses_batch(line, drawn.display_data[key])
-				self.color_reset()
-				continue
-
-			display_data = []
-			drawn.display_data[key] = display_data
-
-			if self.display_infostring and drawn.infostring \
-					and self.settings.display_size_in_main_column:
-				infostring = str(drawn.infostring) + " "
-			else:
-				infostring = ""
-
-			this_color = base_color + list(drawn.mimetype_tuple)
-			text = drawn.basename
-
-			space = self.wid - len(infostring)
-			if self.main_column:
-				space -= 2
-			elif self.settings.display_tags_in_all_columns:
-				space -= 1
-
-			if i == selected_i:
-				this_color.append('selected')
-
-			if drawn.marked:
-				this_color.append('marked')
-				if self.main_column or self.settings.display_tags_in_all_columns:
-					text = " " + text
-
-			if tagged:
-				this_color.append('tagged')
-
-			if drawn.is_directory:
-				this_color.append('directory')
-			else:
-				this_color.append('file')
-
-			if drawn.stat:
-				mode = drawn.stat.st_mode
-				if mode & stat.S_IXUSR:
-					this_color.append('executable')
-				if stat.S_ISFIFO(mode):
-					this_color.append('fifo')
-				if stat.S_ISSOCK(mode):
-					this_color.append('socket')
-				if drawn.is_device:
-					this_color.append('device')
-
-			if drawn.path in copied:
-				this_color.append('cut' if self.fm.do_cut else 'copied')
-
-			if drawn.is_link:
-				this_color.append('link')
-				this_color.append(drawn.exists and 'good' or 'bad')
-
-			attr = self.settings.colorscheme.get_attr(*this_color)
-
-			if (self.main_column or self.settings.display_tags_in_all_columns) \
-					and tagged and self.wid > 2:
-				this_color.append('tag_marker')
-				tag_attr = self.settings.colorscheme.get_attr(*this_color)
-				display_data.append([tagged_marker, tag_attr])
-			else:
-				text = " " + text
-				space += 1
-
-			wtext = WideString(text)
-			if len(wtext) > space:
-				wtext = wtext[:max(0, space - 1)] + ellipsis
-			text = str(wtext)
-
-			display_data.append([text, attr])
-
-			padding = self.wid - len(wtext)
-			if tagged and (self.main_column or \
-					self.settings.display_tags_in_all_columns):
-				padding -= 1
-			if infostring:
-				if len(wtext) + 1 + len(infostring) > self.wid:
-					pass
-				else:
-					padding -= len(infostring)
-					padding = max(0, padding)
-					infostring = (" " * padding) + infostring
-					display_data.append([infostring, attr])
-			else:
-				display_data.append([" " * max(0, padding), attr])
-
-			self.execute_curses_batch(line, display_data)
-			self.color_reset()
-
-	def _get_scroll_begin(self):
-		"""Determines scroll_begin (the position of the first displayed file)"""
-		offset = self.settings.scroll_offset
-		dirsize = len(self.target)
-		winsize = self.hei
-		halfwinsize = winsize // 2
-		index = self.target.pointer or 0
-		original = self.target.scroll_begin
-		projected = index - original
-
-		upper_limit = winsize - 1 - offset
-		lower_limit = offset
-
-		if original < 0:
-			return 0
-
-		if dirsize < winsize:
-			return 0
-
-		if halfwinsize < offset:
-			return min( dirsize - winsize, max( 0, index - halfwinsize ))
-
-		if original > dirsize - winsize:
-			self.target.scroll_begin = dirsize - winsize
-			return self._get_scroll_begin()
-
-		if projected < upper_limit and projected > lower_limit:
-			return original
-
-		if projected > upper_limit:
-			return min( dirsize - winsize,
-					original + (projected - upper_limit))
-
-		if projected < upper_limit:
-			return max( 0,
-					original - (lower_limit - projected))
-
-		return original
-
-	def _set_scroll_begin(self):
-		"""Updates the scroll_begin value"""
-		self.scroll_begin = self._get_scroll_begin()
-		self.target.scroll_begin = self.scroll_begin
-
-	def scroll(self, n):
-		"""scroll down by n lines"""
-		self.need_redraw = True
-		self.target.move(down=n)
-		self.target.scroll_begin += 3 * n
-
-	def __str__(self):
-		return self.__class__.__name__ + ' at level ' + str(self.level)
+    main_column = False
+    display_infostring = False
+    scroll_begin = 0
+    target = None
+    last_redraw_time = -1
+    ellipsis = { False: '~', True: '…' }
+
+    old_dir = None
+    old_thisfile = None
+
+    def __init__(self, win, level):
+        """
+        win = the curses window object of the BrowserView
+        level = what to display?
+
+        level >0 => previews
+        level 0 => current file/directory
+        level <0 => parent directories
+        """
+        Pager.__init__(self, win)
+        Widget.__init__(self, win)
+        self.level = level
+        self.original_level = level
+
+        self.settings.signal_bind('setopt.display_size_in_main_column',
+                self.request_redraw, weak=True)
+
+    def request_redraw(self):
+        self.need_redraw = True
+
+    def resize(self, y, x, hei, wid):
+        Widget.resize(self, y, x, hei, wid)
+
+    def click(self, event):
+        """Handle a MouseEvent"""
+        direction = event.mouse_wheel_direction()
+        if not (event.pressed(1) or event.pressed(3) or direction):
+            return False
+
+        if self.target is None:
+            pass
+
+        elif self.target.is_directory:
+            if self.target.accessible and self.target.content_loaded:
+                index = self.scroll_begin + event.y - self.y
+
+                if direction:
+                    if self.level == -1:
+                        self.fm.move_parent(direction)
+                    else:
+                        return False
+                elif event.pressed(1):
+                    if not self.main_column:
+                        self.fm.enter_dir(self.target.path)
+
+                    if index < len(self.target):
+                        self.fm.move(to=index)
+                elif event.pressed(3):
+                    try:
+                        clicked_file = self.target.files[index]
+                        if clicked_file.is_directory:
+                            self.fm.enter_dir(clicked_file.path)
+                        elif self.level == 0:
+                            self.fm.thisdir.move_to_obj(clicked_file)
+                            self.fm.execute_file(clicked_file)
+                    except:
+                        pass
+
+        else:
+            if self.level > 0 and not direction:
+                self.fm.move(right=0)
+
+        return True
+
+    def execute_curses_batch(self, line, commands):
+        """
+        Executes a list of "commands" which can be easily cached.
+
+        "commands" is a list of lists.  Each element contains
+        a text and an attribute.  First, the attribute will be
+        set with attrset, then the text is printed.
+
+        Example:
+        execute_curses_batch(0, [["hello ", 0], ["world", curses.A_BOLD]])
+        """
+        try:
+            self.win.move(line, 0)
+        except:
+            return
+        for entry in commands:
+            text, attr = entry
+            self.addstr(text, attr)
+
+    def has_preview(self):
+        if self.target is None:
+            return False
+
+        if self.target.is_file:
+            if not self.target.has_preview():
+                return False
+
+        if self.target.is_directory:
+            if self.level > 0 and not self.settings.preview_directories:
+                return False
+
+        return True
+
+    def level_shift(self, amount):
+        self.level = self.original_level + amount
+
+    def level_restore(self):
+        self.level = self.original_level
+
+    def poke(self):
+        Widget.poke(self)
+        self.target = self.fm.thistab.at_level(self.level)
+
+    def draw(self):
+        """Call either _draw_file() or _draw_directory()"""
+        if self.target != self.old_dir:
+            self.need_redraw = True
+            self.old_dir = self.target
+
+        if self.target:  # don't garbage collect this directory please
+            self.target.use()
+
+        if self.target and self.target.is_directory \
+                and (self.level <= 0 or self.settings.preview_directories):
+            if self.target.pointed_obj != self.old_thisfile:
+                self.need_redraw = True
+                self.old_thisfile = self.target.pointed_obj
+
+            if self.target.load_content_if_outdated() \
+            or self.target.sort_if_outdated() \
+            or self.last_redraw_time < self.target.last_update_time:
+                self.need_redraw = True
+
+        if self.need_redraw:
+            self.win.erase()
+            if self.target is None:
+                pass
+            elif self.target.is_file:
+                Pager.open(self)
+                self._draw_file()
+            elif self.target.is_directory:
+                self._draw_directory()
+                Widget.draw(self)
+            self.need_redraw = False
+            self.last_redraw_time = time()
+
+    def _draw_file(self):
+        """Draw a preview of the file, if the settings allow it"""
+        self.win.move(0, 0)
+        if not self.target.accessible:
+            self.addnstr("not accessible", self.wid)
+            Pager.close(self)
+            return
+
+        if self.target is None or not self.target.has_preview():
+            Pager.close(self)
+            return
+
+        if self.fm.settings.preview_images and self.target.image:
+            self.set_image(self.target.realpath)
+            Pager.draw(self)
+        else:
+            f = self.target.get_preview_source(self.wid, self.hei)
+            if f is None:
+                Pager.close(self)
+            else:
+                self.set_source(f)
+                Pager.draw(self)
+
+    def _draw_directory(self):
+        """Draw the contents of a directory"""
+        if self.image:
+            self.image = None
+            self.need_clear_image = True
+            Pager.clear_image(self)
+
+        if self.level > 0 and not self.settings.preview_directories:
+            return
+
+        base_color = ['in_browser']
+
+        self.win.move(0, 0)
+
+        if not self.target.content_loaded:
+            self.color(tuple(base_color))
+            self.addnstr("...", self.wid)
+            self.color_reset()
+            return
+
+        if self.main_column:
+            base_color.append('main_column')
+
+        if not self.target.accessible:
+            self.color(tuple(base_color + ['error']))
+            self.addnstr("not accessible", self.wid)
+            self.color_reset()
+            return
+
+        if self.target.empty():
+            self.color(tuple(base_color + ['empty']))
+            self.addnstr("empty", self.wid)
+            self.color_reset()
+            return
+
+        self._set_scroll_begin()
+
+        copied = [f.path for f in self.fm.copy_buffer]
+        ellipsis = self.ellipsis[self.settings.unicode_ellipsis]
+
+        selected_i = self.target.pointer
+        for line in range(self.hei):
+            i = line + self.scroll_begin
+            if line > self.hei:
+                break
+
+            try:
+                drawn = self.target.files[i]
+            except IndexError:
+                break
+
+            tagged = self.fm.tags and drawn.realpath in self.fm.tags
+            if tagged:
+                tagged_marker = self.fm.tags.marker(drawn.realpath)
+            else:
+                tagged_marker = " "
+
+            key = (self.wid, selected_i == i, drawn.marked, self.main_column,
+                    drawn.path in copied, tagged_marker, drawn.infostring,
+                    self.fm.do_cut)
+
+            if key in drawn.display_data:
+                self.execute_curses_batch(line, drawn.display_data[key])
+                self.color_reset()
+                continue
+
+            display_data = []
+            drawn.display_data[key] = display_data
+
+            if self.display_infostring and drawn.infostring \
+                    and self.settings.display_size_in_main_column:
+                infostring = str(drawn.infostring) + " "
+            else:
+                infostring = ""
+
+            this_color = base_color + list(drawn.mimetype_tuple)
+            text = drawn.basename
+
+            space = self.wid - len(infostring)
+            if self.main_column:
+                space -= 2
+            elif self.settings.display_tags_in_all_columns:
+                space -= 1
+
+            if i == selected_i:
+                this_color.append('selected')
+
+            if drawn.marked:
+                this_color.append('marked')
+                if self.main_column or self.settings.display_tags_in_all_columns:
+                    text = " " + text
+
+            if tagged:
+                this_color.append('tagged')
+
+            if drawn.is_directory:
+                this_color.append('directory')
+            else:
+                this_color.append('file')
+
+            if drawn.stat:
+                mode = drawn.stat.st_mode
+                if mode & stat.S_IXUSR:
+                    this_color.append('executable')
+                if stat.S_ISFIFO(mode):
+                    this_color.append('fifo')
+                if stat.S_ISSOCK(mode):
+                    this_color.append('socket')
+                if drawn.is_device:
+                    this_color.append('device')
+
+            if drawn.path in copied:
+                this_color.append('cut' if self.fm.do_cut else 'copied')
+
+            if drawn.is_link:
+                this_color.append('link')
+                this_color.append(drawn.exists and 'good' or 'bad')
+
+            attr = self.settings.colorscheme.get_attr(*this_color)
+
+            if (self.main_column or self.settings.display_tags_in_all_columns) \
+                    and tagged and self.wid > 2:
+                this_color.append('tag_marker')
+                tag_attr = self.settings.colorscheme.get_attr(*this_color)
+                display_data.append([tagged_marker, tag_attr])
+            else:
+                text = " " + text
+                space += 1
+
+            wtext = WideString(text)
+            if len(wtext) > space:
+                wtext = wtext[:max(0, space - 1)] + ellipsis
+            text = str(wtext)
+
+            display_data.append([text, attr])
+
+            padding = self.wid - len(wtext)
+            if tagged and (self.main_column or \
+                    self.settings.display_tags_in_all_columns):
+                padding -= 1
+            if infostring:
+                if len(wtext) + 1 + len(infostring) > self.wid:
+                    pass
+                else:
+                    padding -= len(infostring)
+                    padding = max(0, padding)
+                    infostring = (" " * padding) + infostring
+                    display_data.append([infostring, attr])
+            else:
+                display_data.append([" " * max(0, padding), attr])
+
+            self.execute_curses_batch(line, display_data)
+            self.color_reset()
+
+    def _get_scroll_begin(self):
+        """Determines scroll_begin (the position of the first displayed file)"""
+        offset = self.settings.scroll_offset
+        dirsize = len(self.target)
+        winsize = self.hei
+        halfwinsize = winsize // 2
+        index = self.target.pointer or 0
+        original = self.target.scroll_begin
+        projected = index - original
+
+        upper_limit = winsize - 1 - offset
+        lower_limit = offset
+
+        if original < 0:
+            return 0
+
+        if dirsize < winsize:
+            return 0
+
+        if halfwinsize < offset:
+            return min( dirsize - winsize, max( 0, index - halfwinsize ))
+
+        if original > dirsize - winsize:
+            self.target.scroll_begin = dirsize - winsize
+            return self._get_scroll_begin()
+
+        if projected < upper_limit and projected > lower_limit:
+            return original
+
+        if projected > upper_limit:
+            return min( dirsize - winsize,
+                    original + (projected - upper_limit))
+
+        if projected < upper_limit:
+            return max( 0,
+                    original - (lower_limit - projected))
+
+        return original
+
+    def _set_scroll_begin(self):
+        """Updates the scroll_begin value"""
+        self.scroll_begin = self._get_scroll_begin()
+        self.target.scroll_begin = self.scroll_begin
+
+    def scroll(self, n):
+        """scroll down by n lines"""
+        self.need_redraw = True
+        self.target.move(down=n)
+        self.target.scroll_begin += 3 * n
+
+    def __str__(self):
+        return self.__class__.__name__ + ' at level ' + str(self.level)