diff --git a/lib/resources/ui/sp-process-model-row.ui b/lib/resources/ui/sp-process-model-row.ui index 8f65dd8a..48a4c936 100644 --- a/lib/resources/ui/sp-process-model-row.ui +++ b/lib/resources/ui/sp-process-model-row.ui @@ -18,6 +18,17 @@ 0.0 + + + false + true + end + 0.0 + + + false diff --git a/lib/sp-process-model-item.c b/lib/sp-process-model-item.c index 7067dc61..73fe3c49 100644 --- a/lib/sp-process-model-item.c +++ b/lib/sp-process-model-item.c @@ -16,15 +16,18 @@ * along with this program. If not, see . */ +#include + #include "sp-process-model-item.h" #include "sp-proc-source.h" struct _SpProcessModelItem { - GObject parent_instance; - GPid pid; - gchar *command_line; - guint is_kernel : 1; + GObject parent_instance; + GPid pid; + gchar *command_line; /* Short version (first field) */ + gchar **argv; /* Long version (argv as a strv) */ + guint is_kernel : 1; }; G_DEFINE_TYPE (SpProcessModelItem, sp_process_model_item, G_TYPE_OBJECT) @@ -44,6 +47,7 @@ sp_process_model_item_finalize (GObject *object) SpProcessModelItem *self = (SpProcessModelItem *)object; g_clear_pointer (&self->command_line, g_free); + g_clear_pointer (&self->argv, g_strfreev); G_OBJECT_CLASS (sp_process_model_item_parent_class)->finalize (object); } @@ -189,3 +193,42 @@ sp_process_model_item_is_kernel (SpProcessModelItem *self) return self->is_kernel; } + +const gchar const * const * +sp_process_model_item_get_argv (SpProcessModelItem *self) +{ + g_autofree gchar *contents = NULL; + g_autofree gchar *path = NULL; + const gchar *pos; + const gchar *endptr; + GPtrArray *ar; + gsize size = 0; + GPid pid; + + g_return_val_if_fail (SP_IS_PROCESS_MODEL_ITEM (self), NULL); + + if (self->argv) + return (const gchar * const *)self->argv; + + if ((pid = sp_process_model_item_get_pid (self)) < 0) + return NULL; + + path = g_strdup_printf ("/proc/%u/cmdline", (guint)pid); + if (!g_file_get_contents (path, &contents, &size, NULL)) + return NULL; + + ar = g_ptr_array_new (); + + /* Each parameter is followed by \0 */ + for (pos = contents, endptr = contents + size; + pos < endptr; + pos += strlen (pos) + 1) + g_ptr_array_add (ar, g_strdup (pos)); + g_ptr_array_add (ar, NULL); + + g_clear_pointer (&self->argv, g_strfreev); + self->argv = (gchar **)g_ptr_array_free (ar, FALSE); + + return (const gchar * const *)self->argv; +} + diff --git a/lib/sp-process-model-item.h b/lib/sp-process-model-item.h index 850a741a..3db0dfaf 100644 --- a/lib/sp-process-model-item.h +++ b/lib/sp-process-model-item.h @@ -27,13 +27,14 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (SpProcessModelItem, sp_process_model_item, SP, PROCESS_MODEL_ITEM, GObject) -SpProcessModelItem *sp_process_model_item_new (GPid pid); -guint sp_process_model_item_hash (SpProcessModelItem *self); -gboolean sp_process_model_item_equal (SpProcessModelItem *self, - SpProcessModelItem *other); -GPid sp_process_model_item_get_pid (SpProcessModelItem *self); -const gchar *sp_process_model_item_get_command_line (SpProcessModelItem *self); -gboolean sp_process_model_item_is_kernel (SpProcessModelItem *self); +SpProcessModelItem *sp_process_model_item_new (GPid pid); +guint sp_process_model_item_hash (SpProcessModelItem *self); +gboolean sp_process_model_item_equal (SpProcessModelItem *self, + SpProcessModelItem *other); +GPid sp_process_model_item_get_pid (SpProcessModelItem *self); +const gchar *sp_process_model_item_get_command_line (SpProcessModelItem *self); +gboolean sp_process_model_item_is_kernel (SpProcessModelItem *self); +const gchar * const *sp_process_model_item_get_argv (SpProcessModelItem *self); G_END_DECLS diff --git a/lib/sp-process-model-row.c b/lib/sp-process-model-row.c index b8e6e77b..a5b005f3 100644 --- a/lib/sp-process-model-row.c +++ b/lib/sp-process-model-row.c @@ -22,6 +22,7 @@ typedef struct { SpProcessModelItem *item; + GtkLabel *args_label; GtkLabel *label; GtkLabel *pid; GtkImage *image; @@ -71,12 +72,20 @@ sp_process_model_row_set_item (SpProcessModelRow *self, const gchar *command_line; g_auto(GStrv) parts = NULL; g_autofree gchar *pidstr = NULL; + const gchar * const *argv; GPid pid; command_line = sp_process_model_item_get_command_line (item); parts = g_strsplit (command_line ?: "", "\n", 0); gtk_label_set_label (priv->label, parts [0]); + if ((NULL != (argv = sp_process_model_item_get_argv (item))) && (argv[0] != NULL)) + { + g_autofree gchar *argvstr = g_strjoinv (" ", (gchar **)&argv[1]); + + gtk_label_set_label (priv->args_label, argvstr); + } + pid = sp_process_model_item_get_pid (item); pidstr = g_strdup_printf ("%u", pid); gtk_label_set_label (priv->pid, pidstr); @@ -111,6 +120,34 @@ sp_process_model_row_set_selected (SpProcessModelRow *self, } } +static gboolean +sp_process_model_row_query_tooltip (GtkWidget *widget, + gint x, + gint y, + gboolean keyboard_mode, + GtkTooltip *tooltip) +{ + SpProcessModelRow *self = (SpProcessModelRow *)widget; + SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self); + + g_assert (SP_IS_PROCESS_MODEL_ROW (self)); + g_assert (GTK_IS_TOOLTIP (tooltip)); + + if (priv->item != NULL) + { + const gchar * const *argv = sp_process_model_item_get_argv (priv->item); + + if (argv != NULL) + { + g_autofree gchar *str = g_strjoinv (" ", (gchar **)argv); + gtk_tooltip_set_text (tooltip, str); + return TRUE; + } + } + + return FALSE; +} + static void sp_process_model_row_finalize (GObject *object) { @@ -178,6 +215,8 @@ sp_process_model_row_class_init (SpProcessModelRowClass *klass) object_class->get_property = sp_process_model_row_get_property; object_class->set_property = sp_process_model_row_set_property; + widget_class->query_tooltip = sp_process_model_row_query_tooltip; + properties [PROP_ITEM] = g_param_spec_object ("item", "Item", @@ -196,6 +235,7 @@ sp_process_model_row_class_init (SpProcessModelRowClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sp-process-model-row.ui"); + gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, args_label); gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, image); gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, label); gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, pid); @@ -206,4 +246,6 @@ static void sp_process_model_row_init (SpProcessModelRow *self) { gtk_widget_init_template (GTK_WIDGET (self)); + + gtk_widget_set_has_tooltip (GTK_WIDGET (self), TRUE); }