4
using TeeJee.FileSystem;
5
using TeeJee.JsonHelper;
6
using TeeJee.ProcessHelper;
10
namespace TeeJee.GtkHelper{
14
// messages -----------
16
public void show_err_log(Gtk.Window parent, bool disable_log = true){
17
if ((err_log != null) && (err_log.length > 0)){
18
gtk_messagebox(_("Error"), err_log, parent, true);
26
public void gtk_do_events (){
28
/* Do pending events */
30
while(Gtk.events_pending ())
31
Gtk.main_iteration ();
34
public void gtk_set_busy (bool busy, Gtk.Window win) {
36
/* Show or hide busy cursor on window */
38
Gdk.Cursor? cursor = null;
41
cursor = new Gdk.Cursor(Gdk.CursorType.WATCH);
44
cursor = new Gdk.Cursor(Gdk.CursorType.ARROW);
47
var window = win.get_window ();
50
window.set_cursor (cursor);
56
public void gtk_messagebox(
57
string title, string message, Gtk.Window? parent_win, bool is_error = false){
59
/* Shows a simple message box */
61
var type = Gtk.MessageType.INFO;
63
type = Gtk.MessageType.ERROR;
66
type = Gtk.MessageType.INFO;
69
/*var dlg = new Gtk.MessageDialog.with_markup(null, Gtk.DialogFlags.MODAL, type, Gtk.ButtonsType.OK, message);
71
dlg.set_default_size (200, -1);
72
if (parent_win != null){
73
dlg.set_transient_for(parent_win);
79
var dlg = new CustomMessageDialog(title,message,type,parent_win, Gtk.ButtonsType.OK);
84
public string? gtk_inputbox(
85
string title, string message, Gtk.Window? parent_win, bool mask_password = false){
87
/* Shows a simple input prompt */
90
Gtk.Box vbox_main = new Box (Orientation.VERTICAL, 0);
94
Gtk.Label lbl_input = new Gtk.Label(title);
95
lbl_input.xalign = (float) 0.0;
96
lbl_input.label = message;
99
Gtk.Entry txt_input = new Gtk.Entry();
100
txt_input.margin_top = 3;
101
txt_input.set_visibility(false);
104
var dlg = new Gtk.Dialog.with_buttons(title, parent_win, DialogFlags.MODAL);
106
dlg.set_default_size (300, -1);
107
if (parent_win != null){
108
dlg.set_transient_for(parent_win);
113
var content = (Box) dlg.get_content_area ();
114
vbox_main.pack_start (lbl_input, false, true, 0);
115
vbox_main.pack_start (txt_input, false, true, 0);
116
content.add(vbox_main);
120
var actions = (Box) dlg.get_action_area ();
121
dlg.add_button(_("OK"),Gtk.ResponseType.OK);
122
dlg.add_button(_("Cancel"),Gtk.ResponseType.CANCEL);
123
//actions.margin = 6;
124
actions.margin_top = 12;
127
txt_input.key_press_event.connect ((w, event) => {
128
if (event.keyval == 65293) {
129
dlg.response(Gtk.ResponseType.OK);
136
int response = dlg.run();
137
string input_text = txt_input.text;
140
if (response == Gtk.ResponseType.CANCEL){
151
public bool gtk_combobox_set_value (ComboBox combo, int index, string val){
153
/* Conveniance function to set combobox value */
157
TreeModel model = (TreeModel) combo.model;
159
bool iterExists = model.get_iter_first (out iter);
161
model.get(iter, 1, out comboVal);
162
if (comboVal == val){
163
combo.set_active_iter(iter);
166
iterExists = model.iter_next (ref iter);
172
public string gtk_combobox_get_value (ComboBox combo, int index, string default_value){
174
/* Conveniance function to get combobox value */
176
if ((combo.model == null) || (combo.active < 0)) { return default_value; }
180
combo.get_active_iter (out iter);
181
TreeModel model = (TreeModel) combo.model;
182
model.get(iter, index, out val);
187
public GLib.Object gtk_combobox_get_selected_object (
190
GLib.Object default_value){
192
/* Conveniance function to get combobox value */
194
if ((combo.model == null) || (combo.active < 0)) { return default_value; }
197
GLib.Object val = null;
198
combo.get_active_iter (out iter);
199
TreeModel model = (TreeModel) combo.model;
200
model.get(iter, index, out val);
205
public int gtk_combobox_get_value_enum (ComboBox combo, int index, int default_value){
207
/* Conveniance function to get combobox value */
209
if ((combo.model == null) || (combo.active < 0)) { return default_value; }
213
combo.get_active_iter (out iter);
214
TreeModel model = (TreeModel) combo.model;
215
model.get(iter, index, out val);
222
public Gdk.Pixbuf? get_app_icon(int icon_size, string format = ".png"){
223
var img_icon = get_shared_icon(AppShortName, AppShortName + format,icon_size,"pixmaps");
224
if (img_icon != null){
225
return img_icon.pixbuf;
232
public Gtk.Image? get_shared_icon(
234
string fallback_icon_file_name,
236
string icon_directory = AppShortName + "/images"){
238
Gdk.Pixbuf pix_icon = null;
239
Gtk.Image img_icon = null;
242
Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default();
244
pix_icon = icon_theme.load_icon_for_scale (
245
icon_name, Gtk.IconSize.MENU, icon_size, Gtk.IconLookupFlags.FORCE_SIZE);
248
//log_error (e.message);
251
string fallback_icon_file_path = "/usr/share/%s/%s".printf(icon_directory, fallback_icon_file_name);
253
if (pix_icon == null){
255
pix_icon = new Gdk.Pixbuf.from_file_at_size (fallback_icon_file_path, icon_size, icon_size);
257
log_error (e.message);
261
if (pix_icon == null){
262
log_error (_("Missing Icon") + ": '%s', '%s'".printf(icon_name, fallback_icon_file_path));
265
img_icon = new Gtk.Image.from_pixbuf(pix_icon);
271
public Gdk.Pixbuf? get_shared_icon_pixbuf(string icon_name,
272
string fallback_file_name,
274
string icon_directory = AppShortName + "/images"){
276
var img = get_shared_icon(icon_name, fallback_file_name, icon_size, icon_directory);
277
var pixbuf = (img == null) ? null : img.pixbuf;
281
// styles ----------------
283
public static int CSS_AUTO_CLASS_INDEX = 0;
284
public static void gtk_apply_css(Gtk.Widget[] widgets, string css_style){
285
var css_provider = new Gtk.CssProvider();
286
var css = ".style_%d { %s }".printf(++CSS_AUTO_CLASS_INDEX, css_style);
288
css_provider.load_from_data(css,-1);
289
} catch (GLib.Error e) {
293
foreach(var widget in widgets){
295
widget.get_style_context().add_provider(
296
css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
298
widget.get_style_context().add_class("style_%d".printf(CSS_AUTO_CLASS_INDEX));
302
// treeview -----------------
304
public int gtk_treeview_model_count(TreeModel model){
307
if (model.get_iter_first(out iter)){
309
while(model.iter_next(ref iter)){
316
public void gtk_stripe_row(
317
Gtk.CellRenderer cell,
319
string odd_color = "#F4F6F7",
320
string even_color = "#FFFFFF"){
322
if (cell is Gtk.CellRendererText){
323
(cell as Gtk.CellRendererText).background = odd_row ? odd_color : even_color;
325
else if (cell is Gtk.CellRendererPixbuf){
326
(cell as Gtk.CellRendererPixbuf).cell_background = odd_row ? odd_color : even_color;
330
public void gtk_treeview_redraw(Gtk.TreeView treeview){
331
var model = treeview.model;
332
treeview.model = null;
333
treeview.model = model;
338
public void gtk_menu_add_separator(Gtk.Menu menu){
339
Gdk.RGBA gray = Gdk.RGBA();
340
gray.parse ("rgba(200,200,200,1)");
343
var menu_item = new Gtk.SeparatorMenuItem();
344
menu_item.override_color (StateFlags.NORMAL, gray);
345
menu.append(menu_item);
348
public Gtk.MenuItem gtk_menu_add_item(
352
Gtk.Image? icon_image,
353
Gtk.SizeGroup? sg_icon = null,
354
Gtk.SizeGroup? sg_label = null){
356
var menu_item = new Gtk.MenuItem();
357
menu.append(menu_item);
359
var box = new Gtk.Box(Orientation.HORIZONTAL, 3);
364
if (icon_image == null){
365
var dummy = new Gtk.Label("");
368
if (sg_icon != null){
369
sg_icon.add_widget(dummy);
375
if (sg_icon != null){
376
sg_icon.add_widget(icon_image);
382
var lbl = new Gtk.Label(label);
383
lbl.xalign = (float) 0.0;
384
lbl.margin_right = 6;
387
if (sg_label != null){
388
sg_label.add_widget(lbl);
391
box.set_tooltip_text(tooltip);
398
public Gtk.Label gtk_box_add_header(Gtk.Box box, string text){
399
var label = new Gtk.Label("<b>" + text + "</b>");
400
label.set_use_markup(true);
401
label.xalign = (float) 0.0;
402
label.margin_bottom = 6;
410
public bool gtk_container_has_child(Gtk.Container container, Gtk.Widget widget){
411
foreach(var child in container.get_children()){
412
if (child == widget){
420
private void text_view_append(Gtk.TextView view, string text){
422
view.buffer.get_end_iter(out iter);
423
view.buffer.insert(ref iter, text, text.length);
426
private void text_view_prepend(Gtk.TextView view, string text){
428
view.buffer.get_start_iter(out iter);
429
view.buffer.insert(ref iter, text, text.length);
432
private void text_view_scroll_to_end(Gtk.TextView view){
434
view.buffer.get_end_iter(out iter);
435
view.scroll_to_iter(iter, 0.0, false, 0.0, 0.0);
438
private void text_view_scroll_to_start(Gtk.TextView view){
440
view.buffer.get_start_iter(out iter);
441
view.scroll_to_iter(iter, 0.0, false, 0.0, 0.0);
444
// file chooser ----------------
446
public Gtk.FileFilter create_file_filter(string group_name, string[] patterns) {
447
var filter = new Gtk.FileFilter ();
448
filter.set_filter_name(group_name);
449
foreach(string pattern in patterns) {
450
filter.add_pattern (pattern);
455
// utility ------------------
458
private Gtk.Notebook add_notebook(
459
Gtk.Box box, bool show_tabs = true, bool show_border = true){
462
var book = new Gtk.Notebook();
464
book.show_tabs = show_tabs;
465
book.show_border = show_border;
467
box.pack_start(book, true, true, 0);
473
private Gtk.Box add_tab(
474
Gtk.Notebook book, string title, int margin = 12, int spacing = 6){
477
var label = new Gtk.Label(title);
480
var vbox = new Box (Gtk.Orientation.VERTICAL, spacing);
481
vbox.margin = margin;
482
book.append_page (vbox, label);
488
private Gtk.TreeView add_treeview(Gtk.Box box,
489
Gtk.SelectionMode selection_mode = Gtk.SelectionMode.SINGLE){
492
var treeview = new TreeView();
493
treeview.get_selection().mode = selection_mode;
494
treeview.set_rules_hint (true);
495
treeview.show_expanders = true;
496
treeview.enable_tree_lines = true;
499
var scrollwin = new ScrolledWindow(null, null);
500
scrollwin.set_shadow_type (ShadowType.ETCHED_IN);
501
scrollwin.add (treeview);
502
scrollwin.expand = true;
509
private Gtk.TreeViewColumn add_column_text(
510
Gtk.TreeView treeview, string title, out Gtk.CellRendererText cell){
513
var col = new Gtk.TreeViewColumn();
516
cell = new Gtk.CellRendererText();
517
cell.xalign = (float) 0.0;
518
col.pack_start (cell, false);
519
treeview.append_column(col);
526
private Gtk.TreeViewColumn add_column_icon(
527
Gtk.TreeView treeview, string title, out Gtk.CellRendererPixbuf cell){
530
var col = new Gtk.TreeViewColumn();
533
cell = new Gtk.CellRendererPixbuf();
535
col.pack_start (cell, false);
536
treeview.append_column(col);
541
// add_column_icon_and_text
542
private Gtk.TreeViewColumn add_column_icon_and_text(
543
Gtk.TreeView treeview, string title,
544
out Gtk.CellRendererPixbuf cell_pix, out Gtk.CellRendererText cell_text){
547
var col = new Gtk.TreeViewColumn();
550
cell_pix = new Gtk.CellRendererPixbuf();
552
col.pack_start (cell_pix, false);
554
cell_text = new Gtk.CellRendererText();
555
cell_text.xalign = (float) 0.0;
556
col.pack_start (cell_text, false);
557
treeview.append_column(col);
562
// add_column_radio_and_text
563
private Gtk.TreeViewColumn add_column_radio_and_text(
564
Gtk.TreeView treeview, string title,
565
out Gtk.CellRendererToggle cell_radio, out Gtk.CellRendererText cell_text){
568
var col = new Gtk.TreeViewColumn();
571
cell_radio = new Gtk.CellRendererToggle();
573
cell_radio.radio = true;
574
cell_radio.activatable = true;
575
col.pack_start (cell_radio, false);
577
cell_text = new Gtk.CellRendererText();
578
cell_text.xalign = (float) 0.0;
579
col.pack_start (cell_text, false);
580
treeview.append_column(col);
585
// add_column_icon_radio_text
586
private Gtk.TreeViewColumn add_column_icon_radio_text(
587
Gtk.TreeView treeview, string title,
588
out Gtk.CellRendererPixbuf cell_pix,
589
out Gtk.CellRendererToggle cell_radio,
590
out Gtk.CellRendererText cell_text){
593
var col = new Gtk.TreeViewColumn();
596
cell_pix = new Gtk.CellRendererPixbuf();
598
col.pack_start (cell_pix, false);
600
cell_radio = new Gtk.CellRendererToggle();
602
cell_radio.radio = true;
603
cell_radio.activatable = true;
604
col.pack_start (cell_radio, false);
606
cell_text = new Gtk.CellRendererText();
607
cell_text.xalign = (float) 0.0;
608
col.pack_start (cell_text, false);
609
treeview.append_column(col);
614
// add_label_scrolled
615
private Gtk.Label add_label_scrolled(
616
Gtk.Box box, string text,
617
bool show_border = false, bool wrap = false, int ellipsize_chars = 40){
620
var scroll = new Gtk.ScrolledWindow(null, null);
621
scroll.hscrollbar_policy = PolicyType.NEVER;
622
scroll.vscrollbar_policy = PolicyType.ALWAYS;
623
scroll.expand = true;
626
var label = new Gtk.Label(text);
627
label.xalign = (float) 0.0;
628
label.yalign = (float) 0.0;
630
label.set_use_markup(true);
635
label.wrap_mode = Pango.WrapMode.WORD;
639
label.ellipsize = Pango.EllipsizeMode.MIDDLE;
640
label.max_width_chars = ellipsize_chars;
644
scroll.set_shadow_type (ShadowType.ETCHED_IN);
647
label.margin_left = 0;
654
private Gtk.TextView add_text_view(
655
Gtk.Box box, string text){
658
var scrolled = new Gtk.ScrolledWindow(null, null);
659
scrolled.hscrollbar_policy = PolicyType.NEVER;
660
scrolled.vscrollbar_policy = PolicyType.ALWAYS;
661
scrolled.expand = true;
664
var view = new Gtk.TextView();
665
view.wrap_mode = Gtk.WrapMode.WORD_CHAR;
666
view.accepts_tab = false;
667
view.editable = false;
668
view.cursor_visible = false;
669
view.buffer.text = text;
670
view.sensitive = false;
677
private Gtk.Label add_label(
678
Gtk.Box box, string text, bool bold = false,
679
bool italic = false, bool large = false){
681
string msg = "<span%s%s%s>%s</span>".printf(
682
(bold ? " weight=\"bold\"" : ""),
683
(italic ? " style=\"italic\"" : ""),
684
(large ? " size=\"x-large\"" : ""),
687
var label = new Gtk.Label(msg);
688
label.set_use_markup(true);
689
label.xalign = (float) 0.0;
691
label.wrap_mode = Pango.WrapMode.WORD;
696
private string format_text(
698
bool bold = false, bool italic = false, bool large = false){
700
string msg = "<span%s%s%s>%s</span>".printf(
701
(bold ? " weight=\"bold\"" : ""),
702
(italic ? " style=\"italic\"" : ""),
703
(large ? " size=\"x-large\"" : ""),
710
private Gtk.Label add_label_header(
711
Gtk.Box box, string text, bool large_heading = false){
713
var label = add_label(box, escape_html(text), true, false, large_heading);
714
label.margin_bottom = 12;
719
private Gtk.Label add_label_subnote(
720
Gtk.Box box, string text){
722
var label = add_label(box, text, false, true);
723
label.margin_left = 6;
728
private Gtk.RadioButton add_radio(
729
Gtk.Box box, string text, Gtk.RadioButton? another_radio_in_group){
731
Gtk.RadioButton radio = null;
733
if (another_radio_in_group == null){
734
radio = new Gtk.RadioButton(null);
737
radio = new Gtk.RadioButton.from_widget(another_radio_in_group);
744
foreach(var child in radio.get_children()){
745
if (child is Gtk.Label){
746
var label = (Gtk.Label) child;
747
label.use_markup = true;
756
private Gtk.CheckButton add_checkbox(
757
Gtk.Box box, string text){
759
var chk = new Gtk.CheckButton.with_label(text);
763
foreach(var child in chk.get_children()){
764
if (child is Gtk.Label){
765
var label = (Gtk.Label) child;
766
label.use_markup = true;
772
chk.toggled.connect(()=>{
781
private Gtk.SpinButton add_spin(
782
Gtk.Box box, double min, double max, double val,
783
int digits = 0, double step = 1, double step_page = 1){
785
var adj = new Gtk.Adjustment(val, min, max, step, step_page, 0);
786
var spin = new Gtk.SpinButton(adj, step, digits);
787
spin.xalign = (float) 0.5;
791
spin.value_changed.connect(()=>{
792
label.sensitive = spin.sensitive;
800
private Gtk.Button add_button(
801
Gtk.Box box, string text, string tooltip,
802
ref Gtk.SizeGroup? size_group,
803
Gtk.Image? icon = null){
805
var button = new Gtk.Button();
808
button.set_label(text);
809
button.set_tooltip_text(tooltip);
812
button.set_image(icon);
813
button.set_always_show_image(true);
816
if (size_group == null){
817
size_group = new Gtk.SizeGroup(SizeGroupMode.HORIZONTAL);
820
size_group.add_widget(button);
826
private Gtk.ToggleButton add_toggle_button(
827
Gtk.Box box, string text, string tooltip,
828
ref Gtk.SizeGroup? size_group,
829
Gtk.Image? icon = null){
831
var button = new Gtk.ToggleButton();
834
button.set_label(text);
835
button.set_tooltip_text(tooltip);
838
button.set_image(icon);
839
button.set_always_show_image(true);
842
if (size_group == null){
843
size_group = new Gtk.SizeGroup(SizeGroupMode.HORIZONTAL);
846
size_group.add_widget(button);
851
// add_directory_chooser
852
private Gtk.Entry add_directory_chooser(
853
Gtk.Box box, string selected_directory, Gtk.Window parent_window){
856
var entry = new Gtk.Entry();
857
entry.hexpand = true;
858
//entry.margin_left = 6;
859
entry.secondary_icon_stock = "gtk-open";
860
entry.placeholder_text = _("Enter path or browse for directory");
863
if ((selected_directory != null) && dir_exists(selected_directory)){
864
entry.text = selected_directory;
867
entry.icon_release.connect((p0, p1) => {
869
var chooser = new Gtk.FileChooserDialog(
872
FileChooserAction.SELECT_FOLDER,
874
Gtk.ResponseType.CANCEL,
876
Gtk.ResponseType.ACCEPT
879
chooser.select_multiple = false;
880
chooser.set_filename(selected_directory);
882
if (chooser.run() == Gtk.ResponseType.ACCEPT) {
883
entry.text = chooser.get_filename();
885
//App.repo = new SnapshotRepo.from_path(entry.text, this);
886
//check_backup_location();