How to select text in GtkEntry - c

i have dialog window with GtkEntry. I want to select all text in entry right after dialog window becomes visible to user. I tried this, but its not working, i see no selection:
static void OnEntryShow(GtkWidget *entry, gpointer user_data)
{
gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
}
...
gtk_entry_set_text(GTK_ENTRY(myEntry), "text");
g_signal_connect(myEntry, "show", G_CALLBACK(OnEntryShow), NULL);
if (gtk_dialog_run(GTK_DIALOG(myDialog)) == GTK_RESPONSE_OK)
...
How can i select text in GtkEntry after GtkDialog becomes visible?

Perhaps you want the GtkEntry to grab focus?
Try this:
gtk_widget_grab_focus (entry);
where entry is in this case the pointer to your GtkEntry widget.
The documentation of the function can be found here.

You should use the function documented here.
text_entry.select_region(0,2) will select the first two characters, while (0, -1) will select the entire text.

Here's a solution I've used for gtkmm using the get_iter_at_offset and select_range functions.
Gtk::TextIter match_start = m_textBuffer->get_iter_at_offset(0);
Gtk::TextIter match_end = m_textBuffer->get_iter_at_offset(-1); // -1 to select all
m_textBuffer->select_range(match_start,match_end);

Related

How to add a hover effect to a GtkTreeView cell

