diff options
author | Stefano Karapetsas <[email protected]> | 2011-11-21 23:44:15 +0100 |
---|---|---|
committer | Stefano Karapetsas <[email protected]> | 2011-11-21 23:44:15 +0100 |
commit | 69ecddf1317e71f35b1c1de00392dc76f8f1701c (patch) | |
tree | aba29401d8d4b88f14d67aac2b0e60980a78fa2e /sensors-applet | |
download | mate-sensors-applet-69ecddf1317e71f35b1c1de00392dc76f8f1701c.tar.bz2 mate-sensors-applet-69ecddf1317e71f35b1c1de00392dc76f8f1701c.tar.xz |
Initial release bases on sensors-applet
Diffstat (limited to 'sensors-applet')
22 files changed, 6621 insertions, 0 deletions
diff --git a/sensors-applet/Makefile.am b/sensors-applet/Makefile.am new file mode 100644 index 0000000..a87feb0 --- /dev/null +++ b/sensors-applet/Makefile.am @@ -0,0 +1,50 @@ +## Process this file with automake to produce Makefile.in +INCLUDES = -DGNOMELOCALEDIR=\""$(datadir)/locale/"\" \ + -DG_LOG_DOMAIN=\""Sensors Applet"\" \ + -DPIXMAPS_DIR=\""$(datadir)/pixmaps/$(PACKAGE)/"\" \ + -DDATADIR=\""$(datadir)"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DSENSORS_APPLET_PLUGIN_DIR=\""$(libdir)/$(PACKAGE)/plugins/"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ + -DPREFIX=\""$(prefix)"\" \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) $(GTK_CFLAGS) $(GNOME_CFLAGS) $(CAIRO_CFLAGS) $(LIBNOTIFY_CFLAGS) + + +LIBS = $(GLIB_LIBS) $(GTK_LIBS) $(GNOME_LIBS) $(CAIRO_LIBS) $(LIBNOTIFY_LIBS) + +if LIBNOTIFY +libnotify_SRC = active-sensor-libnotify.c \ + active-sensor-libnotify.h +else +libnotify_SRC = +endif + +libexec_PROGRAMS = sensors-applet +sensors_applet_SOURCES = main.c \ + about-dialog.c \ + about-dialog.h \ + active-sensor.c \ + active-sensor.h \ + prefs-dialog.c \ + prefs-dialog.h \ + sensor-config-dialog.c \ + sensor-config-dialog.h \ + sensors-applet.c \ + sensors-applet.h \ + sensors-applet-sensor.h \ + sensors-applet-plugins.c \ + sensors-applet-plugins.h \ + sensors-applet-gconf.c \ + sensors-applet-gconf.h \ + $(libnotify_SRC) + +# install headers for plugins to use +INST_H_FILES = sensors-applet-plugin.h sensors-applet-sensor.h + +headerdir = $(prefix)/include/sensors-applet + +header_DATA = $(INST_H_FILES) + +# since it is separate +EXTRA_DIST = sensors-applet-plugin.h
\ No newline at end of file diff --git a/sensors-applet/Makefile.in b/sensors-applet/Makefile.in new file mode 100644 index 0000000..dd6765f --- /dev/null +++ b/sensors-applet/Makefile.in @@ -0,0 +1,678 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +libexec_PROGRAMS = sensors-applet$(EXEEXT) +subdir = sensors-applet +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/config.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(headerdir)" +PROGRAMS = $(libexec_PROGRAMS) +am__sensors_applet_SOURCES_DIST = main.c about-dialog.c about-dialog.h \ + active-sensor.c active-sensor.h prefs-dialog.c prefs-dialog.h \ + sensor-config-dialog.c sensor-config-dialog.h sensors-applet.c \ + sensors-applet.h sensors-applet-sensor.h \ + sensors-applet-plugins.c sensors-applet-plugins.h \ + sensors-applet-gconf.c sensors-applet-gconf.h \ + active-sensor-libnotify.c active-sensor-libnotify.h +@LIBNOTIFY_TRUE@am__objects_1 = active-sensor-libnotify.$(OBJEXT) +am_sensors_applet_OBJECTS = main.$(OBJEXT) about-dialog.$(OBJEXT) \ + active-sensor.$(OBJEXT) prefs-dialog.$(OBJEXT) \ + sensor-config-dialog.$(OBJEXT) sensors-applet.$(OBJEXT) \ + sensors-applet-plugins.$(OBJEXT) \ + sensors-applet-gconf.$(OBJEXT) $(am__objects_1) +sensors_applet_OBJECTS = $(am_sensors_applet_OBJECTS) +sensors_applet_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(sensors_applet_SOURCES) +DIST_SOURCES = $(am__sensors_applet_SOURCES_DIST) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +DATA = $(header_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AR = @AR@ +ATICONFIG_EXE = @ATICONFIG_EXE@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUSGLIB_CFLAGS = @DBUSGLIB_CFLAGS@ +DBUSGLIB_LIBS = @DBUSGLIB_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DOC_USER_FORMATS = @DOC_USER_FORMATS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GNOME_CFLAGS = @GNOME_CFLAGS@ +GNOME_LIBS = @GNOME_LIBS@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HELP_DIR = @HELP_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBATASMART_CFLAGS = @LIBATASMART_CFLAGS@ +LIBATASMART_LIBS = @LIBATASMART_LIBS@ +LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@ +LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = $(GLIB_LIBS) $(GTK_LIBS) $(GNOME_LIBS) $(CAIRO_LIBS) $(LIBNOTIFY_LIBS) +LIBSENSORS_CFLAGS = @LIBSENSORS_CFLAGS@ +LIBSENSORS_LIBS = @LIBSENSORS_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NVIDIA_CFLAGS = @NVIDIA_CFLAGS@ +NVIDIA_LIBS = @NVIDIA_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OMF_DIR = @OMF_DIR@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGIN_LIBTOOL_FLAGS = @PLUGIN_LIBTOOL_FLAGS@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +XGETTEXT = @XGETTEXT@ +XSLTPROC = @XSLTPROC@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -DGNOMELOCALEDIR=\""$(datadir)/locale/"\" \ + -DG_LOG_DOMAIN=\""Sensors Applet"\" \ + -DPIXMAPS_DIR=\""$(datadir)/pixmaps/$(PACKAGE)/"\" \ + -DDATADIR=\""$(datadir)"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DSENSORS_APPLET_PLUGIN_DIR=\""$(libdir)/$(PACKAGE)/plugins/"\" \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ + -DPREFIX=\""$(prefix)"\" \ + -I$(top_srcdir) \ + $(GLIB_CFLAGS) $(GTK_CFLAGS) $(GNOME_CFLAGS) $(CAIRO_CFLAGS) $(LIBNOTIFY_CFLAGS) + +@LIBNOTIFY_FALSE@libnotify_SRC = +@LIBNOTIFY_TRUE@libnotify_SRC = active-sensor-libnotify.c \ +@LIBNOTIFY_TRUE@ active-sensor-libnotify.h + +sensors_applet_SOURCES = main.c \ + about-dialog.c \ + about-dialog.h \ + active-sensor.c \ + active-sensor.h \ + prefs-dialog.c \ + prefs-dialog.h \ + sensor-config-dialog.c \ + sensor-config-dialog.h \ + sensors-applet.c \ + sensors-applet.h \ + sensors-applet-sensor.h \ + sensors-applet-plugins.c \ + sensors-applet-plugins.h \ + sensors-applet-gconf.c \ + sensors-applet-gconf.h \ + $(libnotify_SRC) + + +# install headers for plugins to use +INST_H_FILES = sensors-applet-plugin.h sensors-applet-sensor.h +headerdir = $(prefix)/include/sensors-applet +header_DATA = $(INST_H_FILES) + +# since it is separate +EXTRA_DIST = sensors-applet-plugin.h +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sensors-applet/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu sensors-applet/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status sensors-applet/config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)" + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +sensors-applet$(EXEEXT): $(sensors_applet_OBJECTS) $(sensors_applet_DEPENDENCIES) + @rm -f sensors-applet$(EXEEXT) + $(LINK) $(sensors_applet_OBJECTS) $(sensors_applet_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/about-dialog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/active-sensor-libnotify.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/active-sensor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prefs-dialog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sensor-config-dialog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sensors-applet-gconf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sensors-applet-plugins.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sensors-applet.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-headerDATA: $(header_DATA) + @$(NORMAL_INSTALL) + test -z "$(headerdir)" || $(MKDIR_P) "$(DESTDIR)$(headerdir)" + @list='$(header_DATA)'; test -n "$(headerdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(headerdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(headerdir)" || exit $$?; \ + done + +uninstall-headerDATA: + @$(NORMAL_UNINSTALL) + @list='$(header_DATA)'; test -n "$(headerdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(headerdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(headerdir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(DATA) config.h +installdirs: + for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(headerdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-headerDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-headerDATA uninstall-libexecPROGRAMS + +.MAKE: all install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libexecPROGRAMS clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-headerDATA install-html \ + install-html-am install-info install-info-am \ + install-libexecPROGRAMS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-headerDATA \ + uninstall-libexecPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/sensors-applet/about-dialog.c b/sensors-applet/about-dialog.c new file mode 100644 index 0000000..27a86f1 --- /dev/null +++ b/sensors-applet/about-dialog.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <gnome.h> +#include "about-dialog.h" + +void about_dialog_open(SensorsApplet *sensors_applet) { + gchar *translator; + const gchar *authors[] = { + "Alex Murray <[email protected]>", + NULL + }; + + if (_("Translator") == "Translator") { + translator = NULL; + } else { + translator = g_strdup(_("To translator: Put your name here to show up in the About dialog as the translator")); + } + + /* Construct the about dialog */ + gtk_show_about_dialog(NULL, + "program-name", PACKAGE_NAME, + "version", PACKAGE_VERSION, + "copyright", "(C) 2005-2009, Alex Murray <[email protected]>", + "authors", authors, + "documenters", authors, + "translator-credits", translator, + "logo-icon-name", SENSORS_APPLET_ICON, + "website", "http://sensors-applet.sourceforge.net/", + NULL); + + + if (translator != NULL) { + g_free(translator); + } + +} diff --git a/sensors-applet/about-dialog.h b/sensors-applet/about-dialog.h new file mode 100644 index 0000000..01537e0 --- /dev/null +++ b/sensors-applet/about-dialog.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ABOUT_DIALOG_H +#define ABOUT_DIALOG_H + +#include "sensors-applet.h" + +/* function prototypes */ +void about_dialog_open(SensorsApplet *sensors_applet); + +#endif /* ABOUT_DIALOG_H */ diff --git a/sensors-applet/active-sensor-libnotify.c b/sensors-applet/active-sensor-libnotify.c new file mode 100644 index 0000000..e69b005 --- /dev/null +++ b/sensors-applet/active-sensor-libnotify.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_LIBNOTIFY +#include <libnotify/notify.h> +#endif + +#include "active-sensor-libnotify.h" + +static void notif_closed_cb(NotifyNotification *notification, + ActiveSensor *active_sensor) +{ + g_assert(notification != NULL && active_sensor != NULL); + + int i; + + g_debug("Notification was closed.. setting reference to NULL so we can show again if needed."); + + // set notif reference to NULL + for (i = 0; i < NUM_NOTIFS; i++) { + if (active_sensor->notification[i] == notification) { + active_sensor->notification[i] = NULL; + break; + } + } +} + + +void active_sensor_libnotify_notify_end(ActiveSensor *active_sensor, + NotifType notif_type) { + GError *error = NULL; + if (active_sensor->notification[notif_type]) { + g_debug("Closing notification"); + if(!notify_notification_close(active_sensor->notification[notif_type], + &error)) { + g_warning("Error closing notification: %s", error->message); + g_error_free(error); + } + g_object_unref(active_sensor->notification[notif_type]); + active_sensor->notification[notif_type] = NULL; + } +} + +void active_sensor_libnotify_notify(ActiveSensor *active_sensor, + NotifType notif_type, + const gchar *summary, + const gchar *message, + const gchar *icon_filename, + gint timeout_msecs, + GtkWidget *attach) { + GError *error = NULL; + + if (!notify_is_initted()) { + if (!notify_init(PACKAGE)) { + return; + } + } + g_debug("Doing notification %s: %s: %s", (notif_type == SENSOR_INTERFACE_ERROR ? "interface-error" : "other") ,summary, message); + + /* leave any existing notification since most likely hasn't changed */ + if (active_sensor->notification[notif_type] != NULL) { + return; +/* active_sensor_libnotify_notify_end(active_sensor, notif_type); */ + } + + /* now create a new one */ + g_debug("Creating new notification"); + active_sensor->notification[notif_type] = notify_notification_new(summary, + message, + icon_filename, + attach); + g_signal_connect(active_sensor->notification[notif_type], "closed", + G_CALLBACK(notif_closed_cb), + active_sensor); + + notify_notification_set_urgency(active_sensor->notification[notif_type], + NOTIFY_URGENCY_CRITICAL); + + + /* timeout may have changed so update it */ + notify_notification_set_timeout(active_sensor->notification[notif_type], + timeout_msecs); + + + g_debug("showing notification"); + if (!notify_notification_show(active_sensor->notification[notif_type], &error)) { + g_debug("Error showing notification: %s", error->message); + g_error_free(error); + } + + + +} + diff --git a/sensors-applet/active-sensor-libnotify.h b/sensors-applet/active-sensor-libnotify.h new file mode 100644 index 0000000..3c81c88 --- /dev/null +++ b/sensors-applet/active-sensor-libnotify.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ACTIVE_SESNOR_LIBNOTIFY_H +#define ACTIVE_SENSOR_LIBNOTIFY_H + +#include "sensors-applet.h" +#include "active-sensor.h" + +void active_sensor_libnotify_notify(ActiveSensor *active_sensor, + NotifType notif_type, + const gchar *summary, + const gchar *message, + const gchar *icon_filename, + gint timeout_msecs, + GtkWidget *attach); +void active_sensor_libnotify_notify_end(ActiveSensor *active_sensor, + NotifType notif_type); + +#endif /* SENSORS_APPLET_LIBNOTIFY_H */ diff --git a/sensors-applet/active-sensor.c b/sensors-applet/active-sensor.c new file mode 100644 index 0000000..84b84cc --- /dev/null +++ b/sensors-applet/active-sensor.c @@ -0,0 +1,835 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_STRING_H +#include <string.h> +#endif /* HAVE_STRING_H */ + +#include <gconf/gconf-client.h> +#include <gnome.h> + +#include "active-sensor.h" +#include "sensors-applet-plugins.h" +#include "sensors-applet-gconf.h" + +typedef enum { + VERY_LOW_SENSOR_VALUE = 0, + LOW_SENSOR_VALUE, + NORMAL_SENSOR_VALUE, + HIGH_SENSOR_VALUE, + VERY_HIGH_SENSOR_VALUE +} SensorValueRange; + +/* Cast a given value to a valid SensorValueRange */ +#define SENSOR_VALUE_RANGE(x) ((SensorValueRange)(CLAMP(x, VERY_LOW_SENSOR_VALUE, VERY_HIGH_SENSOR_VALUE))) + +#define CAIRO_GRAPH_COLOR_GRADIENT 0.4 + +static const gchar * const temp_overlay_icons[] = { + PIXMAPS_DIR "very-low-temp-icon.png", + PIXMAPS_DIR "low-temp-icon.png", + PIXMAPS_DIR "normal-temp-icon.png", + PIXMAPS_DIR "high-temp-icon.png", + PIXMAPS_DIR "very-high-temp-icon.png" +}; + +static gdouble sensor_value_range_normalised(gdouble value, + gdouble low_value, + gdouble high_value) { + return ((value - low_value)/(high_value - low_value)); +} + +static SensorValueRange sensor_value_range(gdouble sensor_value, + gdouble low_value, + gdouble high_value) { + gdouble range; + range = sensor_value_range_normalised(sensor_value, low_value, high_value)*(gdouble)(VERY_HIGH_SENSOR_VALUE); + + /* check if need to round up, otherwise let int conversion + * round down for us and make sure it is a valid range + * value */ + return SENSOR_VALUE_RANGE(((gint)range + ((range - ((gint)range)) >= 0.5))); +} + + +static gboolean active_sensor_execute_alarm(ActiveSensor *active_sensor, + NotifType notif_type) { + int pid; + + sensors_applet_notify_active_sensor(active_sensor, notif_type); + g_debug("EXECUTING %s ALARM: %s", + (notif_type == LOW_ALARM ? + "LOW" : "HIGH"), + active_sensor->alarm_command[notif_type]); + pid = gnome_execute_shell(NULL, + active_sensor->alarm_command[notif_type]); + g_debug("Command executed in shell with pid %d", pid); + + return (pid != -1); +} + +static gboolean active_sensor_execute_low_alarm(ActiveSensor *active_sensor) { + return active_sensor_execute_alarm(active_sensor, LOW_ALARM); +} + +static gboolean active_sensor_execute_high_alarm(ActiveSensor *active_sensor) { + return active_sensor_execute_alarm(active_sensor, HIGH_ALARM); +} + +/* needs to be able to be called by the config dialog when the alarm + * command changes */ +void active_sensor_alarm_off(ActiveSensor *active_sensor, + NotifType notif_type) { + g_assert(active_sensor); + + if (active_sensor->alarm_timeout_id[notif_type] != -1) { + g_debug("Disabling %s alarm.", + (notif_type == LOW_ALARM ? "LOW" : "HIGH")); + if (!g_source_remove(active_sensor->alarm_timeout_id[notif_type])) { + g_debug("Error removing alarm source"); + } + g_free(active_sensor->alarm_command[notif_type]); + active_sensor->alarm_timeout_id[notif_type] = -1; + + } + sensors_applet_notify_end(active_sensor, notif_type); +} + +static void active_sensor_all_alarms_off(ActiveSensor *active_sensor) { + /* turn off any alarms */ + int i; + for (i = 0; i < NUM_ALARMS; i++) { + if (active_sensor->alarm_timeout_id[i] >= 0) { + g_debug("-- turning off notif with type %d ---", i); + active_sensor_alarm_off(active_sensor, i); + } + } +} + +static void active_sensor_alarm_on(ActiveSensor *active_sensor, + NotifType notif_type) { + GtkTreeModel *model; + GtkTreePath *tree_path; + GtkTreeIter iter; + + g_assert(active_sensor); + + model = gtk_tree_row_reference_get_model(active_sensor->sensor_row); + tree_path = gtk_tree_row_reference_get_path(active_sensor->sensor_row); + + if (gtk_tree_model_get_iter(model, &iter, tree_path)) { + + if (active_sensor->alarm_timeout_id[notif_type] == -1) { + /* alarm is not currently on */ + gtk_tree_model_get(model, + &iter, + (notif_type == LOW_ALARM ? + LOW_ALARM_COMMAND_COLUMN : + HIGH_ALARM_COMMAND_COLUMN), + &(active_sensor->alarm_command[notif_type]), + ALARM_TIMEOUT_COLUMN, &(active_sensor->alarm_timeout), + -1); + g_debug("Activating alarm to repeat every %d seconds", active_sensor->alarm_timeout); + + /* execute alarm once, then add to time to + keep repeating it */ + active_sensor_execute_alarm(active_sensor, notif_type); + int timeout = (active_sensor->alarm_timeout <= 0 ? + G_MAXINT : + active_sensor->alarm_timeout); + switch (notif_type) { + case LOW_ALARM: + active_sensor->alarm_timeout_id[notif_type] = g_timeout_add_seconds(timeout, + (GSourceFunc)active_sensor_execute_low_alarm, + active_sensor); + break; + case HIGH_ALARM: + active_sensor->alarm_timeout_id[notif_type] = g_timeout_add_seconds(timeout, + (GSourceFunc)active_sensor_execute_high_alarm, + active_sensor); + break; + default: + g_debug("Unkown notif type: %d", notif_type); + } + + + } + } + gtk_tree_path_free(tree_path); + +} + +/** + * Compares two ActiveSensors and returns -1 if a comes before b in the tree, + * 0 if refer to same row, 1 if b comes before a + */ +gint active_sensor_compare(ActiveSensor *a, ActiveSensor *b) { + GtkTreePath *a_tree_path, *b_tree_path; + gint ret_val; + + g_assert(a); + g_assert(b); + + a_tree_path = gtk_tree_row_reference_get_path(a->sensor_row); + b_tree_path = gtk_tree_row_reference_get_path(b->sensor_row); + + ret_val = gtk_tree_path_compare(a_tree_path, b_tree_path); + + gtk_tree_path_free(a_tree_path); + gtk_tree_path_free(b_tree_path); + + return ret_val; +} + +static void active_sensor_update_icon(ActiveSensor *active_sensor, + GdkPixbuf *base_icon, + SensorType sensor_type) { + + GdkPixbuf *overlay_icon, *new_icon; + const gchar *overlay_icon_filename = NULL; + SensorValueRange value_range; + + g_assert(active_sensor); + + /* select overlay icon + * depending on sensor + * value */ + value_range = sensor_value_range(active_sensor->sensor_values[0], + active_sensor->sensor_low_value, + active_sensor->sensor_high_value); + + if (sensor_type == TEMP_SENSOR) { + overlay_icon_filename = temp_overlay_icons[value_range]; + } + + /* load base icon */ + new_icon = gdk_pixbuf_copy(base_icon); + + /* only load overlay if required */ + if (overlay_icon_filename) { + overlay_icon = gdk_pixbuf_new_from_file_at_size(overlay_icon_filename, + DEFAULT_ICON_SIZE, + DEFAULT_ICON_SIZE, + NULL); + if (overlay_icon) { + gdk_pixbuf_composite(overlay_icon, new_icon, + 0, 0, + DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE, + 0, 0, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + 255); + + g_object_unref(overlay_icon); + } + } + gtk_image_set_from_pixbuf(GTK_IMAGE(active_sensor->icon), + new_icon); + g_object_unref(new_icon); + +} + +static void active_sensor_update_graph(ActiveSensor *as) { + gdouble line_height; + gdouble width, height; + gdouble x, y; + cairo_t *cr; + cairo_pattern_t *pattern; + gint i; + GdkPixmap *pixmap; + + width = as->graph->allocation.width; + height = as->graph->allocation.height; + + /* only do if drawable - will not be drawable if not currently + * displayed on screen */ + if (GDK_IS_DRAWABLE(as->graph->window)) { + /* use pixmap, draw to it, then use gdk to draw the + * pixmap onto the drawable surface of the graph to + * stop flickering */ + pixmap = gdk_pixmap_new(as->graph->window, + width, height, -1); + + cr = gdk_cairo_create(pixmap); + + /* so we can set a clipping area, as well as fill the + * back of the graph black */ + cairo_rectangle(cr, + 0, 0, + width, + height); + /* clip to rectangle and keep it as a path so can be + * filled below */ + cairo_clip_preserve(cr); + + /* use black for bg color of graphs */ + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + cairo_fill(cr); + + + /* determine height to scale line at for each value - + * only do as many as will fit or the number of + * samples that we have */ + for (i = 0; i < MIN(as->num_samples, width); i++) { + /* need to remove one more to make it line up + * properly when drawing */ + x = width - i - 1; + y = height; + + line_height = sensor_value_range_normalised(as->sensor_values[i], + as->sensor_low_value, + as->sensor_high_value) * height; + + + + if (line_height > 0) { + cairo_move_to(cr, + x, + y); + cairo_line_to(cr, x, + y - line_height); + } + + } + /* make lines a gradient from slightly darker than + * chosen color at bottom of graph, to slightly + * lighter than chosen color at top of graph */ + pattern = cairo_pattern_create_linear(x, y, + x, 0); + cairo_pattern_add_color_stop_rgb(pattern, + 0, + as->graph_color.red / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT, + as->graph_color.green / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT, + as->graph_color.blue / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT); + + cairo_pattern_add_color_stop_rgb(pattern, + height, + as->graph_color.red / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT, + as->graph_color.green / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT, + as->graph_color.blue / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT); + + cairo_set_source(cr, pattern); + cairo_stroke(cr); + cairo_pattern_destroy(pattern); + cairo_destroy(cr); + + /* now draw pixmap onto drawable surface */ + gdk_draw_drawable(as->graph->window, + as->graph->style->fg_gc[GTK_WIDGET_STATE(as->graph)], + pixmap, + 0, 0, + 0, 0, + -1, -1); + /* don't need pixmap anymore */ + g_object_unref(pixmap); + } +} + +void active_sensor_destroy(ActiveSensor *active_sensor) { + g_debug("-- destroying active sensor label..."); + gtk_object_destroy(GTK_OBJECT(active_sensor->label)); + + g_debug("-- destroying active sensor icon.."); + gtk_object_destroy(GTK_OBJECT(active_sensor->icon)); + + g_debug("-- destroying active sensor value..."); + gtk_object_destroy(GTK_OBJECT(active_sensor->value)); + + g_debug("-- destroying active sensor graph and frame..."); + gtk_object_destroy(GTK_OBJECT(active_sensor->graph)); + gtk_object_destroy(GTK_OBJECT(active_sensor->graph_frame)); + + g_debug("-- destroying active sensor values..."); + g_free(active_sensor->sensor_values); + + active_sensor_all_alarms_off(active_sensor); + + g_free(active_sensor); +} + + +gboolean graph_expose_event_cb(GtkWidget *graph, + GdkEventExpose *event, + gpointer data) { + ActiveSensor *as; + + as = (ActiveSensor *)data; + + active_sensor_update_graph(as); + /* propagate event onwards */ + return FALSE; +} + +static void active_sensor_set_graph_dimensions(ActiveSensor *as, + gint width, + gint height) { + gdouble *old_values; + gint num_samples, old_num_samples; + gint graph_width, graph_height; + + /* dimensions are really for graph frame, so need to remove + * extra width added by graph frame - make sure not less than + * 1 - always need atleast 1 sample */ + graph_width = CLAMP(width - GRAPH_FRAME_EXTRA_WIDTH, 1, width - GRAPH_FRAME_EXTRA_WIDTH); + graph_height = CLAMP(height - GRAPH_FRAME_EXTRA_WIDTH, 1 , height - GRAPH_FRAME_EXTRA_WIDTH); + + g_debug("setting graph dimensions to %d x %d", graph_width, graph_height); + num_samples = graph_width; + + if (as->sensor_values) { + old_values = as->sensor_values; + old_num_samples = as->num_samples; + + as->num_samples = num_samples; + as->sensor_values = g_malloc0(sizeof(gdouble)*as->num_samples); + memcpy(as->sensor_values, + old_values, + MIN(old_num_samples, as->num_samples)*sizeof(gdouble)); + + g_free(old_values); + } else { + as->sensor_values = g_malloc0(sizeof(gdouble)*num_samples); + as->num_samples = num_samples; + } + + /* update graph frame size request */ + gtk_widget_set_size_request(as->graph, + graph_width, + graph_height); +} + +void active_sensor_update_graph_dimensions(ActiveSensor *as, + gint sizes[2]) { + active_sensor_set_graph_dimensions(as, sizes[0], sizes[1]); + active_sensor_update_graph(as); +} + +ActiveSensor *active_sensor_new(SensorsApplet *sensors_applet, + GtkTreeRowReference *sensor_row) { + ActiveSensor *active_sensor; + PanelAppletOrient orient; + gint graph_size; + gboolean horizontal; + + g_assert(sensors_applet); + g_assert(sensor_row); + + g_debug("creating new active sensor"); + + active_sensor = g_new0(ActiveSensor, 1); + active_sensor->sensors_applet = sensors_applet; + + active_sensor->sensor_row = sensor_row; + + int i; + for (i = 0; i < NUM_NOTIFS; i++) { + active_sensor->alarm_timeout_id[i] = -1; + } + + active_sensor->label = gtk_label_new(""); + active_sensor->value = gtk_label_new(""); + active_sensor->icon = gtk_image_new(); + + active_sensor->graph = gtk_drawing_area_new(); + active_sensor->graph_frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(active_sensor->graph_frame), + GTK_SHADOW_IN); + gtk_container_add(GTK_CONTAINER(active_sensor->graph_frame), + active_sensor->graph); + gtk_widget_add_events(active_sensor->graph_frame, + GDK_ALL_EVENTS_MASK); + + /* need to set size according to orientation */ + orient = panel_applet_get_orient(active_sensor->sensors_applet->applet); + graph_size = panel_applet_gconf_get_int(active_sensor->sensors_applet->applet, + GRAPH_SIZE, NULL); + + horizontal = ((orient == PANEL_APPLET_ORIENT_UP) || + (orient == PANEL_APPLET_ORIENT_DOWN)); + + active_sensor_set_graph_dimensions(active_sensor, + (horizontal ? graph_size : sensors_applet->size), + (horizontal ? sensors_applet->size : graph_size)); + + g_signal_connect(G_OBJECT(active_sensor->graph), + "expose_event", + G_CALLBACK(graph_expose_event_cb), + active_sensor); + + active_sensor->updated = FALSE; + return active_sensor; +} + +static void active_sensor_update_sensor_value(ActiveSensor *as, + gdouble sensor_value) { + + /* only if have more than 1 sample stored */ + if (as->num_samples > 1) { + memmove(&(as->sensor_values[1]), + as->sensor_values, + (as->num_samples - 1)*sizeof(gdouble)); + } + + as->sensor_values[0] = sensor_value; +} + +void active_sensor_update(ActiveSensor *active_sensor, + SensorsApplet *sensors_applet) { + + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + + /* instance data from the tree for this sensor */ + gchar *sensor_path = NULL; + gchar *sensor_id = NULL; + gchar *sensor_label = NULL; + SensorType sensor_type; + gchar *sensor_interface; + gboolean sensor_enabled; + gdouble sensor_low_value; + gdouble sensor_high_value; + gboolean sensor_alarm_enabled; + gdouble sensor_multiplier; + gdouble sensor_offset; + gdouble sensor_value; + GdkPixbuf *icon_pixbuf; + gchar *graph_color; + + /* to build the list of labels as we go */ + gchar *value_text = NULL; + gchar *old_value_text; + + TemperatureScale scale; + DisplayMode display_mode; + + GError *error = NULL; + + gchar *tooltip = NULL; + gchar *value_tooltip = NULL; + + /* hidden gconf options */ + GConfClient *client; + gint font_size = 0; + gboolean hide_units = FALSE; + + g_assert(active_sensor); + g_assert(active_sensor->sensor_row); + g_assert(sensors_applet); + + model = gtk_tree_row_reference_get_model(active_sensor->sensor_row); + path = gtk_tree_row_reference_get_path(active_sensor->sensor_row); + + /* if can successfully get iter can proceed */ + if (gtk_tree_model_get_iter(model, &iter, path)) { + gtk_tree_path_free(path); + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), + &iter, + PATH_COLUMN, &sensor_path, + ID_COLUMN, &sensor_id, + LABEL_COLUMN, &sensor_label, + INTERFACE_COLUMN, &sensor_interface, + SENSOR_TYPE_COLUMN, &sensor_type, + ENABLE_COLUMN, &sensor_enabled, + LOW_VALUE_COLUMN, &sensor_low_value, + HIGH_VALUE_COLUMN, &sensor_high_value, + ALARM_ENABLE_COLUMN, &sensor_alarm_enabled, + MULTIPLIER_COLUMN, &sensor_multiplier, + OFFSET_COLUMN, &sensor_offset, + ICON_PIXBUF_COLUMN, &icon_pixbuf, + GRAPH_COLOR_COLUMN, &graph_color, + -1); + + + SensorsAppletPluginGetSensorValue get_sensor_value; + /* only call function if is in hash table for plugin */ + if ((get_sensor_value = sensors_applet_plugins_get_sensor_value_func(sensors_applet, sensor_interface)) != NULL) { + sensor_value = get_sensor_value(sensor_path, + sensor_id, + sensor_type, + &error); + + + if (error) { + g_debug("Error updating active sensor: %s", error->message); + sensors_applet_notify_active_sensor(active_sensor, + SENSOR_INTERFACE_ERROR); + + /* hard code text as ERROR */ + value_text = g_strdup(_("ERROR")); + value_tooltip = g_strdup_printf("- %s", error->message); + g_error_free(error); + error = NULL; + + /* set sensor value to an error code - + * note this is not unique */ + sensor_value = -1; + } else { + /* use hidden gconf key for hide_units */ + + if ((client = gconf_client_get_default()) != NULL) { + hide_units = gconf_client_get_bool(client, + "/apps/sensors-applet/" HIDE_UNITS, + &error); + if (error) { + g_debug("Could not get hide units from GConf - assuming false"); + hide_units = FALSE; + g_error_free(error); + error = NULL; + } + + g_object_unref(client); + } + + + /* scale value and set text using this + * value */ + switch (sensor_type) { + case TEMP_SENSOR: + + scale = (TemperatureScale)panel_applet_gconf_get_int(sensors_applet->applet, TEMPERATURE_SCALE, NULL); + /* scale value */ + sensor_value = sensors_applet_convert_temperature(sensor_value, + CELSIUS, + scale); + + sensor_value = (sensor_value * sensor_multiplier) + sensor_offset; + switch (scale) { + case FAHRENHEIT: + value_text = g_strdup_printf("%2.0f %s", sensor_value, (hide_units ? "" : UNITS_FAHRENHEIT)); + /* tooltip should + * always display + * units */ + value_tooltip = g_strdup_printf("%2.0f %s", sensor_value, UNITS_FAHRENHEIT); + + break; + case CELSIUS: + value_text = g_strdup_printf("%2.0f %s", sensor_value, (hide_units ? "" : UNITS_CELSIUS)); + value_tooltip = g_strdup_printf("%2.0f %s", sensor_value, UNITS_CELSIUS); + break; + case KELVIN: + value_text = g_strdup_printf("%2.0f", sensor_value); + value_tooltip = g_strdup(value_text); + break; + } + break; + + case FAN_SENSOR: + sensor_value = (sensor_value * sensor_multiplier) + sensor_offset; + value_text = g_strdup_printf("%4.0f %s", sensor_value, (hide_units ? "" : UNITS_RPM)); + value_tooltip = g_strdup_printf("%4.0f %s", sensor_value, UNITS_RPM); + + break; + + case VOLTAGE_SENSOR: + sensor_value = (sensor_value * sensor_multiplier) + sensor_offset; + value_text = g_strdup_printf("%4.2f %s", sensor_value, (hide_units ? "" : UNITS_VOLTAGE)); + value_tooltip = g_strdup_printf("%4.2f %s", sensor_value, UNITS_VOLTAGE); + + break; + + case CURRENT_SENSOR: + sensor_value = (sensor_value * sensor_multiplier) + sensor_offset; + value_text = g_strdup_printf("%4.2f %s", sensor_value, (hide_units ? "" : UNITS_CURRENT)); + value_tooltip = g_strdup_printf("%4.2f %s", sensor_value, UNITS_CURRENT); + break; + + } /* end switch(sensor_type) */ + } /* end else on error */ + + /* setup for tooltips */ + tooltip = g_strdup_printf("%s %s", sensor_label, value_tooltip); + g_free(value_tooltip); + + /* only do icons and labels / graphs if needed */ + display_mode = panel_applet_gconf_get_int(sensors_applet->applet, + DISPLAY_MODE, + NULL); + + /* most users wont have a font size set */ + if ((client = gconf_client_get_default()) != NULL) { + font_size = gconf_client_get_int(client, + "/apps/sensors-applet/" FONT_SIZE, + &error); + if (error) { + g_debug("Could not get font size from GConf - assuming default size"); + font_size = 0; + g_error_free(error); + error = NULL; + } + + g_object_unref(client); + } + + + /* do icon if needed */ + if (display_mode == DISPLAY_ICON || + display_mode == DISPLAY_ICON_WITH_VALUE) { + /* update icon if icon range has changed if no + * update has been done before */ + if ((sensor_value_range(sensor_value, sensor_low_value, sensor_high_value) != sensor_value_range(active_sensor->sensor_values[0], active_sensor->sensor_low_value, active_sensor->sensor_high_value)) || !(active_sensor->updated)) { + active_sensor_update_sensor_value(active_sensor, + sensor_value); + active_sensor->sensor_low_value = sensor_low_value; + active_sensor->sensor_high_value = sensor_high_value; + active_sensor_update_icon(active_sensor, icon_pixbuf, sensor_type); + } + /* always update tooltip */ + gtk_widget_set_tooltip_text(active_sensor->icon, + tooltip); + } + active_sensor_update_sensor_value(active_sensor, + sensor_value); + active_sensor->sensor_low_value = sensor_low_value; + active_sensor->sensor_high_value = sensor_high_value; + + /* do graph if needed */ + if (display_mode == DISPLAY_GRAPH) { + /* update graph color in case has changed */ + gdk_color_parse(graph_color, + &(active_sensor->graph_color)); + + active_sensor_update_graph(active_sensor); + gtk_widget_set_tooltip_text(active_sensor->graph, + tooltip); + + } + + old_value_text = value_text; + + if (sensor_alarm_enabled) { + if (sensor_value >= sensor_high_value || + sensor_value <= sensor_low_value) { + /* make value text red and + * activate alarm */ + if (display_mode == DISPLAY_LABEL_WITH_VALUE || + display_mode == DISPLAY_ICON_WITH_VALUE || + display_mode == DISPLAY_VALUE) { + value_text = g_markup_printf_escaped("<span foreground=\"#FF0000\">%s</span>", old_value_text); + + g_free(old_value_text); + } + /* could have both coditions at once */ + if (sensor_value >= sensor_high_value) { + active_sensor_alarm_on(active_sensor, HIGH_ALARM); + } + + if (sensor_value <= sensor_low_value) { + active_sensor_alarm_on(active_sensor, LOW_ALARM); + } + + } else { + /* make sure alarms are off */ + active_sensor_all_alarms_off(active_sensor); + } + } else { /* else for if alarm enabled */ + /* make sure all alarms are off */ + active_sensor_all_alarms_off(active_sensor); + } + + /* do value label */ + if (display_mode == DISPLAY_LABEL_WITH_VALUE || + display_mode == DISPLAY_ICON_WITH_VALUE || + display_mode == DISPLAY_VALUE) { + if (font_size) { + old_value_text = value_text; + + value_text = g_strdup_printf("<span font_desc=\"%d\">%s</span>", font_size, old_value_text); + g_free(old_value_text); + } + gtk_label_set_markup(GTK_LABEL(active_sensor->value), + value_text); + + + gtk_widget_set_tooltip_text(active_sensor->value, + tooltip); + } + /* finished with value text */ + g_free(value_text); + + /* do label label */ + if (display_mode == DISPLAY_LABEL_WITH_VALUE) { + if (font_size) { + old_value_text = sensor_label; + sensor_label = g_strdup_printf("<span font_desc=\"%d\">%s</span>", font_size, old_value_text); + g_free(old_value_text); + } + gtk_label_set_markup(GTK_LABEL(active_sensor->label), + sensor_label); + gtk_widget_set_tooltip_text(active_sensor->label, + tooltip); + + } + + g_free(tooltip); + } else { + g_debug("no get_sensor_value function yet installed for interface %s.", sensor_interface); + } + g_free(sensor_path); + g_free(sensor_id); + g_free(sensor_label); + g_free(sensor_interface); + g_free(graph_color); + g_object_unref(icon_pixbuf); + + } else { + g_debug("Error getting iter when updating sensor..."); + + } + active_sensor->updated = TRUE; + +} + +/* to be called when the icon within the GtkRowReference that this + * sensor references is changed - updates icon based upon value in the + * ActiveSensor */ +void active_sensor_icon_changed(ActiveSensor *active_sensor, + SensorsApplet *sensors_applet) { + + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + + SensorType sensor_type; + GdkPixbuf *icon_pixbuf; + + g_assert(active_sensor); + g_assert(sensors_applet); + + model = gtk_tree_row_reference_get_model(active_sensor->sensor_row); + path = gtk_tree_row_reference_get_path(active_sensor->sensor_row); + + /* if can successfully get iter can proceed */ + if (gtk_tree_model_get_iter(model, &iter, path)) { + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), + &iter, + SENSOR_TYPE_COLUMN, &sensor_type, + ICON_PIXBUF_COLUMN, &icon_pixbuf, + -1); + + active_sensor_update_icon(active_sensor, + icon_pixbuf, + sensor_type); + g_object_unref(icon_pixbuf); + } + gtk_tree_path_free(path); +} diff --git a/sensors-applet/active-sensor.h b/sensors-applet/active-sensor.h new file mode 100644 index 0000000..2d4674b --- /dev/null +++ b/sensors-applet/active-sensor.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ACTIVE_SENSOR_H +#define ACTIVE_SENSOR_H + +#ifdef HAVE_LIBNOTIFY +#include <libnotify/notify.h> +#include "active-sensor-libnotify.h" +#endif + +#include "sensors-applet.h" + +struct _ActiveSensor { + SensorsApplet *sensors_applet; + + /* widgets to render to display the sensor */ + GtkWidget *label; + GtkWidget *icon; + GtkWidget *value; + GtkWidget *graph; + GtkWidget *graph_frame; + + GdkColor graph_color; + + GtkTreeRowReference *sensor_row; + +#ifdef HAVE_LIBNOTIFY + NotifyNotification *notification[NUM_NOTIFS]; +#endif + + gboolean updated; + + /* alarm related stuff */ + gint alarm_timeout_id[NUM_ALARMS]; + gchar *alarm_command[NUM_ALARMS]; + gint alarm_timeout; + + /* buffer of sensor values */ + gdouble *sensor_values; + + /* length of sensor_values buffer */ + gint num_samples; + + gdouble sensor_low_value; + gdouble sensor_high_value; +}; + +ActiveSensor *active_sensor_new(SensorsApplet *sensors_applet, + GtkTreeRowReference *sensor_row); +void active_sensor_destroy(ActiveSensor *active_sensor); +gint active_sensor_compare(ActiveSensor *a, ActiveSensor *b); +void active_sensor_update(ActiveSensor *sensor, SensorsApplet *sensors_applet); +void active_sensor_icon_changed(ActiveSensor *sensor, SensorsApplet *sensors_applet); +void active_sensor_update_graph_dimensions(ActiveSensor *as, + gint dimensions[2]); +void active_sensor_alarm_off(ActiveSensor *active_sensor, NotifType notif_type); +#endif /* ACTIVE_SENSOR_H */ diff --git a/sensors-applet/config.h.in b/sensors-applet/config.h.in new file mode 100644 index 0000000..a32469b --- /dev/null +++ b/sensors-applet/config.h.in @@ -0,0 +1,134 @@ +/* sensors-applet/config.h.in. Generated from configure.ac by autoheader. */ + +/* aticonfig executable */ +#undef ATICONFIG_EXE + +/* always defined to indicate that i18n is enabled */ +#undef ENABLE_NLS + +/* Package name for gettext */ +#undef GETTEXT_PACKAGE + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#undef HAVE_ARPA_INET_H + +/* using aticonfig */ +#undef HAVE_ATICONFIG + +/* Define to 1 if you have the `bind_textdomain_codeset' function. */ +#undef HAVE_BIND_TEXTDOMAIN_CODESET + +/* Define to 1 if you have the `dcgettext' function. */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define if your <locale.h> file defines LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* libnotify available */ +#undef HAVE_LIBNOTIFY + +/* libsensors is available */ +#undef HAVE_LIBSENSORS + +/* Define to 1 if you have the <locale.h> header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the <NVCtrl/NVCtrlLib.h> header file. */ +#undef HAVE_NVCTRL_NVCTRLLIB_H + +/* Define to 1 if you have the <NVCtrl/NVCtrl.h> header file. */ +#undef HAVE_NVCTRL_NVCTRL_H + +/* nvidia sensors available */ +#undef HAVE_NVIDIA + +/* Define to 1 if you have the <regex.h> header file. */ +#undef HAVE_REGEX_H + +/* Define to 1 if you have the <sensors/sensors.h> header file. */ +#undef HAVE_SENSORS_SENSORS_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the <X11/Xlib.h> header file. */ +#undef HAVE_X11_XLIB_H + +/* Define to 1 if you have the <\> header file. */ +#undef HAVE__ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/sensors-applet/main.c b/sensors-applet/main.c new file mode 100644 index 0000000..b04e9eb --- /dev/null +++ b/sensors-applet/main.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <panel-applet.h> +#include <string.h> +#include "sensors-applet.h" + +static gboolean sensors_applet_fill(PanelApplet *applet, + const gchar *iid, + gpointer data) { + SensorsApplet *sensors_applet; + gboolean retval = FALSE; + if (strcmp(iid, "OAFIID:SensorsApplet") == 0) { + sensors_applet = g_new0(SensorsApplet, 1); + sensors_applet->applet = applet; + sensors_applet_init(sensors_applet); + retval = TRUE; + } + return retval; +} + +PANEL_APPLET_BONOBO_FACTORY ("OAFIID:SensorsApplet_Factory", + PANEL_TYPE_APPLET, + PACKAGE, + PACKAGE_VERSION, + sensors_applet_fill, + NULL); diff --git a/sensors-applet/prefs-dialog.c b/sensors-applet/prefs-dialog.c new file mode 100644 index 0000000..fc7d3ac --- /dev/null +++ b/sensors-applet/prefs-dialog.c @@ -0,0 +1,1009 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <libgnome/libgnome.h> +#include "sensors-applet-gconf.h" +#include "prefs-dialog.h" +#include "sensor-config-dialog.h" + +#define OLD_TEMP_SCALE 0 +#define NEW_TEMP_SCALE 1 + +/* when a user closes the prefs-dialog we assume that applet is now + setup, so store all values in gconf */ +void prefs_dialog_close(SensorsApplet *sensors_applet) { + + if (sensors_applet->sensors != NULL) { + if (sensors_applet_gconf_save_sensors(sensors_applet)) + panel_applet_gconf_set_bool(sensors_applet->applet, + IS_SETUP, TRUE, NULL); + } + if (sensors_applet->prefs_dialog) { + gtk_widget_destroy(GTK_WIDGET(sensors_applet->prefs_dialog->dialog)); + g_free(sensors_applet->prefs_dialog); + sensors_applet->prefs_dialog = NULL; + + } + if (sensors_applet->timeout_id == 0) { + sensors_applet->timeout_id = g_timeout_add_seconds(panel_applet_gconf_get_int(sensors_applet->applet, TIMEOUT, NULL) / 1000, (GSourceFunc)sensors_applet_update_active_sensors, sensors_applet); + } + + +} + +void prefs_dialog_response(GtkDialog *prefs_dialog, + gint response, + gpointer data) { + + SensorsApplet *sensors_applet; + GError *error = NULL; + gint current_page; + gchar *uri; + + sensors_applet = (SensorsApplet *)data; + + switch (response) { + case GTK_RESPONSE_HELP: + g_debug("loading help in prefs"); + current_page = gtk_notebook_get_current_page(sensors_applet->prefs_dialog->notebook); + uri = g_strdup_printf("ghelp:sensors-applet?%s", + ((current_page == 0) ? + "sensors-applet-general-options" : + ((current_page == 1) ? + "sensors-applet-sensors" : + NULL))); + gtk_show_uri(NULL, uri, gtk_get_current_event_time(), &error); + g_free(uri); + + if (error) { + g_debug("Could not open help document: %s ",error->message); + g_error_free (error); + } + break; + default: + g_debug("closing prefs dialog"); + prefs_dialog_close(sensors_applet); + } +} + + +static gboolean prefs_dialog_convert_low_and_high_values(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + TemperatureScale scales[2]) { + SensorType sensor_type; + gdouble low_value, high_value; + + gtk_tree_model_get(model, + iter, + SENSOR_TYPE_COLUMN, &sensor_type, + LOW_VALUE_COLUMN, &low_value, + HIGH_VALUE_COLUMN, &high_value, + -1); + + if (sensor_type == TEMP_SENSOR) + { + low_value = sensors_applet_convert_temperature(low_value, + scales[OLD_TEMP_SCALE], + scales[NEW_TEMP_SCALE]); + + high_value = sensors_applet_convert_temperature(high_value, + scales[OLD_TEMP_SCALE], + scales[NEW_TEMP_SCALE]); + + + gtk_tree_store_set(GTK_TREE_STORE(model), + iter, + LOW_VALUE_COLUMN, low_value, + HIGH_VALUE_COLUMN, high_value, + -1); + } + return FALSE; +} + + +static void prefs_dialog_timeout_changed(GtkSpinButton *button, + PrefsDialog *prefs_dialog) { + gint value; + value = (gint)(gtk_spin_button_get_value(button) * 1000); + panel_applet_gconf_set_int(prefs_dialog->sensors_applet->applet, TIMEOUT, value, NULL); +} + +static void prefs_dialog_display_mode_changed(GtkComboBox *display_mode_combo_box, + PrefsDialog *prefs_dialog) { + + int display_mode; + + display_mode = gtk_combo_box_get_active(display_mode_combo_box); + + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->layout_mode_label), + (display_mode != DISPLAY_ICON) && + (display_mode != DISPLAY_VALUE) && + (display_mode != DISPLAY_GRAPH)); + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->layout_mode_combo_box), + (display_mode != DISPLAY_ICON) && + (display_mode != DISPLAY_VALUE) && + (display_mode != DISPLAY_GRAPH)); + + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->graph_size_label), + (display_mode == DISPLAY_GRAPH)); + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->graph_size_spinbutton), + (display_mode == DISPLAY_GRAPH)); + + panel_applet_gconf_set_int(prefs_dialog->sensors_applet->applet, + DISPLAY_MODE, + gtk_combo_box_get_active(display_mode_combo_box), + NULL); + + sensors_applet_display_layout_changed(prefs_dialog->sensors_applet); +} + +static void prefs_dialog_layout_mode_changed(GtkComboBox *layout_mode_combo_box, + PrefsDialog *prefs_dialog) { + + panel_applet_gconf_set_int(prefs_dialog->sensors_applet->applet, + LAYOUT_MODE, + gtk_combo_box_get_active(layout_mode_combo_box), + NULL); + + sensors_applet_display_layout_changed(prefs_dialog->sensors_applet); +} + + +static void prefs_dialog_temperature_scale_changed(GtkComboBox *temperature_scale_combo_box, + PrefsDialog *prefs_dialog) { + /* get old temp scale value */ + TemperatureScale scales[2]; + GtkTreeModel *model; + + scales[OLD_TEMP_SCALE] = (TemperatureScale)panel_applet_gconf_get_int(prefs_dialog->sensors_applet->applet, + TEMPERATURE_SCALE, + NULL); + + scales[NEW_TEMP_SCALE] = (TemperatureScale)gtk_combo_box_get_active(temperature_scale_combo_box); + + panel_applet_gconf_set_int(prefs_dialog->sensors_applet->applet, + TEMPERATURE_SCALE, + scales[NEW_TEMP_SCALE], + NULL); + + /* now go thru and convert all low and high sensor values in + * the tree to either celcius or Fahrenheit */ + model = gtk_tree_view_get_model(prefs_dialog->view); + gtk_tree_model_foreach(model, + (GtkTreeModelForeachFunc)prefs_dialog_convert_low_and_high_values, + scales); + + /* finally update display of active sensors */ + sensors_applet_update_active_sensors(prefs_dialog->sensors_applet); +} + + +#ifdef HAVE_LIBNOTIFY +static void prefs_dialog_display_notifications_toggled(GtkCheckButton *display_notifications, + PrefsDialog *prefs_dialog) { + + gboolean notify; + + notify = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(display_notifications)); + panel_applet_gconf_set_bool(prefs_dialog->sensors_applet->applet, + DISPLAY_NOTIFICATIONS, + notify, + NULL); + + if (notify) { + sensors_applet_update_active_sensors(prefs_dialog->sensors_applet); + } else { + sensors_applet_notify_end_all(prefs_dialog->sensors_applet); + } +} +#endif + +static void prefs_dialog_graph_size_changed(GtkSpinButton *button, + PrefsDialog *prefs_dialog) { + gint value; + value = (gint)(gtk_spin_button_get_value(button)); + panel_applet_gconf_set_int(prefs_dialog->sensors_applet->applet, GRAPH_SIZE, value, NULL); + + /* notify change of number of samples */ + sensors_applet_graph_size_changed(prefs_dialog->sensors_applet); + +} + +/* callbacks for the tree of sensors */ +static void prefs_dialog_sensor_toggled(GtkCellRenderer *renderer, gchar *path_str, PrefsDialog *prefs_dialog) { + GtkTreeIter iter; + GtkTreePath *path; + + gboolean old_value; + + path = gtk_tree_path_new_from_string(path_str); + + gtk_tree_model_get_iter(GTK_TREE_MODEL(prefs_dialog->sensors_applet->sensors), &iter, path); + gtk_tree_model_get(GTK_TREE_MODEL(prefs_dialog->sensors_applet->sensors), + &iter, + ENABLE_COLUMN, &old_value, + -1); + + if (old_value) { + sensors_applet_sensor_disabled(prefs_dialog->sensors_applet, + path); + } else { + sensors_applet_sensor_enabled(prefs_dialog->sensors_applet, + path); + } + + gtk_tree_store_set(prefs_dialog->sensors_applet->sensors, &iter, + ENABLE_COLUMN, !old_value, + -1); + + gtk_tree_path_free(path); +} + +static void prefs_dialog_sensor_name_changed(GtkCellRenderer *renderer, gchar *path_str, gchar *new_text, PrefsDialog *prefs_dialog) { + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string(path_str); + + gtk_tree_model_get_iter(GTK_TREE_MODEL(prefs_dialog->sensors_applet->sensors), &iter, path); + + gtk_tree_store_set(prefs_dialog->sensors_applet->sensors, &iter, LABEL_COLUMN, new_text, -1); + + sensors_applet_update_sensor(prefs_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void prefs_dialog_row_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, PrefsDialog *prefs_dialog) { + /* only bring up dialog this if is a sensor - ie has no + * children */ + GtkTreeIter iter; + GtkTreeModel *model; + + model = gtk_tree_view_get_model(view); + /* make sure can set iter first */ + if (gtk_tree_model_get_iter(model, &iter, path) && !gtk_tree_model_iter_has_child(model, &iter)) { + sensor_config_dialog_create(prefs_dialog->sensors_applet); + } +} + + +static void prefs_dialog_sensor_up_button_clicked(GtkButton *button, PrefsDialog *prefs_dialog) { + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + + if (gtk_tree_selection_get_selected(prefs_dialog->sensors_applet->selection, &model, &iter)) { + /* if has no prev node set up button insentive */ + path = gtk_tree_model_get_path(model, &iter); + if (gtk_tree_path_prev(path)) { + GtkTreeIter prev_iter; + /* check is a valid node in out model */ + if (gtk_tree_model_get_iter(model, &prev_iter, path)) { + gtk_tree_store_move_before(GTK_TREE_STORE(model), + &iter, + &prev_iter); + g_signal_emit_by_name(prefs_dialog->sensors_applet->selection, + "changed"); + + sensors_applet_reorder_sensors(prefs_dialog->sensors_applet); + + + } + } + + gtk_tree_path_free(path); + + } +} + +static void prefs_dialog_sensor_down_button_clicked(GtkButton *button, PrefsDialog *prefs_dialog) { + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeIter iter_next; + + if (gtk_tree_selection_get_selected(prefs_dialog->sensors_applet->selection, &model, &iter)) { + iter_next = iter; + /* if has no next node set down button insentive */ + if (gtk_tree_model_iter_next(model, &iter_next)) { + gtk_tree_store_move_after(GTK_TREE_STORE(model), + &iter, + &iter_next); + g_signal_emit_by_name(prefs_dialog->sensors_applet->selection, + "changed"); + sensors_applet_reorder_sensors(prefs_dialog->sensors_applet); + + } + } +} + + + +static void prefs_dialog_sensor_config_button_clicked(GtkButton *button, PrefsDialog *prefs_dialog) { + sensor_config_dialog_create(prefs_dialog->sensors_applet); +} + + +/* if a sensor is selected, make config sure button is able to be + * clicked and also set the sensitivities properly for the up and down + * buttons */ +static void prefs_dialog_selection_changed(GtkTreeSelection *selection, + PrefsDialog *prefs_dialog) { + GtkTreeIter iter; + GtkTreePath *path; + GtkTreeModel *model; + /* if there is a selection with no children make config button + * sensitive */ + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + if (!gtk_tree_model_iter_has_child(model, &iter)) { + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_config_button), TRUE); + } else { + /* otherwise make insensitive */ + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_config_button), FALSE); + } + + /* if has no prev node set up button insentive */ + path = gtk_tree_model_get_path(model, &iter); + if (gtk_tree_path_prev(path)) { + GtkTreeIter prev_iter; + /* check is a valid node in out model */ + if (gtk_tree_model_get_iter(model, &prev_iter, path)) { + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_up_button), TRUE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_up_button), FALSE); + } + } else { + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_up_button), FALSE); + } + + gtk_tree_path_free(path); + + /* if has no next node set down button insentive */ + if (gtk_tree_model_iter_next(model, &iter)) { + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_down_button), TRUE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_down_button), FALSE); + } + + } else { + /* otherwise make all insensitive */ + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_config_button), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_up_button), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_down_button), FALSE); + + } +} + +void prefs_dialog_open(SensorsApplet *sensors_applet) { + gchar *header_text; + PrefsDialog *prefs_dialog; + DisplayMode display_mode; + + g_assert(sensors_applet->prefs_dialog == NULL); + + /* while prefs dialog is open, stop the updating of sensors so + * we don't get any race conditions due to concurrent updates + * of the labels, values and icons linked lists etc. */ + if (sensors_applet->timeout_id != 0) { + if (g_source_remove(sensors_applet->timeout_id)) { + sensors_applet->timeout_id = 0; + } + } + + sensors_applet->prefs_dialog = g_new0(PrefsDialog, 1); + prefs_dialog = sensors_applet->prefs_dialog; + + prefs_dialog->sensors_applet = sensors_applet; + + prefs_dialog->dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Sensors Applet Preferences"), + NULL, + GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + NULL)); + g_object_set(prefs_dialog->dialog, + "border-width", 12, + "default-width", 480, + "default-height", 350, + NULL); + + gtk_box_set_homogeneous(GTK_BOX(prefs_dialog->dialog->vbox), FALSE); + + gtk_box_set_spacing(GTK_BOX(prefs_dialog->dialog->vbox), 5); + + + g_signal_connect(prefs_dialog->dialog, + "response", G_CALLBACK(prefs_dialog_response), + sensors_applet); + + g_signal_connect_swapped(prefs_dialog->dialog, + "delete-event", G_CALLBACK(prefs_dialog_close), + sensors_applet); + + g_signal_connect_swapped(prefs_dialog->dialog, + "destroy", G_CALLBACK(prefs_dialog_close), + sensors_applet); + + /* if no SensorsList's have been created, this is because + we haven't been able to access any sensors */ + if (sensors_applet->sensors == NULL) { + GtkWidget *label; + label = gtk_label_new(_("No sensors found!")); + gtk_box_pack_start_defaults(GTK_BOX(prefs_dialog->dialog->vbox), label); + return; + } + + + header_text = g_markup_printf_escaped("<b>%s</b>", _("Display")); + prefs_dialog->display_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + + "xalign", 0.0, + NULL); + g_free(header_text); + + prefs_dialog->display_mode_combo_box = GTK_COMBO_BOX(gtk_combo_box_new_text()); + + + gtk_combo_box_append_text(prefs_dialog->display_mode_combo_box, _("label with value")); + gtk_combo_box_append_text(prefs_dialog->display_mode_combo_box, _("icon with value")); + gtk_combo_box_append_text(prefs_dialog->display_mode_combo_box, _("value only")); + gtk_combo_box_append_text(prefs_dialog->display_mode_combo_box, _("icon only")); + gtk_combo_box_append_text(prefs_dialog->display_mode_combo_box, _("graph only")); + + + display_mode = panel_applet_gconf_get_int(sensors_applet->applet, DISPLAY_MODE, NULL); + gtk_combo_box_set_active(prefs_dialog->display_mode_combo_box, display_mode); + + g_signal_connect(prefs_dialog->display_mode_combo_box, + "changed", + G_CALLBACK(prefs_dialog_display_mode_changed), + prefs_dialog); + + + + /* use spaces in label to indent */ + prefs_dialog->display_mode_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("_Display sensors in panel as"), + "mnemonic-widget", prefs_dialog->display_mode_combo_box, + "xalign", 0.0, + NULL); + + + + + prefs_dialog->layout_mode_combo_box = GTK_COMBO_BOX(gtk_combo_box_new_text()); + + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->layout_mode_combo_box), + (display_mode != DISPLAY_ICON) && + (display_mode != DISPLAY_VALUE) && + (display_mode != DISPLAY_GRAPH)); + + gtk_combo_box_append_text(prefs_dialog->layout_mode_combo_box, _("beside labels / icons")); + gtk_combo_box_append_text(prefs_dialog->layout_mode_combo_box, _("below labels / icons")); + + gtk_combo_box_set_active(prefs_dialog->layout_mode_combo_box, panel_applet_gconf_get_int(sensors_applet->applet, LAYOUT_MODE, NULL)); + + g_signal_connect(prefs_dialog->layout_mode_combo_box, + "changed", + G_CALLBACK(prefs_dialog_layout_mode_changed), + prefs_dialog); + + prefs_dialog->layout_mode_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("Preferred _position of sensor values"), + "mnemonic-widget", prefs_dialog->layout_mode_combo_box, + "xalign", 0.0, + NULL); + + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->layout_mode_label), + (display_mode != DISPLAY_ICON) && + (display_mode != DISPLAY_VALUE) && + (display_mode != DISPLAY_GRAPH)); + + prefs_dialog->temperature_scale_combo_box = GTK_COMBO_BOX(gtk_combo_box_new_text()); + + gtk_combo_box_append_text(prefs_dialog->temperature_scale_combo_box, _("Kelvin")); + gtk_combo_box_append_text(prefs_dialog->temperature_scale_combo_box, _("Celsius")); + gtk_combo_box_append_text(prefs_dialog->temperature_scale_combo_box, _("Fahrenheit")); + + gtk_combo_box_set_active(prefs_dialog->temperature_scale_combo_box, panel_applet_gconf_get_int(sensors_applet->applet, TEMPERATURE_SCALE, NULL)); + + g_signal_connect(prefs_dialog->temperature_scale_combo_box, + "changed", + G_CALLBACK(prefs_dialog_temperature_scale_changed), + prefs_dialog); + + prefs_dialog->temperature_scale_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("_Temperature scale"), + "mnemonic-widget", prefs_dialog->temperature_scale_combo_box, + "xalign", 0.0, + NULL); + + prefs_dialog->graph_size_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", (gdouble)panel_applet_gconf_get_int(sensors_applet->applet, + GRAPH_SIZE, + NULL), + "lower", 1.0, + "upper", 100.0, + "step-increment", 1.0, + "page-increment", 10.0, + "page-size", 0.0, + NULL); + + prefs_dialog->graph_size_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", prefs_dialog->graph_size_adjust, + "climb-rate", 1.0, + "digits", 0, + "value", (gdouble)panel_applet_gconf_get_int(sensors_applet->applet, + GRAPH_SIZE, + NULL), + "width-chars", 4, + NULL); + + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->graph_size_spinbutton), + (display_mode == DISPLAY_GRAPH)); + + prefs_dialog->graph_size_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("Graph _size (pixels)"), + "mnemonic-widget", prefs_dialog->graph_size_spinbutton, + "xalign", 0.0, + NULL); + + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->graph_size_label), + (display_mode == DISPLAY_GRAPH)); + + g_signal_connect(prefs_dialog->graph_size_spinbutton, "value-changed", + G_CALLBACK(prefs_dialog_graph_size_changed), + prefs_dialog); + + + header_text = g_markup_printf_escaped("<b>%s</b>", _("Update")); + prefs_dialog->update_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + + "xalign", 0.0, + NULL); + g_free(header_text); + + + prefs_dialog->timeout_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", 2.0, + "lower", 1.5, + "upper", 10.0, + "step-increment", 0.5, + "page-increment", 1.0, + "page-size", 0.0, + NULL); + + prefs_dialog->timeout_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", prefs_dialog->timeout_adjust, + "climb-rate", 0.5, + "digits", 1, + "value", (gdouble) panel_applet_gconf_get_int(sensors_applet->applet, TIMEOUT, NULL) / 1000.0, + "width-chars", 4, + NULL); + + + prefs_dialog->timeout_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("Update _interval (secs)"), + "mnemonic-widget", prefs_dialog->timeout_spinbutton, + "xalign", 0.0, + NULL); + + g_signal_connect(prefs_dialog->timeout_spinbutton, "value-changed", + G_CALLBACK(prefs_dialog_timeout_changed), + prefs_dialog); + +#ifdef HAVE_LIBNOTIFY + header_text = g_markup_printf_escaped("<b>%s</b>", _("Notifications")); + prefs_dialog->notifications_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + + "xalign", 0.0, + NULL); + g_free(header_text); + + prefs_dialog->display_notifications = g_object_new(GTK_TYPE_CHECK_BUTTON, + "use-underline", TRUE, + "label", _("Display _notifications"), + NULL); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(prefs_dialog->display_notifications), + panel_applet_gconf_get_bool(sensors_applet->applet, + DISPLAY_NOTIFICATIONS, + NULL)); + g_signal_connect(prefs_dialog->display_notifications, + "toggled", + G_CALLBACK(prefs_dialog_display_notifications_toggled), + prefs_dialog); +#endif + + /* SIZE AND LAYOUT */ + /* keep all widgets same size */ + prefs_dialog->size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + + gtk_size_group_add_widget(prefs_dialog->size_group, + GTK_WIDGET(prefs_dialog->display_mode_combo_box)); + + gtk_size_group_add_widget(prefs_dialog->size_group, + GTK_WIDGET(prefs_dialog->layout_mode_combo_box)); + + gtk_size_group_add_widget(prefs_dialog->size_group, + GTK_WIDGET(prefs_dialog->temperature_scale_combo_box)); + + gtk_size_group_add_widget(prefs_dialog->size_group, + GTK_WIDGET(prefs_dialog->timeout_spinbutton)); + + g_object_unref(prefs_dialog->size_group); + + prefs_dialog->globals_table = g_object_new(GTK_TYPE_TABLE, + "homogeneous", FALSE, + "n-columns", 3, +#ifdef HAVE_LIBNOTIFY + "n-rows", 9, +#else + "n-rows", 7, +#endif + "row-spacing", 6, + "column-spacing", 12, + NULL); + + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->display_header), + 0, 2, + 0, 1, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->display_mode_label), + 1, 2, + 1, 2, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->display_mode_combo_box), + 2, 3, + 1, 2, + GTK_FILL, + GTK_FILL, + 0, + 0); + + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->layout_mode_label), + 1, 2, + 2, 3, + GTK_FILL, + GTK_FILL, + 0, + 0); + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->layout_mode_combo_box), + 2, 3, + 2, 3, + GTK_FILL, + GTK_FILL, + 0, + 0); + + + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->graph_size_label), + 1, 2, + 3, 4, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->graph_size_spinbutton), + 2, 3, + 3, 4, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->temperature_scale_label), + 1, 2, + 4, 5, + GTK_FILL, + GTK_FILL, + 0, + 0); + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->temperature_scale_combo_box), + 2, 3, + 4, 5, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->update_header), + 0, 2, + 5, 6, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->timeout_label), + 1, 2, + 6, 7, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->timeout_spinbutton), + 2, 3, + 6, 7, + GTK_FILL, + GTK_FILL, + 0, + 0); + + +#ifdef HAVE_LIBNOTIFY + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->notifications_header), + 0, 2, + 7, 8, + GTK_FILL, + GTK_FILL, + 0, + 0); + + gtk_table_attach(prefs_dialog->globals_table, + GTK_WIDGET(prefs_dialog->display_notifications), + 1, 2, + 8, 9, + GTK_FILL, + GTK_FILL, + 0, + 0); +#endif + + + prefs_dialog->view = g_object_new(GTK_TYPE_TREE_VIEW, + "model", GTK_TREE_MODEL(sensors_applet->sensors), + "rules-hint", TRUE, + "reorderable", FALSE, + "enable-search", TRUE, + "search-column", LABEL_COLUMN, + NULL); + + /* get double clicks on rows - do same as configure sensor + * button clicks */ + g_signal_connect(prefs_dialog->view, "row-activated", + G_CALLBACK(prefs_dialog_row_activated), + prefs_dialog); + + prefs_dialog->id_renderer = gtk_cell_renderer_text_new(); + prefs_dialog->label_renderer = gtk_cell_renderer_text_new(); + g_object_set(prefs_dialog->label_renderer, + "editable", TRUE, + NULL); + + g_signal_connect(prefs_dialog->label_renderer, "edited", + G_CALLBACK(prefs_dialog_sensor_name_changed), + prefs_dialog); + + prefs_dialog->enable_renderer = gtk_cell_renderer_toggle_new(); + g_signal_connect(prefs_dialog->enable_renderer, "toggled", + G_CALLBACK(prefs_dialog_sensor_toggled), + prefs_dialog); + prefs_dialog->icon_renderer = gtk_cell_renderer_pixbuf_new(); + + prefs_dialog->id_column = gtk_tree_view_column_new_with_attributes(_("Sensor"), + prefs_dialog->id_renderer, + "text", ID_COLUMN, + NULL); + + gtk_tree_view_column_set_min_width(prefs_dialog->id_column, 90); + + prefs_dialog->label_column = gtk_tree_view_column_new_with_attributes(_("Label"), + prefs_dialog->label_renderer, + "text", LABEL_COLUMN, + "visible", VISIBLE_COLUMN, + NULL); + + gtk_tree_view_column_set_min_width(prefs_dialog->label_column, 100); + + /* create the tooltip */ + gtk_widget_set_tooltip_text(GTK_WIDGET(prefs_dialog->view), + _("Labels can be edited directly by clicking on them.")); + prefs_dialog->enable_column = gtk_tree_view_column_new_with_attributes(_("Enabled"), + prefs_dialog->enable_renderer, + "active", ENABLE_COLUMN, + "visible", VISIBLE_COLUMN, + NULL); + + prefs_dialog->icon_column = gtk_tree_view_column_new_with_attributes(_("Icon"), + prefs_dialog->icon_renderer, + "pixbuf", ICON_PIXBUF_COLUMN, + "visible", VISIBLE_COLUMN, + NULL); + gtk_tree_view_append_column(prefs_dialog->view, + prefs_dialog->id_column); + gtk_tree_view_append_column(prefs_dialog->view, + prefs_dialog->icon_column); + gtk_tree_view_append_column(prefs_dialog->view, + prefs_dialog->label_column); + gtk_tree_view_append_column(prefs_dialog->view, + prefs_dialog->enable_column); + + gtk_tree_view_columns_autosize(prefs_dialog->view); + + prefs_dialog->scrolled_window = g_object_new(GTK_TYPE_SCROLLED_WINDOW, + "hadjustment", NULL, + "height-request", 200, + "hscrollbar-policy", GTK_POLICY_AUTOMATIC, + "vadjustment",NULL, + "vscrollbar-policy", GTK_POLICY_AUTOMATIC, + NULL); + + gtk_container_add(GTK_CONTAINER(prefs_dialog->scrolled_window), GTK_WIDGET(prefs_dialog->view)); + + /* GtkTree Selection */ + sensors_applet->selection = gtk_tree_view_get_selection(prefs_dialog->view); + /* allow user to only select one row at a time at most */ + gtk_tree_selection_set_mode(sensors_applet->selection, GTK_SELECTION_SINGLE); + /* when selection is changed, make sure sensor_config button is + activated */ + + /* Create buttons for user to interact with sensors tree */ + prefs_dialog->sensor_up_button = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_GO_UP)); + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_up_button), FALSE); + + g_signal_connect(prefs_dialog->sensor_up_button, "clicked", + G_CALLBACK(prefs_dialog_sensor_up_button_clicked), + prefs_dialog); + + prefs_dialog->sensor_down_button = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_GO_DOWN)); + gtk_widget_set_sensitive(GTK_WIDGET(prefs_dialog->sensor_down_button), FALSE); + + g_signal_connect(prefs_dialog->sensor_down_button, "clicked", + G_CALLBACK(prefs_dialog_sensor_down_button_clicked), + prefs_dialog); + + + prefs_dialog->buttons_box = GTK_VBUTTON_BOX(gtk_vbutton_box_new()); + + gtk_button_box_set_layout(GTK_BUTTON_BOX(prefs_dialog->buttons_box), + GTK_BUTTONBOX_SPREAD); + + gtk_box_pack_start(GTK_BOX(prefs_dialog->buttons_box), GTK_WIDGET(prefs_dialog->sensor_up_button), FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(prefs_dialog->buttons_box), GTK_WIDGET(prefs_dialog->sensor_down_button), FALSE, FALSE, 0); + + prefs_dialog->sensors_hbox = g_object_new(GTK_TYPE_HBOX, + "border-width", 5, + "homogeneous", FALSE, + "spacing", 5, + NULL); + + gtk_box_pack_start(prefs_dialog->sensors_hbox, + GTK_WIDGET(prefs_dialog->scrolled_window), + TRUE, TRUE, 0); /* make sure window takes + * up most of room */ + + gtk_box_pack_start(prefs_dialog->sensors_hbox, + GTK_WIDGET(prefs_dialog->buttons_box), + FALSE, FALSE, 0); + + + /* Sensor Config button */ + /* initially make button insensitive until user selects a row + from the sensors tree */ + prefs_dialog->sensor_config_button = GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_PROPERTIES)); + g_object_set(prefs_dialog->sensor_config_button, + "sensitive", FALSE, + NULL); + + + g_signal_connect(sensors_applet->selection, + "changed", + G_CALLBACK(prefs_dialog_selection_changed), + prefs_dialog); + + /* pass selection to signal handler so we can give user a + sensors_applet->prefs_dialog with the selected rows alarm + value and enable */ + g_signal_connect(prefs_dialog->sensor_config_button, "clicked", + G_CALLBACK(prefs_dialog_sensor_config_button_clicked), + prefs_dialog); + + prefs_dialog->sensor_config_hbox = g_object_new(GTK_TYPE_HBOX, + "border-width", 5, + "homogeneous", FALSE, + "spacing", 0, + NULL); + gtk_box_pack_end(prefs_dialog->sensor_config_hbox, + GTK_WIDGET(prefs_dialog->sensor_config_button), + FALSE, FALSE, 0); + + /* pack sensors_vbox */ + prefs_dialog->sensors_vbox = g_object_new(GTK_TYPE_VBOX, + "border-width", 5, + "homogeneous", FALSE, + "spacing", 0, + NULL); + + gtk_box_pack_start(prefs_dialog->sensors_vbox, + GTK_WIDGET(prefs_dialog->sensors_hbox), + TRUE, TRUE, 0); + gtk_box_pack_start(prefs_dialog->sensors_vbox, + GTK_WIDGET(prefs_dialog->sensor_config_hbox), + FALSE, FALSE, 0); + + prefs_dialog->globals_alignment = g_object_new(GTK_TYPE_ALIGNMENT, + "xalign", 0.5, + "yalign", 0.0, + "top-padding", 12, + "left-padding", 12, + "bottom-padding", 12, + "right-padding", 12, + NULL); + gtk_container_add(GTK_CONTAINER(prefs_dialog->globals_alignment), + GTK_WIDGET(prefs_dialog->globals_table)); + + prefs_dialog->notebook = g_object_new(GTK_TYPE_NOTEBOOK, + NULL); + + gtk_notebook_append_page(prefs_dialog->notebook, + GTK_WIDGET(prefs_dialog->globals_alignment), + gtk_label_new(_("General Options"))); + + gtk_notebook_append_page(prefs_dialog->notebook, + GTK_WIDGET(prefs_dialog->sensors_vbox), + gtk_label_new(_("Sensors"))); + + /* pack notebook into prefs_dialog */ + gtk_box_pack_start_defaults(GTK_BOX(prefs_dialog->dialog->vbox), + GTK_WIDGET(prefs_dialog->notebook)); + + + gtk_widget_show_all(GTK_WIDGET(prefs_dialog->dialog)); +} diff --git a/sensors-applet/prefs-dialog.h b/sensors-applet/prefs-dialog.h new file mode 100644 index 0000000..5d1270b --- /dev/null +++ b/sensors-applet/prefs-dialog.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PREFS_DIALOG_H +#define PREFS_DIALOG_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "sensors-applet.h" + +typedef struct { + SensorsApplet *sensors_applet; + GtkDialog *dialog; + GtkNotebook *notebook; + + /* widgets for global prefs */ + GtkSpinButton *timeout_spinbutton, *graph_size_spinbutton; + GtkTable *globals_table; + GtkHSeparator *globals_separator; + GtkComboBox *display_mode_combo_box, *layout_mode_combo_box, *temperature_scale_combo_box; + GtkLabel *timeout_label, *display_mode_label, *layout_mode_label, *temperature_scale_label, *graph_size_label, *update_header, *display_header; + GtkAdjustment *timeout_adjust, *graph_size_adjust; + +#ifdef HAVE_LIBNOTIFY + GtkCheckButton *display_notifications; + GtkLabel *notifications_header; +#endif + + /* widgets for sensors tree */ + GtkTreeView *view; + GtkTreeViewColumn *id_column, *label_column, *enable_column, *icon_column; + GtkCellRenderer *id_renderer, *label_renderer, *enable_renderer, *icon_renderer; + GtkScrolledWindow *scrolled_window; + + GtkVButtonBox *buttons_box; /* holds sensor reorder buttons */ + GtkBox *sensors_hbox; /* holds scrolled window and + * buttons_vbox */ + GtkAlignment *globals_alignment; + GtkBox *sensors_vbox; /* holds sensors_hbox and sensor_config_hbox */ + GtkBox *sensor_config_hbox; /* holds config button */ + GtkSizeGroup *size_group; /* so comboboxes all + * request the same size */ + + GtkButton *sensor_up_button; + GtkButton *sensor_down_button; + GtkButton *sensor_config_button; +} PrefsDialog; + +/* function prototypes */ +void prefs_dialog_open(SensorsApplet *sensors_applet); +void prefs_dialog_close(SensorsApplet *sensors_applet); + +#endif /* PREFS_DIALOG_H */ diff --git a/sensors-applet/sensor-config-dialog.c b/sensors-applet/sensor-config-dialog.c new file mode 100644 index 0000000..bd55836 --- /dev/null +++ b/sensors-applet/sensor-config-dialog.c @@ -0,0 +1,918 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <gnome.h> +#include "sensor-config-dialog.h" +#include "sensors-applet.h" + +#define SPINBUTTON_WIDTH_CHARS 8 +#define VALUE_DECIMAL_PLACES 3 + +typedef struct { + SensorsApplet *sensors_applet; + + GtkWidget *dialog; + /* icon widgets */ + GtkLabel *icon_header, *icon_type_label; + GtkComboBox *icon_type_combo_box; + GtkAlignment *icon_type_combo_box_aligner; + GtkCellRenderer *icon_renderer; + + /* Graph Color chooser */ + GtkColorButton *graph_color_button; + GtkAlignment *graph_color_button_aligner; + GtkLabel *graph_color_label, *graph_header; + + /* multiplier and offset widgets */ + GtkLabel *scale_header, *multiplier_label, *offset_label; + GtkAlignment *multiplier_spinbutton_aligner, *offset_spinbutton_aligner; + GtkAdjustment *multiplier_adjust, *offset_adjust; + GtkSpinButton *multiplier_spinbutton, *offset_spinbutton; + + GtkLabel *limits_header; + GtkLabel *low_value_label, *high_value_label; + GtkAlignment *low_value_spinbutton_aligner, *high_value_spinbutton_aligner; + GtkAdjustment *low_value_adjust, *high_value_adjust; + GtkSpinButton *low_value_spinbutton, *high_value_spinbutton; + + /* alarm widgets */ + GtkLabel *alarm_header; + GtkLabel *low_alarm_command_label, *high_alarm_command_label, *alarm_timeout_label; + GtkAlignment *alarm_timeout_spinbutton_aligner; + GtkAdjustment *alarm_timeout_adjust; + GtkSpinButton *alarm_timeout_spinbutton; + GtkTable *table; + GtkAlignment *alarm_enable_aligner; + GtkCheckButton *alarm_enable_checkbutton; + GtkEntry *low_alarm_command_entry, *high_alarm_command_entry; + + GtkSizeGroup *size_group; +} SensorConfigDialog; + +static void sensor_config_dialog_response(GtkDialog *dialog, + gint response, + gpointer data) { + SensorConfigDialog *config_dialog; + GError *error = NULL; + + config_dialog = (SensorConfigDialog *)data; + + switch (response) { + case GTK_RESPONSE_HELP: + g_debug("loading help in config dialog"); + gtk_show_uri(NULL, + "ghelp:sensors-applet?sensors-applet-sensors", + gtk_get_current_event_time(), + &error); + + if (error) { + g_debug("Could not open help document: %s ",error->message); + g_error_free (error); + } + break; + default: + g_debug("destroying config dialog"); + gtk_widget_destroy(GTK_WIDGET(dialog)); + } +} + +static void sensor_config_dialog_multiplier_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gdouble value; + + value = gtk_spin_button_get_value(spinbutton); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + MULTIPLIER_COLUMN, value, + -1); + + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_offset_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gdouble value; + + value = gtk_spin_button_get_value(spinbutton); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + OFFSET_COLUMN, value, + -1); + + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_low_value_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gdouble value; + + value = gtk_spin_button_get_value(spinbutton); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + LOW_VALUE_COLUMN, value, + -1); + + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_high_value_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gdouble value; + + value = gtk_spin_button_get_value(spinbutton); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + HIGH_VALUE_COLUMN, value, + -1); + + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_alarm_toggled(GtkToggleButton *button, SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + + gboolean value; + value = gtk_toggle_button_get_active(button); + + /* update state of alarm widgets */ + gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->alarm_timeout_label), value); + gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->alarm_timeout_spinbutton), value); + gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->low_alarm_command_label), value); + gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->low_alarm_command_entry), value); + gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->high_alarm_command_label), value); + gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->high_alarm_command_entry), value); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + ALARM_ENABLE_COLUMN, value, + -1); + + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_alarm_timeout_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gint value; + + value = gtk_spin_button_get_value_as_int(spinbutton); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + + sensors_applet_all_alarms_off(config_dialog->sensors_applet, path); + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + ALARM_TIMEOUT_COLUMN, value, + -1); + + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_alarm_command_edited(GtkEntry *command_entry, SensorConfigDialog *config_dialog, NotifType notif_type) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + + gchar *value; + g_object_get(command_entry, "text", &value, NULL); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + + sensors_applet_alarm_off(config_dialog->sensors_applet, path, notif_type); + + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + (notif_type == LOW_ALARM ? + LOW_ALARM_COMMAND_COLUMN : HIGH_ALARM_COMMAND_COLUMN), + value, + -1); + g_free(value); + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +static void sensor_config_dialog_low_alarm_command_edited(GtkEntry *command_entry, SensorConfigDialog *config_dialog) { + sensor_config_dialog_alarm_command_edited(command_entry, + config_dialog, + LOW_ALARM); +} + +static void sensor_config_dialog_high_alarm_command_edited(GtkEntry *command_entry, SensorConfigDialog *config_dialog) { + sensor_config_dialog_alarm_command_edited(command_entry, + config_dialog, + HIGH_ALARM); +} + +static void sensor_config_dialog_icon_type_changed(GtkComboBox *icon_type_combo_box, + SensorConfigDialog *config_dialog) { + GtkTreeModel *icons_model; + GtkTreeIter icons_iter; + + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + + GdkPixbuf *new_icon; + IconType icon_type; + + icons_model = gtk_combo_box_get_model(icon_type_combo_box); + if (gtk_combo_box_get_active_iter(icon_type_combo_box, + &icons_iter)) { + + gtk_tree_model_get(icons_model, &icons_iter, + 0, &new_icon, + -1); + + icon_type = gtk_combo_box_get_active(icon_type_combo_box); + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + + path = gtk_tree_model_get_path(model, &iter); + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + ICON_TYPE_COLUMN, icon_type, + ICON_PIXBUF_COLUMN, new_icon, + -1); + g_object_unref(new_icon); + sensors_applet_icon_changed(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); + } +} + +static void sensor_config_dialog_graph_color_set(GtkColorButton *color_button, + SensorConfigDialog *config_dialog) { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + GdkColor color; + gchar *color_string; + + gtk_color_button_get_color(color_button, + &color); + + color_string = g_strdup_printf("#%02X%02X%02X", color.red / 256, + color.green / 256, color.blue / 256); + + gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection, + &model, + &iter); + + gtk_tree_store_set(config_dialog->sensors_applet->sensors, + &iter, + GRAPH_COLOR_COLUMN, color_string, + -1); + + g_free(color_string); + + path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors), + &iter); + sensors_applet_update_sensor(config_dialog->sensors_applet, path); + gtk_tree_path_free(path); +} + +void sensor_config_dialog_create(SensorsApplet *sensors_applet) { + GtkTreeModel *model; + GtkTreeIter iter; + + SensorConfigDialog *config_dialog; + + GtkListStore *icon_store; + IconType count; + GdkPixbuf *pixbuf; + + GdkColor graph_color; + gchar *sensor_label; + gchar *header_text; + + /* instance variables for data */ + gdouble low_value, high_value, multiplier, offset; + gboolean alarm_enable; + gchar *low_alarm_command, *high_alarm_command; + gint alarm_timeout; + IconType icon_type; + gchar *graph_color_string; + + config_dialog = g_new0(SensorConfigDialog, 1); + config_dialog->sensors_applet = sensors_applet; + + gtk_tree_selection_get_selected(sensors_applet->selection, + &model, + &iter); + /* get current values of alarm and its enable */ + gtk_tree_model_get(model, &iter, + LOW_VALUE_COLUMN, &low_value, + HIGH_VALUE_COLUMN, &high_value, + ALARM_ENABLE_COLUMN, &alarm_enable, + LOW_ALARM_COMMAND_COLUMN, &low_alarm_command, + HIGH_ALARM_COMMAND_COLUMN, &high_alarm_command, + ALARM_TIMEOUT_COLUMN, &alarm_timeout, + MULTIPLIER_COLUMN, &multiplier, + OFFSET_COLUMN, &offset, + ICON_TYPE_COLUMN, &icon_type, + GRAPH_COLOR_COLUMN, &graph_color_string, + LABEL_COLUMN, &sensor_label, + -1); + header_text = g_strdup_printf("%s - %s", _("Sensor Properties"), sensor_label); + + config_dialog->dialog = gtk_dialog_new_with_buttons(header_text, + GTK_WINDOW(sensors_applet->prefs_dialog->dialog), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_HELP, + GTK_RESPONSE_HELP, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + NULL); + + g_free(header_text); + g_free(sensor_label); + + g_object_set(config_dialog->dialog, + "border-width", 12, + NULL); + + g_signal_connect(config_dialog->dialog, + "response", + G_CALLBACK(sensor_config_dialog_response), + config_dialog); + + + /* graph stuff */ + header_text = g_markup_printf_escaped("<b>%s</b>", _("Graph")); + config_dialog->graph_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + "xalign", 0.0, + NULL); + g_free(header_text); + + + gdk_color_parse(graph_color_string, + &graph_color); + + config_dialog->graph_color_button = GTK_COLOR_BUTTON(gtk_color_button_new_with_color(&graph_color)); + config_dialog->graph_color_button_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->graph_color_button, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + gtk_color_button_set_title(config_dialog->graph_color_button, _("Graph Color")); + + config_dialog->graph_color_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Graph _color"), + "mnemonic-widget", config_dialog->graph_color_button, + "use-underline", TRUE, + "xalign", 0.0, + NULL); + + g_signal_connect(config_dialog->graph_color_button, "color-set", + G_CALLBACK(sensor_config_dialog_graph_color_set), + config_dialog); + + /* icon stuff */ + header_text = g_markup_printf_escaped("<b>%s</b>", _("Icon")); + config_dialog->icon_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + "xalign", 0.0, + NULL); + g_free(header_text); + + /* icon type */ + icon_store = gtk_list_store_new(1, GDK_TYPE_PIXBUF); + + /* populate list with icons */ + for (count = CPU_ICON; count < NUM_ICONS; count++) { + pixbuf = sensors_applet_load_icon(count); + if (pixbuf) { + gtk_list_store_insert(icon_store, &iter, count); + gtk_list_store_set(icon_store, &iter, + 0, pixbuf, + -1); + /* let list hold icons */ + g_object_unref(pixbuf); + } + } + + config_dialog->icon_type_combo_box = GTK_COMBO_BOX(gtk_combo_box_new_with_model(GTK_TREE_MODEL(icon_store))); + + config_dialog->icon_type_combo_box_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->icon_type_combo_box, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + config_dialog->icon_renderer = gtk_cell_renderer_pixbuf_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(config_dialog->icon_type_combo_box), + GTK_CELL_RENDERER(config_dialog->icon_renderer), + FALSE); + + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(config_dialog->icon_type_combo_box), + GTK_CELL_RENDERER(config_dialog->icon_renderer), + "pixbuf", 0); + + gtk_combo_box_set_active(config_dialog->icon_type_combo_box, + icon_type); + + g_signal_connect(config_dialog->icon_type_combo_box, "changed", + G_CALLBACK(sensor_config_dialog_icon_type_changed), + config_dialog); + + + + config_dialog->icon_type_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Sensor _icon"), + "mnemonic-widget", config_dialog->icon_type_combo_box, + "use-underline", TRUE, + "xalign", 0.0, + NULL); + + header_text = g_markup_printf_escaped("<b>%s</b>", _("Scaling Parameters")); + config_dialog->scale_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + "xalign", 0.0, + NULL); + g_free(header_text); + + /* do multiplier and offset widgets */ + config_dialog->multiplier_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", 1.0, + "lower", 0.001, + "upper", 1000.0, + "step-increment", 0.1, + "page-increment", 1.0, + "page-size", 1.0, + NULL); + + + config_dialog->multiplier_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", config_dialog->multiplier_adjust, + "digits", VALUE_DECIMAL_PLACES, + "value", multiplier, + "width-chars", SPINBUTTON_WIDTH_CHARS, + NULL); + + config_dialog->multiplier_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->multiplier_spinbutton, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + config_dialog->multiplier_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Sensor value _multiplier"), + "mnemonic-widget", config_dialog->multiplier_spinbutton, + "use-underline", TRUE, + "xalign", 0.0, + NULL); + + + g_signal_connect(config_dialog->multiplier_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_multiplier_changed), config_dialog); + + + config_dialog->offset_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", 0.0, + "lower", -1000.000, + "upper", 1000.000, + "step-increment", 0.01, + "page-increment", 1.0, + "page-size", 1.0, + NULL); + + config_dialog->offset_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", config_dialog->offset_adjust, + "digits", VALUE_DECIMAL_PLACES, + "value", (gdouble)offset, + "width-chars", SPINBUTTON_WIDTH_CHARS, + NULL); + + config_dialog->offset_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->offset_spinbutton, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + config_dialog->offset_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Sensor value _offset"), + "mnemonic-widget", config_dialog->offset_spinbutton, + "use-underline", TRUE, + "xalign", 0.0, + NULL); + + g_signal_connect(config_dialog->offset_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_offset_changed), config_dialog); + + + /* now do alarm widgets */ + header_text = g_markup_printf_escaped("<b>%s</b>", _("Sensor Limits")); + config_dialog->limits_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + "xalign", 0.0, + NULL); + g_free(header_text); + + config_dialog->low_value_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", 0.0, + "lower", -100000.0, + "upper", 100000.0, + "step-increment", 1.0, + "page-increment", 10.0, + "page-size", 100.0, + NULL); + + + config_dialog->low_value_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", config_dialog->low_value_adjust, + "digits", VALUE_DECIMAL_PLACES, + "value", low_value, + "width-chars", SPINBUTTON_WIDTH_CHARS, + + NULL); + + config_dialog->low_value_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->low_value_spinbutton, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + config_dialog->low_value_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Sensor _low value"), + "mnemonic-widget", config_dialog->low_value_spinbutton, + "use-underline", TRUE, + "xalign", 0.0, + + NULL); + + + g_signal_connect(config_dialog->low_value_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_low_value_changed), config_dialog); + + config_dialog->high_value_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", 0.0, + "lower", -100000.0, + "upper", 100000.0, + "step-increment", 1.0, + "page-increment", 10.0, + "page-size", 100.0, + NULL); + + + config_dialog->high_value_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", config_dialog->high_value_adjust, + "digits", VALUE_DECIMAL_PLACES, + "value", high_value, + "width-chars", SPINBUTTON_WIDTH_CHARS, + + NULL); + + config_dialog->high_value_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->high_value_spinbutton, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + config_dialog->high_value_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Sensor _high value"), + "mnemonic-widget", config_dialog->high_value_spinbutton, + "use-underline", TRUE, + "xalign", 0.0, + + NULL); + + + g_signal_connect(config_dialog->high_value_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_high_value_changed), config_dialog); + + + header_text = g_markup_printf_escaped("<b>%s</b>", _("Alarm")); + config_dialog->alarm_header = g_object_new(GTK_TYPE_LABEL, + "use-markup", TRUE, + "label", header_text, + "xalign", 0.0, + NULL); + g_free(header_text); + + config_dialog->alarm_timeout_adjust = g_object_new(GTK_TYPE_ADJUSTMENT, + "value", 0.0, + "lower", 0.0, + "upper", 10000.0, + "step-increment", 1.0, + "page-increment", 10.0, + "page-size", 100.0, + NULL); + + config_dialog->alarm_timeout_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON, + "adjustment", config_dialog->alarm_timeout_adjust, + "digits", 0, + "value", (gdouble)alarm_timeout, + "width-chars", SPINBUTTON_WIDTH_CHARS, + "sensitive", alarm_enable, + + NULL); + config_dialog->alarm_timeout_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->alarm_timeout_spinbutton, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + config_dialog->alarm_timeout_label = g_object_new(GTK_TYPE_LABEL, + "label", _("Alarm _repeat interval (secs)"), + "mnemonic-widget", config_dialog->alarm_timeout_spinbutton, + + "use-underline", TRUE, + "xalign", 0.0, + "sensitive", alarm_enable, + NULL); + + g_signal_connect(config_dialog->alarm_timeout_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_alarm_timeout_changed), config_dialog); + + config_dialog->low_alarm_command_entry = g_object_new(GTK_TYPE_ENTRY, + "text", low_alarm_command, + "width-chars", 25, + "sensitive", alarm_enable, + NULL); + + g_free(low_alarm_command); + + config_dialog->low_alarm_command_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("Lo_w alarm command"), + "mnemonic-widget", config_dialog->low_alarm_command_entry, + "xalign", 0.0, + "sensitive", alarm_enable, + + NULL); + + g_signal_connect(config_dialog->low_alarm_command_entry, + "changed", + G_CALLBACK(sensor_config_dialog_low_alarm_command_edited), + config_dialog); + + config_dialog->high_alarm_command_entry = g_object_new(GTK_TYPE_ENTRY, + "text", high_alarm_command, + "width-chars", 25, + "sensitive", alarm_enable, + NULL); + + g_free(high_alarm_command); + + config_dialog->high_alarm_command_label = g_object_new(GTK_TYPE_LABEL, + "use-underline", TRUE, + "label", _("Hi_gh alarm command"), + "mnemonic-widget", config_dialog->high_alarm_command_entry, + "xalign", 0.0, + "sensitive", alarm_enable, + + NULL); + + g_signal_connect(config_dialog->high_alarm_command_entry, + "changed", + G_CALLBACK(sensor_config_dialog_high_alarm_command_edited), + config_dialog); + + config_dialog->alarm_enable_checkbutton = g_object_new(GTK_TYPE_CHECK_BUTTON, + "use-underline", TRUE, + "label", _("_Enable alarm"), + "active", alarm_enable, + "xalign", 0.0, + NULL); + + config_dialog->alarm_enable_aligner = g_object_new(GTK_TYPE_ALIGNMENT, + "child", config_dialog->alarm_enable_checkbutton, + "xalign", 0.0, + "xscale", 0.0, + NULL); + + g_signal_connect(config_dialog->alarm_enable_checkbutton, "toggled", G_CALLBACK(sensor_config_dialog_alarm_toggled), config_dialog); + + + + config_dialog->size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->multiplier_spinbutton)); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->offset_spinbutton)); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->low_value_spinbutton)); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->high_value_spinbutton)); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->alarm_timeout_spinbutton)); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->icon_type_combo_box)); + gtk_size_group_add_widget(config_dialog->size_group, + GTK_WIDGET(config_dialog->graph_color_button)); + g_object_unref(config_dialog->size_group); + + config_dialog->table = g_object_new(GTK_TYPE_TABLE, + "column-spacing", 5, + "homogeneous", FALSE, + "n-columns", 3, + "n-rows", 15, + "row-spacing", 6, + "column-spacing", 12, + NULL); + + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->scale_header), + 0, 2, + 0, 1); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->multiplier_label), + 1, 2, + 1, 2); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->multiplier_spinbutton_aligner), + 2, 3, + 1, 2); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->offset_label), + 1, 2, + 2, 3); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->offset_spinbutton_aligner), + 2, 3, + 2, 3); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->limits_header), + 0, 2, + 3, 4); + + /* now pack alarm widgets */ + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->low_value_label), + 1, 2, + 4, 5); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->low_value_spinbutton_aligner), + 2, 3, + 4, 5); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->high_value_label), + 1, 2, + 5, 6); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->high_value_spinbutton_aligner), + 2, 3, + 5, 6); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->alarm_header), + 0, 2, + 6, 7); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->alarm_enable_aligner), + 1, 2, + 7, 8); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->alarm_timeout_label), + 1, 2, + 8, 9); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->alarm_timeout_spinbutton_aligner), + 2, 3, + 8, 9); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->low_alarm_command_label), + 1, 2, + 9, 10); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->low_alarm_command_entry), + 2, 3, + 9, 10); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->high_alarm_command_label), + 1, 2, + 10, 11); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->high_alarm_command_entry), + 2, 3, + 10, 11); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->icon_header), + 0, 2, + 11, 12); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->icon_type_label), + 1, 2, + 12, 13); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->icon_type_combo_box_aligner), + 2, 3, + 12, 13); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->graph_header), + 0, 2, + 13, 14); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->graph_color_label), + 1, 2, + 14, 15); + + gtk_table_attach_defaults(config_dialog->table, + GTK_WIDGET(config_dialog->graph_color_button_aligner), + 2, 3, + 14, 15); + + gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(config_dialog->dialog)->vbox), GTK_WIDGET(config_dialog->table)); + gtk_widget_show_all(config_dialog->dialog); + +} diff --git a/sensors-applet/sensor-config-dialog.h b/sensors-applet/sensor-config-dialog.h new file mode 100644 index 0000000..53929f6 --- /dev/null +++ b/sensors-applet/sensor-config-dialog.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SENSOR_CONFIG_DIALOG_H +#define SENSOR_CONFIG_DIALOG_H + +#include "sensors-applet.h" + +/* function definition */ + +void sensor_config_dialog_create(SensorsApplet *sensors_applet); + +#endif /* SENSOR_CONFIG_DIALOG_H */ diff --git a/sensors-applet/sensors-applet-gconf.c b/sensors-applet/sensors-applet-gconf.c new file mode 100644 index 0000000..852a3fc --- /dev/null +++ b/sensors-applet/sensors-applet-gconf.c @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "sensors-applet.h" +#include "sensors-applet-gconf.h" + +#define DEFAULT_TIMEOUT 2000 +#define DEFAULT_GRAPH_SIZE 42 + +static const gchar * const compatible_versions[] = { + PACKAGE_VERSION, /* always list current version */ + "2.2.6", + "2.2.5", + "2.2.4", + "2.2.3", + "2.2.2", +}; + +#define NUM_COMPATIBLE_VERSIONS G_N_ELEMENTS(compatible_versions) + +typedef enum { + SENSORS_APPLET_GCONF_ERROR = 0, + SENSORS_APPLET_VERSION_ERROR, +} SensorsAppletGConfError; + +static const gchar * const error_titles[] = { + N_("An error occurred loading the stored sensors data"), + N_("Incompatible sensors configuration found") +}; + +static const gchar * const error_messages[] = { + N_("An error has occurred when loading the stored sensors data. " + "The default values will be used to recover from this error."), + + N_("Unfortunately the previous configuration for GNOME Sensors Applet " + "is not compatible with this version. The existing sensors data " + "will be overwritten with the default values for this new version.") +}; + +/* function to be called if an error occurs + when loading values from gconf */ +static void sensors_applet_gconf_error_occurred(SensorsAppletGConfError error) { + GtkWidget *dialog; + gchar *markup; + + g_debug("Error occurred: %s", error_titles[error]); + markup = g_markup_printf_escaped("<span size=\"large\" weight=\"bold\">%s</span>\n\n%s", _(error_titles[error]), _(error_messages[error])); + + dialog = gtk_message_dialog_new_with_markup(NULL, /* no parent window */ + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "%s", markup); + + g_free(markup); + + /* runs dialog as modal and doesn't return until user clicks + * button */ + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + + +static void sensors_applet_gconf_set_defaults(SensorsApplet *sensors_applet) { + panel_applet_gconf_set_int(sensors_applet->applet, DISPLAY_MODE, DISPLAY_ICON_WITH_VALUE, NULL); + panel_applet_gconf_set_int(sensors_applet->applet, LAYOUT_MODE, VALUE_BESIDE_LABEL, NULL); + panel_applet_gconf_set_int(sensors_applet->applet, TEMPERATURE_SCALE, CELSIUS, NULL); + panel_applet_gconf_set_int(sensors_applet->applet, TIMEOUT, DEFAULT_TIMEOUT, NULL); + panel_applet_gconf_set_int(sensors_applet->applet, GRAPH_SIZE, DEFAULT_GRAPH_SIZE, NULL); +#ifdef HAVE_LIBNOTIFY + panel_applet_gconf_set_bool(sensors_applet->applet, DISPLAY_NOTIFICATIONS, TRUE, NULL); +#endif + panel_applet_gconf_set_bool(sensors_applet->applet, IS_SETUP, FALSE, NULL); + +} + +/** + * Returns TRUE is old_version is one of the compatible versions + */ +static gboolean sensors_applet_gconf_is_compatible(const gchar *old_version) { + guint i; + for (i = 0; i < NUM_COMPATIBLE_VERSIONS; i++) { + if (g_ascii_strcasecmp(old_version, compatible_versions[i]) == 0) { + return TRUE; + } + } + return FALSE; +} + + +void sensors_applet_gconf_setup(SensorsApplet *sensors_applet) { + gboolean setup = FALSE; + gchar *old_version; + GError *error = NULL; + + /* need to convert old num_samples value to new GRAPH_SIZE + * parameter */ + gint num_samples; + if ((num_samples = panel_applet_gconf_get_int(sensors_applet->applet, + "num_samples", + NULL))) { + g_debug("Convering old num_samples value %d into graph_size", num_samples); + panel_applet_gconf_set_int(sensors_applet->applet, + GRAPH_SIZE, + (num_samples + GRAPH_FRAME_EXTRA_WIDTH), + NULL); + /* reset num_samples to zero */ + panel_applet_gconf_set_int(sensors_applet->applet, + "num_samples", + 0, + NULL); + + } + + /* convert old alarm_commands to high and low if exist */ + GSList *alarm_commands; + if ((alarm_commands = panel_applet_gconf_get_list(sensors_applet->applet, + "alarm_commands", + GCONF_VALUE_STRING, + NULL))) { + + g_debug("Converting old alarm commands to new high and low commands"); + + panel_applet_gconf_set_list(sensors_applet->applet, + LOW_ALARM_COMMANDS, + GCONF_VALUE_STRING, + alarm_commands, + NULL); + panel_applet_gconf_set_list(sensors_applet->applet, + HIGH_ALARM_COMMANDS, + GCONF_VALUE_STRING, + alarm_commands, + NULL); + /* reset old list to null */ + panel_applet_gconf_set_list(sensors_applet->applet, + "alarm_commands", + GCONF_VALUE_STRING, + NULL, + NULL); + g_slist_foreach(alarm_commands, (GFunc)g_free, NULL); + g_slist_free(alarm_commands); + + } + + setup = panel_applet_gconf_get_bool(sensors_applet->applet, + IS_SETUP, &error); + if (error) { + g_debug("Previous configuration not found: %s, setting up manually", error->message); + g_error_free(error); + error = NULL; + setup = FALSE; + } + + + if (setup) { + /* see if setup version matches */ + old_version = panel_applet_gconf_get_string(sensors_applet->applet, + SENSORS_APPLET_VERSION, + &error); + /* if versions don't match or there is no saved + * version string then need to overwrite old config */ + if (error) { + g_debug("Error getting old version string: %s", error->message); + g_error_free(error); + error = NULL; + old_version = NULL; + } + + if (old_version) { + if (sensors_applet_gconf_is_compatible(old_version)) { + /* previously setup and versions match so use + * old values */ + g_debug("GConf data is compatible. Trying to set up sensors from gconf data"); + if (sensors_applet_gconf_setup_sensors(sensors_applet)) { + g_debug("done setting up from gconf"); + } else { + g_debug("Setting gconf defaults only"); + sensors_applet_gconf_set_defaults(sensors_applet); + } + g_free(old_version); + + return; + + + } + g_free(old_version); + + } + sensors_applet_notify(sensors_applet, GCONF_READ_ERROR); + + + sensors_applet_gconf_error_occurred(SENSORS_APPLET_VERSION_ERROR); + } + + /* use defaults */ + g_debug("Setting gconf defaults only"); + sensors_applet_gconf_set_defaults(sensors_applet); +} + +enum { + PATHS_INDEX = 0, + IDS_INDEX, + LABELS_INDEX, + INTERFACES_INDEX, + SENSOR_TYPES_INDEX, + ENABLES_INDEX, + LOW_VALUES_INDEX, + HIGH_VALUES_INDEX, + ALARM_ENABLES_INDEX, + LOW_ALARM_COMMANDS_INDEX, + HIGH_ALARM_COMMANDS_INDEX, + ALARM_TIMEOUTS_INDEX, + MULTIPLIERS_INDEX, + OFFSETS_INDEX, + ICON_TYPES_INDEX, + GRAPH_COLORS_INDEX, + NUM_KEYS +}; + +const gchar * const keys[NUM_KEYS] = { + PATHS, + IDS, + LABELS, + INTERFACES, + SENSOR_TYPES, + ENABLES, + LOW_VALUES, + HIGH_VALUES, + ALARM_ENABLES, + LOW_ALARM_COMMANDS, + HIGH_ALARM_COMMANDS, + ALARM_TIMEOUTS, + MULTIPLIERS, + OFFSETS, + ICON_TYPES, + GRAPH_COLORS, +}; + +/* MUST CORRESPOND TO ABOVE KEYS */ +const GConfValueType key_types[NUM_KEYS] = { + GCONF_VALUE_STRING, /* PATHS */ + GCONF_VALUE_STRING, /* IDS, */ + GCONF_VALUE_STRING, /* LABELS */ + GCONF_VALUE_STRING, /* INTERFACES, */ + GCONF_VALUE_INT, /* SENSOR_TYPES, */ + GCONF_VALUE_BOOL, /* ENABLES, */ + GCONF_VALUE_INT, /* LOW_VALUES, */ + GCONF_VALUE_INT, /* HIGH_VALUES, */ + GCONF_VALUE_BOOL, /* ALARM_ENABLES, */ + GCONF_VALUE_STRING, /* LOW_ALARM_COMMANDS, */ + GCONF_VALUE_STRING, /* HIGH_ALARM_COMMANDS, */ + GCONF_VALUE_INT, /* ALARM_TIMEOUTS, */ + GCONF_VALUE_INT, /* MULTIPLIERS, */ + GCONF_VALUE_INT, /* OFFSETS, */ + GCONF_VALUE_INT, /* ICON_TYPES, */ + GCONF_VALUE_STRING /* GRAPH_COLORS, */ +}; + +void sensors_applet_gconf_set_current_to_lists(GSList *current[], + GSList *lists[], + int len) { + for (len--; len >= 0; len--) { + current[len] = lists[len]; + } +} + +int sensors_applet_gconf_current_not_null(GSList *current[], + int len) { + for (len--; len >= 0; len--) { + if (NULL == current[len]) { + return FALSE; + } + } + return TRUE; +} +void sensors_applet_gconf_current_get_next(GSList *current[], + int len) { + for (len--; len >= 0; len--) { + current[len] = g_slist_next(current[len]); + } +} + +void sensors_applet_gconf_free_lists(GSList *lists[], + int len) { + for (len--; len >= 0; len--) { + if (key_types[len] == GCONF_VALUE_STRING) { + g_slist_foreach(lists[len], (GFunc)g_free, NULL); + } + g_slist_free(lists[len]); + } + +} + +/* gets called if are already setup so we don't have to manually go + through and find sensors etc again */ +gboolean sensors_applet_gconf_setup_sensors(SensorsApplet *sensors_applet) { + /* everything gets stored except alarm timeout indexes, which + we set to -1, and visible which we set to false for all + parent nodes and true for all child nodes */ + int i; + GSList *lists[NUM_KEYS] = {NULL}; + + GSList *current[NUM_KEYS] = {NULL}; + + GError *error = NULL; + + for (i = 0; i < NUM_KEYS; i++) { + lists[i] = panel_applet_gconf_get_list(sensors_applet->applet, + keys[i], + key_types[i], + &error); + if (error || NULL == lists[i]) { + sensors_applet_notify(sensors_applet, GCONF_READ_ERROR); + + sensors_applet_gconf_error_occurred(SENSORS_APPLET_GCONF_ERROR); + if (error) { + g_error_free(error); + } + return FALSE; + } + } + + for (sensors_applet_gconf_set_current_to_lists(current, + lists, + NUM_KEYS); + sensors_applet_gconf_current_not_null(current, + NUM_KEYS); + sensors_applet_gconf_current_get_next(current, + NUM_KEYS)) { + + + g_debug("trying to add sensor from gconf data: %s\n", (gchar *)(current[IDS_INDEX]->data)); + /* need to ensure correct order */ + sensors_applet_add_sensor(sensors_applet, + (gchar *)(current[PATHS_INDEX]->data), + (gchar *)(current[IDS_INDEX]->data), + (gchar *)(current[LABELS_INDEX]->data), + (gchar *)(current[INTERFACES_INDEX]->data), + GPOINTER_TO_UINT(current[SENSOR_TYPES_INDEX]->data), + GPOINTER_TO_INT(current[ENABLES_INDEX]->data), + (gdouble)(GPOINTER_TO_INT(current[LOW_VALUES_INDEX]->data) / 1000.0), + (gdouble)(GPOINTER_TO_INT(current[HIGH_VALUES_INDEX]->data) / 1000.0), + GPOINTER_TO_INT(current[ALARM_ENABLES_INDEX]->data), + (gchar *)(current[LOW_ALARM_COMMANDS_INDEX]->data), + (gchar *)(current[HIGH_ALARM_COMMANDS_INDEX]->data), + GPOINTER_TO_INT(current[ALARM_TIMEOUTS_INDEX]->data), + (gdouble)(GPOINTER_TO_INT(current[MULTIPLIERS_INDEX]->data) / 1000.0), + (gdouble)(GPOINTER_TO_INT(current[OFFSETS_INDEX]->data) / 1000.0), + (SensorType)GPOINTER_TO_UINT(current[ICON_TYPES_INDEX]->data), + (gchar *)(current[GRAPH_COLORS_INDEX]->data) + + ); + + } + sensors_applet_gconf_free_lists(lists, + NUM_KEYS); + + return TRUE; +} + + +gboolean sensors_applet_gconf_save_sensors(SensorsApplet *sensors_applet) { + /* write everything to gconf except VISIBLE and + ALARM_TIMEOUT_INDEX */ + /* for stepping through GtkTreeStore data structure */ + GtkTreeIter interfaces_iter, sensors_iter; + gboolean not_end_of_interfaces = TRUE, not_end_of_sensors = TRUE; + + /* make sure all are initialized to null - since list of + * intializers is horter than number of element, rest get set + * to 0 (ie NULL) */ + GSList *lists[NUM_KEYS] = {NULL}; + int i; + gchar *current_path, *current_id, *current_label, *current_interface, + *current_low_alarm_command, *current_high_alarm_command, + *current_graph_color; + gboolean current_enable, current_alarm_enable; + gdouble current_low_value, current_high_value, current_multiplier, + current_offset; + guint current_alarm_timeout, current_sensor_type, + current_icon_type; + + GError *error = NULL; + + /* now step through the GtkTreeStore sensors to + find which sensors are enabled */ + for (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter); not_end_of_interfaces; not_end_of_interfaces = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter)) { + // store a gconf key for this interface + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), + &interfaces_iter, + ID_COLUMN, ¤t_id, + -1); + + panel_applet_gconf_set_bool(sensors_applet->applet, current_id, TRUE, NULL); + g_free(current_id); + + /* reset sensors sentinel */ + not_end_of_sensors = TRUE; + + for (gtk_tree_model_iter_children(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter, &interfaces_iter); not_end_of_sensors; not_end_of_sensors = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter)) { + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), + &sensors_iter, + PATH_COLUMN, ¤t_path, + ID_COLUMN, ¤t_id, + LABEL_COLUMN, ¤t_label, + INTERFACE_COLUMN, ¤t_interface, + SENSOR_TYPE_COLUMN, ¤t_sensor_type, + ENABLE_COLUMN, ¤t_enable, + LOW_VALUE_COLUMN, ¤t_low_value, + HIGH_VALUE_COLUMN, ¤t_high_value, + ALARM_ENABLE_COLUMN, ¤t_alarm_enable, + LOW_ALARM_COMMAND_COLUMN, ¤t_low_alarm_command, + HIGH_ALARM_COMMAND_COLUMN, ¤t_high_alarm_command, + ALARM_TIMEOUT_COLUMN, ¤t_alarm_timeout, + MULTIPLIER_COLUMN, ¤t_multiplier, + OFFSET_COLUMN, ¤t_offset, + ICON_TYPE_COLUMN, ¤t_icon_type, + GRAPH_COLOR_COLUMN, ¤t_graph_color, + -1); + + /* prepend values as this is faster then just + reverse list when finished */ + lists[PATHS_INDEX] = g_slist_prepend(lists[PATHS_INDEX], current_path); + lists[IDS_INDEX] = g_slist_prepend(lists[IDS_INDEX], current_id); + lists[LABELS_INDEX] = g_slist_prepend(lists[LABELS_INDEX], current_label); + lists[INTERFACES_INDEX] = g_slist_prepend(lists[INTERFACES_INDEX], current_interface); + lists[ENABLES_INDEX] = g_slist_prepend(lists[ENABLES_INDEX], GINT_TO_POINTER(current_enable)); + lists[LOW_VALUES_INDEX] = g_slist_prepend(lists[LOW_VALUES_INDEX], GINT_TO_POINTER((gint)(current_low_value * 1000))); + lists[HIGH_VALUES_INDEX] = g_slist_prepend(lists[HIGH_VALUES_INDEX], GINT_TO_POINTER((gint)(current_high_value * 1000))); + lists[ALARM_ENABLES_INDEX] = g_slist_prepend(lists[ALARM_ENABLES_INDEX], GINT_TO_POINTER(current_alarm_enable)); + lists[LOW_ALARM_COMMANDS_INDEX] = g_slist_prepend(lists[LOW_ALARM_COMMANDS_INDEX], current_low_alarm_command); + lists[HIGH_ALARM_COMMANDS_INDEX] = g_slist_prepend(lists[HIGH_ALARM_COMMANDS_INDEX], current_high_alarm_command); + lists[ALARM_TIMEOUTS_INDEX] = g_slist_prepend(lists[ALARM_TIMEOUTS_INDEX], GINT_TO_POINTER(current_alarm_timeout)); + lists[SENSOR_TYPES_INDEX] = g_slist_prepend(lists[SENSOR_TYPES_INDEX], GUINT_TO_POINTER(current_sensor_type)); + lists[MULTIPLIERS_INDEX] = g_slist_prepend(lists[MULTIPLIERS_INDEX], GINT_TO_POINTER((gint)(current_multiplier * 1000))); + lists[OFFSETS_INDEX] = g_slist_prepend(lists[OFFSETS_INDEX], GINT_TO_POINTER((gint)(current_offset * 1000))); + lists[ICON_TYPES_INDEX] = g_slist_prepend(lists[ICON_TYPES_INDEX], GUINT_TO_POINTER(current_icon_type)); + lists[GRAPH_COLORS_INDEX] = g_slist_prepend(lists[GRAPH_COLORS_INDEX], current_graph_color); + } + } + + /* keep lists in original order */ + for (i = 0; i < NUM_KEYS; i++) { + if (lists[i] != NULL) { + lists[i] = g_slist_reverse(lists[i]); + + panel_applet_gconf_set_list(sensors_applet->applet, + keys[i], + key_types[i], + lists[i], &error); + if (error) { + sensors_applet_notify(sensors_applet, GCONF_WRITE_ERROR); + + g_error_free(error); + return FALSE; + } + } else { + g_debug("list %s is NULL", keys[i]); + } + + } + + sensors_applet_gconf_free_lists(lists, + NUM_KEYS); + + /* store current version to identify config data */ + panel_applet_gconf_set_string(sensors_applet->applet, + SENSORS_APPLET_VERSION, + PACKAGE_VERSION, &error); + + return TRUE; +} + diff --git a/sensors-applet/sensors-applet-gconf.h b/sensors-applet/sensors-applet-gconf.h new file mode 100644 index 0000000..527e364 --- /dev/null +++ b/sensors-applet/sensors-applet-gconf.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SENSORS_APPLET_GCONF_H +#define SENSORS_APPLET_GCONF_H + +#include "sensors-applet.h" +#include <panel-applet-gconf.h> + +#define FONT_SIZE "font-size" /* hidden gconf option specifying font + * size in points */ + +#define HIDE_UNITS "hide-units" /* hidden gconf option specifying not to + * show sensor units */ + +#define IS_SETUP "setup" /* have we actually set up this instance of + * the applet (gets set to true after + * closing prefences dialog) */ + +#define DISPLAY_MODE "display_mode" /* display icons or text labels?*/ + +#define LAYOUT_MODE "layout_mode" /* value beside or below label */ +#define TEMPERATURE_SCALE "temperature_scale" /* Kelvin, + Celsius or + Fahrenheit */ +#define DISPLAY_NOTIFICATIONS "display_notifications" /* whether to + * display + * notifications */ +#define TIMEOUT "timeout_delay" /* delay (in ms) between refreshes */ +#define GRAPH_SIZE "graph_size" /* the size of the graph in pixels - + * either width if horizontal, or + * height if vertical */ +#define PATHS "paths" /* full paths to filenames */ +#define IDS "ids" /* a list of the sensor device ids */ +#define INTERFACES "interfaces" /* a list of the sensor device + * interface for each sensor */ +#define LABELS "labels" /* user defined labels for each sensor */ +#define ENABLES "sensor_enables" /* list of booleans corresponding to + * the filenames of whether a sensor + * is enabled or not */ +#define LOW_VALUES "low_values" /* stored as ints (1000 * double + * value) for accuracy, since can + * only do ints easily */ +#define HIGH_VALUES "high_values" /* stored as ints (1000 * double + * value) for accuracy, since can + * only do ints easily */ +#define ALARM_ENABLES "alarm_enables" /* list of whether each sensor + * has its alarm enabled */ +#define LOW_ALARM_COMMANDS "low_alarm_commands" /* list of commands to execute + * when each alarm is + * activated */ +#define HIGH_ALARM_COMMANDS "high_alarm_commands" /* list of commands to execute + * when each alarm is + * activated */ + +#define ALARM_TIMEOUTS "alarm_timeouts" /* list of how often each + alarm should be sounded (in + seconds) */ + +#define SENSOR_TYPES "sensor_types" /* used to identify a sensor in a + list */ + +#define MULTIPLIERS "multipliers" +#define OFFSETS "offsets" +#define ICON_TYPES "icon_types" +#define GRAPH_COLORS "graph_colors" + +#define SENSORS_APPLET_VERSION "sensors_applet_version" /* version of + * config + * data */ + +gboolean sensors_applet_gconf_save_sensors(SensorsApplet *sensors_applet); +gboolean sensors_applet_gconf_setup_sensors(SensorsApplet *sensors_applet); +void sensors_applet_gconf_setup(SensorsApplet *sensors_applet); + +#endif /* SENSORS_APPLET_GCONF_H*/ diff --git a/sensors-applet/sensors-applet-plugin.h b/sensors-applet/sensors-applet-plugin.h new file mode 100644 index 0000000..9c664b5 --- /dev/null +++ b/sensors-applet/sensors-applet-plugin.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SENSORS_APPLET_PLUGIN_H +#define SENSORS_APPLET_PLUGIN_H + +#include <sensors-applet/sensors-applet-sensor.h> + +GQuark sensors_applet_plugin_error_quark(void); + +/* for error handling */ +#define SENSORS_APPLET_PLUGIN_ERROR (sensors_applet_plugin_error_quark()) + + +/** + * Initialises the plugin, and returns the list of SensorsAppletSensorInfo + * structs to create the sensors for this plugin from + */ +GList *sensors_applet_plugin_init(void); +gdouble sensors_applet_plugin_get_sensor_value(const gchar *path, + const gchar *id, + SensorType type, + GError **error); + +typedef void SensorsAppletPluginTestSensorFunc(GList **sensors, + const gchar *path); +void sensors_applet_plugin_find_sensors(GList **sensors, + const gchar *path, + SensorsAppletPluginTestSensorFunc); + +void sensors_applet_plugin_default_sensor_limits(SensorType type, + gdouble *low_value, + gdouble *high_value); + +void sensors_applet_plugin_add_sensor(GList **sensors, + const gchar *path, + const gchar *id, + const gchar *label, + SensorType type, + gboolean enable, + IconType icon, + const gchar *graph_color); + + +void sensors_applet_plugin_add_sensor_with_limits(GList **sensors, + const gchar *path, + const gchar *id, + const gchar *label, + SensorType type, + gboolean enable, + gdouble low_value, + gdouble high_value, + IconType icon, + const gchar *graph_color); + + +#endif // SENSORS_APPLET_PLUGIN_H diff --git a/sensors-applet/sensors-applet-plugins.c b/sensors-applet/sensors-applet-plugins.c new file mode 100644 index 0000000..7dfad78 --- /dev/null +++ b/sensors-applet/sensors-applet-plugins.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif /* HAVE_DLFCN_H */ + +#include "sensors-applet-plugins.h" +#include "sensors-applet-sensor.h" + +#define SENSORS_APPLET_USER_PLUGIN_DIR ".gnome2/sensors-applet/plugins" + +static void load_all_plugins(SensorsApplet *sensors_applet, + const gchar *path) +{ + if (g_file_test(path, + G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + GDir *dir; + if ((dir = g_dir_open(path, 0, NULL)) != NULL) { + const gchar *file; + while ((file = g_dir_read_name(dir)) != NULL) { + // try and open plugin + gchar *plugin_file; + void *handle; + SensorsAppletPluginName name_fn; + SensorsAppletPluginInit init_fn; + SensorsAppletPluginGetSensorValue get_value_fn; + + plugin_file = g_strdup_printf("%s/%s", path, file); + g_debug("found %s in plugin directory", plugin_file); + if ((handle = dlopen(plugin_file, RTLD_NOW)) != NULL) { + + if ((name_fn = dlsym(handle, "sensors_applet_plugin_name")) != NULL && + (init_fn = dlsym(handle, "sensors_applet_plugin_init")) != NULL && + (get_value_fn = dlsym(handle, "sensors_applet_plugin_get_sensor_value")) != NULL) { + GList *sensors; + g_debug("calling init function for plugin file %s", plugin_file); + + if ((sensors = init_fn()) != NULL) { + GList *sensor; + + g_debug("registering plugin %s", name_fn()); + g_hash_table_insert(sensors_applet->plugins, + g_strdup(name_fn()), + get_value_fn); + for (sensor = g_list_first(sensors); + sensor != NULL; + sensor = g_list_next(sensor)) { + SensorsAppletSensorInfo *sensor_info = (SensorsAppletSensorInfo *)sensor->data; + sensors_applet_add_sensor(sensors_applet, + sensor_info->path, + sensor_info->id, + sensor_info->label, + name_fn(), + sensor_info->type, + sensor_info->enable, + sensor_info->low_value, + sensor_info->high_value, + FALSE, // ALARM OFF + "", // no alarm commands + "", // no alarm commands + 0, // alarm_timeout + sensor_info->multiplier, + sensor_info->offset, + sensor_info->icon, + sensor_info->graph_color); + + g_free(sensor_info->path); + g_free(sensor_info->id); + g_free(sensor_info->label); + g_free(sensor_info->graph_color); + g_free(sensor_info); + } + g_list_free(sensors); + } else { + g_debug("plugin could not find any sensors"); + if (g_hash_table_lookup(sensors_applet->required_plugins, + name_fn())) + { + g_debug("plugin is required - registering even though no sensors detected"); + g_debug("registering plugin %s", name_fn()); + g_hash_table_insert(sensors_applet->plugins, + g_strdup(name_fn()), + get_value_fn); + } else { + g_debug("unloading plugin"); + } + } + + + + } else { + g_debug("plugin file %s does not contain the required interface", plugin_file); + if (dlclose(handle) != 0) { + g_debug("error closing plugin file %s", plugin_file); + } + } + } else { + g_debug("Could not dlopen: %s: %s", plugin_file, dlerror()); + } + g_free(plugin_file); + } + g_dir_close(dir); + } else { + g_debug("error opening plugin dir %s", path); + } + } else { + g_debug("path %s is not a valid directory", path); + } +} + +void sensors_applet_plugins_load_all(SensorsApplet *sensors_applet) +{ + const gchar *home; + + if ((home = g_get_home_dir()) != NULL) { + gchar *path; + path = g_build_filename(home, + SENSORS_APPLET_USER_PLUGIN_DIR, + NULL); + load_all_plugins(sensors_applet, path); + g_free(path); + } else { + g_warning("could not get home dir of user"); + } + + + load_all_plugins(sensors_applet, SENSORS_APPLET_PLUGIN_DIR); +} + +SensorsAppletPluginGetSensorValue sensors_applet_plugins_get_sensor_value_func(SensorsApplet *sensors_applet, + const gchar *plugin) +{ + return g_hash_table_lookup(sensors_applet->plugins, + plugin); +} + + diff --git a/sensors-applet/sensors-applet-plugins.h b/sensors-applet/sensors-applet-plugins.h new file mode 100644 index 0000000..2f6dd3d --- /dev/null +++ b/sensors-applet/sensors-applet-plugins.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SENSORS_APPLET_PLUGINS_H +#define SENSORS_APPLET_PLUGINS_H + +#include "sensors-applet.h" + +typedef const gchar *(*SensorsAppletPluginName)(void); +typedef GList *(*SensorsAppletPluginInit)(void); +typedef gdouble (*SensorsAppletPluginGetSensorValue)(const gchar *path, + const gchar *id, + SensorType type, + GError **error); + +void sensors_applet_plugins_load_all(SensorsApplet *sensors_applet); +void sensors_applet_plugins_unload_all(SensorsApplet *sensors_applet); +SensorsAppletPluginGetSensorValue sensors_applet_plugins_get_sensor_value_func(SensorsApplet *sensors_applet, + const gchar *plugin); + +#endif // SENSORS_APPLET_PLUGINS_H diff --git a/sensors-applet/sensors-applet-sensor.h b/sensors-applet/sensors-applet-sensor.h new file mode 100644 index 0000000..2314a52 --- /dev/null +++ b/sensors-applet/sensors-applet-sensor.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SENSORS_APPLET_SENSOR_H +#define SENSORS_APPLET_SENSOR_H + +#include <glib.h> + +// forward declare for plugins to use +typedef struct _SensorsApplet SensorsApplet; + +#define DEFAULT_GRAPH_COLOR "#ff0000" + +/* device icons */ +typedef enum { + CPU_ICON = 0, + HDD_ICON, + BATTERY_ICON, + MEMORY_ICON, + GPU_ICON, + GENERIC_ICON, + FAN_ICON, + CASE_ICON, + NUM_ICONS, +} IconType; + +typedef enum { + CURRENT_SENSOR = 0, + FAN_SENSOR, + TEMP_SENSOR, + VOLTAGE_SENSOR +} SensorType; + +typedef struct _SensorsAppletSensorInfo { + gchar *path; // must be dynamically allocated + gchar *id; // must be dynamically allocated + gchar *label; // must be dynamically allocated + SensorType type; + gboolean enable; + gdouble low_value; + gdouble high_value; + gdouble multiplier; + gdouble offset; + IconType icon; + gchar *graph_color; // must be dynamically allocated +} SensorsAppletSensorInfo; + + +#endif // SENSORS_APPLET_SENSOR_H diff --git a/sensors-applet/sensors-applet.c b/sensors-applet/sensors-applet.c new file mode 100644 index 0000000..9486173 --- /dev/null +++ b/sensors-applet/sensors-applet.c @@ -0,0 +1,1451 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** Contain the functions for operating on the SensorsApplet structure + * (represents the applet itself, and its associated variables. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#include <gnome.h> +#include <glib/gprintf.h> +#include "sensors-applet.h" +#include "active-sensor.h" +#include "sensors-applet-gconf.h" +#include "sensors-applet-plugins.h" + +#ifdef HAVE_LIBNOTIFY +#include "active-sensor-libnotify.h" +#define DEFAULT_NOTIFY_TIMEOUT 3000 +#endif + +#include "prefs-dialog.h" +#include "about-dialog.h" + +#define SENSORS_APPLET_MENU_FILE "SensorsApplet.xml" +#define DEFAULT_APPLET_SIZE 24 /* initially set as + * sensors_applet->size to ensure a + * real value is stored */ +#define COLUMN_SPACING 2 +#define ROW_SPACING 0 + +/* callbacks for panel menu */ +static void prefs_cb(BonoboUIComponent *uic, + gpointer *data, + const gchar *verbname) { + + SensorsApplet *sensors_applet; + sensors_applet = (SensorsApplet *)data; + + if (sensors_applet->prefs_dialog) { + gtk_window_present(GTK_WINDOW(sensors_applet->prefs_dialog->dialog)); + return; + } + prefs_dialog_open(sensors_applet); +} + +static void about_cb(BonoboUIComponent *uic, + gpointer data, + const gchar *verbname) { + SensorsApplet *sensors_applet; + sensors_applet = (SensorsApplet *)data; + + about_dialog_open(sensors_applet); +} + +static void help_cb(BonoboUIComponent *uic, + gpointer data, + const gchar *verbname) { + + GError *error = NULL; + + gtk_show_uri(NULL, "ghelp:sensors-applet", + gtk_get_current_event_time(), + &error); + + if (error) { + g_debug("Could not open help document: %s ",error->message); + g_error_free(error); + } +} + +static void destroy_cb(GtkWidget *widget, gpointer data) { + SensorsApplet *sensors_applet; + sensors_applet = (SensorsApplet *)data; + + /* destory dialogs, remove timeout and clear sensors tree and finally + * the applet */ + if (sensors_applet->prefs_dialog != NULL) { + // destroy's dialog too + prefs_dialog_close(sensors_applet); + } + + if (sensors_applet->timeout_id) { + g_source_remove(sensors_applet->timeout_id); + } + + // destroy all active sensors + g_list_foreach(sensors_applet->active_sensors, + (GFunc)active_sensor_destroy, + NULL); + + if (sensors_applet->sensors != NULL) { + gtk_tree_store_clear(sensors_applet->sensors); + } + + gtk_widget_destroy(GTK_WIDGET(sensors_applet->applet)); + + g_free(sensors_applet); + return; +} + +static void change_background_cb(PanelApplet *applet, + PanelAppletBackgroundType type, + GdkColor *color, + GdkPixmap *pixmap, + gpointer *data) { + GtkRcStyle *rc_style; + GtkStyle *style; + + g_debug("change-background occurred"); + + /* reset style */ + gtk_widget_set_style(GTK_WIDGET(applet), NULL); + rc_style = gtk_rc_style_new(); + gtk_widget_modify_style(GTK_WIDGET(applet), rc_style); + gtk_rc_style_unref(rc_style); + + switch(type) { + case PANEL_COLOR_BACKGROUND: + gtk_widget_modify_bg(GTK_WIDGET(applet), + GTK_STATE_NORMAL, color); + break; + + case PANEL_PIXMAP_BACKGROUND: + style = gtk_style_copy(GTK_WIDGET(applet)->style); + if (style->bg_pixmap[GTK_STATE_NORMAL]) { + g_object_unref(style->bg_pixmap[GTK_STATE_NORMAL]); + } + style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref(pixmap); + gtk_widget_set_style(GTK_WIDGET(applet), style); + g_object_unref(style); + break; + + case PANEL_NO_BACKGROUND: + /* fall through */ + default: + break; + } +} + +static void change_orient_cb (PanelApplet *applet, + PanelAppletOrient orient, + gpointer data) { + SensorsApplet *sensors_applet; + sensors_applet = (SensorsApplet *)data; + + sensors_applet_display_layout_changed(sensors_applet); +} + +static void size_allocate_cb(PanelApplet *applet, + GtkAllocation *allocation, + gpointer data) { + SensorsApplet *sensors_applet; + PanelAppletOrient orient; + + g_debug("size-allocate occurred"); + sensors_applet = (SensorsApplet *)data; + orient = panel_applet_get_orient(sensors_applet->applet); + + if ((orient == PANEL_APPLET_ORIENT_LEFT) || + (orient == PANEL_APPLET_ORIENT_RIGHT)) { + if (sensors_applet->size == allocation->width) + return; + sensors_applet->size = allocation->width; + } else { + if (sensors_applet->size == allocation->height) + return; + sensors_applet->size = allocation->height; + } + /* update if new value */ + sensors_applet_graph_size_changed(sensors_applet); + sensors_applet_display_layout_changed(sensors_applet); +} + +static void style_set_cb(GtkWidget *widget, + GtkStyle *old_style, + gpointer data) { + + /* update all icons in the sensors tree and update all active + * sensors */ + GtkTreeIter interfaces_iter, sensors_iter; + GtkTreePath *path; + gboolean not_end_of_interfaces = TRUE, not_end_of_sensors = TRUE; + IconType icon_type; + GdkPixbuf *new_icon; + gboolean enabled; + SensorsApplet *sensors_applet; + DisplayMode display_mode; + + sensors_applet = (SensorsApplet *)data; + + g_debug("set-style occurred"); + + display_mode = panel_applet_gconf_get_int(sensors_applet->applet, + DISPLAY_MODE, + NULL); + if (sensors_applet->sensors) { + for (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter); not_end_of_interfaces; not_end_of_interfaces = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter)) { + + /* reset sensors sentinel */ + not_end_of_sensors = TRUE; + + for (gtk_tree_model_iter_children(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter, &interfaces_iter); not_end_of_sensors; not_end_of_sensors = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter)) { + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), + &sensors_iter, + ENABLE_COLUMN, &enabled, + ICON_TYPE_COLUMN, &icon_type, + -1); + /* update icons */ + new_icon = sensors_applet_load_icon(icon_type); + + gtk_tree_store_set(sensors_applet->sensors, + &sensors_iter, + ICON_PIXBUF_COLUMN, new_icon, + -1); + g_object_unref(new_icon); + + /* update icons only if currently being + * displayed */ + if (enabled && + (display_mode == DISPLAY_ICON || + display_mode == DISPLAY_ICON_WITH_VALUE)) { + path = gtk_tree_model_get_path(GTK_TREE_MODEL(sensors_applet->sensors), + &sensors_iter); + sensors_applet_icon_changed(sensors_applet, + path); + gtk_tree_path_free(path); + } + } + } + /* now update layout as size may have changed */ + sensors_applet_display_layout_changed(sensors_applet); + } + +} + +static const BonoboUIVerb sensors_applet_menu_verbs[] = { + BONOBO_UI_UNSAFE_VERB("Preferences", prefs_cb), + BONOBO_UI_UNSAFE_VERB ("Help", help_cb), + BONOBO_UI_UNSAFE_VERB("About", about_cb), + BONOBO_UI_VERB_END +}; + +#ifdef HAVE_LIBNOTIFY +static void notif_closed_cb(NotifyNotification *notification, + SensorsApplet *sensors_applet) +{ + g_assert(sensors_applet); + + sensors_applet->notification = NULL; +} +#endif // HAVE_LIBNOTIFY + +void sensors_applet_notify(SensorsApplet *sensors_applet, + NotifType notif_type) +{ +#ifdef HAVE_LIBNOTIFY + gchar *message; + gchar *summary; + GError *error = NULL; + g_assert(sensors_applet); + + if (!notify_is_initted()) { + if (!notify_init(PACKAGE)) { + return; + } + } + + if (sensors_applet->notification) { + g_debug("notification already shown, not showing another one..."); + return; + } + + switch (notif_type) { + case GCONF_READ_ERROR: + summary = g_strdup_printf(_("Error restoring saved sensor configuration.")); + message = g_strdup_printf(_("An error occurred while trying to restore the saved sensor configuration. The previous configuration has been lost and will need to be re-entered.")); + break; + + case GCONF_WRITE_ERROR: + summary = g_strdup_printf(_("Error saving sensor configuration.")); + message = g_strdup_printf(_("An error occurred while trying to save the current sensor configuration. ")); + break; + } + + sensors_applet->notification = notify_notification_new(summary, + message, + GTK_STOCK_DIALOG_WARNING, + GTK_WIDGET(sensors_applet->applet)); + g_free(summary); + g_free(message); + + g_signal_connect(sensors_applet->notification, + "closed", + G_CALLBACK(notif_closed_cb), + sensors_applet); + g_debug("showing notification"); + if (!notify_notification_show(sensors_applet->notification, &error)) { + g_debug("Error showing notification: %s", error->message); + g_error_free(error); + } +#endif // HAVE_LIBNOTIFY +} + + +void sensors_applet_notify_active_sensor(ActiveSensor *active_sensor, NotifType notif_type) { +#ifdef HAVE_LIBNOTIFY + + SensorsApplet *sensors_applet; + GList *table_children; + GtkWidget *attach = NULL; + gchar *summary, *message; + gint timeout_msecs; + gchar *sensor_label; + gchar *sensor_path; + SensorType sensor_type; + TemperatureScale temp_scale; + GtkTreeIter iter; + GtkTreePath *path; + const gchar *unit_type = NULL; + const gchar *unit_type_title = NULL; + const gchar *relation = NULL; + const gchar *limit_type = NULL; + const gchar *units = NULL; + gdouble limit_value; + + sensors_applet = active_sensor->sensors_applet; + + if (!panel_applet_gconf_get_bool(sensors_applet->applet, + DISPLAY_NOTIFICATIONS, + NULL)) { + g_debug("Wanted to display notification, but user has disabled them"); + return; + } + + table_children = gtk_container_get_children(GTK_CONTAINER(sensors_applet->table)); + + if (g_list_find(table_children, active_sensor->icon)) { + attach = GTK_WIDGET(active_sensor->icon); + } else if (g_list_find(table_children, active_sensor->label)) { + attach = GTK_WIDGET(active_sensor->label); + } else if (g_list_find(table_children, active_sensor->value)) { + attach = GTK_WIDGET(active_sensor->value); + } else if (g_list_find(table_children, active_sensor->graph)) { + attach = GTK_WIDGET(active_sensor->graph); + } else { + g_warning("Wanted to do notify for a sensor which has no elements in the table!!!"); + return; + } + g_list_free(table_children); + + path = gtk_tree_row_reference_get_path(active_sensor->sensor_row); + if (gtk_tree_model_get_iter(GTK_TREE_MODEL(sensors_applet->sensors), + &iter, path)) { + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), &iter, + LABEL_COLUMN, &sensor_label, + PATH_COLUMN, &sensor_path, + SENSOR_TYPE_COLUMN, &sensor_type, + -1); + } else { + g_warning("Error getting data from tree for notification..."); + gtk_tree_path_free(path); + return; + } + gtk_tree_path_free(path); + + // do different stuff for different notif types + switch (notif_type) { + case LOW_ALARM: // fall thru + case HIGH_ALARM: + if (active_sensor->sensor_values[0] <= active_sensor->sensor_low_value && + notif_type == LOW_ALARM) { + relation = _("is very low"); + limit_type = _("lower limit"); + limit_value = active_sensor->sensor_low_value; + } else if (active_sensor->sensor_values[0] >= active_sensor->sensor_high_value && + notif_type == HIGH_ALARM) { + /* assume high alarm condition */ + relation = _("is very high"); + limit_type = _("upper limit"); + limit_value = active_sensor->sensor_high_value; + } else { + g_warning("Alarm notify called when no alarm condition!"); + g_free(sensor_path); + g_free(sensor_label); + return; + } + + switch ((SensorType)sensor_type) { + case TEMP_SENSOR: + unit_type_title = _("Temperature"); + unit_type = _("temperature"); + temp_scale = (TemperatureScale)panel_applet_gconf_get_int(active_sensor->sensors_applet->applet, + TEMPERATURE_SCALE, + NULL); + + switch (temp_scale) { + case CELSIUS: + units = UNITS_CELSIUS; + break; + case FAHRENHEIT: + units = UNITS_FAHRENHEIT; + break; + case KELVIN: + units = UNITS_KELVIN; + break; + default: + units = NULL; + } + + break; + case VOLTAGE_SENSOR: + unit_type_title = _("Voltage"); + unit_type = _("voltage"); + units = UNITS_VOLTAGE; + break; + case FAN_SENSOR: + unit_type_title = _("Fan Speed"); + unit_type = _("fan speed"); + units = UNITS_RPM; + break; + case CURRENT_SENSOR: + unit_type_title = _("Current"); + unit_type = _("current"); + units = UNITS_CURRENT; + break; + } + + timeout_msecs = (active_sensor->alarm_timeout ? MIN(DEFAULT_NOTIFY_TIMEOUT, (active_sensor->alarm_timeout * 1000)) : DEFAULT_NOTIFY_TIMEOUT); + + summary = g_strdup_printf("%s %s %s", sensor_label, unit_type_title, _("Alarm")); + message = g_strdup_printf("%s %s %s (%s %2.0f%s)", sensor_label, unit_type, + relation, limit_type, limit_value, units); + break; + + case SENSOR_INTERFACE_ERROR: + summary = g_strdup_printf(_("Error updating sensor %s"), sensor_label); + message = g_strdup_printf(_("An error occurred while trying to update the value of the sensor %s located at %s."), sensor_label, sensor_path); + timeout_msecs = panel_applet_gconf_get_int(active_sensor->sensors_applet->applet, + TIMEOUT, + NULL); + + break; + + default: + g_assert_not_reached(); + } + + active_sensor_libnotify_notify(active_sensor, + notif_type, + summary, + message, + GTK_STOCK_DIALOG_WARNING, + timeout_msecs, + attach); + + g_free(sensor_path); + g_free(sensor_label); + g_free(summary); + g_free(message); +#endif +} + +void sensors_applet_notify_end(ActiveSensor *active_sensor, + NotifType notif_type) { +#ifdef HAVE_LIBNOTIFY + active_sensor_libnotify_notify_end(active_sensor, notif_type); +#endif +} + +#ifdef HAVE_LIBNOTIFY +static void sensors_applet_notify_end_all_gfunc(ActiveSensor *active_sensor, + gpointer data) { + active_sensor_libnotify_notify_end(active_sensor, LOW_ALARM); + active_sensor_libnotify_notify_end(active_sensor, HIGH_ALARM); +} +#endif + +void sensors_applet_notify_end_all(SensorsApplet *sensors_applet) { +#ifdef HAVE_LIBNOTIFY + g_list_foreach(sensors_applet->active_sensors, + (GFunc)sensors_applet_notify_end_all_gfunc, + NULL); +#endif +} + +/* internal helper functions for updating display etc*/ + + +/* should be called as a g_container_foreach at the start of + * pack_display if ythe table already exists to remove but keep alive + * all children of the table before repacking it */ +static void sensors_applet_pack_display_empty_table_cb(GtkWidget *widget, + gpointer data) { + GtkContainer *container; + + container = GTK_CONTAINER(data); + + /* ref then remove widget */ + g_object_ref(widget); + gtk_container_remove(container, widget); +} + +/* should be called as a g_container_foreach at the end of + * pack_display to unref any of the old children that we have readdded + * to the table to stop reference creep from the g_object_ref called + * on each child at the start of pack labels */ +static void sensors_applet_pack_display_cleanup_refs_cb(GtkWidget *widget, + gpointer data) { + + GList *old_children; + + old_children = (GList *)data; + if (g_list_find(old_children, widget)) { + g_object_unref(widget); + } +} + +static void sensors_applet_pack_display(SensorsApplet *sensors_applet) { + /* note the if () around each widget is to ensure we only + * operate on those that actually exist */ + GtkLabel *no_sensors_enabled_label = NULL; + gint num_active_sensors = 0, num_sensors_per_group, rows, cols, i, j; + GList *old_table_children = NULL; + + GList *current_sensor; + + DisplayMode display_mode; + LayoutMode layout_mode; + + gboolean horizontal; + gint label_width, icon_width, value_width; + gint label_height, icon_height, value_height; + + GtkRequisition req; + + ActiveSensor *first_sensor; + + /* it is possible that there could be no active sensors so + * handle that case first - make sure we dont do a NULL + * pointer access first though */ + if (sensors_applet->active_sensors == NULL || + g_list_length(sensors_applet->active_sensors) == 0) { + g_debug("no active sensors to pack in table"); + no_sensors_enabled_label = g_object_new(GTK_TYPE_LABEL, + "label", _("No sensors enabled!"), + NULL); + + if (sensors_applet->table == NULL) { + /* only need 1 row and 1 col */ + sensors_applet->table = gtk_table_new(1, 1, FALSE); + gtk_table_set_col_spacings(GTK_TABLE(sensors_applet->table), COLUMN_SPACING); + gtk_table_set_row_spacings(GTK_TABLE(sensors_applet->table), ROW_SPACING); + /* add table to applet */ + gtk_container_add(GTK_CONTAINER(sensors_applet->applet), sensors_applet->table); + + } else { + /* destroy existing widgets - could be an + * existing version of no sensors label - okay + * to just add again though if destory fist */ + g_debug("destorying any existing widgets in container"); + gtk_container_foreach(GTK_CONTAINER(sensors_applet->table), + (GtkCallback)gtk_widget_destroy, + NULL); + /* make sure only 1x1 table */ + gtk_table_resize(GTK_TABLE(sensors_applet->table), + 1, 1); + } + g_debug("packing no sensors enabled label"); + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + GTK_WIDGET(no_sensors_enabled_label), + 0, 1, + 0, 1); + gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet)); + return; + + } + /* otherwise can acess active_sensors without any worries */ + num_active_sensors = g_list_length(sensors_applet->active_sensors); + + display_mode = (DisplayMode)panel_applet_gconf_get_int(sensors_applet->applet, + DISPLAY_MODE, NULL); + layout_mode = (LayoutMode)panel_applet_gconf_get_int(sensors_applet->applet, + LAYOUT_MODE, NULL); + + + horizontal = (((panel_applet_get_orient(sensors_applet->applet) == PANEL_APPLET_ORIENT_UP) || + (panel_applet_get_orient(sensors_applet->applet) == PANEL_APPLET_ORIENT_DOWN))); + + /* figure out num rows / cols by how high / wide sensors + * labels / icons are and how much size we have to put them + * in */ + + /* get the first active sensor */ + first_sensor = (ActiveSensor *)sensors_applet->active_sensors->data; + + + switch (display_mode) { + case DISPLAY_VALUE: + gtk_widget_size_request(GTK_WIDGET(first_sensor->value), + &req); + value_width = req.width + COLUMN_SPACING; + value_height = req.height + ROW_SPACING; + + /* make sure all widths and heights are non zero, + * otherwise will get a divide by zero exception below + * - is a non critical error since can happen when + * elements first added to list, so simply return - is + * not a programming error */ + if (value_width == 0 && value_height == 0) { + return; + } + + num_sensors_per_group = (sensors_applet->size / + (horizontal ? value_height : + value_width)); + break; + + case DISPLAY_LABEL_WITH_VALUE: + /* even though we end up packing the event boxes into the + * panel, these dont give back request sizes, so need to ask + * widgets directly */ + gtk_widget_size_request(GTK_WIDGET(first_sensor->value), + &req); + value_width = req.width + COLUMN_SPACING; + value_height = req.height + ROW_SPACING; + + gtk_widget_size_request(GTK_WIDGET(first_sensor->label), + &req); + label_width = req.width + COLUMN_SPACING; + label_height = req.height + ROW_SPACING; + + /* make sure all widths and heights are non zero, otherwise + * will get a divide by zero exception below + * - is a non critical error since can happen when + * elements first added to list, so simply return - is + * not a programming error */ + if (!(label_width && label_height && + value_width && value_height)) { + return; + } + + switch (layout_mode) { + case VALUE_BESIDE_LABEL: + num_sensors_per_group = (sensors_applet->size / + (horizontal ? MAX(label_height, value_height) : + (label_width + value_width))); + break; + case VALUE_BELOW_LABEL: + num_sensors_per_group = (sensors_applet->size / + (horizontal ? (label_height + value_height) : + MAX(label_width, value_width))); + + + break; + } + break; + + case DISPLAY_ICON_WITH_VALUE: + gtk_widget_size_request(GTK_WIDGET(first_sensor->value), + &req); + value_width = req.width + COLUMN_SPACING; + value_height = req.height + ROW_SPACING; + + gtk_widget_size_request(GTK_WIDGET(first_sensor->icon), + &req); + icon_width = req.width + COLUMN_SPACING; + icon_height = req.height + ROW_SPACING; + + if (!(icon_width && icon_height && + value_width && value_height)) { + return; + } + + switch (layout_mode) { + case VALUE_BESIDE_LABEL: + num_sensors_per_group = (sensors_applet->size / + (horizontal ? MAX(icon_height, value_height) : + (icon_width + value_width))); + break; + case VALUE_BELOW_LABEL: + num_sensors_per_group = (sensors_applet->size / + (horizontal ? (icon_height + value_height) : + MAX(icon_width, value_width))); + + + break; + } + break; + + case DISPLAY_ICON: + gtk_widget_size_request(GTK_WIDGET(first_sensor->icon), + &req); + icon_width = req.width + COLUMN_SPACING; + icon_height = req.height + ROW_SPACING; + if (!(icon_width && icon_height)) { + return; + } + + num_sensors_per_group = (sensors_applet->size / + (horizontal ? icon_height : + icon_width)); + break; + + case DISPLAY_GRAPH: + /* only show graphs in a line like System Monitor + * applet */ + num_sensors_per_group = 1; + break; + } + /* ensure always atleast 1 sensor per group */ + if (num_sensors_per_group < 1) { + /* force a better layout */ + if (horizontal && layout_mode == VALUE_BELOW_LABEL) { + layout_mode = VALUE_BESIDE_LABEL; + } else if (!horizontal && layout_mode == VALUE_BESIDE_LABEL) { + layout_mode = VALUE_BELOW_LABEL; + } + num_sensors_per_group = 1; + } + + if (horizontal) { + /* if oriented horizontally, want as many + sensors per column as user has defined, then + enough columns to hold all the widgets */ + rows = num_sensors_per_group; + cols = num_active_sensors / num_sensors_per_group; + while (rows * cols < num_active_sensors || cols == 0) { + cols++; + } + + } else { + /* if oriented vertically, want as many + sensors per row as user has defined, then + enough rows to hold all the widgets*/ + cols = num_sensors_per_group; + rows = num_active_sensors / num_sensors_per_group; + while (rows * cols < num_active_sensors || rows == 0) { + rows++; + } + + } + + /* if displaying labels / icons and values need to modify + number of rows / colums to accomodate this */ + if (display_mode == DISPLAY_LABEL_WITH_VALUE || + display_mode == DISPLAY_ICON_WITH_VALUE) { + if (layout_mode == VALUE_BESIDE_LABEL) { + /* to display labels next to values need twice + as many columns */ + cols *= 2; + } else { + /* to display labels above values, we need + * twice as many rows as without */ + rows *= 2; + } + } + + if (sensors_applet->table == NULL) { + /* create table and add to applet */ + sensors_applet->table = gtk_table_new(rows, cols, FALSE); + gtk_table_set_col_spacings(GTK_TABLE(sensors_applet->table), COLUMN_SPACING); + gtk_table_set_row_spacings(GTK_TABLE(sensors_applet->table), ROW_SPACING); + gtk_container_add(GTK_CONTAINER(sensors_applet->applet), sensors_applet->table); + } else { + /* remove all children if table already exists so we can start + * again */ + /* save a list of the old children for later */ + old_table_children = gtk_container_get_children(GTK_CONTAINER(sensors_applet->table)); + + gtk_container_foreach(GTK_CONTAINER(sensors_applet->table), + sensors_applet_pack_display_empty_table_cb, + sensors_applet->table); + + /* then resize table */ + gtk_table_resize(GTK_TABLE(sensors_applet->table), rows, cols); + } + + /* pack icons / labels and values into table */ + current_sensor = sensors_applet->active_sensors; + + /* if showing labels / icons and values, need to pack labels / + * icons these first */ + if (display_mode == DISPLAY_ICON_WITH_VALUE || + display_mode == DISPLAY_LABEL_WITH_VALUE) { + /* loop through columns */ + for (i = 0; current_sensor != NULL && i < cols; /* increments depends on how we lay them out - see below */) { + + /* loop through rows in a column */ + for (j = 0; current_sensor && j < rows; /* see bottom of for loop*/) { + /* attach label / icon at this point */ + if (display_mode == DISPLAY_ICON_WITH_VALUE) { + if (((ActiveSensor *)(current_sensor->data))->icon) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->icon, + i, i + 1, + j, j + 1); + } + } else { + if (((ActiveSensor *)(current_sensor->data))->label) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->label, + i, i + 1, + j, j + 1); + } + } + /* now attach sensor value to either + row below or column next to */ + if (layout_mode == VALUE_BESIDE_LABEL) { + /* left align labels */ + if (((ActiveSensor *)(current_sensor->data))->icon) { + gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->icon), 0.0, 0.5); + } + if (((ActiveSensor *)(current_sensor->data))->label) { + gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->label), 0.0, 0.5); + } + if (((ActiveSensor *)(current_sensor->data))->value) { + gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->value), 0.0, 0.5); + } + + + /* place value next to label */ + if (((ActiveSensor *)(current_sensor->data))->value) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->value, + i + 1, i + 2, + j, j + 1); + } + j++; + } else { /* place value below label */ + /* center align labels */ + if (((ActiveSensor *)(current_sensor->data))->icon) { + gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->icon), 0.5, 0.5); + } + if (((ActiveSensor *)(current_sensor->data))->label) { + gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->label), 0.5, 0.5); + } + if (((ActiveSensor *)(current_sensor->data))->value) { + gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->value), 0.5, 0.5); + } + + if (((ActiveSensor *)(current_sensor->data))->value) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->value, + i, i + 1, + j + 1, j + 2); + } + j += 2; + } + current_sensor = g_list_next(current_sensor); + + } /* end row loop */ + /* now increment column index as needed */ + if (layout_mode == VALUE_BESIDE_LABEL) { /* place value next to label */ + i += 2; + } else { + i++; + } + + + } /* end column loop */ + + + } else { /* not showing labels and icons with values, so just + * pack either only icons or values */ + for (i = 0; current_sensor != NULL && i < cols; ++i) { + for (j = 0; current_sensor!= NULL && j < rows; ++j) { + if (display_mode == DISPLAY_VALUE) { + + if (((ActiveSensor *)(current_sensor->data))->value) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->value, + i, i + 1, + j, j + 1); + } + } else if (display_mode == DISPLAY_ICON) { + if (((ActiveSensor *)(current_sensor->data))->value) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->icon, + i, i + 1, + j, j + 1); + } + } else if (display_mode == DISPLAY_GRAPH) { + if (((ActiveSensor *)(current_sensor->data))->graph) { + gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table), + ((ActiveSensor *)(current_sensor->data))->graph_frame, + i, i + 1, + j, j + 1); + } + } + + + current_sensor = g_list_next(current_sensor); + } + } + + } + if (old_table_children != NULL) { + gtk_container_foreach(GTK_CONTAINER(sensors_applet->table), + sensors_applet_pack_display_cleanup_refs_cb, + old_table_children); + g_list_free(old_table_children); + } + gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet)); + +} + +/* must unref when done with returned pixbuf */ +GdkPixbuf *sensors_applet_load_icon(IconType icon_type) { + GtkIconTheme *icon_theme; + GdkPixbuf *icon = NULL; + GError *error = NULL; + + /* try to load the icon */ + + /* not allowed to unref or ref icon_theme once we have it */ + icon_theme = gtk_icon_theme_get_default(); + icon = gtk_icon_theme_load_icon(icon_theme, + stock_icons[icon_type], + DEFAULT_ICON_SIZE, + GTK_ICON_LOOKUP_USE_BUILTIN, + &error); + if (error) { + g_warning ("Could not load icon: %s", error->message); + g_error_free(error); + error = NULL; + + /* try again with default icon */ + icon = gtk_icon_theme_load_icon(icon_theme, + GTK_STOCK_MISSING_IMAGE, + DEFAULT_ICON_SIZE, + GTK_ICON_LOOKUP_USE_BUILTIN, + &error); + if (error) { + /* this will quit sensors-applet but + * it is a pretty major error so may + * as well */ + + g_error("Could not load GTK_STOCK_MISSING_IMAGE - major error!!!: %s", error->message); + + g_error_free(error); + error = NULL; + } + + } + return icon; +} + +gboolean sensors_applet_add_sensor(SensorsApplet *sensors_applet, + const gchar *path, + const gchar *id, + const gchar *label, + const gchar *interface, + SensorType type, + gboolean enable, + gdouble low_value, + gdouble high_value, + gboolean alarm_enable, + const gchar *low_alarm_command, + const gchar *high_alarm_command, + gint alarm_timeout, + gdouble multiplier, + gdouble offset, + IconType icon_type, + const gchar *graph_color) { + + + GtkTreeIter interfaces_iter, sensors_iter; + gboolean not_empty_tree; + + gchar *node_interface; + gboolean not_end_of_interfaces = TRUE, interface_exists = FALSE; + gboolean not_end_of_sensors = TRUE; + gchar *sensor_id; + gchar *sensor_path; + SensorType sensor_type; + GdkPixbuf *icon; + GtkTreePath *tree_path; + + g_assert(sensors_applet); + + /* assume tree is not empty */ + not_empty_tree = TRUE; + + + if (NULL == sensors_applet->sensors) { + + sensors_applet->sensors = gtk_tree_store_new(N_COLUMNS, + G_TYPE_STRING, /* path */ + G_TYPE_STRING, /* id */ + G_TYPE_STRING, /* label */ + G_TYPE_STRING, /* interface */ + G_TYPE_UINT, /* sensor + * type */ + G_TYPE_BOOLEAN, /* enable */ + G_TYPE_BOOLEAN, /* visible */ + G_TYPE_DOUBLE, /* low value */ + G_TYPE_DOUBLE, /* high type */ + G_TYPE_BOOLEAN, /* alarm enable */ + G_TYPE_STRING, /* low alarm command */ + G_TYPE_STRING, /* high alarm command */ + G_TYPE_UINT, /* alarm timeout */ + G_TYPE_DOUBLE, /* multiplier */ + G_TYPE_DOUBLE, /* offset */ + G_TYPE_UINT, /* icon type */ + GDK_TYPE_PIXBUF, /* icon pixbuf */ + G_TYPE_STRING); /* graph color */ + + + g_debug("Sensor tree created."); + + /* we know tree is actually empty since we just created it */ + not_empty_tree = FALSE; + } + + /* search sensor tree for the parent interface to place this + * sensor under */ + for (not_empty_tree = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter); not_empty_tree && not_end_of_interfaces && !interface_exists; not_end_of_interfaces = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter)) { + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter, + INTERFACE_COLUMN, &node_interface, + -1); + if (g_ascii_strcasecmp(interface, node_interface) == 0) { + /* found interface in tree */ + interface_exists = TRUE; + + /* now see if this actual sensor already + * exists within this interface - don't want + * to add duplicates */ + /* see if have children */ + for (not_end_of_sensors = gtk_tree_model_iter_children(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter, &interfaces_iter); not_end_of_sensors; not_end_of_sensors = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter)) { + gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter, + PATH_COLUMN, &sensor_path, + ID_COLUMN, &sensor_id, + SENSOR_TYPE_COLUMN, &sensor_type, + -1); + if (g_ascii_strcasecmp(sensor_id, id) == 0 && + g_ascii_strcasecmp(sensor_path, path) == 0 && + sensor_type == type) { + /* sensor already exists so + * dont add a second time */ + g_debug("sensor with path: %s, id: %s already exists in tree, not adding a second time", sensor_path, sensor_id); + g_free(sensor_id); + g_free(sensor_path); + g_free(node_interface); + return FALSE; + } + g_free(sensor_id); + g_free(sensor_path); + } + g_free(node_interface); + break; + } + g_free(node_interface); + } + + + + if (!interface_exists) { + /* add to required plugins hash table so we ensure this + plugin stays loaded to make sure we have a get sensor + value function if possible */ + g_hash_table_insert(sensors_applet->required_plugins, + g_strdup(interface), + GINT_TO_POINTER(TRUE)); + g_debug("added interface %s to required plugins", interface); + + /* wasn't able to find interface root node so create it */ + gtk_tree_store_append(sensors_applet->sensors, + &interfaces_iter, + NULL); + + gtk_tree_store_set(sensors_applet->sensors, + &interfaces_iter, + ID_COLUMN, interface, + INTERFACE_COLUMN, interface, + VISIBLE_COLUMN, FALSE, + -1); + g_debug("Added sensor interface %s to tree", interface); + } + + icon = sensors_applet_load_icon(icon_type); + + + /* then add sensor as a child under interface node - ie assume + * we either found it or created it - the inteface node that + * is */ + + /* for now just add sensors all in a single list */ + gtk_tree_store_append(sensors_applet->sensors, + &sensors_iter, + &interfaces_iter); + + gtk_tree_store_set(sensors_applet->sensors, + &sensors_iter, + PATH_COLUMN, path, + ID_COLUMN, id, + LABEL_COLUMN, label, + INTERFACE_COLUMN, interface, + SENSOR_TYPE_COLUMN, type, + ENABLE_COLUMN, enable, + VISIBLE_COLUMN, TRUE, + LOW_VALUE_COLUMN, low_value, + HIGH_VALUE_COLUMN, high_value, + ALARM_ENABLE_COLUMN, alarm_enable, + ALARM_TIMEOUT_COLUMN, alarm_timeout, + LOW_ALARM_COMMAND_COLUMN, low_alarm_command, + HIGH_ALARM_COMMAND_COLUMN, high_alarm_command, + MULTIPLIER_COLUMN, multiplier, + OFFSET_COLUMN, offset, + ICON_TYPE_COLUMN, icon_type, + ICON_PIXBUF_COLUMN, icon, + GRAPH_COLOR_COLUMN, graph_color, + -1); + g_debug("added sensor %s to tree", path); + + /* remove reference to icon as tree now has ref */ + g_object_unref(icon); + + /* create the active sensor */ + if (enable) { + tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter); + sensors_applet_sensor_enabled(sensors_applet, tree_path); + gtk_tree_path_free(tree_path); + } + return TRUE; +} + + +static ActiveSensor *sensors_applet_find_active_sensor(SensorsApplet *sensors_applet, + GtkTreePath *path) { + GtkTreePath *sensor_tree_path; + GList *current_sensor; + + for (current_sensor = sensors_applet->active_sensors; current_sensor != NULL; current_sensor = g_list_next(current_sensor)) { + sensor_tree_path = gtk_tree_row_reference_get_path(((ActiveSensor *)(current_sensor->data))->sensor_row); + + if (gtk_tree_path_compare(path, sensor_tree_path) == 0) { + gtk_tree_path_free(sensor_tree_path); + return ((ActiveSensor *)(current_sensor->data)); + } + gtk_tree_path_free(sensor_tree_path); + } + return NULL; +} + + +/* path should be the full path to a file representing the sensor (eg + * /dev/hda or /sys/devices/platform/i2c-0/0-0290/temp1_input) */ + +void sensors_applet_display_layout_changed(SensorsApplet *sensors_applet) { + /* update sensors since will need to update icons / graphs etc + * if weren't displayed before */ + GList *list = NULL; + for (list = sensors_applet->active_sensors; + list != NULL; + list = list->next) { + ActiveSensor *as = (ActiveSensor *)list->data; + as->updated = FALSE; + } + sensors_applet_update_active_sensors(sensors_applet); + sensors_applet_pack_display(sensors_applet); +} + +void sensors_applet_alarm_off(SensorsApplet *sensors_applet, + GtkTreePath *path, + NotifType notif_type) { + ActiveSensor *active_sensor; + + if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet, + path)) != NULL) { + active_sensor_alarm_off(active_sensor, notif_type); + } +} + +void sensors_applet_all_alarms_off(SensorsApplet *sensors_applet, + GtkTreePath *path) { + sensors_applet_alarm_off(sensors_applet, path, LOW_ALARM); + sensors_applet_alarm_off(sensors_applet, path, HIGH_ALARM); +} + + +void sensors_applet_sensor_enabled(SensorsApplet *sensors_applet, + GtkTreePath *path) { + ActiveSensor *active_sensor; + + g_assert(sensors_applet); + g_assert(path); + + active_sensor = active_sensor_new(sensors_applet, + gtk_tree_row_reference_new(GTK_TREE_MODEL(sensors_applet->sensors), path)); + + active_sensor_update(active_sensor, sensors_applet); + + /* keep list sorted */ + sensors_applet->active_sensors = g_list_insert_sorted(sensors_applet->active_sensors, + active_sensor, + (GCompareFunc)active_sensor_compare); + + sensors_applet_pack_display(sensors_applet); +} + +void sensors_applet_reorder_sensors(SensorsApplet *sensors_applet) { + sensors_applet->active_sensors = g_list_sort(sensors_applet->active_sensors, (GCompareFunc)active_sensor_compare); + + sensors_applet_pack_display(sensors_applet); +} + +void sensors_applet_sensor_disabled(SensorsApplet *sensors_applet, + GtkTreePath *path) { + + ActiveSensor *active_sensor; + + g_assert(sensors_applet); + g_assert(path); + + if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet, + path)) != NULL) { + g_debug("Destroying active sensor..."); + + g_debug("-- removing from list..."); + sensors_applet->active_sensors = g_list_remove(sensors_applet->active_sensors, + active_sensor); + g_debug("-- repacking display...."); + sensors_applet_pack_display(sensors_applet); + + active_sensor_destroy(active_sensor); + } +} + + +void sensors_applet_update_sensor(SensorsApplet *sensors_applet, + GtkTreePath *path) { + ActiveSensor *active_sensor; + + g_assert(sensors_applet); + g_assert(path); + + if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet, + path)) != NULL) { + active_sensor_update(active_sensor, + sensors_applet); + } +} + +void sensors_applet_icon_changed(SensorsApplet *sensors_applet, + GtkTreePath *path) { + ActiveSensor *active_sensor; + + g_assert(sensors_applet); + g_assert(path); + + if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet, + path)) != NULL) { + active_sensor_icon_changed(active_sensor, + sensors_applet); + } +} + +/** + * Cycle thru ActiveSensors and update them all + */ +gboolean sensors_applet_update_active_sensors(SensorsApplet *sensors_applet) { + g_assert(sensors_applet); + + if (sensors_applet->active_sensors) { + g_list_foreach(sensors_applet->active_sensors, + (GFunc)active_sensor_update, + sensors_applet); + return TRUE; + } + return FALSE; +} + +/** + * Cycle thru ActiveSensors and set new graph dimensions + */ +void sensors_applet_graph_size_changed(SensorsApplet *sensors_applet) { + gint dimensions[2]; + gint graph_size; + g_assert(sensors_applet); + + if (sensors_applet->active_sensors) { + + graph_size = panel_applet_gconf_get_int(sensors_applet->applet, + GRAPH_SIZE, + NULL); + if (panel_applet_get_orient(sensors_applet->applet) == + PANEL_APPLET_ORIENT_UP || + panel_applet_get_orient(sensors_applet->applet) == + PANEL_APPLET_ORIENT_DOWN) { + /* is horizontal so set graph_size as width */ + dimensions[0] = graph_size; + dimensions[1] = sensors_applet->size; + } else { + dimensions[0] = sensors_applet->size; + dimensions[1] = graph_size; + } + + g_list_foreach(sensors_applet->active_sensors, + (GFunc)active_sensor_update_graph_dimensions, + &dimensions); + } + +} + +gdouble sensors_applet_convert_temperature(gdouble value, + TemperatureScale old, + TemperatureScale new) { + + switch (old) { + case KELVIN: + switch (new) { + case CELSIUS: + value = value - 273.0; + break; + case FAHRENHEIT: + value = (9.0 * (value - 273) / 5.0) + 32.0; + break; + case KELVIN: + break; + } + break; + case CELSIUS: + switch (new) { + case FAHRENHEIT: + value = (9.0 * value / 5.0) + 32.0; + break; + case KELVIN: + value = value + 273.0; + break; + case CELSIUS: + break; + } + break; + + case FAHRENHEIT: + switch (new) { + case CELSIUS: + value = (5.0 * (value - 32.0) / 9.0); + break; + case KELVIN: + value = (5.0 * (value - 32.0) / 9.0) + 273.0; + break; + case FAHRENHEIT: + break; + } + break; + } + return value; +} + +void sensors_applet_init(SensorsApplet *sensors_applet) { + + g_assert(sensors_applet); + g_assert(sensors_applet->applet); + + /* plugin functions are stored as name -> get_value_function pairs so + * use standard string functions on hash table */ + sensors_applet->plugins = g_hash_table_new(g_str_hash, + g_str_equal); + + sensors_applet->required_plugins = g_hash_table_new_full(g_str_hash, + g_str_equal, + g_free, + NULL); + + /* initialise size */ + sensors_applet->size = DEFAULT_APPLET_SIZE; + + panel_applet_set_flags(sensors_applet->applet, + PANEL_APPLET_EXPAND_MINOR); + + g_signal_connect(sensors_applet->applet, "destroy", + G_CALLBACK(destroy_cb), + sensors_applet); + + + /* if not setup, write defaults to gconf */ + sensors_applet_gconf_setup(sensors_applet); + + /* now do any setup needed manually */ + sensors_applet_plugins_load_all(sensors_applet); + + /* should have created sensors tree above, but if have + not was because we couldn't find any sensors */ + if (NULL == sensors_applet->sensors) { + GtkWidget *label; + label = gtk_label_new(_("No sensors found!")); + gtk_container_add(GTK_CONTAINER(sensors_applet->applet), label); + gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet)); + return; + } + + /* only do menu and signal connections if sensors are found */ + panel_applet_setup_menu_from_file(sensors_applet->applet, + DATADIR, + SENSORS_APPLET_MENU_FILE, + NULL, + sensors_applet_menu_verbs, + sensors_applet); + + g_signal_connect(sensors_applet->applet, "style-set", + G_CALLBACK(style_set_cb), + sensors_applet); + + g_signal_connect(sensors_applet->applet, "change_background", + G_CALLBACK(change_background_cb), + sensors_applet); + + g_signal_connect(G_OBJECT(sensors_applet->applet), "change_orient", + G_CALLBACK(change_orient_cb), + sensors_applet); + + g_signal_connect(G_OBJECT(sensors_applet->applet), "size_allocate", + G_CALLBACK(size_allocate_cb), + sensors_applet); + + + + sensors_applet_update_active_sensors(sensors_applet); + sensors_applet_pack_display(sensors_applet); + + sensors_applet->timeout_id = g_timeout_add_seconds(panel_applet_gconf_get_int(sensors_applet->applet, TIMEOUT, NULL) / 1000, + (GSourceFunc)sensors_applet_update_active_sensors, + sensors_applet); + gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet)); +} + + + diff --git a/sensors-applet/sensors-applet.h b/sensors-applet/sensors-applet.h new file mode 100644 index 0000000..ac56dc4 --- /dev/null +++ b/sensors-applet/sensors-applet.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2005-2009 Alex Murray <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SENSORS_APPLET_H +#define SENSORS_APPLET_H + +#include <gtk/gtk.h> +#include <panel-applet.h> +#include "sensors-applet-sensor.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_LIBNOTIFY +#include <libnotify/notify.h> +#endif + +typedef struct _ActiveSensor ActiveSensor; + +#include "prefs-dialog.h" + +#define GRAPH_FRAME_EXTRA_WIDTH 6 +#define SENSORS_APPLET_ICON "sensors-applet" + +static const gchar * const stock_icons[NUM_ICONS] = { + "sensors-applet-cpu", + "sensors-applet-drive-harddisk", + "sensors-applet-battery", + "sensors-applet-memory", + "sensors-applet-gpu", + "sensors-applet-chip", + "sensors-applet-fan", + "sensors-applet-case" +}; + +#define DEFAULT_ICON_SIZE 22 + +#define UNITS_CELSIUS "\302\260C" +#define UNITS_FAHRENHEIT "\302\260F" +#define UNITS_KELVIN "" +#define UNITS_RPM _("RPM") +#define UNITS_VOLTAGE _("V") +#define UNITS_CURRENT _("A") + + +/* enumeration used to identify columns in the GtkTreeStore data + * structure and to access specific gconf keys too. + */ +enum { + PATH_COLUMN = 0, + ID_COLUMN, + LABEL_COLUMN, + INTERFACE_COLUMN, + SENSOR_TYPE_COLUMN, + ENABLE_COLUMN, + VISIBLE_COLUMN, + LOW_VALUE_COLUMN, + HIGH_VALUE_COLUMN, + ALARM_ENABLE_COLUMN, + LOW_ALARM_COMMAND_COLUMN, + HIGH_ALARM_COMMAND_COLUMN, + ALARM_TIMEOUT_COLUMN, + MULTIPLIER_COLUMN, + OFFSET_COLUMN, + ICON_TYPE_COLUMN, + ICON_PIXBUF_COLUMN, + GRAPH_COLOR_COLUMN, + N_COLUMNS +}; + + +/* for display mode */ +typedef enum { + DISPLAY_LABEL_WITH_VALUE = 0, + DISPLAY_ICON_WITH_VALUE, + DISPLAY_VALUE, + DISPLAY_ICON, + DISPLAY_GRAPH +} DisplayMode; + +typedef enum { + VALUE_BESIDE_LABEL = 0, + VALUE_BELOW_LABEL +} LayoutMode; + +typedef enum { + KELVIN = 0, + CELSIUS, + FAHRENHEIT +} TemperatureScale; + +/* types of Notifs - low and high alarm warnings and error conditions*/ +typedef enum { + LOW_ALARM = 0, + HIGH_ALARM, + SENSOR_INTERFACE_ERROR, + GCONF_READ_ERROR, + GCONF_WRITE_ERROR, + NUM_NOTIFS +} NotifType; + +/* only always two type of alarms - may have more notif types */ +#define NUM_ALARMS 2 + +struct _SensorsApplet { + /* the actual applet for this instance */ + PanelApplet* applet; + gint size; + + GtkTreeStore *sensors; + GtkTreeSelection *selection; + + GHashTable *required_plugins; + GHashTable *plugins; + + guint timeout_id; + /* preferences and about windows (if Gtk < 2.6)*/ + PrefsDialog *prefs_dialog; + + /* primary table to contain the panel dispay - we pack the + * list of labels and sensor values into this container */ + GtkWidget *table; + GList *active_sensors; +#ifdef HAVE_LIBNOTIFY + NotifyNotification *notification; +#endif // HAVE_LIBNOTIFY +}; + + + +/* non-static function prototypes */ +void sensors_applet_init(SensorsApplet *sensors_applet); +void sensors_applet_sensor_enabled(SensorsApplet *sensors_applet, + GtkTreePath *path); +void sensors_applet_sensor_disabled(SensorsApplet *sensors_applet, + GtkTreePath *path); +gboolean sensors_applet_update_active_sensors(SensorsApplet *sensors_applet); +/** + * to be called by things like prefs dialog to turn off a sensor alarm + */ +void sensors_applet_alarm_off(SensorsApplet *sensors_applet, + GtkTreePath *path, + NotifType notif_type); +void sensors_applet_all_alarms_off(SensorsApplet *sensors_applet, + GtkTreePath *path); +void sensors_applet_icon_changed(SensorsApplet *sensors_applet, + GtkTreePath *path); +void sensors_applet_update_sensor(SensorsApplet *sensors_applet, + GtkTreePath *path); + +void sensors_applet_display_layout_changed(SensorsApplet *sensors_applet); +void sensors_applet_reorder_sensors(SensorsApplet *sensors_applet); +gdouble sensors_applet_convert_temperature(gdouble value, + TemperatureScale old, + TemperatureScale new); +void sensors_applet_notify(SensorsApplet *sensors_applet, + NotifType notif_type); +void sensors_applet_notify_end(ActiveSensor *active_sensor, NotifType notif_type); +void sensors_applet_notify_end_all(SensorsApplet *sensors_applet); +void sensors_applet_notify_active_sensor(ActiveSensor *active_sensor, NotifType notif_type); +GdkPixbuf *sensors_applet_load_icon(IconType icon_type); +void sensors_applet_graph_size_changed(SensorsApplet *sensors_applet); + +typedef void SensorsInterfaceTestSensorFunc(SensorsApplet *sensors_applet, + const gchar *path); +void sensors_applet_find_sensors(SensorsApplet *sensors_applet, + const gchar *path, + SensorsInterfaceTestSensorFunc test_sensor); + +#endif /* SENSORS_APPLET_H */ |