Add ability to copy About dialog configuration

settings to the clipboard so they can all be
pasted in one go.
pull/2153/head
Robert Fewell 3 months ago
parent c80234341c
commit ed03e61dab

@ -5266,22 +5266,162 @@ url_signal_cb (GtkAboutDialog *dialog, gchar *uri, gpointer data)
return TRUE;
}
#define DEFAULT_MARGIN 5
static void
set_text_cursor (GdkWindow *win, GdkCursorType type)
{
if (!win && !type)
return;
GdkCursor *current = gdk_window_get_cursor (win);
if (type == gdk_cursor_get_cursor_type (current))
return;
GdkCursor *cur = gdk_cursor_new_for_display (gdk_window_get_display (win), type);
gdk_window_set_cursor (win, cur);
}
static gboolean
textview_motion_notify_cb (GtkWidget *textview,
GdkEventMotion *event,
gpointer user_data)
{
if (event->state & GDK_BUTTON1_MASK)
return false;
GtkTextIter iter;
gboolean valid = gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW(textview),
&iter, event->x, event->y);
if (valid && (event->y > DEFAULT_MARGIN))
{
GSList *tt_list = gtk_text_iter_get_tags (&iter);
if (tt_list)
{
GtkTextTag *tt = (GtkTextTag*)g_slist_nth_data (tt_list, 0);
if (g_object_get_data (G_OBJECT(tt), "link"))
set_text_cursor (event->window, GDK_HAND1);
else
set_text_cursor (event->window, GDK_XTERM);
g_slist_free (tt_list);
}
else
set_text_cursor (event->window, GDK_XTERM);
}
else
set_text_cursor (event->window, GDK_XTERM);
return true;
}
static gboolean
link_button_cb (GtkLinkButton *button, gpointer user_data)
textview_url_activate (GtkTextTag *tag,
GObject *object,
GdkEvent *event,
GtkTextIter *iter,
gpointer user_data)
{
const gchar *uri = gtk_link_button_get_uri (button);
gchar *escaped_uri = g_uri_escape_string (uri, ":/.\\", true);
gnc_launch_doclink (GTK_WINDOW(user_data), escaped_uri);
g_free (escaped_uri);
return TRUE;
GdkEventButton *event_button = (GdkEventButton*)event;
if ((event->type == GDK_BUTTON_RELEASE) &&
(event_button->button == 1) &&
(event_button->y > DEFAULT_MARGIN))
{
gchar *link = (gchar*)g_object_get_data (G_OBJECT(tag), "link");
PINFO("Link is '%s'", link);
gchar *escaped_uri = g_uri_escape_string (link, ":/.\\", true);
PINFO("Escaped Link is '%s'", escaped_uri);
gnc_launch_doclink (GTK_WINDOW(user_data), escaped_uri);
g_free (escaped_uri);
return true;
}
return false;
}
static gint
get_max_text_width (GtkTextView *textview, std::vector<EnvPaths> ep_vec)
{
gint max_text_width = 0;
for (const auto& ep : ep_vec)
{
gint text_width;
gchar *env_name = g_strconcat (ep.env_name, ":", nullptr);
PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET(textview),
env_name);
pango_layout_get_pixel_size (layout, &text_width, nullptr);
g_object_unref (layout);
g_free (env_name);
max_text_width = MAX(max_text_width, text_width);
}
return max_text_width;
}
static GtkTextTag *
create_left_margin_text_tag (GtkTextView *textview,
gchar *lmargin_tag,
const gchar *text,
gint max_width)
{
if (!lmargin_tag)
return nullptr;
GtkTextTag *lmargin_tt = gtk_text_tag_new (lmargin_tag);
int text_width;
PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET(textview), text);
pango_layout_get_pixel_size (layout, &text_width, nullptr);
g_object_unref (layout);
g_object_set (G_OBJECT(lmargin_tt), "left_margin",
DEFAULT_MARGIN + max_width - text_width, nullptr);
return lmargin_tt;
}
static GdkRGBA
get_link_color (void)
{
GdkRGBA link_color;
GtkWidget *dummy_link_button = gtk_link_button_new_with_label ("https://www.gnucash.org", "Dummy");
GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET(dummy_link_button));
gtk_style_context_get_color (context, GTK_STATE_FLAG_LINK, &link_color);
return link_color;
}
static GtkTextTag *
create_url_text_tag (GtkDialog *dialog,
GdkRGBA link_color,
gchar *url_tag,
const gchar *uri)
{
if (!url_tag)
return nullptr;
GtkTextTag *url_tt = gtk_text_tag_new (url_tag);
g_object_set (G_OBJECT(url_tt), "underline", PANGO_UNDERLINE_SINGLE,
"underline-set", true, nullptr);
g_object_set (G_OBJECT(url_tt), "foreground-rgba", &link_color, nullptr);
g_object_set_data_full (G_OBJECT(url_tt), "link", g_strdup (uri), g_free);
g_signal_connect (G_OBJECT(url_tt), "event",
G_CALLBACK(textview_url_activate), dialog);
return url_tt;
}
static void
add_about_paths (GtkDialog *dialog)
{
GtkWidget *page_vbox = gnc_get_dialog_widget_from_id (dialog, "page_vbox");
GtkWidget *grid;
gint i = 0;
if (!page_vbox)
{
@ -5289,40 +5429,74 @@ add_about_paths (GtkDialog *dialog)
return;
}
grid = gtk_grid_new ();
GtkWidget *textview = gtk_text_view_new ();
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(textview));
GtkTextTagTable *ttt = gtk_text_buffer_get_tag_table (buffer);
GtkTextIter iter;
std::vector<EnvPaths> ep_vec = gnc_list_all_paths ();
int ep_size = (int)ep_vec.size();
int row = 1;
GdkRGBA link_color = get_link_color ();
gint max_text_width = get_max_text_width (GTK_TEXT_VIEW(textview), ep_vec);
for (const auto& ep : gnc_list_all_paths ())
gtk_text_view_set_left_margin (GTK_TEXT_VIEW(textview), DEFAULT_MARGIN);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW(textview), DEFAULT_MARGIN);
gtk_text_view_set_top_margin (GTK_TEXT_VIEW(textview), DEFAULT_MARGIN);
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW(textview), DEFAULT_MARGIN);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(textview), GTK_WRAP_NONE);
gtk_text_buffer_create_tag (buffer, "italic", "style", PANGO_STYLE_ITALIC, nullptr);
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
for (const auto& ep : ep_vec)
{
gchar *env_name = g_strconcat (ep.env_name, ":", NULL);
GtkWidget *label = gtk_label_new (env_name);
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
const gchar *uri = gnc_uri_create_uri ("file", NULL, 0, NULL, NULL, ep.env_path);
gchar *env_name = g_strconcat (ep.env_name, ":", nullptr);
const gchar *uri = gnc_uri_create_uri ("file", nullptr, 0, nullptr, nullptr, ep.env_path);
gchar *display_uri = gnc_doclink_get_unescaped_just_uri (uri);
GtkWidget *widget = gtk_link_button_new_with_label (uri, display_uri);
gtk_grid_attach (GTK_GRID(grid), label, 0, i, 1, 1);
gtk_widget_set_halign (label, GTK_ALIGN_END);
gtk_grid_attach (GTK_GRID(grid), widget, 1, i, 1, 1);
gtk_widget_set_halign (widget, GTK_ALIGN_START);
gtk_widget_set_margin_top (widget, 0);
gtk_widget_set_margin_bottom (widget, 0);
gchar *url_tag = g_strdup_printf ("%s%d", "url_tag", row);
gchar *lmargin_tag = g_strdup_printf ("%s%d", "lmargin_tag", row);
gtk_text_tag_table_add (ttt, create_left_margin_text_tag (GTK_TEXT_VIEW(textview),
lmargin_tag,
env_name,
max_text_width));
gtk_text_tag_table_add (ttt, create_url_text_tag (dialog,
link_color,
url_tag,
uri));
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, env_name, -1, lmargin_tag, nullptr);
gtk_text_buffer_insert (buffer, &iter, " ", -1);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, display_uri, -1, url_tag, nullptr);
g_free (url_tag);
g_free (lmargin_tag);
g_free (display_uri);
g_free (env_name);
if (ep.modifiable)
{
GtkWidget *mod_lab = gtk_label_new (_("(user modifiable)"));
gtk_grid_attach (GTK_GRID(grid), mod_lab, 2, i, 1, 1);
gtk_widget_show (mod_lab);
gtk_text_buffer_insert (buffer, &iter, " ", -1);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, _("(User modifiable)"), -1, "italic", nullptr);
}
g_signal_connect (widget, "activate-link",
G_CALLBACK(link_button_cb), dialog);
i++;
g_free (display_uri);
g_free (env_name);
if (row != ep_size)
gtk_text_buffer_insert (buffer, &iter, "\n", -1);
row++;
}
gtk_container_add_with_properties (GTK_CONTAINER(page_vbox), grid,
"position", 1, NULL);
gtk_widget_show_all (grid);
gtk_text_view_set_editable (GTK_TEXT_VIEW(textview), false);
g_signal_connect (G_OBJECT(textview), "motion-notify-event",
G_CALLBACK(textview_motion_notify_cb), nullptr);
gtk_container_add_with_properties (GTK_CONTAINER(page_vbox), textview,
"position", 1, nullptr);
gtk_widget_show_all (page_vbox);
}
/** Create and display the "about" dialog for gnucash.

@ -89,8 +89,3 @@ dialog#GnuCash > box > box > label
{
font-size: 24px;
}
dialog#GnuCash grid * {
padding-top: 0px;
padding-bottom: 0px;
min-height: 4px;
}

Loading…
Cancel
Save