~ubuntu-branches/ubuntu/quantal/libfm/quantal

« back to all changes in this revision

Viewing changes to .pc/02-libfm-0.1.14-API-changes.patch/src/gtk/fm-path-entry.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2011-02-21 21:55:43 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20110221215543-m7gn2snkhpk1kk9u
Tags: 0.1.15+git-3625952cea-0ubuntu1
* New upstream snapshot (2011-02-15)
 - Use x-schemas-handler (LP: #683922)
* debian/patches/
 - 90_add_gobject_link.patch: Remove, merged upstream.
 - 02-libfm-0.1.14-API-changes.patch: Refresh.
 - 03_disable_deprecated_gio_module.patch: Refresh.
 - 04_fix_docs_linker.patch: Fix DSO linking in docs/.
* debian/libfm0.install:
 - Remove usr/lib/libfm/gnome-terminal, dropped upstream.
 - Remove gio module, dropped upstream.
* debian/rules:
 - Add --enable-gtk-doc to configure.
* debian/libfm-gtk0.symbols:
 - Update with new symbols.
* debian/apport/source_libfm.py
 - Fix location of pcmanfm config files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *      fm-path-entry.c
3
 
 *
4
 
 *      Copyright 2009 PCMan <pcman.tw@gmail.com>
5
 
 *      Copyright 2009 Jürgen Hötzel <juergen@archlinux.org>
6
 
 *
7
 
 *      This program is free software; you can redistribute it and/or modify
8
 
 *      it under the terms of the GNU General Public License as published by
9
 
 *      the Free Software Foundation; either version 2 of the License, or
10
 
 *      (at your option) any later version.
11
 
 *
12
 
 *      This program is distributed in the hope that it will be useful,
13
 
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *      GNU General Public License for more details.
16
 
 *
17
 
 *      You should have received a copy of the GNU General Public License
18
 
 *      along with this program; if not, write to the Free Software
19
 
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
 
 *      MA 02110-1301, USA.
21
 
 */
22
 
 
23
 
#include "fm-path-entry.h"
24
 
/* for completion */
25
 
#include "fm-folder-model.h"
26
 
#include <string.h>
27
 
#include <gio/gio.h>
28
 
#include <gdk/gdkkeysyms.h>
29
 
/* properties */
30
 
enum
31
 
{
32
 
    PROP_0,
33
 
    PROP_HIGHLIGHT_COMPLETION_MATCH
34
 
};
35
 
 
36
 
#define FM_PATH_ENTRY_GET_PRIVATE(obj) ( G_TYPE_INSTANCE_GET_PRIVATE( (obj), FM_TYPE_PATH_ENTRY, FmPathEntryPrivate ) )
37
 
 
38
 
typedef struct _FmPathEntryPrivate FmPathEntryPrivate;
39
 
 
40
 
struct _FmPathEntryPrivate
41
 
{
42
 
    FmPath* path;
43
 
    /* associated with a folder model */
44
 
    FmFolderModel* model;
45
 
    /* current model used for completion */
46
 
    FmFolderModel* completion_model;
47
 
    /* Current len of the completion string */
48
 
    gint completion_len;
49
 
    /* prevent recurs. if text is changed by insert. compl. suffix */
50
 
    gboolean in_change;
51
 
    gboolean highlight_completion_match;
52
 
    GtkEntryCompletion* completion;
53
 
    /* automatic common suffix completion */
54
 
    gint common_suffix_append_idle_id;
55
 
    gchar common_suffix[PATH_MAX];
56
 
};
57
 
 
58
 
static void      fm_path_entry_activate(GtkEntry *entry);
59
 
static gboolean  fm_path_entry_key_press(GtkWidget   *widget, GdkEventKey *event);
60
 
static void      fm_path_entry_class_init(FmPathEntryClass *klass);
61
 
static void  fm_path_entry_editable_init(GtkEditableClass *iface);
62
 
static void      fm_path_entry_changed(GtkEditable *editable);
63
 
static void      fm_path_entry_do_insert_text(GtkEditable *editable,
64
 
                                              const gchar *new_text,
65
 
                                              gint new_text_length,
66
 
                                              gint        *position);
67
 
static gboolean  fm_path_entry_suffix_append_idle(gpointer user_data);
68
 
static void      fm_path_entry_suffix_append_idle_destroy(gpointer user_data);
69
 
static gboolean  fm_path_entry_update_expand_path(FmPathEntry *entry);
70
 
static void      fm_path_entry_init(FmPathEntry *entry);
71
 
static void      fm_path_entry_finalize(GObject *object);
72
 
static gboolean  fm_path_entry_match_func(GtkEntryCompletion   *completion,
73
 
                                          const gchar          *key,
74
 
                                          GtkTreeIter          *iter,
75
 
                                          gpointer user_data);
76
 
static gboolean  fm_path_entry_match_selected(GtkEntryCompletion *widget,
77
 
                                              GtkTreeModel       *model,
78
 
                                              GtkTreeIter        *iter,
79
 
                                              gpointer user_data);
80
 
static void fm_path_entry_completion_render_func(GtkCellLayout *cell_layout,
81
 
                                                 GtkCellRenderer *cell,
82
 
                                                 GtkTreeModel *model,
83
 
                                                 GtkTreeIter *iter,
84
 
                                                 gpointer data);
85
 
static void fm_path_entry_set_property(GObject *object,
86
 
                                       guint prop_id,
87
 
                                       const GValue *value,
88
 
                                       GParamSpec *pspec);
89
 
static void fm_path_entry_get_property(GObject *object,
90
 
                                       guint prop_id,
91
 
                                       GValue *value,
92
 
                                       GParamSpec *pspec);
93
 
 
94
 
G_DEFINE_TYPE_EXTENDED( FmPathEntry, fm_path_entry, GTK_TYPE_ENTRY,
95
 
                       0, G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE, fm_path_entry_editable_init) );
