Clean up repository.
Remove all non-lib related files including old CVS things, examples, website and so on.
@@ -1,13 +0,0 @@
|
|||||||
# The "checkoutlist" file is used to support additional version controlled
|
|
||||||
# administrative files in $CVSROOT/CVSROOT, such as template files.
|
|
||||||
#
|
|
||||||
# The first entry on a line is a filename which will be checked out from
|
|
||||||
# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
|
|
||||||
# The remainder of the line is an error message to use if the file cannot
|
|
||||||
# be checked out.
|
|
||||||
#
|
|
||||||
# File format:
|
|
||||||
#
|
|
||||||
# [<whitespace>]<filename>[<whitespace><error message>]<end-of-line>
|
|
||||||
#
|
|
||||||
# comment lines begin with '#'
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# The "commitinfo" file is used to control pre-commit checks.
|
|
||||||
# The filter on the right is invoked with the repository and a list
|
|
||||||
# of files to check. A non-zero exit of the filter program will
|
|
||||||
# cause the commit to be aborted.
|
|
||||||
#
|
|
||||||
# The first entry on a line is a regular expression which is tested
|
|
||||||
# against the directory that the change is being committed to, relative
|
|
||||||
# to the $CVSROOT. For the first match that is found, then the remainder
|
|
||||||
# of the line is the name of the filter to run.
|
|
||||||
#
|
|
||||||
# If the repository name does not match any of the regular expressions in this
|
|
||||||
# file, the "DEFAULT" line is used, if it is specified.
|
|
||||||
#
|
|
||||||
# If the name "ALL" appears as a regular expression it is always used
|
|
||||||
# in addition to the first matching regex or "DEFAULT".
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Set this to "no" if pserver shouldn't check system users/passwords
|
|
||||||
#SystemAuth=no
|
|
||||||
|
|
||||||
# Put CVS lock files in this directory rather than directly in the repository.
|
|
||||||
#LockDir=/var/lock/cvs
|
|
||||||
|
|
||||||
# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
|
|
||||||
# level of the new working directory when using the `cvs checkout'
|
|
||||||
# command.
|
|
||||||
#TopLevelAdmin=no
|
|
||||||
|
|
||||||
# Set `LogHistory' to `all' or `TOEFWUPCGMAR' to log all transactions to the
|
|
||||||
# history file, or a subset as needed (ie `TMAR' logs all write operations)
|
|
||||||
#LogHistory=TOEFWUPCGMAR
|
|
||||||
|
|
||||||
# Set `RereadLogAfterVerify' to `always' (the default) to allow the verifymsg
|
|
||||||
# script to change the log message. Set it to `stat' to force CVS to verify# that the file has changed before reading it (this can take up to an extra
|
|
||||||
# second per directory being committed, so it is not recommended for large
|
|
||||||
# repositories. Set it to `never' (the previous CVS behavior) to prevent
|
|
||||||
# verifymsg scripts from changing the log message.
|
|
||||||
#RereadLogAfterVerify=always
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# This file affects handling of files based on their names.
|
|
||||||
#
|
|
||||||
# The -m option specifies whether CVS attempts to merge files.
|
|
||||||
#
|
|
||||||
# The -k option specifies keyword expansion (e.g. -kb for binary).
|
|
||||||
#
|
|
||||||
# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
|
|
||||||
#
|
|
||||||
# wildcard [option value][option value]...
|
|
||||||
#
|
|
||||||
# where option is one of
|
|
||||||
# -f from cvs filter value: path to filter
|
|
||||||
# -t to cvs filter value: path to filter
|
|
||||||
# -m update methodology value: MERGE or COPY
|
|
||||||
# -k expansion mode value: b, o, kkv, &c
|
|
||||||
#
|
|
||||||
# and value is a single-quote delimited value.
|
|
||||||
# For example:
|
|
||||||
#*.gif -k 'b'
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# The "editinfo" file is used to allow verification of logging
|
|
||||||
# information. It works best when a template (as specified in the
|
|
||||||
# rcsinfo file) is provided for the logging procedure. Given a
|
|
||||||
# template with locations for, a bug-id number, a list of people who
|
|
||||||
# reviewed the code before it can be checked in, and an external
|
|
||||||
# process to catalog the differences that were code reviewed, the
|
|
||||||
# following test can be applied to the code:
|
|
||||||
#
|
|
||||||
# Making sure that the entered bug-id number is correct.
|
|
||||||
# Validating that the code that was reviewed is indeed the code being
|
|
||||||
# checked in (using the bug-id number or a seperate review
|
|
||||||
# number to identify this particular code set.).
|
|
||||||
#
|
|
||||||
# If any of the above test failed, then the commit would be aborted.
|
|
||||||
#
|
|
||||||
# Actions such as mailing a copy of the report to each reviewer are
|
|
||||||
# better handled by an entry in the loginfo file.
|
|
||||||
#
|
|
||||||
# One thing that should be noted is the the ALL keyword is not
|
|
||||||
# supported. There can be only one entry that matches a given
|
|
||||||
# repository.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# The "loginfo" file controls where "cvs commit" log information
|
|
||||||
# is sent. The first entry on a line is a regular expression which must match
|
|
||||||
# the directory that the change is being made to, relative to the
|
|
||||||
# $CVSROOT. If a match is found, then the remainder of the line is a filter
|
|
||||||
# program that should expect log information on its standard input.
|
|
||||||
#
|
|
||||||
# If the repository name does not match any of the regular expressions in this
|
|
||||||
# file, the "DEFAULT" line is used, if it is specified.
|
|
||||||
#
|
|
||||||
# If the name ALL appears as a regular expression it is always used
|
|
||||||
# in addition to the first matching regex or DEFAULT.
|
|
||||||
#
|
|
||||||
# You may specify a format string as part of the
|
|
||||||
# filter. The string is composed of a `%' followed
|
|
||||||
# by a single format character, or followed by a set of format
|
|
||||||
# characters surrounded by `{' and `}' as separators. The format
|
|
||||||
# characters are:
|
|
||||||
#
|
|
||||||
# s = file name
|
|
||||||
# V = old version number (pre-checkin)
|
|
||||||
# v = new version number (post-checkin)
|
|
||||||
# t = tag or branch name
|
|
||||||
#
|
|
||||||
# For example:
|
|
||||||
#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
|
|
||||||
# or
|
|
||||||
#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Three different line formats are valid:
|
|
||||||
# key -a aliases...
|
|
||||||
# key [options] directory
|
|
||||||
# key [options] directory files...
|
|
||||||
#
|
|
||||||
# Where "options" are composed of:
|
|
||||||
# -i prog Run "prog" on "cvs commit" from top-level of module.
|
|
||||||
# -o prog Run "prog" on "cvs checkout" of module.
|
|
||||||
# -e prog Run "prog" on "cvs export" of module.
|
|
||||||
# -t prog Run "prog" on "cvs rtag" of module.
|
|
||||||
# -u prog Run "prog" on "cvs update" of module.
|
|
||||||
# -d dir Place module in directory "dir" instead of module name.
|
|
||||||
# -l Top-level directory only -- do not recurse.
|
|
||||||
#
|
|
||||||
# NOTE: If you change any of the "Run" options above, you'll have to
|
|
||||||
# release and re-checkout any working directories of these modules.
|
|
||||||
#
|
|
||||||
# And "directory" is a path to a directory relative to $CVSROOT.
|
|
||||||
#
|
|
||||||
# The "-a" option specifies an alias. An alias is interpreted as if
|
|
||||||
# everything on the right of the "-a" had been typed on the command line.
|
|
||||||
#
|
|
||||||
# You can encode a module within a module by using the special '&'
|
|
||||||
# character to interpose another module into the current module. This
|
|
||||||
# can be useful for creating a module that consists of many directories
|
|
||||||
# spread out over the entire source repository.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# The "notify" file controls where notifications from watches set by
|
|
||||||
# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
|
|
||||||
# a regular expression which is tested against the directory that the
|
|
||||||
# change is being made to, relative to the $CVSROOT. If it matches,
|
|
||||||
# then the remainder of the line is a filter program that should contain
|
|
||||||
# one occurrence of %s for the user to notify, and information on its
|
|
||||||
# standard input.
|
|
||||||
#
|
|
||||||
# "ALL" or "DEFAULT" can be used in place of the regular expression.
|
|
||||||
#
|
|
||||||
# For example:
|
|
||||||
#ALL mail -s "CVS notification" %s
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# The "rcsinfo" file is used to control templates with which the editor
|
|
||||||
# is invoked on commit and import.
|
|
||||||
#
|
|
||||||
# The first entry on a line is a regular expression which is tested
|
|
||||||
# against the directory that the change is being made to, relative to the
|
|
||||||
# $CVSROOT. For the first match that is found, then the remainder of the
|
|
||||||
# line is the name of the file that contains the template.
|
|
||||||
#
|
|
||||||
# If the repository name does not match any of the regular expressions in this
|
|
||||||
# file, the "DEFAULT" line is used, if it is specified.
|
|
||||||
#
|
|
||||||
# If the name "ALL" appears as a regular expression it is always used
|
|
||||||
# in addition to the first matching regex or "DEFAULT".
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# The "taginfo" file is used to control pre-tag checks.
|
|
||||||
# The filter on the right is invoked with the following arguments:
|
|
||||||
#
|
|
||||||
# $1 -- tagname
|
|
||||||
# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
|
|
||||||
# $3 -- repository
|
|
||||||
# $4-> file revision [file revision ...]
|
|
||||||
#
|
|
||||||
# A non-zero exit of the filter program will cause the tag to be aborted.
|
|
||||||
#
|
|
||||||
# The first entry on a line is a regular expression which is tested
|
|
||||||
# against the directory that the change is being committed to, relative
|
|
||||||
# to the $CVSROOT. For the first match that is found, then the remainder
|
|
||||||
# of the line is the name of the filter to run.
|
|
||||||
#
|
|
||||||
# If the repository name does not match any of the regular expressions in this
|
|
||||||
# file, the "DEFAULT" line is used, if it is specified.
|
|
||||||
#
|
|
||||||
# If the name "ALL" appears as a regular expression it is always used
|
|
||||||
# in addition to the first matching regex or "DEFAULT".
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# The "verifymsg" file is used to allow verification of logging
|
|
||||||
# information. It works best when a template (as specified in the
|
|
||||||
# rcsinfo file) is provided for the logging procedure. Given a
|
|
||||||
# template with locations for, a bug-id number, a list of people who
|
|
||||||
# reviewed the code before it can be checked in, and an external
|
|
||||||
# process to catalog the differences that were code reviewed, the
|
|
||||||
# following test can be applied to the code:
|
|
||||||
#
|
|
||||||
# Making sure that the entered bug-id number is correct.
|
|
||||||
# Validating that the code that was reviewed is indeed the code being
|
|
||||||
# checked in (using the bug-id number or a seperate review
|
|
||||||
# number to identify this particular code set.).
|
|
||||||
#
|
|
||||||
# If any of the above test failed, then the commit would be aborted.
|
|
||||||
#
|
|
||||||
# Actions such as mailing a copy of the report to each reviewer are
|
|
||||||
# better handled by an entry in the loginfo file.
|
|
||||||
#
|
|
||||||
# One thing that should be noted is the the ALL keyword is not
|
|
||||||
# supported. There can be only one entry that matches a given
|
|
||||||
# repository.
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
[Pywmdatetime]
|
|
||||||
Pywmdatetime is a WindowMaker dockapp for displaying time, date and
|
|
||||||
some other information. The colors and formats are easy to configure
|
|
||||||
through the configuration file or as command line arguments. Invoke
|
|
||||||
the program with --help or see the sample rc-file for more information.
|
|
||||||
|
|
||||||
[Pywmgeneric]
|
|
||||||
Pywmgeneric is a dockapp with five entrys that display the first line of
|
|
||||||
output from an external program, the returned string from an python
|
|
||||||
method or an static string. Three mouse actions can be associated with
|
|
||||||
each displayed entry.
|
|
||||||
|
|
||||||
[Pywmgeneric -- DETAILED]
|
|
||||||
Five different entries can be defined in pywmgeneric. Every entry can
|
|
||||||
have an action, an update_delay and up to three mouse actions associated
|
|
||||||
with it. Some additional options are also available.
|
|
||||||
|
|
||||||
The associated action of an entry is executed with update_delay time
|
|
||||||
between executions. The output from the action is stored. If no special
|
|
||||||
display options are defined, the application will display the first line
|
|
||||||
of output from the action. If it does not fit in the window, it will
|
|
||||||
slowly scroll in the window. Clicking with the mouse on the text invokes
|
|
||||||
one of the mouse actions, depending on which button was pressed. The
|
|
||||||
action can be to execute an external program, to run a python method or
|
|
||||||
to update the text through performing the action associated with the
|
|
||||||
entry. The mouse actions can retreive the text genererated by the timed
|
|
||||||
action.
|
|
||||||
|
|
||||||
Python methods that should be executed as actions should be defined in
|
|
||||||
the class UserMethods. Look in pywmgeneric.py, near the top, for this
|
|
||||||
class and the documentation of how these methods should be defined.
|
|
||||||
Note that the methods allready there only are samples and will probably
|
|
||||||
not work on your system.
|
|
||||||
|
|
||||||
Other options in the configuration file include:
|
|
||||||
scroll = yes|no - en-/disable scrolling of the text when it doesn't fit
|
|
||||||
display = <text> - display a static string instead of the first line of
|
|
||||||
the action-generated output.
|
|
||||||
|
|
||||||
See the sample configuration file for examples and more information.
|
|
||||||
Note that this file is only for reference, it is the one I use. Things
|
|
||||||
will probably not work on your system if you do not change it.
|
|
||||||
|
|
||||||
[Pywmgeneric -- USES]
|
|
||||||
This program is very generic (hence the name ;) ), the uses are many
|
|
||||||
since it is highly configurable.
|
|
||||||
|
|
||||||
I use it for displaying my cpu and system temperatures. I just defined
|
|
||||||
methods for reading two files in the /proc filesystem on my system.
|
|
||||||
|
|
||||||
I also use it for fetching headlines from a newspaper, displaying the
|
|
||||||
first headline fetched. If I click with my left button, all headlines
|
|
||||||
will appear in an xmessage. If I rightclick the headlines along with
|
|
||||||
summaries are displayed, and if I click with my middle button mozilla
|
|
||||||
will fire up showing the newspaper's website.
|
|
||||||
|
|
||||||
I have an external program which displays what's currently on tv,
|
|
||||||
ideal for use with this program I thought! I modified it a bit so
|
|
||||||
it printed a summary line at the top, and voila I have all
|
|
||||||
currently running tv programs scrolling by in an dockapp. And clicking
|
|
||||||
on it shows me the details.
|
|
||||||
|
|
||||||
You could use it as an application launcher, just display the name of
|
|
||||||
the applications and associate mouse actions to lauch them. The
|
|
||||||
xterm-entry in the sample shows this.
|
|
||||||
|
|
||||||
You could probably come up with much more than this!
|
|
||||||
|
|
||||||
[pywmhdmon]
|
|
||||||
pywmhdmon is a WindowMaker dockapp that displays the available space on
|
|
||||||
up to four of your filesystems. It also contains a bar showing the
|
|
||||||
current HD activity. It currently only works on system which has a
|
|
||||||
/proc/stat like file. The application is easy to configure, invoke it
|
|
||||||
with --help or see the sample rc-file for more information.
|
|
||||||
|
|
||||||
[pywmhdmon -- BUGS]
|
|
||||||
The activity bar does not work with the proc filesystem that comes with
|
|
||||||
the 2.6 kernels. It is just a matter of rewriting the app to parse the
|
|
||||||
new format, but I'm low on time personally.
|
|
||||||
|
|
||||||
[Pywmseti]
|
|
||||||
Pywmseti is an WindowMaker dockapp for monitoring your seti@home progress.
|
|
||||||
The application displays how many workunits you have done and the progress
|
|
||||||
on the current one. You start/stop the seti@home process by simply clicking
|
|
||||||
anywhere in the application. It also displays the time spent on the workunit
|
|
||||||
(or since you started the program if you restart it in the middle of a
|
|
||||||
workunit). Invoke the program with --help or see the sample rc-file for
|
|
||||||
more information about customization.
|
|
||||||
|
|
||||||
[pywmsysmon]
|
|
||||||
pywmsysmon is a WindowMaker dockapp that displays your cpu and memory
|
|
||||||
usages. The upper graph shows your cpu usage history and the lower
|
|
||||||
"progress bar" shows your current memory usage excluding cached and
|
|
||||||
buffered data. This program currently only works on systems which got
|
|
||||||
the /proc/stat and /proc/meminfo files available. Invoke the program
|
|
||||||
with --help for information about customization.
|
|
||||||
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmdatetime.py
|
|
||||||
|
|
||||||
WindowMaker dockapp that displays time, date, weekday and week number.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Kristoffer Erlandsson
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
2003-09-01 Kristoffer Erlandsson
|
|
||||||
Fixed a bug where the week didn't update if we used %q style week numbering.
|
|
||||||
|
|
||||||
2003-06-28 Kristoffer Erlandsson
|
|
||||||
Fixed a bug where a mouse click caused an infinite loop
|
|
||||||
|
|
||||||
2003-06-26 Kristoffer Erlandsson
|
|
||||||
Fixed bug when longer strings didn't get cleared when shorter ones where
|
|
||||||
painted. Now only repaint the strings when they have changed.
|
|
||||||
|
|
||||||
2003-06-24 Kristoffer Erlandsson
|
|
||||||
Added event handling for graceful shutdown
|
|
||||||
|
|
||||||
2003-06-16 Kristoffer Erlandsson
|
|
||||||
First workingish version
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
|
|
||||||
from wmdocklib import wmoo, readConfigFile
|
|
||||||
|
|
||||||
width = 64
|
|
||||||
height = 64
|
|
||||||
|
|
||||||
xOffset = 4
|
|
||||||
yOffset = 4
|
|
||||||
|
|
||||||
patterns = [
|
|
||||||
".+@@+.....#@...#@@#...#@@#....$@%...@@@@+..+=@%..+@@@@@..%@@+...&@@#.....",
|
|
||||||
"$@==@$...+@@..&@--@&.*@--@&...#@%..*@-%%*.$==-@&.*%%%@=.#@-=@*.*@=-@&....",
|
|
||||||
"&@**@&..#@@@..&@$.@%.&-..@%..*@@%..+@+....+@*.%*....+@*.%@.+@+.%@$.-%.*+.",
|
|
||||||
"%@..@%..#+%@.....$@%....+@#..--@%..&@=@#..%@$+$.....--..&@&%@$.%@..%@.%@.",
|
|
||||||
"%@..@%....%@.....%@*...%@-..*@$@%..%@%=@*.%@=@@*...*@&...=@@#..&@%&@@.*+.",
|
|
||||||
"%@..@%....%@....+@%....&-@+.=#.@%...*.$@%.%@%&@-...#@...#@&%@*..=@@@@....",
|
|
||||||
"%@..@%....%@...+@=$......-@.@-%@=&.....@%.%@..%@...=-...@%..@%...+*%@.&%.",
|
|
||||||
"&@**@&....%@..$@=$...&-..-@.@@@@@%.--.*@#.+@$.-@...@%...@-.$@%.$#*.=%.%@.",
|
|
||||||
"$@==@$....%@..#@-%%&.+@--@#....@%..%@-=@$.$@=-@#..+@+...#@-=@*.$@=-@+....",
|
|
||||||
".+@@+.....%@..@@@@@%..#@@#.....@%..$-@=+...+=@%$..+@+...$#@@&...+@@#.....",
|
|
||||||
]
|
|
||||||
palette = {
|
|
||||||
".":"#181818",
|
|
||||||
"+":"#6E6E0F",
|
|
||||||
"@":"#FFFF00",
|
|
||||||
"#":"#A0A009",
|
|
||||||
"$":"#3B3B14",
|
|
||||||
"%":"#B9B907",
|
|
||||||
"&":"#87870C",
|
|
||||||
"*":"#545411",
|
|
||||||
"=":"#E6E602",
|
|
||||||
"-":"#CFCF04",
|
|
||||||
}
|
|
||||||
|
|
||||||
timeDefaultFormat = '%H:%M:%S'
|
|
||||||
dateDefaultFormat = '%d-%m-%y'
|
|
||||||
dayDefaultFormat = '%A'
|
|
||||||
weekDefaultFormat = 'wk %q' # %q added by Kristoffer for different week calculation.
|
|
||||||
|
|
||||||
defaultConfigFile = '~/.pywmdatetimerc'
|
|
||||||
|
|
||||||
class Application(wmoo.Application):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
|
||||||
parser.add_option('-a', '--antialiased', dest='antialiased',
|
|
||||||
action="store_true", default=False)
|
|
||||||
parser.add_option('-f', '--foreground', type='string', default='cyan3')
|
|
||||||
parser.add_option('-F', '--font', type='string', default='6x8orig')
|
|
||||||
parser.add_option('-b', '--background', type='string', default='black')
|
|
||||||
parser.add_option('-t', '--timeformat', type='string', default=timeDefaultFormat)
|
|
||||||
parser.add_option('-d', '--dateformat', default=dateDefaultFormat)
|
|
||||||
parser.add_option('-y', '--weekdayformat', default=dayDefaultFormat)
|
|
||||||
parser.add_option('-e', '--weekformat', default=weekDefaultFormat)
|
|
||||||
parser.add_option('--height', type='int', default=64)
|
|
||||||
parser.add_option('-r', '--rgbfile')
|
|
||||||
#parser.add_option('-c', '--configfile', default=defaultConfigFile)
|
|
||||||
parser.add_option('--debug', action='store_true', default=False)
|
|
||||||
|
|
||||||
configFile = os.path.expanduser("~/.pywmdatetimerc")
|
|
||||||
# Merge the two configs, let the commandline options overwrite those in the
|
|
||||||
# configuration file.
|
|
||||||
config = readConfigFile(configFile, sys.stderr)
|
|
||||||
parser.set_defaults(**config)
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
palette[0] = options.background
|
|
||||||
palette[2] = options.foreground
|
|
||||||
|
|
||||||
self.hpad = hpad = (64 - options.height) / 2
|
|
||||||
|
|
||||||
if options.antialiased:
|
|
||||||
background = [((6,3+hpad),(57,19+hpad)),
|
|
||||||
((3,22+hpad),(60,60-hpad))]
|
|
||||||
else:
|
|
||||||
background = [((3,3+hpad),(59,60-hpad))]
|
|
||||||
|
|
||||||
wmoo.Application.__init__(self,
|
|
||||||
patterns=patterns,
|
|
||||||
font_name=options.font,
|
|
||||||
bg=0, fg=2, palette=palette,
|
|
||||||
background=background,
|
|
||||||
debug=options.debug)
|
|
||||||
|
|
||||||
|
|
||||||
if options.antialiased:
|
|
||||||
self.addWidget('date', wmoo.Label, orig=(4,24+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
self.addWidget('day', wmoo.Label, orig=(4,36+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
if 48+hpad <= 50:
|
|
||||||
self.addWidget('week', wmoo.Label, orig=(4,48), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
else:
|
|
||||||
self.addWidget('time', wmoo.Label, orig=(4, 5+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
self.addWidget('time2', wmoo.Label, orig=(4,16+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
self.addWidget('date', wmoo.Label, orig=(4,27+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
self.addWidget('day', wmoo.Label, orig=(4,38+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
if 49+hpad <= 50:
|
|
||||||
self.addWidget('week', wmoo.Label, orig=(4,49+hpad), size=(54,10), align=wmoo.CENTRE)
|
|
||||||
|
|
||||||
self.timeFmt = options.timeformat
|
|
||||||
self.dateFmt = options.dateformat
|
|
||||||
self.dayFmt = options.weekdayformat
|
|
||||||
self.weekFmt = options.weekformat
|
|
||||||
self.antialiased = options.antialiased
|
|
||||||
self.debug = options.debug
|
|
||||||
|
|
||||||
self.recalcWeek = self.weekFmt.find('%q') + 1 # True if we found %q.
|
|
||||||
self.counter = -1
|
|
||||||
self.lastStrs = [''] * 4
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
def calculateWeek(self, localTime):
|
|
||||||
"""Calculate the week number as we do, for example in Sweden.
|
|
||||||
|
|
||||||
That is, add one to the %W format if the year didn't start on a monday."""
|
|
||||||
day = int(time.strftime('%j', localTime))
|
|
||||||
weekDay = int(time.strftime('%w')) - 1
|
|
||||||
if weekDay == -1:
|
|
||||||
weekDay = 6
|
|
||||||
lastMonday = day - weekDay
|
|
||||||
if lastMonday % 7 == 0:
|
|
||||||
return int(time.strftime('%W'))
|
|
||||||
return int(time.strftime('%W')) + 1
|
|
||||||
|
|
||||||
def updateTimeString(self, s):
|
|
||||||
if self.antialiased:
|
|
||||||
x, y = 8, 6+self.hpad
|
|
||||||
for c in s:
|
|
||||||
charW = 7
|
|
||||||
charX = (ord(c) - ord('0')) * 7
|
|
||||||
if not c.isdigit():
|
|
||||||
charX = 70
|
|
||||||
charW = 3
|
|
||||||
self.putPattern(charX, 0, charW, 10, x, y)
|
|
||||||
x += charW
|
|
||||||
else:
|
|
||||||
self['time'].setText(s)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self.counter += 1
|
|
||||||
lt = time.localtime()
|
|
||||||
timeStr = time.strftime(self.timeFmt, lt)
|
|
||||||
self.updateTimeString(timeStr)
|
|
||||||
self.lastStrs[0] = timeStr
|
|
||||||
if self.counter % 100 == 0:
|
|
||||||
# We only perform the date/week checks/updates once every 100th
|
|
||||||
# iteration. We will maybe lag behind a couple of seconds when
|
|
||||||
# switching, but switching occurs seldom and it will be alot of
|
|
||||||
# unnecessary checks :).
|
|
||||||
dateStr = time.strftime(self.dateFmt, lt)
|
|
||||||
newWeekFmt = self.weekFmt
|
|
||||||
if self.recalcWeek:
|
|
||||||
week = self.calculateWeek(lt)
|
|
||||||
newWeekFmt = self.weekFmt.replace('%q', str(week))
|
|
||||||
weekStr = time.strftime(newWeekFmt, lt)
|
|
||||||
dayStr = time.strftime(self.dayFmt, lt)
|
|
||||||
if self.lastStrs[1] != dateStr:
|
|
||||||
self['date'].setText(dateStr)
|
|
||||||
self.lastStrs[1] = dateStr
|
|
||||||
if self.lastStrs[2] != dayStr:
|
|
||||||
self['day'].setText(dayStr)
|
|
||||||
self.lastStrs[2] = dayStr
|
|
||||||
if self.lastStrs[3] != weekStr:
|
|
||||||
if 'week' in self._widgets:
|
|
||||||
self['week'].setText(weekStr)
|
|
||||||
self.lastStrs[3] = weekStr
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app = Application()
|
|
||||||
app.run()
|
|
||||||
@@ -1,679 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""pywmgeneric.py
|
|
||||||
|
|
||||||
WindowMaker dockapp to display the output from an external program, or the
|
|
||||||
string returned from a python function. Mouse actions can be associated with
|
|
||||||
the displayed text.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Kristoffer Erlandsson
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Changes
|
|
||||||
2003-07-02 Kristoffer Erlandsson
|
|
||||||
Added support for up to 10 mouse buttons.
|
|
||||||
The char translation now handles both upper and lower case.
|
|
||||||
|
|
||||||
2003-06-29 Kristoffer Erlandsson
|
|
||||||
Additional error checking around string interpolations from cfg file.
|
|
||||||
|
|
||||||
2003-06-27 Kristoffer Erlandsson
|
|
||||||
First working version
|
|
||||||
"""
|
|
||||||
|
|
||||||
usage = """pywmgeneric.py [options]
|
|
||||||
Available options are:
|
|
||||||
-h, --help print this help
|
|
||||||
-t, --text <color> set the text color
|
|
||||||
-b, --background <color> set the background color
|
|
||||||
-F, --font <file> set the font name
|
|
||||||
-r, --rgbfile <file> set the rgb file to get color codes from
|
|
||||||
-c, --configfile <file> set the config file to use
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import string
|
|
||||||
import ConfigParser
|
|
||||||
import getopt
|
|
||||||
import popen2
|
|
||||||
|
|
||||||
import wmdocklib
|
|
||||||
|
|
||||||
prevStat = {'user':0,
|
|
||||||
'nice':0,
|
|
||||||
'sys':0,
|
|
||||||
'idle':0,
|
|
||||||
'total':0,
|
|
||||||
}
|
|
||||||
import re
|
|
||||||
cpuinfo = re.compile(r'^cpu[^ ]* +(?P<user>[0-9]+) +(?P<nice>[0-9]+)'
|
|
||||||
r'+(?P<sys>[0-9]+) +(?P<idle>[0-9]+)')
|
|
||||||
|
|
||||||
class UserMethods:
|
|
||||||
"""Put methods that should be called when the action is method=... here.
|
|
||||||
|
|
||||||
The action methods should return a function, which in turn returns
|
|
||||||
the string to be displayed (if no 'display =' exists) and stored
|
|
||||||
for later retreival.
|
|
||||||
|
|
||||||
The mouse action methods gets the entry instance as an argument. Return
|
|
||||||
value doesn't matter.
|
|
||||||
|
|
||||||
An instance of this class is created at initialization and passed to all
|
|
||||||
entries, so keep in mind that they share the same object.
|
|
||||||
|
|
||||||
THE METHODS ALREADY HERE ARE JUST SAMPLES AND WILL PROBABLY NOT WORK
|
|
||||||
WITH YOUR SYSTEM.
|
|
||||||
"""
|
|
||||||
|
|
||||||
userTicks = sysTicks = niceTicks = idleTicks = 0
|
|
||||||
|
|
||||||
def getCpuTemp(self):
|
|
||||||
def result():
|
|
||||||
global prevStat
|
|
||||||
try:
|
|
||||||
f = file('/proc/stat', 'r')
|
|
||||||
except IOError:
|
|
||||||
return 'error'
|
|
||||||
|
|
||||||
currStat = dict(
|
|
||||||
[(k, int(v))
|
|
||||||
for (k,v) in cpuinfo.match(f.readline()).groupdict().items()]
|
|
||||||
)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
total = 0
|
|
||||||
for k,v in currStat.items():
|
|
||||||
total += v
|
|
||||||
currStat['total'] = total
|
|
||||||
totalTicks = (currStat['total'] - prevStat['total'])
|
|
||||||
|
|
||||||
result = {}
|
|
||||||
if (totalTicks <= 0):
|
|
||||||
return '00/00/00'
|
|
||||||
|
|
||||||
for k in prevStat:
|
|
||||||
result[k] = (100. * (currStat[k] - prevStat[k])) / totalTicks
|
|
||||||
prevStat = currStat
|
|
||||||
|
|
||||||
return '%(user)02.f/%(sys)02.f/%(idle)02.f' % result
|
|
||||||
return result
|
|
||||||
|
|
||||||
def getSysTemp(self):
|
|
||||||
try:
|
|
||||||
f = file('/proc/sys/dev/sensors/w83697hf-isa-0290/temp1', 'r')
|
|
||||||
except IOError:
|
|
||||||
return lambda: 'error'
|
|
||||||
temp = f.readline().split()[2]
|
|
||||||
f.close()
|
|
||||||
return lambda: 'sys: %s' % temp
|
|
||||||
|
|
||||||
def ls(self):
|
|
||||||
return lambda: 'boh'
|
|
||||||
|
|
||||||
def showDnWithoutDescs(self, entry):
|
|
||||||
"""Strip descriptions from some text where the descs are indented.
|
|
||||||
|
|
||||||
Display it in an xmessage.
|
|
||||||
"""
|
|
||||||
text = entry.getAllText()
|
|
||||||
s = '\n'.join([x for x in text.split('\n') if not x.startswith(' ')])
|
|
||||||
os.system('xmessage "' + s.replace('"', r'\"') + '" &')
|
|
||||||
|
|
||||||
def showTvWithoutDescs(self, entry):
|
|
||||||
"""Strip descriptions from some text where the descs are indented.
|
|
||||||
|
|
||||||
Display it in an xmessage.
|
|
||||||
"""
|
|
||||||
text = entry.getAllText()
|
|
||||||
s='\n'.join([x for x in
|
|
||||||
text.split('\n')[1:] if not x.startswith(' ')])
|
|
||||||
s = s.replace('\n\n', '\n')
|
|
||||||
os.system('xmessage "' + s.replace('"', r'\"') + '" &')
|
|
||||||
|
|
||||||
width = 64
|
|
||||||
height = 64
|
|
||||||
|
|
||||||
xOffset = 4
|
|
||||||
yOffset = 4
|
|
||||||
|
|
||||||
maxChars = 13
|
|
||||||
|
|
||||||
defaultConfigFile = '~/.pywmgenericrc'
|
|
||||||
defaultRGBFiles = ('/usr/share/X11/rgb.txt', '/usr/X11R6/lib/X11/rgb.txt')
|
|
||||||
|
|
||||||
err = sys.stderr.write
|
|
||||||
|
|
||||||
def addString(s, x, y):
|
|
||||||
"""Convenience function around pwymhelpers.addString."""
|
|
||||||
try:
|
|
||||||
wmdocklib.addString(s, x, y, xOffset, yOffset,
|
|
||||||
width, height)
|
|
||||||
except ValueError, e:
|
|
||||||
sys.stderr.write('Error when painting string:\n' + str(e) + '\n')
|
|
||||||
sys.exit(3)
|
|
||||||
|
|
||||||
def clearLine(y):
|
|
||||||
"""Clear a line of text at position y."""
|
|
||||||
wmdocklib.copyXPMArea(0, 64+yOffset,
|
|
||||||
width - 2 * xOffset, char_height,
|
|
||||||
xOffset, y + yOffset)
|
|
||||||
|
|
||||||
def getXY(line):
|
|
||||||
"""Return the x and y positions to be used at line line."""
|
|
||||||
return 0, line * (char_height + 3) + 1
|
|
||||||
|
|
||||||
def isTrue(s):
|
|
||||||
"""Return true if the string s can be interpreted as a true value.
|
|
||||||
|
|
||||||
Raises ValueError if we get a string we don't like.
|
|
||||||
"""
|
|
||||||
trueThings = ['on', 'yes', '1', 'true']
|
|
||||||
falseThings = ['off', 'no', '0', 'false']
|
|
||||||
if s in trueThings:
|
|
||||||
return 1
|
|
||||||
elif s in falseThings:
|
|
||||||
return 0
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
|
|
||||||
class Entry:
|
|
||||||
def __init__(self, line, updateDelay, action, mouseActions,
|
|
||||||
userMethods, display=None, scrollText=1):
|
|
||||||
self._updateDelay = updateDelay
|
|
||||||
self._line = line
|
|
||||||
self._action = self._parseAction(action)
|
|
||||||
self._mouseActions = [self._parseAction(a) for a in mouseActions]
|
|
||||||
self._userMethods = userMethods
|
|
||||||
self._display = display
|
|
||||||
self._scrollText = scrollText
|
|
||||||
|
|
||||||
self._glue = ' ... '
|
|
||||||
self._scrollPos = 0
|
|
||||||
self._tickCount = 0L
|
|
||||||
|
|
||||||
self._runningProcs = []
|
|
||||||
self._actionProc = None
|
|
||||||
self._getTextMethod = None
|
|
||||||
self._allText = ''
|
|
||||||
self._displayLine = ''
|
|
||||||
# Do one action when we start, so we are sure that one gets done even
|
|
||||||
# if we do not want any other updates.
|
|
||||||
self._doAction()
|
|
||||||
self._lastActionAt = time.time()
|
|
||||||
|
|
||||||
def _parseAction(self, action):
|
|
||||||
"""Parse an action string, return (<action>, <argument string>).
|
|
||||||
|
|
||||||
Or none if we get an empty action."""
|
|
||||||
if action:
|
|
||||||
whatToDo = action.split()[0]
|
|
||||||
argStr = action[len(whatToDo):].lstrip()
|
|
||||||
return (whatToDo, argStr)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _execExternal(self, command):
|
|
||||||
"""Exec an external command in the background.
|
|
||||||
|
|
||||||
Return the running process as created by Popen3()."""
|
|
||||||
proc = popen2.Popen3(command)
|
|
||||||
self._runningProcs.append(proc)
|
|
||||||
return proc
|
|
||||||
|
|
||||||
def _doMouseAction(self, button):
|
|
||||||
"""Perform the mouse action associated with a button."""
|
|
||||||
if len(self._mouseActions) < button:
|
|
||||||
return # Just for safety, shouldn't happen.
|
|
||||||
item = self._mouseActions[button - 1]
|
|
||||||
if item:
|
|
||||||
# We have an action associated with the button.
|
|
||||||
action, arg = item
|
|
||||||
else:
|
|
||||||
# No action associated with the button.
|
|
||||||
return
|
|
||||||
if action == 'exec':
|
|
||||||
self._execExternal(self._expandStr(arg))
|
|
||||||
elif action == 'method':
|
|
||||||
try:
|
|
||||||
method = getattr(self._userMethods, arg)
|
|
||||||
except AttributeError:
|
|
||||||
method = None
|
|
||||||
if method:
|
|
||||||
method(self)
|
|
||||||
else:
|
|
||||||
err("Warning: Method %s does not exist." % arg)
|
|
||||||
elif action == 'update':
|
|
||||||
self._doAction()
|
|
||||||
else:
|
|
||||||
err("Warning: Unknown mouse action: %s, ignoring.\n" % action)
|
|
||||||
|
|
||||||
def _doAction(self):
|
|
||||||
"""Perform the action associated with this entry."""
|
|
||||||
if self._action is None:
|
|
||||||
return
|
|
||||||
action, arg = self._action
|
|
||||||
if action == 'exec':
|
|
||||||
if self._actionProc is None :
|
|
||||||
self._actionProc = self._execExternal(arg)
|
|
||||||
else:
|
|
||||||
if not self._actionProc in self._runningProcs:
|
|
||||||
# The action process since the last time is finished, we
|
|
||||||
# can start another one without risking that we get
|
|
||||||
# flooded by processes.
|
|
||||||
self._actionProc = self._execExternal(arg)
|
|
||||||
self._getTextMethod = self._readFromActionProc
|
|
||||||
elif action == 'method':
|
|
||||||
try:
|
|
||||||
method = getattr(self._userMethods, arg)
|
|
||||||
except AttributeError:
|
|
||||||
method = None
|
|
||||||
if method:
|
|
||||||
self._getTextMethod = method()
|
|
||||||
else:
|
|
||||||
err('Warning: method %s does not exist. Ignoring.\n' % arg)
|
|
||||||
else:
|
|
||||||
err("Warning: Unknown action: %s, ignoring.\n" % action)
|
|
||||||
|
|
||||||
def _readFromActionProc(self):
|
|
||||||
"""If our action process is ready, return the output. Otherwise None.
|
|
||||||
"""
|
|
||||||
if self._actionProc.poll() == -1:
|
|
||||||
# Wait until the process is ready before we really read the text.
|
|
||||||
return None
|
|
||||||
# fromchild.read() will return '' if we allready have read the output
|
|
||||||
# so there will be no harm in calling this method more times.
|
|
||||||
return self._actionProc.fromchild.read()
|
|
||||||
|
|
||||||
def _reapZombies(self):
|
|
||||||
"""Poll all running childs. This will reap all zombies."""
|
|
||||||
i = 0
|
|
||||||
for p in self._runningProcs:
|
|
||||||
val = p.poll()
|
|
||||||
if val != -1:
|
|
||||||
self._runningProcs.pop(i)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
def _updateText(self):
|
|
||||||
"""Get the text, update the display if it has changed.
|
|
||||||
"""
|
|
||||||
text = ''
|
|
||||||
if self._getTextMethod:
|
|
||||||
text = self._getTextMethod()
|
|
||||||
# Only change the text if we get anything from the getTextMethod()
|
|
||||||
if text:
|
|
||||||
self._allText = text
|
|
||||||
if self._display is None:
|
|
||||||
# We have no display = in the config file, we want to
|
|
||||||
# display the first line of the output of the action.
|
|
||||||
if text:
|
|
||||||
displayLine = text.split(os.linesep)[0]
|
|
||||||
else:
|
|
||||||
displayLine = self._displayLine
|
|
||||||
else:
|
|
||||||
displayLine = self._display
|
|
||||||
if displayLine != self._displayLine:
|
|
||||||
# Line to display has changed, display the new one.
|
|
||||||
self._displayLine = displayLine
|
|
||||||
self._scrollPos = 0
|
|
||||||
self.displayText(displayLine)
|
|
||||||
elif len(self._displayLine) > maxChars and self._scrollText:
|
|
||||||
# Line is the same and is longer than the display and we
|
|
||||||
# want to scroll it.
|
|
||||||
if self._tickCount % 2 == 0:
|
|
||||||
# Only scroll every third tick.
|
|
||||||
self._scrollAndDisplay()
|
|
||||||
|
|
||||||
def _scrollAndDisplay(self):
|
|
||||||
"""Scroll the text one step to the left and redisplay it.
|
|
||||||
|
|
||||||
When reaching the end, paint number of spaces before scrolling in the
|
|
||||||
same line again from the right.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# increase the amount of scrolled chars by one, modulo the lenght.
|
|
||||||
# take the line, append to it some glue and a copy of the line
|
|
||||||
# again, drop as many characters as the updated scrollPos, display
|
|
||||||
# the resulting text.
|
|
||||||
self._scrollPos += 1
|
|
||||||
self._scrollPos %= len(self._displayLine) + len(self._glue)
|
|
||||||
disp = self._displayLine + self._glue + self._displayLine
|
|
||||||
disp = disp[self._scrollPos:]
|
|
||||||
self.displayText(disp)
|
|
||||||
|
|
||||||
def tick1(self):
|
|
||||||
"""Do things that should be done often.
|
|
||||||
"""
|
|
||||||
self._tickCount += 1
|
|
||||||
self._reapZombies()
|
|
||||||
self._updateText()
|
|
||||||
currTime = time.time()
|
|
||||||
if not self._updateDelay is None and \
|
|
||||||
currTime - self._lastActionAt > self._updateDelay:
|
|
||||||
# We want to do this last in the tick so the command gets the time
|
|
||||||
# to finish before the next tick (if it's a fast one).
|
|
||||||
self._lastActionAt = currTime
|
|
||||||
self._doAction()
|
|
||||||
|
|
||||||
def tick2(self):
|
|
||||||
"""Do things that should be done a bit less often.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def translateText(self, text):
|
|
||||||
"""Translate chars that can't be painted in the app to something nicer.
|
|
||||||
|
|
||||||
Or nothing if we can't come up with something good. Could be nice to
|
|
||||||
extend this function with chars more fitting for your language.
|
|
||||||
"""
|
|
||||||
fromChars = u'ñźńśćżłáéíóúàèìòùâêîôûäëïöüãẽĩõũ'
|
|
||||||
toChars = u'nznsczlaeiouaeiouaeiouaeiouaeiou'
|
|
||||||
for frm, to in zip(fromChars, toChars):
|
|
||||||
text = text.replace(frm, to)
|
|
||||||
text = text.replace(frm.upper(), to.upper())
|
|
||||||
text = ''.join([i for i in text if 32 <= ord(i) < 128])
|
|
||||||
return text
|
|
||||||
|
|
||||||
def getAllText(self):
|
|
||||||
return self._allText
|
|
||||||
|
|
||||||
def getDisplayedLine(self):
|
|
||||||
return self._displayLine
|
|
||||||
|
|
||||||
def _expandStr(self, s):
|
|
||||||
"""Expand s, which now should be a line from an on_mouseX field.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
res = s % {'allText' : self._allText,
|
|
||||||
'displayedLine' : self._displayLine,
|
|
||||||
'allTextEscaped' : self._allText.replace('"', r'\"'),
|
|
||||||
'allTextButFirstLine' :
|
|
||||||
'\n'.join(self._allText.split('\n')[1:]),
|
|
||||||
'allTextButFirstLineEscaped' :
|
|
||||||
'\n'.join(self._allText.replace('"', '\"').
|
|
||||||
split('\n')[1:])}
|
|
||||||
except (KeyError, TypeError, ValueError):
|
|
||||||
err(
|
|
||||||
"Warning: %s doesn't expand correctly. Ignoring interpolations.\n"
|
|
||||||
% s)
|
|
||||||
res = s
|
|
||||||
return res
|
|
||||||
|
|
||||||
def displayText(self, text):
|
|
||||||
"""Display text on the entry's line.
|
|
||||||
|
|
||||||
Remove or translate characters that aren't supported. Truncate the text
|
|
||||||
to fit in the app.
|
|
||||||
"""
|
|
||||||
x, y = getXY(self._line)
|
|
||||||
clearLine(y)
|
|
||||||
addString(self.translateText(text)[:maxChars], x, y)
|
|
||||||
|
|
||||||
def mouseClicked(self, button):
|
|
||||||
"""A mouse button has been clicked, do things."""
|
|
||||||
if 0 < button < 11:
|
|
||||||
self._doMouseAction(button)
|
|
||||||
|
|
||||||
class PywmGeneric:
|
|
||||||
def __init__(self, config):
|
|
||||||
self._entrys = []
|
|
||||||
line = 0
|
|
||||||
um = UserMethods()
|
|
||||||
for c in config:
|
|
||||||
# Create our 5 entrys.
|
|
||||||
if not c:
|
|
||||||
self._entrys.append(None)
|
|
||||||
line += 1
|
|
||||||
continue
|
|
||||||
delay = c.get('update_delay')
|
|
||||||
if not delay is None:
|
|
||||||
try:
|
|
||||||
delay = self.parseTimeStr(delay)
|
|
||||||
except ValueError:
|
|
||||||
err("Malformed update_delay in section %s. "
|
|
||||||
% str(i))
|
|
||||||
err("Ignoring this section.\n")
|
|
||||||
self._entrys.append(None)
|
|
||||||
line += 1
|
|
||||||
continue
|
|
||||||
action = c.get('action')
|
|
||||||
display = c.get('display')
|
|
||||||
if action is None and display is None:
|
|
||||||
err(
|
|
||||||
"Warning: No action or display in section %d, ignoring it.\n"
|
|
||||||
% i)
|
|
||||||
self._entrys.append(None)
|
|
||||||
else:
|
|
||||||
scroll = isTrue(c.get('scroll', '1'))
|
|
||||||
# Get the mouse actions.
|
|
||||||
mouseActions = []
|
|
||||||
for i in range(10):
|
|
||||||
but = str(i + 1)
|
|
||||||
opt = 'on_mouse' + but
|
|
||||||
mouseActions.append(c.get(opt))
|
|
||||||
self._entrys.append(Entry(line, delay, action,
|
|
||||||
mouseActions, um, display, scroll))
|
|
||||||
line += 1
|
|
||||||
self._setupMouseRegions()
|
|
||||||
|
|
||||||
def _setupMouseRegions(self):
|
|
||||||
for i in range(5):
|
|
||||||
x, y = getXY(i)
|
|
||||||
if not self._entrys[i] is None:
|
|
||||||
wmdocklib.addMouseRegion(i, x + xOffset, y + yOffset,
|
|
||||||
width - 2 * xOffset, y + yOffset + char_height)
|
|
||||||
|
|
||||||
def parseTimeStr(self, timeStr):
|
|
||||||
"""Take a string on a form like 10h and return the number of seconds.
|
|
||||||
|
|
||||||
Raise ValueError if timeStr is on a bad format.
|
|
||||||
"""
|
|
||||||
multipliers = {'s' : 1, 'm' : 60, 'h' : 3600}
|
|
||||||
timeStr = timeStr.strip()
|
|
||||||
if timeStr:
|
|
||||||
timeLetter = timeStr[-1]
|
|
||||||
multiplier = multipliers.get(timeLetter)
|
|
||||||
if not multiplier is None:
|
|
||||||
timeNum = float(timeStr[:-1].strip())
|
|
||||||
numSecs = timeNum * multiplier
|
|
||||||
return numSecs
|
|
||||||
raise ValueError, 'Invalid literal'
|
|
||||||
|
|
||||||
def _checkForEvents(self):
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
while not event is None:
|
|
||||||
if event['type'] == 'destroynotify':
|
|
||||||
sys.exit(0)
|
|
||||||
elif event['type'] == 'buttonrelease':
|
|
||||||
region = wmdocklib.checkMouseRegion(event['x'], event['y'])
|
|
||||||
button = event['button']
|
|
||||||
if region != -1:
|
|
||||||
if not self._entrys[region] is None:
|
|
||||||
self._entrys[region].mouseClicked(button)
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
|
|
||||||
def mainLoop(self):
|
|
||||||
counter = -1
|
|
||||||
while 1:
|
|
||||||
counter += 1
|
|
||||||
self._checkForEvents()
|
|
||||||
if counter % 2 == 0:
|
|
||||||
[e.tick1() for e in self._entrys if not e is None]
|
|
||||||
if counter % 20 == 0:
|
|
||||||
[e.tick2() for e in self._entrys if not e is None]
|
|
||||||
|
|
||||||
if counter == 999999:
|
|
||||||
counter = -1
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
def parseCommandLine(argv):
|
|
||||||
"""Parse the commandline. Return a dictionary with options and values."""
|
|
||||||
shorts = 'ht:b:r:c:F:'
|
|
||||||
longs = ['help', 'text=', 'background=', 'rgbfile=', 'configfile=',
|
|
||||||
'font=', 'debug']
|
|
||||||
try:
|
|
||||||
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
|
|
||||||
except getopt.GetoptError, e:
|
|
||||||
err('Error when parsing commandline: ' + str(e) + '\n')
|
|
||||||
err(usage)
|
|
||||||
sys.exit(2)
|
|
||||||
d = {}
|
|
||||||
for o, a in opts:
|
|
||||||
if o in ('-h', '--help'):
|
|
||||||
sys.stdout.write(usage)
|
|
||||||
sys.exit(0)
|
|
||||||
if o in ('-t', '--text'):
|
|
||||||
d['text'] = a
|
|
||||||
if o in ('-b', '--background'):
|
|
||||||
d['background'] = a
|
|
||||||
if o in ('-F', '--font'):
|
|
||||||
d['font'] = a
|
|
||||||
if o in ('-r', '--rgbfile'):
|
|
||||||
d['rgbfile'] = a
|
|
||||||
if o in ('-c', '--configfile'):
|
|
||||||
d['configfile'] = a
|
|
||||||
if o in ('--debug'):
|
|
||||||
d['debug'] = True
|
|
||||||
return d
|
|
||||||
|
|
||||||
def readConfigFile(fileName):
|
|
||||||
"""Read the config file.
|
|
||||||
|
|
||||||
Return a list with dictionaries with the options and values in sections
|
|
||||||
[0]-[4].
|
|
||||||
"""
|
|
||||||
fileName = os.path.expanduser(fileName)
|
|
||||||
if not os.access(fileName, os.R_OK):
|
|
||||||
err("Can't read the configuration file %s.\n" % fileName)
|
|
||||||
# We can't do much without a configuration file
|
|
||||||
sys.exit(3)
|
|
||||||
cp = ConfigParser.ConfigParser()
|
|
||||||
try:
|
|
||||||
cp.read(fileName)
|
|
||||||
except ConfigParser.Error, e:
|
|
||||||
err("Error when reading configuration file:\n%s\n" % str(e))
|
|
||||||
sys.exit(3)
|
|
||||||
l = [{}, {}, {}, {}, {}]
|
|
||||||
for i in range(5):
|
|
||||||
strI = str(i)
|
|
||||||
if cp.has_section(strI):
|
|
||||||
for o in cp.options(strI):
|
|
||||||
l[i][o] = cp.get(strI, o, raw=1)
|
|
||||||
return l
|
|
||||||
|
|
||||||
background = \
|
|
||||||
[
|
|
||||||
' ...............................................................................................',
|
|
||||||
' .///..___..ooo..___..___.......................................................................',
|
|
||||||
' .///..___..ooo..___..___.......................................................................',
|
|
||||||
' .///..___..ooo..___..___.......................................................................',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///.._________________________________________________________________________________________',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..ooo.......................................................................',
|
|
||||||
' .///..___..___..___..ooo.......................................................................',
|
|
||||||
' .///..___..___..___..ooo.......................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' ...............................................................................................',
|
|
||||||
' ...............................................................................................',
|
|
||||||
]
|
|
||||||
|
|
||||||
def main():
|
|
||||||
clConfig = parseCommandLine(sys.argv)
|
|
||||||
|
|
||||||
palette = {
|
|
||||||
'.': '#0000FF',
|
|
||||||
'o': '#C7C3C7',
|
|
||||||
'O': '#86828E',
|
|
||||||
'+': '#EFF3EF',
|
|
||||||
'@': '#616161',
|
|
||||||
'#': '#9EA29E',
|
|
||||||
'$': '#414141',
|
|
||||||
}
|
|
||||||
|
|
||||||
palette['o'] = clConfig.get('indicator', '#20b2aa')
|
|
||||||
palette['/'] = clConfig.get('graph', '#20b2aa')
|
|
||||||
palette['-'] = clConfig.get('graphbg', '#707070')
|
|
||||||
palette['_'] = clConfig.get('background', '#FFFFFF')
|
|
||||||
palette['%'] = clConfig.get('text', '#20B2AE')
|
|
||||||
|
|
||||||
font = clConfig.get('font', '6x8')
|
|
||||||
|
|
||||||
configFile = clConfig.get('configfile', defaultConfigFile)
|
|
||||||
if not configFile.count(os.sep):
|
|
||||||
configFile = os.sep.join(sys.argv[0].split(os.sep)[:-1]) + os.sep + configFile
|
|
||||||
configFile = os.path.expanduser(configFile)
|
|
||||||
config = readConfigFile(configFile)
|
|
||||||
try:
|
|
||||||
programName = sys.argv[0].split(os.sep)[-1]
|
|
||||||
except IndexError:
|
|
||||||
programName = ''
|
|
||||||
sys.argv[0] = programName
|
|
||||||
|
|
||||||
global char_width, char_height
|
|
||||||
char_width, char_height = wmdocklib.initPixmap(#patterns=background,
|
|
||||||
font_name=font,
|
|
||||||
bg='_', fg='%',
|
|
||||||
palette=palette)
|
|
||||||
|
|
||||||
wmdocklib.openXwindow(sys.argv, width, height)
|
|
||||||
pywmgeneric = PywmGeneric(config)
|
|
||||||
pywmgeneric.mainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,541 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmhdmon.py
|
|
||||||
|
|
||||||
WindowMaker dockapp to monitor the free space on your partitions and
|
|
||||||
the disk activity.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Kristoffer Erlandsson
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Changes
|
|
||||||
|
|
||||||
2005-09-02 Mario Frasca
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
Fixed a bug where the numbers wouldn't show if they were between 1000 and 1024.
|
|
||||||
|
|
||||||
2003-06-25 Kristoffer Erlandsson
|
|
||||||
Fixed a bug where a mouse click caused the app to enter an infinite loop
|
|
||||||
|
|
||||||
2003-06-24 Kristoffer Erlandsson
|
|
||||||
Additional fine tuning
|
|
||||||
|
|
||||||
2003-06-23 Kristoffer Erlandsson
|
|
||||||
First working version
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
usage = """pywmhdmon.py [options]
|
|
||||||
Available options are:
|
|
||||||
-h, --help print this help
|
|
||||||
-t, --textcolor <color> set the text color
|
|
||||||
-f, --barfgcolor <color> set the foregroundcolor of the act. bar
|
|
||||||
-g, --barbgcolor <color> set the background color of the act. bar
|
|
||||||
-b, --background <color> set the background color
|
|
||||||
-F, --font <file> set the font name
|
|
||||||
-r, --rgbfile <file> set the rgb file to get color codes from
|
|
||||||
-c, --configfile <file> set the config file to use
|
|
||||||
-p, --procstat <file> set the location of /proc/stat
|
|
||||||
-s, --skipconf <num> determines how many configuration items to skip
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import getopt
|
|
||||||
import os
|
|
||||||
|
|
||||||
import wmdocklib
|
|
||||||
|
|
||||||
width = 64
|
|
||||||
height = 64
|
|
||||||
|
|
||||||
xOffset = 4
|
|
||||||
yOffset = 5
|
|
||||||
|
|
||||||
graphStartX = 7
|
|
||||||
graphStartY = 53
|
|
||||||
graphHeight = 4
|
|
||||||
|
|
||||||
graphBgStartX = 72-64
|
|
||||||
graphBgStartY = 53+64
|
|
||||||
|
|
||||||
graphLineStartX = 2
|
|
||||||
graphLineStartY = 58+64
|
|
||||||
|
|
||||||
defaultConfigFile = os.environ['HOME']+'/.pywmhdmonrc'
|
|
||||||
defaultProcStat = '/proc/stat'
|
|
||||||
displayModes = ('bar', 'percent', 'free', 'used')
|
|
||||||
defaultMode = 'bar'
|
|
||||||
|
|
||||||
hdmon = None
|
|
||||||
|
|
||||||
class NotMounted(OSError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class PywmHDMon:
|
|
||||||
def __init__(self, pathsToMonitor, procStat='/proc/stat', actMonEnabled=1, skipping=0):
|
|
||||||
self._pathsToMonitor = pathsToMonitor
|
|
||||||
self._actMonEnabled = actMonEnabled
|
|
||||||
self._skipping = skipping
|
|
||||||
self._lineCount = (height - yOffset*2 - 2) / (char_height+1)
|
|
||||||
|
|
||||||
self._statFile = procStat
|
|
||||||
self._maxIODiff = 0
|
|
||||||
self._lastIO = -1
|
|
||||||
for i in range(max(self._lineCount, len(pathsToMonitor)-skipping)):
|
|
||||||
wmdocklib.addMouseRegion(i+1, 8, self.getY(i+1)+yOffset,
|
|
||||||
58, self.getY(i+1)+char_height+yOffset)
|
|
||||||
|
|
||||||
|
|
||||||
def addString(self, s, x, y):
|
|
||||||
try:
|
|
||||||
wmdocklib.addString(s, x, y, xOffset, yOffset, width, height)
|
|
||||||
except ValueError, e:
|
|
||||||
sys.stderr.write('Error when painting string:\n' + str(e) + '\n')
|
|
||||||
sys.exit(3)
|
|
||||||
|
|
||||||
def getHdInfo(self, path):
|
|
||||||
"""Get the free and total space of the filesystem which path is on.
|
|
||||||
|
|
||||||
Return a tuple with (<total space>, <free space>) in bytes. Raise
|
|
||||||
OSError if we can't stat the path. Raise NotMounted if not mounted.
|
|
||||||
These operations are quite costly, not adviced to perform these checks
|
|
||||||
more than once every 10 seconds.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# check if is mounted <- st_dev(/mount/point) == st_dev(/mount)
|
|
||||||
if path is not '/':
|
|
||||||
statOwn = os.stat(path)
|
|
||||||
|
|
||||||
# the following is a bit ugly: it removes the trailing
|
|
||||||
# dirname from the mount point. split by '/', leave the
|
|
||||||
# last string, join back, check for empty string.
|
|
||||||
statCnt = os.stat('/'.join(path.split('/')[:-1]) or '/')
|
|
||||||
if statOwn[2] == statCnt[2]:
|
|
||||||
raise NotMounted
|
|
||||||
stat = os.statvfs(path)
|
|
||||||
blockSize = stat.f_bsize
|
|
||||||
availableBlocks = stat.f_bavail
|
|
||||||
totalBlocks = stat.f_blocks
|
|
||||||
free = blockSize * availableBlocks
|
|
||||||
total = blockSize * totalBlocks
|
|
||||||
return (total, free)
|
|
||||||
|
|
||||||
def paintGraph(self, percentFilled, x, y, w, thin=None):
|
|
||||||
"""Paint a graph with percentFilled percent filled.
|
|
||||||
|
|
||||||
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))
|
|
||||||
if paintWidth > 0:
|
|
||||||
wmdocklib.copyXPMArea(
|
|
||||||
graphLineStartX, graphLineStartY, paintWidth, thin or graphHeight,
|
|
||||||
x + xOffset, y + yOffset)
|
|
||||||
if w - paintWidth > 0:
|
|
||||||
wmdocklib.copyXPMArea(
|
|
||||||
graphBgStartX, graphBgStartY, w - paintWidth, thin or graphHeight,
|
|
||||||
x + paintWidth + xOffset, y + yOffset)
|
|
||||||
|
|
||||||
def getY(self, line):
|
|
||||||
"returns the y coordinate of the top line for the box"
|
|
||||||
interlinea = (height - yOffset*2 - 2 - self._lineCount * char_height) / (self._lineCount-1)
|
|
||||||
interlinea += char_height
|
|
||||||
lastBaseline = yOffset + self._lineCount * interlinea
|
|
||||||
from math import ceil
|
|
||||||
extraYOffset = int(ceil((height - yOffset - lastBaseline) / 2.0))
|
|
||||||
return extraYOffset + (line - 1) * interlinea
|
|
||||||
|
|
||||||
def paintLabel(self, line, label):
|
|
||||||
self.addString(label, 1, self.getY(line))
|
|
||||||
|
|
||||||
def paintHdData(self, line, data, mode):
|
|
||||||
total, free = data
|
|
||||||
xStart = (width*2)/5
|
|
||||||
if total==0:
|
|
||||||
self.addString(' ', width-yOffset*2-5*char_width-1, self.getY(line))
|
|
||||||
self.paintGraph(0, xStart, self.getY(line) + 4,
|
|
||||||
width - xOffset*2 - xStart - 2,
|
|
||||||
thin=1)
|
|
||||||
pass
|
|
||||||
elif mode == 'percent':
|
|
||||||
percent = (float(free) / float(total)) * 100.0
|
|
||||||
percentStr = (str(int(round(percent))) + '%').rjust(5)
|
|
||||||
self.addString(percentStr, xStart, self.getY(line))
|
|
||||||
elif mode == 'used':
|
|
||||||
totalStr = bytesToStr(total).rjust(5)
|
|
||||||
self.addString(totalStr, width-yOffset*2-5*char_width-1, self.getY(line))
|
|
||||||
elif mode == 'free':
|
|
||||||
freeStr = bytesToStr(free).rjust(5)
|
|
||||||
self.addString(freeStr, width-yOffset*2-5*char_width, self.getY(line))
|
|
||||||
elif mode == 'bar':
|
|
||||||
percentUsed = (float(total - free) / float(total)) * 100.0
|
|
||||||
self.paintGraph(percentUsed, xStart, self.getY(line) + 2,
|
|
||||||
width - xOffset*2 - xStart - 2)
|
|
||||||
else:
|
|
||||||
sys.stderr.write('Unknown display mode: %s, ignoring data.\n'
|
|
||||||
% mode)
|
|
||||||
def getHdActivity(self):
|
|
||||||
"""Return the current hd activity in percent.
|
|
||||||
|
|
||||||
Return how many percent of the max achieved activity during the
|
|
||||||
program's lifetime the current activity is. However, every time
|
|
||||||
this method is called we decrease the max achieved activity a
|
|
||||||
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
|
|
||||||
really exactly how active.
|
|
||||||
"""
|
|
||||||
|
|
||||||
statFile = file(self._statFile, 'r')
|
|
||||||
diskIoStartTag = 'disk_io: '
|
|
||||||
ioLine = None
|
|
||||||
for line in statFile:
|
|
||||||
if line.startswith(diskIoStartTag):
|
|
||||||
ioLine = line
|
|
||||||
statFile.close()
|
|
||||||
if ioLine is None:
|
|
||||||
# Can't get HD activity
|
|
||||||
sys.stderr.write("Can't get hd activity from %s\n" %
|
|
||||||
self._statFile)
|
|
||||||
return 0.0
|
|
||||||
ioLine = ioLine[len(diskIoStartTag):]
|
|
||||||
disks = ioLine.split()
|
|
||||||
currIO = 0
|
|
||||||
for disk in disks:
|
|
||||||
dataPart = disk.split(':')[1].strip(')(')
|
|
||||||
infos = dataPart.split(',')
|
|
||||||
blocksRead = long(infos[2])
|
|
||||||
blocksWritten = long(infos[4])
|
|
||||||
currIO += blocksRead + blocksWritten
|
|
||||||
if self._lastIO == -1:
|
|
||||||
self._lastIO = currIO
|
|
||||||
currDiff = currIO - self._lastIO
|
|
||||||
self._lastIO = currIO
|
|
||||||
if currDiff > self._maxIODiff:
|
|
||||||
self._maxIODiff = currDiff
|
|
||||||
if self._maxIODiff <= 0:
|
|
||||||
self._maxIODiff = 0
|
|
||||||
return 0.0
|
|
||||||
currAct = (float(currDiff) / float(self._maxIODiff)) * 100.0
|
|
||||||
self._maxIODiff -= 1 # So spikes won't affect us too much.
|
|
||||||
return currAct
|
|
||||||
|
|
||||||
def updateHdActivity(self):
|
|
||||||
currentAct = self.getHdActivity()
|
|
||||||
self.paintGraph(currentAct, 3, height - yOffset*2 - 3 - graphHeight,
|
|
||||||
width - 2 * xOffset - 6)
|
|
||||||
|
|
||||||
def _checkEvents(self):
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
while event is not None:
|
|
||||||
if event['type'] == 'destroynotify':
|
|
||||||
sys.exit(0)
|
|
||||||
elif event['type'] == 'buttonrelease':
|
|
||||||
area = wmdocklib.checkMouseRegion(event['x'],event['y'])
|
|
||||||
if area is not -1:
|
|
||||||
self.toggleMount(area-1+self._skipping)
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
|
|
||||||
def toggleMount(self, line):
|
|
||||||
label, path, mode, action = self._pathsToMonitor[line]
|
|
||||||
if action is None:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
self.getHdInfo(path)
|
|
||||||
mounted = True
|
|
||||||
except NotMounted:
|
|
||||||
mounted = False
|
|
||||||
except OSError, e:
|
|
||||||
return
|
|
||||||
if mounted:
|
|
||||||
if action == 'mount':
|
|
||||||
os.spawnvp(os.P_NOWAIT, 'umount', ['umount', path])
|
|
||||||
elif action == 'eject':
|
|
||||||
os.spawnvp(os.P_WAIT, 'umount', ['umount', path])
|
|
||||||
os.spawnvp(os.P_NOWAIT, 'eject', ['eject', path])
|
|
||||||
else:
|
|
||||||
os.spawnvp(os.P_NOWAIT, 'mount', ['mount', path])
|
|
||||||
|
|
||||||
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 == self._lineCount:
|
|
||||||
break
|
|
||||||
|
|
||||||
def mainLoop(self):
|
|
||||||
self.updateMonitoredPaths()
|
|
||||||
while 1:
|
|
||||||
self._checkEvents()
|
|
||||||
if self._actMonEnabled:
|
|
||||||
self.updateHdActivity()
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
|
|
||||||
import signal
|
|
||||||
def handler(num, frame):
|
|
||||||
hdmon.updateMonitoredPaths()
|
|
||||||
signal.alarm(10)
|
|
||||||
|
|
||||||
def parseCommandLine(argv):
|
|
||||||
"""Parse the commandline. Return a dictionary with options and values."""
|
|
||||||
shorts = 'ht:f:g:b:r:c:p:s:F:'
|
|
||||||
longs = ['help', 'textcolor=', 'background=', 'barfgcolor=',
|
|
||||||
'rgbfile=', 'configfile=', 'barbgcolor=', 'procstat=',
|
|
||||||
'skipconf=','font=', 'debug']
|
|
||||||
try:
|
|
||||||
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
|
|
||||||
except getopt.GetoptError, e:
|
|
||||||
sys.stderr.write('Error when parsing commandline: ' + str(e) + '\n')
|
|
||||||
sys.stderr.write(usage)
|
|
||||||
sys.exit(2)
|
|
||||||
d = {}
|
|
||||||
for o, a in opts:
|
|
||||||
if o in ('-h', '--help'):
|
|
||||||
sys.stdout.write(usage)
|
|
||||||
sys.exit(0)
|
|
||||||
if o in ('-t', '--textcolor'):
|
|
||||||
d['textcolor'] = a
|
|
||||||
if o in ('-b', '--background'):
|
|
||||||
d['background'] = a
|
|
||||||
if o in ('-r', '--rgbfile'):
|
|
||||||
d['rgbfile'] = a
|
|
||||||
if o in ('-c', '--configfile'):
|
|
||||||
d['configfile'] = a
|
|
||||||
if o in ('-g', '--barbgcolor'):
|
|
||||||
d['barbgcolor'] = a
|
|
||||||
if o in ('-F', '--font'):
|
|
||||||
d['font'] = a
|
|
||||||
if o in ('-f', '--barfgcolor'):
|
|
||||||
d['barfgcolor'] = a
|
|
||||||
if o in ('-p', '--procstat'):
|
|
||||||
d['procstat'] = a
|
|
||||||
if o in ('-s', '--skipconf'):
|
|
||||||
d['skipconf'] = a
|
|
||||||
if o in ('--debug'):
|
|
||||||
d['debug'] = True
|
|
||||||
return d
|
|
||||||
|
|
||||||
def makeNumDigits(num, numDigits):
|
|
||||||
"""Make a floating point number a certain number of digits, including
|
|
||||||
decimal. Return a string containing it.
|
|
||||||
"""
|
|
||||||
lenOfIntPart = len(str(int(num)))
|
|
||||||
if lenOfIntPart > numDigits:
|
|
||||||
# Can't convert a number to less digits then it's integer part...
|
|
||||||
return ''
|
|
||||||
decimalsNeeded = numDigits - lenOfIntPart
|
|
||||||
s = '%' + str(lenOfIntPart) + '.' + str(decimalsNeeded) + 'f'
|
|
||||||
s = s % round(num, decimalsNeeded)
|
|
||||||
return s
|
|
||||||
|
|
||||||
def bytesToStr(bytes):
|
|
||||||
"""Convert a number of bytes to a nice printable string.
|
|
||||||
|
|
||||||
May raise ValueError if bytes can't be seen as an float.
|
|
||||||
"""
|
|
||||||
bytes = float(bytes)
|
|
||||||
kb = 1024
|
|
||||||
mb = 1024 * 1024
|
|
||||||
gb = 1024 * mb
|
|
||||||
tb = 1024 * gb
|
|
||||||
pb = 1024 * tb
|
|
||||||
if bytes < kb:
|
|
||||||
size = bytes
|
|
||||||
letter = 'B'
|
|
||||||
#return makeNumDigits(bytes, numDigits) + 'B'
|
|
||||||
elif bytes < mb:
|
|
||||||
size = bytes / kb
|
|
||||||
letter = 'k'
|
|
||||||
#return makeNumDigits(bytes/kb, numDigits) + 'k'
|
|
||||||
elif bytes < gb:
|
|
||||||
size = bytes / mb
|
|
||||||
letter = 'M'
|
|
||||||
#return makeNumDigits(bytes/mb, numDigits) + 'M'
|
|
||||||
elif bytes < tb:
|
|
||||||
size = bytes / gb
|
|
||||||
letter = 'G'
|
|
||||||
#return makeNumDigits(bytes/gb, numDigits) + 'G'
|
|
||||||
elif bytes < pb:
|
|
||||||
size = bytes / tb
|
|
||||||
letter = 'T'
|
|
||||||
#return makeNumDigits(bytes/tb, numDigits) + 'T'
|
|
||||||
else:
|
|
||||||
size = bytes / pb
|
|
||||||
letter = 'p'
|
|
||||||
#return makeNumDigits(bytes/pb, numDigits) + 'P'
|
|
||||||
if size >= 1000:
|
|
||||||
res = makeNumDigits(size, 4)
|
|
||||||
else:
|
|
||||||
res = makeNumDigits(size, 3)
|
|
||||||
res += letter
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
clConfig = parseCommandLine(sys.argv)
|
|
||||||
configFile = clConfig.get('configfile', defaultConfigFile)
|
|
||||||
configFile = os.path.expanduser(configFile)
|
|
||||||
fileConfig = wmdocklib.readConfigFile(configFile, sys.stderr)
|
|
||||||
config = fileConfig
|
|
||||||
for i in clConfig.iteritems():
|
|
||||||
config[i[0]] = i[1]
|
|
||||||
|
|
||||||
palette = {}
|
|
||||||
palette[0] = clConfig.get('background', 'black')
|
|
||||||
palette[2] = clConfig.get('textcolor', 'cyan3')
|
|
||||||
palette[9] = clConfig.get('barfgcolor', 'cyan')
|
|
||||||
palette[8] = clConfig.get('barbgcolor', 'cyan4')
|
|
||||||
palette[5] = clConfig.get('activitycolor', 'cyan2')
|
|
||||||
|
|
||||||
font = clConfig.get('font', '6x8')
|
|
||||||
debug = clConfig.get('debug')
|
|
||||||
|
|
||||||
global char_width, char_height
|
|
||||||
char_width, char_height = wmdocklib.initPixmap(patterns=patterns,
|
|
||||||
font_name=font,
|
|
||||||
palette=palette,
|
|
||||||
margin=3,
|
|
||||||
bg=0, fg=2, debug=debug)
|
|
||||||
|
|
||||||
pathsToMonitor = []
|
|
||||||
for i in range(1,1000):
|
|
||||||
labelStr = str(i) + '.label'
|
|
||||||
pathStr = str(i) + '.path'
|
|
||||||
modeStr = str(i) + '.displaymode'
|
|
||||||
actionStr = str(i) + '.action'
|
|
||||||
label = config.get(labelStr)
|
|
||||||
if not label: break
|
|
||||||
path = config.get(pathStr)
|
|
||||||
action = config.get(actionStr, 'fixed').lower().strip()
|
|
||||||
if action not in ['mount', 'eject']:
|
|
||||||
action = None
|
|
||||||
displayMode = config.get(modeStr, defaultMode)
|
|
||||||
if not displayMode in displayModes:
|
|
||||||
sys.stderr.write(
|
|
||||||
'Unknown display mode: %s, using default.\n' % displayMode)
|
|
||||||
displayMode = defaultMode
|
|
||||||
takeChars = 3
|
|
||||||
if char_width <= 5:
|
|
||||||
takeChars = 4
|
|
||||||
pathsToMonitor.append((label[:takeChars], path, displayMode, action))
|
|
||||||
procStat = config.get('procstat', defaultProcStat)
|
|
||||||
skipping = int(config.get('skipconf', 0))
|
|
||||||
actMonEnabled = int(config.get('monitoring',0))
|
|
||||||
if not os.access(procStat, os.R_OK):
|
|
||||||
sys.stderr.write(
|
|
||||||
"Can't read your procstat file, try setting it with -p. ")
|
|
||||||
sys.stderr.write("Disabling the HD activity bar.\n")
|
|
||||||
actMonEnabled = 0
|
|
||||||
try:
|
|
||||||
programName = sys.argv[0].split(os.sep)[-1]
|
|
||||||
except IndexError:
|
|
||||||
programName = ''
|
|
||||||
sys.argv[0] = programName
|
|
||||||
wmdocklib.openXwindow(sys.argv, width, height)
|
|
||||||
|
|
||||||
signal.signal(signal.SIGCHLD, handler)
|
|
||||||
signal.signal(signal.SIGALRM, handler)
|
|
||||||
signal.alarm(10)
|
|
||||||
|
|
||||||
global hdmon
|
|
||||||
hdmon = PywmHDMon(pathsToMonitor, procStat, actMonEnabled, skipping)
|
|
||||||
hdmon.mainLoop()
|
|
||||||
|
|
||||||
patterns = \
|
|
||||||
['0000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900555002220055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555002220055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555002220055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550022200555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550022200555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550022200555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500555000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500222000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500222000000000000000000000000000000000000000',
|
|
||||||
'0099900555005550055500222000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099900088888888888888888888888888888888888888888888888888888888',
|
|
||||||
'0099900088888888888888888888888888888888888888888888888888888888',
|
|
||||||
'0099900088888888888888888888888888888888888888888888888888888888',
|
|
||||||
'0099900088888888888888888888888888888888888888888888888888888888',
|
|
||||||
'0099900000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0099999999999999999999999999999999999999999999999999999999999999',
|
|
||||||
'0099999999999999999999999999999999999999999999999999999999999999',
|
|
||||||
'0099999999999999999999999999999999999999999999999999999999999999',
|
|
||||||
'0099999999999999999999999999999999999999999999999999999999999999',
|
|
||||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
||||||
]
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmnop.py
|
|
||||||
|
|
||||||
WindowMaker dockapp doing nothing
|
|
||||||
|
|
||||||
Copyright (C) 2006 Mario Frasca
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys, time
|
|
||||||
import wmdocklib
|
|
||||||
|
|
||||||
def checkForEvents():
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
while not event is None:
|
|
||||||
if event['type'] == 'destroynotify':
|
|
||||||
sys.exit(0)
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
|
|
||||||
def mainLoop():
|
|
||||||
while 1:
|
|
||||||
checkForEvents()
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
wmdocklib.initPixmap()
|
|
||||||
wmdocklib.openXwindow(sys.argv, 64, 64)
|
|
||||||
|
|
||||||
mainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmoonop.py
|
|
||||||
|
|
||||||
object oriented WindowMaker dockapp doing nothing
|
|
||||||
|
|
||||||
Copyright (C) 2007 Mario Frasca
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from wmdocklib import wmoo
|
|
||||||
thisapp = wmoo.Application()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
thisapp.run()
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmphoto.py
|
|
||||||
|
|
||||||
WindowMaker dockapp that displays a static xpm
|
|
||||||
|
|
||||||
Copyright (C) 2006-2007 Mario Frasca
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
2006-10-27 Mario Frasca
|
|
||||||
First workingish version
|
|
||||||
|
|
||||||
2007-05-19 Mario Frasca
|
|
||||||
more compact form, based on wmdocklib.wmoo and optparse.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from wmdocklib import wmoo
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser()
|
|
||||||
parser.add_option("-f", "--file", dest="filename",
|
|
||||||
help="read background from file", metavar="FILE")
|
|
||||||
parser.add_option("-d", "--debug", dest="debug",
|
|
||||||
action="store_true", default=False,
|
|
||||||
help="print the pixmap")
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
app = wmoo.Application(background = options.filename,
|
|
||||||
margin = 3,
|
|
||||||
debug = options.debug)
|
|
||||||
|
|
||||||
app.run()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmnop.py
|
|
||||||
|
|
||||||
WindowMaker dockapp doing nothing
|
|
||||||
|
|
||||||
Copyright (C) 2006 Mario Frasca
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys, time
|
|
||||||
from wmdocklib import wmoo
|
|
||||||
devnull = file('/dev/null')
|
|
||||||
|
|
||||||
class Application(wmoo.Application):
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self._cacheLevel = -50
|
|
||||||
self.child = None
|
|
||||||
self._paused = None
|
|
||||||
self._buffering = 0
|
|
||||||
self._flash = 0
|
|
||||||
self._muting = 0
|
|
||||||
if 'pause' in self._widgets:
|
|
||||||
self['pause'].setPattern((11, 10))
|
|
||||||
self.showCacheLevel()
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
wmoo.Application.__init__(self, *args, **kwargs)
|
|
||||||
self.radioList = []
|
|
||||||
self.currentRadio = 0
|
|
||||||
self._count = 0
|
|
||||||
self._expectdying = 0
|
|
||||||
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
self._buffered = ''
|
|
||||||
import re
|
|
||||||
self._feedback = re.compile(r'.+A:.*?% ([0-9\.]+)%')
|
|
||||||
|
|
||||||
import fileinput, os
|
|
||||||
configfile = os.sep.join([os.environ['HOME'], '.pyradiorc'])
|
|
||||||
|
|
||||||
import codecs
|
|
||||||
f = codecs.open(configfile, 'r', 'utf-8')
|
|
||||||
t = f.read()
|
|
||||||
f.close()
|
|
||||||
for i in t.split(u'\n'):
|
|
||||||
radiodef = i.split('\t')
|
|
||||||
radioname = radiodef[0].lower()
|
|
||||||
if len(radiodef) != 3 or i[0] == '#':
|
|
||||||
continue
|
|
||||||
if radioname == '':
|
|
||||||
globals()[radiodef[1]] = radiodef[2]
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.radioList.append( (radioname, radiodef[1], radiodef[2]) )
|
|
||||||
|
|
||||||
|
|
||||||
def handler(self, num, frame):
|
|
||||||
if self._expectdying:
|
|
||||||
self._expectdying -= 1
|
|
||||||
else:
|
|
||||||
self.reset()
|
|
||||||
self._flash = 4
|
|
||||||
self._colour = 1
|
|
||||||
|
|
||||||
def startPlayer(self):
|
|
||||||
import os, subprocess, signal
|
|
||||||
commandline = [mplayer,
|
|
||||||
'-cache', self.radioList[self.currentRadio][2],
|
|
||||||
self.radioList[self.currentRadio][1]
|
|
||||||
]
|
|
||||||
self.child = subprocess.Popen(commandline,
|
|
||||||
stdin =subprocess.PIPE,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=devnull)
|
|
||||||
signal.signal(signal.SIGCHLD, self.handler)
|
|
||||||
self._flash = 0
|
|
||||||
self._paused = False
|
|
||||||
self._buffered = ''
|
|
||||||
self._buffering = 1
|
|
||||||
self._cacheLevel = 0
|
|
||||||
import fcntl
|
|
||||||
flags = fcntl.fcntl(self.child.stdout, fcntl.F_GETFL)
|
|
||||||
fcntl.fcntl(self.child.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
flags = fcntl.fcntl(self.child.stdin, fcntl.F_GETFL)
|
|
||||||
fcntl.fcntl(self.child.stdin, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
|
|
||||||
def stopPlayer(self):
|
|
||||||
if self.child:
|
|
||||||
self.child.stdin.write('q')
|
|
||||||
self._expectdying += 1
|
|
||||||
self.child = None
|
|
||||||
|
|
||||||
def printevent(self, event):
|
|
||||||
print event
|
|
||||||
|
|
||||||
def previousRadio(self, event):
|
|
||||||
#print 'in previousRadio'
|
|
||||||
if self.currentRadio == 0: self.currentRadio = len(self.radioList)
|
|
||||||
self.currentRadio -= 1
|
|
||||||
self['name'].setText(self.radioList[self.currentRadio][0])
|
|
||||||
if self.child:
|
|
||||||
self.stopPlayer()
|
|
||||||
self.startPlayer()
|
|
||||||
|
|
||||||
def nextRadio(self, event):
|
|
||||||
#print 'in nextRadio'
|
|
||||||
self.currentRadio += 1
|
|
||||||
if self.currentRadio == len(self.radioList): self.currentRadio = 0
|
|
||||||
self['name'].setText(self.radioList[self.currentRadio][0])
|
|
||||||
if self.child:
|
|
||||||
self.stopPlayer()
|
|
||||||
self.startPlayer()
|
|
||||||
|
|
||||||
def playStream(self, event):
|
|
||||||
#print 'in playStream'
|
|
||||||
self.startPlayer()
|
|
||||||
|
|
||||||
def stopStream(self, event):
|
|
||||||
#print 'in stopStream'
|
|
||||||
self.stopPlayer()
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def pauseStream(self, event):
|
|
||||||
#print 'in pauseStream'
|
|
||||||
if self.child and not self._buffering:
|
|
||||||
self.child.stdin.write(' ')
|
|
||||||
self._paused = not self._paused
|
|
||||||
if self._paused:
|
|
||||||
self._colour = 1
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def muteStream(self, event):
|
|
||||||
#print 'in muteStream'
|
|
||||||
if self.child and self._buffering == 0:
|
|
||||||
self.child.stdin.write('m')
|
|
||||||
self['mute'].setPattern((33-11*self._muting, 0))
|
|
||||||
self._muting = 1 - self._muting
|
|
||||||
|
|
||||||
def showCacheLevel(self):
|
|
||||||
if self._buffering:
|
|
||||||
self._cacheLevel += 1
|
|
||||||
if self._cacheLevel >= 25:
|
|
||||||
self._cacheLevel -= 25
|
|
||||||
for i in range(-1, 25):
|
|
||||||
if abs(i - self._cacheLevel) <= 1:
|
|
||||||
self.putPattern(54, self._buffering, 5, 1, 54, 58-i)
|
|
||||||
else:
|
|
||||||
self.putPattern(54, 0, 5, 1, 54, 58-i)
|
|
||||||
else:
|
|
||||||
if self._flash:
|
|
||||||
colour = self._colour = 3 - self._colour
|
|
||||||
self._flash = max(0, self._flash - 1)
|
|
||||||
else:
|
|
||||||
colour = 2
|
|
||||||
for i in range(-1, 25):
|
|
||||||
if (i*4 < self._cacheLevel) or self._flash:
|
|
||||||
self.putPattern(54, colour, 5, 1, 54, 58-i)
|
|
||||||
else:
|
|
||||||
self.putPattern(54, 0, 5, 1, 54, 58-i)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self._count += 1
|
|
||||||
if self._count <= 3:
|
|
||||||
return
|
|
||||||
if self._paused:
|
|
||||||
colour = self._colour = 4 - self._colour
|
|
||||||
self['pause'].setPattern((self._colour*11, 10))
|
|
||||||
self._count = 0
|
|
||||||
if self.child:
|
|
||||||
import select
|
|
||||||
[i, o, e] = select.select([self.child.stdout], [], [], 0)
|
|
||||||
if i:
|
|
||||||
line = self.child.stdout.read(102400)
|
|
||||||
self._buffered += line
|
|
||||||
npos = self._buffered.rfind('\n')+1
|
|
||||||
rpos = self._buffered.rfind('\r')+1
|
|
||||||
if npos != 0:
|
|
||||||
self._buffered = self._buffered[npos:]
|
|
||||||
if rpos != 0:
|
|
||||||
if self._buffered.startswith('Cache fill:'):
|
|
||||||
self._buffering = 2
|
|
||||||
else:
|
|
||||||
match = self._feedback.match(self._buffered[rpos-90:rpos])
|
|
||||||
if match:
|
|
||||||
self._buffering = 0
|
|
||||||
self._cacheLevel = float(match.group(1))
|
|
||||||
|
|
||||||
self._buffered = self._buffered[rpos:]
|
|
||||||
if self.child or self._flash:
|
|
||||||
self.showCacheLevel()
|
|
||||||
|
|
||||||
palette = {
|
|
||||||
'-': "#000000",
|
|
||||||
".": "#868682",
|
|
||||||
"X": "#AEAEAA",
|
|
||||||
"o": "#F7F7F3",
|
|
||||||
"r": "#F73020",
|
|
||||||
"i": "#00F700",
|
|
||||||
}
|
|
||||||
|
|
||||||
background = [
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" X----------------------------------------------------------X ",
|
|
||||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ......... ......... ......... XXXXXX. ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" X----- ",
|
|
||||||
" X----- ",
|
|
||||||
" X----- ",
|
|
||||||
" X----- ",
|
|
||||||
" X.-----.. ",
|
|
||||||
" X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" ......... ......... ......... X----- ",
|
|
||||||
" X----- ",
|
|
||||||
" .----- ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
]
|
|
||||||
|
|
||||||
patterns = [
|
|
||||||
"XXXXXXXXX XXXXXXXXX XXXXXXXXX XXXXXXXXX ----- ",
|
|
||||||
"X-------- X-------- X-------- X-------- rrrrr ",
|
|
||||||
"X-o------ X-----o-- X-----o-- X----rr-- iiiii ",
|
|
||||||
"X-o--oo-- X-oo--o-- X----oo-- X----rr-- ",
|
|
||||||
"X-o-ooo-- X-ooo-o-- X-ooXoo-- X-oorro-- ",
|
|
||||||
"X-ooooo-- X-ooooo-- X-ooXoo-- X-ooroo-- ",
|
|
||||||
"X-o-ooo-- X-ooo-o-- X-ooXoo-- X-orroo-- ",
|
|
||||||
"X-o--oo-- X-oo--o-- X----oo-- X-rr-oo-- ",
|
|
||||||
"X-o------ X-----o-- X-----o-- X-rr--o-- ",
|
|
||||||
"X-------- X-------- X-------- X-------- ",
|
|
||||||
"XXXXXXXXX XXXXXXXXX XXXXXXXXX XXXXXXXXX ",
|
|
||||||
"X-------- X-------- X-------- X-------- ",
|
|
||||||
"X-------- X-------- X-------- X-------- ",
|
|
||||||
"X-oo----- X-oo-oo-- X-ooooo-- X-rr-rr-- ",
|
|
||||||
"X-oooo--- X-oo-oo-- X-ooooo-- X-rr-rr-- ",
|
|
||||||
"X-ooooo-- X-oo-oo-- X-ooooo-- X-rr-rr-- ",
|
|
||||||
"X-oooo--- X-oo-oo-- X-ooooo-- X-rr-rr-- ",
|
|
||||||
"X-oo----- X-oo-oo-- X-ooooo-- X-rr-rr-- ",
|
|
||||||
"X-------- X-------- X-------- X-------- ",
|
|
||||||
"X-------- X-------- X-------- X-------- ",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
global char_width, char_height, maxCharsPerLine, antialiased
|
|
||||||
app = Application(font_name='5x8',
|
|
||||||
margin = 3,
|
|
||||||
bg=0, fg=2, palette = palette,
|
|
||||||
background = background,
|
|
||||||
patterns = patterns)
|
|
||||||
# maxCharsPerLine = (width-2*xOffset) / char width
|
|
||||||
app.addWidget('name', wmoo.Label,
|
|
||||||
(5, 16), (54, 10), app.radioList[app.currentRadio][0])
|
|
||||||
|
|
||||||
app.addWidget('prev', wmoo.Button, ( 6,31), (9, 10), app.previousRadio, pattern=(0,0))
|
|
||||||
app.addWidget('next', wmoo.Button, (21,31), (9, 10), app.nextRadio, pattern=(11,0))
|
|
||||||
app.addWidget('mute', wmoo.Button, (36,31), (9, 10), app.muteStream, pattern=(22,0))
|
|
||||||
|
|
||||||
app.addWidget('play', wmoo.Button, ( 6,47), (9, 10), app.playStream, pattern=(0,10))
|
|
||||||
app.addWidget('pause',wmoo.Button, (21,47), (9, 10), app.pauseStream, pattern=(11,10))
|
|
||||||
app.addWidget('stop', wmoo.Button, (36,47), (9, 10), app.stopStream, pattern=(22,10))
|
|
||||||
|
|
||||||
app.addCallback(app.previousRadio, 'keypress', key='k')
|
|
||||||
app.addCallback(app.nextRadio, 'keypress', key='j')
|
|
||||||
app.addCallback(app.muteStream, 'keypress', key='m')
|
|
||||||
app.addCallback(app.playStream, 'keypress', key='p')
|
|
||||||
app.addCallback(app.pauseStream, 'keypress', key=' ')
|
|
||||||
app.addCallback(app.stopStream, 'keypress', key='q')
|
|
||||||
|
|
||||||
app.run()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,502 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmseti.py
|
|
||||||
|
|
||||||
WindowMaker dockapp to monitor the progress of your seti@home.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Kristoffer Erlandsson
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Changes
|
|
||||||
|
|
||||||
2003-06-24 Kristoffer Erlandsson
|
|
||||||
Added event handling for graceful shutdown
|
|
||||||
|
|
||||||
2003-06-17 Kristoffer Erlandsson
|
|
||||||
First workingish version
|
|
||||||
|
|
||||||
"""
|
|
||||||
usage = """pywmseti.py [options]
|
|
||||||
Available options are:
|
|
||||||
-h, --help print this help
|
|
||||||
-t, --textcolor <color> set the text color
|
|
||||||
-p, --progressbarcolor <color> set the color of the progress bar
|
|
||||||
-g, --barbgcolor <color> set the background color of the progress bar
|
|
||||||
-i, --indicatorcolor <color> set the color of the running indicator
|
|
||||||
-b, --background <color> set the background color
|
|
||||||
-d, --setidir <directory> set the directory where seti@home resides
|
|
||||||
-n, --nice <value> set the nice value to run seti@home with
|
|
||||||
-r, --rgbfile <file> set the rgb file to get color codes from
|
|
||||||
-c, --configfile <file> set the config file to use
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import getopt
|
|
||||||
import os
|
|
||||||
|
|
||||||
import wmdocklib
|
|
||||||
|
|
||||||
width = 64
|
|
||||||
height = 64
|
|
||||||
|
|
||||||
xOffset = 4
|
|
||||||
yOffset = 4
|
|
||||||
|
|
||||||
graphStartX = 7
|
|
||||||
graphStartY = 53
|
|
||||||
graphLength = 50
|
|
||||||
graphHeight = 4
|
|
||||||
|
|
||||||
graphBgStartX = 72
|
|
||||||
graphBgStartY = 53
|
|
||||||
|
|
||||||
graphLineStartX = 66
|
|
||||||
graphLineStartY = 58
|
|
||||||
|
|
||||||
runningIndX = 71
|
|
||||||
runningIndY = 1
|
|
||||||
runningIndWidth = 3
|
|
||||||
runningIndHeight = 15
|
|
||||||
numRunningInds = 4
|
|
||||||
|
|
||||||
defaultConfigFile = '~/.pywmsetirc'
|
|
||||||
defaultRGBFiles = ['/usr/lib/X11/rgb.txt', '/usr/X11R6/lib/X11/rgb.txt']
|
|
||||||
|
|
||||||
stateFileName = 'state.sah'
|
|
||||||
uinfoFileName = 'user_info.sah'
|
|
||||||
pidFileName = 'pid.sah'
|
|
||||||
execFileName = 'setiathome'
|
|
||||||
|
|
||||||
class PywmSeti:
|
|
||||||
def __init__(self, statePath, uinfoPath, pidPath, execCmd):
|
|
||||||
self._statePath = statePath
|
|
||||||
self._uinfoPath = uinfoPath
|
|
||||||
self._pidPath = pidPath
|
|
||||||
self._execCmd = execCmd
|
|
||||||
self._currentRunningInd = 0
|
|
||||||
self._lastTime = time.time()
|
|
||||||
self._lastNumResults = -1
|
|
||||||
self._progress = 0
|
|
||||||
|
|
||||||
def addString(self, s, x, y):
|
|
||||||
try:
|
|
||||||
wmdocklib.addString(s, x, y, digits,
|
|
||||||
xOffset, yOffset, width, height)
|
|
||||||
except ValueError, e:
|
|
||||||
sys.stderr.write('Error when painting string:\n' + str(e) + '\n')
|
|
||||||
sys.exit(3)
|
|
||||||
|
|
||||||
def getCenterStartPos(self, s):
|
|
||||||
return wmdocklib.getCenterStartPos(s, width, xOffset)
|
|
||||||
|
|
||||||
def getVertSpacing(self, numLines, margin):
|
|
||||||
return wmdocklib.getVertSpacing(numLines, margin, height, yOffset)
|
|
||||||
|
|
||||||
def getProgress(self, lines):
|
|
||||||
"""Return the progess of the current workunit.
|
|
||||||
|
|
||||||
Supply the lines of the statefile as argument.
|
|
||||||
"""
|
|
||||||
for line in lines:
|
|
||||||
if line.startswith('prog='):
|
|
||||||
try:
|
|
||||||
progress = float(line.split('=')[-1])
|
|
||||||
except ValueError:
|
|
||||||
progress = 0
|
|
||||||
return progress
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def getNumResults(self, lines):
|
|
||||||
"""Return the number of results produced.
|
|
||||||
|
|
||||||
Supply the lines in the user info file as argument.
|
|
||||||
"""
|
|
||||||
for line in lines:
|
|
||||||
if line.startswith('nresults='):
|
|
||||||
try:
|
|
||||||
results = int(line.split('=')[-1])
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
return results
|
|
||||||
sys.stderr.write(
|
|
||||||
"Error when reading uinfo file! Can't get number of results.\n")
|
|
||||||
return -1
|
|
||||||
|
|
||||||
def pidIsRunning(self, pid):
|
|
||||||
"""Determine if the process with PID pid is running.
|
|
||||||
|
|
||||||
Return 1 if it is running.
|
|
||||||
Return 0 if it is not running.
|
|
||||||
Return -1 if we do not have permission to signal the process
|
|
||||||
This could be slightly non-portal, but I can not find any better
|
|
||||||
way to do it.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
os.kill(pid, 0)
|
|
||||||
except OSError, e:
|
|
||||||
if e.errno == 1:
|
|
||||||
return -1
|
|
||||||
return 0
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def openFileRead(self, fileName):
|
|
||||||
try:
|
|
||||||
f = file(fileName, 'r')
|
|
||||||
except IOError, e:
|
|
||||||
sys.stderr.write('Error when opening %s: %s\n' % (fileName, str(e)))
|
|
||||||
return None
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
def paintCurrentRunningIndicator(self):
|
|
||||||
"""Paint the running indicator.
|
|
||||||
"""
|
|
||||||
indX = runningIndX + self._currentRunningInd * \
|
|
||||||
(runningIndWidth + 2)
|
|
||||||
indY = runningIndY
|
|
||||||
w = runningIndWidth
|
|
||||||
h = runningIndHeight
|
|
||||||
targX = width - xOffset - w - 5
|
|
||||||
targY = yOffset + 5
|
|
||||||
wmdocklib.copyXPMArea(indX, indY, w, h, targX, targY)
|
|
||||||
|
|
||||||
def updateRunning(self):
|
|
||||||
"""Update the information regarding if we got seti@home running or not.
|
|
||||||
|
|
||||||
Return a tuple with (running, startStopenabled).
|
|
||||||
startStopEnabled is 1 if we own the process and got the permissions
|
|
||||||
to start and stop it, or if there is no process running.
|
|
||||||
"""
|
|
||||||
pidFile = self.openFileRead(self._pidPath)
|
|
||||||
if pidFile is None:
|
|
||||||
sys.stderr.write("Can't read pid file")
|
|
||||||
self._running = 0
|
|
||||||
self._startStopEnabled = 0
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
self._pid = int(pidFile.read().strip())
|
|
||||||
except ValueError:
|
|
||||||
sys.stderr.write("Can't get pid from %s.\n" % self._pidPath)
|
|
||||||
self._running = 0
|
|
||||||
self._startStopEnabled = 0
|
|
||||||
return
|
|
||||||
pidFile.close()
|
|
||||||
self._running = self.pidIsRunning(self._pid)
|
|
||||||
if self._running == -1 and self._startStopEnabled:
|
|
||||||
sys.stderr.write(
|
|
||||||
"An other seti@home process which you don't own is running.\n")
|
|
||||||
sys.stderr.write(
|
|
||||||
"Starting and stopping of the process is disabled.\n")
|
|
||||||
self._startStopenabled = 0
|
|
||||||
if self._running == -1:
|
|
||||||
self._running = 1
|
|
||||||
else:
|
|
||||||
# If no process is running (we could have stopped the one
|
|
||||||
# running from an other process), enable starting and stopping.
|
|
||||||
self._startStopEnabled = 1
|
|
||||||
if self._running:
|
|
||||||
self._currentRunningInd = (self._currentRunningInd - 1) \
|
|
||||||
% numRunningInds
|
|
||||||
else:
|
|
||||||
self._currentRunningInd = 0
|
|
||||||
self.paintCurrentRunningIndicator()
|
|
||||||
|
|
||||||
def updateProgress(self):
|
|
||||||
"""Update the progress on the current workunit."""
|
|
||||||
stateFile = self.openFileRead(self._statePath)
|
|
||||||
if stateFile is None:
|
|
||||||
# Can't open file, probably in progress of gettin a new workunit.
|
|
||||||
progress = 0
|
|
||||||
else:
|
|
||||||
progress = self.getProgress(stateFile.readlines())
|
|
||||||
stateFile.close()
|
|
||||||
self._progress = progress
|
|
||||||
percent = int(progress * 100.0)
|
|
||||||
graphSize = int(round(progress * graphLength))
|
|
||||||
wmdocklib.copyXPMArea(
|
|
||||||
graphLineStartX, graphLineStartY, graphSize, graphHeight,
|
|
||||||
graphStartX, graphStartY)
|
|
||||||
wmdocklib.copyXPMArea(
|
|
||||||
graphBgStartX, graphBgStartY, graphLength - graphSize, graphHeight,
|
|
||||||
graphStartX + graphSize, graphStartY)
|
|
||||||
self.addString((str(percent) + '%').ljust(4), 4, 32)
|
|
||||||
|
|
||||||
def updateNumResults(self):
|
|
||||||
"""Update the number of workunits done."""
|
|
||||||
uinfoFile = self.openFileRead(self._uinfoPath)
|
|
||||||
numResults = self.getNumResults(uinfoFile.readlines())
|
|
||||||
if self._lastNumResults == -1:
|
|
||||||
self._lastNumResults = numResults
|
|
||||||
if numResults != self._lastNumResults and self._progress < 0.03:
|
|
||||||
# If we just got a new number of results and the progress of the
|
|
||||||
# current workunit is under 3%, assume we started working on a new
|
|
||||||
# workunit. The times this could be missleading is if we have an
|
|
||||||
# other seti@home process running on an other computer, but this is
|
|
||||||
# accurate enough I think.
|
|
||||||
self.nextWorkUnitStarted()
|
|
||||||
self._lastNumResults = numResults
|
|
||||||
uinfoFile.close()
|
|
||||||
self.addString(str(numResults)[:7], 4, 4)
|
|
||||||
|
|
||||||
def updateTime(self):
|
|
||||||
"""Update the time line.
|
|
||||||
|
|
||||||
We display the time that we have been on the current work unit, since
|
|
||||||
either the last one was done or since we started the program.
|
|
||||||
"""
|
|
||||||
timeSpent = time.time() - self._lastTime
|
|
||||||
hours = int(timeSpent / 3600)
|
|
||||||
mins = int((timeSpent - hours * 3600) / 60)
|
|
||||||
hours = str(hours)[:3]
|
|
||||||
mins = str(mins).zfill(2)
|
|
||||||
s = (hours + ':' + mins).ljust(6)
|
|
||||||
self.addString(s, 4, 18)
|
|
||||||
|
|
||||||
def nextWorkUnitStarted(self):
|
|
||||||
self._lastTime = time.time()
|
|
||||||
|
|
||||||
def handleMouseClick(self, region):
|
|
||||||
if region == 0:
|
|
||||||
if self._startStopEnabled:
|
|
||||||
if self._running:
|
|
||||||
try:
|
|
||||||
os.kill(self._pid, 15)
|
|
||||||
except OSError, e:
|
|
||||||
sys.stderr.write(
|
|
||||||
"Error when ending process: "+str(e)+'\n')
|
|
||||||
else:
|
|
||||||
os.system(self._execCmd) # Use fork instead?
|
|
||||||
|
|
||||||
def _checkForEvents(self):
|
|
||||||
"""Check for, and handle, X events."""
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
while not event is None:
|
|
||||||
if event['type'] == 'buttonrelease':
|
|
||||||
region = wmdocklib.checkMouseRegion(event['x'],
|
|
||||||
event['y'])
|
|
||||||
self.handleMouseClick(region)
|
|
||||||
elif event['type'] == 'destroynotify':
|
|
||||||
sys.exit(0)
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
|
|
||||||
def mainLoop(self):
|
|
||||||
counter = -1
|
|
||||||
self._startStopEnabled = 1
|
|
||||||
while 1:
|
|
||||||
counter += 1
|
|
||||||
self._checkForEvents()
|
|
||||||
if counter % 10 == 0:
|
|
||||||
self.updateRunning()
|
|
||||||
if counter % 100 == 0:
|
|
||||||
self.updateProgress()
|
|
||||||
self.updateNumResults()
|
|
||||||
self.updateTime()
|
|
||||||
if counter == 999999:
|
|
||||||
counter = -1
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
|
|
||||||
def parseCommandLine(argv):
|
|
||||||
"""Parse the commandline. Return a dictionary with options and values."""
|
|
||||||
shorts = 'ht:b:n:d:r:c:p:g:i:'
|
|
||||||
longs = ['help', 'textcolor=', 'background=', 'setidir=', 'nice=',
|
|
||||||
'rgbfile=', 'configfile=', 'progressbarcolor=', 'barbgcolor=',
|
|
||||||
'indicatorcolor=']
|
|
||||||
try:
|
|
||||||
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
|
|
||||||
except getopt.GetoptError, e:
|
|
||||||
sys.stderr.write('Error when parsing commandline: ' + str(e) + '\n')
|
|
||||||
sys.stderr.write(usage)
|
|
||||||
sys.exit(2)
|
|
||||||
d = {}
|
|
||||||
for o, a in opts:
|
|
||||||
if o in ('-h', '--help'):
|
|
||||||
sys.stdout.write(usage)
|
|
||||||
sys.exit(0)
|
|
||||||
if o in ('-t', '--textcolor'):
|
|
||||||
d['textcolor'] = a
|
|
||||||
if o in ('-b', '--background'):
|
|
||||||
d['background'] = a
|
|
||||||
if o in ('-d', '--setidir'):
|
|
||||||
d['setidir'] = a
|
|
||||||
if o in ('-n', '--nice'):
|
|
||||||
d['nice'] = a
|
|
||||||
if o in ('-r', '--rgbfile'):
|
|
||||||
d['rgbfile'] = a
|
|
||||||
if o in ('-c', '--configfile'):
|
|
||||||
d['configfile'] = a
|
|
||||||
if o in ('-p', '--progressbarcolor'):
|
|
||||||
d['progressbarcolor'] = a
|
|
||||||
if o in ('-g', '--barbgcolor'):
|
|
||||||
d['barbgcolor'] = a
|
|
||||||
if o in ('-i', '--indicatorcolor'):
|
|
||||||
d['indicatorcolor'] = a
|
|
||||||
return d
|
|
||||||
|
|
||||||
def parseColors(defaultRGBFileNames, config, xpm):
|
|
||||||
rgbFileName = ''
|
|
||||||
for fn in defaultRGBFileNames:
|
|
||||||
if os.access(fn, os.R_OK):
|
|
||||||
rgbFileName = fn
|
|
||||||
break
|
|
||||||
rgbFileName = config.get('rgbfile', rgbFileName)
|
|
||||||
useColors = 1
|
|
||||||
if not os.access(rgbFileName, os.R_OK):
|
|
||||||
sys.stderr.write(
|
|
||||||
"Can't read the RGB file, try setting it differently using -r,\n")
|
|
||||||
sys.stderr.write(
|
|
||||||
"Ignoring your color settings, using the defaults.\n")
|
|
||||||
useColors = 0
|
|
||||||
if useColors:
|
|
||||||
# Colors is a list with (<config_key>, <xpm-key>) pairs.
|
|
||||||
colors = (('indicatorcolor', 'indicator'),
|
|
||||||
('progressbarcolor', 'graph'),
|
|
||||||
('barbgcolor', 'graphbg'),
|
|
||||||
('textcolor', 'text'),
|
|
||||||
('background', 'background'))
|
|
||||||
for key, value in colors:
|
|
||||||
col = config.get(key)
|
|
||||||
if not col is None:
|
|
||||||
code = wmdocklib.getColorCode(col, rgbFileName)
|
|
||||||
if code is None:
|
|
||||||
sys.stderr.write('Bad colorcode for %s, ignoring.\n' % key)
|
|
||||||
else:
|
|
||||||
wmdocklib.setColor(xpm, value, code)
|
|
||||||
|
|
||||||
palette = {
|
|
||||||
' ': '#208120812081',
|
|
||||||
'.': '#00000000FFFF',
|
|
||||||
'o': '#C71BC30BC71B',
|
|
||||||
'O': '#861782078E38',
|
|
||||||
'+': '#EFBEF3CEEFBE',
|
|
||||||
'@': '#618561856185',
|
|
||||||
'#': '#9E79A2899E79',
|
|
||||||
'$': '#410341034103',
|
|
||||||
'o': '#2020b2b2aaaa',
|
|
||||||
'/': '#2020b2b2aaaa',
|
|
||||||
'-': '#707070707070',
|
|
||||||
'_': '#000000000000',
|
|
||||||
'%': '#2081B2CAAEBA',
|
|
||||||
}
|
|
||||||
|
|
||||||
background = \
|
|
||||||
[' ...............................................................................................',
|
|
||||||
' .///..___..ooo..___..___.......................................................................',
|
|
||||||
' .///..___..ooo..___..___.......................................................................',
|
|
||||||
' .///..___..ooo..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..ooo..___.......................................................................',
|
|
||||||
' .///..___..___..ooo..___.......................................................................',
|
|
||||||
' .///..___..___..ooo..___.......................................................................',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..___.......................................................................',
|
|
||||||
' .///..___..___..___..ooo.......................................................................',
|
|
||||||
' .///..___..___..___..ooo.......................................................................',
|
|
||||||
' .///..___..___..___..ooo.......................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' ...............................................................................................',
|
|
||||||
' ...............................................................................................',
|
|
||||||
]
|
|
||||||
|
|
||||||
def main():
|
|
||||||
clConfig = parseCommandLine(sys.argv)
|
|
||||||
configFile = clConfig.get('configfile', defaultConfigFile)
|
|
||||||
configFile = os.path.expanduser(configFile)
|
|
||||||
fileConfig = wmdocklib.readConfigFile(configFile, sys.stderr)
|
|
||||||
# Merge the two configs, let the commandline options overwrite those in the
|
|
||||||
# configuration file.
|
|
||||||
config = fileConfig
|
|
||||||
for i in clConfig.iteritems():
|
|
||||||
config[i[0]] = i[1]
|
|
||||||
# Get the configurations
|
|
||||||
setiDir = config.get('setidir')
|
|
||||||
if setiDir is None:
|
|
||||||
sys.stderr.write(
|
|
||||||
'You have to supply a directory where seti@home resides. Either in\n')
|
|
||||||
sys.stderr.write(
|
|
||||||
'the configuration file or with -d/--setidir.\n')
|
|
||||||
sys.exit(3)
|
|
||||||
setiDir = os.path.expanduser(setiDir)
|
|
||||||
try:
|
|
||||||
os.chdir(setiDir)
|
|
||||||
except OSError, e:
|
|
||||||
sys.stderr.write('Error when accessing seti directory: %s\n' % str(e))
|
|
||||||
sys.exit(4)
|
|
||||||
statePath = os.path.join(setiDir, stateFileName)
|
|
||||||
uinfoPath = os.path.join(setiDir, uinfoFileName)
|
|
||||||
pidPath = os.path.join(setiDir, pidFileName)
|
|
||||||
execPath = os.path.join(setiDir, execFileName)
|
|
||||||
niceVal = config.get('nice')
|
|
||||||
if niceVal is None:
|
|
||||||
execCmd = execPath
|
|
||||||
else:
|
|
||||||
execCmd = execPath + ' -nice %s' % niceVal + '&'
|
|
||||||
try:
|
|
||||||
programName = sys.argv[0].split(os.sep)[-1]
|
|
||||||
except IndexError:
|
|
||||||
programName = ''
|
|
||||||
sys.argv[0] = programName
|
|
||||||
wmdocklib.initPixmap(background,
|
|
||||||
palette=palette)
|
|
||||||
wmdocklib.openXwindow(sys.argv, width, height)
|
|
||||||
wmdocklib.addMouseRegion(0, xOffset, yOffset, width - 2 * xOffset,
|
|
||||||
height - 2 * yOffset)
|
|
||||||
pwms = PywmSeti(statePath, uinfoPath, pidPath, execCmd)
|
|
||||||
pwms.mainLoop()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,397 +0,0 @@
|
|||||||
#! /usr/bin/env python
|
|
||||||
|
|
||||||
"""pywmsysmon.py
|
|
||||||
|
|
||||||
WindowMaker system monitor dockapp written in Python. It displays your CPU
|
|
||||||
usage and your available/used memory.
|
|
||||||
|
|
||||||
Copyright (C) 2003 Kristoffer Erlandsson
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
|
|
||||||
Changes
|
|
||||||
2003-06-28 Kristoffer Erlandsson
|
|
||||||
Fixed a bug which caused infinite loop if the mouse was clicked
|
|
||||||
|
|
||||||
2003-06-24 Kristoffer Erlandsson
|
|
||||||
First working version
|
|
||||||
"""
|
|
||||||
usage="""pywmsysmon.py [options]
|
|
||||||
Available options are:
|
|
||||||
-h, --help print this help
|
|
||||||
-f, --barfgcolor <color> set the foreground color of the memory bar
|
|
||||||
-g, --barbgcolor <color> set the background color of the memory bar
|
|
||||||
-b, --background <color> set the background color
|
|
||||||
-p, --graphforeground <color> set the cpu graph foreground color
|
|
||||||
-a, --graphbackground <color> set the cpu graph background color
|
|
||||||
-r, --rgbfile <file> set the rgb file to get color codes from
|
|
||||||
-s, --procstat <file> set the location of /proc/stat
|
|
||||||
-m, --procmeminfo <file> set the location of /proc/meminfo
|
|
||||||
-i, --ignorenice ignore nice valued cpu usage
|
|
||||||
-u, --updatedelay <value> delay (in seconds) between cpu graph updates
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import getopt
|
|
||||||
import os
|
|
||||||
|
|
||||||
import wmdocklib
|
|
||||||
|
|
||||||
width = 64
|
|
||||||
height = 64
|
|
||||||
|
|
||||||
xOffset = 4
|
|
||||||
yOffset = 4
|
|
||||||
|
|
||||||
hGraphStartX = 7
|
|
||||||
hGraphStartY = 53
|
|
||||||
hGraphHeight = 4
|
|
||||||
hGraphWidth = width - xOffset * 2 - 6
|
|
||||||
|
|
||||||
hGraphBgStartX = 72
|
|
||||||
hGraphBgStartY = 53
|
|
||||||
|
|
||||||
hGraphLineStartX = 66
|
|
||||||
hGraphLineStartY = 58
|
|
||||||
|
|
||||||
vGraphStartX = 7
|
|
||||||
vGraphStartY = 7
|
|
||||||
vGraphHeight = 43
|
|
||||||
vGraphWidth = 50
|
|
||||||
|
|
||||||
vGraphLineStartX = 95
|
|
||||||
vGraphLineStartY = 1
|
|
||||||
|
|
||||||
vGraphBgStartX = 97
|
|
||||||
vGraphBgStartY = 1
|
|
||||||
|
|
||||||
defaultConfigFile = '~/.pywmhdmonrc'
|
|
||||||
defaultRGBFiles = ('/usr/lib/X11/rgb.txt', '/usr/X11R6/lib/X11/rgb.txt')
|
|
||||||
defaultProcStat = '/proc/stat'
|
|
||||||
defaultProcMeminfo = '/proc/meminfo'
|
|
||||||
|
|
||||||
class PywmSysMon:
|
|
||||||
def __init__(self, procMeminfo, procStat, ignoreNice=0, updateDelay=10):
|
|
||||||
self._procStat = procStat
|
|
||||||
self._procMeminfo = procMeminfo
|
|
||||||
self._ignoreNice = ignoreNice
|
|
||||||
|
|
||||||
self._lastUsed = 0
|
|
||||||
self._lastTotal = 0
|
|
||||||
|
|
||||||
self._usageHistory = [0.0] * vGraphWidth
|
|
||||||
|
|
||||||
self._cpuUpdateDelay = updateDelay
|
|
||||||
self._memUpdateDelay = 30
|
|
||||||
|
|
||||||
def addUsageToHist(self, cpuUsage):
|
|
||||||
self._usageHistory = self._usageHistory[1:]
|
|
||||||
self._usageHistory.append(cpuUsage)
|
|
||||||
|
|
||||||
def getMemInfo(self):
|
|
||||||
"""Get memory information.
|
|
||||||
|
|
||||||
Return a tuple with (total_mem, used_mem, buffered_mem, cached_mem).
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
meminfoFile = file(self._procMeminfo, 'r')
|
|
||||||
except IOError, e:
|
|
||||||
sys.stderr.write("Can't open meminfo file: %s.\n" % str(e))
|
|
||||||
sys.exit(2)
|
|
||||||
total = used = free = shared = buffers = cached = theLine = None
|
|
||||||
for line in meminfoFile:
|
|
||||||
if line.startswith('Mem:'):
|
|
||||||
theLine = line
|
|
||||||
break
|
|
||||||
if line.startswith('MemTotal:'):
|
|
||||||
total = long(line.split()[1])
|
|
||||||
if line.startswith('MemFree:'):
|
|
||||||
free = long(line.split()[1])
|
|
||||||
if line.startswith('Buffers:'):
|
|
||||||
buffers = long(line.split()[1])
|
|
||||||
if line.startswith('Cached:'):
|
|
||||||
cached = long(line.split()[1])
|
|
||||||
if free and total:
|
|
||||||
used = total - free
|
|
||||||
if theLine is not None:
|
|
||||||
parts = [long(x) for x in theLine.split()[1]]
|
|
||||||
total, used, free, shared, buffers, cached = parts[:6]
|
|
||||||
if None in [total, used, buffers, cached]:
|
|
||||||
sys.stderr.write("Can't find memory information in %s.\n" %
|
|
||||||
self._procMeminfo)
|
|
||||||
sys.exit(4)
|
|
||||||
return (total, used, buffers, cached)
|
|
||||||
|
|
||||||
def freeMem(self, memData):
|
|
||||||
"""Take a tuple as returned from getMemInfo and return the free mem.
|
|
||||||
"""
|
|
||||||
total, used, buffers, cached = memData
|
|
||||||
reallyUsed = used - buffers - cached
|
|
||||||
free = total - reallyUsed
|
|
||||||
return free
|
|
||||||
|
|
||||||
def getCPUUsage(self):
|
|
||||||
"""Get the current CPU usage.
|
|
||||||
|
|
||||||
Only works for systems where this can be found in a /proc/stat like
|
|
||||||
file. Return the usage in percent.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
statFile = file(self._procStat, 'r')
|
|
||||||
except IOError, e:
|
|
||||||
sys.stderr.write("Can't open statfile: %s.\n" % str(e))
|
|
||||||
sys.exit(2)
|
|
||||||
line = statFile.readline()
|
|
||||||
statFile.close()
|
|
||||||
cpu, nice, system, idle = [long(x) for x in line.split()[1:]][:4]
|
|
||||||
used = cpu + system
|
|
||||||
if not self._ignoreNice:
|
|
||||||
used += nice
|
|
||||||
total = cpu + nice + system + idle
|
|
||||||
if total - self._lastTotal <= 0 or self._lastTotal == 0:
|
|
||||||
cpuUsage = 0.0
|
|
||||||
else:
|
|
||||||
cpuUsage = 100.0 * (float(used - self._lastUsed) / float(total -
|
|
||||||
self._lastTotal))
|
|
||||||
self._lastUsed = used
|
|
||||||
self._lastTotal = total
|
|
||||||
return cpuUsage
|
|
||||||
|
|
||||||
def addString(self, s, x, y):
|
|
||||||
try:
|
|
||||||
wmdocklib.addString(s, x, y, digits, xOffset, yOffset, width, height)
|
|
||||||
except ValueError, e:
|
|
||||||
sys.stderr.write('Error when painting string:\n' + str(e) + '\n')
|
|
||||||
sys.exit(3)
|
|
||||||
|
|
||||||
def paintGraph(self, percentFilled, x, y, w):
|
|
||||||
"""Paint a graph with percentFilled percent filled.
|
|
||||||
|
|
||||||
Paint at position x, y and with width w.
|
|
||||||
"""
|
|
||||||
paintWidth = int(round(percentFilled/100.0 * w))
|
|
||||||
if paintWidth > 0:
|
|
||||||
wmdocklib.copyXPMArea(
|
|
||||||
hGraphLineStartX, hGraphLineStartY, paintWidth, hGraphHeight,
|
|
||||||
x, y)
|
|
||||||
if w - paintWidth > 0:
|
|
||||||
wmdocklib.copyXPMArea(
|
|
||||||
hGraphBgStartX, hGraphBgStartY, w - paintWidth, hGraphHeight,
|
|
||||||
x + paintWidth, y)
|
|
||||||
|
|
||||||
def drawVertLine(self, sourceX, sourceY, targX, targY, length):
|
|
||||||
"""Draw a vertical line.
|
|
||||||
"""
|
|
||||||
if length > 0:
|
|
||||||
wmdocklib.copyXPMArea(sourceX, sourceY, 1, length, targX, targY)
|
|
||||||
|
|
||||||
def drawCPUUsageHistory(self):
|
|
||||||
"""Draw the complete CPU usage graph according to what's in the history.
|
|
||||||
"""
|
|
||||||
count = 0
|
|
||||||
for histItem in self._usageHistory:
|
|
||||||
lengthFilled = int(round(vGraphHeight * (histItem/100.0)))
|
|
||||||
lengthNotFilled = vGraphHeight - lengthFilled
|
|
||||||
self.drawVertLine(vGraphBgStartX, vGraphBgStartY,
|
|
||||||
vGraphStartX + count, vGraphStartY,
|
|
||||||
lengthNotFilled)
|
|
||||||
self.drawVertLine(vGraphLineStartX, vGraphLineStartY,
|
|
||||||
vGraphStartX + count,
|
|
||||||
vGraphStartY + lengthNotFilled, lengthFilled)
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
def updateCPUInfo(self):
|
|
||||||
"""Update the current cpu usage graph."""
|
|
||||||
currentUsage = self.getCPUUsage()
|
|
||||||
self.addUsageToHist(currentUsage)
|
|
||||||
self.drawCPUUsageHistory()
|
|
||||||
|
|
||||||
def updateMemInfo(self):
|
|
||||||
"""Update the current memory usage graph."""
|
|
||||||
memInfo = self.getMemInfo()
|
|
||||||
total = memInfo[0]
|
|
||||||
free = self.freeMem(memInfo)
|
|
||||||
percentUsed = 100.0 * (float(total - free) / float(total))
|
|
||||||
self.paintGraph(percentUsed, hGraphStartX, hGraphStartY, hGraphWidth)
|
|
||||||
|
|
||||||
def _checkForEvents(self):
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
while not event is None:
|
|
||||||
if event['type'] == 'destroynotify':
|
|
||||||
sys.exit(0)
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
|
|
||||||
def mainLoop(self):
|
|
||||||
counter = -1
|
|
||||||
while 1:
|
|
||||||
counter += 1
|
|
||||||
self._checkForEvents()
|
|
||||||
if counter % self._cpuUpdateDelay == 0:
|
|
||||||
self.updateCPUInfo()
|
|
||||||
if counter % self._memUpdateDelay == 0:
|
|
||||||
self.updateMemInfo()
|
|
||||||
if counter == 999999:
|
|
||||||
counter = -1
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def parseCommandLine(argv):
|
|
||||||
"""Parse the commandline. Return a dictionary with options and values."""
|
|
||||||
shorts = 'hf:g:b:p:a:r:s:m:iu:'
|
|
||||||
longs = ['help=', 'barbgcolor=', 'barfgcolor=', 'background=',
|
|
||||||
'graphforeground=', 'graphbackground=', 'rgbfile=', 'procstat=',
|
|
||||||
'procmeminfo=', 'ignorenice', 'updatedelay=']
|
|
||||||
try:
|
|
||||||
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
|
|
||||||
except getopt.GetoptError, e:
|
|
||||||
sys.stderr.write('Error when parsing commandline: ' + str(e) + '\n')
|
|
||||||
sys.stderr.write(usage)
|
|
||||||
sys.exit(2)
|
|
||||||
d = {}
|
|
||||||
for o, a in opts:
|
|
||||||
if o in ('-h', '--help'):
|
|
||||||
sys.stdout.write(usage)
|
|
||||||
sys.exit(0)
|
|
||||||
if o in ('-b', '--background'):
|
|
||||||
d['background'] = a
|
|
||||||
if o in ('-r', '--rgbfile'):
|
|
||||||
d['rgbfile'] = a
|
|
||||||
if o in ('-g', '--barbgcolor'):
|
|
||||||
d['barbgcolor'] = a
|
|
||||||
if o in ('-f', '--barfgcolor'):
|
|
||||||
d['barfgcolor'] = a
|
|
||||||
if o in ('-s', '--procstat'):
|
|
||||||
d['procstat'] = a
|
|
||||||
if o in ('-p', '--graphforeground'):
|
|
||||||
d['graphforeground'] = a
|
|
||||||
if o in ('-a', '--graphbackground'):
|
|
||||||
d['graphbackground'] = a
|
|
||||||
if o in ('-m', '--procmeminfo'):
|
|
||||||
d['procmeminfo'] = a
|
|
||||||
if o in ('-i', '--ignorenice'):
|
|
||||||
d['ignorenice'] = 1
|
|
||||||
if o in ('-u', '--updatedelay'):
|
|
||||||
try:
|
|
||||||
d['updatedelay'] = int(a) * 10
|
|
||||||
except ValueError:
|
|
||||||
sys.stderr.write(
|
|
||||||
"Value for updatedelay has to be an integer.\n")
|
|
||||||
sys.exit(2)
|
|
||||||
return d
|
|
||||||
|
|
||||||
background = \
|
|
||||||
[' ...............................................................................................',
|
|
||||||
' .///..___..ooo..___..___......|.I..............................................................',
|
|
||||||
' .///..___..ooo..___..___......|.I..............................................................',
|
|
||||||
' .///..___..ooo..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..ooo..___......|.I..............................................................',
|
|
||||||
' .///..___..___..ooo..___......|.I..............................................................',
|
|
||||||
' .///..___..___..ooo..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..___......|.I..............................................................',
|
|
||||||
' .///..___..___..___..ooo......|.I..............................................................',
|
|
||||||
' .///..___..___..___..ooo......|.I..............................................................',
|
|
||||||
' .///..___..___..___..ooo......|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///..........................|.I..............................................................',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...-------------------------------------------------------------------------------------...',
|
|
||||||
' .///...........................................................................................',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' .///////////////////////////////////////////////////////////////////////////////////////////...',
|
|
||||||
' ...............................................................................................',
|
|
||||||
' ...............................................................................................',
|
|
||||||
]
|
|
||||||
|
|
||||||
def main():
|
|
||||||
config = parseCommandLine(sys.argv)
|
|
||||||
procStat = config.get('procstat', defaultProcStat)
|
|
||||||
if not os.access(procStat, os.R_OK):
|
|
||||||
sys.stderr.write(
|
|
||||||
"Can't read your procstat file, try setting it with -s.\n")
|
|
||||||
sys.exit(4)
|
|
||||||
procMeminfo = config.get('procmeminfo', defaultProcMeminfo)
|
|
||||||
if not os.access(procMeminfo, os.R_OK):
|
|
||||||
sys.stderr.write(
|
|
||||||
"Can't read your procmeminfo file, try setting it with -m.\n")
|
|
||||||
sys.exit(4)
|
|
||||||
ignoreNice = config.get('ignorenice', 0)
|
|
||||||
updateDelay = config.get('updatedelay', 30)
|
|
||||||
try:
|
|
||||||
programName = sys.argv[0].split(os.sep)[-1]
|
|
||||||
except IndexError:
|
|
||||||
programName = ''
|
|
||||||
sys.argv[0] = programName
|
|
||||||
|
|
||||||
palette = {
|
|
||||||
' ': '#208120812081',
|
|
||||||
'.': '#00000000FFFF',
|
|
||||||
'o': '#C71BC30BC71B',
|
|
||||||
'O': '#861782078E38',
|
|
||||||
'+': '#EFBEF3CEEFBE',
|
|
||||||
'@': '#618561856185',
|
|
||||||
'#': '#9E79A2899E79',
|
|
||||||
'$': '#410341034103',
|
|
||||||
'o': '#2020b2b2aaaa',
|
|
||||||
}
|
|
||||||
#palette['o'] = config.get('indicator', '#2020b2b2aaaa')
|
|
||||||
palette['/'] = config.get('barfgcolor', '#2020b2b2aaaa')
|
|
||||||
palette['-'] = config.get('barbgcolor', '#707070707070')
|
|
||||||
palette['|'] = config.get('graphforeground', '#2020b2b2aaaa')
|
|
||||||
palette['I'] = config.get('graphbackground', '#707070707070')
|
|
||||||
palette['_'] = config.get('background', '#000000000000')
|
|
||||||
palette['%'] = config.get('foreground', '#2081B2CAAEBA')
|
|
||||||
|
|
||||||
wmdocklib.initPixmap(background, palette=palette)
|
|
||||||
wmdocklib.openXwindow(sys.argv, width, height)
|
|
||||||
pywmsysmon = PywmSysMon(procMeminfo, procStat, ignoreNice, updateDelay)
|
|
||||||
pywmsysmon.mainLoop()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""pywmwet.py
|
|
||||||
WindowMaker dockapp that tracks a Wolf:ET server and displays following info:
|
|
||||||
->Map Name
|
|
||||||
-># of Allies
|
|
||||||
-># of Axis
|
|
||||||
-># of Spectators (if server using 'P' cvar
|
|
||||||
|
|
||||||
Copyright (C) 2007 Nathan Lundquist
|
|
||||||
Licensed under the GNU General Public License.
|
|
||||||
Changes:
|
|
||||||
2007-01-16 Nate Lundquist
|
|
||||||
First attempt
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys, getopt, os
|
|
||||||
import socket
|
|
||||||
import wmdocklib
|
|
||||||
import time, datetime
|
|
||||||
|
|
||||||
DEFAULT_PORT = 27960
|
|
||||||
DEFAULT_INTERVAL = 60 #seconds
|
|
||||||
WIDTH = 64
|
|
||||||
HEIGHT = 64
|
|
||||||
XOFFSET = 4
|
|
||||||
YOFFSET = 4
|
|
||||||
MARGIN = 1
|
|
||||||
LINE_SPACING = 4
|
|
||||||
|
|
||||||
usage = '''\
|
|
||||||
pywmwet.py [options]
|
|
||||||
Available options are:
|
|
||||||
-h, --help Print this help text
|
|
||||||
-s, --server <server address> Server to track
|
|
||||||
-p, --port <port> Server port [default: 27960]
|
|
||||||
-u, --update-interval <seconds> Delay between updates [default: 60 sec]
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def parse_command_line(argv):
|
|
||||||
shorts = 'hs:p:u:'
|
|
||||||
longs = ['help', 'server=', 'port=', 'update-interval=']
|
|
||||||
|
|
||||||
try:
|
|
||||||
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
|
|
||||||
except getopt.GetoptError, e:
|
|
||||||
print 'Error parsing commandline: ' + str(e)
|
|
||||||
print usage
|
|
||||||
sys.exit(2)
|
|
||||||
d = {}
|
|
||||||
for o, a in opts:
|
|
||||||
if o in ('-h', '--help'):
|
|
||||||
print usage
|
|
||||||
sys.exit(0)
|
|
||||||
if o in ('-s', '--server'):
|
|
||||||
d['server'] = a
|
|
||||||
if o in ('-p', '--port'):
|
|
||||||
d['port'] = int(a)
|
|
||||||
else:
|
|
||||||
d['port'] = DEFAULT_PORT
|
|
||||||
if o in ('-u', '--update-interval'):
|
|
||||||
d['update-interval'] = int(a)
|
|
||||||
else:
|
|
||||||
d['update-interval'] = DEFAULT_INTERVAL
|
|
||||||
return d
|
|
||||||
|
|
||||||
def query_server(server, port):
|
|
||||||
try:
|
|
||||||
query = '\xFF\xFF\xFF\xFF\x02getstatus\x0a\x00'
|
|
||||||
addr = (server, port)
|
|
||||||
sockobj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
sockobj.settimeout(4.0)
|
|
||||||
sockobj.connect(addr)
|
|
||||||
sockobj.send(query)
|
|
||||||
data = sockobj.recv(4096)
|
|
||||||
data = data[18:]
|
|
||||||
sockobj.shutdown(0)
|
|
||||||
sockobj.close()
|
|
||||||
#print 'query success'
|
|
||||||
#print data
|
|
||||||
return data
|
|
||||||
except socket.error:
|
|
||||||
#print 'query failure'
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_map(data):
|
|
||||||
data = data.split('\\')
|
|
||||||
i = data.index('mapname')
|
|
||||||
return ' '.join(data[i+1].split('_')).title()
|
|
||||||
|
|
||||||
def get_num_allies(data):
|
|
||||||
data = data.split('\\')
|
|
||||||
try: #servers using older cvar
|
|
||||||
i = data.index('Players_Allies')
|
|
||||||
allies = data[i+1]
|
|
||||||
return len(allies.split())
|
|
||||||
except ValueError: #possibly newer server using 'P' cvar
|
|
||||||
try:
|
|
||||||
#3 - Spectator, 2 - Allies, 1 - Axis
|
|
||||||
i = data.index('P')
|
|
||||||
slots = data[i+1]
|
|
||||||
allies = 0
|
|
||||||
for slot in slots:
|
|
||||||
if slot == '2':
|
|
||||||
allies += 1
|
|
||||||
return allies
|
|
||||||
except ValueError: #no players connected?
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def get_num_axis(data):
|
|
||||||
data = data.split('\\')
|
|
||||||
try: #server using old cvar
|
|
||||||
i = data.index('Players_Axis')
|
|
||||||
axis = data[i+1]
|
|
||||||
return len(axis.split())
|
|
||||||
except ValueError: #possible new cvar
|
|
||||||
try:
|
|
||||||
#3 - Spectator, 2 - Allies, 1 - Axis
|
|
||||||
i = data.index('P')
|
|
||||||
slots = data[i+1]
|
|
||||||
axis = 0
|
|
||||||
for slot in slots:
|
|
||||||
if slot == '1':
|
|
||||||
axis += 1
|
|
||||||
return axis
|
|
||||||
except ValueError: #no players
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def get_num_spectators(data):
|
|
||||||
#This will only work with servers that use the newer 'P' cvar
|
|
||||||
data = data.split('\\')
|
|
||||||
try:
|
|
||||||
#3 - Spectator, 2 - Allies, 1 - Axis
|
|
||||||
i = data.index('P')
|
|
||||||
slots = data[i+1]
|
|
||||||
spec = 0
|
|
||||||
for slot in slots:
|
|
||||||
if slot == '3':
|
|
||||||
spec += 1
|
|
||||||
return spec
|
|
||||||
except ValueError: #check if old cvars in use
|
|
||||||
if 'Players_Axis' in data or 'Players_Allies' in data:
|
|
||||||
#old cvars in use, so we don't know how many spectators there are
|
|
||||||
return '??'
|
|
||||||
else: #no players
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def get_players(data):
|
|
||||||
players = []
|
|
||||||
player_data = data.strip().split('\n')[1:]
|
|
||||||
for player_line in player_data:
|
|
||||||
player = strip_name(player_line.split('"')[1])
|
|
||||||
players.append(player)
|
|
||||||
return players
|
|
||||||
|
|
||||||
def scroll_players(players):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def strip_name(name):
|
|
||||||
stripped_name = ''
|
|
||||||
skip_next = False
|
|
||||||
for x in range(len(name)):
|
|
||||||
if name[x] != '^' and skip_next != True:
|
|
||||||
stripped_name += name[x]
|
|
||||||
elif name[x] == '^':
|
|
||||||
skip_next = True
|
|
||||||
continue
|
|
||||||
skip_next = False
|
|
||||||
return stripped_name
|
|
||||||
|
|
||||||
|
|
||||||
def scroll_text(s, y, speed):
|
|
||||||
#not sure if this is the best way to do this...
|
|
||||||
cen_pos = get_center(s)
|
|
||||||
end_pos = (cen_pos *2) - (MARGIN * 2) - 64
|
|
||||||
for x in range(WIDTH, end_pos, -1):
|
|
||||||
add_string(s, x, y)
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(speed)
|
|
||||||
|
|
||||||
def get_center(s):
|
|
||||||
return wmdocklib.getCenterStartPos(s, WIDTH, XOFFSET)
|
|
||||||
|
|
||||||
def add_string(s, x, y):
|
|
||||||
return wmdocklib.addString(s, x, y, XOFFSET, YOFFSET, WIDTH, HEIGHT)
|
|
||||||
|
|
||||||
def get_spacing(line_no):
|
|
||||||
if line_no == 1:
|
|
||||||
return MARGIN
|
|
||||||
else:
|
|
||||||
# 1 + (4) + 4
|
|
||||||
return MARGIN + (char_height * (line_no - 1)) + LINE_SPACING * (line_no - 1)
|
|
||||||
|
|
||||||
def check_for_events():
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
while not event is None:
|
|
||||||
if event['type'] == 'destroynotify':
|
|
||||||
sys.exit(0)
|
|
||||||
event = wmdocklib.getEvent()
|
|
||||||
|
|
||||||
def main_loop(server, port, update_interval):
|
|
||||||
dif = datetime.timedelta(seconds=update_interval)
|
|
||||||
last_updated = datetime.datetime.now()
|
|
||||||
just_started = True
|
|
||||||
while 1:
|
|
||||||
check_for_events()
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
if now > (last_updated + dif) or just_started == True:
|
|
||||||
data = query_server(server, port)
|
|
||||||
if not data:
|
|
||||||
add_string('Server', get_center('Server'), get_spacing(1))
|
|
||||||
add_string('Not', get_center('Not'), get_spacing(2))
|
|
||||||
add_string('Found', get_center('Found'), get_spacing(3))
|
|
||||||
just_started = False
|
|
||||||
else:
|
|
||||||
mapname = get_map(data)
|
|
||||||
num_allies = get_num_allies(data)
|
|
||||||
num_axis = get_num_axis(data)
|
|
||||||
num_specs = get_num_spectators(data)
|
|
||||||
last_updated = datetime.datetime.now()
|
|
||||||
just_started = False
|
|
||||||
|
|
||||||
if data:
|
|
||||||
add_string(('Allies:%s' % str(num_allies)), MARGIN, get_spacing(2) + 5)
|
|
||||||
add_string(('Axis:%s' % str(num_axis)), MARGIN, get_spacing(3) + 5)
|
|
||||||
add_string(('Spec:%s' % str(num_specs)), MARGIN, get_spacing(4) + 5)
|
|
||||||
|
|
||||||
#mapname last in case it has to scroll
|
|
||||||
if get_center(mapname) < MARGIN:
|
|
||||||
scroll_text(mapname, get_spacing(1), 0.04)
|
|
||||||
else:
|
|
||||||
add_string(mapname, get_center(mapname), get_spacing(1))
|
|
||||||
|
|
||||||
wmdocklib.redraw()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
clConfig = parse_command_line(sys.argv)
|
|
||||||
try:
|
|
||||||
program_name = sys.argv[0].split(os.sep)[-1]
|
|
||||||
except IndexError:
|
|
||||||
program_name = ''
|
|
||||||
|
|
||||||
if not clConfig.has_key('server'):
|
|
||||||
print '\nYou must supply a server using the -s/--server option.\n'
|
|
||||||
print 'Use -h flag to see more options.'
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
global char_width, char_height
|
|
||||||
char_width, char_height = wmdocklib.initPixmap(font_name='5x7', fg=3)
|
|
||||||
wmdocklib.openXwindow(sys.argv, 64, 64)
|
|
||||||
|
|
||||||
try:
|
|
||||||
main_loop(clConfig['server'], clConfig['port'], clConfig['update-interval'])
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print 'Goodbye.'
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
mplayer /usr/bin/mplayer
|
|
||||||
dumpdir /home/mario
|
|
||||||
rai1 rtsp://live.media.rai.it/broadcast/radiouno.rm 48
|
|
||||||
rai2 rtsp://live.media.rai.it/broadcast/radiodue.rm 48
|
|
||||||
rai3tre rtsp://live.media.rai.it/broadcast/radiotre.rm 96
|
|
||||||
nos1 http://livemedia.omroep.nl/radio1-breed 128
|
|
||||||
nos4 http://livemedia.omroep.nl/radio4-breed 128
|
|
||||||
rne1 mms://a729.l830022151.c8300.e.lm.akamaistream.net/D/729/8300/v0001/reflector:22151 128
|
|
||||||
rne3 mms://a1830.l830120550.c8301.e.lm.akamaistream.net/D/1830/8301/v0001/reflector:20550 128
|
|
||||||
rzeszów http://live.radio.rzeszow.pl:8000/hi 128
|
|
||||||
gdańsk http://www.radio.gdansk.pl/audio/radio_gdansk_low.asx 128
|
|
||||||
kielce http://gra.radio.kielce.com.pl:8000/listen.pls 128
|
|
||||||
kraków http://emiter.radio-krakow.pl:8080/ramgen/encoder/krakow.rm 48
|
|
||||||
bialystok rtsp://194.187.119.2/encoder/radio.rm 48
|
|
||||||
bbcws rtsp://rmlive.bbc.co.uk/bbc-rbs/rmlive/ev7/live24/worldservice/liveinfent.ra 256
|
|
||||||
bbc3 rtsp://rmlive.bbc.co.uk/bbc-rbs/rmlive/ev7/live24/radio3/live/r3_dsat_g2.ra 256
|
|
||||||
bbc4 rtsp://rmlive.bbc.co.uk/bbc-rbs/rmlive/ev7/live24/radio4/live/r4_dsat_g2.ra 256
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
# The formats are the same as Python's strftime accept, but one format is
|
|
||||||
# added. %q now means the week-number with monday as the start of the week and
|
|
||||||
# the first day of the year is allways in week 1. We calculate like that for
|
|
||||||
# example here in Sweden.
|
|
||||||
#
|
|
||||||
# Taken from the Python manual:
|
|
||||||
# %a Locale's abbreviated weekday name.
|
|
||||||
# %A Locale's full weekday name.
|
|
||||||
# %b Locale's abbreviated month name.
|
|
||||||
# %B Locale's full month name.
|
|
||||||
# %c Locale's appropriate date and time representation.
|
|
||||||
# %d Day of the month as a decimal number [01,31].
|
|
||||||
# %H Hour (24-hour clock) as a decimal number [00,23].
|
|
||||||
# %I Hour (12-hour clock) as a decimal number [01,12].
|
|
||||||
# %j Day of the year as a decimal number [001,366].
|
|
||||||
# %m Month as a decimal number [01,12].
|
|
||||||
# %M Minute as a decimal number [00,59].
|
|
||||||
# %p Locale's equivalent of either AM or PM.
|
|
||||||
# %S Second as a decimal number [00,61].
|
|
||||||
# %U Week number of the year (Sunday as the first day of the week) as a
|
|
||||||
# decimal number [00,53]. All days in a new year preceding the first
|
|
||||||
# Sunday are considered to be in week 0.
|
|
||||||
# %w Weekday as a decimal number [0(Sunday),6].
|
|
||||||
# %W Week number of the year (Monday as the first day of the week) as a
|
|
||||||
# decimal number [00,53]. All days in a new year preceding the first
|
|
||||||
# Monday are considered to be in week 0.
|
|
||||||
# %x Locale's appropriate date representation.
|
|
||||||
# %X Locale's appropriate time representation.
|
|
||||||
# %y Year without century as a decimal number [00,99].
|
|
||||||
# %Y Year with century as a decimal number.
|
|
||||||
# %Z Time zone name (or by no characters if no time zone exists).
|
|
||||||
# %% A literal "%" character.
|
|
||||||
|
|
||||||
background=black
|
|
||||||
foreground=light sea green
|
|
||||||
timeformat=%H:%M:%S
|
|
||||||
dateformat=%d-%m-%y
|
|
||||||
weekdayformat=%A
|
|
||||||
weekformat=wk %q
|
|
||||||
#rgbfile=/usr/lib/X11/rgb.txt
|
|
||||||
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
# Sample configuration file for pywmgeneric.py.
|
|
||||||
#
|
|
||||||
# THIS IS ONLY A SAMPLE. IT WILL MOST CERTAIN NOT WORK ON YOUR SYSTEM SINCE
|
|
||||||
# CUSTOM PROGRAMS ARE USED IN HERE. ONLY USE THIS AS AN REFERENCE.
|
|
||||||
#
|
|
||||||
# Available actions are:
|
|
||||||
# * method <method> - Call a method defined in the class UserMethods. See the
|
|
||||||
# source file for more information
|
|
||||||
# * exec <command> - Execute an external command
|
|
||||||
#
|
|
||||||
# Available mouse actions are:
|
|
||||||
# * method <method> - Same as above, see the source file for more information.
|
|
||||||
# * exec <command> - Same as above
|
|
||||||
# * update - Update the data through running the action.
|
|
||||||
#
|
|
||||||
# Other options:
|
|
||||||
# * scroll = yes|no - en-/disable scrolling of the text if it doens't fit.
|
|
||||||
# * display = <text> - display a static string instead of the first line of
|
|
||||||
# the action-generated output.
|
|
||||||
# * update_delay = <number><s|m|h> - the time to elapse between performing the
|
|
||||||
# action
|
|
||||||
#
|
|
||||||
# %(allText)s expands to all the text collected by the action.
|
|
||||||
# %(displayedLine)s expands to the line currently displayed in the app. This
|
|
||||||
# may show more than actually displayed since it gets the
|
|
||||||
# entire line, which may be truncated before display.
|
|
||||||
# %(allTextEscaped)s expands to the same as %(allText)s but with all ":s
|
|
||||||
# escaped to \". Great to use when passing the text as a
|
|
||||||
# command line argument to something.
|
|
||||||
# %(allTextButFirstLine)s expands to all text but leaves out the first line.
|
|
||||||
# Useful if your program for example prints a summary
|
|
||||||
# first.
|
|
||||||
# %(allTextButFirstLineEscaped)s is a combination of the two above.
|
|
||||||
#
|
|
||||||
|
|
||||||
[0]
|
|
||||||
action = method getCpuTemp
|
|
||||||
update_delay = 10s
|
|
||||||
on_mouse1 = exec sensors | xmessage -file -
|
|
||||||
on_mouse3 = update
|
|
||||||
scroll = no
|
|
||||||
|
|
||||||
[1]
|
|
||||||
action = method getSysTemp
|
|
||||||
update_delay = 10s
|
|
||||||
on_mouse1 = exec sensors | xmessage -file -
|
|
||||||
on_mouse3 = update
|
|
||||||
scroll = no
|
|
||||||
|
|
||||||
[2]
|
|
||||||
action = exec tvcatcher.py -s -d
|
|
||||||
on_mouse1 = method showTvWithoutDescs
|
|
||||||
on_mouse2 = exec mozilla http://tvprogram.nu
|
|
||||||
on_mouse3 = exec xmessage "%(allTextButFirstLineEscaped)s"
|
|
||||||
update_delay = 5m
|
|
||||||
scroll = yes
|
|
||||||
|
|
||||||
[3]
|
|
||||||
display = xterm
|
|
||||||
on_mouse1 = exec xterm
|
|
||||||
|
|
||||||
[4]
|
|
||||||
action = exec dnheadlinecatcher.py -d
|
|
||||||
on_mouse1 = method showDnWithoutDescs
|
|
||||||
on_mouse2 = exec mozilla http://www.dn.se
|
|
||||||
on_mouse3 = exec xmessage "%(allTextEscaped)s"
|
|
||||||
update_delay = 0.5h
|
|
||||||
scroll = yes
|
|
||||||
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
|
|
||||||
# Displaymodes are used, free, percent or bar, displays the used size,
|
|
||||||
# free size, free percent and a bar representing space, respectively.
|
|
||||||
|
|
||||||
1.label=/
|
|
||||||
1.path=/
|
|
||||||
#1.displaymode=free
|
|
||||||
|
|
||||||
2.label=usr
|
|
||||||
2.path=/usr
|
|
||||||
#2.displaymode=free
|
|
||||||
|
|
||||||
3.label=home
|
|
||||||
3.path=/home
|
|
||||||
#3.displaymode=free
|
|
||||||
|
|
||||||
4.label=cd
|
|
||||||
4.path=/mnt/cd
|
|
||||||
4.displaymode=used
|
|
||||||
4.action=eject
|
|
||||||
|
|
||||||
5.label=jr
|
|
||||||
5.path=/mnt/jr
|
|
||||||
5.displaymode=used
|
|
||||||
5.action=eject
|
|
||||||
|
|
||||||
6.label=sm
|
|
||||||
6.path=/mnt/sm
|
|
||||||
6.displaymode=free
|
|
||||||
6.action=mount
|
|
||||||
|
|
||||||
7.label=cf
|
|
||||||
7.path=/mnt/cf
|
|
||||||
7.displaymode=free
|
|
||||||
7.action=mount
|
|
||||||
|
|
||||||
8.label=flo
|
|
||||||
8.path=/mnt/flo
|
|
||||||
8.displaymode=free
|
|
||||||
8.action=mount
|
|
||||||
|
|
||||||
textcolor=light sea green
|
|
||||||
background=black
|
|
||||||
barfgcolor=light sea green
|
|
||||||
barbgcolor=grey45
|
|
||||||
monitoring=0
|
|
||||||
|
|
||||||
#rgbfile=/usr/lib/X11/rgb.txt
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
setidir=/home/erl/setiathome
|
|
||||||
# Nice value to start the seti@home process with on click.
|
|
||||||
nice=19
|
|
||||||
textcolor=light sea green
|
|
||||||
progressbarcolor=light sea green
|
|
||||||
barbgcolor=grey45
|
|
||||||
indicatorcolor=light sea green
|
|
||||||
background=black
|
|
||||||
|
|
||||||
#rgbfile=/usr/lib/X11/rgb.txt
|
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
[wmdocklib.WHAT]
|
|
||||||
Pywmgeneral is a python module that will help you develope WindowMaker
|
|
||||||
dockapps in python. It is mostly a wrapper around the functions from the
|
|
||||||
popular wmgeneral.c, but some new functions are added too.
|
|
||||||
|
|
||||||
It also contains the Python written module pywmhelpers.py which contains
|
|
||||||
functions to aid the development of wm dockapps. This module contains python
|
|
||||||
functions that wrap up the functions which the extension module provides.
|
|
||||||
They ease up argument passing and give nicer return values. Some additional
|
|
||||||
functions, like help for handling a simple configuration file is also
|
|
||||||
available. This module is better documented than the pywmgeneral. It is
|
|
||||||
adviced to only use pywmhelpers and not touch the pywmgeneral module
|
|
||||||
directly at all. For information about how to use the module, see the
|
|
||||||
documentation in pywmhelpers.py. It is also possible to import it in the
|
|
||||||
interactive interpreter and issue 'help(wmdocklib)'.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
from pywmgeneral import *
|
|
||||||
from pywmhelpers import *
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>pywmdockapps - WindowMaker dockapps written in Python</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="my_style.css">
|
|
||||||
</head>
|
|
||||||
<body bgcolor=#FFFFFF text=#000000>
|
|
||||||
<h1>pywmdockapps - WindowMaker dockapps written in Python</h1>
|
|
||||||
|
|
||||||
<h3>What is this place?</h3>
|
|
||||||
|
|
||||||
<p>pywmdockapps is the place to be if you are interested in <a
|
|
||||||
href="http://www.windowmaker.org">WindowMaker</a>, <a
|
|
||||||
href="http://dockapps.org">dockapps</a> and <a
|
|
||||||
href="http://www.python.org">Python</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
WindowMaker dockapps are graphical applications fitting in a 64x64 tile.
|
|
||||||
they can work in WindowMaker or any other window manager which can handle
|
|
||||||
WindowMaker style dockapps; typically: Gome or fvwm.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
pywmdockapps is a sourceforge hosted project containing a Python library
|
|
||||||
-wmdocklib- and a small collection of rather usable examples.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>although some of the included examples are untested, some others are used
|
|
||||||
and maintained by the project coordinator. non eof them comes with any
|
|
||||||
guarantee: they may work well, not work at all, set your computer in flames.
|
|
||||||
even though no such event has yet been reported, you have been warned. the
|
|
||||||
ones Mario Frasca uses all the time are pywmdatetime (removed wmCalClock in
|
|
||||||
its favour) and pywmhdmon.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The example dockapps aim at simplicity and consistency. they are as similar
|
|
||||||
as possible to each other and with no excessive graphics. Since they are
|
|
||||||
written in Python, it shouldn't be too hard to change something you do not
|
|
||||||
like about them. if you do modify things according to your needs and tastes
|
|
||||||
or if you simply try things out, please share your opinions/changes with the
|
|
||||||
community, by sending a comment, suggestion, patch (highly appreciated), or
|
|
||||||
just drop a note to say that you have tried it. see contact information at
|
|
||||||
the bottom of this page. </p>
|
|
||||||
|
|
||||||
<p>you may also consider filing a <a
|
|
||||||
href="http://sourceforge.net/tracker/?group_id=147660&atid=769418">bug</a>
|
|
||||||
or <a
|
|
||||||
href="http://sourceforge.net/tracker/?group_id=147660&atid=769421">change
|
|
||||||
request</a>... if your request comes with a diff file, chances are that it
|
|
||||||
will be processed quickly (a matter of 3/5 days).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>News</h3>
|
|
||||||
|
|
||||||
<p class="newsdate">2006-10-26</p>
|
|
||||||
|
|
||||||
<p class="newstext">released a few constraints. the font can be
|
|
||||||
antialiased (the colour is interpreted as levels of gray and the resulting
|
|
||||||
effect is an interpolation between background and text-foreground);
|
|
||||||
the set of patterns and the character set may be each reasonable size;
|
|
||||||
some of the programs accept a --debug option, in which case they also
|
|
||||||
output the xpm to stdout; clashes in symbols used in character definition
|
|
||||||
xpm and patterns are resolved by the library. the ' ' (space) is still
|
|
||||||
reserved for the transparency; all 0..9,a..f are still reserved for
|
|
||||||
'built in' colours. </p>
|
|
||||||
|
|
||||||
<p class="newsdate">2006-10-22</p>
|
|
||||||
|
|
||||||
<p class="newstext">radically restyled the initialization of the xpm. the
|
|
||||||
three parts of which it is composed (drawing area, patterns, charset) are
|
|
||||||
now one on top of the other. the client application does not need take care
|
|
||||||
of making the three components of equal width nor of any specific length:
|
|
||||||
it's the library fixing and keeping track of this kind of things.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="newstext">the 'background' parameter for the initialization
|
|
||||||
function can be a static pixel map, (in this case the space character is
|
|
||||||
reserved for specifying transparency), or can be left blank (then the
|
|
||||||
pixel map is constructed with 'margin' transparent pixels all around)
|
|
||||||
or you may give a list of 'viewports': rectangular holes you want to
|
|
||||||
dig in the otherwise transparent pixel map. </p>
|
|
||||||
|
|
||||||
<p class="newstext">use the initialization interactively and give
|
|
||||||
'debug=True' to see the constructed xpm. you may save it in a file and
|
|
||||||
view it with your favourite graphics viewer. there are versions of emacs
|
|
||||||
(e.g.: CVS Emacs on Mac OS X) where you can view a buffer 'graphically'
|
|
||||||
just by hitting C-c C-c. </p>
|
|
||||||
|
|
||||||
<p class="newsdate">2006-10-13</p>
|
|
||||||
<p class="newstext">we are now at version 1.11. the library can be
|
|
||||||
built/installed/distributed using the standard distutils library.
|
|
||||||
do</p>
|
|
||||||
<pre>python setup.py build
|
|
||||||
sudo python setup.py install</pre>
|
|
||||||
|
|
||||||
<p class="newstext">additional fonts can be installed. have a look at the
|
|
||||||
ones defined in the wmdocklib directory. the constraints are: the name must
|
|
||||||
contain an indication of the size of the character cell (something like
|
|
||||||
6x8); only the ASCII characters 32-127 can be defined; the width of the xpm
|
|
||||||
must be 128 pixels; in the xpm the two characters ' '(space) and '%' are
|
|
||||||
reserved for background and foreground.
|
|
||||||
</p>
|
|
||||||
<p class="newstext">once you have added your own font, redo the intallation
|
|
||||||
procedure. </p>
|
|
||||||
|
|
||||||
<p class="newsdate">2005-09-05</p>
|
|
||||||
<p class="newstext">coordination taken over by Mario Frasca. project accepted in sourceforge. </p>
|
|
||||||
|
|
||||||
<p class="newsdate">2004-07-15</p>
|
|
||||||
<p class="newstext">Minor feature enhancement/bug fix in pywmhdmon.</p>
|
|
||||||
<p class="newsdate">2003-09-01</p>
|
|
||||||
<p class="newstext">Some bugfixes in pywmdatetime and pywmhdmon.</p>
|
|
||||||
<p class="newsdate">2003-07-02</p>
|
|
||||||
<p class="newstext">Pywmgeneric now has support for up to ten mouse buttons.</p>
|
|
||||||
<p class="newsdate">2003-06-28</p>
|
|
||||||
<p class="newstext">Fixed a bug in three of the applications where a mouse click caused the app to
|
|
||||||
hang.</p>
|
|
||||||
<p class="newsdate">2003-06-27</p>
|
|
||||||
<p class="newstext">Added a new dockapp, pywmgeneric.</p>
|
|
||||||
<p class="newsdate">2003-06-24</p>
|
|
||||||
<p class="newstext">Added a new dockapp, pywmsysmon.</p>
|
|
||||||
<p class="newsdate">2003-06-23</p>
|
|
||||||
<p class="newstext">Added a new dockapp, pywmhdmon.</p>
|
|
||||||
<p class="newsdate">2003-06-17</p>
|
|
||||||
<p class="newstext">Added a new dockapp, pywmseti.</p>
|
|
||||||
<p class="newsdate">2003-06-16</p>
|
|
||||||
<p class="newstext">Added a new dockapp, pywmdatetime.</p>
|
|
||||||
<p class="newsdate">2003-06-13</p>
|
|
||||||
<p class="newstext">Kristoffer Erlandsson starts the project, creating the file pywmgeneral.c. Thanks to Martijn Pieterse for the original wmgeneral.c</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>wmdocklib</h3>
|
|
||||||
<p>wmdocklib is a library that makes it possible to write WindowMaker
|
|
||||||
dockapps in <a href='http://www.python.org'>Python</a>. Quite a bit of the
|
|
||||||
code is taken from wmgeneral.c and Kristoffer says he just provided Python
|
|
||||||
wrappers around those functions. The library also contains a Python part
|
|
||||||
above the wrappers that ease up argument passing and return values. Also
|
|
||||||
some other usable methods are provided there.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Pywmdatetime</h3>
|
|
||||||
<img src="pictures/pywmdatetime.png" alt="pywmdatetime">
|
|
||||||
<img src="pictures/pywmdatetime-fonts.png" alt="pywmdatetime">
|
|
||||||
<img src="pictures/pywmdatetime-antialiased.png" alt="pywmdatetime">
|
|
||||||
<p>Pywmdatetime is a dockapp that displays the current time, date, weekday
|
|
||||||
and week number. Formats and colours and font are easily configured. The
|
|
||||||
application contains an antialiased font for digits, which is used if the
|
|
||||||
option '-a' is used.</p>
|
|
||||||
<p>Changes:</p>
|
|
||||||
<p class="newsdate">2003-09-01</p>
|
|
||||||
<p class="newstext">Fixed a bug where the week didn't update if we used %q style week numbering.</p>
|
|
||||||
<p class="newsdate">2003-06-28</p>
|
|
||||||
<p class="newstext">Fixed a bug where a mouse click caused an infinite loop.</p>
|
|
||||||
<p class="newsdate">2003-06-26</p>
|
|
||||||
<p class="newstext">Fixed the bug where longer strings didn't get cleared when shorter ones where
|
|
||||||
painted.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Pywmhdmon</h3>
|
|
||||||
<img src="pictures/pywmhdmon.png" alt="pywmhdmon">
|
|
||||||
<img src="pictures/angelico-unmounted.png" alt="pywmhdmon">
|
|
||||||
<img src="pictures/angelico-mounted.png" alt="pywmhdmon">
|
|
||||||
<img src="pictures/croese-mounted.png" alt="pywmhdmon">
|
|
||||||
<img src="pictures/hdmon-41.png" alt="pywmhdmon">
|
|
||||||
<img src="pictures/hdmon-41-blue-yellow.png" alt="pywmhdmon">
|
|
||||||
<img src="pictures/hdmon-41-purple-black.png" alt="pywmhdmon">
|
|
||||||
<p>Pywmhdmon is a dockapp that monitors the free space of up to five of your
|
|
||||||
filesystems (per instance). the fifth line can be set to contain a little
|
|
||||||
bar that displays the current hard drive activity.</p>
|
|
||||||
<p>the configuration file can contain more than 5 entries, the '-s' option
|
|
||||||
is then used to skip the correct amount of entries in each activation of the
|
|
||||||
program.</p>
|
|
||||||
<p>Changes:</p>
|
|
||||||
<p class="newsdate">2006-10-12</p>
|
|
||||||
<p class="newstext">each mount point can be associated to an 'action'. this
|
|
||||||
action can be 'mount' or 'eject'. clicking on a mount point with action
|
|
||||||
'mount' will toggle mounting it. 'eject' is the same, but after unmounting,
|
|
||||||
ejection will be attempted.
|
|
||||||
<p class="newsdate">2004-07-15</p>
|
|
||||||
<p class="newstext">Added a patch from Mario Frasca (Thanks!) which prevents the app from showing
|
|
||||||
the data from the host file system if there is no filesystem mounted at the
|
|
||||||
given point.</p>
|
|
||||||
<p class="newsdate">2003-09-01</p>
|
|
||||||
<p class="newstext">Fixed a bug where the numbers weren't displayed if they were between 1000 and 1024.</p>
|
|
||||||
<p class="newsdate">2003-06-28</p>
|
|
||||||
<p class="newstext">Fixed a bug where a mouse click caused an infinite loop.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>pywmPhoto</h3>
|
|
||||||
<img src="pictures/pywmPhoto.png" alt="pywmPhoto">
|
|
||||||
<p>this program was born because I did not manage to get wmPhoto working on
|
|
||||||
my computer at work and because I wanted to document the process of starting
|
|
||||||
a completely new program using the wmdocklib library.
|
|
||||||
</p>
|
|
||||||
<p>pywmPhoto has not that much funcionality as wmPhoto: it just shows a
|
|
||||||
single static xpm, nothing more. there are limitations on the xpm that can
|
|
||||||
be shown: it may not use the ' ' (space) as a symbol for coding colours, it
|
|
||||||
must use one character to code each colour. use imagemagik's convert with
|
|
||||||
parameters: -depth 256 -colors 80, then make sure that the space is not
|
|
||||||
being used (it is necessary for transparency).</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Pywmseti</h3>
|
|
||||||
<img src="pictures/pywmseti.png" alt="pywmseti">
|
|
||||||
<p>Pywmseti is a dockapp that monitors your <a
|
|
||||||
href="http://setiathome.ssl.berkeley.edu/">SETI@home</a> progress. It displays
|
|
||||||
how many workunits you have done and the progress on the current one. You can
|
|
||||||
start and stop the current process by clicking anywhere within the window.</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Pywmsysmon</h3>
|
|
||||||
<img src="pictures/pywmsysmon.png" alt="pywmsysmon">
|
|
||||||
<p>Pywmsysmon is a dockapp that displays your current CPU and memory usage. It
|
|
||||||
has a graph displaying the history of the CPU usage and a bar to display the
|
|
||||||
current amount of memory in use.</p>
|
|
||||||
<p>Changes:</p>
|
|
||||||
<p class="newsdate">2003-06-28</p>
|
|
||||||
<p class="newstext">Fixed a bug where a mouse click caused an infinite loop.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Pywmgeneric</h3>
|
|
||||||
<img src="pictures/pywmgeneric.png" alt="pywmgeneric">
|
|
||||||
<img src="pictures/generic-defaults.png" alt="pywmgeneric">
|
|
||||||
<img src="pictures/generic-gray80-black.png" alt="pywmgeneric">
|
|
||||||
<p>Pywmgeneric is a dockapp that displays the first line of output from an
|
|
||||||
external program, the returned string from an python method or an static
|
|
||||||
string. Up to ten mouse actions can be associated with every displayed entry.
|
|
||||||
</p>
|
|
||||||
<p>Changes:</p>
|
|
||||||
<p class="newsdate">2003-07-02</p>
|
|
||||||
<p class="newstext">Support for up to ten mouse buttons added. Some additionaly
|
|
||||||
fine tuning.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>download</h3>
|
|
||||||
|
|
||||||
<p>all released files can be found <a
|
|
||||||
href="http://sourceforge.net/project/showfiles.php?group_id=147660">here</a>.</p>
|
|
||||||
|
|
||||||
<p>not yet released versions can be downloaded <a
|
|
||||||
href="http://sourceforge.net/cvs/?group_id=147660">through cvs</a>.</p>
|
|
||||||
|
|
||||||
<h3>Contact</h3>
|
|
||||||
<p>Is there anything you wonder about these programs? Any thoughts,
|
|
||||||
comments, suggestions, bug reports or anything else? Don't hesitate to
|
|
||||||
contact the developers of this project. have a look at <a
|
|
||||||
href="http://sourceforge.net/projects/pywmdockapps">the main page for this
|
|
||||||
project</a>.</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
body {
|
|
||||||
font-size: 12px; color: #000000; margin-left: 10%; margin-right: 10%;
|
|
||||||
background: #FFFFFF;
|
|
||||||
font-family: verdana, helvetica, arial, sans-serif;
|
|
||||||
}
|
|
||||||
body.blank {
|
|
||||||
font-size: 12px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
body.menu {
|
|
||||||
font-size: 12px; margin-top: 7px; margin-left: 10%; margin-right: 10%;
|
|
||||||
font-family: verdana, helvetica, arial, sans-serif;
|
|
||||||
}
|
|
||||||
form {
|
|
||||||
margin: 0px
|
|
||||||
}
|
|
||||||
body a:link {
|
|
||||||
color: #002090
|
|
||||||
}
|
|
||||||
body a:visited {
|
|
||||||
color: #002090
|
|
||||||
}
|
|
||||||
body a:hover {
|
|
||||||
color: #300020;
|
|
||||||
background-color: #c0f0f0;
|
|
||||||
}
|
|
||||||
body a.menu {
|
|
||||||
margin-right: 15px; text-decoration: none; font-size: 12px;
|
|
||||||
}
|
|
||||||
a.bm {
|
|
||||||
margin-left: 20px
|
|
||||||
}
|
|
||||||
td.name {
|
|
||||||
width: 80px
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.noblob {
|
|
||||||
list-style-type: none;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 20px;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-left: -15px;
|
|
||||||
font-family: verdana, helvetica, arial, sans-serif;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
font-size: 14px;
|
|
||||||
font-family: verdana, helvetica, arial, sans-serif;
|
|
||||||
margin: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.listitem {
|
|
||||||
width: 140px
|
|
||||||
}
|
|
||||||
|
|
||||||
p.newsdate {
|
|
||||||
margin-top: 12px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.newstext {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: 24px
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 372 B |
|
Before Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 753 B |
|
Before Width: | Height: | Size: 850 B |
|
Before Width: | Height: | Size: 745 B |
|
Before Width: | Height: | Size: 746 B |
|
Before Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 474 B |