Logo Search packages:      
Sourcecode: galeon version File versions

statusbar.c

/*
 *  Copyright (C) 2002 Jorn Baayen
 *  Copyright (C) 2003 Philip Langdale (Egg port)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "statusbar.h"
#include "pixbuf-cache.h"
#include "hig-alert.h"
#include "galeon-shell.h"
#include "page-info-dialog.h"

#include <string.h>
#include <time.h>
#include <gtk/gtkprogressbar.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkframe.h>
#include <gtk/gtktooltips.h>
#include <glib/gi18n.h>
#include <gtk/gtkbutton.h>
#include <libgnomevfs/gnome-vfs-uri.h>

static void statusbar_class_init (StatusbarClass *klass);
static void statusbar_init (Statusbar *t);
static void statusbar_finalize (GObject *object);

static void
popup_icon_clicked_cb (GtkWidget *widget, Statusbar *s);

static void
security_icon_clicked_cb (GtkWidget *widget, Statusbar *s);

static GObjectClass *parent_class = NULL;
static GtkTooltips *_statusbar_tooltips = NULL;

#define STATUSBAR_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
                               TYPE_STATUSBAR, StatusbarPrivate))


struct StatusbarPrivate
{
      gboolean visibility;

      GtkToggleAction *offline_action;
      GtkWidget *offline_button;
      GtkWidget *offline_icon;

      GtkWidget *security_button;
      GtkWidget *security_icon;

      GtkWidget *progress;

      GtkWidget *popupblock_frame;
      GtkWidget *popupblock_button;
      char *popup_uri;
};

enum {
      REQUEST,    /* request a security info page (and anything we add ...) */
      LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

GType 
statusbar_get_type (void)
{
        static GType statusbar_type = 0;

        if (statusbar_type == 0)
        {
                static const GTypeInfo our_info =
                {
                        sizeof (StatusbarClass),
                        NULL, /* base_init */
                        NULL, /* base_finalize */
                        (GClassInitFunc) statusbar_class_init,
                        NULL,
                        NULL, /* class_data */
                        sizeof (Statusbar),
                        0, /* n_preallocs */
                        (GInstanceInitFunc) statusbar_init
                };

                statusbar_type = g_type_register_static (GTK_TYPE_STATUSBAR,
                                             "Statusbar",
                                             &our_info, 0);
        }

        return statusbar_type;

}

static void
statusbar_class_init (StatusbarClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);

        parent_class = g_type_class_peek_parent (klass);

        object_class->finalize = statusbar_finalize;

      signals[REQUEST] =
            g_signal_new ("request",
                  G_OBJECT_CLASS_TYPE (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (StatusbarClass, request),
                  NULL, NULL,
                  g_cclosure_marshal_VOID__UINT,
                  G_TYPE_NONE, 1,
                  G_TYPE_UINT);

      g_type_class_add_private (klass, sizeof (StatusbarPrivate));
}

static GtkWidget *
create_compact_image_button (const char *stock_id)
{
      GtkWidget      *button;
      GtkRcStyle     *rcstyle;
      GtkWidget      *image;
      GtkRequisition  size;

      /* create a button suitable for packing in a statusbar */
      button = gtk_button_new ();
      gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
      GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);

      /* minimize the amount of white space around the image, +2 is to avoid
       * weird cropping (where does that come from?) */
      rcstyle = gtk_rc_style_new ();
      rcstyle->xthickness = rcstyle->ythickness = 0;
      gtk_widget_modify_style (button, rcstyle);
      gtk_rc_style_unref (rcstyle);

      image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
      gtk_widget_size_request (image, &size);
      gtk_widget_set_size_request (button, size.width + 2, size.height);
      gtk_container_add (GTK_CONTAINER (button), image);

      return button;
}

static void
update_offline_icon (Statusbar *t)
{
      const char *tooltips[] = {
            N_("Galeon is currently online. Click to work offline."),
            N_("Galeon is currently offline. Click to work online.")
      };
      gboolean offline;
      
      offline = gtk_toggle_action_get_active (t->priv->offline_action);

      gtk_image_set_from_stock (GTK_IMAGE (t->priv->offline_icon),
                          offline ? STOCK_DISCONNECT
                                : STOCK_CONNECT,
                          GTK_ICON_SIZE_MENU);
      gtk_tooltips_set_tip (_statusbar_tooltips, t->priv->offline_button, 
                        _(tooltips[!!offline]), NULL);
}