96
 
 
97
 
static GtkEditableClass *parent_editable_interface = NULL;
98
 
 
99
 
static gboolean fm_path_entry_key_press(GtkWidget   *widget, GdkEventKey *event) {
100
 
    FmPathEntry *entry = FM_PATH_ENTRY(widget);
101
 
 
102
 
    switch( event->keyval )
103
 
    {
104
 
    case GDK_Tab:
105
 
        /* place the cursor at the end */
106
 
        gtk_editable_set_position(GTK_EDITABLE(entry), -1);
107
 
        return TRUE;
108
 
    }
109
 
    return FALSE;
110
 
}
111
 
 
112
 
static void  fm_path_entry_activate(GtkEntry *entry)
113
 
{
114
 
    /* Chain up so that entry->activates_default is honored */
115
 
    GTK_ENTRY_CLASS(fm_path_entry_parent_class)->activate(entry);
116
 
}
117
 
 
118
 
static void fm_path_entry_class_init(FmPathEntryClass *klass)
119
 
{
120
 
    GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
121
 
    GObjectClass* object_class = G_OBJECT_CLASS(klass);
122
 
    GtkEntryClass* entry_class = GTK_ENTRY_CLASS(klass);
123
 
 
124
 
    object_class->get_property = fm_path_entry_get_property;
125
 
    object_class->set_property = fm_path_entry_set_property;
126
 
    g_object_class_install_property( object_class,
127
 
                                    PROP_HIGHLIGHT_COMPLETION_MATCH,
128
 
                                    g_param_spec_boolean("highlight-completion-match",
129
 
                                                         "Highlight completion match",
130
 
                                                         "Wheather to highlight the completion match",
131
 
                                                         TRUE, G_PARAM_READWRITE) );
132
 
    object_class->finalize = fm_path_entry_finalize;
133
 
    entry_class->activate = fm_path_entry_activate;
134
 
 
135
 
    g_type_class_add_private( klass, sizeof (FmPathEntryPrivate) );
136
 
}
137
 
 
138
 
static void fm_path_entry_editable_init(GtkEditableClass *iface)
139
 
{
140
 
    parent_editable_interface = g_type_interface_peek_parent(iface);
141
 
    iface->changed = fm_path_entry_changed;
142
 
    iface->do_insert_text = fm_path_entry_do_insert_text;
143
 
}
144
 
 
145
 
static void fm_path_entry_changed(GtkEditable *editable)
146
 