I have a GtkTreeView with two columns of type text (e.g. G_TYPE_STRING) and I am using GtkCellRendererText to render the column.
Is there any why that I can react when the mouse enters and leaves a certain cell and then hover or highlight the cell.
For example I would like to underline the text in the cell renderer, when the mouse enters it, in order to give a visual clue that the cell can be clicked to perform an action.
There are quite a few ways to accomplish the task. A few examples follow, separated by horizontal lines.
The simplest, and in some ways the best, option is to simply change the mouse cursor to a finger (same as the mouse cursor you see in a browser when pointing to a link) within the GtkTreeView.
Let's say GtkTreeView *view is the view we're interested in. After you have called gtk_widget_show_all(window);, you can call
GdkWindow *win = gtk_tree_view_get_bin_window(GTK_TREE_VIEW(view));
GdkDisplay *disp = gdk_window_get_display(win);
gdk_window_set_cursor(win, gdk_cursor_new_from_name(disp, "pointer"));
With this, the mouse pointer will be a finger for all rows in the view, excluding the header row.
The set of cursor names you can use (instead of "pointer" above) is listed here in the GDK3 documentation.
The downside is that if you have empty rows in the tree view, or separator rows, the mouse pointer will still look like a finger for those.
You can override the hover color by applying an application-specific CSS hover color, say
GtkTreeView:hover {
color: #ff0000;
}
with e.g.
GtkCssProvider *css_provider;
css_provider = gtk_css_provider_new();
if (gtk_css_provider_load_from_data(css_provider,
"GtkTreeView:hover {\n"
" color: #ff0000;\n"
"}\n"
"", -1, NULL))
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
GTK_STYLE_PROVIDER(css_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref(css_provider);
after creating your main window. (Of course, you can include all application-specific CSS overrides in the CSS snippet.)
However, on gtk+ 3.18.9 at least, the renderer does not seem to support text-decoration or font CSS attributes here. (The GtkCssProvider does not seem to support cursor attribute at all, in case you're wondering.)
Also, since this essentially overrides the user theme, and there are a number of possible themes a Gtk+ user might be using, changing the color this way is unlikely to look good in all themes.
If your GtkTreeView *view; consists of clickable rows, and you don't need the selection for anything (that is, you don't have a separate button or something that causes an action to be applied to all the selected rows in the GtkTreeView), then you can simply set the selection to follow the mouse cursor:
gtk_tree_view_set_hover_selection(view, TRUE);
this causes the row you hover over to be selected, and therefore also highlighted. You probably also want to limit the selection to one row at a time:
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(view),
GTK_SELECTION_SINGLE);
As Herbalist already mentioned, you can create a custom GtkCellRendererText derivative, which changes the PangoUnderline underline property depending on whether the text cell being rendered is also prelit (hovered over) or not:
#include <gtk/gtk.h>
#define CUSTOM_TYPE_CELL_RENDERER_TEXT (custom_cell_renderer_text_get_type())
#define CUSTOM_CELL_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CUSTOM_TYPE_CELL_RENDERER_TEXT, CustomCellRendererText))
#define CUSTOM_CELL_RENDERER_TEXT_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), CUSTOM_TYPE_CELL_RENDERER_TEXT, CustomCellRendererTextClass))
#define CUSTOM_IS_CELL_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), CUSTOM_TYPE_CELL_RENDERER_TEXT))
#define CUSTOM_IS_CELL_RENDERER_TEXT_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls), CUSTOM_TYPE_CELL_RENDERER_TEXT))
#define CUSTOM_CELL_RENDERER_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), CUSTOM_TYPE_CELL_RENDERER_TEXT, CustomCellRendererTextClass))
GType custom_cell_renderer_text_get_type(void) G_GNUC_CONST;
typedef struct {
GtkCellRendererText renderer;
} CustomCellRendererText;
typedef struct {
GtkCellRendererTextClass parent_class;
} CustomCellRendererTextClass;
G_DEFINE_TYPE(CustomCellRendererText, custom_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT);
void custom_cell_renderer_text_render(GtkCellRenderer *cell,
cairo_t *cr,
GtkWidget *widget,
const GdkRectangle *backarea,
const GdkRectangle *cellarea,
GtkCellRendererState state)
{
if (state & GTK_CELL_RENDERER_PRELIT) {
const PangoUnderline prelit = PANGO_UNDERLINE_SINGLE;
PangoUnderline curr;
g_object_get(cell, "underline", &curr, NULL);
g_object_set(cell, "underline", prelit, NULL);
((GtkCellRendererClass *)custom_cell_renderer_text_parent_class)->render(cell, cr, widget, backarea, cellarea, state);
g_object_set(cell, "underline", curr, NULL);
} else
((GtkCellRendererClass *)custom_cell_renderer_text_parent_class)->render(cell, cr, widget, backarea, cellarea, state);
}
void custom_cell_renderer_text_class_init(CustomCellRendererTextClass *cls)
{
((GtkCellRendererClass *)cls)->render = custom_cell_renderer_text_render;
return;
}
void custom_cell_renderer_text_init(CustomCellRendererText *renderer)
{
return;
}
GtkCellRenderer *custom_cell_renderer_text_new(void)
{
return g_object_new(CUSTOM_TYPE_CELL_RENDERER_TEXT, NULL);
}
If you then replace your gtk_cell_render_text_new() with custom_cell_render_text_new() (and change GtkCellRenderText * to CustomCellRenderText *) in your GtkTreeView code, the row you hover on in the GtkTreeView will become underlined.
Note that all cells in the row you hover over will be highlighted, not just the cell/column you hover over. This is because in a GtkTreeView, the row (or index) is the unit being manipulated (rather than a specific cell on a specific column).
If you use the above renderer only for some columns in your GtkTreeView, the text in those columns will get underlined even when the mouse hovers over some other column on that row.
Also note that if you don't want all rows to indicate clickability, you can add a third column in your data model -- name "sensitive", type G_TYPE_BOOLEAN for gboolean type; value TRUE if the row is clickable, FALSE if the row is non-clickable -- and change the if clause in custom_cell_renderer_text_render() to
const GtkStateFlags flags = gtk_cell_renderer_get_state(cell, widget, state);
if ((state & GTK_CELL_RENDERER_PRELIT) &&
!(flags & GTK_STATE_FLAG_INSENSITIVE)) {
Gtk+ will render rows with TRUE normally, and rows with FALSE as separators or disabled text, because the column names in the model are automatically associated with the GtkCellRenderer properties of the same name.
You could make a custom CellRendererText and set the underline property if the PRELIT flag is present.
i only know in Python:
class My_CellRendererText( Gtk.CellRendererText ):
def __init__( self ):
super().__init__()
def do_render( self, cr, widget, background_area, cell_area, flags ):
self.props.underline = ( ( flags & Gtk.CellRendererState.PRELIT ) != 0 )
return Gtk.CellRendererText.do_render( self, cr, widget, background_area, cell_area, flags )
GObject.type_register( My_CellRendererText )

GtkCellRendererPixbuf and signals

Could anyone please give me a hint on how to attach a "double clicked" signal
to the pixbuf that is in the GtkTreeView? GtkCellRendererPixbuf
doesn't have any signals?
I managed to set the GTK_CELL_RENDERER_MODE_ACTIVATABLE switch to the
renderer, but I don't know how to work.
I checked the header file and in fact there is the "activate" method; could you please
demonstrate how to use it?
renderer = gtk_cell_renderer_pixbuf_new();
g_object_set(renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
column = gtk_tree_view_column_new_with_attributes(NULL,
renderer,
"pixbuf",
0,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
OK I try this:
Tree view's 'row-activated' will send the path and column as arguments
to the callback. With 'cursor-changed' just need to call
gtk_gtk_treeview_get_cursor to find out the path and column. With
gtk Widget's 'button-press-event' I get the event as an argument for
the callback and just need to call gtk_treeview_get_path_at_pos with
event x and event y to get the path and column.
A cell renderer is only supposed to draw the contents of the data model over a portion of the widget. Interaction with the user is in most cases realized using the widget itself.
In other words, simply connect to the button-press-event of the tree view and handle the case when the type is GDK_2BUTTON_PRESS. You can get the row/column under the mouse using gtk_tree_view_get_path_at_pos, as you do in your other question.
Check this:
void on_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
{
GtkTreeModel *model;
GtkTreeIter iter;
model = gtk_tree_view_get_model( treeview );
if ( gtk_tree_model_get_iter(model, &iter, path) )
{
gtk_tree_model_get(model, &iter,
ITEM, &dhd_contaItem2,
CODIGO, &dhd_G_CodProduto2 ,
DESCRICAO, &dhd_G_NomeProduto2 ,
QTD, &dhd_quantidade2,
VALOR, &dhd_valorItem2,
-1);
g_print( "Current row: %s %s %s %s %s\n", dhd_contaItem2, dhd_G_CodProduto2, dhd_G_NomeProduto2, dhd_quantidade2, dhd_valorItem2 );
}
}
I use that in one of my codes to print in terminal the selected row from a TreeView (with ListStore) when double clicked or when you press enter on it. On the gtk_tree_model_get notice that I'm using my own columns and variables, as i do in g_print. And I attach this function with row-activated signal on the TreeView. I don't know if is that what you want exactly but I hope it helps you out. Sorry for my bad english.

Place popup menu below widget GTK

I am having some trouble placing my popup menu where I want in GTK(along the same y axis as my button so it seems to dropdown from the button).
I got it working when I was coding a similar thing in win32 but for the life of me I cannot get this thing to draw where I want!
I've done my research and I know what (I think) should work and that is when I make the call to
gtk_menu_popup()
I should pass it in a function pointer to a method for placing the popup (link to the method specification - http://developer.gnome.org/gtk/2.24/GtkMenu.html#GtkMenuPositionFunc )
But i'm a bit rubbish with function pointers ( I have the Kernighan and ritchie book beside as I speak) but I'm pretty sure I'm doing it right.
Heres my attempt at the method :
void set_position(GtkMenu *menu,gint *x,gint *y,gboolean push_in,gpointer user_data)
{
printf("Help!\n";
GtkWidget *originButton = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(menu),"button");
gdk_window_get_position(originButton->window,x,y);
//now I realise this will place it at the top of the widget but thats acceptable for now, I just want the method to be called!
}
I call it from the button handler by doing this :
static gboolean handler (GtkWidget *widget,GdkEvent *event)
{
GdkEventButton *bevent = (GdkEventButton *) event;
gtk_menu_popup(GTK_MENU(widget),NULL,NULL,set_position,bevent->button,bevent->button,bevent->time);
}
But when I compile this it says its not a GtkMenuPositionFunc, so I just cast it (dont know if thats right though).
The problem is that I dont think my method is getting called because it never prints out help :( plus it still spawns the menu wherever I click (probably due to it not calling the method or whatever it should be doing).
Any help/ideas would be greatly received :) thanks :)
I had the same problem earlier. I used the following code.
static void
set_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
{
GtkWidget *button = GTK_BUTTON(user_data);
gdk_window_get_origin(button->window, x, y);
*x += button->allocation.x;
*y += (button->allocation.y + (button->allocation.height));
}
static void
handler(GtkWidget *menu, GtkWidget *button)
{
GtkRequisition requisition;
gtk_widget_size_request(menu, &requisition);
if (button->allocation.width > requisition.width)
gtk_widget_set_size_request(menu, button->allocation.width, -1);
gtk_menu_popup(GTK_MENU (menu),
NULL, NULL,
(GtkMenuPositionFunc) set_position, button,
0, gtk_get_current_event_time());
}
Okay, thanks very much to Pfeiffer for his sample code. I had to make some changes to it because I was getting compiler errors (i have Werror on though).
In the set poisition method I ended up casting to a GTK_WIDGET instead of a GTK_BUTTON becauses thats what it was expecting
So my new set position method looked like :
static void set_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) {
GtkWidget *button = GTK_WIDGET(user_data);
gdk_window_get_origin(button->window, x, y);
*x += button->allocation.x;
*y += (button->allocation.y + (button->allocation.height));
}
And as I couldn't figure out how to connect and pass the two widgets that Pfeiffer was passing I have this currently :
static gboolean handler(GtkWidget *widget, gpointer data) {
gtk_menu_popup(GTK_MENU(data), NULL, NULL,(GtkMenuPositionFunc)set_position,widget,(guint)widget, gtk_get_current_event_time());
return TRUE;
}
Also had to cast widget to a (guint) otherwise I got a compiler error about the 6th parameter :)
I will probably end up putting more in this method but this is the bare minimum I needed to get it to work.
That is connected using the normal gtk_signal_connect method
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(handler), GTK_OBJECT(menu));
where button and menu are GtkButton and GtkMenu instances I was using previously :)
Full credit goes to Pfeiffer for the answer, i'm just showing what worked for me :)
Thanks and hope this helps someone :)

