~midori/midori/cmake-make-dist

« back to all changes in this revision

Viewing changes to midori/sokoke.c

  • Committer: Christian Dywan
  • Date: 2008-06-01 21:47:27 UTC
  • Revision ID: git-v1:b511f12b9b4b063610161f2229b94a24a86be0fc
Rename folder 'src' to 'midori'

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
 
3
 
 
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.
 
8
 
 
9
 See the file COPYING for the full license text.
 
10
*/
 
11
 
 
12
#include "sokoke.h"
 
13
 
 
14
#include "search.h"
 
15
 
 
16
#include "config.h"
 
17
#include "main.h"
 
18
 
 
19
#ifdef HAVE_UNISTD_H
 
20
    #include <unistd.h>
 
21
#endif
 
22
#include <string.h>
 
23
#include <gdk/gdkkeysyms.h>
 
24
#include <glib/gi18n.h>
 
25
#include <glib/gprintf.h>
 
26
 
 
27
gchar*
 
28
sokoke_magic_uri (const gchar* uri, const gchar* default_search_uri)
 
29
{
 
30
    // Add file:// if we have a local path
 
31
    if (g_path_is_absolute (uri))
 
32
        return g_strconcat ("file://", uri, NULL);
 
33
    // Construct an absolute path if the file is relative
 
34
    if (g_file_test (uri, G_FILE_TEST_EXISTS) && g_file_test (uri, G_FILE_TEST_IS_REGULAR))
 
35
    {
 
36
        gchar* current_dir = g_get_current_dir ();
 
37
        gchar* result = g_strconcat ("file://", current_dir, G_DIR_SEPARATOR_S, uri, NULL);
 
38
        g_free (current_dir);
 
39
        return result;
 
40
    }
 
41
    // Do we need to add a protocol?
 
42
    if (!strstr (uri, "://"))
 
43
    {
 
44
        // Do we have a domain, ip address or localhost?
 
45
        if (strchr (uri, '.') != NULL || !strcmp (uri, "localhost"))
 
46
            return g_strconcat ("http://", uri, NULL);
 
47
        // We don't want to search? So return early.
 
48
        if (!default_search_uri)
 
49
            return g_strdup (uri);
 
50
        gchar* search;
 
51
        const gchar* search_uri = NULL;
 
52
        // Do we have a keyword and a string?
 
53
        gchar** parts = g_strsplit (uri, " ", 2);
 
54
        if (parts[0] && parts[1])
 
55
        {
 
56
            guint n = g_list_length (searchEngines);
 
57
            guint i;
 
58
            for (i = 0; i < n; i++)
 
59
            {
 
60
                SearchEngine* search_engine = (SearchEngine*)g_list_nth_data (
 
61
                    searchEngines, i);
 
62
                if (!strcmp (search_engine_get_keyword (search_engine),
 
63
                                                        parts[0]))
 
64
                    search_uri = search_engine->url;
 
65
            }
 
66
        if (search_uri)
 
67
            search = g_strdup_printf (search_uri, parts[1]);
 
68
        }
 
69
        // We only have a word or there is no matching keyword, so search for it
 
70
        if (!search_uri)
 
71
            search = g_strdup_printf (default_search_uri, uri);
 
72
        return search;
 
73
    }
 
74
    return g_strdup (uri);
 
75
}
 
76
 
 
77
void
 
78
sokoke_entry_setup_completion (GtkEntry* entry)
 
79
{
 
80
    /* TODO: The current behavior works only with the beginning of strings
 
81
             But we want to match "localhost" with "loc" and "hos" */
 
82
    GtkEntryCompletion* completion = gtk_entry_completion_new ();
 
83
    gtk_entry_completion_set_model (completion,
 
84
        GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING)));
 
85
    gtk_entry_completion_set_text_column (completion, 0);
 
86
    gtk_entry_completion_set_minimum_key_length (completion, 3);
 
87
    gtk_entry_set_completion (entry, completion);
 
88
    gtk_entry_completion_set_popup_completion (completion, FALSE); //...
 
89
}
 
90
 
 
91
void
 
92
sokoke_entry_append_completion (GtkEntry* entry, const gchar* text)
 