{
147
 
    FmPathEntry *entry = FM_PATH_ENTRY(editable);
148
 
    FmPathEntryPrivate *priv  = FM_PATH_ENTRY_GET_PRIVATE(entry);
149
 
    const gchar *original_key = gtk_entry_get_text( GTK_ENTRY(entry) );
150
 
    /* len of directory part */
151
 
    gint key_dir_len;
152
 
    gchar *last_slash = strrchr(original_key, G_DIR_SEPARATOR);
153
 
 
154
 
    if( priv->in_change || !priv->path )
155
 
        return;
156
 
 
157
 
    /* not path -> keep current completion model */
158
 
    if( last_slash == NULL )
159
 
        return;
160
 
 
161
 
    /* Check if path entry is not part of current completion folder model */
162
 
    key_dir_len = last_slash - original_key;
163
 
    if( !fm_path_equal_str(priv->path, original_key, key_dir_len) )
164
 
    {
165
 
        gchar* new_path = g_path_get_dirname(original_key);
166
 
        FmPath *new_fm_path = fm_path_new(new_path);
167
 
        g_free(new_path);
168
 
        if( new_fm_path != NULL )
169
 
        {
170
 
            /* set hidden parameter based on prev. model */
171
 
            /* FIXME: this is not very good */
172
 
            gboolean show_hidden = priv->completion_model ? fm_folder_model_get_show_hidden(priv->completion_model) : FALSE;
173
 
            if(priv->completion_model)
174
 
                g_object_unref(priv->completion_model);
175
 
            if(priv->model && fm_path_equal(priv->model->dir->dir_path, new_fm_path))
176
 
            {
177
 
                if(priv->path)
178
 
                    fm_path_unref(priv->path);
179
 
                priv->path = fm_path_ref(priv->model->dir->dir_path);
180
 
                fm_path_unref(new_fm_path);
181
 
                priv->completion_model = g_object_ref(priv->model);
182
 
            }
183
 
            else
184
 
            {
185
 
                FmFolder *new_fm_folder = fm_folder_get_for_path(new_fm_path);
186
 
                FmFolderModel *new_fm = fm_folder_model_new(new_fm_folder, show_hidden);
187
 
                g_object_unref(new_fm_folder);
188
 
                priv->completion_model = new_fm;
189
 
                if(priv->path)
190
 
                    fm_path_unref(priv->path);
191
 
                priv->path = new_fm_path;
192
 
            }
193
 
            if(priv->completion)
194
 
                gtk_entry_completion_set_model( priv->completion, GTK_TREE_MODEL(priv->completion_model) );
195
 
        }
196
 
        else
197
 
        {
198
 
            /* FIXME: Handle invalid Paths */
199
 
            g_warning("Invalid Path: %s", new_path);
200
 
        }
201
 
    }
202
 
}
203
 
 
204
 
static void fm_path_entry_do_insert_text(GtkEditable *editable, const gchar *new_text,
205
 
                                         gint new_text_length, gint        *position)
206
 
{
207
 
    FmPathEntry *entry = FM_PATH_ENTRY(editable);
208
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE(entry);
209
 
    /* let the GtkEntry class handle the insert */
210
 
    (parent_editable_interface->do_insert_text)(editable, new_text, new_text_length, position);
211
 
 
212
 
    if( GTK_WIDGET_HAS_FOCUS(editable) && priv->completion_model )
213
 
    {
214
 
        /* we have a common suffix -> add idle function */
215
 
        if( (priv->common_suffix_append_idle_id < 0) && ( fm_path_entry_update_expand_path(entry) ) )
216
 
            priv->common_suffix_append_idle_id  = g_idle_add_full(G_PRIORITY_HIGH,
217
 
                                                                     fm_path_entry_suffix_append_idle,
218
 
                                                                     entry, fm_path_entry_suffix_append_idle_destroy);
219
 
    }
220
 
}
221
 
 
222
 
static gboolean fm_path_entry_suffix_append_idle(gpointer user_data)
223
 
