summary refs log tree commit diff stats
path: root/ranger/gui/widgets/statusbar.py
blob: b8b418c9965d77e09ccfcfa5010b3360a360f6ec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""The StatusBar displays information about the currently selected file
in the same form as the "ls -l" command on the left side, and
some additional info about the current directory on the right side.
"""

from . import Widget
from ranger import log
from pwd import getpwuid
from grp import getgrgid
from os import getuid
from time import strftime, localtime

class StatusBar(Widget):
	__doc__ = __doc__
	owners = {}
	groups = {}
	timeformat = '%Y-%m-%d %H:%M'

	def __init__(self, win, filelist=None):
		Widget.__init__(self, win)
		self.filelist = filelist
	
	def draw(self):
		"""Draw the statusbar"""

		# each item in the returned array looks like:
		# [ list_with_color_tags,       string       ]
		# [ ['permissions', 'allowed'], '-rwxr-xr-x' ]
		left = self._get_left_part()
		right = self._get_right_part()
		self._print_result(self._combine_parts(left, right))

	def _get_left_part(self):
		part = []

		if self.filelist is not None:
			target = self.filelist.target.pointed_file
		else:
			target = self.env.at_level(0).pointed_file

		if target is None:
			return part

		if target.accessible is False:
			return part

		perms = target.get_permission_string()
		color = ['permissions']
		if getuid() == target.stat.st_uid:
			color.append('good')
		else:
			color.append('bad')
		part.append([color, perms])

		part.append([['space'], " "])
		part.append([['nlink'], str(target.stat.st_nlink)])
		part.append([['space'], " "])
		part.append([['owner'], self._get_owner(target)])
		part.append([['space'], " "])
		part.append([['group'], self._get_group(target)])
		part.append([['space'], " "])
		if target.islink:
			color = ['link']
			color.append(target.exists and 'good' or 'bad')
			part.append([color, '-> ' + target.readlink])
		else:
			part.append([['mtime'], strftime(self.timeformat, \
					localtime(target.stat.st_mtime))])
		return part
	
	def _get_owner(self, target):
		uid = target.stat.st_uid

		try:
			return self.owners[uid]
		except KeyError:
			try:
				self.owners[uid] = getpwuid(uid)[0]
				return self.owners[uid]
			except KeyError:
				return str(uid)

	def _get_group(self, target):
		gid = target.stat.st_gid

		try:
			return self.groups[gid]
		except KeyError:
			try:
				self.groups[gid] = getgrgid(gid)[0]
				return self.groups[gid]
			except KeyError:
				return str(gid)

	def _get_right_part(self):
		part = []
		if self.filelist is not None:
			target = self.filelist.target
		else:
			target = self.env.at_level(0)

		if not target.content_loaded or not target.accessible:
			return part

		if self.filelist is not None:
			pos = target.scroll_begin
			max_pos = len(target) - self.filelist.hei

			if max_pos > 0:
				if pos == 0:
					part.append([['scroll', 'top'], 'Top'])
				elif pos >= max_pos:
					part.append([['scroll', 'bot'], 'Bot'])
				else:
					part.append([['scroll', 'percentage'], \
						'{0:0>.0f}%'.format(100.0 * pos / max_pos)])
			else:
				part.append([['scroll', 'all'], 'All'])
		return part

	def _combine_parts(self, left, right):
		"""Combines left and right, filling the middle with spaces and
		removing elements which don't have enough room to fit in.
		<left> will be turned into the result (which is also returned).
		"""

		leftsize = sum(len(part[1]) for part in left)
		rightsize = sum(len(part[1]) for part in right)
		sumsize = leftsize + rightsize

		# remove elemets from the left until it fits
		if sumsize > self.wid:
			while len(left) > 0:
				leftsize -= len(left.pop(-1)[1])
				if leftsize + rightsize <= self.wid:
					break
			sumsize = leftsize + rightsize

			# remove elemets from the right until it fits
			if sumsize > self.wid:
				while len(right) > 0:
					rightsize -= len(right.pop(0)[1])
					if leftsize + rightsize <= self.wid:
						break
				sumsize = leftsize + rightsize

		if sumsize < self.wid:
			left.append([ ['space'], " " * (self.wid - sumsize) ])
		left.extend(right)
		return left

	def _print_result(self, result):
		import _curses
		self.win.move(self.y, self.x)
		for part in result:
			self.color('in_statusbar', *part[0])
			try:
				self.win.addstr(part[1])
			except _curses.error:
				pass