Skip to content

Commit 2d28e80

Browse files
author
lafricain79
committed
feat: convert bookmarks to tags with color highlighting
- Add COL_COLOR column to bookmark tree store (bookmarks_treeview.h/c) - Add color attribute to XML folder nodes (xml.c/h) - New folder dialog with color picker (ui/folder.gtkbuilder, ui/folder.glade) - Tag color saved and restored from bookmarks.xml - Verse highlighting in Bible text using tag color (display.cc) - Text color auto-adjusted for dark backgrounds (luminance) - Multi-reference support: semicolons, commas, verse ranges - Popup menu for multi-reference bookmarks navigation - Drag and drop reordering enabled by default - Cairo color dot in treeview for tagged folders - Current verse green highlight disabled when tag color present - Fix bookmark folder labels localization: gettext now initialized before default bookmarks are created, so folder names (Personal, What must I do to be saved?, etc.) are properly translated on first run Closes #968 Closes #685
1 parent f5cb572 commit 2d28e80

16 files changed

Lines changed: 1568 additions & 632 deletions

po/fr.po

Lines changed: 230 additions & 211 deletions
Large diffs are not rendered by default.

po/xiphos.pot

Lines changed: 219 additions & 206 deletions
Large diffs are not rendered by default.

src/gtk/bookmark_dialog.c

Lines changed: 76 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "gui/bookmarks_treeview.h"
3434
#include "gui/dialog.h"
3535
#include "gui/utilities.h"
36+
#include "gui/widgets.h"
3637

3738
#include "main/display.hh"
3839
#include "main/sword.h"
@@ -147,56 +148,75 @@ static void add_folder_button(void)
147148
GtkTreeIter iter;
148149
BOOKMARK_DATA *data;
149150
GtkTreeSelection *selection;
150-
char *t;
151-
gint test;
152-
GS_DIALOG *info;
153-
GString *str;
154151

155152
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
156153
if (!gtk_tree_selection_get_selected(selection, NULL, &selected))
157154
return;
158155

159-
t = "|";
160-
str = g_string_new("");
161-
info = gui_new_dialog();
162-
//info->stock_icon = GTK_STOCK_OPEN;
163-
info->title = _("Bookmark");
164-
g_string_printf(str, "<span weight=\"bold\">%s</span>",
165-
_("Enter Folder Name"));
166-
info->label_top = str->str;
167-
info->text1 = g_strdup(_("Folder Name"));
168-
info->label1 = _("Folder: ");
169-
info->ok = TRUE;
170-
info->cancel = TRUE;
156+
gchar *glade_file = gui_general_user_file("folder" UI_SUFFIX, TRUE);
157+
if (!glade_file) return;
158+
#ifdef USE_GTKBUILDER
159+
GtkBuilder *gxml = gtk_builder_new();
160+
gtk_builder_add_from_file(gxml, glade_file, NULL);
161+
#else
162+
GladeXML *gxml = glade_xml_new(glade_file, NULL, NULL);
163+
#endif
164+
g_free(glade_file);
171165