{
224
 
    FmPathEntry *entry = FM_PATH_ENTRY(user_data);
225
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE(entry);
226
 
    const gchar *original_key = gtk_entry_get_text( GTK_ENTRY(entry) );
227
 
 
228
 
    /* we have a common suffix -> insert/select it */
229
 
    fm_path_entry_update_expand_path(entry);
230
 
    if( priv->common_suffix[0] )
231
 
    {
232
 
        gint suffix_offset = g_utf8_strlen(original_key, -1);
233
 
        gint suffix_offset_save = suffix_offset;
234
 
        /* dont recur */
235
 
        priv->in_change = TRUE;
236
 
        gtk_editable_insert_text(GTK_EDITABLE(entry), priv->common_suffix, -1,  &suffix_offset);
237
 
        gtk_editable_select_region(GTK_EDITABLE(entry), suffix_offset_save, -1);
238
 
        priv->in_change = FALSE;
239
 
    }
240
 
    /* don't call again */
241
 
    return FALSE;
242
 
}
243
 
 
244
 
static void fm_path_entry_suffix_append_idle_destroy(gpointer user_data)
245
 
{
246
 
    FmPathEntry *entry = FM_PATH_ENTRY(user_data);
247
 
    FM_PATH_ENTRY_GET_PRIVATE(entry)->common_suffix_append_idle_id = -1;
248
 
}
249
 
 
250
 
static gboolean fm_path_entry_update_expand_path(FmPathEntry *entry)
251
 
{
252
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE(entry);
253
 
    const gchar *original_key = gtk_entry_get_text( GTK_ENTRY(entry) );
254
 
    /* len of directory part */
255
 
    gint key_dir_len;
256
 
    gchar *last_slash = strrchr(original_key, G_DIR_SEPARATOR);
257
 
 
258
 
    priv->common_suffix[0] = 0;
259
 
 
260
 
    /* get completion suffix */
261
 
    if( last_slash && priv->completion_model )
262
 
        fm_folder_model_get_common_suffix_for_prefix(priv->completion_model,
263
 
                                                     last_slash + 1,
264
 
                                                     fm_file_info_is_dir,
265
 
                                                     priv->common_suffix);
266
 
    return (priv->common_suffix[0] != 0);
267
 
}
268
 
 
269
 
static void fm_path_entry_set_property(GObject *object,
270
 
                                       guint prop_id,
271
 
                                       const GValue *value,
272
 
                                       GParamSpec *pspec)
273
 
{
274
 
    FmPathEntry *entry = FM_PATH_ENTRY(object);
275
 
    FmPathEntryPrivate *priv  = FM_PATH_ENTRY_GET_PRIVATE(entry);
276
 
 
277
 
    switch( prop_id )
278
 
    {
279
 
    case PROP_HIGHLIGHT_COMPLETION_MATCH:
280
 
        priv->highlight_completion_match = g_value_get_boolean(value);
281
 
        break;
282
 
    default:
283
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
284
 
        break;
285
 
    }
286
 
}
287
 
 
288
 
static void fm_path_entry_get_property(GObject *object,
289
 
                                       guint prop_id,
290
 
                                       GValue *value,
291
 
                                       GParamSpec *pspec)
292
 
{
293
 
    FmPathEntry *entry = FM_PATH_ENTRY(object);
294
 
    FmPathEntryPrivate *priv  = FM_PATH_ENTRY_GET_PRIVATE(entry);
295
 
 
296
 
    switch( prop_id ) {
297
 
    case PROP_HIGHLIGHT_COMPLETION_MATCH:
298
 
        g_value_set_boolean(value, priv->highlight_completion_match);
299
 
        break;
300
 
    default:
301
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
302
 
        break;
303
 
    }
304
 
}
305
 
 
306
 
static void
307
 
fm_path_entry_init(FmPathEntry *entry)
308
 
{
309
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE(entry);
310
 
    GtkEntryCompletion* completion = gtk_entry_completion_new();
311
 
    GtkCellRenderer* render;
312
 
 
313
 
    priv->model = NULL;
314
 
    priv->completion_model = NULL;
315
 
    priv->completion_len = 0;
316
 
    priv->in_change = FALSE;
317
 
    priv->completion = completion;
318
 
    priv->highlight_completion_match = TRUE;
319
 
    priv->common_suffix_append_idle_id = -1;
320
 
    priv->common_suffix[0] = 0;
321
 
    gtk_entry_completion_set_minimum_key_length(completion, 1);
322
 
    gtk_entry_completion_set_match_func(completion, fm_path_entry_match_func, NULL, NULL);
323
 
    g_signal_connect(G_OBJECT(completion), "match-selected", G_CALLBACK(fm_path_entry_match_selected), (gpointer)NULL);
324
 
    g_object_set(completion, "text-column", COL_FILE_NAME, NULL);
325
 
    render = gtk_cell_renderer_text_new();
326
 
    gtk_cell_layout_pack_start( (GtkCellLayout*)completion, render, TRUE );
327
 
    gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(completion), render, fm_path_entry_completion_render_func, entry, NULL);
