summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2010-03-11 16:27:14 +0100
committerJiri Moskovcak <jmoskovc@redhat.com>2010-03-11 16:27:14 +0100
commitd3fff839380fa1e165b92d3dc79fb7eafaf2a976 (patch)
treeb004421f370a18e9d5079ac779b1123a3c1a184e /src
parentcf9b053459d4931210800b1ce397e1403c06f346 (diff)
downloadabrt-d3fff839380fa1e165b92d3dc79fb7eafaf2a976.tar.gz
abrt-d3fff839380fa1e165b92d3dc79fb7eafaf2a976.tar.xz
abrt-d3fff839380fa1e165b92d3dc79fb7eafaf2a976.zip
GUI: added action to applet to directly report last crash
Revieved by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'src')
-rw-r--r--src/Applet/Applet.cpp20
-rw-r--r--src/Applet/CCApplet.cpp134
-rw-r--r--src/Applet/CCApplet.h11
-rw-r--r--src/Daemon/CommLayerServer.h2
-rw-r--r--src/Daemon/CommLayerServerDBus.cpp10
-rw-r--r--src/Daemon/CommLayerServerDBus.h4
-rw-r--r--src/Daemon/Daemon.cpp12
7 files changed, 168 insertions, 25 deletions
diff --git a/src/Applet/Applet.cpp b/src/Applet/Applet.cpp
index 8972dcb5..ccd6f393 100644
--- a/src/Applet/Applet.cpp
+++ b/src/Applet/Applet.cpp
@@ -47,7 +47,18 @@ static void Crash(DBusMessage* signal)
dbus_message_iter_init(signal, &in_iter);
const char* package_name;
r = load_val(&in_iter, package_name);
- /* Optional 2nd param: uid */
+ /* 2nd param: crash_id */
+ const char* crash_id = NULL;
+ if (r == ABRT_DBUS_MORE_FIELDS)
+ {
+ r = load_val(&in_iter, crash_id);
+ }
+ else
+ {
+ error_msg("dbus signal %s: parameter type mismatch", __func__);
+ return;
+ }
+ /* Optional 3rd param: uid */
const char* uid_str = NULL;
if (r == ABRT_DBUS_MORE_FIELDS)
{
@@ -80,7 +91,7 @@ static void Crash(DBusMessage* signal)
//applet->AddEvent(uid, package_name);
applet->SetIconTooltip(message, package_name);
applet->ShowIcon();
- applet->CrashNotify(message, package_name);
+ applet->CrashNotify(crash_id, message, package_name);
}
static void QuotaExceed(DBusMessage* signal)
@@ -99,7 +110,7 @@ static void QuotaExceed(DBusMessage* signal)
//if (m_pSessionDBus->has_name("com.redhat.abrt.gui"))
// return;
applet->ShowIcon();
- applet->CrashNotify("%s", str);
+ applet->MessageNotify("%s", str);
}
static void NameOwnerChanged(DBusMessage* signal)
@@ -178,6 +189,7 @@ static void die_if_dbus_error(bool error_flag, DBusError* err, const char* msg)
int main(int argc, char** argv)
{
+ const char * app_name = "abrt-gui";
/* I18n */
setlocale(LC_ALL, "");
#if ENABLE_NLS
@@ -237,7 +249,7 @@ int main(int argc, char** argv)
/* Initialize GUI stuff.
* Note: inside CApplet ctor, libnotify hooks session dbus
* to glib main loop */
- applet = new CApplet;
+ applet = new CApplet(app_name);
/* dbus_abrt cannot handle more than one bus, and we don't really need to.
* The only thing we want to do is to announce ourself on session dbus */
DBusConnection* session_conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
diff --git a/src/Applet/CCApplet.cpp b/src/Applet/CCApplet.cpp
index 13a6eb6f..63b23a87 100644
--- a/src/Applet/CCApplet.cpp
+++ b/src/Applet/CCApplet.cpp
@@ -113,7 +113,29 @@ Patrick Connelly &lt;pcon@fedoraproject.org&gt;</property>\
</object>\
</interface>";
-CApplet::CApplet()
+void static on_notify_close(NotifyNotification *notification, gpointer user_data)
+{
+ g_object_unref(notification);
+}
+
+static NotifyNotification *new_warn_notification()
+{
+ NotifyNotification *notification;
+ notification = notify_notification_new(_("Warning"), NULL, NULL, NULL);
+ g_signal_connect(notification, "closed", G_CALLBACK(on_notify_close), NULL);
+
+ GdkPixbuf *pixbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
+ GTK_STOCK_DIALOG_WARNING, 48, GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+
+ if (pixbuf)
+ notify_notification_set_icon_from_pixbuf(notification, pixbuf);
+ notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL);
+ notify_notification_set_timeout(notification, NOTIFY_EXPIRES_DEFAULT);
+
+ return notification;
+}
+
+CApplet::CApplet(const char* app_name)
{
m_bDaemonRunning = true;
/* set-up icon buffers */
@@ -129,10 +151,7 @@ CApplet::CApplet()
{
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);
+ notify_init(app_name);
gtk_status_icon_set_visible(m_pStatusIcon, FALSE);
@@ -171,6 +190,8 @@ CApplet::CApplet()
CApplet::~CApplet()
{
+ if (notify_is_initted())
+ notify_uninit();
}
void CApplet::SetIconTooltip(const char *format, ...)
@@ -188,19 +209,112 @@ void CApplet::SetIconTooltip(const char *format, ...)
free(buf);
}
-void CApplet::CrashNotify(const char *format, ...)
+void CApplet::action_report(NotifyNotification *notification, gchar *action, gpointer user_data)
{
- va_list args;
+ CApplet *applet = (CApplet *)user_data;
+ if (applet->m_bDaemonRunning)
+ {
+ pid_t pid = vfork();
+ if (pid < 0)
+ perror_msg("vfork");
+ if (pid == 0)
+ { /* child */
+ char *buf = xasprintf("--report=%s", applet->m_pLastCrashID);
+ signal(SIGCHLD, SIG_DFL); /* undo SIG_IGN in abrt-applet */
+ execl(BIN_DIR"/abrt-gui", "abrt-gui", buf, (char*) NULL);
+ /* Did not find abrt-gui in installation directory. Oh well */
+ /* Trying to find it in PATH */
+ execlp("abrt-gui", "abrt-gui", buf, (char*) NULL);
+ perror_msg_and_die("Can't exec abrt-gui");
+ }
+ GError *err = NULL;
+ notify_notification_close(notification, &err);
+ if (err != NULL)
+ {
+ error_msg("%s", err->message);
+ g_error_free(err);
+ }
+ gtk_status_icon_set_visible(applet->m_pStatusIcon, false);
+ applet->stop_animate_icon();
+ }
+}
+void CApplet::action_open_gui(NotifyNotification *notification, gchar *action, 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");
+ }
+ GError *err = NULL;
+ notify_notification_close(notification, &err);
+ if (err != NULL)
+ {
+ error_msg("%s", err->message);
+ g_error_free(err);
+ }
+ gtk_status_icon_set_visible(applet->m_pStatusIcon, false);
+ applet->stop_animate_icon();
+ }
+}
+
+void CApplet::CrashNotify(const char* crash_id, const char *format, ...)
+{
+ m_pLastCrashID = crash_id;
+ va_list args;
va_start(args, format);
char *buf = xvasprintf(format, args);
va_end(args);
- notify_notification_update(m_pNotification, _("Warning"), buf, NULL);
+ NotifyNotification *notification = new_warn_notification();
+ notify_notification_add_action(notification, "REPORT", _("Report"),
+ NOTIFY_ACTION_CALLBACK(CApplet::action_report),
+ this, NULL);
+ notify_notification_add_action(notification, "OPEN_MAIN_WINDOW", "Open ABRT",
+ NOTIFY_ACTION_CALLBACK(CApplet::action_open_gui),
+ this, NULL);
+ notify_notification_update(notification, _("Warning"), buf, NULL);
+ free(buf);
+ GError *err = NULL;
+ notify_notification_show(notification, &err);
+ if (err != NULL)
+ {
+ error_msg("%s", err->message);
+ g_error_free(err);
+ }
+}
+
+void CApplet::MessageNotify(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ char *buf = xvasprintf(format, args);
+ va_end(args);
+
+ /* we don't want to show any buttons now,
+ maybe later we can add action binded to message
+ like >>Clear old dumps<< for quota exceeded
+ */
+ NotifyNotification *notification = new_warn_notification();
+ notify_notification_add_action(notification, "OPEN_MAIN_WINDOW", "Open ABRT",
+ NOTIFY_ACTION_CALLBACK(CApplet::action_open_gui),
+ this, NULL);
+ notify_notification_update(notification, _("Warning"), buf, NULL);
+ free(buf);
GError *err = NULL;
- if (gtk_status_icon_is_embedded(m_pStatusIcon))
- notify_notification_show(m_pNotification, &err);
+ notify_notification_show(notification, &err);
if (err != NULL)
{
error_msg("%s", err->message);
diff --git a/src/Applet/CCApplet.h b/src/Applet/CCApplet.h
index a14498e8..ca92f082 100644
--- a/src/Applet/CCApplet.h
+++ b/src/Applet/CCApplet.h
@@ -35,13 +35,13 @@ class CApplet
GObject *m_pmiAbout;
GObject *m_pAboutDialog;
- NotifyNotification *m_pNotification;
// std::map<int, std::string> m_mapEvents;
bool m_bDaemonRunning;
int m_iAnimationStage;
guint m_iAnimator;
unsigned m_iAnimCountdown;
bool m_bIconsLoaded;
+ const char *m_pLastCrashID;
enum ICON_STAGES
{
@@ -57,14 +57,15 @@ class CApplet
GdkPixbuf *icon_stages_buff[ICON_STAGE_LAST];
public:
- CApplet();
+ CApplet(const char* app_name);
~CApplet();
void ShowIcon();
void HideIcon();
//void DisableIcon();
// void BlinkIcon(bool pBlink);
void SetIconTooltip(const char *format, ...);
- void CrashNotify(const char *format, ...);
+ void CrashNotify(const char* crash_id, const char *format, ...);
+ void MessageNotify(const char *format, ...);
void Disable(const char *reason);
void Enable(const char *reason);
// create some event storage, to let user choose
@@ -77,6 +78,10 @@ class CApplet
protected:
//@@TODO applet menus
static void OnAppletActivate_CB(GtkStatusIcon *status_icon, gpointer user_data);
+ //this action should open the reporter dialog directly, without showing the main window
+ static void action_report(NotifyNotification *notification, gchar *action, gpointer user_data);
+ //this action should open the main window
+ static void action_open_gui(NotifyNotification *notification, gchar *action, gpointer user_data);
static void OnMenuPopup_cb(GtkStatusIcon *status_icon,
guint button,
guint activate_time,
diff --git a/src/Daemon/CommLayerServer.h b/src/Daemon/CommLayerServer.h
index 2daaf93a..9e095c39 100644
--- a/src/Daemon/CommLayerServer.h
+++ b/src/Daemon/CommLayerServer.h
@@ -30,7 +30,7 @@ class CCommLayerServer {
virtual ~CCommLayerServer();
/* just stubs to be called when not implemented in specific comm layer */
- virtual void Crash(const char *package_name, const char *uid_str) {}
+ virtual void Crash(const char *package_name, const char* crash_id, const char *uid_str) {}
virtual void JobDone(const char* peer) = 0;
virtual void QuotaExceed(const char* str) {}
diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp
index 517a9e2a..103f8675 100644
--- a/src/Daemon/CommLayerServerDBus.cpp
+++ b/src/Daemon/CommLayerServerDBus.cpp
@@ -64,23 +64,27 @@ static void send_flush_and_unref(DBusMessage* msg)
}
/* Notify the clients (UI) about a new crash */
-void CCommLayerServerDBus::Crash(const char *package_name, const char *uid_str)
+void CCommLayerServerDBus::Crash(const char *package_name,
+ const char* crash_id,
+ const char *uid_str)
{
DBusMessage* msg = new_signal_msg("Crash");
if (uid_str)
{
dbus_message_append_args(msg,
DBUS_TYPE_STRING, &package_name,
+ DBUS_TYPE_STRING, &crash_id,
DBUS_TYPE_STRING, &uid_str,
DBUS_TYPE_INVALID);
- VERB2 log("Sending signal Crash('%s','%s')", package_name, uid_str);
+ VERB2 log("Sending signal Crash('%s','%s','%s')", package_name, crash_id, uid_str);
}
else
{
dbus_message_append_args(msg,
DBUS_TYPE_STRING, &package_name,
+ DBUS_TYPE_STRING, &crash_id,
DBUS_TYPE_INVALID);
- VERB2 log("Sending signal Crash('%s')", package_name);
+ VERB2 log("Sending signal Crash('%s','%s')", package_name, crash_id);
}
send_flush_and_unref(msg);
}
diff --git a/src/Daemon/CommLayerServerDBus.h b/src/Daemon/CommLayerServerDBus.h
index c62d9a9f..7ccad083 100644
--- a/src/Daemon/CommLayerServerDBus.h
+++ b/src/Daemon/CommLayerServerDBus.h
@@ -29,7 +29,9 @@ class CCommLayerServerDBus
virtual ~CCommLayerServerDBus();
/* DBus signal senders */
- virtual void Crash(const char *package_name, const char *uid_str);
+ virtual void Crash(const char *package_name,
+ const char *crash_id,
+ const char *uid_str);
virtual void JobDone(const char* peer);
virtual void QuotaExceed(const char* str);
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp
index 46bd9502..66f1d6e9 100644
--- a/src/Daemon/Daemon.cpp
+++ b/src/Daemon/Daemon.cpp
@@ -75,7 +75,7 @@ using namespace std;
* - SetSettings(map_abrt_settings_t): returns void
*
* DBus signals we emit:
- * - Crash(progname,uid) - a new crash occurred (new /var/cache/abrt/DIR is found)
+ * - Crash(progname, crash_id, uid) - a new crash occurred (new /var/cache/abrt/DIR is found)
* - JobDone(client_dbus_ID) - see StartJob above.
* Sent as unicast to the client which did StartJob.
* - Warning(msg)
@@ -542,11 +542,17 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
}
}
}
-
/* Send dbus signal */
if (analyzer_has_InformAllUsers(analyzer))
uid_str = NULL;
- g_pCommLayer->Crash(get_crash_data_item_content(crashinfo, FILENAME_PACKAGE).c_str(), uid_str);
+ char *crash_id = xasprintf("%s:%s",
+ get_crash_data_item_content(crashinfo, CD_UID).c_str(),
+ get_crash_data_item_content(crashinfo, CD_UUID).c_str()
+ );
+ g_pCommLayer->Crash(get_crash_data_item_content(crashinfo, FILENAME_PACKAGE).c_str(),
+ crash_id,
+ uid_str);
+ free(crash_id);
break;
#undef fullname
}