From a8987293d28f0024984b24f916ab7bf927505377 Mon Sep 17 00:00:00 2001 From: esanchezm Date: Fri, 15 Sep 2006 15:16:33 +0000 Subject: [PATCH] 2006-08-31 Esteban Sanchez * Initial import. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@172 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f --- pandora_applet/AUTHORS | 1 + pandora_applet/COPYING | 1 + pandora_applet/ChangeLog | 3 + pandora_applet/INSTALL | 1 + pandora_applet/Makefile.am | 2 + pandora_applet/NEWS | 0 pandora_applet/README | 0 pandora_applet/acinclude.m4 | 94 + pandora_applet/autogen.sh | 45 + pandora_applet/configure.in | 58 + pandora_applet/data/Makefile.am | 20 + pandora_applet/data/bubble-source.svg | 116 + pandora_applet/data/help-browser.svg | 213 ++ pandora_applet/data/lamp-source.svg | 1131 ++++++ pandora_applet/data/pandora-agents-bad.png | Bin 0 -> 1412 bytes pandora_applet/data/pandora-agents-ok.png | Bin 0 -> 1503 bytes .../data/pandora-agents-unknown.png | Bin 0 -> 1409 bytes pandora_applet/data/pandora-alerts-bad.png | Bin 0 -> 1949 bytes pandora_applet/data/pandora-alerts-ok.png | Bin 0 -> 1977 bytes .../data/pandora-alerts-unknown.png | Bin 0 -> 1928 bytes pandora_applet/data/pandora-applet-bad.png | Bin 0 -> 960 bytes pandora_applet/data/pandora-applet-good.png | Bin 0 -> 968 bytes .../data/pandora-applet-unknown.png | Bin 0 -> 964 bytes pandora_applet/data/pandora-servers-bad.png | Bin 0 -> 1395 bytes pandora_applet/data/pandora-servers-ok.png | Bin 0 -> 1593 bytes .../data/pandora-servers-unknown.png | Bin 0 -> 1881 bytes pandora_applet/data/pandora.png | Bin 0 -> 4808 bytes pandora_applet/data/server-source.svg | 3095 +++++++++++++++++ pandora_applet/po/POTFILES.in | 8 + pandora_applet/src/Makefile.am | 20 + pandora_applet/src/eggtrayicon.c | 559 +++ pandora_applet/src/eggtrayicon.h | 80 + pandora_applet/src/main.c | 64 + pandora_applet/src/pandora-applet.c | 513 +++ pandora_applet/src/pandora-applet.h | 56 + pandora_applet/src/pandora-info-window.c | 414 +++ pandora_applet/src/pandora-info-window.h | 53 + pandora_applet/src/pandora-setup-dialog.c | 291 ++ pandora_applet/src/pandora-setup-dialog.h | 57 + pandora_applet/src/pandora-setup.c | 417 +++ pandora_applet/src/pandora-setup.h | 65 + pandora_applet/src/pandora-status-checker.c | 402 +++ pandora_applet/src/pandora-status-checker.h | 65 + pandora_applet/src/pandora-status.c | 218 ++ pandora_applet/src/pandora-status.h | 67 + 45 files changed, 8129 insertions(+) create mode 100644 pandora_applet/AUTHORS create mode 120000 pandora_applet/COPYING create mode 100644 pandora_applet/ChangeLog create mode 120000 pandora_applet/INSTALL create mode 100644 pandora_applet/Makefile.am create mode 100644 pandora_applet/NEWS create mode 100644 pandora_applet/README create mode 100644 pandora_applet/acinclude.m4 create mode 100755 pandora_applet/autogen.sh create mode 100644 pandora_applet/configure.in create mode 100644 pandora_applet/data/Makefile.am create mode 100644 pandora_applet/data/bubble-source.svg create mode 100644 pandora_applet/data/help-browser.svg create mode 100644 pandora_applet/data/lamp-source.svg create mode 100644 pandora_applet/data/pandora-agents-bad.png create mode 100644 pandora_applet/data/pandora-agents-ok.png create mode 100644 pandora_applet/data/pandora-agents-unknown.png create mode 100644 pandora_applet/data/pandora-alerts-bad.png create mode 100644 pandora_applet/data/pandora-alerts-ok.png create mode 100644 pandora_applet/data/pandora-alerts-unknown.png create mode 100644 pandora_applet/data/pandora-applet-bad.png create mode 100644 pandora_applet/data/pandora-applet-good.png create mode 100644 pandora_applet/data/pandora-applet-unknown.png create mode 100644 pandora_applet/data/pandora-servers-bad.png create mode 100644 pandora_applet/data/pandora-servers-ok.png create mode 100644 pandora_applet/data/pandora-servers-unknown.png create mode 100644 pandora_applet/data/pandora.png create mode 100644 pandora_applet/data/server-source.svg create mode 100644 pandora_applet/po/POTFILES.in create mode 100644 pandora_applet/src/Makefile.am create mode 100644 pandora_applet/src/eggtrayicon.c create mode 100644 pandora_applet/src/eggtrayicon.h create mode 100644 pandora_applet/src/main.c create mode 100644 pandora_applet/src/pandora-applet.c create mode 100644 pandora_applet/src/pandora-applet.h create mode 100644 pandora_applet/src/pandora-info-window.c create mode 100644 pandora_applet/src/pandora-info-window.h create mode 100644 pandora_applet/src/pandora-setup-dialog.c create mode 100644 pandora_applet/src/pandora-setup-dialog.h create mode 100644 pandora_applet/src/pandora-setup.c create mode 100644 pandora_applet/src/pandora-setup.h create mode 100644 pandora_applet/src/pandora-status-checker.c create mode 100644 pandora_applet/src/pandora-status-checker.h create mode 100644 pandora_applet/src/pandora-status.c create mode 100644 pandora_applet/src/pandora-status.h diff --git a/pandora_applet/AUTHORS b/pandora_applet/AUTHORS new file mode 100644 index 0000000000..d6b1c721bb --- /dev/null +++ b/pandora_applet/AUTHORS @@ -0,0 +1 @@ +Esteban Sanchez diff --git a/pandora_applet/COPYING b/pandora_applet/COPYING new file mode 120000 index 0000000000..e1cdc17cb3 --- /dev/null +++ b/pandora_applet/COPYING @@ -0,0 +1 @@ +/usr/share/automake-1.4/COPYING \ No newline at end of file diff --git a/pandora_applet/ChangeLog b/pandora_applet/ChangeLog new file mode 100644 index 0000000000..54a57c7789 --- /dev/null +++ b/pandora_applet/ChangeLog @@ -0,0 +1,3 @@ +2006-08-31 Esteban Sanchez + + * Initial import. diff --git a/pandora_applet/INSTALL b/pandora_applet/INSTALL new file mode 120000 index 0000000000..56c9903c02 --- /dev/null +++ b/pandora_applet/INSTALL @@ -0,0 +1 @@ +/usr/share/automake-1.4/INSTALL \ No newline at end of file diff --git a/pandora_applet/Makefile.am b/pandora_applet/Makefile.am new file mode 100644 index 0000000000..8723614eb7 --- /dev/null +++ b/pandora_applet/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS=src data + diff --git a/pandora_applet/NEWS b/pandora_applet/NEWS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pandora_applet/README b/pandora_applet/README new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pandora_applet/acinclude.m4 b/pandora_applet/acinclude.m4 new file mode 100644 index 0000000000..3f0e7044a3 --- /dev/null +++ b/pandora_applet/acinclude.m4 @@ -0,0 +1,94 @@ +dnl @synopsis CHECK_MYSQL_DB +dnl +dnl This macro tries to find the headers and librariess for the +dnl MySQL database to build client applications. +dnl +dnl If includes are found, the variable MYSQL_INC will be set. If +dnl libraries are found, the variable MYSQL_LIB will be set. if no check +dnl was successful, the script exits with a error message. +dnl +dnl @category InstalledPackages +dnl @author Harald Welte +dnl @version 2006-01-07 +dnl @license AllPermissive + +AC_DEFUN([CHECK_MYSQL_DB], [ + +AC_ARG_WITH(mysql, + [ --with-mysql=PREFIX Prefix of your MySQL installation], + [my_prefix=$withval], [my_prefix=]) +AC_ARG_WITH(mysql-inc, + [ --with-mysql-inc=PATH Path to the include directory of MySQL], + [my_inc=$withval], [my_inc=]) +AC_ARG_WITH(mysql-lib, + [ --with-mysql-lib=PATH Path to the libraries of MySQL], + [my_lib=$withval], [my_lib=]) + + +AC_SUBST(MYSQL_INC) +AC_SUBST(MYSQL_LIB) + +if test "$my_prefix" != "no"; then + +AC_MSG_CHECKING([for MySQL mysql_config program]) +for d in $my_prefix/bin /usr/bin /usr/local/bin /usr/local/mysql/bin /opt/mysql/bin /opt/packages/mysql/bin +do + if test -x $d/mysql_config + then + AC_MSG_RESULT(found mysql_config in $d) + MYSQL_INC=$($d/mysql_config --include) + MYSQL_LIB=$($d/mysql_config --libs) + break + fi +done + +if test "$MYSQL_INC" = ""; then +AC_MSG_RESULT(mysql_config not found) +if test "$my_prefix" != ""; then + AC_MSG_CHECKING([for MySQL includes in $my_prefix/include]) + if test -f "$my_prefix/include/mysql.h" ; then + MYSQL_INC="-I$my_prefix/include" + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR(mysql.h not found) + fi + AC_MSG_CHECKING([for MySQL libraries in $my_prefix/lib]) + if test -f "$my_prefix/lib/libmysql.so" ; then + MYSQL_LIB="-L$my_prefix/lib -lmysqlclient" + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR(libmysqlclient.so not found) + fi +else + if test "$my_inc" != ""; then + AC_MSG_CHECKING([for MySQL includes in $my_inc]) + if test -f "$my_inc/mysql.h" ; then + MYSQL_INC="-I$my_inc" + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR(mysql.h not found) + fi + fi + if test "$my_lib" != ""; then + AC_MSG_CHECKING([for MySQL libraries in $my_lib]) + if test -f "$my_lib/libmysqlclient.so" ; then + MYSQL_LIB="-L$my_lib -lmysqlclient" + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR(libmysqlclient.so not found) + fi + fi +fi + +fi + +if test "$MYSQL_INC" = "" ; then + AC_CHECK_HEADER([mysql.h], [], AC_MSG_ERROR(mysql.h not found)) +fi +if test "$MYSQL_LIB" = "" ; then + AC_CHECK_LIB(mysqlclient, mysql_close, [], AC_MSG_ERROR(libmysqlclient.so not found)) +fi + +fi + +]) diff --git a/pandora_applet/autogen.sh b/pandora_applet/autogen.sh new file mode 100755 index 0000000000..5b2a78a59a --- /dev/null +++ b/pandora_applet/autogen.sh @@ -0,0 +1,45 @@ +#! /bin/sh + +# $Id: autogen.sh,v 1.4 2002/12/02 01:39:49 murrayc Exp $ +# +# Copyright (c) 2002 Daniel Elstner +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License VERSION 2 as +# published by the Free Software Foundation. You are not allowed to +# use any other version of the license; unless you got the explicit +# permission from the author to do so. +# +# 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 + +dir=`echo "$0" | sed 's,[^/]*$,,'` +test "x${dir}" = "x" && dir='.' + +if test "x`cd "${dir}" 2>/dev/null && pwd`" != "x`pwd`" +then + echo "This script must be executed directly from the source directory." + exit 1 +fi + +rm -f config.cache acconfig.h + +echo "- Running aclocal." && \ +aclocal && \ +echo "- Running autoconf." && \ +autoconf && \ +echo "- Running autoheader." && \ +autoheader && \ +echo "- Running automake." && \ +automake --add-missing --gnu && \ +echo && \ +./configure "$@" && exit 0 + +exit 1 + diff --git a/pandora_applet/configure.in b/pandora_applet/configure.in new file mode 100644 index 0000000000..0baddea4ed --- /dev/null +++ b/pandora_applet/configure.in @@ -0,0 +1,58 @@ +AC_PREREQ(2.59) + +m4_define([pandoraapplet_major_version], [1]) +m4_define([pandoraapplet_minor_version], [0]) +m4_define([pandoraapplet_micro_version], [0]) +m4_define([pandoraapplet_build_version], []) +m4_define([pandoraapplet_version], m4_format('%s.%s.%s%s', pandoraapplet_major_version, pandoraapplet_minor_version, pandoraapplet_micro_version, pandoraapplet_build_version)) + +AC_INIT([pandora-applet], [pandoraapplet_version], [http://sourceforge.net/], [pandora_applet]) +AC_CONFIG_SRCDIR([src/main.c]) +AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) + +AC_SUBST(ACLOCAL_AMFLAGS, "$ACLOCAL_FLAGS") + +AM_CONFIG_HEADER(config.h) +AM_MAINTAINER_MODE + +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC +AC_STDC_HEADERS + +GLIB_REQUIRED=2.6.0 +GTK_REQUIRED=2.8.0 + +PKG_CHECK_MODULES(PANDORA, + glib-2.0 >= $GLIB_REQUIRED + gtk+-2.0 >= $GTK_REQUIRED + gthread-2.0 + libxml-2.0) + +CHECK_MYSQL_DB + +GETTEXT_PACKAGE=pandora-applet +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The gettext package]) +ALL_LINGUAS="" +AM_GLIB_GNU_GETTEXT + +if test "x${prefix}" = "xNONE"; then + AC_DEFINE_UNQUOTED(PIXMAPS_DIR, "${ac_default_prefix}/$DATADIRNAME/${PACKAGE}/pixmaps", [Pixmaps directory]) + pixmaps_dir="${ac_default_prefix}/$DATADIRNAME/${PACKAGE}/pixmaps" +else + AC_DEFINE_UNQUOTED(PIXMAPS_DIR, "${prefix}/$DATADIRNAME/${PACKAGE}/pixmaps", [Pixmaps directory]) + pixmaps_dir="${prefix}/$DATADIRNAME/${PACKAGE}/pixmaps" +fi + +AC_SUBST(pixmaps_dir) + +AC_SUBST(PANDORA_CFLAGS) +AC_SUBST(PANDORA_LIBS) + +AC_CONFIG_FILES([ +Makefile +src/Makefile +data/Makefile]) + +AC_OUTPUT diff --git a/pandora_applet/data/Makefile.am b/pandora_applet/data/Makefile.am new file mode 100644 index 0000000000..75d35ca9b1 --- /dev/null +++ b/pandora_applet/data/Makefile.am @@ -0,0 +1,20 @@ +pixmapsdir = $(pixmaps_dir) + +pixmaps_DATA = \ + pandora-applet-bad.png \ + pandora-applet-good.png \ + pandora-applet-unknown.png \ + pandora-alerts-bad.png \ + pandora-alerts-ok.png \ + pandora-alerts-unknown.png \ + pandora-servers-bad.png \ + pandora-servers-ok.png \ + pandora-servers-unknown.png \ + pandora-agents-bad.png \ + pandora-agents-ok.png \ + pandora-agents-unknown.png \ + pandora.png + +EXTRA_DIST = \ + $(pixmaps_DATA) + diff --git a/pandora_applet/data/bubble-source.svg b/pandora_applet/data/bubble-source.svg new file mode 100644 index 0000000000..a7846212b6 --- /dev/null +++ b/pandora_applet/data/bubble-source.svg @@ -0,0 +1,116 @@ + + + + + + + + + image/svg+xml + + + Emblem Important + + + Jakub Steiner + + + + + emblem + photos + pictures + raw + jpeg + + + + + + + + + + + + + + + + + + + diff --git a/pandora_applet/data/help-browser.svg b/pandora_applet/data/help-browser.svg new file mode 100644 index 0000000000..669dda345f --- /dev/null +++ b/pandora_applet/data/help-browser.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Help Browser + 2005-11-06 + + + Tuomas Kuosmanen + + + + + help + browser + documentation + docs + man + info + + + + + + Jakub Steiner, Andreas Nilsson + + + http://tigert.com + + + + + + + + + + + + + + + + + + diff --git a/pandora_applet/data/lamp-source.svg b/pandora_applet/data/lamp-source.svg new file mode 100644 index 0000000000..74a9aa7885 --- /dev/null +++ b/pandora_applet/data/lamp-source.svg @@ -0,0 +1,1131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Info + + + Jakub Steiner + + + + + dialog + info + + + http://jimmac.musichall.cz + + + + Garrett LeSage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pandora_applet/data/pandora-agents-bad.png b/pandora_applet/data/pandora-agents-bad.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e892007d07de4960e05c9d1a2085a1b15fc86d GIT binary patch literal 1412 zcmV-~1$+95P)85WrW0k&;@Ijs8Q4gH7R%+Y%u$ zfq7tF2r)Afi4?4GI3<;em>}o`-EOt#`x{#8bzl`(odfSU{~?Y@1mHTbFq%l*NnW{< zh)qlov27#*27S;Pgajoq#?bXVTHD*yH#Zwzqp@O)SpuHUod&5j$RWgHY<&D~c4kJ| zu^6USN4MKB7<~LjDG|{qG9IJrd6b_$3u@cj%UbJ)bKstc)Y|a7dtuvtl)H7yi6$pzrv2aj(JawDP8Z(n}%ts}}M=npt^2!V`@^5;2}FaO*vAj#kB*+cRga;cT@R1rqSR$VFFEPBt+`crMvqL`VFat%(ZJu zSF3yu=)r)@__z{6EC9$gh$_pv<4jDPN-sL8wn9>2ClYtoAS!|R_=O9JLr2DWRIAs; zNv9LQyaeWB+3e@5(p$|Fvu$3Jni+E(jPHL|QiMW;0j1Q86hah2;qaMs?qfkpOs`Kk z5-C_fN=eD7Ot*d?(`-Q7gI*V-H9{#E9R=G)#NwdTA;Jn!mX)%E5D}q2VVr1xt5T^9tJ3S8p1Avc%;sMhw>W&j8#m~7IvW; zaS*mWyukM{trn(M1)A2ZiKYqsu@%D_*vm?agw3h*?BCP9cdf;;y%mB~=6R2smloC8m5y;5y9k*U<@naANUekeqz-Cmgk@Ac}k zwBx#g%;kpFI%lX{j?$}F!M4J>M$XHvf!`(b(Ht2A;klwQr># zmWsuCKa)X>jh$186mn{c;)@sceGm9wH!}yW4uS_SH#W2^6kufJ%ojUrdK$M>(jCux z@UE3VXtADjJa6gc))wm8wX-881lH6PAoa4>aI zNPC6H3F|_M)62~K=QB*!pQwaWk`Lf>i{o|)D@8wgl7#t%fa00007Tw+eRN-pf4h)p{a8?w zizwh`IF!0GHTvt+PZ9|d{v&K@9(Bht1gTqNeB}y{*Z)>?o#HLvULlVh8ftP88<^`) zU7Wpq{#SaCM}(xp>&jD6R`moAi~lk8(!+TXbGwko`%$PK(4U8LSARP_@*Y|LA(}2H zB|))mP4MsP7Ui|Se=5fN{fl7M0bBOTKz91$tD{%R`b%hhPErbpNsV-LfJ!hs-D<4G z(!Z0xRPTO&kA7jz%|v2+c6#)E`u&F}3~x#~e}kWHKTzm@o0{KoUKzq0>nasvg|7wrKb9V;ZvzguPzUoknCfJ5>qy)OwiK2 zd@LSaK3!VWaixiei(pV#1PBvWF~TI!&!241$)=08f*D&W9pN=x5)Av)aAb!z4dmc% zgt~ynCPqI=HHb~G&n zQlU)~j_Jzbw$;ZFV6P2gyd@i0XggbfY-G=|<$aFoHKXzdAr4YopQG(;11xA@!F4w4 zbu-j!CgjwC033aRR`u&Tu%HWhnqvG1jmkDnJ$5FA(^FBZ?LIoK-3Ns{%_ptPytDnK zU(uJ4!_B8Bs+#pKjpBd(-oW~_pIY`i&HLr;5{`B8RDoQTVP`){tG;?4SbhrC8>MeM z#V=~b?pt(J@>GBfHYNQ&)wO@s5V`$iq<=a%6!NT#>E0?o{)gGpAK(*yqdt452nJ+$GV$1pv|A6!9q=3qHp3PF7{oP0Nz`Y+FMyq!r{Skll zTxYD+cBdutbE1^6a8Gc{f^6H@*eEt|ieG#R{GpJ4z9V?4kEq_oq(9;_&uzq-&ThV& z{6Gb42uby|fm(WyO?8dU)fLk$fAyyx(2r*cFQzWa3fxHyUQT6mIWlIMsM$F3k>jci zHS1k=8jAYH=QYoDj-I-_oKG=lhvGM41DC91I!l6eqGp4TR8R+I4T_FR($YgXYMh$m z;uOF1JI$T@Aji+A4o>ozRXT7zoET1q62pX|X(Ay_K>H}V2o|2$v^xs7)xdR%wCn42 zzq|hcIJqS6RhcJn1*N8xvNB5B5ix#C#H%2(0vtQ@{1)?Jbo8~%8EXIl002ovPDHLk FV1kQ?)cF7a literal 0 HcmV?d00001 diff --git a/pandora_applet/data/pandora-agents-unknown.png b/pandora_applet/data/pandora-agents-unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..dc2ede74a127206467e82417c3f5149c84fed37e GIT binary patch literal 1409 zcmV-{1%CR8P) zK~z}7#hANK99I;Fzk6qv-Ps4bEbo^M*u<9Y7`cj4A^rnfvV>gG$3;*YcNBCeMQCW! zL{t`%3pcJJ1^FL{WCbfGi!s<>76R+tW%fPy-V_X&5aaMN{G_Soj^?|+Gv~}bM{rC{ zj}ZZefFU6muq>2aZe;unpr*&@0wyBS*l=rW zyVc&-K(gK<7LnN2;g4$#g_0(dtFZb$&3Zbm+@d#Q439>}Sve8Z^cVto5C{aOIyx^U zdM-87)@T!~6UU7>o-%A~Rd~I)#9DeYTdtUgz~hl|%#op{$FPBkSS&Vr<;qpr*BvGr zmYi0VnqhHigVe%no!eHEzH8pWb=Dz3KPQvP?{40>Ci;6ELc!Am0oazHDH$aasTb~c z=G#(Pci$c4+0*CfL!tbT{n*fu`0m!tujuOvVoAYSN(hL@LPVo6^101BrHYB(9pu-i z&p)m?Xu*R>*crWc?JAc$>JVqk^Dnix#<_XpD)A_zz=Qqw^9m2 z>^L|ku*t<8;%EK5+HjpV5-6KL7-<6HST{)_|we-%0 z0_|WofpV$V6iSn^ft2gImy}n;vcsQoWy^P^dUoHosX_HE)KieM@1?E{r+%Dz%YO6iVcPSvfLJ!5E%wW(}E~x{$J2sT$sID5^D{jEqy* z{kKf!UDWcL=eu>jT3PqVzeeYcdkHgQM0(}Q7kh9%t@NXu zOLl(QqgXy4yOf4kZ)$9PAPYR&ZRz)p1|#FF7{kN#rqM4KD%89$3uX+YmaDu?YhCqt zxWAP@cwTv2tueXu-Y~aN{bFFoz{0yKe=RHAB9p-5Lz~g3&*9!6zj=!8?Si>eu4<|(3i*L;(Al?c^A#F3|NPP5yZKT=f| z-)X&F4!2SZ64GC&GWKJ)wsGpIw8&UV2e P00000NkvXXu0mjf-00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)(H&|7B^4IT$TU;2P#QK zK~zY`m6vU7Q`Z^CfA?NHwqrX9c3udCk`5XOVYGn;nn^%V+i6UpliGpMR%z=R35{){ zOk1@VtwP#|X__iaovMAnld05p6H})GS(yeZFA;?*&_GDzgb*kYJI2P2->>cawhxyC z6OsZ)dUVb`e$M~@yqxE`*8=m5*LwB>EC;p=u*IgTtK6De2avH?VnxX^Y`_WNU%=IX z-!~_YFb{Bx0Do%MlGB74XUc3q5`s63|U5NTZ8i5ZG7ph;-ia~bGH?B zFW?XOeZ~U>cft2PQqWudcLL$nSD~xR{6$qkQA{b7OetSW5_EMT zM#8w>+`|tyZxj}}U2g+z0MctcdlBJ452aO$Pk)NIts7cfP3u(El)2W^o~SCg-7qwS zFqOb|b(Ff-cUk*~gU!#Z?fg&#+FCSa>&l56h@J(odi6aE%PpT?E6P2uruQ`syj}pL z3;nd*yhcmY;;lfN2<+?>bU_*!hV|?3KUf};a+xbsWuxM~zq4WedI8vJ5n*#{F^`al zLqmh9Je|Pud9DPPuT!ZR0%_npE4&^=LD+0@8ODn0R1yTiOxU!`<)B{&uImtw-$#J1 zQxyqOZMUzmI0ZaHp-w&D0gMicX?3x%Jh6@+wY;s0zJsDY!ibY+&Fj3zK zRx4z)aO{{_or(hW_4n?7Inm@KoH~UuI7o8cI&?|8A6=4|TD*izE@4SQY{PSoX9f-Ny48Hd4 z28QDabi??c1^B41sD9bCaZB668`q&&G_4E<;p2}@!p267x89;ySqbShs>6W}h*z)T zICKbW891Vd{LA0aclO*A@SYg(`xIGKcfV(ImGawO2C>ZDg9j0G9ck}gtnKYsJ30_v zc?HW0FW`FmX{t}1qTE>^Ir>)X1NaJImC>SmmMxlU^Ox|ayx^yWf>&{6JOJ*8_f^ z4$QP`?!M~Y{VW{WKmM)FGoey0UnW&w|G+hzs;xy024|j?@9*U3vExIEqVxp(K6NG~ z<%a@(AG)p|4%r6^mp_N@lRg#zltdYpfUSZK<(&_Z6fZtar#}wzNk-q*JC>p8HC+EHO(>p4(_}0b zjhaS{^}3B)H)C8G)vBgz>QM!6TQ77@?1dTJOmzxU8>TJ5_vgn%Da5y^{i)zSnltM8q)8MV$f)k3-Ph)a3qVW224w zx=!4#mDp@H91c5nyA4qgNvHFq(ghkDJhCmM}&>sB~hEQXqNJ)i3B z9hn!y@^u8gy(0z?*|DSbV6kZZ$=bD@B$G)Zkv;^$aq#frFH$^YSa`JYi^0LcbTAnF j0f3??9|FIBl!N~VL$?g?9Mbcy00000NkvXXu0mjf1J9l4 literal 0 HcmV?d00001 diff --git a/pandora_applet/data/pandora-alerts-ok.png b/pandora_applet/data/pandora-alerts-ok.png new file mode 100644 index 0000000000000000000000000000000000000000..0be5bbe73e410a9ce58a22355ab9009f71f38ec8 GIT binary patch literal 1977 zcmV;q2S)gbP)00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)(H&|7A>-bUKr(6I``iqhIu67dG;6W5Y&_I7yjgwOP$~v}eg}cXIi|*0?sT9RPgw zKCiq-U=n^%TdVy#=O=b?!PP`cNwAg8RI`#I3Xw<*3`|TCr0AfFFS*DGwOMIC=U?f^BMNwgRap&Voy>4CjYYP*71Pmpl`CZ}rTa z5oCOZfQd=K9Uvz^XQf5tilVegVPFsGMXGw%(Qu_)L()H3o+t+%30zh(9kKRB)iR~`#r=k=eR(dyw3X2T2xb=0asC3 z6k1F?8gI8C`Ow;I+qG=zGP;#+db!Ch23Wx|&T@*N9OJBcp3mf2uBn{_#4u4}d@Zq< zKco-wl&oW;@f2|-krmirY#`VXM4Ivw3-Gt}`PB6%>NZ#RFX+!kzk@FR!N>G+lQI_a z8~F=z(+(m;ap(>(B|S%(=&4tFMao~tj@AGO}Qh&pG)RuWZ`8-PY zc!CrB9aESbP~WA-TE|A~x7jIv%F~wbvDUSfbNNl2vYnX`p0_e@V*Ja*Kj1%D@AC$y zXkUc8!f%xSd9nF})c3O@O*G@eg$)}LNmz~YU;Ax_a)wbA6)RRQaU~0XU3-mZEDZ}FNLOS&B z?EOxCC!d`8?3$)&d+U8({ccXCwR)cy(=<=o{dQc^1%Tf&gc?v#jk{A-U4V00B zNoIaNaAY9)_V`;YHgs*o(b+7^ zJjdYIi;Kb)->eGK*U-%!DS522hONbU*sV6Sh{hd%kbm}^Bu~Z}4>aXyS}HsjXg+~H zzdzcm>)P@kzPKF2EZ}B;gy3Kd!-!(B7%a-y5H&V#-x{I2%gCGBQx7WOaJlWC1*I;Q zl)r##f$}9?7=}SI5hoG}GZGl4yK{&eeSS1e`@Er{GdUMXnMa_=k)!6BGD9NiN7q9W zqY_f745OnV#>OJ#|2?U@}rs+C8(&WCqX>maBtbZmqHIAC zZntv@Q1LJVu}CBn9~)0HFnF3s>nU}Pl7?c0N~blP8Tnu%~jL+88<%l{K-Xy}wcVE67-C(>!_o^|VL z357xg0*wgaIC1i1OPKpK3lG-bY-?+abaZsQ44`S+ao|@E^2PrF@J$XhWR}8k00000 LNkvXXu0mjf!&a{L literal 0 HcmV?d00001 diff --git a/pandora_applet/data/pandora-alerts-unknown.png b/pandora_applet/data/pandora-alerts-unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..91c1c5e48acf2e4717bba11d2fa783be81f631c2 GIT binary patch literal 1928 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 literal 0 HcmV?d00001 diff --git a/pandora_applet/data/pandora-servers-unknown.png b/pandora_applet/data/pandora-servers-unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..6a3c37840c6e90f3f3e9886ebca08efe27f9af34 GIT binary patch literal 1881 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 d&eQi&V5e5YUqqX8RD-|RkO9V2x9Xxp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Server + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + server + daemon + comupetr + lan + service + provider + + + + + Garrett LeSage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pandora_applet/po/POTFILES.in b/pandora_applet/po/POTFILES.in new file mode 100644 index 0000000000..72ce77c84a --- /dev/null +++ b/pandora_applet/po/POTFILES.in @@ -0,0 +1,8 @@ +[encoding: UTF-8] +# List of source files containing translatable strings. +# Please keep this file sorted alphabetically. + +src/main.c +src/pandora-applet.c +src/pandora-info-window.c +src/pandora-setup-dialog.c diff --git a/pandora_applet/src/Makefile.am b/pandora_applet/src/Makefile.am new file mode 100644 index 0000000000..fdbad846ca --- /dev/null +++ b/pandora_applet/src/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES = $(PANDORA_CFLAGS) \ + $(MYSQL_INC) \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + -DGLADEDIR=\""$(gladedir)"\" + +bin_PROGRAMS = pandora-applet + +pandora_applet_SOURCES = main.c \ + pandora-applet.c pandora-applet.h \ + pandora-setup.c pandora-setup.h \ + pandora-status.c pandora-status.h \ + pandora-status-checker.c pandora-status-checker.h \ + pandora-info-window.c pandora-info-window.h \ + pandora-setup-dialog.c pandora-setup-dialog.h \ + eggtrayicon.c eggtrayicon.h + +pandora_applet_LDADD = $(PANDORA_LIBS) \ + $(MYSQL_LIB) + diff --git a/pandora_applet/src/eggtrayicon.c b/pandora_applet/src/eggtrayicon.c new file mode 100644 index 0000000000..ebf8a4814d --- /dev/null +++ b/pandora_applet/src/eggtrayicon.c @@ -0,0 +1,559 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* eggtrayicon.c + * Copyright (C) 2002 Anders Carlsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "eggtrayicon.h" + +#include +#if defined (GDK_WINDOWING_X11) +#include +#include +#elif defined (GDK_WINDOWING_WIN32) +#include +#endif + +#ifndef EGG_COMPILATION +#ifndef _ +#define _(x) dgettext (GETTEXT_PACKAGE, x) +#define N_(x) x +#endif +#else +#define _(x) x +#define N_(x) x +#endif + +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + +#define SYSTEM_TRAY_ORIENTATION_HORZ 0 +#define SYSTEM_TRAY_ORIENTATION_VERT 1 + +enum { + PROP_0, + PROP_ORIENTATION +}; + +static GtkPlugClass *parent_class = NULL; + +static void egg_tray_icon_init (EggTrayIcon *icon); +static void egg_tray_icon_class_init (EggTrayIconClass *klass); + +static void egg_tray_icon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void egg_tray_icon_realize (GtkWidget *widget); +static void egg_tray_icon_unrealize (GtkWidget *widget); + +static void egg_tray_icon_add (GtkContainer *container, + GtkWidget *widget); + +#ifdef GDK_WINDOWING_X11 +static void egg_tray_icon_update_manager_window (EggTrayIcon *icon, + gboolean dock_if_realized); +static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon); +#endif + +GType +egg_tray_icon_get_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + { + static const GTypeInfo our_info = + { + sizeof (EggTrayIconClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) egg_tray_icon_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EggTrayIcon), + 0, /* n_preallocs */ + (GInstanceInitFunc) egg_tray_icon_init + }; + + our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0); + } + + return our_type; +} + +static void +egg_tray_icon_init (EggTrayIcon *icon) +{ + icon->stamp = 1; + icon->orientation = GTK_ORIENTATION_HORIZONTAL; + + gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); +} + +static void +egg_tray_icon_class_init (EggTrayIconClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + GtkContainerClass *container_class = (GtkContainerClass *)klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->get_property = egg_tray_icon_get_property; + + widget_class->realize = egg_tray_icon_realize; + widget_class->unrealize = egg_tray_icon_unrealize; + + container_class->add = egg_tray_icon_add; + + g_object_class_install_property (gobject_class, + PROP_ORIENTATION, + g_param_spec_enum ("orientation", + _("Orientation"), + _("The orientation of the tray."), + GTK_TYPE_ORIENTATION, + GTK_ORIENTATION_HORIZONTAL, + G_PARAM_READABLE)); + +#if defined (GDK_WINDOWING_X11) + /* Nothing */ +#elif defined (GDK_WINDOWING_WIN32) + g_warning ("Port eggtrayicon to Win32"); +#else + g_warning ("Port eggtrayicon to this GTK+ backend"); +#endif +} + +static void +egg_tray_icon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EggTrayIcon *icon = EGG_TRAY_ICON (object); + + switch (prop_id) + { + case PROP_ORIENTATION: + g_value_set_enum (value, icon->orientation); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +#ifdef GDK_WINDOWING_X11 + +static void +egg_tray_icon_get_orientation_property (EggTrayIcon *icon) +{ + Display *xdisplay; + Atom type; + int format; + union { + gulong *prop; + guchar *prop_ch; + } prop = { NULL }; + gulong nitems; + gulong bytes_after; + int error, result; + + g_assert (icon->manager_window != None); + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + gdk_error_trap_push (); + type = None; + result = XGetWindowProperty (xdisplay, + icon->manager_window, + icon->orientation_atom, + 0, G_MAXLONG, FALSE, + XA_CARDINAL, + &type, &format, &nitems, + &bytes_after, &(prop.prop_ch)); + error = gdk_error_trap_pop (); + + if (error || result != Success) + return; + + if (type == XA_CARDINAL) + { + GtkOrientation orientation; + + orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ? + GTK_ORIENTATION_HORIZONTAL : + GTK_ORIENTATION_VERTICAL; + + if (icon->orientation != orientation) + { + icon->orientation = orientation; + + g_object_notify (G_OBJECT (icon), "orientation"); + } + } + + if (prop.prop) + XFree (prop.prop); +} + +static GdkFilterReturn +egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data) +{ + EggTrayIcon *icon = user_data; + XEvent *xev = (XEvent *)xevent; + + if (xev->xany.type == ClientMessage && + xev->xclient.message_type == icon->manager_atom && + xev->xclient.data.l[1] == icon->selection_atom) + { + egg_tray_icon_update_manager_window (icon, TRUE); + } + else if (xev->xany.window == icon->manager_window) + { + if (xev->xany.type == PropertyNotify && + xev->xproperty.atom == icon->orientation_atom) + { + egg_tray_icon_get_orientation_property (icon); + } + if (xev->xany.type == DestroyNotify) + { + egg_tray_icon_manager_window_destroyed (icon); + } + } + return GDK_FILTER_CONTINUE; +} + +#endif + +static void +egg_tray_icon_unrealize (GtkWidget *widget) +{ +#ifdef GDK_WINDOWING_X11 + EggTrayIcon *icon = EGG_TRAY_ICON (widget); + GdkWindow *root_window; + + if (icon->manager_window != None) + { + GdkWindow *gdkwin; + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget), + icon->manager_window); + + gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); + } + + root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); + + gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon); + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); +#endif +} + +#ifdef GDK_WINDOWING_X11 + +static void +egg_tray_icon_send_manager_message (EggTrayIcon *icon, + long message, + Window window, + long data1, + long data2, + long data3) +{ + XClientMessageEvent ev; + Display *display; + + ev.type = ClientMessage; + ev.window = window; + ev.message_type = icon->system_tray_opcode_atom; + ev.format = 32; + ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window); + ev.data.l[1] = message; + ev.data.l[2] = data1; + ev.data.l[3] = data2; + ev.data.l[4] = data3; + + display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + gdk_error_trap_push (); + XSendEvent (display, + icon->manager_window, False, NoEventMask, (XEvent *)&ev); + XSync (display, False); + gdk_error_trap_pop (); +} + +static void +egg_tray_icon_send_dock_request (EggTrayIcon *icon) +{ + egg_tray_icon_send_manager_message (icon, + SYSTEM_TRAY_REQUEST_DOCK, + icon->manager_window, + gtk_plug_get_id (GTK_PLUG (icon)), + 0, 0); +} + +static void +egg_tray_icon_update_manager_window (EggTrayIcon *icon, + gboolean dock_if_realized) +{ + Display *xdisplay; + + if (icon->manager_window != None) + return; + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + XGrabServer (xdisplay); + + icon->manager_window = XGetSelectionOwner (xdisplay, + icon->selection_atom); + + if (icon->manager_window != None) + XSelectInput (xdisplay, + icon->manager_window, StructureNotifyMask|PropertyChangeMask); + + XUngrabServer (xdisplay); + XFlush (xdisplay); + + if (icon->manager_window != None) + { + GdkWindow *gdkwin; + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), + icon->manager_window); + + gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); + + if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) + egg_tray_icon_send_dock_request (icon); + + egg_tray_icon_get_orientation_property (icon); + } +} + +static void +egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon) +{ + GdkWindow *gdkwin; + + g_return_if_fail (icon->manager_window != None); + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), + icon->manager_window); + + gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); + + icon->manager_window = None; + + egg_tray_icon_update_manager_window (icon, TRUE); +} + +#endif + +static gboolean +transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) +{ + gdk_window_clear_area (widget->window, event->area.x, event->area.y, + event->area.width, event->area.height); + return FALSE; +} + +static void +make_transparent_again (GtkWidget *widget, GtkStyle *previous_style, + gpointer user_data) +{ + gdk_window_set_back_pixmap (widget->window, NULL, TRUE); +} + +static void +make_transparent (GtkWidget *widget, gpointer user_data) +{ + if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget)) + return; + + gtk_widget_set_app_paintable (widget, TRUE); + gtk_widget_set_double_buffered (widget, FALSE); + gdk_window_set_back_pixmap (widget->window, NULL, TRUE); + g_signal_connect (widget, "expose_event", + G_CALLBACK (transparent_expose_event), NULL); + g_signal_connect_after (widget, "style_set", + G_CALLBACK (make_transparent_again), NULL); +} + +static void +egg_tray_icon_realize (GtkWidget *widget) +{ +#ifdef GDK_WINDOWING_X11 + EggTrayIcon *icon = EGG_TRAY_ICON (widget); + GdkScreen *screen; + GdkDisplay *display; + Display *xdisplay; + char buffer[256]; + GdkWindow *root_window; + + if (GTK_WIDGET_CLASS (parent_class)->realize) + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + make_transparent (widget, NULL); + + screen = gtk_widget_get_screen (widget); + display = gdk_screen_get_display (screen); + xdisplay = gdk_x11_display_get_xdisplay (display); + + /* Now see if there's a manager window around */ + g_snprintf (buffer, sizeof (buffer), + "_NET_SYSTEM_TRAY_S%d", + gdk_screen_get_number (screen)); + + icon->selection_atom = XInternAtom (xdisplay, buffer, False); + + icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False); + + icon->system_tray_opcode_atom = XInternAtom (xdisplay, + "_NET_SYSTEM_TRAY_OPCODE", + False); + + icon->orientation_atom = XInternAtom (xdisplay, + "_NET_SYSTEM_TRAY_ORIENTATION", + False); + + egg_tray_icon_update_manager_window (icon, FALSE); + egg_tray_icon_send_dock_request (icon); + + root_window = gdk_screen_get_root_window (screen); + + /* Add a root window filter so that we get changes on MANAGER */ + gdk_window_add_filter (root_window, + egg_tray_icon_manager_filter, icon); +#endif +} + +static void +egg_tray_icon_add (GtkContainer *container, GtkWidget *widget) +{ + g_signal_connect (widget, "realize", + G_CALLBACK (make_transparent), NULL); + GTK_CONTAINER_CLASS (parent_class)->add (container, widget); +} + +EggTrayIcon * +egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL); +} + +EggTrayIcon* +egg_tray_icon_new (const gchar *name) +{ + return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL); +} + +guint +egg_tray_icon_send_message (EggTrayIcon *icon, + gint timeout, + const gchar *message, + gint len) +{ + guint stamp; + + g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); + g_return_val_if_fail (timeout >= 0, 0); + g_return_val_if_fail (message != NULL, 0); + +#ifdef GDK_WINDOWING_X11 + if (icon->manager_window == None) + return 0; +#endif + + if (len < 0) + len = strlen (message); + + stamp = icon->stamp++; + +#ifdef GDK_WINDOWING_X11 + /* Get ready to send the message */ + egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, + icon->manager_window, + timeout, len, stamp); + + /* Now to send the actual message */ + gdk_error_trap_push (); + while (len > 0) + { + XClientMessageEvent ev; + Display *xdisplay; + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + ev.type = ClientMessage; + ev.window = icon->manager_window; + ev.format = 8; + ev.message_type = XInternAtom (xdisplay, + "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); + if (len > 20) + { + memcpy (&ev.data, message, 20); + len -= 20; + message += 20; + } + else + { + memcpy (&ev.data, message, len); + len = 0; + } + + XSendEvent (xdisplay, + icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev); + XSync (xdisplay, False); + } + gdk_error_trap_pop (); +#endif + + return stamp; +} + +void +egg_tray_icon_cancel_message (EggTrayIcon *icon, + guint id) +{ + g_return_if_fail (EGG_IS_TRAY_ICON (icon)); + g_return_if_fail (id > 0); +#ifdef GDK_WINDOWING_X11 + egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, + (Window)gtk_plug_get_id (GTK_PLUG (icon)), + id, 0, 0); +#endif +} + +GtkOrientation +egg_tray_icon_get_orientation (EggTrayIcon *icon) +{ + g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL); + + return icon->orientation; +} diff --git a/pandora_applet/src/eggtrayicon.h b/pandora_applet/src/eggtrayicon.h new file mode 100644 index 0000000000..e6664fcb08 --- /dev/null +++ b/pandora_applet/src/eggtrayicon.h @@ -0,0 +1,80 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* eggtrayicon.h + * Copyright (C) 2002 Anders Carlsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __EGG_TRAY_ICON_H__ +#define __EGG_TRAY_ICON_H__ + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +G_BEGIN_DECLS + +#define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ()) +#define EGG_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon)) +#define EGG_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) +#define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON)) +#define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON)) +#define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) + +typedef struct _EggTrayIcon EggTrayIcon; +typedef struct _EggTrayIconClass EggTrayIconClass; + +struct _EggTrayIcon +{ + GtkPlug parent_instance; + + guint stamp; + +#ifdef GDK_WINDOWING_X11 + Atom selection_atom; + Atom manager_atom; + Atom system_tray_opcode_atom; + Atom orientation_atom; + Window manager_window; +#endif + GtkOrientation orientation; +}; + +struct _EggTrayIconClass +{ + GtkPlugClass parent_class; +}; + +GType egg_tray_icon_get_type (void); + +EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen *screen, + const gchar *name); + +EggTrayIcon *egg_tray_icon_new (const gchar *name); + +guint egg_tray_icon_send_message (EggTrayIcon *icon, + gint timeout, + const char *message, + gint len); +void egg_tray_icon_cancel_message (EggTrayIcon *icon, + guint id); + +GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon); + +G_END_DECLS + +#endif /* __EGG_TRAY_ICON_H__ */ diff --git a/pandora_applet/src/main.c b/pandora_applet/src/main.c new file mode 100644 index 0000000000..aaf21cf613 --- /dev/null +++ b/pandora_applet/src/main.c @@ -0,0 +1,64 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 +#endif + +#include + +#include "pandora-applet.h" + +#include +#include + +void +exit_app () +{ + gtk_main_quit (); +} + +int +main (int argc, char *argv[]) +{ + PandoraApplet *applet; + + gtk_init (&argc, &argv); + + g_set_application_name (_("Pandora applet")); + + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + /* Init threads */ + if (!g_thread_supported ()) { + g_thread_init (NULL); + } + + applet = pandora_applet_new (); + + if (!applet) { + return 1; + } + + gtk_main (); + + return 0; +} diff --git a/pandora_applet/src/pandora-applet.c b/pandora_applet/src/pandora-applet.c new file mode 100644 index 0000000000..6c71bafe70 --- /dev/null +++ b/pandora_applet/src/pandora-applet.c @@ -0,0 +1,513 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + Based on NetworkManager Wireless Applet + GNOME Wireless Applet Authors: + * Eskil Heyn Olsen + * Bastien Nocera (Gnome2 port) + + 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, 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 +#endif + +#include +#include + +#include "pandora-applet.h" +#include "pandora-info-window.h" +#include "pandora-status-checker.h" +#include "pandora-status.h" +#include "pandora-setup-dialog.h" +#include "pandora-setup.h" + +struct _PandoraAppletPrivate { + GtkImage *image; + GdkPixbuf *icon_good; + GdkPixbuf *icon_bad; + GdkPixbuf *icon_unknown; + GtkWidget *event_box; + GtkWidget *context_menu; + + gchar *userdir; + gchar *userfile; + + PandoraInfoWindow *info_window; + PandoraSetupDialog *setup_dialog; + PandoraSetup *setup; + PandoraStatusChecker *checker; + PandoraStatus *status; +}; + +#define PANDORA_APPLET_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), PANDORA_TYPE_APPLET, PandoraAppletPrivate)) + +static gboolean pandora_applet_create_setup_file (PandoraApplet *applet); +static void pandora_applet_create_user_dir (PandoraApplet *applet); +static void pandora_applet_set_image_from_pixbuf (PandoraApplet *applet, + GdkPixbuf *icon); +static void pandora_applet_set_image_from_stock (PandoraApplet *applet, + gchar *stock_id); +static gboolean pandora_applet_toplevel_menu_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + gpointer data); +static void pandora_applet_changed_status_cb (GObject *object, + gpointer *data); +static GtkWidget *pandora_applet_context_menu_create (PandoraApplet *applet); + +static GObject *pandora_applet_constructor (GType type, guint n_props, + GObjectConstructParam *props); +static GtkWidget *pandora_applet_get_instance (PandoraApplet *applet); +static void pandora_applet_destroy (PandoraApplet *applet); +static GType pandora_applet_get_type (void); /* for G_DEFINE_TYPE */ + +G_DEFINE_TYPE (PandoraApplet, pandora_applet, EGG_TYPE_TRAY_ICON) + +static void +pandora_applet_init (PandoraApplet *applet) +{ + applet->priv = PANDORA_APPLET_GET_PRIVATE (applet); + + applet->priv->icon_good = load_icon_from_disk ("pandora-applet-good.png"); + applet->priv->icon_bad = load_icon_from_disk ("pandora-applet-bad.png"); + applet->priv->icon_unknown = load_icon_from_disk ("pandora-applet-unknown.png"); + + applet->priv->userdir = g_build_filename (g_get_home_dir (), ".pandora", NULL); + applet->priv->userfile = g_build_filename (applet->priv->userdir, "config.xml", + NULL); + pandora_applet_create_user_dir (applet); + + g_signal_connect (applet, "destroy", G_CALLBACK (pandora_applet_destroy), NULL); + + /* Event box is the main applet widget */ + applet->priv->event_box = gtk_event_box_new (); + gtk_container_set_border_width (GTK_CONTAINER (applet->priv->event_box), + 0); + + applet->priv->image = GTK_IMAGE (gtk_image_new ()); + gtk_container_add (GTK_CONTAINER (applet->priv->event_box), + GTK_WIDGET (applet->priv->image)); + gtk_container_add (GTK_CONTAINER (applet), applet->priv->event_box); + + g_signal_connect (applet->priv->event_box, "button_press_event", + G_CALLBACK (pandora_applet_toplevel_menu_button_press_cb), + applet); + + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_unknown); + + applet->priv->context_menu = pandora_applet_context_menu_create (applet); + + /* Init setup */ + applet->priv->setup = pandora_setup_new (applet->priv->userfile); + + /* Init windows and dialogs */ + applet->priv->info_window = PANDORA_INFO_WINDOW (pandora_info_window_new ()); + + applet->priv->setup_dialog = PANDORA_SETUP_DIALOG (pandora_setup_dialog_new ()); + pandora_setup_dialog_set_setup (applet->priv->setup_dialog, + applet->priv->setup); + + /* Init status and checker */ + applet->priv->status = PANDORA_STATUS (pandora_status_new ()); + + pandora_info_window_set_status (applet->priv->info_window, + applet->priv->status); + + applet->priv->checker = pandora_status_checker_new (applet->priv->setup, + applet->priv->status); + + gtk_widget_show_all (GTK_WIDGET (applet)); + + g_signal_connect (G_OBJECT (applet->priv->status), "changed", + G_CALLBACK (pandora_applet_changed_status_cb), + (gpointer) applet); + + pandora_status_checker_run (applet->priv->checker); +} + +static void +pandora_applet_class_init (PandoraAppletClass *klass) +{ + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (PandoraAppletPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->constructor = pandora_applet_constructor; +} + +static GObject * +pandora_applet_constructor (GType type, guint n_props, + GObjectConstructParam *props) +{ + GObject *obj; + PandoraApplet *applet; + PandoraAppletClass *klass; + + klass = PANDORA_APPLET_CLASS (g_type_class_peek (type)); + obj = G_OBJECT_CLASS (pandora_applet_parent_class)->constructor (type, + n_props, + props); + applet = PANDORA_APPLET (obj); + + return obj; +} + +static GtkWidget * +pandora_applet_get_instance (PandoraApplet *applet) +{ + gtk_widget_hide (GTK_WIDGET (applet)); + + + return GTK_WIDGET (applet); +} + +static void +pandora_applet_destroy (PandoraApplet *applet) +{ + pandora_status_checker_stop (applet->priv->checker); + + gtk_widget_destroy (GTK_WIDGET (applet->priv->info_window)); + gtk_widget_destroy (GTK_WIDGET (applet->priv->setup_dialog)); + + exit_app (); +} + +PandoraApplet * +pandora_applet_new () +{ + return g_object_new (PANDORA_TYPE_APPLET, "title", "Pandora", NULL); +} + +static void +pandora_applet_quit_cb (GtkMenuItem *mi, PandoraApplet *applet) +{ + gtk_widget_destroy (GTK_WIDGET (applet)); +} + +static void +pandora_applet_about_cb (GtkMenuItem *mi, PandoraApplet *applet) +{ + GdkPixbuf *pixbuf; + gchar *pixbuf_path; + static const gchar *authors[] = + { + "Artica Soluciones Tecnológicas:\n", + "Esteban Sánchez ", + NULL + }; + static const gchar *artists[] = + { + "Esteban Sánchez " + "Icons from Tango Desktop Project ", + NULL + }; + + + + pixbuf_path = g_build_filename (PIXMAPS_DIR, "pandora.png", NULL); + pixbuf = gdk_pixbuf_new_from_file (pixbuf_path, NULL); + g_free (pixbuf_path); + + gtk_show_about_dialog (NULL, + "name", _("Pandora Enterprise monitor applet"), + "version", VERSION, + "copyright", _("Copyright \xc2\xa9 2006 Artica ST.\n"), + "comments", _("Notification area applet for monitoring your Pandora system."), + "website", "http://pandora.sourceforge.net/", + "authors", authors, + "artists", artists, + "translator-credits", _("translator-credits"), + "logo", pixbuf, + NULL); + + if (pixbuf) { + g_object_unref (pixbuf); + } + +} + +static void +pandora_applet_show_info_cb (GtkMenuItem *mi, PandoraApplet *applet) +{ + gtk_window_present (GTK_WINDOW (applet->priv->info_window)); +} + +static void +pandora_applet_show_setup_cb (GtkMenuItem *mi, PandoraApplet *applet) +{ + gint result; + + gtk_widget_show_all (GTK_WIDGET (applet->priv->setup_dialog)); + + result = gtk_dialog_run (GTK_DIALOG (applet->priv->setup_dialog)); + + switch (result) { + case GTK_RESPONSE_ACCEPT: + pandora_setup_dialog_apply_changes (applet->priv->setup_dialog); + pandora_setup_save_to_disk (applet->priv->setup); + break; + default: + break; + } + + gtk_widget_hide (GTK_WIDGET (applet->priv->setup_dialog)); +} + +static void +pandora_applet_changed_status_cb (GObject *object, + gpointer *data) +{ + PandoraApplet *applet = PANDORA_APPLET (data); + + switch (pandora_status_get_alerts (PANDORA_STATUS (object))) { + case STATE_BAD: + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_bad); + return; + break; + case STATE_OK: + break; + default: + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_unknown); + return; + } + + switch (pandora_status_get_servers (PANDORA_STATUS (object))) { + case STATE_BAD: + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_bad); + return; + break; + case STATE_OK: + break; + default: + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_unknown); + return; + } + + switch (pandora_status_get_agents (PANDORA_STATUS (object))) { + case STATE_BAD: + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_bad); + return; + break; + case STATE_OK: + break; + default: + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_unknown); + return; + } + + pandora_applet_set_image_from_pixbuf (applet, applet->priv->icon_good); +} + +static GtkWidget * +pandora_applet_context_menu_create (PandoraApplet *applet) +{ + GtkWidget *menu; + GtkWidget *menu_item; + GtkWidget *image; + + g_return_val_if_fail (applet != NULL, NULL); + + menu = gtk_menu_new (); + + /* Show status item */ + menu_item = gtk_image_menu_item_new_with_mnemonic (_("_Show main window")); + g_signal_connect (G_OBJECT (menu_item), "activate", + G_CALLBACK (pandora_applet_show_info_cb), applet); + image = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), + image); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + + /* Preferences item */ + menu_item = gtk_image_menu_item_new_with_mnemonic (_("_Preferences")); + g_signal_connect (G_OBJECT (menu_item), "activate", + G_CALLBACK (pandora_applet_show_setup_cb), applet); + image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), + image); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + + /* Separator */ + menu_item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_show (menu_item); + + /* About item */ + menu_item = gtk_image_menu_item_new_with_mnemonic (_("_About")); + g_signal_connect (G_OBJECT (menu_item), "activate", + G_CALLBACK (pandora_applet_about_cb), applet); + image = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + + /* Quit item */ + menu_item = gtk_image_menu_item_new_with_mnemonic (_("_Quit")); + g_signal_connect (G_OBJECT (menu_item), "activate", + G_CALLBACK (pandora_applet_quit_cb), applet); + image = gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + + gtk_widget_show_all (menu); + + return menu; +} + +static void +pandora_applet_menu_position_func (GtkMenu *menu G_GNUC_UNUSED, + int *x, int *y, gboolean *push_in, + gpointer user_data) +{ + int screen_w, screen_h, button_x, button_y, panel_w, panel_h; + GtkRequisition requisition; + GdkScreen *screen; + PandoraApplet *applet = (PandoraApplet *)user_data; + + screen = gtk_widget_get_screen (applet->priv->event_box); + screen_w = gdk_screen_get_width (screen); + screen_h = gdk_screen_get_height (screen); + + gdk_window_get_origin (applet->priv->event_box->window, &button_x, &button_y); + gtk_window_get_size (GTK_WINDOW (gtk_widget_get_toplevel (applet->priv->event_box)), + &panel_w, &panel_h); + + *x = button_x; + + /* Check to see if we would be placing the menu off of the end of the screen. */ + gtk_widget_size_request (GTK_WIDGET (menu), &requisition); + if (button_y + panel_h + requisition.height >= screen_h) + *y = button_y - requisition.height; + else + *y = button_y + panel_h; + + *push_in = TRUE; +} + +static gboolean +pandora_applet_toplevel_menu_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + + PandoraApplet *applet; + + applet = PANDORA_APPLET (data); + + g_return_val_if_fail (applet != NULL, FALSE); + g_return_val_if_fail (PANDORA_IS_APPLET (applet), FALSE); + + switch (event->button) { + case 3: + gtk_menu_popup (GTK_MENU (applet->priv->context_menu), + NULL, NULL, + pandora_applet_menu_position_func, + applet, event->button, event->time); + return TRUE; + default: + g_signal_stop_emission_by_name (widget, "button_press_event"); + return FALSE; + } + + return FALSE; +} + +static void +pandora_applet_setup_widgets (PandoraApplet *applet) +{ +} + +static void +pandora_applet_set_image_from_stock (PandoraApplet *applet, + gchar *stock_id) +{ + gtk_image_set_from_stock (GTK_IMAGE (applet->priv->image), + stock_id, GTK_ICON_SIZE_MENU); +} + +static void +pandora_applet_set_image_from_pixbuf (PandoraApplet *applet, GdkPixbuf *icon) +{ + g_return_if_fail (PANDORA_IS_APPLET (applet)); + g_return_if_fail (icon != NULL); + + gtk_image_set_from_pixbuf (GTK_IMAGE (applet->priv->image), icon); +} + +GdkPixbuf * +load_icon_from_disk (gchar *icon_name) +{ + GError *err = NULL; + gchar *icon_path; + GdkPixbuf *pixbuf; + + icon_path = g_build_filename (PIXMAPS_DIR, icon_name, NULL); + pixbuf = gdk_pixbuf_new_from_file (icon_path, &err); + g_free (icon_path); + + if (pixbuf == NULL) { + g_warning ("Icon %s missing: %s", icon_name, err->message); + g_error_free (err); + return NULL; + } + + return pixbuf; +} + +static gboolean +pandora_applet_create_setup_file (PandoraApplet *applet) +{ + const gchar *contents = "\n\n\n"; + +#if GTK_CHECK_VERSION(2,8,0) + return g_file_set_contents (applet->priv->userfile, contents, -1, NULL); +#else + gint fd; + + if ((fd = open (applet->priv->userfile, O_CREAT | O_WRONLY, 0644)) < 0) { + return FALSE; + } + + if (write (fd, contents, strlen (contents)) < 0) { + close (fd); + return FALSE; + } + + if (close (fd) < 0) { + return FALSE; + } + + return TRUE; +#endif +} + +static void +pandora_applet_create_user_dir (PandoraApplet *applet) +{ + if (!g_file_test (applet->priv->userdir, G_FILE_TEST_IS_DIR)) { + if (g_mkdir (applet->priv->userdir, 0755) != 0) { + g_error ("Cannot create user's directory"); + } + } + + if (!g_file_test (applet->priv->userfile, G_FILE_TEST_IS_REGULAR)) { + if (!pandora_applet_create_setup_file (applet)) { + g_error ("Cannot create user's configuration file"); + } + } +} diff --git a/pandora_applet/src/pandora-applet.h b/pandora_applet/src/pandora-applet.h new file mode 100644 index 0000000000..0732373951 --- /dev/null +++ b/pandora_applet/src/pandora-applet.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 APPLET_H +#define APPLET_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "eggtrayicon.h" + +#define PANDORA_TYPE_APPLET (pandora_applet_get_type()) +#define PANDORA_APPLET(object) (G_TYPE_CHECK_INSTANCE_CAST((object), PANDORA_TYPE_APPLET, PandoraApplet)) +#define PANDORA_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANDORA_TYPE_APPLET, PandoraAppletClass)) +#define PANDORA_IS_APPLET(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), PANDORA_TYPE_APPLET)) +#define PANDORA_IS_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANDORA_TYPE_APPLET)) +#define PANDORA_APPLET_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANDORA_TYPE_APPLET, PandoraAppletClass)) + +typedef struct _PandoraAppletPrivate PandoraAppletPrivate; + +typedef struct { + EggTrayIconClass parent_class; +} PandoraAppletClass; + +/* + * Applet instance data + * + */ +typedef struct { + EggTrayIcon parent; + PandoraAppletPrivate *priv; +} PandoraApplet; + +PandoraApplet *pandora_applet_new (void); + +GdkPixbuf *load_icon_from_disk (gchar *icon_name); + +#endif diff --git a/pandora_applet/src/pandora-info-window.c b/pandora_applet/src/pandora-info-window.c new file mode 100644 index 0000000000..d5165d7e30 --- /dev/null +++ b/pandora_applet/src/pandora-info-window.c @@ -0,0 +1,414 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 +#endif + +#include +#include +#include + +#include "pandora-applet.h" +#include "pandora-info-window.h" + +struct _PandoraInfoWindowPrivate { + GtkWidget *label_alerts; + GtkWidget *label_servers; + GtkWidget *label_agents; + + GtkImage *image_alerts; + GtkImage *image_servers; + GtkImage *image_agents; + + GdkPixbuf *pixbuf_alerts_ok; + GdkPixbuf *pixbuf_alerts_bad; + GdkPixbuf *pixbuf_alerts_unknown; + + GdkPixbuf *pixbuf_servers_ok; + GdkPixbuf *pixbuf_servers_bad; + GdkPixbuf *pixbuf_servers_unknown; + + GdkPixbuf *pixbuf_agents_ok; + GdkPixbuf *pixbuf_agents_bad; + GdkPixbuf *pixbuf_agents_unknown; + + PandoraState state_alerts; + PandoraState state_servers; + PandoraState state_agents; + + PandoraStatus *status; +}; + +#define PANDORA_INFO_WINDOW_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), PANDORA_INFO_WINDOW_TYPE, \ + PandoraInfoWindowPrivate)) + +static void pandora_info_window_init (PandoraInfoWindow *window); +static void pandora_info_window_class_init (PandoraInfoWindowClass *klass); +static void pandora_info_window_finalize (GObject *object); + +static gboolean pandora_info_window_delete_cb (GtkWidget *dialog, + GdkEvent *event, + gpointer data); + +static gboolean pandora_info_window_close_cb (GtkWidget *widget, + gpointer data); + +static void pandora_info_window_status_changed_cb (GObject *object, + gpointer data); + +static void pandora_info_window_status_update (PandoraInfoWindow *window); + +static void pandora_info_window_status_update_alerts (PandoraInfoWindow *window, + PandoraState state); +static void pandora_info_window_status_update_agents (PandoraInfoWindow *window, + PandoraState state); +static void pandora_info_window_status_update_servers (PandoraInfoWindow *window, + PandoraState state); + +GType +pandora_info_window_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (PandoraInfoWindowClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pandora_info_window_class_init, + NULL, + NULL, + sizeof (PandoraInfoWindow), + 0, + (GInstanceInitFunc) pandora_info_window_init + }; + + type = g_type_register_static (GTK_TYPE_WINDOW, "PandoraInfoWindow", + &info, 0); + } + + return type; +} + +static void +pandora_info_window_init (PandoraInfoWindow *window) +{ + GtkWidget *table; + GtkWidget *image; + GtkWidget *hbutton_box; + GtkWidget *button_close; + + window->priv = PANDORA_INFO_WINDOW_GET_PRIVATE (window); + + window->priv->status = NULL; + window->priv->state_alerts = STATE_INVALID; + window->priv->state_servers = STATE_INVALID; + window->priv->state_agents = STATE_INVALID; + + window->priv->pixbuf_alerts_ok = load_icon_from_disk ("pandora-alerts-ok.png"); + window->priv->pixbuf_alerts_bad = load_icon_from_disk ("pandora-alerts-bad.png"); + window->priv->pixbuf_alerts_unknown = load_icon_from_disk ("pandora-alerts-unknown.png"); + window->priv->image_alerts = GTK_IMAGE (gtk_image_new ()); + + window->priv->pixbuf_servers_ok = load_icon_from_disk ("pandora-servers-ok.png"); + window->priv->pixbuf_servers_bad = load_icon_from_disk ("pandora-servers-bad.png"); + window->priv->pixbuf_servers_unknown = load_icon_from_disk ("pandora-servers-unknown.png"); + window->priv->image_servers = GTK_IMAGE (gtk_image_new ()); + + window->priv->pixbuf_agents_ok = load_icon_from_disk ("pandora-agents-ok.png"); + window->priv->pixbuf_agents_bad = load_icon_from_disk ("pandora-agents-bad.png"); + window->priv->pixbuf_agents_unknown = load_icon_from_disk ("pandora-agents-unknown.png"); + window->priv->image_agents = GTK_IMAGE (gtk_image_new ()); + + gtk_window_set_title (GTK_WINDOW (window), _("Pandora status")); + gtk_container_set_border_width (GTK_CONTAINER (window), 5); + gtk_window_set_icon_name (GTK_WINDOW (window), + GTK_STOCK_INFO); + + table = gtk_table_new (4, 2, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + /* First row */ + window->priv->label_alerts = gtk_label_new (_("Alerts status.")); + gtk_misc_set_alignment (GTK_MISC (window->priv->label_alerts), 0, 0.5); + + gtk_image_set_from_pixbuf (window->priv->image_alerts, + window->priv->pixbuf_alerts_unknown); + + gtk_table_attach (GTK_TABLE (table), GTK_WIDGET (window->priv->image_alerts), + 0, 1, 0, 1, GTK_FILL , GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), window->priv->label_alerts, + 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + /* Third row */ + window->priv->label_agents = gtk_label_new (_("Agents status.")); + gtk_misc_set_alignment (GTK_MISC (window->priv->label_agents), 0, 0.5); + + gtk_image_set_from_pixbuf (window->priv->image_agents, + window->priv->pixbuf_agents_unknown); + + gtk_table_attach (GTK_TABLE (table), GTK_WIDGET (window->priv->image_agents), + 0, 1, 1, 2, GTK_FILL , GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), window->priv->label_agents, + 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + /* Second row */ + window->priv->label_servers = gtk_label_new (_("Servers status.")); + gtk_misc_set_alignment (GTK_MISC (window->priv->label_servers), 0, 0.5); + + gtk_image_set_from_pixbuf (window->priv->image_servers, + window->priv->pixbuf_servers_unknown); + + gtk_table_attach (GTK_TABLE (table), GTK_WIDGET (window->priv->image_servers), + 0, 1, 2, 3, GTK_FILL , GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), window->priv->label_servers, + 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + /* Buttons at the bottom */ + hbutton_box = gtk_hbutton_box_new (); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbutton_box), + GTK_BUTTONBOX_END); + + button_close = gtk_button_new_from_stock (GTK_STOCK_CLOSE); + g_signal_connect (G_OBJECT (button_close), "clicked", + G_CALLBACK (pandora_info_window_close_cb), + (gpointer) window); + + gtk_box_pack_start (GTK_BOX (hbutton_box), button_close, + FALSE, TRUE, 5); + + gtk_table_attach (GTK_TABLE (table), hbutton_box, + 0, 2, 3, 4, GTK_FILL, 0, 0, 0); + + gtk_widget_show_all (table); + + gtk_container_add (GTK_CONTAINER (window), table); + + g_signal_connect (G_OBJECT (window), "delete-event", + G_CALLBACK (pandora_info_window_delete_cb), NULL); +} + + +static void +pandora_info_window_class_init (PandoraInfoWindowClass *klass) +{ + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (PandoraInfoWindowPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = pandora_info_window_finalize; +} + +static void +pandora_info_window_finalize (GObject *object) +{ + PandoraInfoWindow *window = PANDORA_INFO_WINDOW (object); + + if (window->priv->status) { + g_object_unref (window->priv->status); + window->priv->status = NULL; + } + + if (window->priv->pixbuf_alerts_ok) { + g_object_unref (window->priv->pixbuf_alerts_ok); + window->priv->pixbuf_alerts_ok = NULL; + } + + if (window->priv->pixbuf_servers_ok) { + g_object_unref (window->priv->pixbuf_servers_ok); + window->priv->pixbuf_servers_ok = NULL; + } + + if (window->priv->pixbuf_agents_ok) { + g_object_unref (window->priv->pixbuf_agents_ok); + window->priv->pixbuf_agents_ok = NULL; + } +} + +GtkWidget * +pandora_info_window_new (void) +{ + GtkWidget *window; + + window = GTK_WIDGET (g_object_new (PANDORA_INFO_WINDOW_TYPE, + "type", GTK_WINDOW_TOPLEVEL, + "default-width", 300, + "resizable", FALSE, + NULL)); + + gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER); + + return window; +} + +static gboolean +pandora_info_window_close_cb (GtkWidget *widget, gpointer data) +{ + GtkWidget *window; + + if (data != NULL) { + window = GTK_WIDGET (data); + gtk_widget_hide (window); + } + + return TRUE; +} + +static gboolean +pandora_info_window_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + gtk_widget_hide (widget); + + return TRUE; +} + +void +pandora_info_window_set_status (PandoraInfoWindow *window, + PandoraStatus *status) +{ + if (window->priv->status) { + g_object_unref (window->priv->status); + } + + window->priv->status = status; + + g_signal_connect (status, "changed", + G_CALLBACK (pandora_info_window_status_changed_cb), + (gpointer) window); + + pandora_info_window_status_update (window); +} + +static void +pandora_info_window_status_update_alerts (PandoraInfoWindow *window, + PandoraState state) +{ + switch (state) { + case STATE_BAD: + gtk_image_set_from_pixbuf (window->priv->image_alerts, + window->priv->pixbuf_alerts_bad); + gtk_label_set_text (GTK_LABEL (window->priv->label_alerts), + _("There are agents with alerts.")); + + break; + case STATE_OK: + gtk_image_set_from_pixbuf (window->priv->image_alerts, + window->priv->pixbuf_alerts_ok); + gtk_label_set_text (GTK_LABEL (window->priv->label_alerts), + _("There are no alerts.")); + break; + default: + gtk_image_set_from_pixbuf (window->priv->image_alerts, + window->priv->pixbuf_alerts_unknown); + gtk_label_set_text (GTK_LABEL (window->priv->label_alerts), + _("Alerts status unknown.")); + return; + } +} + +static void +pandora_info_window_status_update_agents (PandoraInfoWindow *window, + PandoraState state) +{ + switch (state) { + case STATE_BAD: + gtk_image_set_from_pixbuf (window->priv->image_agents, + window->priv->pixbuf_agents_bad); + gtk_label_set_text (GTK_LABEL (window->priv->label_agents), + _("There are agents down.")); + + break; + case STATE_OK: + gtk_image_set_from_pixbuf (window->priv->image_agents, + window->priv->pixbuf_agents_ok); + gtk_label_set_text (GTK_LABEL (window->priv->label_agents), + _("All the agents are running.")); + break; + default: + gtk_image_set_from_pixbuf (window->priv->image_agents, + window->priv->pixbuf_agents_unknown); + gtk_label_set_text (GTK_LABEL (window->priv->label_agents), + _("Agents status unknown.")); + return; + } +} + +static void +pandora_info_window_status_update_servers (PandoraInfoWindow *window, + PandoraState state) +{ + switch (state) { + case STATE_BAD: + gtk_image_set_from_pixbuf (window->priv->image_servers, + window->priv->pixbuf_servers_bad); + gtk_label_set_text (GTK_LABEL (window->priv->label_servers), + _("There are servers down.")); + + break; + case STATE_OK: + gtk_image_set_from_pixbuf (window->priv->image_servers, + window->priv->pixbuf_servers_ok); + gtk_label_set_text (GTK_LABEL (window->priv->label_servers), + _("All the servers are running.")); + break; + default: + gtk_image_set_from_pixbuf (window->priv->image_servers, + window->priv->pixbuf_servers_unknown); + gtk_label_set_text (GTK_LABEL (window->priv->label_servers), + _("Servers status unknown.")); + return; + } +} + +static void +pandora_info_window_status_update (PandoraInfoWindow *window) +{ + PandoraStatus *status; + PandoraState state; + + status = window->priv->status; + + if (status == NULL) { + pandora_info_window_status_update_alerts (window, TRUE); + pandora_info_window_status_update_agents (window, TRUE); + pandora_info_window_status_update_servers (window, TRUE); + } else { + state = pandora_status_get_alerts (status); + pandora_info_window_status_update_alerts (window, state); + + state = pandora_status_get_agents (status); + pandora_info_window_status_update_agents (window, state); + + state = pandora_status_get_servers (status); + pandora_info_window_status_update_servers (window, state); + } +} + +static void +pandora_info_window_status_changed_cb (GObject *object, + gpointer data) +{ + PandoraInfoWindow *window = PANDORA_INFO_WINDOW (data); + + pandora_info_window_status_update (window); +} diff --git a/pandora_applet/src/pandora-info-window.h b/pandora_applet/src/pandora-info-window.h new file mode 100644 index 0000000000..a47d0ccf2a --- /dev/null +++ b/pandora_applet/src/pandora-info-window.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 INFO_WINDOW_H +#define INFO_WINDOW_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pandora-status.h" + +#include + +#define PANDORA_INFO_WINDOW_TYPE (pandora_info_window_get_type()) +#define PANDORA_INFO_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST((object), PANDORA_INFO_WINDOW_TYPE, PandoraInfoWindow)) +#define PANDORA_INFO_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANDORA_INFO_WINDOW_TYPE, PandoraInfoWindowClass)) +#define PANDORA_IS_INFO_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), PANDORA_INFO_WINDOW_TYPE)) +#define PANDORA_IS_INFO_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANDORA_INFO_WINDOW_TYPE)) +#define PANDORA_INFO_WINDOW_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANDORA_INFO_WINDOW_TYPE, PandoraInfoWindowClass)) + +typedef struct _PandoraInfoWindowPrivate PandoraInfoWindowPrivate; + +typedef struct { + GtkWindowClass parent_class; +} PandoraInfoWindowClass; + +typedef struct { + GtkWindow parent; + PandoraInfoWindowPrivate *priv; +} PandoraInfoWindow; + +GtkWidget *pandora_info_window_new (void); +void pandora_info_window_set_status (PandoraInfoWindow *window, + PandoraStatus *status); + +#endif diff --git a/pandora_applet/src/pandora-setup-dialog.c b/pandora_applet/src/pandora-setup-dialog.c new file mode 100644 index 0000000000..3582b78cca --- /dev/null +++ b/pandora_applet/src/pandora-setup-dialog.c @@ -0,0 +1,291 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 +#endif + +#include +#include +#include + +#include "pandora-setup-dialog.h" + +struct _PandoraSetupDialogPrivate { + GtkWidget *entry_host; + GtkWidget *entry_username; + GtkWidget *entry_password; + gchar *real_password; + GtkWidget *entry_dbname; + + PandoraSetup *setup; +}; + +#define PANDORA_SETUP_DIALOG_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), PANDORA_SETUP_DIALOG_TYPE, \ + PandoraSetupDialogPrivate)) + +static void pandora_setup_dialog_init (PandoraSetupDialog *dialog); +static void pandora_setup_dialog_class_init (PandoraSetupDialogClass *klass); +static void pandora_setup_dialog_finalize (GObject *object); + +static gboolean pandora_setup_close_cb (GtkWidget *dialog, gpointer data); + +GType +pandora_setup_dialog_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (PandoraSetupDialogClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pandora_setup_dialog_class_init, + NULL, + NULL, + sizeof (PandoraSetupDialog), + 0, + (GInstanceInitFunc) pandora_setup_dialog_init + }; + + type = g_type_register_static (GTK_TYPE_DIALOG, "PandoraSetupDialog", + &info, 0); + } + + return type; +} + +static void +pandora_setup_dialog_init (PandoraSetupDialog *dialog) +{ + GtkWidget *table; + GtkWidget *hbutton_box; + GtkWidget *button_close; + GtkWidget *frame; + GtkWidget *label_title; + GtkWidget *label; + GtkWidget *alignment; + gchar *str; + + dialog->priv = PANDORA_SETUP_DIALOG_GET_PRIVATE (dialog); + dialog->priv->setup = NULL; + + + gtk_window_set_title (GTK_WINDOW (dialog), _("Preferences")); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_CANCEL); + + gtk_window_set_icon_name (GTK_WINDOW (dialog), + GTK_STOCK_PREFERENCES); + /* Frame */ + str = g_strdup_printf ("%s:", _("Database connection")); + label_title = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label_title), str); + gtk_misc_set_alignment (GTK_MISC (label_title), 0, 0.5); + + frame = gtk_frame_new (NULL); + gtk_frame_set_label_widget (GTK_FRAME (frame), label_title); + gtk_container_set_border_width (GTK_CONTAINER (frame), 5); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); + + /* Table inside frame */ + table = gtk_table_new (4, 2, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + /* First row */ + label = gtk_label_new (_("Host")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + dialog->priv->entry_host = gtk_entry_new (); + + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), dialog->priv->entry_host, + 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + /* Second row */ + label = gtk_label_new (_("Username")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + dialog->priv->entry_username = gtk_entry_new (); + + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), dialog->priv->entry_username, + 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + /* Third row */ + label = gtk_label_new (_("Password")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + dialog->priv->entry_password = gtk_entry_new (); + gtk_entry_set_invisible_char (GTK_ENTRY (dialog->priv->entry_password), + '*'); + gtk_entry_set_visibility (GTK_ENTRY (dialog->priv->entry_password), + FALSE); + + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), dialog->priv->entry_password, + 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + /* Fourth row */ + label = gtk_label_new (_("Database name")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + dialog->priv->entry_dbname = gtk_entry_new (); + + gtk_table_attach (GTK_TABLE (table), label, + 0, 1, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + gtk_table_attach (GTK_TABLE (table), dialog->priv->entry_dbname, + 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); + + alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0); + gtk_container_add (GTK_CONTAINER (alignment), table); + gtk_container_add (GTK_CONTAINER (frame), alignment); + + gtk_widget_show_all (frame); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, FALSE, FALSE, 0); +} + + +static void +pandora_setup_dialog_class_init (PandoraSetupDialogClass *klass) +{ + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (PandoraSetupDialogPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = pandora_setup_dialog_finalize; +} + +static void +pandora_setup_dialog_finalize (GObject *object) +{ + PandoraSetupDialog *dialog; + + dialog = PANDORA_SETUP_DIALOG (object); + + if (dialog->priv->setup) { + g_object_unref (dialog->priv->setup); + } +} + +GtkWidget * +pandora_setup_dialog_new (void) +{ + GtkWidget *dialog; + + dialog = GTK_WIDGET (g_object_new (PANDORA_SETUP_DIALOG_TYPE, + NULL)); + return dialog; +} + +void +pandora_setup_dialog_set_setup (PandoraSetupDialog *dialog, + PandoraSetup *setup) +{ + gchar *value; + + if (dialog->priv->setup) { + g_object_unref (dialog->priv->setup); + } + + dialog->priv->setup = setup; + g_object_ref (G_OBJECT (setup)); + + value = pandora_setup_get_host (setup); + if (value) { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_host), + value); + g_free (value); + value = NULL; + } else { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_host), + ""); + } + + value = pandora_setup_get_username (setup); + if (value) { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_username), + value); + g_free (value); + } else { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_username), + ""); + } + + value = pandora_setup_get_password (setup); + if (value) { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_password), + NOT_SHOWN_PASSWORD); + g_free (value); + } else { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_password), + ""); + } + + value = pandora_setup_get_dbname (setup); + if (value) { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_dbname), + value); + g_free (value); + } else { + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry_dbname), + ""); + } +} + +void +pandora_setup_dialog_apply_changes (PandoraSetupDialog *dialog) +{ + const gchar *host; + const gchar *username; + const gchar *password; + const gchar *dbname; + + host = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry_host)); + username = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry_username)); + password = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry_password)); + dbname = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry_dbname)); + + g_object_set (G_OBJECT (dialog->priv->setup), + "host", host, + "username", username, + "dbname", dbname, + NULL); + + if (g_ascii_strcasecmp (password, NOT_SHOWN_PASSWORD) != 0) { + pandora_setup_set_password (dialog->priv->setup, password); + } +} diff --git a/pandora_applet/src/pandora-setup-dialog.h b/pandora_applet/src/pandora-setup-dialog.h new file mode 100644 index 0000000000..88bb8da841 --- /dev/null +++ b/pandora_applet/src/pandora-setup-dialog.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 SETUP_DIALOG_H +#define SETUP_DIALOG_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "pandora-setup.h" + +#define NOT_SHOWN_PASSWORD "nonenonenone" + +#define PANDORA_SETUP_DIALOG_TYPE (pandora_setup_dialog_get_type()) +#define PANDORA_SETUP_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST((object), PANDORA_SETUP_DIALOG_TYPE, PandoraSetupDialog)) +#define PANDORA_SETUP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANDORA_SETUP_DIALOG_TYPE, PandoraSetupDialogClass)) +#define PANDORA_IS_SETUP_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), PANDORA_SETUP_DIALOG_TYPE)) +#define PANDORA_IS_SETUP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANDORA_SETUP_DIALOG_TYPE)) +#define PANDORA_SETUP_DIALOG_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANDORA_SETUP_DIALOG_TYPE, PandoraSetupDialogClass)) + +typedef struct _PandoraSetupDialogPrivate PandoraSetupDialogPrivate; + +typedef struct { + GtkDialogClass parent_class; +} PandoraSetupDialogClass; + +typedef struct { + GtkDialog parent; + PandoraSetupDialogPrivate *priv; +} PandoraSetupDialog; + +GtkWidget *pandora_setup_dialog_new (void); + +void pandora_setup_dialog_set_setup (PandoraSetupDialog *dialog, + PandoraSetup *setup); +void pandora_setup_dialog_apply_changes (PandoraSetupDialog *dialog); + +#endif diff --git a/pandora_applet/src/pandora-setup.c b/pandora_applet/src/pandora-setup.c new file mode 100644 index 0000000000..f1509c2235 --- /dev/null +++ b/pandora_applet/src/pandora-setup.c @@ -0,0 +1,417 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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. +*/ + +#include "pandora-setup.h" + +#include +#include +#include + +enum { + PROP_0, + PROP_HOST, + PROP_USERNAME, + PROP_PASSWORD, + PROP_DBNAME +}; + +struct _PandoraSetupPrivate { + gchar *config_file; + + gchar *host; + gchar *username; + gchar *password; + gchar *dbname; +}; + +#define PANDORA_SETUP_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), PANDORA_TYPE_SETUP, \ + PandoraSetupPrivate)) + +static GObjectClass *parent_class = NULL; + +static void pandora_setup_read_config_file (PandoraSetup *setup, gchar *file); +static void pandora_setup_init (PandoraSetup *pandora_setup); +static void pandora_setup_class_init (PandoraSetupClass *klass); +static void pandora_setup_finalize (GObject *object); +static void pandora_setup_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void pandora_setup_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +GType +pandora_setup_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (PandoraSetupClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pandora_setup_class_init, + NULL, + NULL, + sizeof (PandoraSetup), + 0, + (GInstanceInitFunc) pandora_setup_init + }; + + type = g_type_register_static (G_TYPE_OBJECT, "PandoraSetup", + &info, 0); + } + + return type; +} + +static void +pandora_setup_init (PandoraSetup *setup) +{ + setup->priv = PANDORA_SETUP_GET_PRIVATE (setup); + + setup->priv->host = NULL; + setup->priv->username = NULL; + setup->priv->password = NULL; + setup->priv->dbname = NULL; +} + +static void +pandora_setup_class_init (PandoraSetupClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (PandoraSetupPrivate)); + + object_class->set_property = pandora_setup_set_property; + object_class->get_property = pandora_setup_get_property; + + g_object_class_install_property (object_class, + PROP_HOST, + g_param_spec_string ("host", + "Host", + "Host to connect to", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_USERNAME, + g_param_spec_string ("username", + "Username", + "Username to use in the connection", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password", + "Password to use in the connection", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_DBNAME, + g_param_spec_string ("dbname", + "Database name", + "Database name to connect to", + NULL, + G_PARAM_READWRITE)); + + object_class->finalize = pandora_setup_finalize; +} + +static void +pandora_setup_finalize (GObject *object) +{ + PandoraSetup *setup = PANDORA_SETUP (object); + + /* Make persistent */ + pandora_setup_save_to_disk (setup); + + if (setup->priv->config_file) { + g_free (setup->priv->config_file); + setup->priv->config_file = NULL; + } + + if (setup->priv->host) { + g_free (setup->priv->host); + setup->priv->host = NULL; + } + + if (setup->priv->username) { + g_free (setup->priv->username); + setup->priv->username = NULL; + } + + if (setup->priv->password) { + g_free (setup->priv->password); + setup->priv->password = NULL; + } + + if (setup->priv->dbname) { + g_free (setup->priv->dbname); + setup->priv->dbname = NULL; + } + + if (G_OBJECT_CLASS (parent_class)->finalize) + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +static void +pandora_setup_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PandoraSetup *setup = PANDORA_SETUP (object); + GDate *date; + + switch (prop_id) { + case PROP_HOST: + g_free (setup->priv->host); + setup->priv->host = g_value_dup_string (value); + + break; + case PROP_USERNAME: + g_free (setup->priv->username); + setup->priv->username = g_value_dup_string (value); + + break; + case PROP_PASSWORD: + g_free (setup->priv->password); + setup->priv->password = g_value_dup_string (value); + + break; + case PROP_DBNAME: + g_free (setup->priv->dbname); + setup->priv->dbname = g_value_dup_string (value); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +pandora_setup_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PandoraSetup *setup = PANDORA_SETUP (object); + + switch (prop_id) { + case PROP_HOST: + g_value_set_string (value, setup->priv->host); + + break; + case PROP_USERNAME: + g_value_set_string (value, setup->priv->username); + + break; + case PROP_PASSWORD: + g_value_set_string (value, setup->priv->password); + + break; + case PROP_DBNAME: + g_value_set_string (value, setup->priv->dbname); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +gchar * +pandora_setup_get_host (PandoraSetup *setup) +{ + gchar *host = NULL; + + g_return_val_if_fail (PANDORA_IS_SETUP (setup), NULL); + + g_object_get (G_OBJECT (setup), "host", &host, NULL); + + return host; +} + +gchar * +pandora_setup_get_username (PandoraSetup *setup) +{ + gchar *username = NULL; + + g_return_val_if_fail (PANDORA_IS_SETUP (setup), NULL); + + g_object_get (G_OBJECT (setup), "username", &username, NULL); + + return username; +} + +gchar * +pandora_setup_get_password (PandoraSetup *setup) +{ + gchar *password = NULL; + + g_return_val_if_fail (PANDORA_IS_SETUP (setup), NULL); + + g_object_get (G_OBJECT (setup), "password", &password, NULL); + + return password; +} + +gchar * +pandora_setup_get_dbname (PandoraSetup *setup) +{ + gchar *dbname = NULL; + + g_return_val_if_fail (PANDORA_IS_SETUP (setup), NULL); + + g_object_get (G_OBJECT (setup), "dbname", &dbname, NULL); + + return dbname; +} + +void +pandora_setup_set_host (PandoraSetup *setup, const gchar *host) +{ + g_return_if_fail (PANDORA_IS_SETUP (setup)); + g_return_if_fail (host != NULL); + + g_object_set (G_OBJECT (setup), "host", host, NULL); +} + +void +pandora_setup_set_username (PandoraSetup *setup, const gchar *username) +{ + g_return_if_fail (PANDORA_IS_SETUP (setup)); + g_return_if_fail (username != NULL); + + g_object_set (G_OBJECT (setup), "username", username, NULL); + +} + +void +pandora_setup_set_password (PandoraSetup *setup, const gchar *password) +{ + g_return_if_fail (PANDORA_IS_SETUP (setup)); + g_return_if_fail (password != NULL); + + g_object_set (G_OBJECT (setup), "password", password, NULL); + +} + +void +pandora_setup_set_dbname (PandoraSetup *setup, const gchar *dbname) +{ + g_return_if_fail (PANDORA_IS_SETUP (setup)); + g_return_if_fail (dbname != NULL); + + g_object_set (G_OBJECT (setup), "dbname", dbname, NULL); + +} + +static void +pandora_setup_read_config_file (PandoraSetup *setup, gchar *file) +{ + xmlDocPtr doc; + xmlNodePtr root; + gchar *host; + gchar *username; + gchar *password; + gchar *dbname; + + doc = xmlParseFile (file); + + if (!doc) { + return; + } + + root = xmlDocGetRootElement (doc); + + if (!root) { + return; + } + + if (g_ascii_strcasecmp ((const gchar*) root->name, "config") == 0) { + host = (gchar *) xmlGetProp (root, (xmlChar *) "host"); + username = (gchar *) xmlGetProp (root, (xmlChar *) "username"); + password = (gchar *) xmlGetProp (root, (xmlChar *) "password"); + dbname = (gchar *) xmlGetProp (root, (xmlChar *) "dbname"); + + g_object_set (setup, + "host", host, + "username", username, + "password", password, + "dbname", dbname, + NULL); + + g_free (host); + g_free (username); + g_free (password); + g_free (dbname); + } +} + +void +pandora_setup_save_to_disk (PandoraSetup *setup) +{ + xmlTextWriterPtr writer; + + writer = xmlNewTextWriterFilename (setup->priv->config_file, 0); + + xmlTextWriterStartDocument (writer, NULL, NULL, NULL); + xmlTextWriterStartElement (writer, BAD_CAST "config"); + + xmlTextWriterWriteAttribute (writer, + BAD_CAST "host", + BAD_CAST setup->priv->host); + xmlTextWriterWriteAttribute (writer, + BAD_CAST "username", + BAD_CAST setup->priv->username); + xmlTextWriterWriteAttribute (writer, + BAD_CAST "password", + BAD_CAST setup->priv->password); + xmlTextWriterWriteAttribute (writer, + BAD_CAST "dbname", + BAD_CAST setup->priv->dbname); + + xmlTextWriterEndElement (writer); + xmlTextWriterEndDocument (writer); + xmlFreeTextWriter (writer); +} + + +PandoraSetup * +pandora_setup_new (gchar *config_file) +{ + PandoraSetup *setup; + + setup = PANDORA_SETUP (g_object_new (PANDORA_TYPE_SETUP, NULL)); + + setup->priv->config_file = g_strdup (config_file); + + pandora_setup_read_config_file (setup, config_file); + + return setup; +} + diff --git a/pandora_applet/src/pandora-setup.h b/pandora_applet/src/pandora-setup.h new file mode 100644 index 0000000000..94d27adee9 --- /dev/null +++ b/pandora_applet/src/pandora-setup.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 SETUP_H +#define SETUP_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#define PANDORA_TYPE_SETUP (pandora_setup_get_type()) +#define PANDORA_SETUP(object) (G_TYPE_CHECK_INSTANCE_CAST((object), PANDORA_TYPE_SETUP, PandoraSetup)) +#define PANDORA_SETUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANDORA_TYPE_SETUP, PandoraSetupClass)) +#define PANDORA_IS_SETUP(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), PANDORA_TYPE_SETUP)) +#define PANDORA_IS_SETUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANDORA_TYPE_SETUP)) +#define PANDORA_SETUP_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANDORA_TYPE_SETUP, PandoraSetupClass)) + +typedef struct _PandoraSetupPrivate PandoraSetupPrivate; + +typedef struct { + GObjectClass parent_class; +} PandoraSetupClass; + +/* + * Setup instance data + * + */ +typedef struct { + GObject parent; + PandoraSetupPrivate *priv; +} PandoraSetup; + +PandoraSetup *pandora_setup_new (gchar *config_file); + +gchar *pandora_setup_get_host (PandoraSetup *setup); +gchar *pandora_setup_get_username (PandoraSetup *setup); +gchar *pandora_setup_get_password (PandoraSetup *setup); +gchar *pandora_setup_get_dbname (PandoraSetup *setup); + +void pandora_setup_set_host (PandoraSetup *setup, const gchar *host); +void pandora_setup_set_username (PandoraSetup *setup, const gchar *username); +void pandora_setup_set_password (PandoraSetup *setup, const gchar *password); +void pandora_setup_set_dbname (PandoraSetup *setup, const gchar *dbname); + +void pandora_setup_save_to_disk (PandoraSetup *setup); + +#endif diff --git a/pandora_applet/src/pandora-status-checker.c b/pandora_applet/src/pandora-status-checker.c new file mode 100644 index 0000000000..ebd610aa46 --- /dev/null +++ b/pandora_applet/src/pandora-status-checker.c @@ -0,0 +1,402 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 +#endif + +#include +#include + +#include "pandora-status-checker.h" + +struct _PandoraStatusCheckerPrivate { + GThread *thread; + GMutex *state_mutex; + + gint state; + + PandoraStatus *status; + PandoraSetup *setup; + + MYSQL *connection; +}; + +#define PANDORA_STATUS_CHECKER_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), PANDORA_STATUS_CHECKER_TYPE, \ + PandoraStatusCheckerPrivate)) + +static gboolean pandora_status_checker_connect (PandoraStatusChecker *checker); +static gboolean pandora_status_checker_disconnect (PandoraStatusChecker *checker); + +static PandoraState pandora_status_checker_check_alerts (PandoraStatusChecker *checker); +static PandoraState pandora_status_checker_check_servers (PandoraStatusChecker *checker); +static PandoraState pandora_status_checker_check_agents (PandoraStatusChecker *checker); + +static void pandora_status_checker_init (PandoraStatusChecker *checker); +static void pandora_status_checker_class_init (PandoraStatusCheckerClass *klass); +static void pandora_status_checker_finalize (GObject *object); + +static gpointer pandora_status_checker_run_thread (gpointer data); + +GType +pandora_status_checker_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (PandoraStatusCheckerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pandora_status_checker_class_init, + NULL, + NULL, + sizeof (PandoraStatusChecker), + 0, + (GInstanceInitFunc) pandora_status_checker_init + }; + + type = g_type_register_static (G_TYPE_OBJECT, "PandoraStatusChecker", + &info, 0); + } + + return type; +} + +static void +pandora_status_checker_init (PandoraStatusChecker *checker) +{ + checker->priv = PANDORA_STATUS_CHECKER_GET_PRIVATE (checker); + + checker->priv->connection = NULL; + + checker->priv->state_mutex = g_mutex_new (); + + checker->priv->state = CHECKER_STATE_READY; +} + + +static void +pandora_status_checker_class_init (PandoraStatusCheckerClass *klass) +{ + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (PandoraStatusCheckerPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = pandora_status_checker_finalize; +} + +static void +pandora_status_checker_finalize (GObject *object) +{ + PandoraStatusChecker *checker; + + checker = PANDORA_STATUS_CHECKER (object); + + switch (checker->priv->state) { + case CHECKER_STATE_RUNNING: + pandora_status_checker_stop (checker); + /* Do not break! */ + case CHECKER_STATE_STOPPING: + g_thread_join (checker->priv->thread); + break; + default: + break; + } + + if (checker->priv->status) { + g_object_unref (checker->priv->status); + checker->priv->status = NULL; + } + + + if (checker->priv->state_mutex) { + g_mutex_free (checker->priv->state_mutex); + checker->priv->state_mutex = NULL; + } + + if (checker->priv->setup) { + g_object_unref (checker->priv->setup); + checker->priv->setup = NULL; + } + + if (checker->priv->connection) { + mysql_close (checker->priv->connection); + checker->priv->connection = NULL; + } +} + +PandoraStatusChecker * +pandora_status_checker_new (PandoraSetup *setup, PandoraStatus *status) +{ + PandoraStatusChecker *checker; + + checker = PANDORA_STATUS_CHECKER (g_object_new (PANDORA_STATUS_CHECKER_TYPE, + NULL)); + checker->priv->setup = setup; + g_object_ref (setup); + + checker->priv->status = status; + g_object_ref (status); + + return checker; +} + +static gboolean +pandora_status_checker_connect (PandoraStatusChecker *checker) +{ + MYSQL *connection; + PandoraSetup *setup; + gchar *host, *username, *password, *dbname; + gboolean retval = TRUE; + + connection = checker->priv->connection; + setup = checker->priv->setup; + + if (connection) { + mysql_close (connection); + } + + connection = mysql_init (NULL); + + if (connection == NULL) { + return FALSE; + } + + g_object_get (G_OBJECT (setup), "host", &host, "username", &username, + "password", &password, "dbname", &dbname, NULL); + + if (mysql_real_connect (connection, host, username, + password, dbname, 3306, NULL, 0) == NULL) + { + + g_print ("mysql_real_connect() failed. %s\n", + mysql_error (connection)); + mysql_close (connection); + + retval = FALSE; + } + + checker->priv->connection = connection; + return retval; +} + +static gboolean +pandora_status_checker_disconnect (PandoraStatusChecker *checker) +{ + if (checker->priv->connection) { + mysql_close (checker->priv->connection); + } + + checker->priv->connection = NULL; +} + +static PandoraState +pandora_status_checker_check_agents (PandoraStatusChecker *checker) +{ + MYSQL *connection = NULL; + MYSQL_RES *result; + MYSQL_ROW row; + const gchar const *query_time = "SELECT * FROM tagente " + "WHERE UNIX_TIMESTAMP(ultimo_contacto_remoto)" + "- intervalo > UNIX_TIMESTAMP(NOW())" ; + const gchar const *query_status = "SELECT * FROM tagente_estado " + "LEFT JOIN tagente " + "ON tagente_estado.id_agente = tagente.id_agente " + "WHERE estado != 100 and datos = 0.0"; + connection = checker->priv->connection; + g_return_val_if_fail (connection != NULL, FALSE); + + if (mysql_query (connection, query_time) != 0) { + return STATE_UNKNOWN; + } + + result = mysql_store_result (connection); + + if (mysql_num_rows (result) > 0) { + return STATE_BAD; + } + + mysql_free_result (result); + + if (mysql_query (connection, query_status) != 0) { + return STATE_UNKNOWN; + } + + result = mysql_store_result (connection); + + if (mysql_num_rows (result) > 0) { + return STATE_BAD; + } + + mysql_free_result (result); + return STATE_OK; +} + +static PandoraState +pandora_status_checker_check_servers (PandoraStatusChecker *checker) +{ + MYSQL *connection = NULL; + MYSQL_RES *result; + MYSQL_ROW row; + const gchar const *query = "SELECT * FROM tserver " + "WHERE status = 0"; + + connection = checker->priv->connection; + g_return_val_if_fail (connection != NULL, FALSE); + + if (mysql_query (connection, query) != 0) { + return STATE_UNKNOWN; + } + + result = mysql_store_result (connection); + + if (mysql_num_rows (result) > 0) + return STATE_BAD; + + mysql_free_result (result); + return STATE_OK; +} + +static PandoraState +pandora_status_checker_check_alerts (PandoraStatusChecker *checker) +{ + MYSQL *connection = NULL; + MYSQL_RES *result1 = NULL, *result2 = NULL, *result3 = NULL; + MYSQL_ROW row; + const gchar const *query_all_agents = "SELECT * FROM tagente " + "WHERE disabled = 0"; + const gchar const *query_agent_state = "SELECT * FROM tagente_estado " + "WHERE id_agente = %s"; + const gchar const *query_agent_alert = "SELECT * FROM talerta_agente_modulo " + "WHERE id_agente_modulo = %s " + "AND times_fired > 0"; + gchar *query; + + connection = checker->priv->connection; + g_return_val_if_fail (connection != NULL, FALSE); + + if (mysql_query (connection, query_all_agents) != 0) { + return STATE_UNKNOWN; + } + + result1 = mysql_store_result (connection); + if (result1 == NULL) + return STATE_UNKNOWN; + + if (mysql_num_rows (result1) == 0) + return STATE_UNKNOWN; + + while (row = mysql_fetch_row (result1)) { + query = g_strdup_printf (query_agent_state, row[0]); + + if (mysql_query (connection, query) == 0) { + result2 = mysql_store_result (connection); + + if (mysql_num_rows (result2) > 0) { + + while (row = mysql_fetch_row (result2)) { + + g_free (query); + query = g_strdup_printf (query_agent_alert, + row[1]); + + if (mysql_query (connection, query) == 0) { + result3 = mysql_store_result (connection); + + if (mysql_num_rows (result3) > 0) { + mysql_free_result (result1); + mysql_free_result (result2); + mysql_free_result (result3); + + g_free (query); + + return STATE_BAD; + } + + mysql_free_result (result3); + } + } + + mysql_free_result (result2); + } + } + + g_free (query); + } + + if (mysql_num_rows (result1) > 0) + mysql_free_result (result1); + + return STATE_OK; +} + +static gpointer +pandora_status_checker_run_thread (gpointer data) +{ + PandoraStatusChecker *checker = PANDORA_STATUS_CHECKER (data); + PandoraState alerts, servers, agents; + + g_mutex_lock (checker->priv->state_mutex); + checker->priv->state = CHECKER_STATE_RUNNING; + + while (checker->priv->state == CHECKER_STATE_RUNNING) { + g_mutex_unlock (checker->priv->state_mutex); + + if (!pandora_status_checker_connect (checker)) { + pandora_status_checker_stop (checker); + return NULL; + } + + alerts = pandora_status_checker_check_alerts (checker); + servers = pandora_status_checker_check_servers (checker); + agents = pandora_status_checker_check_agents (checker); + + pandora_status_set_alerts (checker->priv->status, alerts); + pandora_status_set_servers (checker->priv->status, servers); + pandora_status_set_agents (checker->priv->status, agents); + + pandora_status_checker_disconnect (checker); + + g_usleep (G_USEC_PER_SEC * 10); + + g_mutex_lock (checker->priv->state_mutex); + } + + g_mutex_unlock (checker->priv->state_mutex); + + return NULL; +} + +void +pandora_status_checker_run (PandoraStatusChecker *checker) +{ + checker->priv->thread = g_thread_create (pandora_status_checker_run_thread, + (gpointer) checker, TRUE, NULL); +} + +void +pandora_status_checker_stop (PandoraStatusChecker *checker) +{ + g_mutex_lock (checker->priv->state_mutex); + checker->priv->state = CHECKER_STATE_RUNNING; + g_mutex_unlock (checker->priv->state_mutex); +} diff --git a/pandora_applet/src/pandora-status-checker.h b/pandora_applet/src/pandora-status-checker.h new file mode 100644 index 0000000000..d715524f74 --- /dev/null +++ b/pandora_applet/src/pandora-status-checker.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 STATUS_CHECKER_H +#define STATUS_CHECKER_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "pandora-setup.h" +#include "pandora-status.h" + +enum { + CHECKER_STATE_READY, + CHECKER_STATE_RUNNING, + CHECKER_STATE_FINISHED, + CHECKER_STATE_STOPPING, + CHECKER_STATE_FAILED +}; + +#define PANDORA_STATUS_CHECKER_TYPE (pandora_status_checker_get_type()) +#define PANDORA_STATUS_CHECKER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), PANDORA_STATUS_CHECKER_TYPE, PandoraStatusChecker)) +#define PANDORA_STATUS_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANDORA_STATUS_CHECKER_TYPE, PandoraStatusCheckerClass)) +#define PANDORA_IS_STATUS_CHECKER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), PANDORA_STATUS_CHECKER_TYPE)) +#define PANDORA_IS_STATUS_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANDORA_STATUS_CHECKER_TYPE)) +#define PANDORA_STATUS_CHECKER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANDORA_STATUS_CHECKER_TYPE, PandoraStatusCheckerClass)) + +typedef struct _PandoraStatusCheckerPrivate PandoraStatusCheckerPrivate; + +typedef struct { + GObjectClass parent_class; +} PandoraStatusCheckerClass; + +typedef struct { + GObject parent; + + PandoraStatusCheckerPrivate *priv; +} PandoraStatusChecker; + +PandoraStatusChecker *pandora_status_checker_new (PandoraSetup *setup, + PandoraStatus *status); + +void pandora_status_checker_run (PandoraStatusChecker *checker); +void pandora_status_checker_stop (PandoraStatusChecker *checker); + +#endif diff --git a/pandora_applet/src/pandora-status.c b/pandora_applet/src/pandora-status.c new file mode 100644 index 0000000000..d34b92327b --- /dev/null +++ b/pandora_applet/src/pandora-status.c @@ -0,0 +1,218 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 +#endif + +#include +#include + +#include "pandora-status.h" + +enum { + CHANGED, + N_SIGNALS +}; + +struct _PandoraStatusPrivate { + PandoraState alerts; + PandoraState agents; + PandoraState servers; + + GMutex *mutex; +}; + +static guint pandora_status_signals[N_SIGNALS]; + +#define PANDORA_STATUS_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), PANDORA_STATUS_TYPE, \ + PandoraStatusPrivate)) + +static void pandora_status_init (PandoraStatus *status); +static void pandora_status_class_init (PandoraStatusClass *klass); +static void pandora_status_finalize (GObject *object); + +GType +pandora_status_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (PandoraStatusClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pandora_status_class_init, + NULL, + NULL, + sizeof (PandoraStatus), + 0, + (GInstanceInitFunc) pandora_status_init + }; + + type = g_type_register_static (G_TYPE_OBJECT, "PandoraStatus", + &info, 0); + } + + return type; +} + +static void +pandora_status_init (PandoraStatus *status) +{ + status->priv = PANDORA_STATUS_GET_PRIVATE (status); + status->priv->alerts = FALSE; + status->priv->agents = FALSE; + status->priv->servers = FALSE; + + status->priv->mutex = g_mutex_new (); +} + + +static void +pandora_status_class_init (PandoraStatusClass *klass) +{ + GObjectClass *object_class; + + g_type_class_add_private (klass, sizeof (PandoraStatusPrivate)); + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = pandora_status_finalize; + + pandora_status_signals[CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (PandoraStatusClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +pandora_status_finalize (GObject *object) +{ + PandoraStatus *status; + + status = PANDORA_STATUS (object); + + if (status->priv->mutex) { + g_mutex_free (status->priv->mutex); + status->priv->mutex = NULL; + } +} + +PandoraStatus * +pandora_status_new (void) +{ + PandoraStatus *status; + + status = PANDORA_STATUS (g_object_new (PANDORA_STATUS_TYPE, + NULL)); + + return status; +} + +void +pandora_status_set_alerts (PandoraStatus *status, PandoraState value) +{ + g_return_if_fail (PANDORA_IS_STATUS (status)); + + g_mutex_lock (status->priv->mutex); + + if (status->priv->alerts != value) { + status->priv->alerts = value; + g_mutex_unlock (status->priv->mutex); + + g_signal_emit (status, pandora_status_signals[CHANGED], 0); + } else { + g_mutex_unlock (status->priv->mutex); + } +} + +void +pandora_status_set_agents (PandoraStatus *status, PandoraState value) +{ + g_return_if_fail (PANDORA_IS_STATUS (status)); + + g_mutex_lock (status->priv->mutex); + + if (status->priv->agents != value) { + status->priv->agents = value; + g_mutex_unlock (status->priv->mutex); + + g_signal_emit (status, pandora_status_signals[CHANGED], 0); + } else { + g_mutex_unlock (status->priv->mutex); + } +} + +void +pandora_status_set_servers (PandoraStatus *status, PandoraState value) +{ + g_return_if_fail (PANDORA_IS_STATUS (status)); + + g_mutex_lock (status->priv->mutex); + + if (status->priv->servers != value) { + status->priv->servers = value; + g_mutex_unlock (status->priv->mutex); + + g_signal_emit (status, pandora_status_signals[CHANGED], 0); + } else { + g_mutex_unlock (status->priv->mutex); + } +} + +PandoraState +pandora_status_get_alerts (PandoraStatus *status) +{ + PandoraState value; + + g_mutex_lock (status->priv->mutex); + value = status->priv->alerts; + g_mutex_unlock (status->priv->mutex); + + return value; +} + +PandoraState +pandora_status_get_agents (PandoraStatus *status) +{ + PandoraState value; + + g_mutex_lock (status->priv->mutex); + value = status->priv->agents; + g_mutex_unlock (status->priv->mutex); + + return value; +} + +PandoraState +pandora_status_get_servers (PandoraStatus *status) +{ + PandoraState value; + + g_mutex_lock (status->priv->mutex); + value = status->priv->servers; + g_mutex_unlock (status->priv->mutex); + + return value; +} diff --git a/pandora_applet/src/pandora-status.h b/pandora_applet/src/pandora-status.h new file mode 100644 index 0000000000..540f1ae447 --- /dev/null +++ b/pandora_applet/src/pandora-status.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2006 Artica ST. + Written by Esteban Sanchez. + + 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, 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 STATUS_H +#define STATUS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +typedef enum { + STATE_INVALID, + STATE_UNKNOWN, + STATE_OK, + STATE_BAD +} PandoraState; + +#define PANDORA_STATUS_TYPE (pandora_status_get_type()) +#define PANDORA_STATUS(object) (G_TYPE_CHECK_INSTANCE_CAST((object), PANDORA_STATUS_TYPE, PandoraStatus)) +#define PANDORA_STATUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PANDORA_STATUS_TYPE, PandoraStatusClass)) +#define PANDORA_IS_STATUS(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), PANDORA_STATUS_TYPE)) +#define PANDORA_IS_STATUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PANDORA_STATUS_TYPE)) +#define PANDORA_STATUS_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), PANDORA_STATUS_TYPE, PandoraStatusClass)) + +typedef struct _PandoraStatusPrivate PandoraStatusPrivate; + +typedef struct { + GObject parent; + + PandoraStatusPrivate *priv; +} PandoraStatus; + +typedef struct { + GObjectClass parent_class; + + void (* changed) (PandoraStatus *view); +} PandoraStatusClass; + +PandoraStatus *pandora_status_new (void); +void pandora_status_set_alerts (PandoraStatus *status, PandoraState value); +void pandora_status_set_agents (PandoraStatus *status, PandoraState value); +void pandora_status_set_servers (PandoraStatus *status, PandoraState value); + +PandoraState pandora_status_get_alerts (PandoraStatus *status); +PandoraState pandora_status_get_agents (PandoraStatus *status); +PandoraState pandora_status_get_servers (PandoraStatus *status); + + +#endif