328
 
    gtk_entry_completion_set_inline_completion(completion, TRUE);
329
 
    gtk_entry_completion_set_popup_set_width(completion, TRUE);
330
 
    g_signal_connect(G_OBJECT(entry), "key-press-event", G_CALLBACK(fm_path_entry_key_press), NULL);
331
 
    gtk_entry_set_completion(GTK_ENTRY(entry), completion);
332
 
}
333
 
 
334
 
static void fm_path_entry_completion_render_func(GtkCellLayout *cell_layout,
335
 
                                                 GtkCellRenderer *cell,
336
 
                                                 GtkTreeModel *model,
337
 
                                                 GtkTreeIter *iter,
338
 
                                                 gpointer data)
339
 
{
340
 
 
341
 
    gchar *model_file_name;
342
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE( FM_PATH_ENTRY(data) );
343
 
    gtk_tree_model_get(GTK_TREE_MODEL(model), iter,
344
 
                       COL_FILE_NAME, &model_file_name, -1);
345
 
    if( priv->highlight_completion_match )
346
 
    {
347
 
        gchar markup[PATH_MAX];
348
 
        gchar *trail = g_stpcpy(markup, "<b><u>");
349
 
        trail = strncpy(trail, model_file_name, priv->completion_len) + priv->completion_len;
350
 
        trail = g_stpcpy(trail, "</u></b>");
351
 
        trail = g_stpcpy(trail, model_file_name + priv->completion_len);
352
 
        g_object_set(cell, "markup", markup, NULL);
353
 
    }
354
 
    /* FIXME: We don't need a custom render func if we don't hightlight */
355
 
    else
356
 
        g_object_set(cell, "text", model_file_name, NULL);
357
 
}
358
 
 
359
 
static void
360
 
fm_path_entry_finalize(GObject *object)
361
 
{
362
 
    FmPathEntryPrivate* priv = FM_PATH_ENTRY_GET_PRIVATE(object);
363
 
 
364
 
    if(priv->completion)
365
 
        g_object_unref(priv->completion);
366
 
 
367
 
    if(priv->path)
368
 
        fm_path_unref(priv->path);
369
 
 
370
 
    /* release the folder model reference */
371
 
    if(priv->model)
372
 
        g_object_unref(priv->model);
373
 
 
374
 
    if(priv->completion_model)
375
 
        g_object_unref(priv->completion_model);
376
 
 
377
 
    /* drop idle func for suffix completion */
378
 
    if( priv->common_suffix_append_idle_id > 0 )
379
 
        g_source_remove(priv->common_suffix_append_idle_id);
380
 
 
381
 
    (*G_OBJECT_CLASS(fm_path_entry_parent_class)->finalize)(object);
382
 
 
383
 
}
384
 
 
385
 
GtkWidget* fm_path_entry_new()
386
 
{
387
 
    return g_object_new(FM_TYPE_PATH_ENTRY, NULL);
388
 
}
389
 
 
390
 
void fm_path_entry_set_model(FmPathEntry *entry, FmPath* path, FmFolderModel* model)
391
 
