diff --git a/src/sysprof/sysprof-greeter.c b/src/sysprof/sysprof-greeter.c index 5f44cb60..dc48c2d1 100644 --- a/src/sysprof/sysprof-greeter.c +++ b/src/sysprof/sysprof-greeter.c @@ -42,12 +42,14 @@ struct _SysprofGreeter AdwWindow parent_instance; GtkStringList *envvars; + GtkStringList *debugdirs; SysprofRecordingTemplate *recording_template; AdwViewStack *view_stack; GtkListBox *sidebar_list_box; AdwPreferencesPage *record_page; GtkListBox *app_environment; + GtkListBox *debug_directories; GtkSwitch *sample_native_stacks; GtkSwitch *sample_javascript_stacks; GtkSwitch *record_disk_usage; @@ -109,6 +111,20 @@ on_env_items_changed_cb (SysprofGreeter *self, g_list_model_get_n_items (model) > 0); } +static void +on_debug_dir_items_changed_cb (SysprofGreeter *self, + guint position, + guint removed, + guint added, + GListModel *model) +{ + g_assert (SYSPROF_IS_GREETER (self)); + g_assert (G_IS_LIST_MODEL (model)); + + gtk_widget_set_visible (GTK_WIDGET (self->debug_directories), + g_list_model_get_n_items (model) > 0); +} + static void on_env_entry_changed_cb (SysprofGreeter *self, SysprofEntryPopover *popover) @@ -155,6 +171,26 @@ failure: sysprof_entry_popover_set_message (popover, errstr); } +static void +on_debug_dir_entry_changed_cb (SysprofGreeter *self, + SysprofEntryPopover *popover) +{ + const char *errstr = NULL; + gboolean valid = FALSE; + const char *text; + + g_assert (SYSPROF_IS_GREETER (self)); + g_assert (SYSPROF_IS_ENTRY_POPOVER (popover)); + + text = sysprof_entry_popover_get_text (popover); + + if (!(valid = g_file_test (text, G_FILE_TEST_IS_DIR))) + errstr = _("Directory does not exist"); + + sysprof_entry_popover_set_ready (popover, valid); + sysprof_entry_popover_set_message (popover, errstr); +} + static void on_env_entry_activate_cb (SysprofGreeter *self, const char *text, @@ -168,6 +204,19 @@ on_env_entry_activate_cb (SysprofGreeter *self, sysprof_entry_popover_set_text (popover, ""); } +static void +on_debug_dir_entry_activate_cb (SysprofGreeter *self, + const char *text, + SysprofEntryPopover *popover) +{ + g_assert (SYSPROF_IS_GREETER (self)); + g_assert (SYSPROF_IS_ENTRY_POPOVER (popover)); + g_assert (GTK_IS_STRING_LIST (self->debugdirs)); + + gtk_string_list_append (self->debugdirs, text); + sysprof_entry_popover_set_text (popover, ""); +} + static void sysprof_greeter_record_cb (GObject *object, GAsyncResult *result, @@ -205,6 +254,9 @@ sysprof_greeter_create_profiler (SysprofGreeter *self, g_autoptr(GFile) dir = NULL; GtkStringObject *strobj; const char *str; + guint n_items; + g_autoptr(GStrvBuilder) builder = NULL; + g_auto(GStrv) debugdirs = NULL; g_assert (SYSPROF_IS_GREETER (self)); @@ -232,6 +284,23 @@ sysprof_greeter_create_profiler (SysprofGreeter *self, "power-profile", str, NULL); + if ((n_items = g_list_model_get_n_items (G_LIST_MODEL (self->debugdirs)))) + { + builder = g_strv_builder_new (); + + for (guint i = 0; i < n_items; i++) + { + strobj = g_list_model_get_item (G_LIST_MODEL (self->debugdirs), i); + g_strv_builder_add (builder, gtk_string_object_get_string (strobj)); + } + + debugdirs = g_strv_builder_end (builder); + + g_object_set (self->recording_template, + "debugdirs", debugdirs, + NULL); + } + if (!(profiler = sysprof_recording_template_apply (self->recording_template, error))) return NULL; @@ -453,6 +522,31 @@ delete_envvar_cb (SysprofGreeter *self, } } +static void +delete_debugdirs_cb (SysprofGreeter *self, + GtkButton *button) +{ + const char *debug_directory; + guint n_items; + + g_assert (SYSPROF_IS_GREETER (self)); + g_assert (GTK_IS_BUTTON (button)); + + debug_directory = g_object_get_data (G_OBJECT (button), "DEBUGDIR"); + n_items = g_list_model_get_n_items (G_LIST_MODEL (self->debugdirs)); + + for (guint i = 0; i < n_items; i++) + { + g_autoptr(GtkStringObject) str = g_list_model_get_item (G_LIST_MODEL (self->debugdirs), i); + + if (g_strcmp0 (debug_directory, gtk_string_object_get_string (str)) == 0) + { + gtk_string_list_remove (self->debugdirs, i); + break; + } + } +} + static GtkWidget * create_envvar_row_cb (gpointer item, gpointer user_data) @@ -493,6 +587,46 @@ create_envvar_row_cb (gpointer item, return GTK_WIDGET (row); } +static GtkWidget * +create_debugdirs_row_cb (gpointer item, + gpointer user_data) +{ + SysprofGreeter *self = user_data; + GtkStringObject *obj = item; + const char *str; + g_autofree char *markup = NULL; + g_autofree char *escaped = NULL; + AdwActionRow *row; + GtkButton *button; + + g_assert (SYSPROF_IS_GREETER (self)); + g_assert (GTK_IS_STRING_OBJECT (obj)); + + str = gtk_string_object_get_string (obj); + escaped = g_markup_escape_text (str, -1); + markup = g_strdup_printf ("%s", escaped); + row = g_object_new (ADW_TYPE_ACTION_ROW, + "title", markup, + "title-selectable", TRUE, + NULL); + button = g_object_new (GTK_TYPE_BUTTON, + "icon-name", "list-remove-symbolic", + "css-classes", STRV_INIT ("flat", "circular"), + "valign", GTK_ALIGN_CENTER, + NULL); + g_object_set_data_full (G_OBJECT (button), + "DEBUGDIR", + g_strdup (str), + g_free); + g_signal_connect_object (button, + "clicked", + G_CALLBACK (delete_debugdirs_cb), + self, + G_CONNECT_SWAPPED); + adw_action_row_add_suffix (row, GTK_WIDGET (button)); + + return GTK_WIDGET (row); +} static char * translate_power_profile (GtkStringObject *strobj) @@ -542,6 +676,7 @@ sysprof_greeter_dispose (GObject *object) gtk_widget_dispose_template (GTK_WIDGET (self), SYSPROF_TYPE_GREETER); g_clear_object (&self->envvars); + g_clear_object (&self->debugdirs); g_clear_object (&self->recording_template); G_OBJECT_CLASS (sysprof_greeter_parent_class)->dispose (object); @@ -558,9 +693,11 @@ sysprof_greeter_class_init (SysprofGreeterClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-greeter.ui"); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, app_environment); + gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, debug_directories); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, bundle_symbols); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, debuginfod); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, envvars); + gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, debugdirs); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, power_combo); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, record_compositor); gtk_widget_class_bind_template_child (widget_class, SysprofGreeter, record_disk_usage); @@ -582,6 +719,8 @@ sysprof_greeter_class_init (SysprofGreeterClass *klass) gtk_widget_class_bind_template_callback (widget_class, get_file_path); gtk_widget_class_bind_template_callback (widget_class, on_env_entry_activate_cb); gtk_widget_class_bind_template_callback (widget_class, on_env_entry_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, on_debug_dir_entry_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, on_debug_dir_entry_activate_cb); gtk_widget_class_bind_template_callback (widget_class, translate_power_profile); gtk_widget_class_install_action (widget_class, "win.record-to-memory", NULL, sysprof_greeter_record_to_memory_action); @@ -614,6 +753,13 @@ sysprof_greeter_init (SysprofGreeter *self) G_CONNECT_SWAPPED); on_env_items_changed_cb (self, 0, 0, 0, G_LIST_MODEL (self->envvars)); + g_signal_connect_object (self->debugdirs, + "items-changed", + G_CALLBACK (on_debug_dir_items_changed_cb), + self, + G_CONNECT_SWAPPED); + on_debug_dir_items_changed_cb (self, 0, 0, 0, G_LIST_MODEL (self->debugdirs)); + gtk_list_box_bind_model (self->sidebar_list_box, G_LIST_MODEL (adw_view_stack_get_pages (self->view_stack)), sysprof_greeter_create_sidebar_row, @@ -624,6 +770,11 @@ sysprof_greeter_init (SysprofGreeter *self) create_envvar_row_cb, self, NULL); + gtk_list_box_bind_model (self->debug_directories, + G_LIST_MODEL (self->debugdirs), + create_debugdirs_row_cb, + self, NULL); + if (self->recording_template) { g_auto(GStrv) environ = NULL; diff --git a/src/sysprof/sysprof-greeter.ui b/src/sysprof/sysprof-greeter.ui index e69e2658..5af1dcc5 100644 --- a/src/sysprof/sysprof-greeter.ui +++ b/src/sysprof/sysprof-greeter.ui @@ -636,6 +636,48 @@ + + + Debug File Directories + Directories to search for debug files + + + 12 + none + false + + + + + + + up + 12 + center + + + Add _Directory + true + + + + + Add Directory + _Add + 400 + + + + + + + + @@ -706,6 +748,8 @@ + + diff --git a/src/sysprof/sysprof-recording-template.c b/src/sysprof/sysprof-recording-template.c index 3d7646de..8b93b684 100644 --- a/src/sysprof/sysprof-recording-template.c +++ b/src/sysprof/sysprof-recording-template.c @@ -35,6 +35,7 @@ struct _SysprofRecordingTemplate char *cwd; char *power_profile; char **environ; + char **debugdirs; guint stack_size; @@ -65,6 +66,7 @@ enum { PROP_BATTERY_CHARGE, PROP_BUNDLE_SYMBOLS, PROP_DEBUGINFOD, + PROP_DEBUGDIRS, PROP_CLEAR_ENVIRON, PROP_COMMAND_LINE, PROP_CPU_USAGE, @@ -103,6 +105,7 @@ sysprof_recording_template_finalize (GObject *object) g_clear_pointer (&self->cwd, g_free); g_clear_pointer (&self->power_profile, g_free); g_clear_pointer (&self->environ, g_free); + g_clear_pointer (&self->debugdirs, g_strfreev); G_OBJECT_CLASS (sysprof_recording_template_parent_class)->finalize (object); } @@ -156,6 +159,10 @@ sysprof_recording_template_get_property (GObject *object, case PROP_ENVIRON: g_value_set_boxed (value, self->environ); break; + + case PROP_DEBUGDIRS: + g_value_set_boxed (value, self->debugdirs); + break; case PROP_FRAME_TIMINGS: g_value_set_boolean (value, self->frame_timings); @@ -272,6 +279,11 @@ sysprof_recording_template_set_property (GObject *object, g_clear_pointer (&self->environ, g_strfreev); self->environ = g_value_dup_boxed (value); break; + + case PROP_DEBUGDIRS: + g_clear_pointer (&self->debugdirs, g_strfreev); + self->debugdirs = g_value_dup_boxed (value); + break; case PROP_FRAME_TIMINGS: self->frame_timings = g_value_get_boolean (value); @@ -396,6 +408,11 @@ sysprof_recording_template_class_init (SysprofRecordingTemplateClass *klass) g_param_spec_boxed ("environ", NULL, NULL, G_TYPE_STRV, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + properties[PROP_DEBUGDIRS] = + g_param_spec_boxed ("debugdirs", NULL, NULL, + G_TYPE_STRV, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); properties[PROP_FRAME_TIMINGS] = g_param_spec_boolean ("frame-timings", NULL, NULL, @@ -783,9 +800,9 @@ sysprof_recording_template_create_loader (SysprofRecordingTemplate *self, multi = sysprof_multi_symbolizer_new (); elf = SYSPROF_ELF_SYMBOLIZER (sysprof_elf_symbolizer_new ()); - /* TODO: add extra-debug-directories property and use that to - * call sysprof_elf_symbolizer_set_external_debug_dirs(elf,...) - */ + + if (self->debugdirs) + sysprof_elf_symbolizer_set_external_debug_dirs (elf, (const char * const *)self->debugdirs); /* Add in order of priority */ sysprof_multi_symbolizer_take (multi, sysprof_bundled_symbolizer_new ());