93
{
 
94
    GtkEntryCompletion* completion = gtk_entry_get_completion (entry);
 
95
    GtkTreeModel* completion_store = gtk_entry_completion_get_model (completion);
 
96
    GtkTreeIter iter;
 
97
    gtk_list_store_insert (GTK_LIST_STORE (completion_store), &iter, 0);
 
98
    gtk_list_store_set (GTK_LIST_STORE (completion_store), &iter, 0, text, -1);
 
99
}
 
100
 
 
101
void
 
102
sokoke_combo_box_add_strings (GtkComboBox* combobox,
 
103
                              const gchar* label_first, ...)
 
104
{
 
105
    // Add a number of strings to a combobox, terminated with NULL
 
106
    // This works only for text comboboxes
 
107
    va_list args;
 
108
    va_start (args, label_first);
 
109
 
 
110
    const gchar* label;
 
111
    for (label = label_first; label; label = va_arg (args, const gchar*))
 
112
        gtk_combo_box_append_text (combobox, label);
 
113
 
 
114
    va_end (args);
 
115
}
 
116
 
 
117
void sokoke_widget_set_visible (GtkWidget* widget, gboolean visible)
 
118
{
 
119
    // Show or hide the widget
 
120
    if (visible)
 
121
        gtk_widget_show (widget);
 
122
    else
 
123
        gtk_widget_hide (widget);
 
124
}
 
125
 
 
126
void
 
127
sokoke_container_show_children (GtkContainer* container)
 
128
{
 
129
    // Show every child but not the container itself
 
130
    gtk_container_foreach (container, (GtkCallback)(gtk_widget_show_all), NULL);
 
131
}
 
132
 
 
133
void
 
134
sokoke_widget_set_tooltip_text (GtkWidget* widget, const gchar* text)
 
135
{
 
136
    #if GTK_CHECK_VERSION(2, 12, 0)
 
137
    gtk_widget_set_tooltip_text (widget, text);
 
138
    #else
 
139
    static GtkTooltips* tooltips;
 
140
    if (!tooltips)
 
141
        tooltips = gtk_tooltips_new ();
 
142
    gtk_tooltips_set_tip (tooltips, widget, text, NULL);
 
143
    #endif
 
144
}
 
145
 
 
146
void
 
147
sokoke_tool_item_set_tooltip_text (GtkToolItem* toolitem, const gchar* text)
 
148
{
 
149
    if (text && *text)
 
150
    {
 
151
        #if GTK_CHECK_VERSION(2, 12, 0)
 
152
        gtk_tool_item_set_tooltip_text (toolitem, text);
 
153
        #else
 
154
        static GtkTooltips* tooltips = NULL;
 
155
        if (G_UNLIKELY (!tooltips))
 
156
            tooltips = gtk_tooltips_new();
 
157
 
 
158
        gtk_tool_item_set_tooltip (toolitem, tooltips, text, NULL);
 
159
        #endif
 
160
    }
 
161
}
 
162
 
 
163
typedef struct
 
164
{
 
165
     GtkWidget* widget;
 
166
     SokokeMenuPos position;
 
167
} SokokePopupInfo;
 
168
 
 
169
static void
 
170
sokoke_widget_popup_position_menu (GtkMenu*  menu,
 
171
                                   gint*     x,
 
172
                                   gint*     y,
 
173
                                   gboolean* push_in,
 
174
                                   gpointer  user_data)
 
175
{
 
176
    gint wx, wy;
 
177
    gint menu_width;
 
178
    GtkRequisition menu_req;
 
179
    GtkRequisition widget_req;
 
180
    SokokePopupInfo* info = user_data;
 
181
    GtkWidget* widget = info->widget;
 
182
 
 
183
    // Retrieve size and position of both widget and menu
 
184
    if (GTK_WIDGET_NO_WINDOW (widget))
 
185
    {
 
186
        gdk_window_get_position (widget->window, &wx, &wy);
 
187
        wx += widget->allocation.x;
 
188
        wy += widget->allocation.y;
 
189
    }
 
190
    else
 
191
        gdk_window_get_origin (widget->window, &wx, &wy);
 
192
    gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
 
193
    gtk_widget_size_request (widget, &widget_req);
 
194
    menu_width = menu_req.width;
 
195
    gint widget_height = widget_req.height; // Better than allocation.height
 
196
 
 
197
    // Calculate menu position
 
198
    if (info->position == SOKOKE_MENU_POSITION_CURSOR)
 
199
        ; // Do nothing?
 
200
    else if (info->position == SOKOKE_MENU_POSITION_RIGHT)
 
201
    {
 
202
        *x = wx + widget->allocation.width - menu_width;
 
203
        *y = wy + widget_height;
 
204
    } else if (info->position == SOKOKE_MENU_POSITION_LEFT)
 
205
    {
 
206
        *x = wx;
 
207
        *y = wy + widget_height;
 
208
    }
 
209
 
 
210
    *push_in = TRUE;
 
211
}
 