{
392
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE(entry);
393
 
    /* FIXME: should we use UTF-8 encoded display name here? */
394
 
    gchar *path_str = fm_path_display_name(path, FALSE);
395
 
    if(priv->path)
396
 
        fm_path_unref(priv->path);
397
 
    priv->path = fm_path_ref(path);
398
 
 
399
 
    if( priv->model )
400
 
        g_object_unref( priv->model );
401
 
    if( priv->completion_model )
402
 
        g_object_unref(priv->completion_model);
403
 
    if(model)
404
 
    {
405
 
        priv->model = g_object_ref(model);
406
 
        priv->completion_model = g_object_ref(model);
407
 
        gtk_entry_set_completion(GTK_ENTRY(entry), priv->completion);
408
 
    }
409
 
    else
410
 
    {
411
 
        priv->model = NULL;
412
 
        priv->completion_model = NULL;
413
 
        if(priv->completion)
414
 
        {
415
 
            g_object_unref(priv->completion);
416
 
            priv->completion = NULL;
417
 
        }
418
 
        gtk_entry_set_completion(GTK_ENTRY(entry), NULL);
419
 
    }
420
 
    if(priv->completion)
421
 
        gtk_entry_completion_set_model( priv->completion, (GtkTreeModel*)priv->completion_model );
422
 
    priv->in_change = TRUE;
423
 
    gtk_entry_set_text(GTK_ENTRY(entry), path_str);
424
 
    priv->in_change = FALSE;
425
 
    gtk_editable_set_position(GTK_EDITABLE(entry), -1);
426
 
    g_free(path_str);
427
 
}
428
 
 
429
 
static gboolean fm_path_entry_match_func(GtkEntryCompletion   *completion,
430
 
                                         const gchar          *key,
431
 
                                         GtkTreeIter          *iter,
432
 
                                         gpointer user_data)
433
 
{
434
 
    gboolean ret;
435
 
    GtkTreeModel *model = gtk_entry_completion_get_model(completion);
436
 
    FmPathEntry *pe = FM_PATH_ENTRY( gtk_entry_completion_get_entry(completion) );
437
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE(pe);
438
 
    FmFileInfo *model_file_info;
439
 
    gchar *model_file_name;
440
 
    /* get original key (case sensitive) */
441
 
    const gchar *original_key = gtk_entry_get_text( GTK_ENTRY(pe) );
442
 
    gboolean is_dir;
443
 
    /* find sep in key */
444
 
    gchar *key_last_slash = strrchr(original_key, G_DIR_SEPARATOR);
445
 
 
446
 
    /* no model based completion possible */
447
 
    if( (!model) || (key_last_slash == NULL) )
448
 
        return FALSE;
449
 
 
450
 
    priv->completion_len = strlen(key_last_slash + 1);
451
 
 
452
 
    /* get filename, info from model */
453
 
    gtk_tree_model_get(GTK_TREE_MODEL(model), iter,
454
 
                       COL_FILE_NAME, &model_file_name,
455
 
                       COL_FILE_INFO, &model_file_info,
456
 
                       -1);
457
 
 
458
 
    ret = fm_file_info_is_dir(model_file_info) && g_str_has_prefix(model_file_name, key_last_slash + 1);
459
 
    g_free(model_file_name);
460
 
    return ret;
461
 
}
462
 
 
463
 
static gboolean  fm_path_entry_match_selected(GtkEntryCompletion *widget,
464
 
                                              GtkTreeModel       *model,
465
 
                                              GtkTreeIter        *iter,
466
 
                                              gpointer user_data)
467
 
{
468
 
    GtkWidget *entry = gtk_entry_completion_get_entry(widget);
469
 
    gchar new_text[PATH_MAX];
470
 
    FmPathEntryPrivate *priv = FM_PATH_ENTRY_GET_PRIVATE( FM_PATH_ENTRY(entry) );
471
 
    gchar *model_file_name;
472
 
    gchar *new_path;
473
 
    gtk_tree_model_get(GTK_TREE_MODEL(model), iter,
474
 
                       COL_FILE_NAME, &model_file_name,
475
 
                       -1);
476
 
    /* FIXME: should we use UTF-8 encoded display name here? */
477
 
    new_path = fm_path_to_str(priv->completion_model->dir->dir_path);
478
 
    g_sprintf(new_text, "%s/%s",
479
 
              /* prevent leading double slash */
480
 
              g_str_equal(new_path, "/") ? "" : new_path,
481
 
              model_file_name);
482
 
    g_free(new_path);
483
 
    priv->completion_len = 0;
484
 
    gtk_entry_set_text(GTK_ENTRY(entry), new_text);
485
 
    /* move the cursor to the end of entry */
486
 
    gtk_editable_set_position(GTK_EDITABLE(entry), -1);
487
 
    return TRUE;
488
 
}
489