static void
create_statusbar_offline_icon (Statusbar *s, GtkToggleAction *action)
{
      GtkWidget *button;

      button = create_compact_image_button (STOCK_CONNECT);
      s->priv->offline_action = g_object_ref (action);
      s->priv->offline_icon = GTK_BIN(button)->child;
      s->priv->offline_button = button;

      g_signal_connect_swapped(s->priv->offline_action, "toggled",
                         G_CALLBACK(update_offline_icon), s);
      g_signal_connect_swapped(s->priv->offline_button, "clicked",
                         G_CALLBACK(gtk_action_activate), action);

      gtk_box_pack_start (GTK_BOX(s), button, FALSE, FALSE, 0);
      gtk_box_reorder_child (GTK_BOX(s), button, 0);

      update_offline_icon (s);

      gtk_widget_show_all (button);
}

static void
create_statusbar_security_icon (Statusbar *s)
{
      GtkWidget *button, *frame;

      frame = gtk_frame_new (NULL);
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);

      button = create_compact_image_button (GALEON_STOCK_INSECURE);
        s->priv->security_icon   = GTK_BIN(button)->child;
        s->priv->security_button = button;

        gtk_container_add (GTK_CONTAINER (frame), 
                           GTK_WIDGET (s->priv->security_button));
      g_signal_connect(G_OBJECT(s->priv->security_button),
                   "clicked",
                   G_CALLBACK(security_icon_clicked_cb), s);

      gtk_box_pack_end (GTK_BOX(s), frame, FALSE, FALSE, 0);
      
        gtk_widget_show_all (frame);
}

static void
create_statusbar_progress (Statusbar *s)
{
      s->priv->progress = gtk_progress_bar_new ();

      gtk_box_pack_end(GTK_BOX(s), s->priv->progress,
                   FALSE, FALSE, 0);

      gtk_widget_show_all (s->priv->progress);
}

static void
create_statusbar_popupblock_icon(Statusbar *s)
{
      GtkWidget *button;

      s->priv->popupblock_frame = gtk_frame_new(NULL);
      gtk_frame_set_shadow_type(GTK_FRAME(s->priv->popupblock_frame), 
                          GTK_SHADOW_IN);

      button = create_compact_image_button (GALEON_STOCK_POPUP_BLOCKED);
      s->priv->popupblock_button = button;

      gtk_container_add(GTK_CONTAINER(s->priv->popupblock_frame), 
                    GTK_WIDGET(s->priv->popupblock_button));
      g_signal_connect(G_OBJECT(s->priv->popupblock_button),
                   "clicked",
                   G_CALLBACK(popup_icon_clicked_cb), s);

      gtk_box_pack_end(GTK_BOX(s), s->priv->popupblock_frame,
                   FALSE, FALSE, 0);
      
      statusbar_set_popup_block(s, FALSE, NULL);
}

static void
statusbar_init (Statusbar *t)
{
      if (!_statusbar_tooltips)
      {
            _statusbar_tooltips = gtk_tooltips_new ();
            g_object_add_weak_pointer (G_OBJECT (_statusbar_tooltips),
                                 (gpointer)&_statusbar_tooltips);
      }

      g_object_ref (_statusbar_tooltips);
      gtk_object_sink (GTK_OBJECT (_statusbar_tooltips));

        t->priv = STATUSBAR_GET_PRIVATE (t);
      t->priv->visibility = TRUE;
}

static void
statusbar_finalize (GObject *object)
{
      Statusbar *s;

        g_return_if_fail (object != NULL);
        g_return_if_fail (IS_STATUSBAR (object));

      s = STATUSBAR (object);

        g_return_if_fail (s->priv != NULL);

      g_object_unref (s->priv->offline_action);
      
      g_free (s->priv->popup_uri);

      g_object_unref (_statusbar_tooltips);

        G_OBJECT_CLASS (parent_class)->finalize (object);
}

GtkWidget *
statusbar_new (GtkToggleAction *offline_action)
{
      Statusbar *s;

      s = STATUSBAR (g_object_new (TYPE_STATUSBAR, NULL));

      create_statusbar_offline_icon (s, offline_action);
      create_statusbar_security_icon (s);
      create_statusbar_popupblock_icon(s);
      create_statusbar_progress (s);
      gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(s),
                                FALSE);

      g_return_val_if_fail (s->priv != NULL, NULL);

      return GTK_WIDGET(s);
}

void
statusbar_set_visibility (Statusbar *t, 
                    gboolean visibility)
{
      if (visibility == t->priv->visibility) return;
      
      t->priv->visibility = visibility;

      if (visibility)
            gtk_widget_show(GTK_WIDGET(t));
      else
            gtk_widget_hide(GTK_WIDGET(t));
}