172-
data = g_new(BOOKMARK_DATA, 1);
173-
/*** open dialog to get name for new folder ***/
174-
test = gui_gs_dialog(info);
175-
if (test == GS_OK) {
176-
char *buf = g_strdelimit(info->text1, t, ' ');
177-
data->caption = g_strdup(buf);
178-
data->key = NULL;
179-
data->module = NULL;
180-
data->module_desc = NULL;
181-
data->description = NULL;
166+
GtkWidget *entry = GTK_WIDGET(UI_GET_ITEM(gxml, "folder_entry_name"));
167+
GtkWidget *colorbtn = GTK_WIDGET(UI_GET_ITEM(gxml, "folder_color_button"));
168+
GtkWidget *clearbtn = GTK_WIDGET(UI_GET_ITEM(gxml, "folder_clear_color"));
169+
GtkWidget *clearbtn = GTK_WIDGET(gtk_builder_get_object(gxml, "folder_clear_color"));
170+
171+
if (!fdialog || !entry || !colorbtn || !clearbtn) {
172+
#ifdef USE_GTKBUILDER
173+
g_object_unref(gxml);
174+
#endif
175+
return;
176+
}
177+
178+
gtk_window_set_title(GTK_WINDOW(fdialog), _("New Tag"));
179+
gtk_entry_set_text(GTK_ENTRY(entry), "");
180+
g_signal_connect_swapped(clearbtn, "clicked",
181+
G_CALLBACK(gtk_widget_set_sensitive), colorbtn);
182+
183+
if (gtk_dialog_run(GTK_DIALOG(fdialog)) == GTK_RESPONSE_OK) {
184+
const gchar *name = gtk_entry_get_text(GTK_ENTRY(entry));
185+
gchar *color = NULL;
186+
if (gtk_widget_is_sensitive(colorbtn)) {
187+
#if GTK_CHECK_VERSION(3, 4, 0)
188+
GdkRGBA rgba;
189+
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(colorbtn), &rgba);
190+
if (rgba.red < 0.99 || rgba.green < 0.99 || rgba.blue < 0.99)
191+
color = g_strdup_printf("#%02X%02X%02X",
192+
(guint)(rgba.red * 255),
193+
(guint)(rgba.green * 255),
194+
(guint)(rgba.blue * 255));
195+
#endif
196+
}
197+
data = g_new0(BOOKMARK_DATA, 1);
198+
data->caption = g_strdelimit(g_strdup(name), "/|><.'`\"", ' ');
199+
data->color = color;
182200
data->is_leaf = FALSE;
183-
data->opened = bm_pixbufs->pixbuf_opened;
184-
data->closed = bm_pixbufs->pixbuf_closed;
201+
data->opened = bm_pixbufs->pixbuf_opened;
202+
data->closed = bm_pixbufs->pixbuf_closed;
185203
gui_add_item_to_tree(&iter, &selected, data);
186204
bookmarks_changed = TRUE;
187205
gui_save_bookmarks(NULL, NULL);
188-
g_free(data->caption);
206+
/* expand and select the new folder */
189207
GtkTreePath *path =
190-
gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter);
191-
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(treeview),
192-
path);
208+
gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter);
209+
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(treeview), path);
193210
gtk_tree_selection_select_path(selection, path);
194211
gtk_tree_path_free(path);
212+
g_free(data->caption);
213+
g_free(data->color);
214+
g_free(data);
195215
}
196-
g_free(data);
197-
g_free(info->text1);
198-
g_free(info);
199-
g_string_free(str, TRUE);
216+
gtk_widget_destroy(fdialog);
217+
#ifdef USE_GTKBUILDER
218+
g_object_unref(gxml);
219+
#endif
200220
}
201221

202222
/******************************************************************************
@@ -219,15 +239,13 @@ void on_dialog_response(GtkDialog *dialog,
219239
gint response_id, gpointer user_data)
220240
{
221241
switch (response_id) {
222-
case GTK_RESPONSE_CANCEL: /* cancel button pressed */
223-
case GTK_RESPONSE_NONE: /* dialog destroyed */
224-
gtk_widget_destroy(GTK_WIDGET(dialog));
242+
case GTK_RESPONSE_CANCEL:
243+
case GTK_RESPONSE_NONE:
225244
break;
226-
case GTK_RESPONSE_OK: /* add button pressed */
245+
case GTK_RESPONSE_OK:
227246
add_bookmark_button();
228-
gtk_widget_destroy(GTK_WIDGET(dialog));
229247
break;
230-
case GTK_RESPONSE_ACCEPT: /* add folder pressed */
248+
case GTK_RESPONSE_ACCEPT:
231249
add_folder_button();
232250
break;
233251
}
@@ -441,8 +459,6 @@ static GtkWidget *_create_bookmark_dialog(gchar *label,
441459

442460
/* lookup the root widget */
443461
bookmark_dialog = UI_GET_ITEM(gxml, "dialog");
444-
g_signal_connect(bookmark_dialog, "response",
445-
G_CALLBACK(on_dialog_response), NULL);
446462

447463
/* treeview */
448464
treeview = UI_GET_ITEM(gxml, "treeview");
@@ -581,7 +597,22 @@ void gui_bookmark_dialog(gchar *label, gchar *module_name, gchar *key)
581597
_create_bookmark_dialog(label, module_name, key);
582598
if (!dialog)
583599
return;
584-
gtk_dialog_run(GTK_DIALOG(dialog));
600+
gint response;
601+
while (TRUE) {
602+
response = gtk_dialog_run(GTK_DIALOG(dialog));
603+
if (response == GTK_RESPONSE_ACCEPT) {
604+
/* New folder — keep dialog open */
605+
add_folder_button();
606+
} else if (response == GTK_RESPONSE_OK) {
607+
/* Add bookmark — close dialog */
608+
add_bookmark_button();
609+
break;
610+
} else {
611+
/* Cancel or destroy */
612+
break;
613+
}
614+
}
615+
gtk_widget_destroy(dialog);
585616
}
586617

587618
/******************************************************************************

0 commit comments

Comments
 (0)