Compare commits
1 Commits
cairo
...
checkmenui
| Author | SHA1 | Date | |
|---|---|---|---|
| 45dabcc3ed |
56
.gitignore
vendored
56
.gitignore
vendored
@@ -1,56 +0,0 @@
|
|||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
bin/
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
.tox/
|
|
||||||
.coverage
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
|
|
||||||
# Mr Developer
|
|
||||||
.mr.developer.cfg
|
|
||||||
.project
|
|
||||||
.pydevproject
|
|
||||||
|
|
||||||
# Rope
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
#deleted files
|
|
||||||
*~
|
|
||||||
|
|
||||||
# Temporary graph file
|
|
||||||
graph.png
|
|
||||||
200
pinger.py
Executable file → Normal file
200
pinger.py
Executable file → Normal file
@@ -1,11 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
#
|
||||||
# Pinger.py -- A ping tool that sits in your system tray
|
# Pinger.py -- A ping tool that sits in your system tray
|
||||||
# Copyright 2013 Will Bradley
|
# Copyright 2013 Will Bradley
|
||||||
#
|
#
|
||||||
# Contributors: Will Bradley <bradley.will@gmail.com>
|
# Authors: Will Bradley <bradley.will@gmail.com>
|
||||||
# AltF4 <altf4@phx2600.org>
|
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of either or both of the following licenses:
|
# under the terms of either or both of the following licenses:
|
||||||
@@ -26,6 +24,10 @@
|
|||||||
# <http://www.gnu.org/licenses/>
|
# <http://www.gnu.org/licenses/>
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# User-editable variables
|
||||||
|
host = "4.2.2.2" # IP or hostname
|
||||||
|
ping_frequency = 5 # in seconds
|
||||||
|
|
||||||
#
|
#
|
||||||
# Dependencies
|
# Dependencies
|
||||||
#
|
#
|
||||||
@@ -43,88 +45,19 @@ import re
|
|||||||
import signal
|
import signal
|
||||||
# File paths
|
# File paths
|
||||||
import os
|
import os
|
||||||
# Argument parsing
|
|
||||||
import argparse
|
|
||||||
# For exit
|
|
||||||
import sys
|
|
||||||
# For graphing
|
|
||||||
import cairo
|
|
||||||
|
|
||||||
# Vars
|
# Vars
|
||||||
startup_active_label = "✓ Start Automatically"
|
startup_label = "Start Automatically"
|
||||||
startup_inactive_label = "Start Automatically"
|
|
||||||
pause_label = "Pause"
|
|
||||||
play_label = "Resume"
|
|
||||||
home_path = os.path.expanduser("~")
|
home_path = os.path.expanduser("~")
|
||||||
startup_path = home_path+'/.config/autostart/pinger.desktop'
|
startup_path = home_path+'/.config/autostart/pinger.desktop'
|
||||||
startup_dir = home_path+'/.config/autostart/'
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("-t", "--target", help="Target to PING against. (IP / Hostname / Domain name). Defaults to 4.2.2.2")
|
|
||||||
parser.add_argument("-f", "--freq", help="Timeout between pings, in seconds. Defaults to 5")
|
|
||||||
parser.add_argument("-m", "--maxlog", help="Maximum amount of pings to log. Defaults to 40")
|
|
||||||
parser.add_argument("-c", "--color", help="Color scheme ('dark' or 'light'). Defaults to dark.")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
ubuntu_mono_dark_rgba = [0xdf, 0xd8, 0xc8, 0xff]
|
|
||||||
ubuntu_mono_light_rgba = [0x3a, 0x39, 0x35, 0xff]
|
|
||||||
black = [0, 0, 0, 0xff]
|
|
||||||
red = [0xff, 0, 0, 0xff]
|
|
||||||
white = [0xff, 0xff, 0xff, 0xff]
|
|
||||||
dark_bg = [0, 0, 0, 0x3f]
|
|
||||||
light_bg = [0xff, 0xff, 0xff, 0x3f]
|
|
||||||
|
|
||||||
#accumulate the arguments for use later
|
|
||||||
arguments = " "
|
|
||||||
for arg in sys.argv[1:]:
|
|
||||||
arguments += arg + " "
|
|
||||||
|
|
||||||
# User-editable variables
|
|
||||||
if args.target:
|
|
||||||
host = args.target
|
|
||||||
else:
|
|
||||||
host = "4.2.2.2" # IP or hostname
|
|
||||||
print "Using default target IP of 4.2.2.2"
|
|
||||||
|
|
||||||
if args.freq:
|
|
||||||
try:
|
|
||||||
ping_frequency = int(args.freq)
|
|
||||||
except ValueError:
|
|
||||||
sys.stderr.write("Error parsing argument '--freq'\n")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
ping_frequency = 5 # in seconds
|
|
||||||
|
|
||||||
if args.maxlog:
|
|
||||||
try:
|
|
||||||
ping_log_max_size = int(args.maxlog)
|
|
||||||
except ValueError:
|
|
||||||
sys.stderr.write("Error parsing argument '--maxlog'\n")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
ping_log_max_size = 40
|
|
||||||
|
|
||||||
if args.color == "light":
|
|
||||||
graph_color = ubuntu_mono_light_rgba
|
|
||||||
graph_highlight = ubuntu_mono_dark_rgba
|
|
||||||
graph_background = light_bg
|
|
||||||
else:
|
|
||||||
graph_color = ubuntu_mono_dark_rgba
|
|
||||||
graph_highlight = ubuntu_mono_light_rgba
|
|
||||||
graph_background = dark_bg
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Main Class
|
# Main Class
|
||||||
#
|
#
|
||||||
|
|
||||||
class Pinger:
|
class Pinger:
|
||||||
ping_log = []
|
|
||||||
paused = False
|
|
||||||
autostart = False
|
|
||||||
icon_height = 22
|
|
||||||
|
|
||||||
def ping(self, widget=None, data=None):
|
def ping(self, widget=None, data=None):
|
||||||
if not self.paused:
|
|
||||||
ping = subprocess.Popen(
|
ping = subprocess.Popen(
|
||||||
["ping", "-c", "1", host],
|
["ping", "-c", "1", host],
|
||||||
stdout = subprocess.PIPE,
|
stdout = subprocess.PIPE,
|
||||||
@@ -134,26 +67,19 @@ class Pinger:
|
|||||||
m = re.search('time=(.*) ms', out)
|
m = re.search('time=(.*) ms', out)
|
||||||
if error or m == None:
|
if error or m == None:
|
||||||
label = "PING FAIL"
|
label = "PING FAIL"
|
||||||
self.log_ping(-1)
|
|
||||||
else:
|
else:
|
||||||
latency = "%.2f" % float(m.group(1))
|
label = m.group(1)+" ms"
|
||||||
label = latency+" ms"
|
self.ind.set_label (label, "100.0 ms")
|
||||||
self.log_ping(latency)
|
#self.ping_menu_item.set_label(out)
|
||||||
#self.ind.set_label(label, "100.0 ms")
|
|
||||||
gobject.timeout_add_seconds(self.timeout, self.ping)
|
gobject.timeout_add_seconds(self.timeout, self.ping)
|
||||||
|
|
||||||
def log_ping(self, value):
|
def create_menu_item(self, menu_type, text, callback):
|
||||||
self.ping_log.append(float(value))
|
if menu_type == "check":
|
||||||
self.update_log_menu()
|
menu_item = Gtk.CheckMenuItem(text)
|
||||||
# limit the size of the log
|
menu_item.set_active(True)
|
||||||
if len(self.ping_log) >= ping_log_max_size:
|
else:
|
||||||
# remove the earliest ping, not the latest
|
|
||||||
self.ping_log.pop(0)
|
|
||||||
|
|
||||||
def create_menu_item(self, text, callback):
|
|
||||||
menu_item = Gtk.MenuItem(text)
|
menu_item = Gtk.MenuItem(text)
|
||||||
self.menu.append(menu_item)
|
self.menu.append(menu_item)
|
||||||
if callback:
|
|
||||||
menu_item.connect("activate", callback, text)
|
menu_item.connect("activate", callback, text)
|
||||||
menu_item.show()
|
menu_item.show()
|
||||||
return menu_item
|
return menu_item
|
||||||
@@ -162,78 +88,27 @@ class Pinger:
|
|||||||
print "Quitting..."
|
print "Quitting..."
|
||||||
Gtk.main_quit()
|
Gtk.main_quit()
|
||||||
|
|
||||||
def toggle_autostart(self, widget, data=None):
|
def create_autostart(self, widget, data=None):
|
||||||
if not self.autostart:
|
|
||||||
if not os.path.exists(startup_dir):
|
|
||||||
os.makedirs(startup_dir)
|
|
||||||
with open(startup_path,'w') as f:
|
with open(startup_path,'w') as f:
|
||||||
f.write("[Desktop Entry]\r\n"
|
f.write("[Desktop Entry]\r\n"
|
||||||
"Type=Application\r\n"
|
"Type=Application\r\n"
|
||||||
"Exec=python "+os.path.abspath( __file__ )+arguments+"\r\n"
|
"Exec=python "+os.path.abspath( __file__ )+"\r\n"
|
||||||
"X-GNOME-Autostart-enabled=true\r\n"
|
"X-GNOME-Autostart-enabled=true\r\n"
|
||||||
"Name=Pinger\r\n"
|
"Name=Pinger\r\n"
|
||||||
"Comment=Pings the internet every few seconds")
|
"Comment=Pings the internet every few seconds")
|
||||||
self.autostart = True
|
self.update_startup_menu()
|
||||||
self.startup_menu.set_label(startup_active_label)
|
|
||||||
else:
|
def remove_autostart(self, widget, data=None):
|
||||||
os.remove(startup_path)
|
os.remove(startup_path)
|
||||||
self.autostart = False
|
self.update_startup_menu()
|
||||||
self.startup_menu.set_label(startup_inactive_label)
|
|
||||||
|
|
||||||
def toggle_pause(self, widget, data=None):
|
def update_startup_menu(self):
|
||||||
if self.paused:
|
if os.path.exists(startup_path):
|
||||||
self.paused = False
|
self.startup_menu.connect("activate", self.remove_autostart, startup_label)
|
||||||
self.pause_menu.set_label(pause_label)
|
self.startup_menu.set_active(False)
|
||||||
else:
|
else:
|
||||||
self.paused = True
|
self.startup_menu.connect("activate", self.create_autostart, startup_label)
|
||||||
self.pause_menu.set_label(play_label)
|
self.startup_menu.set_active(True)
|
||||||
|
|
||||||
def update_log_menu(self):
|
|
||||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, ping_log_max_size, self.icon_height)
|
|
||||||
ctx = cairo.Context(surface)
|
|
||||||
|
|
||||||
# draw semitransparent box
|
|
||||||
self.draw_rect( ctx, [0,0], [ping_log_max_size,self.icon_height], graph_background )
|
|
||||||
|
|
||||||
if(max(self.ping_log) < 100):
|
|
||||||
max_ping = 100
|
|
||||||
else:
|
|
||||||
max_ping = max(self.ping_log)
|
|
||||||
|
|
||||||
for index, ping in enumerate(self.ping_log):
|
|
||||||
|
|
||||||
if float(ping) == -1: # Ping error
|
|
||||||
# Draw full-height error bar
|
|
||||||
self.draw_rect( ctx, [index,self.icon_height], [1,-self.icon_height-1], red )
|
|
||||||
else:
|
|
||||||
# draw normal bar
|
|
||||||
bar_height = -int(self.scale(ping, (0,max_ping), (0,self.icon_height)))
|
|
||||||
|
|
||||||
if bar_height > -1:
|
|
||||||
bar_height = -1
|
|
||||||
|
|
||||||
self.draw_rect( ctx, [index,self.icon_height], [1,bar_height], graph_color )
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.remove("/tmp/graph.png")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
surface.write_to_png("/tmp/graph.png")
|
|
||||||
self.ind.set_icon("") # gotta set it to nothing in order to update
|
|
||||||
self.ind.set_icon("graph")
|
|
||||||
self.ping_menu.set_label("Ping: "+str(self.ping_log[-1])+" ms")
|
|
||||||
|
|
||||||
def draw_rect(self, ctx, point, size, rgba):
|
|
||||||
ctx.rectangle( point[0], point[1], size[0], size[1] )
|
|
||||||
ctx.set_source_rgba(rgba[0]/float(255), rgba[1]/float(255), rgba[2]/float(255), rgba[3]/float(255))
|
|
||||||
ctx.fill()
|
|
||||||
|
|
||||||
def scale(self, val, src, dst):
|
|
||||||
"""
|
|
||||||
Scale the given value from the scale of src to the scale of dst.
|
|
||||||
"""
|
|
||||||
scale = ((val - src[0]) / (src[1]-src[0])) * (dst[1]-dst[0]) + dst[0]
|
|
||||||
return scale
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Handle ctrl-c
|
# Handle ctrl-c
|
||||||
@@ -246,27 +121,16 @@ class Pinger:
|
|||||||
self.ind = appindicator.Indicator.new (
|
self.ind = appindicator.Indicator.new (
|
||||||
"pinger",
|
"pinger",
|
||||||
"", # no icon
|
"", # no icon
|
||||||
appindicator.IndicatorCategory.SYSTEM_SERVICES)
|
appindicator.IndicatorCategory.COMMUNICATIONS)
|
||||||
self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)
|
self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)
|
||||||
#self.ind.set_label ("Pinger Loading...", "Pinger Loading...")
|
self.ind.set_label ("Pinger Loading...", "Pinger Loading...")
|
||||||
self.ind.set_icon_theme_path("/tmp")
|
|
||||||
|
|
||||||
# create a menu
|
# create a menu
|
||||||
self.menu = Gtk.Menu()
|
self.menu = Gtk.Menu()
|
||||||
# with ping numbers
|
|
||||||
self.ping_menu = self.create_menu_item("", None)
|
self.startup_menu = self.create_menu_item("check",startup_label, self.remove_autostart)
|
||||||
# with pause option
|
#self.update_startup_menu()
|
||||||
self.pause_menu = self.create_menu_item(pause_label, self.toggle_pause)
|
self.create_menu_item(None, "Exit", self.destroy)
|
||||||
# with autostart option
|
|
||||||
# first, check current autostart state by checking existance of .desktop file
|
|
||||||
if os.path.exists(startup_path):
|
|
||||||
self.autostart = True
|
|
||||||
self.startup_menu = self.create_menu_item(startup_active_label, self.toggle_autostart)
|
|
||||||
else:
|
|
||||||
self.autostart = False
|
|
||||||
self.startup_menu = self.create_menu_item(startup_inactive_label, self.toggle_autostart)
|
|
||||||
# and exit option
|
|
||||||
self.create_menu_item("Exit", self.destroy)
|
|
||||||
self.ind.set_menu(self.menu)
|
self.ind.set_menu(self.menu)
|
||||||
|
|
||||||
# start the ping process
|
# start the ping process
|
||||||
|
|||||||
Reference in New Issue
Block a user