void
statusbar_set_security_state (Statusbar *t, 
                        const char *stock_icon,
                        const char *tooltip)
{
        gtk_image_set_from_stock (GTK_IMAGE (t->priv->security_icon),
                          stock_icon, GTK_ICON_SIZE_MENU);

      gtk_tooltips_set_tip (_statusbar_tooltips, t->priv->security_button, 
                        tooltip, NULL);
}

void
statusbar_set_progress (Statusbar *t, 
                  int progress)
{
      if (progress == -1)
      {
            gtk_progress_bar_pulse (GTK_PROGRESS_BAR(t->priv->progress));
      }
      else
      {
            gdouble tmp;
            tmp = ((gdouble) progress) / 100;
            if (tmp > 1)
            {
                  tmp = 1;
            }
            if (tmp < 0)
            {
                  tmp = 0;
            }
            gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(t->priv->progress),
                                     tmp);
      }
}

void
statusbar_set_message (Statusbar *s,
                   const char *message)
{
      g_return_if_fail (message != NULL);

      gtk_statusbar_pop(GTK_STATUSBAR(s), 0);
      gtk_statusbar_push(GTK_STATUSBAR(s), 0, message);
}

void
statusbar_set_popup_block(Statusbar *s, 
                    gboolean state,
                    const char *uri)
{
      char *tooltip = NULL;

      state ? gtk_widget_show_all(s->priv->popupblock_frame) :
            gtk_widget_hide_all(s->priv->popupblock_frame);

      g_free (s->priv->popup_uri);

      if (!uri)
      {
            s->priv->popup_uri = NULL;
      }
      else 
      {
            s->priv->popup_uri = gnome_vfs_uri_make_full_from_relative (uri, "/");
      }     

      if (s->priv->popup_uri)
            tooltip = g_strdup_printf (_("A popup from %s was blocked. "
                                   "Click to allow popups from this site."),
                                 s->priv->popup_uri);

      gtk_tooltips_set_tip(_statusbar_tooltips, s->priv->popupblock_button, 
                       tooltip, NULL);
      g_free(tooltip);
}


static void
popup_dialog_response_cb (GtkWidget *dialog, int response, 
                    const char *popup_uri)
{
      if (response == 1)
      {
            GaleonEmbedShell *embed_shell;

            embed_shell = galeon_shell_get_embed_shell (galeon_shell);
            g_return_if_fail (embed_shell != NULL);

            galeon_embed_shell_set_permission(embed_shell,
                                      popup_uri,
                                      POPUPS_PERMISSION, TRUE);
      }
      gtk_widget_destroy (dialog);
}


static void
popup_icon_clicked_cb (GtkWidget *widget, Statusbar *s)
{
      GtkWidget *dialog;
      GtkWidget *window;
      char *tt_uri;

      if (!s->priv->popup_uri) return;

      window = gtk_widget_get_toplevel (GTK_WIDGET (s));
      dialog = hig_alert_new (GTK_WINDOW (window),
                        GTK_DIALOG_DESTROY_WITH_PARENT,
                        HIG_ALERT_CONFIRMATION,
                        NULL,
                        NULL,
                        GTK_STOCK_CANCEL,
                        GTK_RESPONSE_CANCEL,
                        _("_Allow Popups"),
                        1,
                        NULL);
      gtk_dialog_set_default_response (GTK_DIALOG (dialog), 1);
      
      tt_uri = g_strdup_printf( "\"<tt>%s</tt>\"", s->priv->popup_uri);

      hig_alert_set_primary_printf (HIG_ALERT (dialog),
                              _("Allow popups from %s?"), s->priv->popup_uri);

      hig_alert_set_secondary_printf (HIG_ALERT (dialog),
                              _("A popup from %s was blocked. You can allow popups from "
                                "this site to be shown in the future."),
                              tt_uri);
      g_free (tt_uri);

      g_signal_connect_data (G_OBJECT(dialog),
                         "response",
                         G_CALLBACK(popup_dialog_response_cb),
                         g_strdup (s->priv->popup_uri),
                         (GClosureNotify)g_free,
                         (GConnectFlags)0);

      gtk_widget_show (dialog);
}


static void
security_icon_clicked_cb (GtkWidget *widget, Statusbar *self)
{
      g_signal_emit (G_OBJECT(self), signals[REQUEST], 0, STATUSBAR_SHOW_SECURITY_INFO);
}

Generated by  Doxygen 1.6.0   Back to index