commit 76ecb92ecd16500199c404ad7805836b0f5a888a Author: daoo Date: Sat Aug 7 20:53:09 2010 +0200 Initial commit diff --git a/README b/README new file mode 100644 index 0000000..eb5cfc9 --- /dev/null +++ b/README @@ -0,0 +1,15 @@ +conkygraph is a lua script for drawing graphs in conky using cairo. + +REQUIREMENTS: + * conky + * lua + * lua-cairo + * lua-json + * lua-lfs (lua-filesystem) + +USAGE: +1. Create a (or use a existing) file containing data about the graphs in json format. +2. Add the following to your conkyrc: + lua_load /path/to/conkygraph.lua + lua_startup_hook load_graphs /path/to/graphs_data.json + lua_draw_hook_pre draw_graphs diff --git a/conkygraph.lua b/conkygraph.lua new file mode 100644 index 0000000..f5cde8b --- /dev/null +++ b/conkygraph.lua @@ -0,0 +1,210 @@ +-- This work is licensed under the Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + +function antialias( cr, antialias ) + require( "cairo" ) + + if antialias then + cairo_set_antialias( cr, CAIRO_ANTIALIAS_DEFAULT ) + else + cairo_set_antialias( cr, CAIRO_ANTIALIAS_NONE ) + end +end + +function rgb_to_r_g_b( color, alpha ) + local c = tonumber( "0x" .. color ) + + return ( ( c / 0x10000 ) % 0x100 ) / 255.0, ( ( c / 0x100 ) % 0x100 ) / 255.0, ( c % 0x100 ) / 255.0, alpha +end + +function cairo_graph( cr, x, y, width, height, f ) + require( "cairo" ) + + local function value_to_y( height, value ) + if height ~= nil and value ~= nil then + return height * ( 1 - value ) + end + + return 0 + end + + if f.data ~= nil and #f.data > 0 then + local x2 = x + width + local nx = x2 + + cairo_move_to( cr, x2, y + value_to_y( height, f.data[1] ) ) + + -- Drawn from right to left + local curve_to = cairo_line_to + for i, v in pairs( f.data ) do + nx = nx - f.dx + + if nx >= x then + curve_to( cr, nx, y + value_to_y( height, v ) ) + else + break + end + end + + antialias( cr, f.antialias ) + cairo_set_source_rgba( cr, rgb_to_r_g_b( f.stroke_color, 1 ) ) + cairo_set_line_width( cr, f.stroke_width ) + + if f.fill then + cairo_stroke_preserve( cr ) + + cairo_line_to( cr, nx, y + height ) + cairo_line_to( cr, x2, y + height ) + cairo_close_path( cr ) + cairo_set_source_rgba( cr, rgb_to_r_g_b( f.fill_color, f.fill_alpha ) ) + cairo_fill( cr ) + else + cairo_stroke( cr ) + end + end +end +------------------------------------------------------------------------------------------------------------------------ +function draw_graph( cr, x, y, width, height, graph ) + if conky_window == nil or graph == nil then + return + end + + local function push( t, v, c ) + while #t > c do + table.remove( t, #t ) + end + + table.insert( t, 1, v ) + end + + -- Find margins, sizes and positions + local x_outer = tonumber( x ) + conky_window.text_start_x + local y_outer = tonumber( y ) + conky_window.text_start_y + + local w_outer = tonumber( width ) + if w_outer == 0 then + w_outer = conky_window.text_width - x + end + local h_outer = tonumber( height ) + if h_outer == 0 then + h_outer = conky_window.text_height - y + end + + local x_inner = x_outer + local y_inner = y_inner + local w_inner = w_outer + local h_inner = h_outer + if graph.outline then + local o = graph.outline_width + x_inner = x_outer + o + y_inner = y_outer + o + + local o2 = o * 2 + w_inner = w_outer - o2 + h_inner = h_outer - o2 + end + + require( "cairo" ) + + cairo_rectangle( cr, x_inner, y_inner, w_inner, h_inner ) + cairo_clip( cr ) + + for i, f in pairs( graph.functions ) do + if f.data == nil then + f.data = {} + end + + local pixels_per_value = w_inner / f.dx + + local str = conky_parse( f.conky_variable ) + local val = tonumber( str ) + + if val ~= nil then + if f.record_max then + if val > f.max_value then + f.max_value = val + else + for i, v in pairs( f.data ) do + if v > f.max_value then + f.max_value = v + end + end + end + end + + push( f.data, val / f.max_value, pixels_per_value ) + end + + cairo_graph( cr, x_inner, y_inner, w_inner, h_inner, f ) + end + + cairo_reset_clip( cr ) + + if graph.outline then + cairo_set_source_rgba( cr, rgb_to_r_g_b( graph.outline_color, graph.outline_alpha ) ) + cairo_rectangle( cr, x_outer, y_outer, w_outer, h_outer ) + antialias( cr, graph.outline_antialias ) + cairo_set_line_width( cr, graph.outline_width ) + cairo_stroke( cr ) + end +end + +function conky_load_graphs( file ) + function json_decode_file( file ) + local json = require( "json" ) + + local t = {} + for line in io.lines( file ) do + t[#t + 1] = line + end + local str = table.concat( t, "\n" ) + + return json.decode( str ) + end + + local lfs = require( "lfs" ) + + mod_time = lfs.attributes( file, "modification" ) + graphs_file = file + graphs = json_decode_file( file ) +end + +function is_file_dirty( file ) + local lfs = require( "lfs" ) + + local tmp = lfs.attributes( file, "modification" ) + if tmp ~= mod_time then + mod_time = tmp + return true + end + + return false +end + +function conky_draw_graphs() + if conky_window == nil then + return + end + + if is_file_dirty( graphs_file ) then + print( "Reloading " .. graphs_file .. "..." ) + conky_load_graphs( graphs_file ) + end + + if graphs == nil then + return + end + + require( "cairo" ) + + local cs = cairo_xlib_surface_create( conky_window.display, conky_window.drawable, conky_window.visual, + conky_window.width, conky_window.height ) + local cr = cairo_create( cs ) + + cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND ) + + for k, v in pairs( graphs ) do + draw_graph( cr, v.x, v.y, v.width, v.height, v ) + end + + cairo_destroy( cr ) +end diff --git a/example1/conkyrc b/example1/conkyrc new file mode 100644 index 0000000..3fa9160 --- /dev/null +++ b/example1/conkyrc @@ -0,0 +1,21 @@ +alignment top_right +background yes +border_width 0 +double_buffer yes +draw_borders no +gap_x 10 +gap_y 10 +own_window_hints undecorated,below,sticky,skip_taskbar +own_window_transparent yes +own_window_type override +own_window yes +update_interval 1 +use_spacer none +minimum_size 1260 1004 + +# Lua +lua_load /stuff/programming/misc/conky/conkygraph/conkygraph.lua +lua_startup_hook load_graphs ./graphs.json +lua_draw_hook_pre draw_graphs + +TEXT diff --git a/example1/graphs.json b/example1/graphs.json new file mode 100644 index 0000000..f165674 --- /dev/null +++ b/example1/graphs.json @@ -0,0 +1,162 @@ +{ + "cpu": { + "name": "cpu usage", + "outline": true, + "outline_color": "ffffff", + "outline_antialias": false, + "outline_alpha": 1, + "outline_width": 1, + "x": 0, + "y": 0, + "width": 0, + "height": 328, + "functions": { + "cpu0": { + "name": "cpu0", + "conky_variable": "${cpu cpu1}", + "dx": 1, + "record_max": false, + "max_value": 100, + "antialias": true, + "stroke_color": "73d216", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + }, + "cpu1": { + "name": "cpu1", + "conky_variable": "${cpu cpu2}", + "dx": 1, + "record_max": false, + "max_value": 100, + "antialias": true, + "stroke_color": "3465a4", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + }, + "cpu2": { + "name": "cpu2", + "conky_variable": "${cpu cpu3}", + "dx": 1, + "record_max": false, + "max_value": 100, + "antialias": true, + "stroke_color": "cc0000", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + }, + "cpu3": { + "name": "cpu3", + "conky_variable": "${cpu cpu4}", + "dx": 1, + "record_max": false, + "max_value": 100, + "antialias": true, + "stroke_color": "f57900", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + } + } + }, + "ram_swap": { + "name": "ram and swap", + "outline": true, + "outline_color": "ffffff", + "outline_antialias": false, + "outline_alpha": 1, + "outline_width": 1, + "x": 0, + "y": 338, + "width": 0, + "height": 328, + "functions": { + "ram": { + "name": "ram", + "conky_variable": "${memperc}", + "dx": 1, + "record_max": false, + "max_value": 100, + "antialias": true, + "stroke_color": "73d216", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + }, + "swap": { + "name": "swap", + "conky_variable": "${swapperc}", + "dx": 1, + "record_max": false, + "max_value": 100, + "antialias": true, + "stroke_color": "cc0000", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + } + } + }, + "link_up_down": { + "name": "link quality, up and down", + "outline": true, + "outline_color": "ffffff", + "outline_antialias": false, + "outline_alpha": 1, + "outline_width": 1, + "x": 0, + "y": 676, + "width": 0, + "height": 328, + "functions": { + "link": { + "name": "link", + "conky_variable": "${wireless_link_qual wlan0}", + "dx": 1, + "record_max": false, + "max_value": 70, + "max_parse": "${wireless_link_qual_max wlan0}", + "antialias": true, + "stroke_color": "3465a4", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + }, + "down": { + "name": "down", + "conky_variable": "${to_bytes ${downspeedf wlan0}}", + "dx": 1, + "record_max": true, + "max_value": 0, + "antialias": true, + "stroke_color": "75507b", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + }, + "up": { + "name": "up", + "conky_variable": "${to_bytes ${upspeedf wlan0}}", + "dx": 1, + "record_max": true, + "max_value": 0, + "antialias": true, + "stroke_color": "f57900", + "stroke_width": 2, + "fill": false, + "fill_color": null, + "fill_alpha": null + } + } + } +}