What's the GTK header I need to include so I can use lookup_widget?

As shown in the example below, this callback function is when the user clicks an OK button. I can get window (the top level widget) from button by using gtk_widget_get_toplevel, but I'm stuck trying to get a widget pointer for a GtkEntry widget with name ENTRY.
/* Called when OK button is clicked */
on_BT_OK_clicked(GtkButton *button, gpointer user_data)
{
//The line directly below is the one I get an error on
GtkWidget *entry = lookup_widget( GTK_WIDGET(button), "ENTRY" );
gchar *text1, *text2;
text1 = gtk_entry_get_text( GTK_ENTRY(entry));
text2 = g_strconcat("Hello, ", text1, NULL);
GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET(button));
GtkWidget *dialog = gtk_message_dialog_new( window,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
text2);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
But I get the error "undefined reference to lookup_widget." I can find a billion examples of snippets of code using lookup_widget, but not a single one full source code example showing the headers that enable the use of it. I'm using Anjuta3.2.0 and the latest Glade plugin.
As Basile Starynkevitch says, lookup_widget() was a function generated by Glade 2. However, code generation by Glade has been deprecated for quite a long time now, in favor of (first) libglade and (later) GtkBuilder. In fact, Glade 3 won't even do it.
The preferred solution is to pass a pointer to your ENTRY as the user data pointer when you connect the signal, or, if you're using gtk_builder_connect_signals(), store a pointer to ENTRY in your class and pass the class as the user data pointer.
However, if you must use lookup_widget(), here's the source that Glade 2 generated as of about 6 years ago:
GtkWidget*
lookup_widget (GtkWidget *widget,
const gchar *widget_name)
{
GtkWidget *parent, *found_widget;
for (;;)
{
if (GTK_IS_MENU (widget))
parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
else
parent = widget->parent;
if (!parent)
parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
if (parent == NULL)
break;
widget = parent;
}
found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
widget_name);
if (!found_widget)
g_warning ("Widget not found: %s", widget_name);
return found_widget;
}
For this to work, you have to do the following for every widget contained within a toplevel window:
g_object_set_data_full (G_OBJECT (toplevel), "name-of-widget", gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref);
and then the following once for each toplevel window:
g_object_set_data (G_OBJECT (toplevel), "name-of-toplevel", toplevel);
Seems to me to be more trouble than it's worth.
Glade-2 implements lookup_widget() in support.c and the header is support.h
Once the GLADE GUI is converted to C codes these files are generated automatically.

