2
Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Lesser General Public
6
License as published by the Free Software Foundation; either
7
version 2.1 of the License, or (at your option) any later version.
9
See the file COPYING for the full license text.
20
GtkIconTheme* get_icon_theme(GtkWidget* widget)
22
return gtk_icon_theme_get_for_screen(gtk_widget_get_screen(widget));
25
GtkWidget* menu_item_new(const gchar* text, const gchar* icon
26
, GCallback signal, gboolean sensitive, gpointer userdata)
30
menuitem = gtk_image_menu_item_new_with_mnemonic(text);
32
menuitem = gtk_image_menu_item_new_from_stock(icon, NULL);
35
GtkWidget* image = gtk_image_new_from_stock(icon, GTK_ICON_SIZE_MENU);
36
if(gtk_image_get_storage_type(GTK_IMAGE(image)) == GTK_IMAGE_EMPTY)
37
image = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_MENU);
38
if(gtk_image_get_storage_type(GTK_IMAGE(image)) != GTK_IMAGE_EMPTY)
39
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
41
g_print("Note: The icon %s is not available.", icon);
44
g_signal_connect(menuitem, "activate", signal, userdata);
45
gtk_widget_set_sensitive(GTK_WIDGET(menuitem), sensitive && signal);
49
GtkToolItem* tool_button_new(const gchar* text, const gchar* icon
50
, gboolean important, gboolean sensitive, GCallback signal
51
, const gchar* tooltip, gpointer userdata)
53
GtkToolItem* toolbutton = gtk_tool_button_new(NULL, NULL);
54
GtkStockItem stockItem;
55
if(gtk_stock_lookup(icon, &stockItem))
56
toolbutton = gtk_tool_button_new_from_stock(icon);
59
GtkIconTheme* iconTheme = get_icon_theme(GTK_WIDGET(toolbutton));
60
if(gtk_icon_theme_has_icon(iconTheme, icon))
61
gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolbutton), icon);
63
gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(toolbutton), GTK_STOCK_MISSING_IMAGE);
66
gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbutton), text);
68
gtk_tool_item_set_is_important(toolbutton, TRUE);
70
g_signal_connect(toolbutton, "clicked", signal, userdata);
71
gtk_widget_set_sensitive(GTK_WIDGET(toolbutton), sensitive && signal);
73
sokoke_tool_item_set_tooltip_text(toolbutton, tooltip);
77
GtkWidget* check_menu_item_new(const gchar* text
78
, GCallback signal, gboolean sensitive, gboolean active, CBrowser* browser)
80
GtkWidget* menuitem = gtk_check_menu_item_new_with_mnemonic(text);
81
gtk_widget_set_sensitive(menuitem, sensitive && signal);
82
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), active);
84
g_signal_connect(menuitem, "activate", signal, browser);
88
GtkWidget* radio_button_new(GtkRadioButton* radio_button, const gchar* label)
90
return gtk_radio_button_new_with_mnemonic_from_widget(radio_button, label);
93
void show_error(const gchar* text, const gchar* text2, CBrowser* browser)
95
GtkWidget* dialog = gtk_message_dialog_new(
96
browser ? GTK_WINDOW(browser->window) : NULL
97
, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, text);
99
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), text2);
100
gtk_dialog_run(GTK_DIALOG(dialog));
101
gtk_widget_destroy(dialog);
104
gboolean spawn_protocol_command(const gchar* protocol, const gchar* res)
106
const gchar* command = g_datalist_get_data(&config->protocols_commands, protocol);
110
// Create an argument vector
111
gchar* uriEscaped = g_shell_quote(res);
113
if(strstr(command, "%s"))
114
commandReady = g_strdup_printf(command, uriEscaped);
116
commandReady = g_strconcat(command, " ", uriEscaped, NULL);
117
gchar** argv; GError* error = NULL;
118
if(!g_shell_parse_argv(commandReady, NULL, &argv, &error))
120
// FIXME: Should we have a more specific message?
121
show_error("Could not run external program.", error->message, NULL);
123
g_free(commandReady); g_free(uriEscaped);
127
// Try to run the command
129
gboolean success = g_spawn_async(NULL, argv, NULL
130
, (GSpawnFlags)G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD
131
, NULL, NULL, NULL, &error);
136
// FIXME: Should we have a more specific message?
137
show_error("Could not run external program.", error->message, NULL);
140
g_free(commandReady); g_free(uriEscaped);
144
GdkPixbuf* load_web_icon(const gchar* icon, GtkIconSize size, GtkWidget* widget)
146
g_return_val_if_fail(GTK_IS_WIDGET(widget), NULL);
147
GdkPixbuf* pixbuf = NULL;
150
// TODO: We want to allow http as well, maybe also base64?
151
const gchar* iconReady = g_str_has_prefix(icon, "file://") ? &icon[7] : icon;
152
GtkStockItem stockItem;
153
if(gtk_stock_lookup(icon, &stockItem))
154
pixbuf = gtk_widget_render_icon(widget, iconReady, size, NULL);
157
gint width; gint height;
158
gtk_icon_size_lookup(size, &width, &height);
159
pixbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default()
160
, icon, MAX(width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
163
pixbuf = gdk_pixbuf_new_from_file_at_size(iconReady, 16, 16, NULL);
166
pixbuf = gtk_widget_render_icon(widget, GTK_STOCK_FIND, size, NULL);
170
void entry_setup_completion(GtkEntry* entry)
172
/* TODO: The current behavior works only with the beginning of strings
173
But we want to match "localhost" with "loc" and "hos" */
174
GtkEntryCompletion* completion = gtk_entry_completion_new();
175
gtk_entry_completion_set_model(completion
176
, GTK_TREE_MODEL(gtk_list_store_new(1, G_TYPE_STRING)));
177
gtk_entry_completion_set_text_column(completion, 0);
178
gtk_entry_completion_set_minimum_key_length(completion, 3);
179
gtk_entry_set_completion(entry, completion);
180
gtk_entry_completion_set_popup_completion(completion, FALSE); //...
183
void entry_completion_append(GtkEntry* entry, const gchar* text)
185
GtkEntryCompletion* completion = gtk_entry_get_completion(entry);
186
GtkTreeModel* completion_store = gtk_entry_completion_get_model(completion);
188
gtk_list_store_insert(GTK_LIST_STORE(completion_store), &iter, 0);
189
gtk_list_store_set(GTK_LIST_STORE(completion_store), &iter, 0, text, -1);
192
GtkWidget* get_nth_webView(gint n, CBrowser* browser)
195
n = gtk_notebook_get_current_page(GTK_NOTEBOOK(browser->webViews));
196
GtkWidget* scrolled = gtk_notebook_get_nth_page(GTK_NOTEBOOK(browser->webViews), n);
197
return gtk_bin_get_child(GTK_BIN(scrolled));
200
gint get_webView_index(GtkWidget* webView, CBrowser* browser)
202
GtkWidget* scrolled = gtk_widget_get_parent(webView);
203
return gtk_notebook_page_num(GTK_NOTEBOOK(browser->webViews), scrolled);
206
CBrowser* get_browser_from_webView(GtkWidget* webView)
208
// FIXME: g_list_first
209
CBrowser* browser = NULL; GList* item = g_list_first(browsers);
212
browser = (CBrowser*)item->data;
213
if(browser->webView == webView)
216
while((item = g_list_next(item)));
220
void update_favicon(CBrowser* browser)
222
if(browser->loadedPercent == -1)
224
if(0) //browser->favicon // Has favicon?
226
// TODO: use custom icon
227
// gtk_image_set_from_file(GTK_IMAGE(browser->icon_page), "image");
229
else if(0) // Known mime-type?
231
// TODO: Retrieve mime type and load icon; don't forget ftp listings
234
gtk_image_set_from_stock(GTK_IMAGE(browser->webView_icon)
235
, GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
239
gtk_image_set_from_stock(GTK_IMAGE(browser->webView_icon)
240
, GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
244
void update_security(CBrowser* browser)
246
const gchar* uri = xbel_bookmark_get_href(browser->sessionItem);
247
// TODO: This check is bogus, until webkit tells us how secure a page is
248
if(g_str_has_prefix(uri, "https://"))
250
// TODO: highlighted entry indicates security, find an alternative
251
gtk_widget_modify_base(browser->location, GTK_STATE_NORMAL
252
, &browser->location->style->base[GTK_STATE_SELECTED]);
253
gtk_widget_modify_text(browser->location, GTK_STATE_NORMAL
254
, &browser->location->style->text[GTK_STATE_SELECTED]);
255
gtk_image_set_from_stock(GTK_IMAGE(browser->icon_security)
256
, GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_MENU);
260
gtk_widget_modify_base(browser->location, GTK_STATE_NORMAL, NULL);
261
gtk_widget_modify_text(browser->location, GTK_STATE_NORMAL, NULL);
262
gtk_image_set_from_stock(GTK_IMAGE(browser->icon_security)
263
, GTK_STOCK_INFO, GTK_ICON_SIZE_MENU);
267
void update_visibility(CBrowser* browser, gboolean visibility)
269
// A tabbed window shouldn't be manipulatable
270
if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(browser->webViews)) > 1)
273
// SHOULD SCRIPTS BE ABLE TO HIDE WINDOWS AT ALL?
276
gtk_widget_hide(browser->window);
280
g_print("Window was not hidden.\n");
282
sokoke_widget_set_visible(browser->menubar, browser->hasMenubar);
283
sokoke_widget_set_visible(browser->navibar, browser->hasToolbar);
284
sokoke_widget_set_visible(browser->location, browser->hasLocation);
285
sokoke_widget_set_visible(browser->webSearch, browser->hasLocation);
286
sokoke_widget_set_visible(browser->statusbar, browser->hasStatusbar);
289
void action_set_active(const gchar* name, gboolean active, CBrowser* browser)
291
// This shortcut toggles activity state by an action name
292
GtkAction* action = gtk_action_group_get_action(browser->actiongroup, name);
293
g_return_if_fail(GTK_IS_ACTION(action));
294
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), active);
297
void action_set_sensitive(const gchar* name, gboolean sensitive, CBrowser* browser)
299
// This shortcut toggles sensitivity by an action name
300
GtkAction* action = gtk_action_group_get_action(browser->actiongroup, name);
301
g_return_if_fail(GTK_IS_ACTION(action));
302
gtk_action_set_sensitive(action, sensitive);
305
void action_set_visible(const gchar* name, gboolean visible, CBrowser* browser)
307
// This shortcut toggles visibility by an action name
308
GtkAction* action = gtk_action_group_get_action(browser->actiongroup, name);
309
g_return_if_fail(GTK_IS_ACTION(action));
310
gtk_action_set_visible(action, visible);
313
void update_statusbar_text(CBrowser* browser)
315
if(browser->statusMessage)
317
gtk_statusbar_pop(GTK_STATUSBAR(browser->statusbar), 1);
318
gtk_statusbar_push(GTK_STATUSBAR(browser->statusbar), 1
319
, browser->statusMessage);
324
if(browser->loadedPercent)
325
message = g_strdup_printf("%d%% loaded, %d/%d bytes"
326
, browser->loadedPercent, browser->loadedBytes, browser->loadedBytesMax);
327
else if(browser->loadedBytes)
328
message = g_strdup_printf("%d bytes", browser->loadedBytes);
330
message = g_strdup(" ");
331
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(browser->progress), message);
336
void update_edit_items(CBrowser* browser)
338
GtkWidget* widget = gtk_window_get_focus(GTK_WINDOW(browser->window));
339
gboolean hasSelection = FALSE;
340
gboolean canCut = FALSE; gboolean canCopy = FALSE; gboolean canPaste = FALSE;
341
if(widget && (/*WEBKIT_IS_WEB_VIEW(widget) || */GTK_IS_EDITABLE(widget)))
343
hasSelection = /*WEBKIT_IS_WEB_VIEW(widget)
344
? webkit_web_view_has_selection(WEBKIT_WEB_VIEW(widget), NULL, NULL)
345
: */gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), NULL, NULL);
346
canCut = /*WEBKIT_IS_WEB_VIEW(widget)
347
? webkit_web_view_can_cut_clipboard(WEBKIT_WEB_VIEW(widget))
348
: */hasSelection && gtk_editable_get_editable(GTK_EDITABLE(widget));
349
canCopy = /*WEBKIT_IS_WEB_VIEW(widget)
350
? webkit_web_view_can_copy_clipboard(WEBKIT_WEB_VIEW(widget))
352
canPaste = /*WEBKIT_IS_WEB_VIEW(widget)
353
? webkit_web_view_can_paste_clipboard(WEBKIT_WEB_VIEW(widget))
354
: */gtk_editable_get_editable(GTK_EDITABLE(widget));
356
action_set_sensitive("Cut", canCut, browser);
357
action_set_sensitive("Copy", canCopy, browser);
358
action_set_sensitive("Paste", canPaste, browser);
359
action_set_sensitive("Delete", canCut, browser);
360
action_set_sensitive("SelectAll", !hasSelection, browser);
363
void update_gui_state(CBrowser* browser)
365
GtkWidget* webView = get_nth_webView(-1, browser);
366
action_set_sensitive("ZoomIn", FALSE, browser);//webkit_web_view_can_increase_text_size(WEBKIT_WEB_VIEW(webView), browser);
367
action_set_sensitive("ZoomOut", FALSE, browser);//webkit_web_view_can_decrease_text_size(WEBKIT_WEB_VIEW(webView)), browser);
368
action_set_sensitive("ZoomNormal", FALSE, browser);//webkit_web_view_get_text_size(WEBKIT_WEB_VIEW(webView)) != 1, browser);
369
action_set_sensitive("Back", webkit_web_view_can_go_backward(WEBKIT_WEB_VIEW(webView)), browser);
370
action_set_sensitive("Forward", webkit_web_view_can_go_forward(WEBKIT_WEB_VIEW(webView)), browser);
371
action_set_sensitive("Refresh", browser->loadedPercent == -1, browser);
372
action_set_sensitive("Stop", browser->loadedPercent != -1, browser);
374
GtkAction* action = gtk_action_group_get_action(browser->actiongroup, "RefreshStop");
375
if(browser->loadedPercent == -1)
377
gtk_widget_hide(browser->throbber);
378
g_object_set(action, "stock-id", GTK_STOCK_REFRESH, NULL);
379
g_object_set(action, "tooltip", "Refresh the current page", NULL);
383
gtk_widget_show(browser->throbber);
384
g_object_set(action, "stock-id", GTK_STOCK_STOP, NULL);
385
g_object_set(action, "tooltip", "Stop loading the current page", NULL);
388
gtk_image_set_from_stock(GTK_IMAGE(browser->location_icon), GTK_STOCK_FILE
389
, GTK_ICON_SIZE_MENU);
391
if(browser->loadedBytesMax < 1) // Skip null and negative values
393
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(browser->progress));
394
update_statusbar_text(browser);
398
if(browser->loadedBytes > browser->loadedBytesMax)
399
browser->loadedPercent = 100;
401
browser->loadedPercent
402
= (browser->loadedBytes * 100) / browser->loadedBytesMax;
403
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(browser->progress)
404
, browser->loadedPercent / 100.0);
405
update_statusbar_text(browser);
409
void update_feeds(CBrowser* browser)
411
// TODO: Look for available feeds, requires dom access
414
void update_search_engines(CBrowser* browser)
416
// TODO: Look for available search engines, requires dom access
419
void update_status_message(const gchar* message, CBrowser* browser)
421
g_free(browser->statusMessage);
422
browser->statusMessage = g_strdup(message ? message : "");
423
update_statusbar_text(browser);
426
void update_browser_actions(CBrowser* browser)
428
gboolean active = gtk_notebook_get_n_pages(GTK_NOTEBOOK(browser->webViews)) > 1;
429
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(browser->webViews), active);
430
action_set_sensitive("TabClose", active, browser);
431
guint n = xbel_folder_get_n_items(tabtrash);
432
action_set_sensitive("UndoTabClose", n, browser);
433
action_set_sensitive("TabsClosed", n, browser);
436
gchar* magic_uri(const gchar* uri, gboolean search)
438
// Add file:// if we have a local path
439
if(g_path_is_absolute(uri))
440
return g_strconcat("file://", uri, NULL);
441
// Do we need to add a protocol?
442
if(!strstr(uri, "://"))
444
// Do we have a domain, ip address or localhost?
445
if(strstr(uri, ".") != NULL || !strcmp(uri, "localhost"))
446
return g_strconcat("http://", uri, NULL);
447
// We don't want to search? So return early.
449
return g_strdup(uri);
451
const gchar* searchUrl = NULL;
452
// Do we have a keyword and a string?
453
gchar** parts = g_strsplit(uri, " ", 2);
454
if(parts[0] && parts[1])
456
guint n = g_list_length(searchEngines);
458
for(i = 0; i < n; i++)
460
SearchEngine* searchEngine = (SearchEngine*)g_list_nth_data(searchEngines, i);
461
if(!strcmp(search_engine_get_keyword(searchEngine), parts[0]))
462
searchUrl = searchEngine->url;
464
if(searchUrl != NULL)
465
g_snprintf(search, 255, searchUrl, parts[1]);
467
//g_strfreev(sParts);
468
// We only have a word or there is no matching keyowrd, so search for it
469
if(searchUrl == NULL)
470
g_snprintf(search, 255, config->locationSearch, uri);
471
return g_strdup(search);
473
return g_strdup(uri);
476
gchar* get_default_font(void)
478
GtkSettings* gtksettings = gtk_settings_get_default();
480
g_object_get(gtksettings, "gtk-font-name", &defaultFont, NULL);
484
GtkToolbarStyle config_to_toolbarstyle(guint toolbarStyle)
488
case CONFIG_TOOLBAR_ICONS:
489
return GTK_TOOLBAR_ICONS;
490
case CONFIG_TOOLBAR_TEXT:
491
return GTK_TOOLBAR_TEXT;
492
case CONFIG_TOOLBAR_BOTH:
493
return GTK_TOOLBAR_BOTH;
494
case CONFIG_TOOLBAR_BOTH_HORIZ:
495
return GTK_TOOLBAR_BOTH_HORIZ;
497
GtkSettings* gtkSettings = gtk_settings_get_default();
498
g_object_get(gtkSettings, "gtk-toolbar-style", &toolbarStyle, NULL);
502
GtkToolbarStyle config_to_toolbariconsize(gboolean toolbarSmall)
504
return toolbarSmall ? GTK_ICON_SIZE_SMALL_TOOLBAR
505
: GTK_ICON_SIZE_LARGE_TOOLBAR;