/* Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) Copyright (C) 2009 RedHat inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #if HAVE_CONFIG_H # include #endif #if ENABLE_NLS # include # define _(S) gettext(S) #else # define _(S) (S) #endif #include "abrtlib.h" #include "CCApplet.h" static const gchar menu_xml[] = "\ \ \ \ \ True\ \ \ True\ Hide\ \ \ \ \ gtk-quit\ True\ True\ True\ True\ \ \ \ \ True\ \ \ \ \ gtk-about\ True\ True\ True\ True\ \ \ \ \ 5\ normal\ False\ Automatic Bug Reporting Tool\ Copyright © 2009 Red Hat, Inc\ https://fedorahosted.org/abrt/\ Website\ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\n\ \n\ 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.\n\ \n\ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\ Anton Arapov <aarapov@redhat.com>\n\ Karel Klic <kklic@redhat.com>\n\ Jiri Moskovcak <jmoskovc@redhat.com>\n\ Nikola Pajkovsky <npajkovs@redhat.com>\n\ Zdenek Prikryl <zprikryl@redhat.com>\n\ Denys Vlasenko <dvlasenk@redhat.com>\n\ \n\ Art:\n\ Patrick Connelly <pcon@fedoraproject.org>\ True\ \ \ True\ vertical\ 2\ \ \ \ \ \ True\ end\ \ \ False\ end\ 0\ \ \ \ \ \ "; CApplet::CApplet() { m_bDaemonRunning = true; /* set-up icon buffers */ m_iAnimator = 0; m_iAnimationStage = ICON_DEFAULT; m_bIconsLoaded = load_icons(); /* - animation - */ if (m_bIconsLoaded == true) { m_pStatusIcon = gtk_status_icon_new_from_pixbuf(icon_stages_buff[ICON_DEFAULT]); } else { m_pStatusIcon = gtk_status_icon_new_from_stock(GTK_STOCK_DIALOG_WARNING); } notify_init("ABRT"); m_pNotification = notify_notification_new_with_status_icon("Warning", NULL, NULL, m_pStatusIcon); notify_notification_set_urgency(m_pNotification, NOTIFY_URGENCY_CRITICAL); notify_notification_set_timeout(m_pNotification, 5000); gtk_status_icon_set_visible(m_pStatusIcon, FALSE); g_signal_connect(G_OBJECT(m_pStatusIcon), "activate", GTK_SIGNAL_FUNC(CApplet::OnAppletActivate_CB), this); g_signal_connect(G_OBJECT(m_pStatusIcon), "popup_menu", GTK_SIGNAL_FUNC(CApplet::OnMenuPopup_cb), this); // SetIconTooltip(_("Pending events: %i"), m_mapEvents.size()); m_pBuilder = gtk_builder_new(); if (!gtk_builder_add_from_string(m_pBuilder, menu_xml, sizeof(menu_xml)-1, NULL)) //if (!gtk_builder_add_from_file(m_pBuilder, "popup.GtkBuilder", NULL)) { error_msg("Can't create menu from the description, popup won't be available"); return; } m_pMenu = gtk_builder_get_object(m_pBuilder, "popup_menu"); //gtk_menu_attach_to_widget(GTK_MENU(m_pMenu), GTK_WIDGET(m_pStatusIcon), NULL); m_pmiHide = gtk_builder_get_object(m_pBuilder, "miHide"); if (m_pmiHide != NULL) { g_signal_connect(m_pmiHide, "activate", G_CALLBACK(CApplet::onHide_cb), this); } m_pmiQuit = gtk_builder_get_object(m_pBuilder, "miQuit"); if (m_pmiQuit != NULL) { g_signal_connect(m_pmiQuit, "activate", G_CALLBACK(gtk_main_quit), NULL); } m_pAboutDialog = gtk_builder_get_object(m_pBuilder, "aboutdialog"); m_pmiAbout = gtk_builder_get_object(m_pBuilder, "miAbout"); if (m_pmiAbout != NULL) { g_signal_connect(m_pmiAbout, "activate", G_CALLBACK(CApplet::onAbout_cb), m_pAboutDialog); } } CApplet::~CApplet() { } void CApplet::SetIconTooltip(const char *format, ...) { va_list args; int n; char *buf; va_start(args, format); buf = NULL; n = vasprintf(&buf, format, args); va_end(args); gtk_status_icon_set_tooltip_text(m_pStatusIcon, (n >= 0 && buf) ? buf : ""); free(buf); } void CApplet::CrashNotify(const char *format, ...) { va_list args; va_start(args, format); char *buf = xvasprintf(format, args); va_end(args); notify_notification_update(m_pNotification, _("Warning"), buf, NULL); GError *err = NULL; if (gtk_status_icon_is_embedded(m_pStatusIcon)) notify_notification_show(m_pNotification, &err); if (err != NULL) { error_msg("%s", err->message); g_error_free(err); } } void CApplet::OnAppletActivate_CB(GtkStatusIcon *status_icon, gpointer user_data) { CApplet *applet = (CApplet *)user_data; if (applet->m_bDaemonRunning) { pid_t pid = vfork(); if (pid < 0) perror_msg("vfork"); if (pid == 0) { /* child */ signal(SIGCHLD, SIG_DFL); /* undo SIG_IGN in abrt-applet */ execl(BIN_DIR"/abrt-gui", "abrt-gui", (char*) NULL); /* Did not find abrt-gui in installation directory. Oh well */ /* Trying to find it in PATH */ execlp("abrt-gui", "abrt-gui", (char*) NULL); perror_msg_and_die("Can't exec abrt-gui"); } gtk_status_icon_set_visible(applet->m_pStatusIcon, false); applet->stop_animate_icon(); } } void CApplet::OnMenuPopup_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data) { CApplet *applet = (CApplet *)user_data; /* stop the animation */ applet->stop_animate_icon(); if (applet->m_pMenu != NULL) { gtk_menu_popup(GTK_MENU(((CApplet *)user_data)->m_pMenu), NULL, NULL, gtk_status_icon_position_menu, status_icon, button, activate_time); } } void CApplet::ShowIcon() { gtk_status_icon_set_visible(m_pStatusIcon, true); /* only animate if all icons are loaded, use the "gtk-warning" instead */ if (m_bIconsLoaded) animate_icon(); } void CApplet::onHide_cb(GtkMenuItem *menuitem, gpointer applet) { gtk_status_icon_set_visible(((CApplet*)applet)->m_pStatusIcon, false); } void CApplet::onAbout_cb(GtkMenuItem *menuitem, gpointer dialog) { if (dialog) gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide(GTK_WIDGET(dialog)); } void CApplet::HideIcon() { gtk_status_icon_set_visible(m_pStatusIcon, false); stop_animate_icon(); } void CApplet::Disable(const char *reason) { /* FIXME: once we have our icon */ m_bDaemonRunning = false; GdkPixbuf *gray_scaled; GdkPixbuf *pixbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), GTK_STOCK_DIALOG_WARNING, 24, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); if (pixbuf) { gray_scaled = gdk_pixbuf_copy(pixbuf); gdk_pixbuf_saturate_and_pixelate(pixbuf, gray_scaled, 0.0, NULL); gtk_status_icon_set_from_pixbuf(m_pStatusIcon, gray_scaled); //do we need to free pixbufs nere? } else error_msg("Can't load icon"); SetIconTooltip(reason); ShowIcon(); } void CApplet::Enable(const char *reason) { /* restore the original icon */ m_bDaemonRunning = true; SetIconTooltip(reason); gtk_status_icon_set_from_stock(m_pStatusIcon, GTK_STOCK_DIALOG_WARNING); ShowIcon(); } gboolean CApplet::update_icon(void *user_data) { CApplet* applet = (CApplet*)user_data; if (applet->m_pStatusIcon && applet->m_iAnimationStage < ICON_STAGE_LAST) { gtk_status_icon_set_from_pixbuf(applet->m_pStatusIcon, applet->icon_stages_buff[applet->m_iAnimationStage++]); } else error_msg("icon is null"); if (applet->m_iAnimationStage == ICON_STAGE_LAST) { applet->m_iAnimationStage = 0; } if (--applet->m_iAnimCountdown == 0) { applet->stop_animate_icon(); } return true; } void CApplet::animate_icon() { if (m_iAnimator == 0) { m_iAnimator = g_timeout_add(100, update_icon, this); m_iAnimCountdown = 10 * 3; /* 3 sec */ } } void CApplet::stop_animate_icon() { /* animator should be 0 if icons are not loaded, so this should be safe */ if (m_iAnimator != 0) { g_source_remove(m_iAnimator); gtk_status_icon_set_from_pixbuf(m_pStatusIcon, icon_stages_buff[ICON_DEFAULT]); m_iAnimator = 0; } } bool CApplet::load_icons() { int stage; for (stage = ICON_DEFAULT; stage < ICON_STAGE_LAST; stage++) { char name[sizeof(ICON_DIR"/abrt%02d.png")]; GError *error = NULL; if (snprintf(name, sizeof(ICON_DIR"/abrt%02d.png"), ICON_DIR"/abrt%02d.png", stage) > 0) { icon_stages_buff[stage] = gdk_pixbuf_new_from_file(name, &error); if (error != NULL) { error_msg("Can't load pixbuf from %s, animation is disabled!", name); return false; } } } return true; } //int CApplet::AddEvent(int pUUID, const char *pProgname) //{ // m_mapEvents[pUUID] = "pProgname"; // SetIconTooltip(_("Pending events: %i"), m_mapEvents.size()); // return 0; //} // //int CApplet::RemoveEvent(int pUUID) //{ // m_mapEvents.erase(pUUID); // return 0; //} //void CApplet::BlinkIcon(bool pBlink) //{ // gtk_status_icon_set_blinking(m_pStatusIcon, pBlink); //}