Fix debug window on GTK4, plus other issues. gtk4

Fri, 26 Aug 2022 02:57:40 -0500

author
Elliott Sales de Andrade <quantum.analyst@gmail.com>
date
Fri, 26 Aug 2022 02:57:40 -0500
branch
gtk4
changeset 41604
ca2d6ea565a6
parent 41603
999f937df903
child 41605
2e2adf4729e7

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>

mercurial