212
 
 
213
 
 
214
void
 
215
sokoke_widget_popup (GtkWidget*      widget,
 
216
                     GtkMenu*        menu,
 
217
                     GdkEventButton* event,
 
218
                     SokokeMenuPos   pos)
 
219
{
 
220
    int button, event_time;
 
221
    if (event)
 
222
    {
 
223
        button = event->button;
 
224
        event_time = event->time;
 
225
    }
 
226
    else
 
227
    {
 
228
        button = 0;
 
229
        event_time = gtk_get_current_event_time ();
 
230
    }
 
231
 
 
232
    if (!gtk_menu_get_attach_widget(menu))
 
233
        gtk_menu_attach_to_widget (menu, widget, NULL);
 
234
 
 
235
    if (widget)
 
236
    {
 
237
        SokokePopupInfo info = { widget, pos };
 
238
        gtk_menu_popup (menu, NULL, NULL,
 
239
                        sokoke_widget_popup_position_menu, &info,
 
240
                        button, event_time);
 
241
    }
 
242
    else
 
243
        gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time);
 
244
}
 
245
 
 
246
typedef enum
 
247
{
 
248
    SOKOKE_DESKTOP_UNTESTED,
 
249
    SOKOKE_DESKTOP_XFCE,
 
250
    SOKOKE_DESKTOP_UNKNOWN
 
251
} SokokeDesktop;
 
252
 
 
253
static SokokeDesktop
 
254
sokoke_get_desktop (void)
 
255
{
 
256
    static SokokeDesktop desktop = SOKOKE_DESKTOP_UNTESTED;
 
257
    if (G_UNLIKELY (desktop == SOKOKE_DESKTOP_UNTESTED))
 
258
    {
 
259
        // Are we running in Xfce?
 
260
        gint result; gchar* out; gchar* err;
 
261
        gboolean success = g_spawn_command_line_sync (
 
262
            "xprop -root _DT_SAVE_MODE | grep -q xfce4",
 
263
            &out, &err, &result, NULL);
 
264
        if (success && !result)
 
265
            desktop = SOKOKE_DESKTOP_XFCE;
 
266
        else
 
267
            desktop = SOKOKE_DESKTOP_UNKNOWN;
 
268
    }
 
269
 
 
270
    return desktop;
 
271
}
 
272
 
 
273
GtkWidget*
 
274
sokoke_xfce_header_new (const gchar* icon,
 
275
                        const gchar* title)
 
276
{
 
277
    // Create an xfce header with icon and title
 
278
    // This returns NULL if the desktop is not xfce
 
279
    if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE)
 
280
    {
 
281
        GtkWidget* entry = gtk_entry_new ();
 
282
        gchar* markup;
 
283
        GtkWidget* xfce_heading = gtk_event_box_new ();
 
284
        gtk_widget_modify_bg (xfce_heading, GTK_STATE_NORMAL,
 
285
            &entry->style->base[GTK_STATE_NORMAL]);
 
286
        GtkWidget* hbox = gtk_hbox_new (FALSE, 12);
 
287
        gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
 
288
        GtkWidget* image = gtk_image_new_from_icon_name (icon,
 
289
                                                         GTK_ICON_SIZE_DIALOG);
 
290
        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
 
291
        GtkWidget* label = gtk_label_new (NULL);
 
292
        gtk_widget_modify_fg (label, GTK_STATE_NORMAL
 
293
         , &entry->style->text[GTK_STATE_NORMAL]);
 
294
        markup = g_strdup_printf ("<span size='large' weight='bold'>%s</span>",
 
295
                                  title);
 
296
        gtk_label_set_markup (GTK_LABEL (label), markup);
 
297
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
298
        gtk_container_add (GTK_CONTAINER (xfce_heading), hbox);
 
299
        g_free (markup);
 
300
        return xfce_heading;
 
301
    }
 
