mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

src/mn-file-chooser-button.gob (7313B) - raw

      1 /*
      2  * MNFileChooserButton - a non-broken partial reimplementation of
      3  * GtkFileChooserButton (GtkFileChooserButton is unusable, see
      4  * http://bugzilla.gnome.org/show_bug.cgi?id=327243)
      5  *
      6  * Based on GtkFileChooserButton,
      7  * Copyright (c) 2004 James M. Cape <jcape@ignore-your.tv>
      8  *
      9  * Mail Notification
     10  * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
     11  *
     12  * This program is free software; you can redistribute it and/or modify
     13  * it under the terms of the GNU General Public License as published by
     14  * the Free Software Foundation; either version 3 of the License, or
     15  * (at your option) any later version.
     16  *
     17  * This program is distributed in the hope that it will be useful,
     18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20  * GNU General Public License for more details.
     21  *
     22  * You should have received a copy of the GNU General Public License along
     23  * with this program; if not, write to the Free Software Foundation, Inc.,
     24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     25  */
     26 
     27 %headertop{
     28 #include <gtk/gtk.h>
     29 %}
     30 
     31 %h{
     32 typedef GtkFileChooserDialog *(*MNFileChooserButtonCreateDialogFunction) (gpointer data);
     33 %}
     34 
     35 %privateheader{
     36 #include <libgnomevfs/gnome-vfs.h>
     37 %}
     38 
     39 %{
     40 #include <glib/gi18n.h>
     41 #include <gnome.h>
     42 #include "mn-util.h"
     43 %}
     44 
     45 class MN:File:Chooser:Button from Gtk:HBox
     46 {
     47   private char *filename destroywith g_free;
     48   property STRING filename (export)
     49     get
     50     {
     51       g_value_set_string(VAL, selfp->filename);
     52     }
     53     set
     54     {
     55       g_free(selfp->filename);
     56       selfp->filename = g_value_dup_string(VAL);
     57 
     58       self_update(self);
     59 
     60       if (selfp->dialog)
     61 	gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(selfp->dialog), selfp->filename);
     62     };
     63 
     64   private MNFileChooserButtonCreateDialogFunction create_dialog;
     65   private gpointer create_dialog_data;
     66 
     67   private GtkWidget *image;
     68   private GtkWidget *label;
     69   private GtkWidget *dialog unrefwith gtk_widget_destroy;
     70 
     71   private GnomeVFSAsyncHandle *async_handle unrefwith gnome_vfs_async_cancel;
     72 
     73   init (self)
     74   {
     75     GtkWidget *button;
     76     GtkWidget *box;
     77     GtkWidget *separator;
     78     GtkWidget *image;
     79 
     80     button = gtk_button_new();
     81     gtk_container_add(GTK_CONTAINER(self), button);
     82     gtk_widget_show(button);
     83 
     84     box = gtk_hbox_new(FALSE, 4);
     85     gtk_container_add(GTK_CONTAINER(button), box);
     86     gtk_widget_show(box);
     87 
     88     selfp->image = gtk_image_new();
     89     gtk_box_pack_start(GTK_BOX(box), selfp->image, FALSE, FALSE, 0);
     90     gtk_widget_show(selfp->image);
     91 
     92     selfp->label = gtk_label_new(NULL);
     93     gtk_label_set_ellipsize(GTK_LABEL(selfp->label), PANGO_ELLIPSIZE_END);
     94     gtk_misc_set_alignment(GTK_MISC(selfp->label), 0.0, 0.5);
     95     gtk_container_add(GTK_CONTAINER(box), selfp->label);
     96     gtk_widget_show(selfp->label);
     97 
     98     separator = gtk_vseparator_new();
     99     gtk_box_pack_start(GTK_BOX(box), separator, FALSE, FALSE, 0);
    100     gtk_widget_show(separator);
    101 
    102     image = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
    103     gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
    104     gtk_widget_show(image);
    105 
    106     g_signal_connect(button, "clicked", G_CALLBACK(self_clicked_h), self);
    107 
    108     self_update(self);
    109   }
    110 
    111   private void
    112     clicked_h (GtkButton *button, gpointer data)
    113   {
    114     Self *self = data;
    115 
    116     if (! selfp->dialog)
    117       {
    118 	/* translators: header capitalization */
    119 	selfp->dialog = GTK_WIDGET(selfp->create_dialog(selfp->create_dialog_data));
    120 	g_assert(GTK_IS_FILE_CHOOSER_DIALOG(selfp->dialog));
    121 
    122 	mn_add_weak_pointer(&selfp->dialog);
    123 
    124 	if (selfp->filename)
    125 	  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(selfp->dialog), selfp->filename);
    126 
    127 	g_signal_connect(selfp->dialog, "response", G_CALLBACK(self_response_h), self);
    128       }
    129 
    130     if (! GTK_WIDGET_VISIBLE(selfp->dialog))
    131       {
    132 	GtkWindow *parent;
    133 
    134 	parent = mn_widget_get_parent_window(GTK_WIDGET(self));
    135 	if (parent)
    136 	  {
    137 	    if (parent != gtk_window_get_transient_for(GTK_WINDOW(selfp->dialog)))
    138 	      gtk_window_set_transient_for(GTK_WINDOW(selfp->dialog), parent);
    139 
    140 	    gtk_window_set_modal(GTK_WINDOW(selfp->dialog), gtk_window_get_modal(parent));
    141 	  }
    142       }
    143 
    144     mn_window_present_from_event(GTK_WINDOW(selfp->dialog));
    145   }
    146 
    147   private void
    148     update (self)
    149   {
    150     GnomeVFSURI *uri = NULL;
    151 
    152     if (selfp->async_handle)
    153       {
    154 	gnome_vfs_async_cancel(selfp->async_handle);
    155 	selfp->async_handle = NULL;
    156       }
    157 
    158     if (selfp->filename && *selfp->filename)
    159       {
    160 	char *text_uri;
    161 	char *base;
    162 
    163 	base = g_path_get_basename(selfp->filename);
    164 	gtk_label_set_text(GTK_LABEL(selfp->label), base);
    165 	g_free(base);
    166 
    167 	text_uri = gnome_vfs_get_uri_from_local_path(selfp->filename);
    168 	if (text_uri)
    169 	  {
    170 	    uri = gnome_vfs_uri_new(text_uri);
    171 	    g_free(text_uri);
    172 	  }
    173       }
    174     else
    175       /*
    176        * translators: GTK+ has the same message used in the same
    177        * context; please use the GTK+ translation for consistency
    178        */
    179       gtk_label_set_text(GTK_LABEL(selfp->label), _("(None)"));
    180 
    181     /*
    182      * Do not use MN_STOCK_UNKNOWN: we want to appear exactly as a
    183      * GtkFileChooserButton.
    184      */
    185     gtk_image_set_from_icon_name(GTK_IMAGE(selfp->image), "stock_unknown", GTK_ICON_SIZE_MENU);
    186 
    187     if (uri)
    188       {
    189 	GList *uri_list = NULL;
    190 
    191 	uri_list = g_list_append(uri_list, uri);
    192 
    193 	g_object_ref(self);
    194 	gnome_vfs_async_get_file_info(&selfp->async_handle,
    195 				      uri_list,
    196 				      GNOME_VFS_FILE_INFO_GET_MIME_TYPE
    197 				      | GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
    198 				      GNOME_VFS_PRIORITY_DEFAULT,
    199 				      self_get_file_info_cb,
    200 				      self);
    201 
    202 	gnome_vfs_uri_unref(uri);
    203 	g_list_free(uri_list);
    204       }
    205   }
    206 
    207   private void
    208     get_file_info_cb (GnomeVFSAsyncHandle *handle, GList *results, gpointer data)
    209   {
    210     Self *self = data;
    211 
    212     GDK_THREADS_ENTER();
    213 
    214     if (results)
    215       {
    216 	GnomeVFSGetFileInfoResult *result = results->data;
    217 
    218 	if (result->result == GNOME_VFS_OK
    219 	    && (result->file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) != 0)
    220 	  {
    221 	    char *uri;
    222 	    char *icon_name;
    223 
    224 	    uri = gnome_vfs_get_uri_from_local_path(selfp->filename);
    225 	    g_assert(uri != NULL);
    226 
    227 	    icon_name = gnome_icon_lookup(gtk_icon_theme_get_default(),
    228 					  NULL,
    229 					  uri,
    230 					  NULL,
    231 					  result->file_info,
    232 					  result->file_info->mime_type,
    233 					  GNOME_ICON_LOOKUP_FLAGS_NONE,
    234 					  NULL);
    235 
    236 	    g_free(uri);
    237 
    238 	    if (icon_name)
    239 	      {
    240 		gtk_image_set_from_icon_name(GTK_IMAGE(selfp->image), icon_name, GTK_ICON_SIZE_MENU);
    241 		g_free(icon_name);
    242 	      }
    243 	  }
    244       }
    245 
    246     selfp->async_handle = NULL;
    247     g_object_unref(self);
    248 
    249     /* do not call gdk_flush(), we're normally in the main thread */
    250     GDK_THREADS_LEAVE();
    251   }
    252 
    253   private void
    254     response_h (GtkDialog *dialog, int response, gpointer user_data)
    255   {
    256     Self *self = user_data;
    257 
    258     if (response == GTK_RESPONSE_ACCEPT)
    259       {
    260 	char *filename;
    261 
    262 	filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
    263 	self_set_filename(self, filename);
    264 	g_free(filename);
    265       }
    266 
    267     gtk_widget_destroy(GTK_WIDGET(dialog));
    268   }
    269 
    270   public GtkWidget *
    271     new (MNFileChooserButtonCreateDialogFunction create_dialog (check null),
    272 	 gpointer data)
    273   {
    274     Self *self = GET_NEW;
    275 
    276     selfp->create_dialog = create_dialog;
    277     selfp->create_dialog_data = data;
    278 
    279     return GTK_WIDGET(self);
    280   }
    281 }