25#include "gnc-option-gtk-ui.hpp"
32#include "gnc-account-sel.h"
34#include "gnc-commodity-edit.h"
35#include "gnc-date-edit.h"
36#include "gnc-date-format.h"
37#include "gnc-general-select.h"
41#include "misc-gnome-utils.h"
51static QofLogModule log_module = GNC_MOD_GUI;
54std::vector<WidgetCreateFunc> GncOptionUIFactory::s_registry{
static_cast<size_t>(GncOptionUIType::MAX_VALUE)};
55bool GncOptionUIFactory::s_initialized{
false};
56static void gnc_options_ui_factory_initialize (
void);
61 s_registry[
static_cast<size_t>(type)] = func;
69 gnc_options_ui_factory_initialize();
72 auto type{option.get_ui_type()};
73 auto func{s_registry[
static_cast<size_t>(type)]};
75 func(option, page, row);
77 PERR(
"No function registered for type %d",
static_cast<int>(type));
80GncOptionGtkUIItem::GncOptionGtkUIItem(GtkWidget* widget,
83 m_widget{static_cast<GtkWidget*>(g_object_ref(widget))} {}
87 m_widget{static_cast<GtkWidget*>(g_object_ref(item.get_widget()))} {}
89GncOptionGtkUIItem::~GncOptionGtkUIItem()
92 g_object_unref(m_widget);
99 gtk_widget_set_sensitive (m_widget, selectable);
106 g_object_unref(m_widget);
111GncOptionGtkUIItem::set_widget(GtkWidget* widget)
113 if (get_ui_type() == GncOptionUIType::INTERNAL)
115 std::string error{
"INTERNAL option, setting the UI item forbidden."};
116 throw std::logic_error(error);
120 g_object_unref(m_widget);
122 m_widget =
static_cast<GtkWidget*
>(g_object_ref(widget));
126GncOptionGtkUIItem::get_widget_scm_value(
const GncOption& option)
const
134static inline GtkWidget*
const
135option_get_gtk_widget(
const GncOption* option)
137 if (!option)
return nullptr;
140 return ui_item->get_widget();
146wrap_check_button (
const GncOption& option, GtkWidget* widget, GtkGrid* page_box,
int row)
148 auto enclosing{gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5)};
149 gtk_box_set_homogeneous (GTK_BOX (enclosing), FALSE);
150 gtk_box_pack_start(GTK_BOX(enclosing), widget, FALSE, FALSE, 0);
151 set_tool_tip(option, enclosing);
152 gtk_widget_show_all(enclosing);
154 grid_attach_widget (GTK_GRID(page_box), enclosing, row);
162 void set_ui_item_from_option(
GncOption& option)
noexcept override
164 auto widget{GTK_TOGGLE_BUTTON(get_widget())};
165 gtk_toggle_button_set_active(widget, option.get_value<
bool>());
167 void set_option_from_ui_item(
GncOption& option)
noexcept override
169 auto widget{GTK_TOGGLE_BUTTON(get_widget())};
170 option.set_value(
static_cast<bool>(gtk_toggle_button_get_active(widget)));
172 SCM get_widget_scm_value(
const GncOption& option)
const override
174 auto widget{GTK_TOGGLE_BUTTON(get_widget())};
175 return gtk_toggle_button_get_active(widget) ?
176 SCM_BOOL_T : SCM_BOOL_F;
181create_option_widget<GncOptionUIType::BOOLEAN> (
GncOption& option,
182 GtkGrid* page_box,
int row)
185 char *local_name{
nullptr};
186 auto name{option.get_name().c_str()};
188 local_name =
_(name);
189 auto widget{gtk_check_button_new_with_label (local_name)};
191 auto ui_item{std::make_unique<GncGtkBooleanUIItem>(widget)};
193 option.set_ui_item(std::move(ui_item));
194 option.set_ui_item_from_option();
196 g_signal_connect(G_OBJECT(widget),
"toggled",
197 G_CALLBACK(gnc_option_changed_widget_cb), &option);
199 wrap_check_button(option, widget, page_box, row);
207 void set_ui_item_from_option(
GncOption& option)
noexcept override
209 auto widget{GTK_ENTRY(get_widget())};
210 gtk_entry_set_text(widget, option.get_value<std::string>().c_str());
212 void set_option_from_ui_item(
GncOption& option)
noexcept override
214 auto widget{GTK_ENTRY(get_widget())};
215 option.set_value(std::string{gtk_entry_get_text(widget)});
220create_option_widget<GncOptionUIType::STRING> (
GncOption& option,
221 GtkGrid *page_box,
int row)
223 auto enclosing{gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5)};
224 gtk_widget_set_hexpand (GTK_WIDGET(enclosing), TRUE);
225 gtk_box_set_homogeneous (GTK_BOX (enclosing), FALSE);
226 auto widget = gtk_entry_new();
227 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
228 gtk_entry_set_alignment (GTK_ENTRY(widget), 1.0);
229 auto ui_item{std::make_unique<GncGtkStringUIItem>(widget)};
231 option.set_ui_item(std::move(ui_item));
232 option.set_ui_item_from_option();
234 g_signal_connect(G_OBJECT(widget),
"changed",
235 G_CALLBACK(gnc_option_changed_widget_cb), &option);
236 gtk_box_pack_start(GTK_BOX(enclosing), widget, TRUE, TRUE, 0);
237 set_name_label(option, page_box, row,
true);
238 set_tool_tip(option, enclosing);
239 gtk_widget_show_all(enclosing);
240 grid_attach_widget (GTK_GRID(page_box), enclosing, row);
248 void set_ui_item_from_option(
GncOption& option)
noexcept override
250 auto widget{GTK_TEXT_VIEW(get_widget())};
251 xxxgtk_textview_set_text(widget, option.get_value<std::string>().c_str());
253 void set_option_from_ui_item(
GncOption& option)
noexcept override
255 auto widget{GTK_TEXT_VIEW(get_widget())};
256 auto str{xxxgtk_textview_get_text(widget)};
257 option.set_value(std::string{str});
263create_option_widget<GncOptionUIType::TEXT> (
GncOption& option, GtkGrid *page_box,
int row)
265 auto scroll = gtk_scrolled_window_new(NULL, NULL);
266 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
268 GTK_POLICY_AUTOMATIC);
269 gtk_container_set_border_width(GTK_CONTAINER(scroll), 2);
271 auto frame = gtk_frame_new(NULL);
272 gtk_container_add(GTK_CONTAINER(frame), scroll);
274 auto enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
275 gtk_widget_set_vexpand (GTK_WIDGET(enclosing), TRUE);
276 gtk_widget_set_hexpand (GTK_WIDGET(enclosing), TRUE);
277 gtk_box_set_homogeneous (GTK_BOX (enclosing), FALSE);
278 auto widget = gtk_text_view_new();
279 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(widget), GTK_WRAP_WORD);
280 gtk_widget_set_size_request(widget, 400, -1);
281 gtk_text_view_set_editable(GTK_TEXT_VIEW(widget), TRUE);
282 gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW(widget), FALSE);
284 auto ui_item{std::make_unique<GncGtkTextUIItem>(widget)};
285 auto text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
286 option.set_ui_item(std::move(ui_item));
287 option.set_ui_item_from_option();
289 g_signal_connect(G_OBJECT(text_buffer),
"changed",
290 G_CALLBACK(gnc_option_changed_option_cb), &option);
291 gtk_container_add (GTK_CONTAINER (scroll), widget);
292 gtk_box_pack_start(GTK_BOX(enclosing), frame, TRUE, TRUE, 0);
293 set_name_label(option, page_box, row,
true);
294 set_tool_tip(option, enclosing);
295 gtk_widget_show_all(enclosing);
296 grid_attach_widget(GTK_GRID(page_box), enclosing, row);
304 void set_ui_item_from_option(
GncOption& option)
noexcept override
306 auto widget{GNC_CURRENCY_EDIT(get_widget())};
307 auto currency{option.get_value<gnc_commodity*>()};
312 void set_option_from_ui_item(
GncOption& option)
noexcept override
314 auto widget{GNC_CURRENCY_EDIT(get_widget())};
316 option.set_value<gnc_commodity*>(currency);
321create_option_widget<GncOptionUIType::CURRENCY> (
GncOption& option, GtkGrid *page_box,
325 auto ui_item{std::make_unique<GncGtkCurrencyUIItem>(widget)};
326 option.set_ui_item(std::move(ui_item));
327 option.set_ui_item_from_option();
329 g_signal_connect(G_OBJECT(widget),
"changed",
330 G_CALLBACK(gnc_option_changed_widget_cb), &option);
331 wrap_widget(option, widget, page_box, row);
339 void set_ui_item_from_option(
GncOption& option)
noexcept override
341 auto widget{GNC_GENERAL_SELECT(get_widget())};
342 auto commodity{option.get_value<gnc_commodity*>()};
345 gnc_general_select_set_selected(widget, GNC_COMMODITY(commodity));
347 void set_option_from_ui_item(
GncOption& option)
noexcept override
349 auto widget{GNC_GENERAL_SELECT(get_widget())};
350 auto commodity{gnc_general_select_get_selected(widget)};
351 option.set_value<gnc_commodity*>(GNC_COMMODITY(commodity));
356create_option_widget<GncOptionUIType::COMMODITY> (
GncOption& option, GtkGrid *page_box,
359 auto widget = gnc_general_select_new(GNC_GENERAL_SELECT_TYPE_SELECT,
360 gnc_commodity_edit_get_string,
361 gnc_commodity_edit_new_select,
364 auto ui_item{std::make_unique<GncGtkCommodityUIItem>(widget)};
365 option.set_ui_item(std::move(ui_item));
366 option.set_ui_item_from_option();
367 g_signal_connect(G_OBJECT(GNC_GENERAL_SELECT(widget)->entry),
"changed",
368 G_CALLBACK(gnc_option_changed_widget_cb), &option);
369 wrap_widget(option, widget, page_box, row);
373create_multichoice_widget(
GncOption& option)
377 g_return_val_if_fail(num_values >= 0, NULL);
378 auto renderer = gtk_cell_renderer_text_new();
379 auto store = gtk_list_store_new(1, G_TYPE_STRING);
381 for (
decltype(num_values) i = 0; i < num_values; i++)
385 gtk_list_store_append (store, &iter);
386 gtk_list_store_set(store, &iter, 0,
387 (itemstring && *itemstring) ?
_(itemstring) :
"", -1);
390 auto widget{GTK_WIDGET(gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)))};
391 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(widget), renderer, TRUE);
392 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(widget),
393 renderer,
"text", 0);
394 g_object_unref(store);
404 void set_ui_item_from_option(
GncOption& option)
noexcept override
406 auto widget{GTK_COMBO_BOX(get_widget())};
407 gtk_combo_box_set_active(widget, option.get_value<uint16_t>());
409 void set_option_from_ui_item(
GncOption& option)
noexcept override
411 auto widget{GTK_COMBO_BOX(get_widget())};
412 option.set_value<uint16_t>(
static_cast<uint16_t
>(gtk_combo_box_get_active(widget)));
414 SCM get_widget_scm_value(
const GncOption& option)
const override
416 auto widget{GTK_COMBO_BOX(get_widget())};
417 auto id{gtk_combo_box_get_active(widget)};
419 return scm_from_utf8_symbol(value);
424create_option_widget<GncOptionUIType::MULTICHOICE> (
GncOption& option, GtkGrid *page_box,
427 auto widget{create_multichoice_widget(option)};
428 auto ui_item{std::make_unique<GncGtkMultichoiceUIItem>(widget)};
429 option.set_ui_item(std::move(ui_item));
430 option.set_ui_item_from_option();
431 g_signal_connect(G_OBJECT(widget),
"changed",
432 G_CALLBACK(gnc_option_changed_widget_cb), &option);
433 wrap_widget(option, widget, page_box, row);
442 virtual void set_entry_from_option(
GncOption& option) = 0;
443 virtual void set_option_from_entry(
GncOption& option) = 0;
445 virtual GtkWidget* get_entry() = 0;
447 virtual GtkWidget* get_widget() = 0;
448 virtual void toggle_relative(
bool) {}
449 virtual void block_signals(
bool) = 0;
453using GncDateEntryPtr = std::unique_ptr<GncDateEntry>;
460 void set_entry_from_option(
GncOption& option)
override;
461 void set_option_from_entry(
GncOption& option)
override;
462 GtkWidget* get_entry()
override {
return GTK_WIDGET(m_entry); }
463 GtkWidget* get_widget()
override {
return GTK_WIDGET(m_entry); }
464 void block_signals(
bool)
override;
467 unsigned long m_handler_id;
470AbsoluteDateEntry::AbsoluteDateEntry(
GncOption& option) :
471 m_entry{GNC_DATE_EDIT(gnc_date_edit_new(time(NULL), FALSE, FALSE))}
473 auto entry = GNC_DATE_EDIT(m_entry)->date_entry;
474 m_handler_id = g_signal_connect(G_OBJECT(entry),
"changed",
475 G_CALLBACK(gnc_option_changed_option_cb),
480AbsoluteDateEntry::block_signals(
bool block)
482 auto entry{G_OBJECT(GNC_DATE_EDIT(m_entry)->date_entry)};
484 g_signal_handler_block(entry, m_handler_id);
486 g_signal_handler_unblock(entry, m_handler_id);
490AbsoluteDateEntry::set_entry_from_option(
GncOption& option)
492 gnc_date_edit_set_time(m_entry, option.get_value<
time64>());
496AbsoluteDateEntry::set_option_from_entry(
GncOption& option)
498 option.set_value<
time64>(gnc_date_edit_get_date(m_entry));
506 void set_entry_from_option(
GncOption& option)
override;
507 void set_option_from_entry(
GncOption& option)
override;
508 GtkWidget* get_widget()
override {
return m_entry; }
509 GtkWidget* get_entry()
override {
return m_entry; }
510 void block_signals(
bool)
override;
513 unsigned long m_handler_id;
517RelativeDateEntry::RelativeDateEntry(
GncOption& option)
520 auto renderer = gtk_cell_renderer_text_new();
521 auto store = gtk_list_store_new(1, G_TYPE_STRING);
524 for (
decltype(num) index = 0; index < num; ++index)
527 gtk_list_store_append (store, &iter);
528 gtk_list_store_set (store, &iter, 0,
533 m_entry = GTK_WIDGET(gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)));
534 gtk_combo_box_set_active(GTK_COMBO_BOX(m_entry), 0);
535 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(m_entry), renderer, TRUE);
536 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(m_entry),
537 renderer,
"text", 0);
539 g_object_unref(store);
541 m_handler_id = g_signal_connect(G_OBJECT(m_entry),
"changed",
542 G_CALLBACK(gnc_option_changed_widget_cb),
547RelativeDateEntry::set_entry_from_option(
GncOption& option)
549 gtk_combo_box_set_active(GTK_COMBO_BOX(m_entry), option.get_value<uint16_t>());
553RelativeDateEntry::set_option_from_entry(
GncOption& option)
555 option.set_value<uint16_t>(gtk_combo_box_get_active(GTK_COMBO_BOX(m_entry)));
559RelativeDateEntry::block_signals(
bool block)
562 g_signal_handler_block(m_entry, m_handler_id);
564 g_signal_handler_unblock(m_entry, m_handler_id);
567using AbsoluteDateEntryPtr = std::unique_ptr<AbsoluteDateEntry>;
568using RelativeDateEntryPtr = std::unique_ptr<RelativeDateEntry>;
575 void set_entry_from_option(
GncOption& option)
override;
576 void set_option_from_entry(
GncOption& option)
override;
577 GtkWidget* get_widget()
override {
return m_widget; }
578 GtkWidget* get_entry()
override;
579 void toggle_relative(
bool use_absolute)
override;
580 void block_signals(
bool)
override;
583 GtkWidget* m_abs_button;
584 AbsoluteDateEntryPtr m_abs_entry;
585 GtkWidget* m_rel_button;
586 RelativeDateEntryPtr m_rel_entry;
587 bool m_use_absolute =
true;
588 unsigned long m_abs_hdlr;
589 unsigned long m_rel_hdlr;
592static void date_set_absolute_cb(GtkWidget *widget, gpointer data1);
593static void date_set_relative_cb(GtkWidget *widget, gpointer data1);
595BothDateEntry::BothDateEntry(
GncOption& option) :
596 m_widget{gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5)},
597 m_abs_button{gtk_radio_button_new(NULL)},
600 gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(m_abs_button))},
603 gtk_box_set_homogeneous (GTK_BOX(m_widget), FALSE);
604 m_abs_hdlr = g_signal_connect(G_OBJECT(m_abs_button),
"toggled",
605 G_CALLBACK(date_set_absolute_cb), &option);
606 m_rel_hdlr = g_signal_connect(G_OBJECT(m_rel_button),
"toggled",
607 G_CALLBACK(date_set_relative_cb), &option);
609 gtk_box_pack_start(GTK_BOX(m_widget),
610 m_abs_button, FALSE, FALSE, 0);
611 gtk_box_pack_start(GTK_BOX(m_widget),
612 m_abs_entry->get_entry(), FALSE, FALSE, 0);
613 gtk_box_pack_start(GTK_BOX(m_widget),
614 m_rel_button, FALSE, FALSE, 0);
615 gtk_box_pack_start(GTK_BOX(m_widget),
616 m_rel_entry->get_entry(), FALSE, FALSE, 0);
621BothDateEntry::get_entry()
623 return m_use_absolute ? m_abs_entry->get_entry() : m_rel_entry->get_entry();
627BothDateEntry::toggle_relative(
bool use_absolute)
629 m_use_absolute = use_absolute;
631 gtk_widget_set_sensitive(GTK_WIDGET(m_abs_entry->get_widget()),
633 gtk_widget_set_sensitive(GTK_WIDGET(m_rel_entry->get_widget()),
638BothDateEntry::set_entry_from_option(
GncOption& option)
643 m_abs_entry->set_entry_from_option(option);
645 m_rel_entry->set_entry_from_option(option);
646 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_rel_button),
648 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_abs_button),
651 toggle_relative(m_use_absolute);
655BothDateEntry::set_option_from_entry(
GncOption& option)
658 m_abs_entry->set_option_from_entry(option);
660 m_rel_entry->set_option_from_entry(option);
664BothDateEntry::block_signals(
bool block)
668 g_signal_handler_block(m_abs_button, m_abs_hdlr);
669 g_signal_handler_block(m_rel_button, m_rel_hdlr);
673 g_signal_handler_unblock(m_abs_button, m_abs_hdlr);
674 g_signal_handler_unblock(m_rel_button, m_rel_hdlr);
676 m_abs_entry->block_signals(block);
677 m_rel_entry->block_signals(block);
686 void clear_ui_item()
override { m_entry =
nullptr; }
687 void set_ui_item_from_option(
GncOption& option)
noexcept override
690 m_entry->set_entry_from_option(option);
692 void set_option_from_ui_item(
GncOption& option)
noexcept override
695 m_entry->set_option_from_entry(option);
697 GtkWidget* get_widget()
const override
699 return m_entry->get_widget();
703 GncDateEntryPtr m_entry;
707date_set_absolute_cb(GtkWidget *widget, gpointer data1)
709 GncOption* option =
static_cast<decltype(option)
>(data1);
710 auto ui_item = option->get_ui_item();
714 gnc_option_changed_option_cb(widget, option);
719date_set_relative_cb(GtkWidget *widget, gpointer data1)
721 GncOption* option =
static_cast<decltype(option)
>(data1);
722 auto ui_item = option->get_ui_item();
726 gnc_option_changed_option_cb(widget, option);
731create_date_option_widget(
GncOption& option, GtkGrid *page_box,
int row)
733 GtkWidget *enclosing{
nullptr};
734 auto type = option.get_ui_type();
737 case GncOptionUIType::DATE_ABSOLUTE:
738 option.set_ui_item(std::make_unique<GncOptionDateUIItem>(std::make_unique<AbsoluteDateEntry>(option), type));
740 case GncOptionUIType::DATE_RELATIVE:
741 option.set_ui_item(std::make_unique<GncOptionDateUIItem>(std::make_unique<RelativeDateEntry>(option), type));
743 case GncOptionUIType::DATE_BOTH:
744 option.set_ui_item(std::make_unique<GncOptionDateUIItem>(std::make_unique<BothDateEntry>(option), type));
747 PERR(
"Attempted to create date option widget with wrong UI type %d",
748 static_cast<int>(type));
752 auto widget{option_get_gtk_widget(&option)};
753 if (type == GncOptionUIType::DATE_RELATIVE)
755 enclosing = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
756 gtk_box_set_homogeneous(GTK_BOX (enclosing), FALSE);
758 gtk_box_pack_start(GTK_BOX(enclosing), widget, FALSE, FALSE, 0);
762 enclosing = gtk_frame_new(
nullptr);
763 g_object_set(G_OBJECT(widget),
"margin", 3, NULL);
765 gtk_container_add (GTK_CONTAINER(enclosing), widget);
768 gtk_widget_set_halign (GTK_WIDGET(enclosing), GTK_ALIGN_START);
769 set_name_label(option, page_box, row,
false);
770 set_tool_tip(option, enclosing);
771 grid_attach_widget (GTK_GRID(page_box), enclosing, row);
774 if (
auto date_ui{ui_item ? ui_item->get_entry() :
nullptr})
776 date_ui->block_signals(
true);
777 date_ui->set_entry_from_option(option);
778 date_ui->block_signals(
false);
781 gtk_widget_show_all(enclosing);
785create_option_widget<GncOptionUIType::DATE_ABSOLUTE>(
GncOption& option,
786 GtkGrid *page_box,
int row)
788 create_date_option_widget(option, page_box, row);
792create_option_widget<GncOptionUIType::DATE_RELATIVE>(
GncOption& option,
793 GtkGrid *page_box,
int row)
795 create_date_option_widget(option, page_box, row);
799create_option_widget<GncOptionUIType::DATE_BOTH>(
GncOption& option,
800 GtkGrid *page_box,
int row)
802 create_date_option_widget(option, page_box, row);
805using GncOptionAccountList = std::vector<GncGUID>;
808account_select_all_cb(GtkWidget *widget, gpointer data)
810 GncOption* option =
static_cast<decltype(option)
>(data);
811 GncTreeViewAccount *tree_view;
812 GtkTreeSelection *selection;
814 tree_view = GNC_TREE_VIEW_ACCOUNT(option_get_gtk_widget (option));
815 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_view));
816 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
817 gtk_tree_selection_select_all(selection);
818 gnc_option_changed_widget_cb(widget, option);
822account_clear_all_cb(GtkWidget *widget, gpointer data)
824 GncOption* option =
static_cast<decltype(option)
>(data);
825 GncTreeViewAccount *tree_view;
826 GtkTreeSelection *selection;
828 tree_view = GNC_TREE_VIEW_ACCOUNT(option_get_gtk_widget (option));
829 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
830 gtk_tree_selection_unselect_all(selection);
831 gnc_option_changed_widget_cb(widget, option);
835account_select_children_cb(GtkWidget *widget, gpointer data)
837 GncOption* option =
static_cast<decltype(option)
>(data);
838 GncTreeViewAccount *tree_view;
839 GList *acct_list = NULL, *acct_iter = NULL;
841 tree_view = GNC_TREE_VIEW_ACCOUNT(option_get_gtk_widget (option));
844 for (acct_iter = acct_list; acct_iter; acct_iter = acct_iter->next)
847 g_list_free (acct_list);
851account_set_default_cb(GtkWidget* widget, gpointer data)
853 GncOption* option =
static_cast<decltype(option)
>(data);
854 account_clear_all_cb(widget, data);
855 option->set_value(option->get_default_value<GncOptionAccountList>());
856 option->set_ui_item_from_option();
860show_hidden_toggled_cb(GtkWidget *widget,
GncOption* option)
862 if (option->get_ui_type() != GncOptionUIType::ACCOUNT_LIST &&
863 option->get_ui_type() != GncOptionUIType::ACCOUNT_SEL)
866 auto tree_view = GNC_TREE_VIEW_ACCOUNT(option_get_gtk_widget(option));
869 avi.show_hidden = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
871 gnc_option_changed_widget_cb(widget, option);
879 void set_ui_item_from_option(
GncOption& option)
noexcept override
881 auto widget{GNC_TREE_VIEW_ACCOUNT(get_widget())};
882 GList *acc_list =
nullptr;
883 const GncOptionAccountList& accounts =
884 option.get_value<GncOptionAccountList>();
885 auto book{gnc_get_current_book()};
886 for (
auto guid : accounts)
889 acc_list = g_list_prepend(acc_list, account);
891 acc_list = g_list_reverse(acc_list);
893 g_list_free(acc_list);
895 void set_option_from_ui_item(
GncOption& option)
noexcept override
897 auto widget{GNC_TREE_VIEW_ACCOUNT(get_widget())};
899 GncOptionAccountList acc_vec;
900 acc_vec.reserve(g_list_length(acc_list));
901 for (
auto node = acc_list; node; node = g_list_next(node))
904 acc_vec.push_back(*guid);
906 g_list_free(acc_list);
907 option.set_value(acc_vec);
912create_account_widget(
GncOption& option,
char *name)
914 bool multiple_selection;
915 GtkWidget *scroll_win;
921 GList *acct_type_list;
922 GtkTreeSelection *selection;
927 frame = gtk_frame_new(name);
929 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
930 gtk_box_set_homogeneous (GTK_BOX (vbox), FALSE);
932 gtk_container_add(GTK_CONTAINER(frame), vbox);
935 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(tree), FALSE);
936 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
937 if (multiple_selection)
938 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
940 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
951 avi.include_type[i] = FALSE;
952 avi.show_hidden = TRUE;
954 for (node = acct_type_list; node; node = node->next)
956 GNCAccountType type =
static_cast<decltype(type)
>(GPOINTER_TO_INT (node->data));
958 avi.include_type[type] = TRUE;
962 g_list_free (acct_type_list);
972 avi.include_type[i] = TRUE;
973 avi.show_hidden = TRUE;
977 scroll_win = gtk_scrolled_window_new(NULL, NULL);
978 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
979 GTK_POLICY_AUTOMATIC,
980 GTK_POLICY_AUTOMATIC);
982 gtk_box_pack_start(GTK_BOX(vbox), scroll_win, TRUE, TRUE, 0);
983 gtk_container_set_border_width(GTK_CONTAINER(scroll_win), 5);
985 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
986 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD);
987 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 10);
989 option.set_ui_item(std::make_unique<GncGtkAccountListUIItem>(tree));
990 option.set_ui_item_from_option();
992 if (multiple_selection)
994 button = gtk_button_new_with_label(
_(
"Select All"));
995 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
996 gtk_widget_set_tooltip_text(button,
_(
"Select all accounts."));
998 g_signal_connect(G_OBJECT(button),
"clicked",
999 G_CALLBACK(account_select_all_cb), &option);
1001 button = gtk_button_new_with_label(
_(
"Clear All"));
1002 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1003 gtk_widget_set_tooltip_text(button,
_(
"Clear the selection and unselect all accounts."));
1005 g_signal_connect(G_OBJECT(button),
"clicked",
1006 G_CALLBACK(account_clear_all_cb), &option);
1008 button = gtk_button_new_with_label(
_(
"Select Children"));
1009 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1010 gtk_widget_set_tooltip_text(button,
_(
"Select all descendents of selected account."));
1012 g_signal_connect(G_OBJECT(button),
"clicked",
1013 G_CALLBACK(account_select_children_cb), &option);
1016 button = gtk_button_new_with_label(
_(
"Select Default"));
1017 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1018 gtk_widget_set_tooltip_text(button,
_(
"Select the default account selection."));
1020 g_signal_connect(G_OBJECT(button),
"clicked",
1021 G_CALLBACK(account_set_default_cb), &option);
1023 gtk_widget_set_margin_start (GTK_WIDGET(bbox), 6);
1024 gtk_widget_set_margin_end (GTK_WIDGET(bbox), 6);
1026 if (multiple_selection)
1030 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1031 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
1032 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1035 button = gtk_check_button_new_with_label(
_(
"Show Hidden Accounts"));
1036 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1037 gtk_widget_set_tooltip_text(button,
_(
"Show accounts that have been marked hidden."));
1038 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
1039 g_signal_connect(G_OBJECT(button),
"toggled",
1040 G_CALLBACK(show_hidden_toggled_cb), &option);
1042 gtk_container_add(GTK_CONTAINER(scroll_win), tree);
1047option_account_sel_changed_cb(GtkTreeSelection *sel, gpointer data)
1049 auto tree_view{gtk_tree_selection_get_tree_view(sel)};
1050 gnc_option_changed_widget_cb(GTK_WIDGET(tree_view),
1055create_option_widget<GncOptionUIType::ACCOUNT_LIST>(
GncOption& option,
1056 GtkGrid *page_box,
int row)
1058 auto enclosing{create_account_widget(option,
nullptr)};
1059 gtk_widget_set_vexpand (GTK_WIDGET(enclosing), TRUE);
1060 gtk_widget_set_hexpand (GTK_WIDGET(enclosing), TRUE);
1061 set_name_label(option, page_box, row,
true);
1062 set_tool_tip(option, enclosing);
1063 grid_attach_widget (GTK_GRID(page_box), enclosing, row);
1065 auto widget{option_get_gtk_widget(&option)};
1066 auto selection{gtk_tree_view_get_selection(GTK_TREE_VIEW(widget))};
1067 g_signal_connect(G_OBJECT(selection),
"changed",
1068 G_CALLBACK(option_account_sel_changed_cb), &option);
1069 gtk_widget_show_all(enclosing);
1077 void set_ui_item_from_option(
GncOption& option)
noexcept override
1079 auto widget{GNC_ACCOUNT_SEL(get_widget())};
1080 auto instance{option.get_value<
const Account*>()};
1082 gnc_account_sel_set_account(widget,
const_cast<Account*
>(instance), FALSE);
1084 void set_option_from_ui_item(
GncOption& option)
noexcept override
1086 auto widget{GNC_ACCOUNT_SEL(get_widget())};
1088 option.set_value(
static_cast<const Account*
>(gnc_account_sel_get_account(widget)));
1093create_option_widget<GncOptionUIType::ACCOUNT_SEL> (
GncOption& option,
1094 GtkGrid *page_box,
int row)
1097 auto widget{gnc_account_sel_new()};
1098 gnc_account_sel_set_acct_filters(GNC_ACCOUNT_SEL(widget),
1099 acct_type_list, NULL);
1100 g_list_free(acct_type_list);
1103 option.set_ui_item(std::make_unique<GncGtkAccountSelUIItem>(widget));
1104 option.set_ui_item_from_option();
1106 g_signal_connect(widget,
"account_sel_changed",
1107 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1108 wrap_widget(option, widget, page_box, row);
1110 gtk_container_child_set(GTK_CONTAINER(gtk_widget_get_parent(widget)),
1111 widget,
"fill", TRUE,
"expand", TRUE,
1116list_changed_cb(GtkTreeSelection *selection,
GncOption* option)
1118 GtkTreeView *view = GTK_TREE_VIEW(option_get_gtk_widget (option));
1119 gnc_option_changed_widget_cb(GTK_WIDGET(view), option);
1123list_select_all_cb(GtkWidget *widget, gpointer data)
1125 GncOption* option =
static_cast<decltype(option)
>(data);
1127 GtkTreeSelection *selection;
1129 view = GTK_TREE_VIEW(option_get_gtk_widget(option));
1130 selection = gtk_tree_view_get_selection(view);
1131 gtk_tree_selection_select_all(selection);
1132 gnc_option_changed_widget_cb(GTK_WIDGET(view), option);
1136list_clear_all_cb(GtkWidget *widget, gpointer data)
1138 GncOption* option =
static_cast<decltype(option)
>(data);
1140 GtkTreeSelection *selection;
1142 view = GTK_TREE_VIEW(option_get_gtk_widget(option));
1143 selection = gtk_tree_view_get_selection(view);
1144 gtk_tree_selection_unselect_all(selection);
1145 gnc_option_changed_widget_cb(GTK_WIDGET(view), option);
1149list_set_default_cb(GtkWidget *widget, gpointer data)
1151 GncOption* option =
static_cast<decltype(option)
>(data);
1152 list_clear_all_cb(widget, data);
1153 option->set_value(option->get_default_value<GncMultichoiceOptionIndexVec>());
1154 option->set_ui_item_from_option();
1163 void set_ui_item_from_option(
GncOption& option)
noexcept override
1165 auto widget{GTK_TREE_VIEW(get_widget())};
1166 auto selection{gtk_tree_view_get_selection(widget)};
1167 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
1168 g_signal_handlers_block_by_func(selection, (gpointer)list_changed_cb, &option);
1169 gtk_tree_selection_unselect_all(selection);
1170 for (
auto index : option.get_value<GncMultichoiceOptionIndexVec>())
1172 auto path{gtk_tree_path_new_from_indices(index, -1)};
1173 gtk_tree_selection_select_path(selection, path);
1174 gtk_tree_path_free(path);
1176 g_signal_handlers_unblock_by_func(selection, (gpointer)list_changed_cb, &option);
1179 void set_option_from_ui_item(
GncOption& option)
noexcept override
1181 auto widget{GTK_TREE_VIEW(get_widget())};
1182 auto selection{gtk_tree_view_get_selection(widget)};
1183 auto selected_rows{gtk_tree_selection_get_selected_rows(selection,
nullptr)};
1184 GncMultichoiceOptionIndexVec vec;
1185 for (
auto row = selected_rows; row; row = g_list_next(row))
1187 auto path{
static_cast<GtkTreePath*
>(row->data)};
1188 auto indices{gtk_tree_path_get_indices(path)};
1189 vec.push_back(*indices);
1191 g_list_free_full(selected_rows, (GDestroyNotify)gtk_tree_path_free);
1192 option.set_value(vec);
1197create_list_widget(
GncOption& option,
char *name)
1199 auto frame = gtk_frame_new(name);
1200 auto hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1201 gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
1202 gtk_container_add(GTK_CONTAINER(frame), hbox);
1204 auto store = gtk_list_store_new(1, G_TYPE_STRING);
1205 auto view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)));
1206 g_object_unref(store);
1207 auto renderer = gtk_cell_renderer_text_new();
1208 auto column = gtk_tree_view_column_new_with_attributes(
"", renderer,
1211 gtk_tree_view_append_column(view, column);
1212 gtk_tree_view_set_headers_visible(view, FALSE);
1215 for (
decltype(num_values) i = 0; i < num_values; i++)
1219 auto string = (raw_string && *raw_string) ? _(raw_string) :
"";
1220 gtk_list_store_append(store, &iter);
1221 gtk_list_store_set(store, &iter, 0,
string ?
string :
"", -1);
1224 option.set_ui_item(std::make_unique<GncGtkListUIItem>(GTK_WIDGET(view)));
1225 option.set_ui_item_from_option();
1227 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(view), FALSE, FALSE, 0);
1229 auto selection = gtk_tree_view_get_selection(view);
1230 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
1231 g_signal_connect(selection,
"changed",
1232 G_CALLBACK(list_changed_cb), &option);
1234 auto bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
1235 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD);
1236 gtk_box_pack_end(GTK_BOX(hbox), bbox, FALSE, FALSE, 0);
1238 auto button = gtk_button_new_with_label(
_(
"Select All"));
1239 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1240 gtk_widget_set_tooltip_text(button,
_(
"Select all entries."));
1242 g_signal_connect(G_OBJECT(button),
"clicked",
1243 G_CALLBACK(list_select_all_cb), &option);
1245 button = gtk_button_new_with_label(
_(
"Clear All"));
1246 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1247 gtk_widget_set_tooltip_text(button,
_(
"Clear the selection and unselect all entries."));
1249 g_signal_connect(G_OBJECT(button),
"clicked",
1250 G_CALLBACK(list_clear_all_cb), &option);
1252 button = gtk_button_new_with_label(
_(
"Select Default"));
1253 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1254 gtk_widget_set_tooltip_text(button,
_(
"Select the default selection."));
1256 g_signal_connect(G_OBJECT(button),
"clicked",
1257 G_CALLBACK(list_set_default_cb), &option);
1259 g_object_set (G_OBJECT(hbox),
"margin", 3, NULL);
1265create_option_widget<GncOptionUIType::LIST> (
GncOption& option,
1266 GtkGrid *page_box,
int row)
1269 auto enclosing{create_list_widget(option,
nullptr)};
1270 set_name_label(option, page_box, row,
true);
1271 set_tool_tip(option, enclosing);
1272 grid_attach_widget (GTK_GRID(page_box), enclosing, row);
1273 gtk_widget_show(enclosing);
1281 void set_ui_item_from_option(
GncOption& option)
noexcept override
1284 if (option.is_alternate())
1285 value =
static_cast<double>(option.get_value<
int>());
1287 value = option.get_value<
double>();
1289 gtk_spin_button_set_value(GTK_SPIN_BUTTON(get_widget()), value);
1291 void set_option_from_ui_item(
GncOption& option)
noexcept override
1293 auto value{gtk_spin_button_get_value(GTK_SPIN_BUTTON(get_widget()))};
1294 if (option.is_alternate())
1295 option.set_value<
int>(
static_cast<int>(value));
1297 option.set_value<
double>(value);
1306static GtkSpinButton*
1309 gdouble lower_bound = G_MINDOUBLE;
1310 gdouble upper_bound = G_MAXDOUBLE;
1311 gdouble step_size = 1.0;
1313 if (option.is_alternate())
1315 int tmp_lower_bound = G_MININT;
1316 int tmp_upper_bound = G_MAXINT;
1317 int tmp_step_size = 1.0;
1318 option.
get_limits<
int>(tmp_upper_bound, tmp_lower_bound, tmp_step_size);
1319 lower_bound =(double)tmp_lower_bound;
1320 upper_bound = (double)tmp_upper_bound;
1321 step_size = (double)tmp_step_size;
1324 option.
get_limits<
double>(upper_bound, lower_bound, step_size);
1326 auto adj = GTK_ADJUSTMENT(gtk_adjustment_new(lower_bound, lower_bound,
1327 upper_bound, step_size,
1331 size_t num_decimals = 0;
1332 for (
auto steps = step_size; steps < 1; steps *= 10)
1334 auto widget = gtk_spin_button_new(adj, step_size, num_decimals);
1335 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
1337 size_t num_digits = 0;
1338 for (
auto bigger = MAX(ABS(lower_bound), ABS(upper_bound));
1339 bigger >= 1; bigger /= 10.0)
1341 num_digits += num_decimals;
1342 gtk_entry_set_width_chars(GTK_ENTRY(widget), num_digits);
1343 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
1345 return GTK_SPIN_BUTTON(widget);
1349create_option_widget<GncOptionUIType::NUMBER_RANGE> (
GncOption& option,
1350 GtkGrid *page_box,
int row)
1352 auto widget{create_range_spinner(option)};
1353 option.set_ui_item(std::make_unique<GncGtkNumberRangeUIItem>(GTK_WIDGET(widget)));
1354 option.set_ui_item_from_option();
1356 g_signal_connect(G_OBJECT(widget),
"changed",
1357 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1358 wrap_widget(option, GTK_WIDGET(widget), page_box, row);
1366 void set_ui_item_from_option(
GncOption& option)
noexcept override
1373 auto value{option.get_value<std::string>().substr(0,6)};
1374 auto rgba_str{g_strdup_printf(
"#%s", value.c_str())};
1375 if (gdk_rgba_parse(&color, rgba_str))
1377 auto color_button = GTK_COLOR_CHOOSER(get_widget());
1378 gtk_color_chooser_set_rgba(color_button, &color);
1382 void set_option_from_ui_item(
GncOption& option)
noexcept override
1385 auto color_button = GTK_COLOR_CHOOSER(get_widget());
1386 gtk_color_chooser_get_rgba(color_button, &color);
1387 auto rgba_str = g_strdup_printf(
"%2x%2x%2x%2x",
1388 (uint8_t)(color.red * 255),
1389 (uint8_t)(color.green * 255),
1390 (uint8_t)(color.blue * 255),
1391 (uint8_t)(color.alpha * 255));
1392 auto rgb_str = g_strdup_printf(
"%2x%2x%2x",
1393 (uint8_t)(color.red * 255),
1394 (uint8_t)(color.green * 255),
1395 (uint8_t)(color.blue * 255));
1397 option.set_value(std::string{rgb_str});
1404create_option_widget<GncOptionUIType::COLOR> (
GncOption& option, GtkGrid *page_box,
int row)
1406 auto widget = gtk_color_button_new();
1407 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(widget), TRUE);
1409 option.set_ui_item(std::make_unique<GncGtkColorUIItem>(widget));
1410 option.set_ui_item_from_option();
1412 g_signal_connect(G_OBJECT(widget),
"color-set",
1413 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1414 wrap_widget(option, widget, page_box, row);
1422 void set_ui_item_from_option(
GncOption& option)
noexcept override
1424 GtkFontChooser *font_chooser = GTK_FONT_CHOOSER(get_widget());
1425 gtk_font_chooser_set_font(font_chooser,
1426 option.get_value<std::string>().c_str());
1429 void set_option_from_ui_item(
GncOption& option)
noexcept override
1431 GtkFontChooser *font_chooser = GTK_FONT_CHOOSER(get_widget());
1432 option.set_value(std::string{gtk_font_chooser_get_font(font_chooser)});
1437create_option_widget<GncOptionUIType::FONT> (
GncOption& option, GtkGrid *page_box,
int row)
1439 auto widget{gtk_font_button_new()};
1440 g_object_set(G_OBJECT(widget),
1446 option.set_ui_item(std::make_unique<GncGtkFontUIItem>(widget));
1447 option.set_ui_item_from_option();
1448 g_signal_connect(G_OBJECT(widget),
"font-set",
1449 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1450 wrap_widget(option, widget, page_box, row);
1453#define LAST_SELECTION "last-selection"
1456update_preview_cb (GtkFileChooser *chooser,
void* data)
1458 g_return_if_fail(chooser != NULL);
1460 ENTER(
"chooser %p", chooser);
1461 auto filename = gtk_file_chooser_get_preview_filename(chooser);
1462 DEBUG(
"chooser preview name is %s.", filename ? filename :
"(null)");
1463 if (filename == NULL)
1465 filename = g_strdup(
static_cast<const char*
>(g_object_get_data(G_OBJECT(chooser), LAST_SELECTION)));
1466 DEBUG(
"using last selection of %s", filename ? filename :
"(null)");
1467 if (filename == NULL)
1469 LEAVE(
"no usable name");
1474 auto image = GTK_IMAGE(gtk_file_chooser_get_preview_widget(chooser));
1475 auto pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL);
1477 auto have_preview = (pixbuf != NULL);
1479 gtk_image_set_from_pixbuf(image, pixbuf);
1481 g_object_unref(pixbuf);
1483 gtk_file_chooser_set_preview_widget_active(chooser, have_preview);
1484 LEAVE(
"preview visible is %d", have_preview);
1488change_image_cb (GtkFileChooser *chooser,
void* data)
1490 auto filename{gtk_file_chooser_get_preview_filename(chooser)};
1493 g_object_set_data_full(G_OBJECT(chooser), LAST_SELECTION, filename, g_free);
1501 void set_ui_item_from_option(
GncOption& option)
noexcept override
1503 auto string{option.get_value<std::string>()};
1504 if (!
string.empty())
1506 DEBUG(
"string = %s",
string.c_str());
1507 auto chooser{GTK_FILE_CHOOSER(get_widget())};
1508 gtk_file_chooser_select_filename(chooser,
string.c_str());
1509 auto filename{gtk_file_chooser_get_filename(chooser)};
1510 g_object_set_data_full(G_OBJECT(chooser), LAST_SELECTION,
1511 g_strdup(
string.c_str()), g_free);
1512 DEBUG(
"Set %s, retrieved %s",
string.c_str(),
1513 filename ? filename :
"(null)");
1514 update_preview_cb(chooser, &option);
1517 void set_option_from_ui_item(
GncOption& option)
noexcept override
1519 auto string = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(get_widget()));
1520 DEBUG(
"filename %s",
string ?
string :
"(null)");
1523 option.set_value(std::string{
string});
1530create_option_widget<GncOptionUIType::PIXMAP> (
GncOption& option,
1531 GtkGrid *page_box,
int row)
1533 auto enclosing{gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5)};
1534 gtk_box_set_homogeneous(GTK_BOX(enclosing), FALSE);
1535 auto button{gtk_button_new_with_label(
_(
"Clear"))};
1536 gtk_widget_set_tooltip_text(button,
_(
"Clear any selected image file."));
1537 auto widget{ gtk_file_chooser_button_new(
_(
"Select image"),
1538 GTK_FILE_CHOOSER_ACTION_OPEN)};
1539 gtk_widget_set_tooltip_text(widget,
_(
"Select an image file."));
1540 g_object_set(G_OBJECT(widget),
1542 "preview-widget", gtk_image_new(),
1544 option.set_ui_item(std::make_unique<GncGtkPixmapUIItem>(widget));
1545 option.set_ui_item_from_option();
1547 g_signal_connect(G_OBJECT (widget),
"selection-changed",
1548 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1549 g_signal_connect(G_OBJECT (widget),
"selection-changed",
1550 G_CALLBACK(change_image_cb), &option);
1551 g_signal_connect(G_OBJECT (widget),
"update-preview",
1552 G_CALLBACK(update_preview_cb), &option);
1553 g_signal_connect_swapped(G_OBJECT (button),
"clicked",
1554 G_CALLBACK(gtk_file_chooser_unselect_all), widget);
1556 gtk_box_pack_start(GTK_BOX(enclosing), widget, FALSE, FALSE, 0);
1557 gtk_box_pack_start(GTK_BOX(enclosing), button, FALSE, FALSE, 0);
1559 gtk_widget_show(widget);
1560 set_name_label(option, page_box, row,
false);
1561 set_tool_tip(option, enclosing);
1562 gtk_widget_show(enclosing);
1563 grid_attach_widget(page_box, enclosing, row);
1567radiobutton_set_cb(GtkWidget *w, gpointer data)
1569 GncOption* option =
static_cast<decltype(option)
>(data);
1570 gpointer _current, _new_value;
1571 gint current, new_value;
1573 auto widget = option_get_gtk_widget(option);
1575 _current = g_object_get_data(G_OBJECT(widget),
"gnc_radiobutton_index");
1576 current = GPOINTER_TO_INT (_current);
1578 _new_value = g_object_get_data (G_OBJECT(w),
"gnc_radiobutton_index");
1579 new_value = GPOINTER_TO_INT (_new_value);
1581 if (current == new_value)
1584 g_object_set_data (G_OBJECT(widget),
"gnc_radiobutton_index",
1585 GINT_TO_POINTER(new_value));
1586 gnc_option_changed_widget_cb(widget, option);
1594 void set_ui_item_from_option(
GncOption& option)
noexcept override
1596 auto index{option.get_value<uint16_t>()};
1597 auto list{gtk_container_get_children(GTK_CONTAINER(get_widget()))};
1598 auto box{GTK_WIDGET(list->data)};
1601 list = gtk_container_get_children(GTK_CONTAINER(box));
1602 auto node{g_list_nth(list, index)};
1603 GtkButton* button{};
1606 button = GTK_BUTTON(node->data);
1610 PERR(
"Invalid Radio Button Selection %hu", index);
1615 auto val{g_object_get_data (G_OBJECT (button),
1616 "gnc_radiobutton_index")};
1617 g_return_if_fail (GPOINTER_TO_UINT (val) == index);
1619 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1621 void set_option_from_ui_item(
GncOption& option)
noexcept override
1623 auto index{g_object_get_data(G_OBJECT(get_widget()),
1624 "gnc_radiobutton_index")};
1625 option.set_value<uint16_t>(GPOINTER_TO_INT(index));
1630create_radiobutton_widget(
char *name,
GncOption& option)
1632 GtkWidget *frame, *box;
1633 GtkWidget *widget = NULL;
1637 g_return_val_if_fail(num_values >= 0, NULL);
1640 frame = gtk_frame_new (name);
1643 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1644 gtk_box_set_homogeneous (GTK_BOX (box), FALSE);
1645 gtk_container_add (GTK_CONTAINER (frame), box);
1647 option.set_ui_item(std::make_unique<GncGtkPixmapUIItem>(frame));
1648 option.set_ui_item_from_option();
1651 for (
decltype(num_values) i = 0; i < num_values; i++)
1656 gtk_radio_button_new_with_label_from_widget (widget ?
1657 GTK_RADIO_BUTTON (widget) :
1659 label && *label ?
_(label) :
"");
1660 g_object_set_data (G_OBJECT (widget),
"gnc_radiobutton_index",
1661 GINT_TO_POINTER (i));
1662 g_signal_connect(G_OBJECT(widget),
"toggled",
1663 G_CALLBACK(radiobutton_set_cb), &option);
1664 gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
1671create_option_widget<GncOptionUIType::RADIOBUTTON> (
GncOption& option, GtkGrid *page_box,
int row)
1673 auto enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
1674 gtk_box_set_homogeneous (GTK_BOX (enclosing), FALSE);
1675 set_name_label(option, page_box, row,
true);
1676 set_tool_tip(option, enclosing);
1677 auto widget = create_radiobutton_widget(NULL, option);
1678 gtk_box_pack_start(GTK_BOX(enclosing), widget, FALSE, FALSE, 0);
1679 gtk_widget_show_all(enclosing);
1680 grid_attach_widget(page_box, enclosing, row);
1688 void set_ui_item_from_option(
GncOption& option)
noexcept override
1690 auto widget{GNC_DATE_FORMAT(get_widget())};
1691 auto [format, months, years, custom] = option.get_value<GncOptionDateFormat>();
1692 gnc_date_format_set_format(widget, format);
1693 gnc_date_format_set_months(widget, months);
1694 gnc_date_format_set_years(widget, years);
1695 gnc_date_format_set_custom(widget, custom.c_str());
1697 void set_option_from_ui_item(
GncOption& option)
noexcept override
1699 auto widget{GNC_DATE_FORMAT(get_widget())};
1700 GncOptionDateFormat format{
1701 gnc_date_format_get_format(widget),
1702 gnc_date_format_get_months(widget),
1703 gnc_date_format_get_years(widget),
1704 gnc_date_format_get_custom(widget)};
1705 option.set_value(format);
1711create_option_widget<GncOptionUIType::DATE_FORMAT> (
GncOption& option,
1712 GtkGrid *page_box,
int row)
1714 auto enclosing = gnc_date_format_new_without_label ();
1715 set_name_label(option, page_box, row,
true);
1716 set_tool_tip(option, enclosing);
1717 option.set_ui_item(std::make_unique<GncGtkDateFormatUIItem>(enclosing));
1718 option.set_ui_item_from_option();
1720 g_signal_connect(G_OBJECT(enclosing),
"format_changed",
1721 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1722 gtk_widget_show_all(enclosing);
1723 grid_attach_widget(page_box, enclosing, row);
1727static void plot_size_set_pixels(GtkWidget*,
PlotSize*);
1728static void plot_size_set_percent(GtkWidget*,
PlotSize*);
1732 GtkWidget *m_widget;
1733 GtkWidget *m_pixel_button;
1734 GtkWidget *m_percent_button;
1735 GtkWidget *m_range_spinner;
1736 GtkAdjustment *m_adj_pct;
1737 GtkAdjustment *m_adj_px;
1738 unsigned long m_percent_handler;
1739 unsigned long m_pixel_handler;
1743 void set_entry_from_option(
GncOption& option);
1744 void set_option_from_entry(
GncOption& option);
1745 GtkWidget* get_widget() {
return m_widget; }
1746 GtkWidget* get_spinner() {
return m_range_spinner; }
1747 void set_pixels() { gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(m_range_spinner), m_adj_px); }
1748 void set_percent() { gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(m_range_spinner), m_adj_pct); }
1752 m_widget{gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4)}, m_pixel_button{gtk_radio_button_new_with_label(nullptr, _(
"Pixels"))},
1753 m_percent_button{gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(m_pixel_button), _(
"Percent"))},
1754 m_range_spinner{GTK_WIDGET(create_range_spinner(option))},
1755 m_adj_pct{GTK_ADJUSTMENT(g_object_ref(gtk_adjustment_new(100.0, 10.0, 100.0, 1.0, 5.0, 0.0)))},
1756 m_adj_px{GTK_ADJUSTMENT(g_object_ref(gtk_adjustment_new(1000.0, 110.0, 10000.0, 10.0, 250.0, 0.0)))}
1758 gtk_box_set_homogeneous(GTK_BOX(m_widget), FALSE);
1759 g_object_set (G_OBJECT(m_widget),
"margin", 3, NULL);
1760 set_tool_tip(option, m_widget);
1761 gtk_box_pack_start(GTK_BOX(m_widget), GTK_WIDGET(m_pixel_button), FALSE, FALSE, 0);
1762 gtk_box_pack_start(GTK_BOX(m_widget), GTK_WIDGET(m_percent_button), FALSE, FALSE, 0);
1763 gtk_box_pack_start(GTK_BOX(m_widget), GTK_WIDGET(m_range_spinner),
1766 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(m_pixel_button), FALSE);
1767 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(m_percent_button), TRUE);
1769 m_pixel_handler = g_signal_connect(m_pixel_button,
"toggled", G_CALLBACK(plot_size_set_pixels),
this);
1770 m_percent_handler = g_signal_connect(m_percent_button,
"toggled", G_CALLBACK(plot_size_set_percent),
this);
1773PlotSize::~PlotSize()
1775 g_signal_handler_disconnect(m_pixel_button, m_pixel_handler);
1776 g_signal_handler_disconnect(m_percent_button, m_percent_handler);
1777 g_object_unref(m_adj_pct);
1778 g_object_unref(m_adj_px);
1782PlotSize::set_option_from_entry(
GncOption& option)
1784 auto value{gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_range_spinner))};
1785 if (option.is_alternate())
1786 option.set_value<
int>(
static_cast<int>(value));
1788 option.set_value<
double>(value);
1792PlotSize::set_entry_from_option(
GncOption& option)
1795 if (option.is_alternate())
1797 auto int_value{option.get_value<
int>()};
1798 value =
static_cast<double>(int_value);
1802 value = option.get_value<
double>();
1806 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_pixel_button), TRUE);
1808 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_percent_button), TRUE);
1810 gtk_spin_button_set_value(GTK_SPIN_BUTTON(m_range_spinner), value);
1814plot_size_set_pixels(GtkWidget *widget,
PlotSize *ps)
1820plot_size_set_percent(GtkWidget *widget,
PlotSize *ps)
1825using PlotSizePtr = std::unique_ptr<PlotSize>;
1832 m_plot_size{std::move(plot_size)} {}
1833 void set_ui_item_from_option(
GncOption& option)
noexcept override
1835 m_plot_size->set_entry_from_option(option);
1837 void set_option_from_ui_item(
GncOption& option)
noexcept override
1839 m_plot_size->set_option_from_entry(option);
1841 PlotSize* get_plot_size() {
return m_plot_size.get(); }
1843PlotSizePtr m_plot_size;
1847create_option_widget<GncOptionUIType::PLOT_SIZE> (
GncOption& option,
1848 GtkGrid *page_box,
int row)
1851 auto enclosing = gtk_frame_new(NULL);
1852 gtk_widget_set_halign (GTK_WIDGET(enclosing), GTK_ALIGN_START);
1853 set_name_label(option, page_box, row,
false);
1855 option.set_ui_item(std::make_unique<GncGtkPlotSizeUIItem>(std::make_unique<PlotSize>(option)));
1856 option.set_ui_item_from_option();
1858 auto widget{option_get_gtk_widget(&option)};
1859 gtk_container_add(GTK_CONTAINER(enclosing), widget);
1861 gtk_widget_show_all(enclosing);
1862 grid_attach_widget(page_box, enclosing, row);
1866 g_signal_connect(G_OBJECT(ui_item->get_plot_size()->get_spinner()),
"changed",
1867 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1875 GtkCellRenderer *cr;
1877 tm = gnc_tree_model_budget_new(gnc_get_current_book());
1878 cb = GTK_COMBO_BOX(gtk_combo_box_new_with_model(tm));
1880 cr = gtk_cell_renderer_text_new();
1881 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cb), cr, TRUE);
1883 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(cb), cr,
"text",
1884 BUDGET_NAME_COLUMN, NULL);
1885 return GTK_WIDGET(cb);
1893 void set_ui_item_from_option(
GncOption& option)
noexcept override
1896 auto widget{GTK_COMBO_BOX(get_widget())};
1897 auto instance{option.get_value<
const QofInstance*>()};
1900 auto tree_model{gtk_combo_box_get_model(widget)};
1901 if (gnc_tree_model_budget_get_iter_for_budget(tree_model, &iter,
1902 GNC_BUDGET(instance)))
1903 gtk_combo_box_set_active_iter(widget, &iter);
1906 void set_option_from_ui_item(
GncOption& option)
noexcept override
1909 auto widget{GTK_COMBO_BOX(get_widget())};
1910 if (gtk_combo_box_get_active_iter(widget, &iter))
1912 auto tree_model{gtk_combo_box_get_model(widget)};
1913 auto budget{gnc_tree_model_budget_get_budget(tree_model, &iter)};
1914 option.set_value(qof_instance_cast(budget));
1920create_option_widget<GncOptionUIType::BUDGET> (
GncOption& option,
1921 GtkGrid *page_box,
int row)
1923 auto widget{create_budget_widget(option)};
1925 option.set_ui_item(std::make_unique<GncGtkBudgetUIItem>(widget));
1926 option.set_ui_item_from_option();
1929 g_signal_connect(G_OBJECT(widget),
"changed",
1930 G_CALLBACK(gnc_option_changed_widget_cb), &option);
1932 wrap_widget(option, widget, page_box, row);
1936gnc_options_ui_factory_initialize(
void)
1939 create_option_widget<GncOptionUIType::BOOLEAN>);
1941 create_option_widget<GncOptionUIType::STRING>);
1943 create_option_widget<GncOptionUIType::TEXT>);
1945 create_option_widget<GncOptionUIType::CURRENCY>);
1947 create_option_widget<GncOptionUIType::COMMODITY>);
1949 create_option_widget<GncOptionUIType::MULTICHOICE>);
1951 create_option_widget<GncOptionUIType::DATE_ABSOLUTE>);
1953 create_option_widget<GncOptionUIType::DATE_RELATIVE>);
1955 create_option_widget<GncOptionUIType::DATE_BOTH>);
1957 create_option_widget<GncOptionUIType::ACCOUNT_LIST>);
1959 create_option_widget<GncOptionUIType::ACCOUNT_SEL>);
1961 create_option_widget<GncOptionUIType::LIST>);
1963 create_option_widget<GncOptionUIType::NUMBER_RANGE>);
1965 create_option_widget<GncOptionUIType::COLOR>);
1967 create_option_widget<GncOptionUIType::FONT>);
1969 create_option_widget<GncOptionUIType::PLOT_SIZE>);
1971 create_option_widget<GncOptionUIType::BUDGET>);
1973 create_option_widget<GncOptionUIType::PIXMAP>);
1975 create_option_widget<GncOptionUIType::RADIOBUTTON>);
1977 create_option_widget<GncOptionUIType::DATE_FORMAT>);
class GncOptionGtkUIItem Gtk-specific Interface class for Option Widget
virtual void set_selectable(bool) const noexcept override
Control wether the widget is sensitive.
void clear_ui_item() override
Clear the data from the widget.
static void set_func(GncOptionUIType type, WidgetCreateFunc func)
Register a WidgetCreateFunc.
static void create(GncOption &option, GtkGrid *page, int row)
Create a widget.
Holds a pointer to the UI item which will control the option and an enum representing the type of the...
Represents the public interface for an option.
Commodity handling public routines.
Currency selection widget.
All type declarations for the whole Gnucash engine.
Implementation templates and specializtions for GncOption values.
C++ Public interface for individual options.
provides some utilities for working with the list of budgets in a book.
GtkTreeView implementation for gnucash account tree.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed.
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id,...
@ NUM_ACCOUNT_TYPES
stop here; the following types just aren't ready for prime time
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
void get_limits(ValueType &, ValueType &, ValueType &) const noexcept
Implemented only for GncOptionNumericRange.
GList * account_type_list() const noexcept
Implemented only for GncOptionAccountListValue.
const char * permissible_value(uint16_t index) const
Implemented only for GncOptionMultiselectValue.
const char * permissible_value_name(uint16_t index) const
Implemented only for GncOptionMultiselectValue.
bool is_multiselect() const noexcept
uint16_t num_permissible_values() const
Implemented only for GncOptionMultiselectValue.
void gnc_currency_edit_set_currency(GNCCurrencyEdit *gce, const gnc_commodity *currency)
Set the widget to display a certain currency name.
GtkWidget * gnc_currency_edit_new(void)
Create a new GNCCurrencyEdit widget which can be used to provide an easy way to enter ISO currency co...
gnc_commodity * gnc_currency_edit_get_currency(GNCCurrencyEdit *gce)
Retrieve the displayed currency of the widget.
void gnc_tree_view_account_select_subaccounts(GncTreeViewAccount *view, Account *account)
This function selects all sub-accounts of an account in the account tree view.
GList * gnc_tree_view_account_get_selected_accounts(GncTreeViewAccount *view)
This function returns a list of the accounts associated with the selected items in the account tree v...
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
void gnc_tree_view_account_get_view_info(GncTreeViewAccount *view, AccountViewInfo *avi)
Given pointers to an account tree and old style filter block, this function will copy the current con...
void gnc_tree_view_account_set_view_info(GncTreeViewAccount *view, AccountViewInfo *avi)
Given pointers to an account tree and old style filter block, this function will applies the settings...
void gnc_tree_view_account_set_selected_accounts(GncTreeViewAccount *view, GList *account_list, gboolean show_last)
This function selects a set of accounts in the account tree view.
const GncGUID * qof_entity_get_guid(gconstpointer ent)
#define DEBUG(format, args...)
Print a debugging message.
#define LEAVE(format, args...)
Print a function exit debugging message.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
RelativeDatePeriod
Reporting periods relative to the current date.
GncOptionUIType
Used by GncOptionClassifier to indicate to dialog-options what control should be displayed for the op...