302
    return NULL;
 
303
}
 
304
 
 
305
GtkWidget*
 
306
sokoke_superuser_warning_new (void)
 
307
{
 
308
    // Create a horizontal bar with a security warning
 
309
    // This returns NULL if the user is no superuser
 
310
    #ifdef HAVE_UNISTD_H
 
311
    if (G_UNLIKELY (!geteuid ())) // effective superuser?
 
312
    {
 
313
        GtkWidget* hbox = gtk_event_box_new ();
 
314
        gtk_widget_modify_bg (hbox, GTK_STATE_NORMAL,
 
315
                              &hbox->style->bg[GTK_STATE_SELECTED]);
 
316
        GtkWidget* label = gtk_label_new (
 
317
            _("Warning: You are using a superuser account!"));
 
318
        gtk_misc_set_padding (GTK_MISC (label), 0, 2);
 
319
        gtk_widget_modify_fg (GTK_WIDGET (label), GTK_STATE_NORMAL,
 
320
            &GTK_WIDGET (label)->style->fg[GTK_STATE_SELECTED]);
 
321
        gtk_widget_show (label);
 
322
        gtk_container_add (GTK_CONTAINER(hbox), GTK_WIDGET (label));
 
323
        gtk_widget_show (hbox);
 
324
        return hbox;
 
325
    }
 
326
    #endif
 
327
    return NULL;
 
328
}
 
329
 
 
330
GtkWidget*
 
331
sokoke_hig_frame_new (const gchar* title)
 
332
{
 
333
    // Create a frame with no actual frame but a bold label and indentation
 
334
    GtkWidget* frame = gtk_frame_new (NULL);
 
335
    gchar* title_bold = g_strdup_printf ("<b>%s</b>", title);
 
336
    GtkWidget* label = gtk_label_new (NULL);
 
337
    gtk_label_set_markup (GTK_LABEL (label), title_bold);
 
338
    g_free (title_bold);
 
339
    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
 
340
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
 
341
    return frame;
 
342
}
 
343
 
 
344
void
 
345
sokoke_widget_set_pango_font_style (GtkWidget* widget,
 
346
                                    PangoStyle style)
 
347
{
 
348
    // Conveniently change the pango font style
 
349
    // For some reason we need to reset if we actually want the normal style
 
350
    if (style == PANGO_STYLE_NORMAL)
 
351
        gtk_widget_modify_font (widget, NULL);
 
352
    else
 
353
    {
 
354
        PangoFontDescription* font_description = pango_font_description_new ();
 
355
        pango_font_description_set_style (font_description, PANGO_STYLE_ITALIC);
 
356
        gtk_widget_modify_font (widget, font_description);
 
357
        pango_font_description_free (font_description);
 
358
    }
 
359
}
 
360
 
 
361
static gboolean
 
362
sokoke_on_entry_focus_in_event (GtkEntry*      entry,
 
363
                                GdkEventFocus* event,
 
364
                                gpointer       userdata)
 
365
{
 
366
    gint default_text = GPOINTER_TO_INT (
 
367
        g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
 
368
    if (default_text)
 
369
    {
 
370
        gtk_entry_set_text (entry, "");
 
371
        g_object_set_data (G_OBJECT(entry), "sokoke_has_default",
 
372
                           GINT_TO_POINTER (0));
 
373
        sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
 
374
                                            PANGO_STYLE_NORMAL);
 
375
    }
 
376
    return FALSE;
 
377
}
 
378
 
 
379
static gboolean
 
380
sokoke_on_entry_focus_out_event (GtkEntry*      entry,
 
381
                                 GdkEventFocus* event,
 
382
                                 gpointer       userdata)
 
383
{
 
384
    const gchar* text = gtk_entry_get_text (entry);
 
385
    if (text && !*text)
 
386
    {
 
387
        const gchar* defaultText = (const gchar*)g_object_get_data (
 
388
         G_OBJECT (entry), "sokoke_default_text");
 
389
        gtk_entry_set_text (entry, defaultText);
 
390
        g_object_set_data (G_OBJECT(entry),
 
391
                           "sokoke_has_default", GINT_TO_POINTER (1));
 
392
        sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
 
393
                                            PANGO_STYLE_ITALIC);
 
394
    }
 
