2
* Copyright (C) 2004 Lukas Lipka <lukas@pmad.net>
3
* (C) 2004 Michael Vogt <mvo@debian.org>
5
* (C) 2004 Michiel Sikkes <michiel@eyesopened.nl>
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
27
#define DBUS_API_SUBJECT_TO_CHANGE 1
28
#include <dbus/dbus.h>
29
#include <dbus/dbus-glib.h>
30
//#define DBUS_HELPER PACKAGE_LIB_DIR"/upgrade-notifier/dbus-helper"
36
#include <glade/glade.h>
39
#include "upgrade-notifier.h"
40
#include "eggtrayicon.h"
43
#define ICON_FILE PACKAGE_DATA_DIR"/pixmaps/upgrade-notifier.png"
44
#define UPGRADE_CHECKER PACKAGE_LIB_DIR"/upgrade-notifier/apt-check"
47
char* actions[][2] = {
48
{ "/usr/bin/update-manager", N_("Show updates") },
49
{ "/usr/sbin/synaptic --upgrade-mode --non-interactive --hide-main-window", N_("Install all updates") },
50
{ "/usr/sbin/synaptic", N_("Package Manager") },
51
{ "/usr/sbin/synaptic --update-at-startup --non-interactive --hide-main-window", N_("Update package list now") },
55
#define GCONF_KEY_DEFAULT_ACTION "/apps/upgrade-notifer/default_action"
56
#define TIMEOUT_FAM 1000*60*5 /* 5 minutes */
58
static LibHalContext *hal_ctx;
61
invoke_with_gksu(gchar *cmd, gchar *descr)
63
gchar *full_descr = NULL;
65
full_descr = g_strdup_printf(_("Please enter your password to run:\n %s"), descr);
67
//g_print("invoke_update_manager ()\n");
69
argv[0] = "/usr/bin/gksudo";
70
argv[1] = "--message";
76
g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL);
81
button_release_cb (GtkWidget *widget,
82
GdkEventButton *event,
86
if (event->button == 1 && event->type == GDK_BUTTON_RELEASE) {
87
index = gconf_client_get_int(un->gconf, GCONF_KEY_DEFAULT_ACTION, NULL);
88
//g_print("%s %s\n",actions[index][0],actions[index][1]);
89
invoke_with_gksu (actions[index][0], actions[index][1]);
95
button_press_cb (GtkWidget *widget,
96
GdkEventButton *event,
99
if (event->button == 3) {
100
gtk_menu_popup (GTK_MENU (un->menu), NULL, NULL, NULL, NULL,
101
event->button, event->time);
107
trayicon_update_tooltip (UpgradeNotifier *un)
109
//g_print("update_tooltip: %x \n", un);
113
updates = g_strdup_printf(_("There are %i updates available!"),
116
explanation = g_strdup(_("Press this icon to show the updates."));
118
gtk_tooltips_set_tip(GTK_TOOLTIPS(un->tooltip),
119
GTK_WIDGET (un->eventbox),
120
updates, explanation);
123
g_free (explanation);
128
cb_action(GObject *self, void *user_data)
130
UpgradeNotifier *un = user_data;
132
int i = g_object_get_data(G_OBJECT(self), "action");
133
invoke_with_gksu (actions[i][0], actions[i][1]);
136
void cb_preferences(GObject *self, void *user_data)
139
//g_print("Trying to open: %s\n",GLADEDIR"/preferences.glade");
140
UpgradeNotifier *un = user_data;
142
GladeXML *xml = glade_xml_new(GLADEDIR"/preferences.glade",
143
"preferences", NULL);
144
GtkWidget *prefs = glade_xml_get_widget(xml, "preferences");
145
GtkWidget *combo = glade_xml_get_widget(xml, "combobox_default");
147
for(i=0;actions[i][0]!=NULL;i++) {
148
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _(actions[i][1]));
150
int default_action = gconf_client_get_int(un->gconf,
151
GCONF_KEY_DEFAULT_ACTION, NULL);
152
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), default_action);
154
int res = gtk_dialog_run(GTK_DIALOG(prefs));
155
if(res == GTK_RESPONSE_CLOSE) {
156
int index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
157
gconf_client_set_int(un->gconf, GCONF_KEY_DEFAULT_ACTION, index, NULL);
159
gtk_widget_destroy(prefs);
163
trayicon_create_menu (UpgradeNotifier *un)
166
GtkAccelGroup *accelgroup;
169
un->menu = gtk_menu_new ();
171
for(i=0;actions[i][0]!=NULL;i++) {
172
menuitem = gtk_menu_item_new_with_label (_(actions[i][1]));
173
gtk_menu_shell_append (GTK_MENU_SHELL (un->menu), menuitem);
174
g_object_set_data(G_OBJECT(menuitem), "action", i);
175
g_signal_connect(G_OBJECT(menuitem), "activate", cb_action, un);
178
menuitem = gtk_separator_menu_item_new();
179
gtk_menu_shell_append (GTK_MENU_SHELL (un->menu), menuitem);
181
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PREFERENCES, accelgroup);
182
gtk_menu_shell_append (GTK_MENU_SHELL (un->menu), menuitem);
183
g_signal_connect(G_OBJECT(menuitem), "activate", cb_preferences, un);
185
gtk_widget_show_all (un->menu);
189
trayicon_load (UpgradeNotifier *un)
193
pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (un->icon));
196
g_object_unref (G_OBJECT (pixbuf));
198
pixbuf = gdk_pixbuf_new_from_file (ICON_FILE, NULL);
200
gtk_image_set_from_pixbuf (GTK_IMAGE (un->icon), pixbuf);
204
trayicon_create (UpgradeNotifier *un)
206
//g_print("trayicon_create()\n");
207
un->tooltip = gtk_tooltips_new ();
208
//g_object_ref(un->tooltip);
209
un->tray_icon = egg_tray_icon_new ("apt upgrade-notifier");
210
un->eventbox = gtk_event_box_new ();
211
un->icon = gtk_image_new ();
212
un->gconf = gconf_client_get_default();
216
gtk_container_add (GTK_CONTAINER (un->eventbox), un->icon);
217
gtk_container_add (GTK_CONTAINER (un->tray_icon), un->eventbox);
219
g_signal_connect (G_OBJECT(un->tray_icon),
220
"button-release-event",
221
G_CALLBACK (button_release_cb),
224
g_signal_connect (G_OBJECT(un->tray_icon),
225
"button-press-event",
226
G_CALLBACK (button_press_cb),
229
gtk_widget_show_all (GTK_WIDGET (un->tray_icon));
231
/* Initial tooltip update */
232
trayicon_update_tooltip (un);
234
/* Menu initialization */
235
trayicon_create_menu (un);
241
the following files change:
245
- /var/lib/upgrade-notifier/dpkg-run-stamp
247
- /var/lib/apt/lists/lock
248
- /var/lib/apt/lists/*
252
fam_check(UpgradeNotifier *un)
255
gboolean need_update_check = FALSE;
256
while(FAMPending(&un->fc)) {
257
if(FAMNextEvent(&un->fc, &fe) < 0) {
258
g_critical("FAMNextEvent() failed");
261
//g_print("FAMPending() %i %s\n",fe.code,fe.filename);
264
if(strstr(fe.filename,"/var/lib/apt/lists") )
265
if(fe.code == FAMChanged || fe.code == FAMDeleted)
266
need_update_check = TRUE;
269
if(strstr(fe.filename,"/var/lib/upgrade-notifier/dpkg-run-stamp"))
270
if(fe.code == FAMChanged)
271
need_update_check = TRUE;
273
if(fe.code == FAMChanged || fe.code == FAMDeleted)
274
need_update_check = TRUE;
277
if(need_update_check)
285
update_check (UpgradeNotifier *un)
287
//g_print("upgrade_check(): %x \n", un);
288
FILE *f = popen(UPGRADE_CHECKER, "r");
291
un->num_upgrades = 0;
293
/* Check the number of upgrades trough the helper script */
294
while (fgets (s, 400, f) != NULL) {
299
if (un->num_upgrades == 0) {
300
/* We don't have any updates. */
301
if (un->is_displayed) {
302
/* We're still displayed, shoot ourselves */
303
gtk_widget_destroy (GTK_WIDGET (un->tray_icon));
304
un->is_displayed = FALSE;
307
/* There are updates */
308
if (un->is_displayed) {
309
/* We're already displayed, update tooltip */
310
trayicon_update_tooltip (un);
312
/* We're not already displayed, display ourselves */
313
if (trayicon_create (un))
314
un->is_displayed = TRUE;
317
//g_print("upgrades: %i\n", un->num_upgrades);
321
static DBusHandlerResult
322
signal_filter(DBusConnection *connection, DBusMessage *message, void *data)
324
#if 0 // DEBUG stuff to better understand about dbus
325
g_print("path: %s\n", dbus_message_get_path(message));
326
g_print("interface: %s\n", dbus_message_get_interface(message));
327
g_print("type: %i\n", dbus_message_get_type(message));
328
g_print("dest: %s\n", dbus_message_get_destination(message));
329
g_print("member: %s\n", dbus_message_get_member(message));
331
//g_print("signal_filter: \n");
333
if(dbus_message_is_signal(message, "app.apt.dbus", "changed")
334
|| dbus_message_is_signal(message, "app.apt.dbus", "updated")) {
336
gboolean finished=FALSE;
337
dbus_error_init(&error);
338
if(dbus_message_get_args(message, &error,
339
DBUS_TYPE_BOOLEAN, &finished,
340
DBUS_TYPE_INVALID)) {
342
//g_print("dbus message triggered update_check\n");
349
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
355
main (int argc, char *argv[])
361
gnome_program_init (PACKAGE, PACKAGE_VERSION,
366
client = gnome_master_client ();
367
if (up_get_clipboard ())
368
gnome_client_set_restart_style (client, GNOME_RESTART_ANYWAY);
370
gnome_client_set_restart_style (client, GNOME_RESTART_NEVER);
371
warn ("already running?\n");
375
/* Make sure we die when the session dies */
376
g_signal_connect (G_OBJECT (client), "die",
377
G_CALLBACK (gtk_main_quit), NULL);
379
/* Create the UpgradeNotifier object */
380
un = g_new0 (UpgradeNotifier, 1);
383
/* setup a dbus channel */
386
loop = g_main_loop_new(NULL, FALSE);
387
dbus_error_init(&error);
388
bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
390
g_error("Failed to connect to D-BUS: %s",error.message);
393
dbus_connection_setup_with_g_main(bus, NULL);
394
dbus_bus_add_match(bus, "type='signal',interface='app.apt.dbus'",
396
dbus_connection_add_filter(bus, signal_filter, un, NULL);
399
/* setup hal so that inserted cdroms can be checked */
400
LibHalFunctions hal_functions = { hal_mainloop_integration,
401
NULL /*hal_device_added*/,
402
NULL /*hal_device_removed*/,
403
NULL /*hal_device_new_capability*/,
404
NULL /*hal_device_lost_capability*/,
405
hal_property_modified,
406
NULL /*hal_device_condition*/};
407
hal_ctx = up_do_hal_init(&hal_functions);
409
g_error("failed to initialize HAL!\n");
412
hal_ctx_set_user_data(hal_ctx, un);
414
/* setup FAM/GAMIN, monitor the importend directories */
416
if(FAMOpen(&un->fc) >= 0) {
417
if(FAMMonitorDirectory(&un->fc, "/var/lib/apt/lists/",
419
g_error("FAMMonitorFile() failed");
421
if(FAMMonitorFile(&un->fc,
422
"/var/lib/upgrade-notifier/dpkg-run-stamp",
424
g_error("FAMMonitorFile() failed");
426
g_critical("FAMOpen() failed");
429
/* Check for updates for the first time */
432
/* Set a time-out for the fam check */
433
g_timeout_add (TIMEOUT_FAM, (GSourceFunc)fam_check, un);
435
/* Start the main gtk loop */