latest update
[hildon] / hildon-widgets / hildon-file-details-dialog.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Luc Pionchon <luc.pionchon@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 /* @file hildon-file-details-dialog.c 
26  * 
27  * This file contains API for Hildon File Details dialog.
28  * 
29  */
30
31 #include <gtk/gtkbox.h>
32 #include <gtk/gtkcheckbutton.h>
33 #include <gtk/gtklabel.h>
34 #include <gtk/gtknotebook.h>
35 #include <gtk/gtktable.h>
36 #include <gtk/gtkhbox.h>
37 #include <gtk/gtkimage.h>
38 #include <gtk/gtkscrolledwindow.h>
39 #include <time.h>
40 #include <libintl.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include <errno.h>
45
46 #include <hildon-widgets/hildon-caption.h>
47 #include <hildon-widgets/hildon-file-system-model.h>
48 #include <hildon-widgets/gtk-infoprint.h>
49 #include "hildon-file-details-dialog.h"
50
51 #ifdef HAVE_CONFIG_H
52 #include <config.h>
53 #endif
54
55 #define _(String) dgettext(PACKAGE, String)
56 #define HILDON_MARGIN_DEFAULT 6
57 #define HILDON_MARGIN_DOUBLE 12
58
59 enum
60 {
61   PROP_SHOW_TABS = 1,
62   PROP_ADDITIONAL_TAB,
63   PROP_ADDITIONAL_TAB_LABEL,
64   PROP_MODEL
65 };
66
67 struct _HildonFileDetailsDialogPrivate {
68     GtkNotebook *notebook;
69
70     GtkWidget *file_location, *file_name;
71     GtkWidget *file_type, *file_size;
72     GtkWidget *file_date, *file_time;
73     GtkWidget *file_readonly, *file_device;
74     GtkWidget *file_location_image, *file_device_image;
75     GtkWidget *ok_button;
76
77     GtkTreeRowReference *active_file;
78     gboolean checkbox_original_state;
79     gulong toggle_handler;
80
81     /* Properties */
82     HildonFileSystemModel *model;
83     GtkWidget *tab_label;
84 };
85
86 static void
87 hildon_file_details_dialog_class_init(HildonFileDetailsDialogClass *
88                                       klass);
89 static void hildon_file_details_dialog_init(HildonFileDetailsDialog *
90                                             filedetailsdialog);
91 static void hildon_file_details_dialog_finalize(GObject * object);
92
93 static void
94 hildon_file_details_dialog_set_property( GObject *object, guint param_id,
95                                                            const GValue *value,
96                                          GParamSpec *pspec );
97 static void
98 hildon_file_details_dialog_get_property( GObject *object, guint param_id,
99                                                            GValue *value, GParamSpec *pspec );
100 static void 
101 hildon_file_details_dialog_response(GtkDialog *dialog, gint response_id);
102
103 static GtkDialogClass *file_details_dialog_parent_class = NULL;
104
105 GType hildon_file_details_dialog_get_type(void)
106 {
107     static GType file_details_dialog_type = 0;
108
109     if (!file_details_dialog_type) {
110         static const GTypeInfo file_details_dialog_info = {
111             sizeof(HildonFileDetailsDialogClass),
112             NULL,       /* base_init */
113             NULL,       /* base_finalize */
114             (GClassInitFunc) hildon_file_details_dialog_class_init,
115             NULL,       /* class_finalize */
116             NULL,       /* class_data */
117             sizeof(HildonFileDetailsDialog),
118             0,  /* n_preallocs */
119             (GInstanceInitFunc) hildon_file_details_dialog_init,
120         };
121
122         file_details_dialog_type =
123             g_type_register_static(GTK_TYPE_DIALOG,
124                                    "HildonFileDetailsDialog",
125                                    &file_details_dialog_info,
126                                    0);
127     }
128
129     return file_details_dialog_type;
130 }
131
132 static void change_state(HildonFileDetailsDialog *self, gboolean readonly)
133 {
134   GtkTreeIter iter;
135
136   g_return_if_fail(HILDON_IS_FILE_DETAILS_DIALOG(self));
137
138   if (hildon_file_details_dialog_get_file_iter(self, &iter))
139   {  
140     gchar *path;
141     struct stat buf;
142
143     gtk_tree_model_get(GTK_TREE_MODEL(self->priv->model), &iter, 
144       HILDON_FILE_SYSTEM_MODEL_COLUMN_LOCAL_PATH, &path, -1);    
145
146     /* Here we should set the read only state */
147     if (stat(path, &buf) == 0)
148     {
149       mode_t perm = (readonly ? 
150                         buf.st_mode & ~(S_IWUSR | S_IWGRP | S_IWOTH) : 
151                         buf.st_mode | (S_IWUSR | S_IWGRP));
152
153       (void) chmod(path, perm);
154     }
155
156     /* No errors are defined in the specs, but the previous operations can still fail */
157     if (errno)
158       gtk_infoprint(GTK_WINDOW(self), g_strerror(errno));
159     
160     g_free(path);
161   }
162   else
163     g_assert_not_reached();
164 }
165
166 /* Cancel changes if read-only is changed */
167 static void 
168 hildon_file_details_dialog_response(GtkDialog *dialog, gint response_id)
169 {
170     if (response_id == GTK_RESPONSE_CANCEL)
171     {
172       HildonFileDetailsDialog *self;
173       gboolean state;
174
175       self = HILDON_FILE_DETAILS_DIALOG(dialog);  
176       state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self->priv->file_readonly));
177
178       if (state != self->priv->checkbox_original_state)
179         change_state(self, self->priv->checkbox_original_state);
180     }
181 }
182
183 static void
184 hildon_file_details_dialog_read_only_toggled(GtkWidget *widget, gpointer data)
185 {
186   change_state(HILDON_FILE_DETAILS_DIALOG(data), 
187     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
188 }
189
190 static void 
191 hildon_file_details_dialog_map(GtkWidget *widget)
192 {
193   GTK_WIDGET_CLASS(file_details_dialog_parent_class)->map(widget);
194   gtk_widget_grab_focus(HILDON_FILE_DETAILS_DIALOG(widget)->priv->ok_button);
195 }
196
197 static void
198 hildon_file_details_dialog_class_init(HildonFileDetailsDialogClass * klass)
199 {
200     GObjectClass *gobject_class;
201
202     file_details_dialog_parent_class = g_type_class_peek_parent(klass);
203     gobject_class = G_OBJECT_CLASS(klass);
204     gobject_class->finalize = hildon_file_details_dialog_finalize;
205     gobject_class->get_property = hildon_file_details_dialog_get_property;
206     gobject_class->set_property = hildon_file_details_dialog_set_property;
207     GTK_WIDGET_CLASS(klass)->map = hildon_file_details_dialog_map;
208     GTK_DIALOG_CLASS(klass)->response = hildon_file_details_dialog_response;
209
210     g_type_class_add_private(klass, sizeof(HildonFileDetailsDialogPrivate));
211
212   /**
213    * HildonFileDetailsDialog:additional_tab:
214    *
215    * This is a place for an additional tab.
216    */
217   g_object_class_install_property( gobject_class, PROP_ADDITIONAL_TAB,
218                                    g_param_spec_object("additional-tab",
219                                    "Additional tab",
220                                    "Tab to show additinal information",
221                                                        GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
222   /**
223    * HildonFileDetailsDialog:show_tabs:
224    *
225    * Do we want to show the tab labels.
226    */
227   g_object_class_install_property( gobject_class, PROP_SHOW_TABS,
228                                    g_param_spec_boolean("show-tabs",
229                                    "Show tab labels",
230                                    "Do we want to show the tab label.",
231                                    FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
232   /**
233    * HildonFileDetailsDialog:additional_tab_label:
234    *
235    * 
236    */
237   g_object_class_install_property( gobject_class, PROP_ADDITIONAL_TAB_LABEL,
238                                    g_param_spec_string("additional-tab-label",
239                                    "Additional tab label",
240                                    "Label to the additional tab",
241                                    NULL, G_PARAM_READWRITE));
242
243   g_object_class_install_property( gobject_class, PROP_MODEL,
244                  g_param_spec_object("model", "Model", 
245                  "HildonFileSystemModel to use when fetching information",
246                  HILDON_TYPE_FILE_SYSTEM_MODEL, G_PARAM_READWRITE));
247 }
248
249
250 static void
251 hildon_file_details_dialog_init(HildonFileDetailsDialog *self)
252 {
253     GtkWidget *caption_location, *caption_name, *caption_type;
254     GtkWidget *caption_date, *caption_size, *caption_time;
255     GtkWidget *caption_read, *caption_device;
256     GtkWidget *hbox_location, *hbox_device;
257     GtkTable *table;
258     GtkSizeGroup *group;
259     GdkGeometry geometry;
260
261     HildonFileDetailsDialogPrivate *priv;
262
263     self->priv = priv =
264       G_TYPE_INSTANCE_GET_PRIVATE(self, \
265           HILDON_TYPE_FILE_DETAILS_DIALOG, HildonFileDetailsDialogPrivate);
266
267     priv->notebook = GTK_NOTEBOOK(gtk_notebook_new());
268     table = GTK_TABLE(gtk_table_new(6, 4, FALSE));
269     group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
270     
271     priv->tab_label = gtk_label_new(_("sfil_ti_notebook_file"));
272     g_object_ref(priv->tab_label);
273     gtk_object_sink(GTK_OBJECT(priv->tab_label));
274     gtk_widget_show(priv->tab_label);
275
276     gtk_container_set_border_width(GTK_CONTAINER(table), 
277         HILDON_MARGIN_DEFAULT);
278     gtk_table_set_col_spacings(table, HILDON_MARGIN_DOUBLE);
279
280     /* Tab one */
281     caption_device = g_object_new(GTK_TYPE_LABEL, 
282         "label", _("sfil_fi_properties_device_prompt"), "xalign", 1.0f, NULL);
283     caption_location = g_object_new(GTK_TYPE_LABEL,
284         "label", _("sfil_fi_properties_location_prompt"), "xalign", 1.0f, NULL);
285     caption_name = g_object_new(GTK_TYPE_LABEL,
286         "label", _("ckdg_fi_properties_name_prompt"), "xalign", 1.0f, NULL);
287     caption_type = g_object_new(GTK_TYPE_LABEL, 
288         "label", _("ckdg_fi_properties_type_prompt"), "xalign", 1.0f, NULL);
289     caption_date = g_object_new(GTK_TYPE_LABEL,
290         "label", _("ckdg_fi_properties_date_prompt"), "xalign", 1.0f, NULL);
291     caption_time = g_object_new(GTK_TYPE_LABEL, 
292         "label", _("ckdg_fi_properties_time_prompt"), "xalign", 1.0f, NULL);
293
294     priv->file_device = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
295     priv->file_location = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
296     priv->file_name = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
297     priv->file_type = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
298     priv->file_size = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
299     priv->file_date = g_object_new(GTK_TYPE_LABEL,"xalign", 0.0f, NULL);
300     priv->file_time = g_object_new(GTK_TYPE_LABEL, "xalign", 0.0f, NULL);
301     priv->file_readonly = gtk_check_button_new();
302
303     /* We have to use caption control also for non-editable object, 
304         because sizings will fail otherwise */
305     caption_size = hildon_caption_new(group, _("ckdg_fi_properties_size_prompt"), 
306       priv->file_size, NULL, HILDON_CAPTION_OPTIONAL);
307     caption_read = hildon_caption_new(group, _("ckdg_fi_properties_read_only"), 
308       priv->file_readonly, NULL, HILDON_CAPTION_OPTIONAL);
309     hildon_caption_set_separator(HILDON_CAPTION(caption_size), "");
310     hildon_caption_set_separator(HILDON_CAPTION(caption_read), "");
311     if (G_IS_OBJECT(group))
312       g_object_unref(group);
313
314     hbox_location = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT);
315     hbox_device = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT);
316
317     priv->file_location_image = gtk_image_new();
318     priv->file_device_image = gtk_image_new();
319
320     gtk_box_pack_start(GTK_BOX(hbox_location), priv->file_location_image, FALSE, TRUE, 0);
321     gtk_box_pack_start(GTK_BOX(hbox_location), priv->file_location, TRUE, TRUE, 0);
322     gtk_box_pack_start(GTK_BOX(hbox_device), priv->file_device_image, FALSE, TRUE, 0);
323     gtk_box_pack_start(GTK_BOX(hbox_device), priv->file_device, TRUE, TRUE, 0);
324
325     /* Labels */
326     gtk_table_attach(table, caption_name, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
327     gtk_table_attach(table, caption_type, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
328     gtk_table_attach(table, caption_location, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
329     gtk_table_attach(table, caption_device, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0); 
330     gtk_table_attach(table, caption_date, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0);
331     gtk_table_attach(table, caption_time, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
332     gtk_table_attach(table, caption_size, 2, 3, 4, 5, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
333     gtk_table_attach(table, caption_read, 2, 4, 5, 6, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
334
335     /* Data */
336     gtk_table_attach(table, priv->file_name, 1, 4, 0, 1, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
337     gtk_table_attach(table, priv->file_type, 1, 4, 1, 2, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
338     gtk_table_attach(table, hbox_location, 1, 4, 2, 3, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
339     gtk_table_attach(table, hbox_device, 1, 4, 3, 4, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0); 
340     gtk_table_attach(table, priv->file_date, 1, 2, 4, 5, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
341     gtk_table_attach(table, priv->file_time, 1, 2, 5, 6, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
342
343     /* Populate dialog */
344     gtk_notebook_append_page(priv->notebook, GTK_WIDGET(table),
345                              gtk_label_new(_("sfil_ti_notebook_common")));
346
347     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(self)->vbox),
348                        GTK_WIDGET(priv->notebook), TRUE, TRUE, 0);
349
350     /* From widget specs, generic dialog size */
351     geometry.min_width = 133;
352     geometry.max_width = 602;
353     geometry.min_height = 120;
354     geometry.max_height = 240;
355
356     gtk_window_set_geometry_hints(GTK_WINDOW(self),
357                                   GTK_WIDGET(priv->notebook), &geometry,
358                                   GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
359
360     gtk_widget_show_all(GTK_WIDGET(priv->notebook));
361     priv->ok_button = gtk_dialog_add_button(GTK_DIALOG(self),
362                           _("sfil_bd_filetype_details_dialog_ok"),
363                           GTK_RESPONSE_OK);
364     gtk_dialog_add_button(GTK_DIALOG(self),
365                           _("sfil_bd_filetype_details_dialog_cancel"),
366                           GTK_RESPONSE_CANCEL);
367     gtk_dialog_set_default_response(GTK_DIALOG(self),
368                           GTK_RESPONSE_OK);
369
370     priv->toggle_handler = g_signal_connect(priv->file_readonly, "toggled", 
371       G_CALLBACK(hildon_file_details_dialog_read_only_toggled), 
372       self);
373 }
374
375 static void
376 hildon_file_details_dialog_set_property( GObject *object, guint param_id,
377                                                            const GValue *value,
378                                          GParamSpec *pspec )
379 {
380   HildonFileDetailsDialogPrivate *priv;
381   GtkNotebook *notebook;
382   GtkLabel *label;
383
384   priv = HILDON_FILE_DETAILS_DIALOG(object)->priv;
385   notebook = priv->notebook;
386   label = GTK_LABEL(priv->tab_label);
387
388   switch( param_id ) 
389   {
390     case PROP_SHOW_TABS:
391     {
392       gtk_notebook_set_show_tabs(notebook, g_value_get_boolean(value));
393       gtk_notebook_set_show_border(notebook, g_value_get_boolean(value));
394       break;
395     }
396     case PROP_ADDITIONAL_TAB:
397     {
398       GtkWidget *widget = g_value_get_object(value);
399       GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
400       
401       if (gtk_notebook_get_n_pages(notebook) == 2)
402         gtk_notebook_remove_page(notebook, 1);
403
404       if (widget == NULL)
405       {
406         widget = gtk_label_new(_("sfil_ia_filetype_no_details"));
407         gtk_widget_show(widget);
408       }
409
410       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
411                                      GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
412       gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), widget);
413       gtk_viewport_set_shadow_type(GTK_VIEWPORT(GTK_BIN(sw)->child),
414                                    GTK_SHADOW_NONE);
415       gtk_widget_show_all(sw);
416       gtk_notebook_append_page(notebook, sw, priv->tab_label);
417       gtk_notebook_set_current_page(notebook, 0);
418       break;
419     }
420     case PROP_ADDITIONAL_TAB_LABEL:
421       gtk_label_set_text(label, g_value_get_string(value));
422       break;
423     case PROP_MODEL:
424     {
425       HildonFileSystemModel *new_model = g_value_get_object(value);
426       if (new_model != priv->model)
427       {
428         if (G_IS_OBJECT(priv->model))
429           g_object_unref(priv->model);
430         priv->model = new_model;
431         if (new_model)
432           g_object_ref(new_model);
433       }  
434       break;
435     }
436     default:
437       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
438       break;
439   }
440 }
441
442 static void
443 hildon_file_details_dialog_get_property( GObject *object, guint param_id,
444                                                            GValue *value, GParamSpec *pspec )
445 {
446   HildonFileDetailsDialogPrivate *priv;
447
448   priv = HILDON_FILE_DETAILS_DIALOG(object)->priv;
449
450   switch (param_id) 
451   {
452     case PROP_SHOW_TABS:
453       g_value_set_boolean(value, gtk_notebook_get_show_tabs(priv->notebook));
454       break;
455     case PROP_ADDITIONAL_TAB:
456       g_assert(gtk_notebook_get_n_pages(priv->notebook) == 2);        
457       g_value_set_object(value, gtk_notebook_get_nth_page(priv->notebook, 1));
458       break;
459     case PROP_ADDITIONAL_TAB_LABEL:
460       g_value_set_string(value, gtk_label_get_text(GTK_LABEL(priv->tab_label)));
461       break;
462     case PROP_MODEL:
463       g_value_set_object(value, priv->model);
464       break;
465     default:
466       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
467       break;
468   }
469 }
470
471 static void hildon_file_details_dialog_finalize(GObject * object)
472 {
473   HildonFileDetailsDialogPrivate *priv;
474
475   g_return_if_fail(HILDON_IS_FILE_DETAILS_DIALOG(object));
476
477   priv = HILDON_FILE_DETAILS_DIALOG(object)->priv;
478   if (G_IS_OBJECT(priv->model))
479     g_object_unref(priv->model);
480   if (G_IS_OBJECT(priv->tab_label))
481     g_object_unref(priv->tab_label);
482   if (priv->active_file)
483     gtk_tree_row_reference_free(priv->active_file);
484     
485   G_OBJECT_CLASS(file_details_dialog_parent_class)->finalize(object);
486 }
487
488 /*******************/
489 /* Public functions */
490 /*******************/
491
492 /**
493  * hildon_file_details_dialog_new:
494  * @parent: the parent window.
495  * @filename: the filename.
496  *
497  * Creates a new #hildon_file_details_dialog AND new underlying 
498  * HildonFileSystemModel. Be carefull with #filename
499  * parameter: You don't get any notification if something fails.
500  * THIS FUNCTION IS DEPRICATED AND PROVIDED ONLY FOR
501  * BACKWARDS COMPABILITY.
502  *
503  * Returns: a new #HildonFileDetailsDialog.
504  */
505 #ifndef HILDON_DISABLE_DEPRECATED
506 GtkWidget *hildon_file_details_dialog_new(GtkWindow * parent,
507                                           const gchar * filename)
508 {
509   HildonFileDetailsDialog *dialog;
510   HildonFileSystemModel *model;
511   GtkTreeIter iter;
512
513   model = g_object_new(HILDON_TYPE_FILE_SYSTEM_MODEL, NULL);
514
515   dialog =
516         g_object_new(HILDON_TYPE_FILE_DETAILS_DIALOG, 
517           "has-separator", FALSE, "title", _("sfil_ti_file_details"), 
518           "model", model, NULL);
519
520   if (filename && filename[0] && 
521     hildon_file_system_model_load_local_path(dialog->priv->model, filename, &iter))
522       hildon_file_details_dialog_set_file_iter(dialog, &iter);
523
524   if (parent)
525     gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
526
527   return GTK_WIDGET(dialog);
528 }
529 #endif
530 /**
531  * hildon_file_details_dialog_new_with_model:
532  * @parent: the parent window.
533  * @model: a #HildonFileSystemModel object used to fetch data.
534  *
535  * This is the preferred way to create #HildonFileDetailsDialog.
536  * You can use a shared model structure to save loading times
537  * (because you probably already have one at your disposal).
538  *
539  * Returns: a new #HildonFileDetailsDialog.
540  */
541 GtkWidget *hildon_file_details_dialog_new_with_model(GtkWindow *parent,
542   HildonFileSystemModel *model)
543 {
544   GtkWidget *dialog;
545
546   dialog = g_object_new(HILDON_TYPE_FILE_DETAILS_DIALOG,
547     "has-separator", FALSE, "title", _("sfil_ti_file_details"), 
548     "model", model, NULL);
549
550   if (parent)
551     gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
552
553   return dialog;
554 }
555
556 /**
557  * hildon_file_details_dialog_set_file_iter:
558  * @self: a #HildonFileDetailsDialog.
559  * @iter: a #GtkTreeIter pointing to desired file.
560  *
561  * Sets the dialog to display information about a file defined by
562  * given iterator.
563  */
564 void hildon_file_details_dialog_set_file_iter(HildonFileDetailsDialog *self, GtkTreeIter *iter)
565 {
566   GtkTreeModel *model;
567   GtkTreePath *path;
568   GtkTreeIter temp_iter, parent_iter;
569   gchar *name, *mime, *local_path;
570   const gchar *fmt;
571   gint64 time_stamp, size;
572   gchar buffer[256];
573   struct tm *time_struct;
574   time_t time_val;
575   gint type;
576   gboolean location_readonly = TRUE;
577
578   g_return_if_fail(HILDON_IS_FILE_DETAILS_DIALOG(self));
579
580   model = GTK_TREE_MODEL(self->priv->model);
581
582   /* Save iterator to priv struct as row reference */
583   gtk_tree_row_reference_free(self->priv->active_file);
584   path = gtk_tree_model_get_path(model, iter);
585   self->priv->active_file = gtk_tree_row_reference_new(model, path);
586   gtk_tree_path_free(path);
587
588   /* Setup the view */
589   gtk_tree_model_get(model, iter,
590     HILDON_FILE_SYSTEM_MODEL_COLUMN_DISPLAY_NAME, &name,
591     HILDON_FILE_SYSTEM_MODEL_COLUMN_MIME_TYPE, &mime,
592     HILDON_FILE_SYSTEM_MODEL_COLUMN_LOCAL_PATH, &local_path,
593     HILDON_FILE_SYSTEM_MODEL_COLUMN_FILE_SIZE, &size,
594     HILDON_FILE_SYSTEM_MODEL_COLUMN_FILE_TIME, &time_stamp,
595     -1);
596
597   g_object_set(self->priv->file_name, "label", name, NULL);
598   g_object_set(self->priv->file_type, "label", _(mime), NULL);
599
600   if (size < 1024)
601     g_snprintf(buffer, sizeof(buffer),
602                _("ckdg_va_properties_size_bytes"), (gint) size);
603   else
604     g_snprintf(buffer, sizeof(buffer),
605                _("ckdg_va_properties_size_kb"), (gint) size / 1024);
606
607   g_object_set(self->priv->file_size, "label", buffer, NULL);
608
609   /* Too bad. We cannot use GDate function, because it doesn't handle
610       time, just dates */
611   time_val = (time_t) time_stamp;
612   time_struct = localtime(&time_val);
613
614   /* There are no more logical names for these. We are allowed
615       to hardcode */
616   strftime(buffer, sizeof(buffer), "%X", time_struct);
617   g_object_set(self->priv->file_time, "label", buffer, NULL);
618   
619   /* If format is passed directly to strftime, gcc complains about
620       that some locales use only 2 digit year numbers. Using
621       a temporary disable this warning (from strftime man page) */
622   fmt = "%x";
623   strftime(buffer, sizeof(buffer), fmt, time_struct);
624   g_object_set(self->priv->file_date, "label", buffer, NULL);
625
626   /* Parent information */
627   if (gtk_tree_model_iter_parent(model, &parent_iter, iter))
628   {
629     gchar *location_name, *parent_path;
630     GdkPixbuf *location_icon;
631
632     gtk_tree_model_get(model, &parent_iter,
633       HILDON_FILE_SYSTEM_MODEL_COLUMN_DISPLAY_NAME, &location_name,
634       HILDON_FILE_SYSTEM_MODEL_COLUMN_LOCAL_PATH, &parent_path,
635       HILDON_FILE_SYSTEM_MODEL_COLUMN_ICON, &location_icon, -1);      
636
637     if (parent_path)
638       location_readonly = access(parent_path, W_OK)  != 0;
639
640     gtk_label_set_text(GTK_LABEL(self->priv->file_location), location_name);
641     gtk_image_set_from_pixbuf(GTK_IMAGE(self->priv->file_location_image), 
642       location_icon);
643
644     if (G_IS_OBJECT(location_icon))
645       g_object_unref(location_icon);
646     g_free(location_name);
647
648     /* Go upwards in model until we find a device node */
649     while (TRUE)
650     {
651       gtk_tree_model_get(model, &parent_iter,
652         HILDON_FILE_SYSTEM_MODEL_COLUMN_TYPE, &type, -1);
653
654       if (type >= HILDON_FILE_SYSTEM_MODEL_MMC)
655         break;
656
657       if (gtk_tree_model_iter_parent(model, &temp_iter, &parent_iter))
658         parent_iter = temp_iter;
659       else 
660         break;
661     }   
662
663     gtk_tree_model_get(model, &parent_iter,
664       HILDON_FILE_SYSTEM_MODEL_COLUMN_DISPLAY_NAME, &location_name, 
665       HILDON_FILE_SYSTEM_MODEL_COLUMN_ICON, &location_icon, 
666       -1);
667
668     gtk_label_set_text(GTK_LABEL(self->priv->file_device), location_name);
669     gtk_image_set_from_pixbuf(GTK_IMAGE(self->priv->file_device_image), 
670       location_icon);
671
672     if (G_IS_OBJECT(location_icon))
673       g_object_unref(location_icon);
674     g_free(location_name);
675     g_free(parent_path);
676   }
677   else 
678   {   /* We really should not come here */
679       gtk_label_set_text(GTK_LABEL(self->priv->file_location), "");
680       gtk_image_set_from_pixbuf(GTK_IMAGE(self->priv->file_location_image), NULL);
681       gtk_label_set_text(GTK_LABEL(self->priv->file_device), "");
682       gtk_image_set_from_pixbuf(GTK_IMAGE(self->priv->file_device_image), NULL);
683   }
684
685   /* We do not want initial setting to cause any action */
686   g_signal_handler_block(self->priv->file_readonly, self->priv->toggle_handler);
687
688   if (local_path)
689   {
690     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->priv->file_readonly), 
691       location_readonly || access(local_path, W_OK)  != 0);
692     gtk_widget_set_sensitive(self->priv->file_readonly, !location_readonly);
693   }
694   else  
695   {
696       /* Backend do not support setting permissions, so we 
697           cannot do anything for paths that are not local */
698     gtk_toggle_button_set_inconsistent(
699         GTK_TOGGLE_BUTTON(self->priv->file_readonly), TRUE);
700     gtk_widget_set_sensitive(self->priv->file_readonly, FALSE);
701   }
702
703   self->priv->checkbox_original_state = gtk_toggle_button_get_active(
704         GTK_TOGGLE_BUTTON(self->priv->file_readonly));
705
706   g_signal_handler_unblock(self->priv->file_readonly, self->priv->toggle_handler);
707
708   g_free(local_path);
709   g_free(name);
710   g_free(mime);
711 }
712
713 /**
714  * hildon_file_details_dialog_get_file_iter:
715  * @self: a #HildonFileDetailsDialog.
716  * @iter: a #GtkTreeIter to be filled.
717  *
718  * Gets an iterator pointing to displayed file.
719  *
720  * Returns: %TRUE, if dialog is displaying some information.
721  */
722 gboolean 
723 hildon_file_details_dialog_get_file_iter(HildonFileDetailsDialog *self, GtkTreeIter *iter)
724 {
725   GtkTreePath *path;
726   gboolean result;
727
728   g_return_val_if_fail(HILDON_IS_FILE_DETAILS_DIALOG(self), FALSE);
729
730   if (!self->priv->active_file)
731     return FALSE;
732   path = gtk_tree_row_reference_get_path(self->priv->active_file);
733   if (!path)
734     return FALSE;
735   
736   result = gtk_tree_model_get_iter(GTK_TREE_MODEL(self->priv->model), iter, path);
737   gtk_tree_path_free(path);  
738
739   return result;
740 }