395
    return FALSE;
 
396
}
 
397
 
 
398
void
 
399
sokoke_entry_set_default_text (GtkEntry*    entry,
 
400
                               const gchar* default_text)
 
401
{
 
402
    // Note: The default text initially overwrites any previous text
 
403
    gchar* old_value = g_object_get_data (G_OBJECT (entry),
 
404
                                          "sokoke_default_text");
 
405
    if (!old_value)
 
406
    {
 
407
        g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
 
408
                           GINT_TO_POINTER (1));
 
409
        sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
 
410
                                            PANGO_STYLE_ITALIC);
 
411
        gtk_entry_set_text (entry, default_text);
 
412
    }
 
413
    g_object_set_data (G_OBJECT (entry), "sokoke_default_text",
 
414
                       (gpointer)default_text);
 
415
    g_signal_connect (entry, "focus-in-event",
 
416
        G_CALLBACK (sokoke_on_entry_focus_in_event), NULL);
 
417
    g_signal_connect (entry, "focus-out-event",
 
418
        G_CALLBACK (sokoke_on_entry_focus_out_event), NULL);
 
419
}
 
420
 
 
421
gchar*
 
422
sokoke_key_file_get_string_default (GKeyFile*    key_file,
 
423
                                    const gchar* group,
 
424
                                    const gchar* key,
 
425
                                    const gchar* default_value,
 
426
                                    GError**     error)
 
427
{
 
428
    gchar* value = g_key_file_get_string (key_file, group, key, error);
 
429
    return value == NULL ? g_strdup (default_value) : value;
 
430
}
 
431
 
 
432
gint
 
433
sokoke_key_file_get_integer_default (GKeyFile*    key_file,
 
434
                                     const gchar* group,
 
435
                                     const gchar* key,
 
436
                                     const gint   default_value,
 
437
                                     GError**     error)
 
438
{
 
439
    if (!g_key_file_has_key (key_file, group, key, NULL))
 
440
        return default_value;
 
441
    return g_key_file_get_integer (key_file, group, key, error);
 
442
}
 
443
 
 
444
gdouble
 
445
sokoke_key_file_get_double_default (GKeyFile*     key_file,
 
446
                                    const gchar*  group,
 
447
                                    const gchar*  key,
 
448
                                    const gdouble default_value,
 
449
                                    GError**      error)
 
450
{
 
451
    if (!g_key_file_has_key (key_file, group, key, NULL))
 
452
        return default_value;
 
453
    return g_key_file_get_double (key_file, group, key, error);
 
454
}
 
455
 
 
456
gboolean
 
457
sokoke_key_file_get_boolean_default (GKeyFile*      key_file,
 
458
                                     const gchar*   group,
 
459
                                     const gchar*   key,
 
460
                                     const gboolean default_value,
 
461
                                     GError**       error)
 
462
{
 
463
    if (!g_key_file_has_key (key_file, group, key, NULL))
 
464
        return default_value;
 
465
    return g_key_file_get_boolean (key_file, group, key, error);
 
466
}
 
467
 
 
468
gboolean
 
469
sokoke_key_file_save_to_file (GKeyFile*    key_file,
 
470
                              const gchar* filename,
 
471
                              GError**     error)
 
472
{
 
473
    gchar* data = g_key_file_to_data (key_file, NULL, error);
 
474
    if (!data)
 
475
        return FALSE;
 
476
    FILE* fp;
 
477
    if (!(fp = fopen (filename, "w")))
 
478
    {
 
479
        *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_ACCES,
 
480
                              _("Writing failed."));
 
481
        return FALSE;
 
482
    }
 
483
    fputs (data, fp);
 
484
    fclose (fp);
 
485
    g_free (data);
 
486
    return TRUE;
 
487
}
 
488
 
 
489
void
 
490
sokoke_widget_get_text_size (GtkWidget*   widget,
 
491
                             const gchar* text,
 
492
                             gint*        width,
 
493
                             gint*        height)
 
494
{
 
495
    PangoLayout* layout = gtk_widget_create_pango_layout (widget, text);
 
496
    pango_layout_get_pixel_size (layout, width, height);
 
497
    g_object_unref (layout);
 
498
}