Fri, 26 Aug 2022 02:57:40 -0500
Fix debug window on GTK4, plus other issues.
* There's no need to go through the request API to make the save button work, so do it with a native file chooser.
* There's an `error` CSS class, so use that instead of our custom one. "working" is the default state, so drop the `good-filter` CSS class.
* Setting the search entry widget text from the preference seems to cause an infinite loop, and I don't know why the pref would change without the widget doing so, so drop that.
* Move delete stuff into `finalize` vfunc.
* Moved filter options menu to the 'filter' button, as `GtkSearchEntry` does not expose the icon as in GTK3.
Testing Done:
Opened debug window, set various debug levels, clicked save button and saved log somewhere, entered some text in filter and toggled enable button, right-clicked enable and toggled the Invert and Highlight options.
Reviewed at https://reviews.imfreedom.org/r/1659/
| pidgin/pidgindebug.c | file | annotate | diff | comparison | revisions | |
| pidgin/resources/Debug/debug.ui | file | annotate | diff | comparison | revisions | |
| pidgin/resources/Debug/filter.css | file | annotate | diff | comparison | revisions | |
| pidgin/resources/pidgin.gresource.xml | file | annotate | diff | comparison | revisions |
--- a/pidgin/pidgindebug.c Fri Aug 26 01:07:29 2022 -0500 +++ b/pidgin/pidgindebug.c Fri Aug 26 02:57:40 2022 -0500 @@ -82,24 +82,6 @@ G_DEFINE_TYPE(PidginDebugWindow, pidgin_debug_window, GTK_TYPE_WINDOW); -static gint -debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused) -{ - purple_prefs_disconnect_by_handle(pidgin_debug_get_handle()); - - if (debug_win->regex != NULL) - g_regex_unref(debug_win->regex); - - /* If the "Save Log" dialog is open then close it */ - purple_request_close_with_handle(debug_win); - - debug_win = NULL; - - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/enabled", FALSE); - - return FALSE; -} - static gboolean save_default_size_cb(GObject *gobject, G_GNUC_UNUSED GParamSpec *pspec, G_GNUC_UNUSED gpointer data) @@ -125,32 +107,82 @@ } static void -save_writefile_cb(void *user_data, const char *filename) +save_response_cb(GtkNativeDialog *self, gint response_id, gpointer data) { - PidginDebugWindow *win = (PidginDebugWindow *)user_data; - FILE *fp; - GtkTextIter start, end; - char *tmp; + PidginDebugWindow *win = (PidginDebugWindow *)data; + + if(response_id == GTK_RESPONSE_ACCEPT) { + GFile *file = NULL; + GFileOutputStream *output = NULL; + GtkTextIter start, end; + gchar *tmp = NULL; + GError *error = NULL; + + file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(self)); + output = g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, + &error); + g_object_unref(file); + + if(output == NULL) { + purple_debug_error("debug", + "Unable to open file to save debug log: %s", + error->message); + g_error_free(error); + g_object_unref(self); + return; + } - if ((fp = g_fopen(filename, "w+")) == NULL) { - purple_notify_error(win, NULL, _("Unable to open file."), NULL, NULL); - return; + tmp = g_strdup_printf("Pidgin Debug Log : %s\n", purple_date_format_full(NULL)); + g_output_stream_write_all(G_OUTPUT_STREAM(output), tmp, strlen(tmp), + NULL, NULL, &error); + g_free(tmp); + + if(error != NULL) { + purple_debug_error("debug", "Unable to save debug log: %s", + error->message); + g_error_free(error); + g_object_unref(output); + g_object_unref(self); + return; + } + + gtk_text_buffer_get_bounds(win->buffer, &start, &end); + tmp = gtk_text_buffer_get_text(win->buffer, &start, &end, TRUE); + g_output_stream_write_all(G_OUTPUT_STREAM(output), tmp, strlen(tmp), + NULL, NULL, &error); + g_free(tmp); + + if(error != NULL) { + purple_debug_error("debug", "Unable to save debug log: %s", + error->message); + g_error_free(error); + g_object_unref(output); + g_object_unref(self); + return; + } + + g_object_unref(output); } - gtk_text_buffer_get_bounds(win->buffer, &start, &end); - tmp = gtk_text_buffer_get_text(win->buffer, &start, &end, TRUE); - fprintf(fp, "Pidgin Debug Log : %s\n", purple_date_format_full(NULL)); - fprintf(fp, "%s", tmp); - g_free(tmp); - - fclose(fp); + g_object_unref(self); } static void save_cb(GtkWidget *w, PidginDebugWindow *win) { - purple_request_file(win, _("Save Debug Log"), "purple-debug.log", TRUE, - G_CALLBACK(save_writefile_cb), NULL, NULL, win); + GtkFileChooserNative *filesel; + + filesel = gtk_file_chooser_native_new(_("Save Debug Log"), GTK_WINDOW(win), + GTK_FILE_CHOOSER_ACTION_SAVE, + _("_Save"), _("_Cancel")); + + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(filesel), + "purple-debug.log"); + + g_signal_connect(filesel, "response", G_CALLBACK(save_response_cb), win); + + gtk_native_dialog_set_modal(GTK_NATIVE_DIALOG(filesel), TRUE); + gtk_native_dialog_show(GTK_NATIVE_DIALOG(filesel)); } static void @@ -180,8 +212,7 @@ static void regex_clear_color(GtkWidget *w) { GtkStyleContext *context = gtk_widget_get_style_context(w); - gtk_style_context_remove_class(context, "good-filter"); - gtk_style_context_remove_class(context, "bad-filter"); + gtk_style_context_remove_class(context, "error"); } static void @@ -189,11 +220,9 @@ GtkStyleContext *context = gtk_widget_get_style_context(w); if (success) { - gtk_style_context_add_class(context, "good-filter"); - gtk_style_context_remove_class(context, "bad-filter"); + gtk_style_context_remove_class(context, "error"); } else { - gtk_style_context_add_class(context, "bad-filter"); - gtk_style_context_remove_class(context, "good-filter"); + gtk_style_context_add_class(context, "error"); } } @@ -301,16 +330,6 @@ } static void -regex_pref_expression_cb(const gchar *name, PurplePrefType type, - gconstpointer val, gpointer data) -{ - PidginDebugWindow *win = (PidginDebugWindow *)data; - const gchar *exp = (const gchar *)val; - - gtk_editable_set_text(GTK_EDITABLE(win->expression), exp); -} - -static void regex_pref_invert_cb(const gchar *name, PurplePrefType type, gconstpointer val, gpointer data) { @@ -396,7 +415,7 @@ { gboolean active; - active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(item)); + active = gtk_check_button_get_active(GTK_CHECK_BUTTON(item)); if (item == win->popover_highlight) { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/highlight", active); @@ -405,22 +424,16 @@ } } -#if 0 -/* FIXME: may not work with GTK4's SearchEntry */ static void -regex_popup_cb(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, - PidginDebugWindow *win) +regex_popup_cb(G_GNUC_UNUSED GtkGestureClick* self, G_GNUC_UNUSED gint n_press, + gdouble x, gdouble y, gpointer data) { - GdkRectangle rect; - if (icon_pos != GTK_ENTRY_ICON_PRIMARY) { - return; - } + PidginDebugWindow *win = data; - gtk_entry_get_icon_area(entry, icon_pos, &rect); - gtk_popover_set_pointing_to(GTK_POPOVER(win->popover), &rect); + gtk_popover_set_pointing_to(GTK_POPOVER(win->popover), + &(const GdkRectangle){(int)x, (int)y, 0, 0}); gtk_popover_popup(GTK_POPOVER(win->popover)); } -#endif static void regex_filter_toggled_cb(GtkToggleButton *button, PidginDebugWindow *win) @@ -472,9 +485,38 @@ } static void +pidgin_debug_window_dispose(GObject *object) +{ + PidginDebugWindow *win = PIDGIN_DEBUG_WINDOW(object); + + gtk_widget_unparent(win->popover); + + G_OBJECT_CLASS(pidgin_debug_window_parent_class)->dispose(object); +} + +static void +pidgin_debug_window_finalize(GObject *object) +{ + PidginDebugWindow *win = PIDGIN_DEBUG_WINDOW(object); + + purple_prefs_disconnect_by_handle(pidgin_debug_get_handle()); + + g_clear_pointer(&win->regex, g_regex_unref); + + debug_win = NULL; + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/enabled", FALSE); + + G_OBJECT_CLASS(pidgin_debug_window_parent_class)->finalize(object); +} + +static void pidgin_debug_window_class_init(PidginDebugWindowClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + obj_class->dispose = pidgin_debug_window_dispose; + obj_class->finalize = pidgin_debug_window_finalize; + gtk_widget_class_set_template_from_resource( widget_class, "/im/pidgin/Pidgin3/Debug/debug.ui" @@ -527,9 +569,7 @@ regex_filter_toggled_cb); gtk_widget_class_bind_template_callback(widget_class, regex_changed_cb); -#if 0 gtk_widget_class_bind_template_callback(widget_class, regex_popup_cb); -#endif gtk_widget_class_bind_template_callback(widget_class, regex_menu_cb); gtk_widget_class_bind_template_callback(widget_class, regex_key_released_cb); @@ -543,12 +583,11 @@ gint width, height; void *handle; GtkTextIter end; - GtkStyleContext *context; - GtkCssProvider *filter_css; - const gchar *res = "/im/pidgin/Pidgin3/Debug/filter.css"; gtk_widget_init_template(GTK_WIDGET(win)); + gtk_widget_set_parent(win->popover, win->filter); + width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/height"); @@ -557,8 +596,6 @@ gtk_window_set_default_size(GTK_WINDOW(win), width, height); - g_signal_connect(G_OBJECT(win), "delete_event", - G_CALLBACK(debug_window_destroy), NULL); g_signal_connect(G_OBJECT(win), "notify::default-width", G_CALLBACK(save_default_size_cb), NULL); g_signal_connect(G_OBJECT(win), "notify::default-height", @@ -580,18 +617,8 @@ regex_pref_filter_cb, win); /* regex entry */ - filter_css = gtk_css_provider_new(); - gtk_css_provider_load_from_resource(filter_css, res); - - context = gtk_widget_get_style_context(win->expression); - gtk_style_context_add_provider(context, - GTK_STYLE_PROVIDER(filter_css), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - gtk_editable_set_text(GTK_EDITABLE(win->expression), purple_prefs_get_string(PIDGIN_PREFS_ROOT "/debug/regex")); - purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/regex", - regex_pref_expression_cb, win); /* connect the rest of our pref callbacks */ win->invert = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/invert"); @@ -608,10 +635,10 @@ purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/filterlevel", filter_level_pref_changed, win); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->popover_invert), - win->invert); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->popover_highlight), - win->highlight); + gtk_check_button_set_active(GTK_CHECK_BUTTON(win->popover_invert), + win->invert); + gtk_check_button_set_active(GTK_CHECK_BUTTON(win->popover_highlight), + win->highlight); } /* The *start* and *end* marks bound the beginning and end of an @@ -827,7 +854,6 @@ { if (debug_win != NULL) { gtk_window_destroy(GTK_WINDOW(debug_win)); - debug_window_destroy(NULL, NULL, NULL); } }
--- a/pidgin/resources/Debug/debug.ui Fri Aug 26 01:07:29 2022 -0500 +++ b/pidgin/resources/Debug/debug.ui Fri Aug 26 02:57:40 2022 -0500 @@ -69,32 +69,32 @@ <object class="GtkTextTagTable" id="message-format"> <child type="tag"> <object class="GtkTextTag" id="tags.level[0]"> - <property name="foreground-rgba">rgb(0,0,0)</property> + <property name="foreground">rgb(0,0,0)</property> </object> </child> <child type="tag"> <object class="GtkTextTag" id="tags.level[1]"> - <property name="foreground-rgba">rgb(102,102,102)</property> + <property name="foreground">rgb(102,102,102)</property> </object> </child> <child type="tag"> <object class="GtkTextTag" id="tags.level[2]"> - <property name="foreground-rgba">rgb(0,0,0)</property> + <property name="foreground">rgb(0,0,0)</property> </object> </child> <child type="tag"> <object class="GtkTextTag" id="tags.level[3]"> - <property name="foreground-rgba">rgb(102,0,0)</property> + <property name="foreground">rgb(102,0,0)</property> </object> </child> <child type="tag"> <object class="GtkTextTag" id="tags.level[4]"> - <property name="foreground-rgba">rgb(255,0,0)</property> + <property name="foreground">rgb(255,0,0)</property> </object> </child> <child type="tag"> <object class="GtkTextTag" id="tags.level[5]"> - <property name="foreground-rgba">rgb(255,0,0)</property> + <property name="foreground">rgb(255,0,0)</property> <property name="weight">700</property> </object> </child> @@ -116,7 +116,7 @@ </child> <child type="tag"> <object class="GtkTextTag" id="tags.match"> - <property name="background-rgba">rgb(255,175,175)</property> + <property name="background">rgb(255,175,175)</property> <property name="weight">700</property> </object> </child> @@ -130,7 +130,7 @@ <property name="tag-table">message-format</property> </object> <template class="PidginDebugWindow" parent="GtkWindow"> - <property name="title" translatable="yes">Debug Window</property> + <property name="title" translatable="1">Debug Window</property> <property name="child"> <object class="GtkBox"> <property name="orientation">vertical</property> @@ -141,8 +141,8 @@ </style> <child> <object class="GtkButton" id="save"> - <property name="tooltip-text" translatable="yes">Save</property> - <property name="label" translatable="yes">_Save...</property> + <property name="tooltip-text" translatable="1">Save</property> + <property name="label" translatable="1">_Save...</property> <property name="use-underline">1</property> <property name="icon-name">document-save</property> <signal name="clicked" handler="save_cb" object="PidginDebugWindow" swapped="no"/> @@ -150,8 +150,8 @@ </child> <child> <object class="GtkButton" id="clear"> - <property name="tooltip-text" translatable="yes">Clear</property> - <property name="label" translatable="yes">_Clear</property> + <property name="tooltip-text" translatable="1">Clear</property> + <property name="label" translatable="1">_Clear</property> <property name="use-underline">1</property> <property name="icon-name">edit-clear</property> <signal name="clicked" handler="clear_cb" object="PidginDebugWindow" swapped="no"/> @@ -164,11 +164,11 @@ </child> <child> <object class="GtkToggleButton" id="pause"> - <property name="tooltip-text" translatable="yes">Pause</property> - <property name="label" translatable="yes">_Pause</property> + <property name="tooltip-text" translatable="1">Pause</property> + <property name="label" translatable="1">_Pause</property> <property name="use-underline">1</property> <property name="icon-name">media-playback-pause</property> - <signal name="clicked" handler="pause_cb" object="PidginDebugWindow" swapped="no"/> + <signal name="toggled" handler="pause_cb" object="PidginDebugWindow" swapped="no"/> </object> </child> <child> @@ -178,11 +178,17 @@ </child> <child> <object class="GtkToggleButton" id="filter"> - <property name="tooltip-text" translatable="yes">Filter</property> - <property name="label" translatable="yes">_Filter</property> + <property name="tooltip-text" translatable="1">Filter</property> + <property name="label" translatable="1">_Filter</property> <property name="use-underline">1</property> <property name="icon-name">edit-find</property> - <signal name="clicked" handler="regex_filter_toggled_cb" object="PidginDebugWindow" swapped="no"/> + <signal name="toggled" handler="regex_filter_toggled_cb" object="PidginDebugWindow" swapped="no"/> + <child> + <object class="GtkGestureClick"> + <property name="button">3</property> + <signal name="pressed" handler="regex_popup_cb" object="PidginDebugWindow" swapped="no"/> + </object> + </child> </object> </child> <child> @@ -193,9 +199,6 @@ </object> </child> <property name="focusable">1</property> - <property name="primary-icon-tooltip-text" translatable="yes">Click for more options.</property> - <!--<signal name="icon-press" handler="regex_popup_cb" object="PidginDebugWindow" swapped="no"/>--> - <property name="sensitive">0</property> <signal name="search-changed" handler="regex_changed_cb" object="PidginDebugWindow" swapped="no"/> </object> </child> @@ -205,16 +208,13 @@ </object> </child> <child> - <object class="GtkLabel"> - <property name="label" translatable="yes">Level </property> - <accessibility> - <relation type="label-for" target="filterlevel"/> - </accessibility> + <object class="GtkLabel" id="filterlevel-label"> + <property name="label" translatable="1">Level </property> </object> </child> <child> - <object class="GtkComboBoxText" id="filterlevel"> - <property name="tooltip-text" translatable="yes">Select the debug filter level.</property> + <object class="GtkComboBoxText" id="filterlevel"> + <property name="tooltip-text" translatable="1">Select the debug filter level.</property> <property name="active">0</property> <items> <item translatable="yes">All</item> @@ -225,6 +225,9 @@ <item translatable="yes">Fatal Error</item> </items> <signal name="changed" handler="filter_level_changed_cb" object="PidginDebugWindow" swapped="no"/> + <accessibility> + <relation name="labelled-by">filterlevel-label</relation> + </accessibility> </object> </child> </object> @@ -247,19 +250,20 @@ </property> </template> <object class="GtkPopover" id="popover"> + <property name="position">bottom</property> <property name="child"> <object class="GtkBox"> <property name="orientation">vertical</property> <child> <object class="GtkCheckButton" id="popover_invert"> - <property name="label" translatable="yes">Invert</property> + <property name="label" translatable="1">Invert</property> <property name="focusable">1</property> <signal name="toggled" handler="regex_menu_cb" object="PidginDebugWindow" swapped="no"/> </object> </child> <child> <object class="GtkCheckButton" id="popover_highlight"> - <property name="label" translatable="yes">Highlight matches</property> + <property name="label" translatable="1">Highlight matches</property> <property name="focusable">1</property> <signal name="toggled" handler="regex_menu_cb" object="PidginDebugWindow" swapped="no"/> </object>
--- a/pidgin/resources/Debug/filter.css Fri Aug 26 01:07:29 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -.bad-filter { - color: @error_fg_color; - text-shadow: 0 1px @error_text_shadow; - background-image: none; - background-color: @error_bg_color; -} - -.good-filter { - color: @question_fg_color; - text-shadow: 0 1px @question_text_shadow; - background-image: none; - background-color: @success_color; -}
--- a/pidgin/resources/pidgin.gresource.xml Fri Aug 26 01:07:29 2022 -0500 +++ b/pidgin/resources/pidgin.gresource.xml Fri Aug 26 02:57:40 2022 -0500 @@ -17,7 +17,6 @@ <file compressed="true">Conversations/tab-label.css</file> <file compressed="true">Conversations/window.ui</file> <file compressed="true">Debug/debug.ui</file> - <file compressed="true">Debug/filter.css</file> <file compressed="true">Dialogs/addbuddy.ui</file> <file compressed="true">Dialogs/addchat.ui</file> <file compressed="true">Keypad/keypad.ui</file>