1
0
mirror of https://github.com/gryf/wmdocklib.git synced 2025-12-20 12:58:08 +01:00

added -s option for skipping an amount of configuration items.

changed some single quotes to double quotes for use in emacs.
  updated the rc sample file
This commit is contained in:
mfrasca
2005-09-06 17:09:12 +00:00
parent f268888d0b
commit 9cbd279699
3 changed files with 135 additions and 95 deletions

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
'''pywmhdmon.py """pywmhdmon.py
WindowMaker dockapp to monitor the free space on your partitions and WindowMaker dockapp to monitor the free space on your partitions and
the disk activity. the disk activity.
@@ -11,10 +11,17 @@ Licensed under the GNU General Public License.
Changes Changes
2004-07-15 Kristoffer Erlandsson
Added a patch from Mario Frasca (Thanks!) which prevents the app from showing 2005-09-02 Mario Frasca
the data from the host file system if there is no filesystem mounted at the added -s option for skipping an amount of configuration items.
given point. changed some single quotes to double quotes for use in emacs.
updated the rc sample file
2004-07-16 Mario Frasca
recognizes unmounted partitions.
configurable mouse actions.
'used' information for read-only media.
recognizes #-started numerical-coded colors.
2003-09-01 Kristoffer Erlandsson 2003-09-01 Kristoffer Erlandsson
Fixed a bug where the numbers wouldn't show if they were between 1000 and 1024. Fixed a bug where the numbers wouldn't show if they were between 1000 and 1024.
@@ -28,7 +35,8 @@ Additional fine tuning
2003-06-23 Kristoffer Erlandsson 2003-06-23 Kristoffer Erlandsson
First working version First working version
''' """
usage = '''pywmhdmon.py [options] usage = '''pywmhdmon.py [options]
Available options are: Available options are:
-h, --help print this help -h, --help print this help
@@ -39,9 +47,9 @@ Available options are:
-r, --rgbfile <file> set the rgb file to get color codes from -r, --rgbfile <file> set the rgb file to get color codes from
-c, --configfile <file> set the config file to use -c, --configfile <file> set the config file to use
-p, --procstat <file> set the location of /proc/stat -p, --procstat <file> set the location of /proc/stat
-s, --skipconf <num> determines how many configuration items to skip
''' '''
import sys import sys
import time import time
import getopt import getopt
@@ -78,19 +86,22 @@ graphLineStartY = 58
letters = 'abcdefghijklmnopqrstuvwxyz' letters = 'abcdefghijklmnopqrstuvwxyz'
digits = '0123456789:/-%. ' digits = '0123456789:/-%. '
defaultConfigFile = '~/.pywmhdmonrc' defaultConfigFile = os.environ['HOME']+'/.pywmhdmonrc'
defaultRGBFiles = ('/usr/lib/X11/rgb.txt', '/usr/X11R6/lib/X11/rgb.txt') defaultRGBFiles = ('/usr/lib/X11/rgb.txt', '/usr/X11R6/lib/X11/rgb.txt')
defaultProcStat = '/proc/stat' defaultProcStat = '/proc/stat'
displayModes = ('bar', 'percent', 'free', 'used') displayModes = ('bar', 'percent', 'free', 'used')
defaultMode = 'bar' defaultMode = 'bar'
hdmon = None
class NotMounted(OSError): class NotMounted(OSError):
pass pass
class PywmHDMon: class PywmHDMon:
def __init__(self, pathsToMonitor, procStat='/proc/stat', actMonEnabled=1): def __init__(self, pathsToMonitor, procStat='/proc/stat', actMonEnabled=1, skipping=0):
self._pathsToMonitor = pathsToMonitor self._pathsToMonitor = pathsToMonitor
self._actMonEnabled = actMonEnabled self._actMonEnabled = actMonEnabled
self._skipping = skipping
self._statFile = procStat self._statFile = procStat
self._maxIODiff = 0 self._maxIODiff = 0
@@ -107,13 +118,14 @@ class PywmHDMon:
sys.exit(3) sys.exit(3)
def getHdInfo(self, path): def getHdInfo(self, path):
'''Get the free and total space of the filesystem which path is on. """Get the free and total space of the filesystem which path is on.
Return a tuple with (<total space>, <free space>) in bytes. Raise Return a tuple with (<total space>, <free space>) in bytes. Raise
OSError if we can't stat the path. Raise NotMounted if not mounted. OSError if we can't stat the path. Raise NotMounted if not mounted.
These operations are quite costly, not adviced to perform these checks These operations are quite costly, not adviced to perform these checks
more than once every 10 seconds. more than once every 10 seconds.
''' """
# check if is mounted <- st_dev(/mount/point) == st_dev(/mount) # check if is mounted <- st_dev(/mount/point) == st_dev(/mount)
if path is not '/': if path is not '/':
statOwn = os.stat(path) statOwn = os.stat(path)
@@ -132,19 +144,20 @@ class PywmHDMon:
total = blockSize * totalBlocks total = blockSize * totalBlocks
return (total, free) return (total, free)
def paintGraph(self, percentFilled, x, y, w): def paintGraph(self, percentFilled, x, y, w, thin=None):
'''Paint a graph with percentFilled percent filled. '''Paint a graph with percentFilled percent filled.
Paint at position x, y and with width w. Paint at position x, y and with width w.
if thin == 1, make it a thin line instead of a block.
''' '''
paintWidth = int(round(percentFilled/100.0 * w)) paintWidth = int(round(percentFilled/100.0 * w))
if paintWidth > 0: if paintWidth > 0:
pywmhelpers.copyXPMArea( pywmhelpers.copyXPMArea(
graphLineStartX, graphLineStartY, paintWidth, graphHeight, graphLineStartX, graphLineStartY, paintWidth, thin or graphHeight,
x + xOffset, y + yOffset) x + xOffset, y + yOffset)
if w - paintWidth > 0: if w - paintWidth > 0:
pywmhelpers.copyXPMArea( pywmhelpers.copyXPMArea(
graphBgStartX, graphBgStartY, w - paintWidth, graphHeight, graphBgStartX, graphBgStartY, w - paintWidth, thin or graphHeight,
x + paintWidth + xOffset, y + yOffset) x + paintWidth + xOffset, y + yOffset)
def getY(self, line): def getY(self, line):
@@ -157,18 +170,21 @@ class PywmHDMon:
total, free = data total, free = data
xStart = width - xOffset - 6 * letterWidth - 1 xStart = width - xOffset - 6 * letterWidth - 1
if total==0: if total==0:
self.addString('-----', xStart, self.getY(line)) self.addString(' ', xStart, self.getY(line))
self.paintGraph(0, xStart, self.getY(line) + 4,
width - xOffset*2 - xStart - 2,
thin=1)
pass pass
elif mode == 'percent': elif mode == 'percent':
percent = (float(free) / float(total)) * 100.0 percent = (float(free) / float(total)) * 100.0
percentStr = (str(int(round(percent))) + '%').rjust(5) percentStr = (str(int(round(percent))) + '%').rjust(5)
self.addString(percentStr, xStart, self.getY(line)) self.addString(percentStr, xStart, self.getY(line))
elif mode == 'free':
freeStr = bytesToStr(free).rjust(5)
self.addString(freeStr, xStart, self.getY(line))
elif mode == 'used': elif mode == 'used':
totalStr = bytesToStr(total).rjust(5) totalStr = bytesToStr(total).rjust(5)
self.addString(totalStr, xStart, self.getY(line)) self.addString(totalStr, xStart, self.getY(line))
elif mode == 'free':
freeStr = bytesToStr(free).rjust(5)
self.addString(freeStr, xStart, self.getY(line))
elif mode == 'bar': elif mode == 'bar':
percentUsed = (float(total - free) / float(total)) * 100.0 percentUsed = (float(total - free) / float(total)) * 100.0
self.paintGraph(percentUsed, xStart, self.getY(line) + 2, self.paintGraph(percentUsed, xStart, self.getY(line) + 2,
@@ -177,7 +193,7 @@ class PywmHDMon:
sys.stderr.write('Unknown display mode: %s, ignoring data.\n' sys.stderr.write('Unknown display mode: %s, ignoring data.\n'
% mode) % mode)
def getHdActivity(self): def getHdActivity(self):
'''Return the current hd activity in percent. """Return the current hd activity in percent.
Return how many percent of the max achieved activity during the Return how many percent of the max achieved activity during the
program's lifetime the current activity is. However, every time program's lifetime the current activity is. However, every time
@@ -185,7 +201,8 @@ class PywmHDMon:
little bit to get a bit less affected by spikes. I think the little bit to get a bit less affected by spikes. I think the
interesting thing is to see if the hard drive is active, not interesting thing is to see if the hard drive is active, not
really exactly how active. really exactly how active.
''' """
statFile = file(self._statFile, 'r') statFile = file(self._statFile, 'r')
diskIoStartTag = 'disk_io: ' diskIoStartTag = 'disk_io: '
ioLine = None ioLine = None
@@ -227,47 +244,60 @@ class PywmHDMon:
def _checkEvents(self): def _checkEvents(self):
event = pywmhelpers.getEvent() event = pywmhelpers.getEvent()
while not event is None: while event is not None:
if event['type'] == 'destroynotify': if event['type'] == 'destroynotify':
sys.exit(0) sys.exit(0)
elif event['type'] == 'buttonrelease':
area = pywmhelpers.checkMouseRegion(event['x'],event['y'])
if area is not -1:
action = self._pathsToMonitor[area-1+self._skipping][3]
if action:
os.spawnvp(os.P_NOWAIT, action[0], action)
event = pywmhelpers.getEvent() event = pywmhelpers.getEvent()
def updateMonitoredPaths(self):
index = 0
pageoffset = self._skipping
for i in self._pathsToMonitor:
index += 1
if index < pageoffset+1:
continue
if i is not None:
label, path, mode, action = i
self.paintLabel(index-pageoffset, label)
try:
hdData = self.getHdInfo(path)
except NotMounted:
hdData = (0, 0)
except OSError, e:
sys.stderr.write(
"Can't get hd data from %s: %s\n" % (path, str(e)))
hdData = (0, 0)
self.paintHdData(index-pageoffset, hdData, mode)
if index - pageoffset == 5:
break
def mainLoop(self): def mainLoop(self):
counter = -1 self.updateMonitoredPaths()
while 1: while 1:
counter += 1
self._checkEvents() self._checkEvents()
if self._actMonEnabled: if self._actMonEnabled:
self.updateHdActivity() self.updateHdActivity()
if counter % 100 == 0:
index = 0
for i in self._pathsToMonitor:
if not i is None:
label, path, mode = i
self.paintLabel(index + 1, label)
try:
hdData = self.getHdInfo(path)
except NotMounted:
hdData = (0, 0)
except OSError, e:
sys.stderr.write(
"Can't get hd data from %s: %s\n" % (path, str(e)))
hdData = (0, 0)
self.paintHdData(index + 1, hdData, mode)
index += 1
if counter == 9999999:
counter = -1
pywmhelpers.redraw() pywmhelpers.redraw()
time.sleep(0.1) time.sleep(0.1)
import signal
def handler(num, frame):
hdmon.updateMonitoredPaths()
signal.alarm(10)
def parseCommandLine(argv): def parseCommandLine(argv):
'''Parse the commandline. Return a dictionary with options and values.''' '''Parse the commandline. Return a dictionary with options and values.'''
shorts = 'ht:f:g:b:r:c:p:' shorts = 'ht:f:g:b:r:c:p:s:'
longs = ['help', 'textcolor=', 'background=', 'barfgcolor=', longs = ['help', 'textcolor=', 'background=', 'barfgcolor=',
'rgbfile=', 'configfile=', 'barbgcolor=', 'procstat='] 'rgbfile=', 'configfile=', 'barbgcolor=', 'procstat=',
'skipconf=']
try: try:
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs) opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
except getopt.GetoptError, e: except getopt.GetoptError, e:
@@ -293,6 +323,8 @@ def parseCommandLine(argv):
d['barfgcolor'] = a d['barfgcolor'] = a
if o in ('-p', '--procstat'): if o in ('-p', '--procstat'):
d['procstat'] = a d['procstat'] = a
if o in ('-s', '--skipconf'):
d['skipconf'] = a
return d return d
def parseColors(defaultRGBFileList, config, xpm): def parseColors(defaultRGBFileList, config, xpm):
@@ -318,7 +350,8 @@ def parseColors(defaultRGBFileList, config, xpm):
for key, value in colors: for key, value in colors:
col = config.get(key) col = config.get(key)
if not col is None: if not col is None:
code = pywmhelpers.getColorCode(col, rgbFileName) if col[0] is '#': code=col
else: code = pywmhelpers.getColorCode(col, rgbFileName)
if code is None: if code is None:
sys.stderr.write('Bad colorcode for %s, ignoring.\n' % key) sys.stderr.write('Bad colorcode for %s, ignoring.\n' % key)
else: else:
@@ -338,10 +371,10 @@ def makeNumDigits(num, numDigits):
return s return s
def bytesToStr(bytes): def bytesToStr(bytes):
'''Convert a number of bytes to a nice printable string. """Convert a number of bytes to a nice printable string.
May raise ValueError if bytes can't be seen as an float. May raise ValueError if bytes can't be seen as an float.
''' """
bytes = float(bytes) bytes = float(bytes)
kb = 1024 kb = 1024
mb = 1024 * 1024 mb = 1024 * 1024
@@ -391,23 +424,28 @@ def main():
parseColors(defaultRGBFiles, config, xpm) parseColors(defaultRGBFiles, config, xpm)
pathsToMonitor = [] pathsToMonitor = []
for i in range(1,5): for i in range(1,1000):
labelStr = str(i) + '.label' labelStr = str(i) + '.label'
pathStr = str(i) + '.path' pathStr = str(i) + '.path'
modeStr = str(i) + '.displaymode' modeStr = str(i) + '.displaymode'
actionStr = str(i) + '.action'
label = config.get(labelStr) label = config.get(labelStr)
if not label: break
path = config.get(pathStr) path = config.get(pathStr)
action = config.get(actionStr)
if action: action=eval(action)
displayMode = config.get(modeStr, defaultMode) displayMode = config.get(modeStr, defaultMode)
if not displayMode in displayModes: if not displayMode in displayModes:
sys.stderr.write( sys.stderr.write(
'Unknown display mode: %s, using default.\n' % displayMode) 'Unknown display mode: %s, using default.\n' % displayMode)
displayMode = defaultMode displayMode = defaultMode
if label is None or path is None: pathsToMonitor.append((label[:3], path, displayMode, action))
pathsToMonitor.append(None) pywmhelpers.addMouseRegion(i,
else: 8, 8 + (i - 1) * (letterHeight + 3),
pathsToMonitor.append((label[:3], path, displayMode)) 58, 4 + i * (letterHeight + 3))
procStat = config.get('procstat', defaultProcStat) procStat = config.get('procstat', defaultProcStat)
actMonEnabled = 1 skipping = int(config.get('skipconf', 0))
actMonEnabled = int(config.get('monitoring'))
if not os.access(procStat, os.R_OK): if not os.access(procStat, os.R_OK):
sys.stderr.write( sys.stderr.write(
"Can't read your procstat file, try setting it with -p. ") "Can't read your procstat file, try setting it with -p. ")
@@ -420,8 +458,13 @@ def main():
sys.argv[0] = programName sys.argv[0] = programName
pywmhelpers.setDefaultPixmap(xpm) pywmhelpers.setDefaultPixmap(xpm)
pywmhelpers.openXwindow(sys.argv, width, height) pywmhelpers.openXwindow(sys.argv, width, height)
# XXX Add commands for clicking different areas?
hdmon = PywmHDMon(pathsToMonitor, procStat, actMonEnabled) signal.signal(signal.SIGCHLD, handler)
signal.signal(signal.SIGALRM, handler)
signal.alarm(10)
global hdmon
hdmon = PywmHDMon(pathsToMonitor, procStat, actMonEnabled, skipping)
hdmon.mainLoop() hdmon.mainLoop()
@@ -544,4 +587,3 @@ xpm = \
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -1,26 +0,0 @@
[DEFAULT]
# Displaymodes are free, percent or bar, displays the free size, free percent
# and a bar representing space, respectively.
1.label=/
1.path=/
1.displaymode=free
2.label=c
2.path=/mnt/c
2.displaymode=free
3.label=d
3.path=/mnt/d
3.displaymode=free
4.label=e
4.path=/mnt/e
4.displaymode=free
textcolor=light sea green
background=black
barfgcolor=light sea green
barbgcolor=grey45
#rgbfile=/usr/lib/X11/rgb.txt

View File

@@ -1,26 +1,50 @@
[DEFAULT] [DEFAULT]
# Displaymodes are free, percent or bar, displays the free size, free percent
# and a bar representing space, respectively. # Displaymodes are used, free, percent or bar, displays the used size,
# free size, free percent and a bar representing space, respectively.
1.label=/ 1.label=/
1.path=/ 1.path=/
1.displaymode=free #1.displaymode=free
2.label=c 2.label=usr
2.path=/mnt/c 2.path=/usr
2.displaymode=free #2.displaymode=free
3.label=d 3.label=home
3.path=/mnt/d 3.path=/home
3.displaymode=free #3.displaymode=free
4.label=e 4.label=cd
4.path=/mnt/e 4.path=/mnt/cd
4.displaymode=free 4.displaymode=used
4.action=['/home/mario/bin/tmount', '/mnt/cd', 'eject']
5.label=jr
5.path=/mnt/jr
5.displaymode=used
5.action=['/home/mario/bin/tmount', '/mnt/jr', 'eject']
6.label=sm
6.path=/mnt/sm
6.displaymode=free
6.action=['/home/mario/bin/tmount', '/mnt/sm']
7.label=cf
7.path=/mnt/cf
7.displaymode=free
7.action=['/home/mario/bin/tmount', '/mnt/cf']
8.label=flo
8.path=/mnt/flo
8.displaymode=free
8.action=['/home/mario/bin/tmount', '/mnt/flo']
textcolor=light sea green textcolor=light sea green
background=black background=black
barfgcolor=light sea green barfgcolor=light sea green
barbgcolor=grey45 barbgcolor=grey45
monitoring=0
#rgbfile=/usr/lib/X11/rgb.txt #rgbfile=/usr/lib/X11/rgb.txt