--- a/pidgin/pidginabout.c Mon Jan 16 22:07:30 2023 -0600
+++ b/pidgin/pidginabout.c Mon Jan 16 22:08:46 2023 -0600
@@ -235,6 +235,25 @@
+pidgin_about_dialog_copy_build_info(void) { + info = g_strdup_printf( + "Purple Version: %u.%u.%u\n" + "GLib Version: %u.%u.%u\n" + "GTK Version: %u.%u.%u\n", + PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION, + GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); pidgin_about_dialog_load_runtime_info(PidginAboutDialog *about) {
/* add the purple version */
@@ -259,6 +278,23 @@
gtk_get_micro_version());
+pidgin_about_dialog_copy_runtime_info(void) { + info = g_strdup_printf( + "Runtime Information\n" + "===================\n" + "Purple Version: %u.%u.%u\n" + "GLib Version: %u.%u.%u\n" + "GTK Version: %u.%u.%u\n", + purple_major_version, purple_minor_version, purple_micro_version, + glib_major_version, glib_minor_version, glib_micro_version, + gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version()); pidgin_about_dialog_load_gtk_settings(PidginAboutDialog *about) {
gchar *cursor_theme_name = NULL, *theme_name = NULL;
@@ -328,6 +364,69 @@
+pidgin_about_dialog_copy_gtk_settings(void) { + char *cursor_theme_name = NULL, *theme_name = NULL; + char *icon_theme_name = NULL; + char *im_module = NULL; + char *sound_theme_name = NULL; + gboolean enable_animations = FALSE; + gboolean shell_shows_app_menu = FALSE, shell_shows_menubar = FALSE; + /* get the settings we're interested in */ + gtk_settings_get_default(), + "gtk-cursor-theme-name", &cursor_theme_name, + "gtk-enable-animations", &enable_animations, + "gtk-icon-theme-name", &icon_theme_name, + "gtk-im-module", &im_module, + "gtk-shell-shows-app-menu", &shell_shows_app_menu, + "gtk-shell-shows-menubar", &shell_shows_menubar, + "gtk-sound-theme-name", &sound_theme_name, + "gtk-theme-name", &theme_name, + g_string_append_printf( + info, "gtk-cursor-theme-name: %s\n", + (cursor_theme_name != NULL) ? cursor_theme_name : _("(not set)")); + g_string_append_printf(info, "gtk-enable-animations: %s\n", + enable_animations ? _("yes") : _("no")); + g_string_append_printf( + info, "gtk-icon-theme-name: %s\n", + (icon_theme_name != NULL) ? icon_theme_name : _("(not set)")); + g_string_append_printf(info, "gtk-im-module: %s\n", + (im_module != NULL) ? im_module : _("(not set)")); + g_string_append_printf(info, "gtk-shell-shows-app-menu: %s\n", + shell_shows_app_menu ? _("yes") : _("no")); + g_string_append_printf(info, "gtk-shell-shows-menubar: %s\n", + shell_shows_menubar ? _("yes") : _("no")); + g_string_append_printf( + info, "gtk-sound-theme-name: %s\n", + (sound_theme_name != NULL) ? sound_theme_name : _("(not set)")); + g_string_append_printf(info, "gtk-theme-name: %s\n", + (theme_name != NULL) ? theme_name : _("(not set)")); + g_free(cursor_theme_name); + g_free(icon_theme_name); + g_free(sound_theme_name); + return g_string_free(info, FALSE); pidgin_about_dialog_load_plugin_search_paths(PidginAboutDialog *about) {
@@ -343,6 +442,27 @@
+pidgin_about_dialog_copy_plugin_search_paths(void) { + GPluginManager *manager = gplugin_manager_get_default(); + "Plugin Search Paths\n" + "===================\n"); + /* add the search paths */ + paths = gplugin_manager_get_paths(manager); + g_string_append_printf(info, "- %s\n", (char *)paths->data); + return g_string_free(info, FALSE); pidgin_about_dialog_load_conf_path_info(PidginAboutDialog *about) {
/* add the cache directory path */
@@ -358,6 +478,23 @@
+pidgin_about_dialog_copy_conf_path_info(void) { + info = g_strdup_printf( + "Runtime Directories\n" + "===================\n" pidgin_about_dialog_add_build_args(PidginAboutDialog *about,
@@ -382,6 +519,42 @@
+pidgin_about_dialog_copy_build_args(const char *build_args) { + /* Walk through the arguments and add them */ + splits = g_strsplit(build_args, " ", -1); + for(gint idx = 0; splits[idx]; idx++) { + char **value_split = g_strsplit(splits[idx], "=", 2); + if(value_split[0] == NULL || value_split[0][0] == '\0') { + if(value_split[1] != NULL) { + value = purple_unescape_text(value_split[1]); + g_string_append_printf(info, "%s: %s\n", value_split[0], value); + g_strfreev(value_split); + return g_string_free(info, FALSE); pidgin_about_dialog_load_build_configuration(PidginAboutDialog *about) {
pidgin_about_dialog_load_build_info(about);
@@ -418,6 +591,73 @@
gtk_show_uri(GTK_WINDOW(data), url, GDK_CURRENT_TIME);
+pidgin_about_dialog_copy_button_cb(GtkButton *button, + PidginAboutDialog *about = NULL; + GdkClipboard *clipboard = NULL; + about = PIDGIN_ABOUT_DIALOG(gtk_widget_get_root(GTK_WIDGET(button))); + if(data == about->build_info_group) { + info = pidgin_about_dialog_copy_build_info(); + } else if(data == about->runtime_info_group) { + info = pidgin_about_dialog_copy_runtime_info(); + } else if(data == about->gtk_settings_group) { + info = pidgin_about_dialog_copy_gtk_settings(); + } else if(data == about->plugin_search_paths_group) { + info = pidgin_about_dialog_copy_plugin_search_paths(); + } else if(data == about->conf_path_info_group) { + info = pidgin_about_dialog_copy_conf_path_info(); + } else if(data == about->build_args_group) { + info = pidgin_about_dialog_copy_build_args(MESON_ARGS); + GString *everything = g_string_new(NULL); + info = pidgin_about_dialog_copy_build_info(); + g_string_append(everything, info); + g_string_append_c(everything, '\n'); + info = pidgin_about_dialog_copy_runtime_info(); + g_string_append(everything, info); + g_string_append_c(everything, '\n'); + info = pidgin_about_dialog_copy_conf_path_info(); + g_string_append(everything, info); + g_string_append_c(everything, '\n'); + info = pidgin_about_dialog_copy_gtk_settings(); + g_string_append(everything, info); + g_string_append_c(everything, '\n'); + info = pidgin_about_dialog_copy_plugin_search_paths(); + g_string_append(everything, info); + g_string_append_c(everything, '\n'); + info = pidgin_about_dialog_copy_build_args(MESON_ARGS); + g_string_append(everything, info); + info = g_string_free(everything, FALSE); + clipboard = gtk_widget_get_clipboard(GTK_WIDGET(about)); + gdk_clipboard_set_text(clipboard, info); /******************************************************************************
*****************************************************************************/
@@ -461,6 +701,8 @@
pidgin_about_dialog_response_cb);
gtk_widget_class_bind_template_callback(widget_class,
pidgin_about_dialog_open_url_cb);
+ gtk_widget_class_bind_template_callback(widget_class, + pidgin_about_dialog_copy_button_cb); --- a/pidgin/resources/About/about.ui Mon Jan 16 22:07:30 2023 -0600
+++ b/pidgin/resources/About/about.ui Mon Jan 16 22:08:46 2023 -0600
@@ -122,34 +122,93 @@
<object class="AdwPreferencesPage">
+ <object class="GtkButton" id="copy_all_button"> + <property name="css-classes">pill</property> + <property name="halign">center</property> + <property name="valign">end</property> + <property name="child"> + <object class="AdwButtonContent"> + <property name="icon-name">edit-copy-symbolic</property> + <property name="label" translatable="1">_Copy All</property> + <property name="use-underline">1</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" swapped="no"/> + <!-- AdwPreferencesPage doesn't track non-AdwPreferencesGroup children, so manually remove when it's destroyed. --> + <signal name="destroy" handler="gtk_widget_unparent" object="copy_all_button" swapped="yes"/> <object class="AdwPreferencesGroup" id="build_info_group">
<property name="title" translatable="1">Build Information</property>
+ <child type="header-suffix"> + <object class="GtkButton"> + <property name="css-classes">flat</property> + <property name="icon-name">edit-copy-symbolic</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" object="build_info_group" swapped="no"/> <object class="AdwPreferencesGroup" id="runtime_info_group">
<property name="title" translatable="1">Runtime Information</property>
+ <child type="header-suffix"> + <object class="GtkButton"> + <property name="css-classes">flat</property> + <property name="icon-name">edit-copy-symbolic</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" object="runtime_info_group" swapped="no"/> <object class="AdwPreferencesGroup" id="conf_path_info_group">
<property name="title" translatable="1">Runtime Directories</property>
+ <child type="header-suffix"> + <object class="GtkButton"> + <property name="css-classes">flat</property> + <property name="icon-name">edit-copy-symbolic</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" object="conf_path_info_group" swapped="no"/> <object class="AdwPreferencesGroup" id="gtk_settings_group">
<property name="title" translatable="1">GTK Settings</property>
+ <child type="header-suffix"> + <object class="GtkButton"> + <property name="css-classes">flat</property> + <property name="icon-name">edit-copy-symbolic</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" object="gtk_settings_group" swapped="no"/> <object class="AdwPreferencesGroup" id="plugin_search_paths_group">
<property name="title" translatable="1">Plugin Search Paths</property>
+ <child type="header-suffix"> + <object class="GtkButton"> + <property name="css-classes">flat</property> + <property name="icon-name">edit-copy-symbolic</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" object="plugin_search_paths_group" swapped="no"/> <object class="AdwPreferencesGroup" id="build_args_group">
<property name="title" translatable="1">Meson Arguments</property>
<property name="visible">0</property>
+ <child type="header-suffix"> + <object class="GtkButton"> + <property name="css-classes">flat</property> + <property name="icon-name">edit-copy-symbolic</property> + <signal name="clicked" handler="pidgin_about_dialog_copy_button_cb" object="build_args_group" swapped="no"/>