How to change the cursor to a watch in GTK for C?

I'm using the C-style GTK functions in C++ and I can't figure out how to set the cursor for the main window.
Use gdk_set_cursor()
(https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-set-cursor)
on a GdkCursor created by gdk_cursor_new()
(https://developer.gnome.org/gdk3/stable/gdk3-Cursors.html)
Use gdk_window_set_cursor() on a GdkCursor created by gdk_cursor_new_from_name().
To get the GdkWindow of a GtkWindow you can use gtk_widget_get_window() because GtkWindow is a subclass of GtkWidget.
Note: this answer is an improvement over idefixs answer (important correction + link update + minor modification to make the answer complete + improved formatting) that was rejected as an edit.
Posting this because the comment about getting the GdkWndow went unanswered so far.
For most widgets, the GdkWindow can be retrieved as the window data field of the GtkWidget structure. The following code sets a cursor on a GtkWindow widget:
GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GdkCursor* watchCursor = gdk_cursor_new(GDK_WATCH);
/* set watch cursor */
gdk_window_set_cursor(win->window, watchCursor);
/* return to normal */
gdk_window_set_cursor(win->window, NULL);
If you need to get to the GtkWindow ancestor from one of its child widgets, you can use:
GtkWidget* win = gtk_widget_get_ancestor(someWidget, GTK_TYPE_WINDOW);
My solution:
void gtkSetCursor(GdkCursorType cursorType) {
GdkScreen * screen = gdk_screen_get_default();
GdkWindow * win = gdk_screen_get_root_window(screen);
GdkCursor * cursor = gdk_cursor_new(cursorType); //http://developer.gimp.org/api/2.0/gdk/gdk-Cursors.html
gdk_window_set_cursor(win, cursor);
while (gtk_events_pending()) gtk_main_iteration();
}
...
gtkSetCursor(GDK_WATCH);
start your stuff here
...
end of your stuff
gtkSetCursor(GDK_LEFT_PTR);
jeff's answer didn't work for me (Gtk3). So here's my solution:
GdkWindow* win = gtk_widget_get_parent_window(widget);
GdkCursor* watchCursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(win, watchCursor);

Resources