Page 1 of 9
simple icon tray
Posted: Thu 01 Mar 2012, 22:13
by technosaurus
I just finished my simple icon tray tool that will allow unlimited number of trayicons with user defined icons,refresh intervals, left and right click actions. all you have to do to update icons is change a symlink and popups can be anything you want (including a gtkdialog script)
This will allow a single tray applet to do as many functions as you would like, network monitor, temperature monitor, volume control, load, battery, clipboard, ... pretty much anything you can dump into an icon. This means less resource usage than running multiple tray applets.
here is a template for using it:
Code: Select all
sit 1000 /usr/share/mini-icons/mini-dog.xpm "sit test" "dogleftclick" "dogrightclick" \
1000 /usr/share/mini-icons/mini-cd.xpm "sit test" "cdleftclick" "cdrightclick" \
2>/dev/null | \
while read LINE; do
case "$LINE" in
#statusicon specific actions here based on its left/right click action
*)Xdialog --under-mouse --infobox "action=$LINE" 0 0 &
;;
esac
done
Posted: Fri 02 Mar 2012, 01:46
by technosaurus
Here is the beginning of the applet suite - a drive tray for the tray
Code: Select all
#!/bin/sh
#move these to an rc file for easier config and just source it
ICONPATH="/usr/share/midi-icons"
DRIVES="1"
BATTERY=""
CPUTEMP="1"
CPULOAD=""
NETWORK=""
cputemp(){
for x in /proc/acpi/thermal_zone/*; do
ZONE=${x##*/}
awk '{BG = "#00FF00"
if ($2 > 65) BG = "#FFFF00"
if ($2 > 80) BG = "#FF0000"
printf "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"> \
<rect width=\"32\" height=\"22\" x=\"0\" y=\"0\" \
style=\"font-size:%d;fill:%s;fill-opacity:0.75;fill-rule:evenodd;stroke-width:3pt;\" id=\"rect1\" /> \
<text x=\"0\" y=\"18\" style=\"font-size:%d;font-weight:normal;fill-opacity:0.75;stroke-width:3pt;font-family:helvetica;\" id=\"text1\"> \
<tspan id=\"tspan1\">%d°C</tspan> \
</text> \
</svg>",14,BG,14,$2}' /proc/acpi/thermal_zone/$ZONE/temperature >/tmp/sit/$ZONE.svg
done
}
mkdir /tmp/sit 2>/dev/null
SITICONS="sit"
[ "$DRIVES" ] && for UEVENT in /sys/dev/block/*/uevent ; do
. $UEVENT
case "${DEVNAME}" in
sd*|hd*) REMOVABLE="0" NOTSWAP="1" LOGICAL=1
[ -e ${UEVENT//uevent/"../removable"} ] && read REMOVABLE <${UEVENT//uevent/"../removable"}
[ $REMOVABLE = 1 ] && ICON=usbdrv48.png || ICON=drive48.png #possibly have something here for devicehandler?
#logical partitions have a size of 2
read LOGICAL <${UEVENT//uevent/size}
LINE=""
while read LINE || [ "$LINE" ]; do
case $LINE in
"/dev/"$DEVNAME*)NOTSWAP=""
esac
done < /proc/swaps
[ ${DEVTYPE} = "partition" ] && [ $NOTSWAP ] && [ ! $LOGICAL = 2 ] && {
[ -d /mnt/$DEVNAME ] && ICON=${ICON/48/_mntd48}
ln -sf ${ICONPATH}/${ICON} /tmp/sit/${DEVNAME}.png 2>/dev/null
SITICONS=${SITICONS}' 1000 "'/tmp/sit/${DEVNAME}.png'" "'${DEVNAME}'" "'mount=${DEVNAME}'" "'umount=${DEVNAME}'" '
}
;;
mm*) [ ${DEVTYPE} = "partition" ] && {
[ -d /mnt/$DEVNAME ] && ICON=card_mntd48.png || ICON=card48.png
ln -sf ${ICONPATH}/${ICON} /tmp/sit/${DEVNAME}.png 2>/dev/null
SITICONS=${SITICONS}' 1000 "'/tmp/sit/${DEVNAME}.png'" "'${DEVNAME}'" "'mount=${DEVNAME}'" "'umount=${DEVNAME}'" '
}
;;
sr*)[ -d /mnt/$DEVNAME ] && ICON=optical_mntd48.png || ICON=optical48.png
ln -sf ${ICONPATH}/${ICON} /tmp/sit/${DEVNAME}.png 2>/dev/null
SITICONS=${SITICONS}' 1000 "'/tmp/sit/${DEVNAME}.png'" "'${DEVNAME}'" "'mount=${DEVNAME}'" "'umount=${DEVNAME}'" '
;;
fd*)[ -d /mnt/$DEVNAME ] && ICON=floppy_mntd48.png || ICON=floppy48.png
ln -sf ${ICONPATH}/${ICON} /tmp/sit/${DEVNAME}.png 2>/dev/null
SITICONS=${SITICONS}' 1000 "'/tmp/sit/${DEVNAME}.png'" "'${DEVNAME}'" "'mount=${DEVNAME}'" "'umount=${DEVNAME}'" '
;;
esac
done
if [ "$CPUTEMP" ];then
cputemp
for x in /proc/acpi/thermal_zone/*; do
ZONE=${x##*/}
SITICONS=${SITICONS}' 5000 "'/tmp/sit/$ZONE.svg'" "'$ZONE'" "'leftclick=$ZONE'" "'rightclick=$ZONE'" '
done
fi
eval "$SITICONS" |while read LINE; do
case "$LINE" in
mount=*)
eval $LINE
if [ ! -d /mnt/$mount ]; then
mkdir /mnt/$mount
busybox mount /dev/$mount /mnt/$mount
ln -sf `readlink /tmp/sit/$mount.png |sed "s/48/_mntd48/"` /tmp/sit/$mount.png
else
rox /mnt/$mount
fi
;;
umount=*)eval $LINE
busybox umount /dev/$umount && \
rmdir /mnt/$umount && \
ln -sf `readlink /tmp/sit/$umount.png |sed "s/_mntd48/48/"` /tmp/sit/$umount.png || \
xmessage error unmounting $umount
;;
*)echo $LINE unused >/dev/stderr
esac
done &
while :; do
sleep 1
[ "$CPUTEMP" ] && cputemp
done
TODO - use awk for the following:
this gives %memused
Code: Select all
awk '/MemTot/{tot = $2} /MemFree/{free = $2; printf "%.0f\n", 100*(1-(free/tot)) " " sum}' /proc/meminfo
battery
/proc/acpi/battery/*/{info,state}
charging/discharging/charged/remaining capacity ...
temperature
/proc/acpi/temperature/*/{trip_points,temperature}
volume
/proc/asound/card0/oss_mixer
webcam
capture image with ffmpeg
network
/proc/net/dev (compare tx and rx with last value)
icon from url
(use wget/other to get file/updates/mail/news... and update icon accordingly)
Posted: Fri 02 Mar 2012, 10:18
by snayak
Dear technosaurus,
It is an excellent try.
I fought a whole day lot to get my CPU temperature on my desktop.
I had to tweak Pwidgets.
Actually, I was looking for something similar to this.
I have an idea. Hope, I'll discuss it in Idea discussion sub-forum.
http://www.murga-linux.com/puppy/viewtopic.php?t=76451
Sincerely,
Srinivas Nayak
Posted: Fri 02 Mar 2012, 11:27
by SFR
@technosaurus:
This is what I've been waiting for.
I've combined your "sit" with my "
SIT", and everything works flawlessly at last.
Just one question:
In your build-script's test routine there's presented a way to get actions when clicking tray icon.
In my script I haven't got click actions handled (no need to); there's refreshing loop instead.
But, for future reference, how to combine both of them (in one script)?
Thanks for the good job and...
Greetings!
Posted: Fri 02 Mar 2012, 16:54
by technosaurus
this is currently a developer tool not an application (though I may provide some examples that actually get used, I prefer to mentor other devs in building the things that prompted me to start this in the first place)
My intent is to provide something simple yet robust that will allow us to build a sort of "pwidgets for the tray ". When/if we get enough applets those will be released as a separate package(s)
Note: If you are having issues with svg, it may be your gtk toolchain
Here is a template for an svg battery (or whatever)
Code: Select all
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.0"
x="0"
y="0"
width="12"
height="24"
id="svg1">
<rect
width="12"
height="24.0000000"
rx="6"
ry="3"
x="0"
y="0"
style="font-size:12;opacity:0.5;fill-opacity:0.999999;fill-rule:evenodd;stroke-width:3pt;"
id="rect1" />
<rect
width="12"
height="12.0000000"
rx="6"
ry="3"
x="0"
y="12"
style="font-size:12;opacity:0.5;fill:#00ff00;fill-opacity:0.999999;fill-rule:evenodd;stroke-width:3pt;"
id="rect2" />
</svg>
Posted: Mon 05 Mar 2012, 22:19
by seaside
technosaurus,
I just checked this out. What a clever and concise job you've done!
Now the tray can be used for just about anything - generate an icon on the fly - throw it into the tray with left/right click options and have the icons update dynamically by changing links. Very nice.
Tried it in Racy522 and all went perfectly - in Pup431, the SITICONS variable was not set (I guess the structure is somewhat different).
For those with gtk's greater than 2.16 who want to use text in their icons, your program "text2xpm" will do the job instead of using an .svg file.
Great job and thanks,
s
(I guess the .pupevent directory would have to be monitored for newly inserted or removed usb drives as well)
Posted: Tue 06 Mar 2012, 14:07
by technosaurus
seaside wrote:(I guess the .pupevent directory would have to be monitored for newly inserted or removed usb drives as well)
It was just an example anyways; however, the daemon process could monitor /var/log/messages for *usb-storage: device scan complete* and simply restart
Posted: Wed 11 Apr 2012, 16:10
by technosaurus
Another great part about using svg, is that you can embed other images (png etc...) and overlay shapes, text, lines etc...
Here is an example using the default drive icon in Wary:
Code: Select all
<svg version="1.0" x="0" y="0" width="48" height="48" id="svg1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="/usr/share/midi-icons/drive48.png"
width="48" height="48" style="font-size:12;" id="image1" />
<ellipse cx="24" cy="22" rx="10" ry="6" style="fill:yellow"/>
</svg>
As you can see it draws a yellow ellipse over the top of the image, but it is not limited to simple circles, you can overlay pretty much any svg element. This is useful for identifying a status (mounted/unmounted/unformatted/...) or to have additional information embedded in a small area (better use of screen space for tablets/netbooks)
Posted: Wed 11 Apr 2012, 21:06
by technosaurus
part 2 of svg icons - using a radial gradient
Code: Select all
<svg width="48" height="48" id="svg1" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs id="defs1">
<linearGradient id="LG1">
<stop style="stop-color:#ffffff;stop-opacity:1;" id="stop1"/>
<stop style="stop-color:#ffff00;stop-opacity:1;" offset="1" id="stop2"/>
</linearGradient>
<radialGradient xlink:href="#LG1" id="RG1" cx="0.5" cy="0.5" r="0.5" fx="0.5" fy="0.5"/>
</defs>
<image xlink:href="/usr/share/midi-icons/drive48.png" width="48" height="48" id="image1"/>
<ellipse cx="24" cy="22" rx="10" ry="6" style="fill:url(#RG1);" id="ellipse1"/>
</svg>
Posted: Thu 12 Apr 2012, 05:36
by technosaurus
part 3 svg icons with embedded text and shapes with gradients
Code: Select all
<svg width="48" height="48" id="svg1" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs id="defs1">
<linearGradient id="LG1">
<stop style="stop-color:#ffff00;stop-opacity:1;" id="stop1"/>
<stop style="stop-color:#cccccc;stop-opacity:1;" offset="1" id="stop2"/>
</linearGradient>
<radialGradient xlink:href="#LG1" id="RG1" cx="0.5" cy="0.5" r="0.5" fx="0.5" fy="0.5"/>
</defs>
<image xlink:href="/usr/share/midi-icons/drive48.png" width="48" height="48" id="image1"/>
<ellipse cx="24" cy="22" rx="10" ry="6" style="fill:url(#RG1);" id="ellipse1"/>
<text style="fill:red;" x="12" y="26" id="text1">sda1</text>
</svg>
Posted: Fri 13 Apr 2012, 23:57
by seaside
technosaurus,
Thanks for the tips on overlaying.
It prompted me to see if I could get some text into a svg with a Gttk higher than 2.16 and apparently it works when using the entire inkscape coding . (Perhaps not all needed, but I'm not sure what isn't)
Here's a stock-ticker using sit. (Left-Click to edit stocks and Right-click to stop)
Code: Select all
#!/bin/sh -a
# stock ticker- seaside April 14, 2012
# stock retrieval ideas from technosaurus
symlist="/root/.stocklist"
# set sample stock info
[[ ! -f $symlist ]] && echo 'ibm
dis
goog ' >$symlist
sit 1000 /tmp/stockicon.svg "Stock-Ticker" "EDIT" "STOP" 2>/dev/null | \
while read ITEM; do
case "$ITEM" in
EDIT)geany "$symlist" & ;;
STOP) ps | grep stock | grep -v grep | awk '{print $1}'|xargs kill ;;
esac
done &
LINE=1
while true; do
STK=`sed -n "${LINE}p" $symlist`
[ "$STK" = "" ] && LINE=1 && STK=`sed -n "${LINE}p" $symlist` #ran out of lines
QUOTE=`wget -q -O - "http://download.finance.yahoo.com/d/quotes.csv?f=sb3c1&s=$STK"`
#returns "IBM",180.27,-1.77
oldIFS=$IFS
IFS=","
read STOCK BID CHANGE<<<"$QUOTE"
IFS=$oldIFS
STOCK="${STOCK//\"/}"
STOCK="${STOCK:0:4}"
BID="${BID:0:6}"
case $CHANGE in
-*) BG=#FF6F55 ;; #light red
+*) BG=#90EE90 ;; #light green
*) BG=#C7E7F1 ;; #light blue
esac
# technosaurus' use of svg for icons
echo '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Created with Inkscape ("http://www.inkscape.org/") -->
<svg
id="svg1"
sodipodi:version="0.32"
inkscape:version="0.36"
width="64"
height="64"
sodipodi:docname="/tmp/stockicon.svg"
sodipodi:docbase="/tmp"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs
id="defs8" />
<sodipodi:namedview
id="base" />
<rect
width="64"
height="64"
x="0.150467"
y="0.257804"
style="fill:'"$BG"'"
id="rect2" />
<text
x="-0.02790701"
y="23.8785315"
style="font-size:32;font-family:Nimbus Mono L;font-weight:bold;font-style:normal;text-anchor:start;writing-mode:lr;"
id="text3"
transform="scale(0.893866,1.000000)"
sodipodi:linespacing="100%">
<tspan
x="-0.02790701"
y="23.8785324"
sodipodi:role="line"
id="tspan11">'"$STOCK"'</tspan>
</text>
<text
x="0.70210701"
y="43.4028667"
style="font-size:20;font-family:Nimbus Mono L;font-weight:bold;font-style:normal;text-anchor:start;writing-mode:lr;"
id="text5"
transform="scale(0.861163,1.371361)"
sodipodi:linespacing="100%">
<tspan
x="0.70210701"
y="43.4028664"
sodipodi:role="line"
id="tspan13">'"$BID"'</tspan>
</text>
</svg>
' >/tmp/stockicon-new.svg
cp /tmp/stockicon-new.svg /tmp/stockicon.svg
LINE=$[LINE+1]
sleep 3 # Wait before checking again.
done
EDITED: April 14, 2012 improved
Regards,
s
Posted: Sat 14 Apr 2012, 02:09
by ka9qlq
IS there a step by step guide to get this up and running with Lucid 5.28?
Posted: Sat 14 Apr 2012, 03:06
by technosaurus
@seaside - cool - the stripped down svgs I posted worked in an older wary with gtk 2.20 so it seemed safe - glad to see it being used
@ ka9qlq - like much of my work, right now it is _just_ a developer tool with some "examples" to help get new developers started building tray applets ... I _could_ write them myself, but I would much rather mentor others that want to learn how to write actual programs ... yeah it takes more of my time to debug someone else's code, but it is more rewarding for me to witness a transition from newbie to intermediate to advanced to master programmer. too many people who could have been code contributors, give up because they just get a bunch of useless "hello world" garbage. What kind of tray applet did you want to have up and running?
Posted: Sat 14 Apr 2012, 04:21
by zigbert
technosaurus
This WILL be helpful one day. - That is for sure.
Thank you!
Sigmund
Posted: Sat 14 Apr 2012, 05:10
by ka9qlq
I'd like to know my cpu speed/temp/%use sounds like I should just install gkrellm
Posted: Sat 14 Apr 2012, 05:16
by jamesbond
This is good stuff, archived for future use ...
Posted: Sun 15 Apr 2012, 04:00
by seaside
technosaurus wrote:@seaside - cool - the stripped down svgs I posted worked in an older wary with gtk 2.20 so it seemed safe - glad to see it being used
technosaurus,
Probably not too useful with sit being killed each time before a new icon was shown. So I changed the stock-ticker to update by copying over the new icon instead and added a right-click stop.
Regards,
s
Posted: Mon 04 Jun 2012, 02:29
by technosaurus
OK, I think I have inotify figured out - pretty simple really and would eliminate the need for update times. Can any C coders check this before I try and merge it into a callback? I am thinking it may be more straight forward to do this per file instead of per directory though.
usage:
myinotifyd /monitor/this/directory
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
int main(int argc, char** argv)
{
int length, i, fd, watch;
char buffer[EVENT_BUF_LEN];
fd = inotify_init();
if ( fd < 0 ) perror( "inotify init failed" );
/* check if argv[1] is a directory */
watch = inotify_add_watch( fd, argv[1], IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO | IN_ATTRIB );
while (1){
i=0;
length = read( fd, buffer, EVENT_BUF_LEN );
if ( length < 0 ) perror( "reading inotify fd" );
while ( i < length ) {
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len ) {
if (event->mask & IN_ATTRIB)printf("%s Metadata changed\n",event->name);
if (event->mask & IN_CREATE)printf("%s created in watched directory\n",event->name);
if (event->mask & IN_DELETE)printf("%s deleted from watched directory\n",event->name);
if (event->mask & IN_MODIFY)printf("%s was modified\n",event->name);
if (event->mask & IN_MOVED_FROM)printf("%s moved out of watched directory\n",event->name);
if (event->mask & IN_MOVED_TO)printf("%s moved into watched directory\n",event->name);
}
i += EVENT_SIZE + event->len;
}
}
inotify_rm_watch( fd, watch );
close( fd );
}
Posted: Tue 12 Jun 2012, 02:17
by technosaurus
so here it is - figured out how to make it update only when a file changes using some pretty hacky inotify and builtin gdk ops. I am going to call this one sit2 since it is significantly different in that it no longer uses a refresh time at all and now executes the right and left click commands directly (no need to keep a shell open to pipe the output through)
Code: Select all
#include <sys/inotify.h>
#include <gtk/gtk.h>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
void leftclick(GtkStatusIcon *si, gpointer s){popen(s,"r");} /* exec s */
void rightclick(GtkStatusIcon *si, guint b,guint a_t, gpointer s){popen(s,"r");}
void refresh(gpointer si, gint fd, GdkInputCondition c){ char buffer[EVENT_BUF_LEN];
read( fd, buffer, EVENT_BUF_LEN ); /* we are just clearing it & don't care what event type */
gtk_status_icon_set_from_file(si,gtk_status_icon_get_title(si));} /* redraws */
int main(int argc, char *argv[]){ GtkStatusIcon *si; int i=1, watch, fd;
gtk_init (&argc, &argv); /* loop through icon, tooltip, click messages */
while (i<argc) { fd = inotify_init(); /* get file descriptor to write on if image changes */
si = gtk_status_icon_new_from_file(argv[i]); /* get a status icon widget */
gtk_status_icon_set_title(si,argv[i]); /* hack to store the image path */
watch = inotify_add_watch( fd, argv[i++], IN_CREATE | IN_MODIFY | IN_MOVED_FROM );
gdk_input_add( fd, GDK_INPUT_READ, refresh, si ); /* inotify fd is ready for reading, refresh */
gtk_status_icon_set_tooltip_text(si,argv[i++]);
g_signal_connect(G_OBJECT(si), "activate", G_CALLBACK(leftclick),(gpointer) argv[i++]);
g_signal_connect(G_OBJECT(si), "popup-menu", G_CALLBACK(rightclick), (gpointer) argv[i++]);}
gtk_main ();}
Posted: Wed 13 Jun 2012, 20:01
by seaside
technosaurus,
jJust tried it out and everything works nicely. Thanks.
I was wondering if it were possible to extend the inotify aspect to include monitoring for usb drive additions and removals.
Regards,
s