X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Fgtk%2Fgtkutils.c;h=600904a3f87466400383a2e9da0e216e497b8c31;hp=bdb7383a05e2746a260474c65423c8b8016cda6d;hb=16f9a5d51f38804fee144a54d80d7c744e00cd53;hpb=dc2e42e4ca387526d1f12414cc110f8754418ba9 diff --git a/src/gtk/gtkutils.c b/src/gtk/gtkutils.c index bdb7383a0..600904a3f 100644 --- a/src/gtk/gtkutils.c +++ b/src/gtk/gtkutils.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team + * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,6 +60,7 @@ #include "prefs_common.h" #include "manage_window.h" #include "base64.h" +#include "manual.h" gboolean gtkut_get_font_size(GtkWidget *widget, gint *width, gint *height) @@ -104,6 +105,36 @@ void gtkut_convert_int_to_gdk_color(gint rgbvalue, GdkColor *color) color->blue = (int) (((gdouble) (rgbvalue & 0x0000ff) / 255.0) * 65535.0); } +void gtkut_stock_button_add_help(GtkWidget *bbox, GtkWidget **help_btn) +{ + g_return_if_fail(bbox != NULL); + + *help_btn = gtk_button_new_from_stock(GTK_STOCK_HELP); + + GTK_WIDGET_SET_FLAGS(*help_btn, GTK_CAN_DEFAULT); + gtk_box_pack_end(GTK_BOX (bbox), *help_btn, TRUE, TRUE, 0); + gtk_button_box_set_child_secondary(GTK_BUTTON_BOX (bbox), + *help_btn, TRUE); + gtk_widget_set_sensitive(*help_btn, + manual_available(MANUAL_MANUAL_LOCAL)); + gtk_widget_show(*help_btn); +} + +void gtkut_stock_button_set_create_with_help(GtkWidget **bbox, + GtkWidget **help_button, + GtkWidget **button1, const gchar *label1, + GtkWidget **button2, const gchar *label2, + GtkWidget **button3, const gchar *label3) +{ + g_return_if_fail(bbox != NULL); + g_return_if_fail(button1 != NULL); + + gtkut_stock_button_set_create(bbox, button1, label1, + button2, label2, button3, label3); + + gtkut_stock_button_add_help(*bbox, help_button); +} + void gtkut_stock_button_set_create(GtkWidget **bbox, GtkWidget **button1, const gchar *label1, GtkWidget **button2, const gchar *label2, @@ -136,6 +167,42 @@ void gtkut_stock_button_set_create(GtkWidget **bbox, } } +void gtkut_stock_with_text_button_set_create(GtkWidget **bbox, + GtkWidget **button1, const gchar *label1, const gchar *text1, + GtkWidget **button2, const gchar *label2, const gchar *text2, + GtkWidget **button3, const gchar *label3, const gchar *text3) +{ + g_return_if_fail(bbox != NULL); + g_return_if_fail(button1 != NULL); + + *bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(*bbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing(GTK_BOX(*bbox), 5); + + *button1 = gtk_button_new_with_mnemonic(text1); + gtk_button_set_image(GTK_BUTTON(*button1), + gtk_image_new_from_stock(label1, GTK_ICON_SIZE_BUTTON)); + GTK_WIDGET_SET_FLAGS(*button1, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(*bbox), *button1, TRUE, TRUE, 0); + gtk_widget_show(*button1); + + if (button2) { + *button2 = gtk_button_new_with_mnemonic(text2); + gtk_button_set_image(GTK_BUTTON(*button2), + gtk_image_new_from_stock(label2, GTK_ICON_SIZE_BUTTON)); + gtk_box_pack_start(GTK_BOX(*bbox), *button2, TRUE, TRUE, 0); + gtk_widget_show(*button2); + } + + if (button3) { + *button3 = gtk_button_new_with_mnemonic(text3); + gtk_button_set_image(GTK_BUTTON(*button3), + gtk_image_new_from_stock(label3, GTK_ICON_SIZE_BUTTON)); + gtk_box_pack_start(GTK_BOX(*bbox), *button3, TRUE, TRUE, 0); + gtk_widget_show(*button3); + } +} + static void combo_button_size_request(GtkWidget *widget, GtkRequisition *requisition, gpointer data) @@ -244,7 +311,7 @@ ComboButton *gtkut_combo_button_create(GtkWidget *button, #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \ ((clist)->row_height + CELL_SPACING)) -void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node) +void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, gint _row) { GtkCList *clist = GTK_CLIST(ctree); gint row; @@ -253,7 +320,8 @@ void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node) g_return_if_fail(ctree != NULL); g_return_if_fail(node != NULL); - row = g_list_position(clist->row_list, (GList *)node); + row = (_row != -1 ? _row : g_list_position(clist->row_list, (GList *)node)); + if (row < 0 || row >= clist->rows || clist->row_height == 0) return; row_visibility = gtk_clist_row_is_visible(clist, row); prev_row_visibility = gtk_clist_row_is_visible(clist, row - 1); @@ -387,6 +455,8 @@ gboolean gtkut_ctree_node_is_parent(GtkCTreeNode *parent, GtkCTreeNode *node) void gtkut_ctree_set_focus_row(GtkCTree *ctree, GtkCTreeNode *node) { + if (node == NULL) + return; gtkut_clist_set_focus_row(GTK_CLIST(ctree), gtkut_ctree_get_nth_from_node(ctree, node)); } @@ -686,6 +756,7 @@ void gtkut_window_popup(GtkWidget *window) if (new_x != x || new_y != y) gdk_window_move(window->window, new_x, new_y); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), FALSE); gtk_window_present(GTK_WINDOW(window)); } @@ -737,36 +808,37 @@ void gtkut_widget_init(void) GtkWidget *clist; clist = gtk_clist_new(1); - g_object_ref(G_OBJECT(clist)); + gtk_object_ref(GTK_OBJECT(clist)); gtk_object_sink(GTK_OBJECT(clist)); gtkut_clist_bindings_add(clist); - g_object_unref(G_OBJECT(clist)); + gtk_object_unref(GTK_OBJECT(clist)); clist = gtk_ctree_new(1, 0); - g_object_ref(G_OBJECT(clist)); + gtk_object_ref(GTK_OBJECT(clist)); gtk_object_sink(GTK_OBJECT(clist)); gtkut_clist_bindings_add(clist); - g_object_unref(G_OBJECT(clist)); + gtk_object_unref(GTK_OBJECT(clist)); clist = gtk_sctree_new_with_titles(1, 0, NULL); - g_object_ref(G_OBJECT(clist)); + gtk_object_ref(GTK_OBJECT(clist)); gtk_object_sink(GTK_OBJECT(clist)); gtkut_clist_bindings_add(clist); - g_object_unref(G_OBJECT(clist)); + gtk_object_unref(GTK_OBJECT(clist)); } void gtkut_widget_set_app_icon(GtkWidget *widget) { -#include "pixmaps/sylpheed.xpm" - static GdkPixmap *sylpheedxpm; - static GdkBitmap *sylpheedxpmmask; +#include "pixmaps/claws-mail.xpm" + static GdkPixmap *sylpheedclawsxpm; + static GdkBitmap *sylpheedclawsxpmmask; g_return_if_fail(widget != NULL); g_return_if_fail(widget->window != NULL); - if (!sylpheedxpm) { - PIXMAP_CREATE(widget, sylpheedxpm, sylpheedxpmmask, sylpheed_xpm); + if (!sylpheedclawsxpm) { + PIXMAP_CREATE(widget, sylpheedclawsxpm, sylpheedclawsxpmmask, + claws_mail_xpm); } - gdk_window_set_icon(widget->window, NULL, sylpheedxpm, sylpheedxpmmask); + gdk_window_set_icon(widget->window, NULL, sylpheedclawsxpm, sylpheedclawsxpmmask); } void gtkut_widget_set_composer_icon(GtkWidget *widget) @@ -782,13 +854,32 @@ void gtkut_widget_set_composer_icon(GtkWidget *widget) gdk_window_set_icon(widget->window, NULL, xpm, bmp); } +static gboolean move_bar = FALSE; +static gint move_bar_id = -1; + +static gboolean move_bar_cb(gpointer data) +{ + GtkWidget *w = (GtkWidget *)data; + if (!move_bar) + return FALSE; + + if (!GTK_IS_PROGRESS_BAR(w)) { + return FALSE; + } + + gtk_progress_bar_pulse(GTK_PROGRESS_BAR(w)); + GTK_EVENTS_FLUSH(); + return TRUE; +} + GtkWidget *label_window_create(const gchar *str) { GtkWidget *window; - GtkWidget *label; + GtkWidget *label, *vbox, *hbox; + GtkWidget *wait_progress = gtk_progress_bar_new(); - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_size_request(window, 380, 60); + window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "gtkutils"); + gtk_widget_set_size_request(window, 380, 70); gtk_container_set_border_width(GTK_CONTAINER(window), 8); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(window), str); @@ -797,14 +888,41 @@ GtkWidget *label_window_create(const gchar *str) manage_window_set_transient(GTK_WINDOW(window)); label = gtk_label_new(str); - gtk_container_add(GTK_CONTAINER(window), label); - gtk_widget_show(label); + + vbox = gtk_vbox_new(FALSE, 6); + hbox = gtk_hbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, FALSE, 0); + hbox = gtk_hbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(hbox), wait_progress, TRUE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(window), vbox); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); + gtk_widget_show_all(vbox); gtk_widget_show_now(window); + + if (move_bar_id == -1) { + move_bar_id = g_timeout_add(200, move_bar_cb, wait_progress); + move_bar = TRUE; + } + + GTK_EVENTS_FLUSH(); return window; } +void label_window_destroy(GtkWidget *window) +{ + move_bar = FALSE; + g_source_remove(move_bar_id); + move_bar_id = -1; + GTK_EVENTS_FLUSH(); + gtk_widget_destroy(window); +} + GtkWidget *gtkut_account_menu_new(GList *ac_list, GCallback callback, gpointer data) @@ -911,30 +1029,10 @@ GtkWidget *gtkut_get_browse_file_btn(const gchar *button_label) { GtkWidget *button; -#if GTK_CHECK_VERSION(2, 6, 0) button = gtk_button_new_with_mnemonic(button_label); gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_BUTTON)); -#else - GtkWidget* image; - GtkWidget* box; - GtkWidget* label; - - button = gtk_button_new(); - box = gtk_hbox_new(FALSE, 0); - - image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON); - label = gtk_label_new(NULL); - gtk_label_set_text_with_mnemonic(GTK_LABEL(label), button_label); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), button); - - gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 1); - gtk_box_pack_end(GTK_BOX(box), label, FALSE, FALSE, 1); - gtk_widget_show(label); - gtk_widget_show(image); - gtk_widget_show(box); - gtk_container_add(GTK_CONTAINER(button), box); -#endif + return button; } @@ -945,35 +1043,56 @@ GtkWidget *gtkut_get_browse_directory_btn(const gchar *button_label) { GtkWidget *button; -#if GTK_CHECK_VERSION(2, 6, 0) button = gtk_button_new_with_mnemonic(button_label); gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_BUTTON)); -#else - GtkWidget* image; - GtkWidget* box; - GtkWidget* label; - - button = gtk_button_new(); - box = gtk_hbox_new(FALSE, 0); - - image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON); - label = gtk_label_new(NULL); - gtk_label_set_text_with_mnemonic(GTK_LABEL(label), button_label); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), button); - - gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 1); - gtk_box_pack_end(GTK_BOX(box), label, FALSE, FALSE, 1); - gtk_widget_show(label); - gtk_widget_show(image); - gtk_widget_show(box); - gtk_container_add(GTK_CONTAINER(button), box); -#endif + + return button; +} + +GtkWidget *gtkut_get_replace_btn(const gchar *button_label) +{ + GtkWidget *button; + + button = gtk_button_new_with_mnemonic(button_label); + gtk_button_set_image(GTK_BUTTON(button), + gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_BUTTON)); + return button; } +/** + * merge some part of code into one function : it creates a frame and add + * these into gtk box widget passed in param. + * \param box gtk box where adding new created frame. + * \param pframe pointer with which to assign the frame. If NULL, no pointer + * is assigned but the frame is anyway created and added to @box. + * \param frame_label frame label of new created frame. + */ +GtkWidget *gtkut_get_options_frame(GtkWidget *box, GtkWidget **pframe, + const gchar *frame_label) +{ + GtkWidget *vbox; + GtkWidget *frame; + + frame = gtk_frame_new(frame_label); + gtk_widget_show(frame); + gtk_box_pack_start(GTK_BOX(box), frame, FALSE, TRUE, 0); + gtk_frame_set_label_align(GTK_FRAME(frame), 0.01, 0.5); + + vbox = gtk_vbox_new (FALSE, 4); + gtk_widget_show(vbox); + gtk_container_add(GTK_CONTAINER (frame), vbox); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); + + if (pframe != NULL) + *pframe = frame; + + return vbox; +} + #if HAVE_LIBCOMPFACE -gint create_xpm_from_xface(gchar *xpm[], const gchar *xface) +static gint create_xpm_from_xface(gchar *xpm[], const gchar *xface) { static gchar *bit_pattern[] = { "....", @@ -1080,6 +1199,10 @@ GtkWidget *xface_get_from_header(const gchar *o_xface, GdkColor *background, gchar xface[2048]; strncpy(xface, o_xface, sizeof(xface)); + if (!window) { + g_warning("no window\n"); + return NULL; + } if (uncompface(xface) < 0) { g_warning("uncompface failed\n"); return NULL; @@ -1114,6 +1237,9 @@ GtkWidget *face_get_from_header(const gchar *o_face) GdkPixbufLoader *loader = gdk_pixbuf_loader_new (); GtkWidget *image; + if (o_face == NULL || strlen(o_face) == 0) + return NULL; + strncpy2(face, o_face, sizeof(face)); unfold_line(face); /* strip all whitespace and linebreaks */ @@ -1142,3 +1268,436 @@ GtkWidget *face_get_from_header(const gchar *o_face) g_object_unref(pixbuf); return image; } + +static GdkCursor *hand_cursor = NULL; + +static void link_btn_enter(GtkButton *button, gpointer data) +{ + GtkWidget *window = (GtkWidget *)data; + + if (!hand_cursor) + hand_cursor = gdk_cursor_new(GDK_HAND2); + if (window && window->window) + gdk_window_set_cursor(window->window, hand_cursor); + + gtk_button_set_relief(button, GTK_RELIEF_NONE); + gtk_widget_set_state(GTK_WIDGET(button), GTK_STATE_NORMAL); + +} + +static void link_btn_leave(GtkButton *button, gpointer data) +{ + GtkWidget *window = (GtkWidget *)data; + + if (window && window->window) + gdk_window_set_cursor(window->window, NULL); + + gtk_button_set_relief(button, GTK_RELIEF_NONE); + gtk_widget_set_state(GTK_WIDGET(button), GTK_STATE_NORMAL); +} + +static void link_btn_pressed(GtkButton *button, gpointer data) +{ + gtk_button_set_relief(button, GTK_RELIEF_NONE); + gtk_widget_set_state(GTK_WIDGET(button), GTK_STATE_NORMAL); +} + +static void link_btn_released(GtkButton *button, gpointer data) +{ + gtk_button_set_relief(button, GTK_RELIEF_NONE); + gtk_widget_set_state(GTK_WIDGET(button), GTK_STATE_NORMAL); +} + +static void link_btn_clicked(GtkButton *button, gpointer data) +{ + gchar *url = (gchar *)data; + gtk_button_set_relief(button, GTK_RELIEF_NONE); + gtk_widget_set_state(GTK_WIDGET(button), GTK_STATE_NORMAL); + open_uri(url, prefs_common.uri_cmd); +} + +static void link_btn_unrealize(GtkButton *button, gpointer data) +{ + gchar *url = (gchar *)data; + g_signal_handlers_disconnect_by_func(G_OBJECT(button), + G_CALLBACK(link_btn_clicked), url); + g_free(url); +} + +GtkWidget *gtkut_get_link_btn(GtkWidget *window, const gchar *url, const gchar *label) +{ + GtkWidget *btn; + GtkWidget *btn_label; + GdkColormap *cmap; + GdkColor uri_color[2] = {{0, 0, 0, 0xffff}, {0, 0xffff, 0, 0}}; + gboolean success[2]; + gchar *local_url = NULL; + if (!url) + return NULL; + + gtkut_convert_int_to_gdk_color(prefs_common.uri_col, + &uri_color[0]); + gtkut_convert_int_to_gdk_color(prefs_common.uri_col, + &uri_color[1]); + + btn = gtk_button_new_with_label(label?label:url); + gtk_button_set_relief(GTK_BUTTON(btn), GTK_RELIEF_NONE); + btn_label = GTK_BIN(btn)->child; + cmap = gdk_drawable_get_colormap(window->window); + gdk_colormap_alloc_colors(cmap, uri_color, 2, FALSE, TRUE, success); + if (success[0] == TRUE && success[1] == TRUE) { + GtkStyle *style; + gtk_widget_ensure_style(btn_label); + style = gtk_style_copy + (gtk_widget_get_style(btn_label)); + style->fg[GTK_STATE_NORMAL] = uri_color[0]; + style->fg[GTK_STATE_ACTIVE] = uri_color[1]; + style->fg[GTK_STATE_PRELIGHT] = uri_color[0]; + gtk_widget_set_style(btn_label, style); + } else + g_warning("about_create(): color allocation failed.\n"); + + g_signal_connect(G_OBJECT(btn), "enter", + G_CALLBACK(link_btn_enter), window); + g_signal_connect(G_OBJECT(btn), "leave", + G_CALLBACK(link_btn_leave), window); + g_signal_connect(G_OBJECT(btn), "pressed", + G_CALLBACK(link_btn_pressed), window); + g_signal_connect(G_OBJECT(btn), "released", + G_CALLBACK(link_btn_released), window); + + local_url = g_strdup(url); + g_signal_connect(G_OBJECT(btn), "clicked", + G_CALLBACK(link_btn_clicked), local_url); + g_signal_connect(G_OBJECT(btn), "unrealize", + G_CALLBACK(link_btn_unrealize), local_url); + return btn; +} + +GtkWidget *gtkut_sc_combobox_create(GtkWidget *eventbox, gboolean focus_on_click) +{ + GtkWidget *combobox; + GtkListStore *menu; + GtkCellRenderer *rend; + + menu = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); + + combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(menu)); + + rend = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), rend, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), rend, + "markup", 0, + NULL); + + if( eventbox != NULL ) + gtk_container_add(GTK_CONTAINER(eventbox), combobox); +#if GTK_CHECK_VERSION(2,6,0) + gtk_combo_box_set_focus_on_click(GTK_COMBO_BOX(combobox), focus_on_click); +#endif + return combobox; +} + +static void gtkutils_smooth_scroll_do(GtkWidget *widget, GtkAdjustment *vadj, + gfloat old_value, gfloat last_value, + gint step) +{ + gint change_value; + gboolean up; + gint i; + + if (old_value < last_value) { + change_value = last_value - old_value; + up = FALSE; + } else { + change_value = old_value - last_value; + up = TRUE; + } + + for (i = step; i <= change_value; i += step) { + vadj->value = old_value + (up ? -i : i); + g_signal_emit_by_name(G_OBJECT(vadj), + "value_changed", 0); + } + + vadj->value = last_value; + g_signal_emit_by_name(G_OBJECT(vadj), "value_changed", 0); + + gtk_widget_queue_draw(widget); +} + +static gboolean gtkutils_smooth_scroll_page(GtkWidget *widget, GtkAdjustment *vadj, gboolean up) +{ + gfloat upper; + gfloat page_incr; + gfloat old_value; + gfloat last_value; + + if (prefs_common.scroll_halfpage) + page_incr = vadj->page_increment / 2; + else + page_incr = vadj->page_increment; + + if (!up) { + upper = vadj->upper - vadj->page_size; + if (vadj->value < upper) { + old_value = vadj->value; + last_value = vadj->value + page_incr; + last_value = MIN(last_value, upper); + + gtkutils_smooth_scroll_do(widget, vadj, old_value, + last_value, + prefs_common.scroll_step); + } else + return FALSE; + } else { + if (vadj->value > 0.0) { + old_value = vadj->value; + last_value = vadj->value - page_incr; + last_value = MAX(last_value, 0.0); + + gtkutils_smooth_scroll_do(widget, vadj, old_value, + last_value, + prefs_common.scroll_step); + } else + return FALSE; + } + + return TRUE; +} + +gboolean gtkutils_scroll_page(GtkWidget *widget, GtkAdjustment *vadj, gboolean up) +{ + gfloat upper; + gfloat page_incr; + + if (prefs_common.enable_smooth_scroll) + return gtkutils_smooth_scroll_page(widget, vadj, up); + + if (prefs_common.scroll_halfpage) + page_incr = vadj->page_increment / 2; + else + page_incr = vadj->page_increment; + + if (!up) { + upper = vadj->upper - vadj->page_size; + if (vadj->value < upper) { + vadj->value += page_incr; + vadj->value = MIN(vadj->value, upper); + g_signal_emit_by_name(G_OBJECT(vadj), + "value_changed", 0); + } else + return FALSE; + } else { + if (vadj->value > 0.0) { + vadj->value -= page_incr; + vadj->value = MAX(vadj->value, 0.0); + g_signal_emit_by_name(G_OBJECT(vadj), + "value_changed", 0); + } else + return FALSE; + } + return TRUE; +} + +static void gtkutils_smooth_scroll_one_line(GtkWidget *widget, GtkAdjustment *vadj, gboolean up) +{ + gfloat upper; + gfloat old_value; + gfloat last_value; + + if (!up) { + upper = vadj->upper - vadj->page_size; + if (vadj->value < upper) { + old_value = vadj->value; + last_value = vadj->value + vadj->step_increment; + last_value = MIN(last_value, upper); + + gtkutils_smooth_scroll_do(widget, vadj, old_value, + last_value, + prefs_common.scroll_step); + } + } else { + if (vadj->value > 0.0) { + old_value = vadj->value; + last_value = vadj->value - vadj->step_increment; + last_value = MAX(last_value, 0.0); + + gtkutils_smooth_scroll_do(widget, vadj, old_value, + last_value, + prefs_common.scroll_step); + } + } +} + +void gtkutils_scroll_one_line(GtkWidget *widget, GtkAdjustment *vadj, gboolean up) +{ + gfloat upper; + + if (prefs_common.enable_smooth_scroll) { + gtkutils_smooth_scroll_one_line(widget, vadj, up); + return; + } + + if (!up) { + upper = vadj->upper - vadj->page_size; + if (vadj->value < upper) { + vadj->value += vadj->step_increment; + vadj->value = MIN(vadj->value, upper); + g_signal_emit_by_name(G_OBJECT(vadj), + "value_changed", 0); + } + } else { + if (vadj->value > 0.0) { + vadj->value -= vadj->step_increment; + vadj->value = MAX(vadj->value, 0.0); + g_signal_emit_by_name(G_OBJECT(vadj), + "value_changed", 0); + } + } +} + +gboolean gtkut_tree_model_text_iter_prev(GtkTreeModel *model, + GtkTreeIter *iter, + const gchar* text) +/* do the same as gtk_tree_model_iter_next, but _prev instead. + to use with widgets with one text column (gtk_combo_box_new_text() + and with GtkComboBoxEntry's for instance), +*/ +{ + GtkTreeIter cur_iter; + gchar *cur_value; + gboolean valid; + gint count; + + g_return_val_if_fail(model != NULL, FALSE); + g_return_val_if_fail(iter != NULL, FALSE); + + if (text == NULL || *text == '\0') + return FALSE; + + valid = gtk_tree_model_get_iter_first(model, &cur_iter); + count = 0; + while (valid) { + gtk_tree_model_get(model, &cur_iter, 0, &cur_value, -1); + + if (strcmp(text, cur_value) == 0) { + if (count <= 0) + return FALSE; + + return gtk_tree_model_iter_nth_child(model, iter, NULL, count - 1); + } + + valid = gtk_tree_model_iter_next(model, &cur_iter); + count++; + } + return FALSE; +} + +gboolean gtkut_tree_model_get_iter_last(GtkTreeModel *model, + GtkTreeIter *iter) +/* do the same as gtk_tree_model_get_iter_first, but _last instead. +*/ +{ + gint count; + + g_return_val_if_fail(model != NULL, FALSE); + g_return_val_if_fail(iter != NULL, FALSE); + + count = gtk_tree_model_iter_n_children(model, NULL); + + if (count <= 0) + return FALSE; + + return gtk_tree_model_iter_nth_child(model, iter, NULL, count - 1); +} + +#ifdef MAEMO +HildonWindow *gtkut_window_new (GtkWindowType type, + const gchar *class) +{ + HildonWindow *window = HILDON_WINDOW(hildon_window_new()); + gtk_window_set_role(GTK_WINDOW(window), class); + hildon_program_add_window(hildon_program(), window); + return window; +} +#else +GtkWidget *gtkut_window_new (GtkWindowType type, + const gchar *class) +{ + GtkWidget *window = gtk_window_new(type); + gtk_window_set_role(GTK_WINDOW(window), class); + return window; +} +#endif + +gboolean gtkut_tree_iter_comp(GtkTreeModel *model, + GtkTreeIter *iter1, + GtkTreeIter *iter2) +{ + GtkTreePath *path1 = gtk_tree_model_get_path(model, iter1); + GtkTreePath *path2 = gtk_tree_model_get_path(model, iter2); + gboolean result; + + result = gtk_tree_path_compare(path1, path2) == 0; + + gtk_tree_path_free(path1); + gtk_tree_path_free(path2); + + return result; +} + +/*! + *\brief Get selected row number. + */ +gint gtkut_list_view_get_selected_row(GtkWidget *list_view) +{ + GtkTreeView *view = GTK_TREE_VIEW(list_view); + GtkTreeModel *model = gtk_tree_view_get_model(view); + int n_rows = gtk_tree_model_iter_n_children(model, NULL); + GtkTreeSelection *selection; + GtkTreeIter iter; + int row; + + if (n_rows == 0) + return -1; + + selection = gtk_tree_view_get_selection(view); + if (!gtk_tree_selection_get_selected(selection, &model, &iter)) + return -1; + + /* get all iterators and compare them... */ + for (row = 0; row < n_rows; row++) { + GtkTreeIter itern; + + gtk_tree_model_iter_nth_child(model, &itern, NULL, row); + if (gtkut_tree_iter_comp(model, &iter, &itern)) + return row; + } + + return -1; +} + +/*! + *\brief Select a row by its number. + */ +gboolean gtkut_list_view_select_row(GtkWidget *list, gint row) +{ + GtkTreeView *list_view = GTK_TREE_VIEW(list); + GtkTreeSelection *selection = gtk_tree_view_get_selection(list_view); + GtkTreeModel *model = gtk_tree_view_get_model(list_view); + GtkTreeIter iter; + GtkTreePath *path; + + if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) + return FALSE; + + gtk_tree_selection_select_iter(selection, &iter); + + path = gtk_tree_model_get_path(model, &iter); + gtk_tree_view_set_cursor(list_view, path, NULL, FALSE); + gtk_tree_path_free(path); + + return TRUE; +} +