/*
* vinagre-fav.c
* This file is part of vinagre
*
* Copyright (C) 2007 - Jonh Wendell <wendell@bani.com.br>
*
* 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 of the License, 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, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include "vinagre-fav.h"
#include "vinagre-utils.h"
#include "vinagre-bookmarks.h"
#include "vinagre-window-private.h"
#define VINAGRE_FAV_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), VINAGRE_TYPE_FAV, VinagreFavPrivate))
struct _VinagreFavPrivate
{
VinagreWindow *window;
GtkWidget *tree;
GtkTreeModel *model;
};
G_DEFINE_TYPE(VinagreFav, vinagre_fav, GTK_TYPE_VBOX)
/* Signals */
enum
{
FAV_ACTIVATED,
FAV_SELECTED,
LAST_SIGNAL
};
/* TreeModel */
enum {
IMAGE_COL = 0,
NAME_COL,
CONN_COL,
NUM_COLS
};
/* Properties */
enum
{
PROP_0,
PROP_WINDOW,
};
static guint signals[LAST_SIGNAL] = { 0 };
static void
vinagre_fav_finalize (GObject *object)
{
// VinagreFav *fav = VINAGRE_FAV (object);
G_OBJECT_CLASS (vinagre_fav_parent_class)->finalize (object);
}
static void
vinagre_fav_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
VinagreFav *fav = VINAGRE_FAV (object);
switch (prop_id)
{
case PROP_WINDOW:
fav->priv->window = VINAGRE_WINDOW (g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
vinagre_fav_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
VinagreFav *fav = VINAGRE_FAV (object);
switch (prop_id)
{
case PROP_WINDOW:
g_value_set_object (value, fav->priv->window);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
vinagre_fav_class_init (VinagreFavClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = vinagre_fav_finalize;
object_class->get_property = vinagre_fav_get_property;
object_class->set_property = vinagre_fav_set_property;
g_object_class_install_property (object_class,
PROP_WINDOW,
g_param_spec_object ("window",
"Window",
"The VinagreWindow this panel is associated with",
VINAGRE_TYPE_WINDOW,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[FAV_ACTIVATED] =
g_signal_new ("fav-activated",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (VinagreFavClass, fav_activated),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
signals[FAV_SELECTED] =
g_signal_new ("fav-selected",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (VinagreFavClass, fav_selected),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_type_class_add_private (object_class, sizeof (VinagreFavPrivate));
}
static void
vinagre_fav_row_activated_cb (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *column,
VinagreFav *fav)
{
GtkTreeIter iter;
VinagreConnection *conn = NULL;
gtk_tree_model_get_iter (fav->priv->model, &iter, path);
gtk_tree_model_get (fav->priv->model,
&iter,
CONN_COL, &conn,
-1);
/* Emits the signal saying that user has activated a bookmark */
g_signal_emit (G_OBJECT (fav),
signals[FAV_ACTIVATED],
0,
conn);
}
static void
vinagre_fav_selection_changed_cb (GtkTreeSelection *selection,
VinagreFav *fav)
{
GtkTreeIter iter;
VinagreConnection *conn = NULL;
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
gtk_tree_model_get (fav->priv->model,
&iter,
CONN_COL, &conn,
-1);
}
/* Emits the signal saying that user has selected a bookmark */
g_signal_emit (G_OBJECT (fav),
signals[FAV_SELECTED],
0,
conn);
}
static GtkTreePath *
get_current_path (VinagreFav *fav)
{
GtkTreePath *path = NULL;
GtkTreeIter iter;
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fav->priv->tree));
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
path = gtk_tree_model_get_path (fav->priv->model, &iter);
return path;
}
static void
menu_position (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
VinagreFav *fav)
{
GtkTreePath *path;
GdkRectangle rect;
gint wx, wy;
GtkRequisition requisition;
GtkWidget *w;
w = fav->priv->tree;
path = get_current_path (fav);
gtk_tree_view_get_cell_area (GTK_TREE_VIEW (w),
path,
NULL,
&rect);
wx = rect.x;
wy = rect.y;
gdk_window_get_origin (w->window, x, y);
gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
*x += w->allocation.x + w->allocation.width - requisition.width - 10;
else
*x += w->allocation.x + 10 ;
wy = MAX (*y + 5, *y + wy + 5);
wy = MIN (wy, *y + w->allocation.height - requisition.height - 5);
*y = wy;
*push_in = TRUE;
if (path)
gtk_tree_path_free (path);
}
static gboolean
show_popup_menu (VinagreFav *fav,
GdkEventButton *event)
{
GtkWidget *menu = NULL;
menu = gtk_ui_manager_get_widget (vinagre_window_get_ui_manager (fav->priv->window),
"/FavPopup");
g_return_val_if_fail (menu != NULL, FALSE);
if (event)
{
gtk_menu_popup (GTK_MENU (menu),
NULL,
NULL,
NULL,
NULL,
event->button,
event->time);
}
else
{
gtk_menu_popup (GTK_MENU (menu),
NULL,
NULL,
(GtkMenuPositionFunc) menu_position,
fav,
0,
gtk_get_current_event_time ());
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
}
return TRUE;
}
static gboolean
fav_button_press_event (GtkTreeView *treeview,
GdkEventButton *event,
VinagreFav *fav)
{
if ((GDK_BUTTON_PRESS == event->type) && (3 == event->button))
{
GtkTreePath* path = NULL;
if (event->window == gtk_tree_view_get_bin_window (treeview))
{
/* Change the cursor position */
if (gtk_tree_view_get_path_at_pos (treeview,
event->x,
event->y,
&path,
NULL,
NULL,
NULL))
{
gtk_tree_view_set_cursor (treeview,
path,
NULL,
FALSE);
gtk_tree_path_free (path);
/* A row exists at mouse position */
return show_popup_menu (fav, event);
}
}
}
return FALSE;
}
static gboolean
fav_popup_menu (GtkWidget *treeview,
VinagreFav *fav)
{
/* Only respond if the treeview is the actual focus */
if (gtk_window_get_focus (GTK_WINDOW (fav->priv->window)) == treeview)
return show_popup_menu (fav, NULL);
return FALSE;
}
static void
vinagre_fav_create_tree (VinagreFav *fav)
{
GtkCellRenderer *cell;
GtkWidget *scroll;
GtkTreeSelection *selection;
/* Create the scrolled window */
scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
GTK_SHADOW_ETCHED_OUT);
gtk_box_pack_start (GTK_BOX(fav), scroll, TRUE, TRUE, 0);
/* Create the model */
fav->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
GDK_TYPE_PIXBUF,
G_TYPE_STRING,
G_TYPE_POINTER));
fav->priv->tree = gtk_tree_view_new_with_model (fav->priv->model);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fav->priv->tree), FALSE);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fav->priv->tree));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
g_signal_connect (selection, "changed", G_CALLBACK (vinagre_fav_selection_changed_cb), fav);
cell = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (fav->priv->tree),
-1,
_("Image"),
cell,
"pixbuf", IMAGE_COL,
NULL);
cell = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW (fav->priv->tree),
-1,
_("Name"),
cell,
"text", NAME_COL,
NULL);
g_signal_connect (fav->priv->tree,
"row-activated",
G_CALLBACK (vinagre_fav_row_activated_cb),
fav);
g_signal_connect (fav->priv->tree,
"button-press-event",
G_CALLBACK (fav_button_press_event),
fav);
g_signal_connect (fav->priv->tree,
"popup-menu",
G_CALLBACK (fav_popup_menu),
fav);
vinagre_fav_update_list (fav);
gtk_container_add (GTK_CONTAINER(scroll), fav->priv->tree);
gtk_widget_show (fav->priv->tree);
g_object_unref (G_OBJECT (fav->priv->model));
}
static void
vinagre_fav_hide (GtkButton *button, VinagreFav *fav)
{
GtkAction *action;
action = gtk_action_group_get_action (fav->priv->window->priv->always_sensitive_action_group,
"ViewBookmarks");
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
}
static void
vinagre_fav_init (VinagreFav *fav)
{
GtkWidget *label_box, *label, *close_button;
fav->priv = VINAGRE_FAV_GET_PRIVATE (fav);
/* setup label */
label_box = gtk_hbox_new (FALSE, 0);
label = gtk_label_new (_("Bookmarks"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (label), 6, 6);
gtk_box_pack_start (GTK_BOX(label_box), label, TRUE, TRUE, 0);
/* setup small close button */
close_button = vinagre_utils_create_small_close_button ();
gtk_box_pack_start (GTK_BOX(label_box), close_button, FALSE, FALSE, 0);
gtk_widget_set_tooltip_text (close_button, _("Hide bookmarks"));
gtk_box_pack_start (GTK_BOX(fav), label_box, FALSE, FALSE, 0);
g_signal_connect (close_button,
"clicked",
G_CALLBACK (vinagre_fav_hide),
fav);
/* setup the tree */
vinagre_fav_create_tree (fav);
}
GtkWidget *
vinagre_fav_new (VinagreWindow *window)
{
g_return_val_if_fail (VINAGRE_IS_WINDOW (window), NULL);
return GTK_WIDGET (g_object_new (VINAGRE_TYPE_FAV,
"window", window,
NULL));
}
void
vinagre_fav_update_list (VinagreFav *fav)
{
GtkTreeIter iter;
GtkListStore *store;
GList *list;
VinagreConnection *conn;
gchar *name;
GdkPixbuf *pixbuf;
g_return_if_fail (VINAGRE_IS_FAV (fav));
store = GTK_LIST_STORE (fav->priv->model);
gtk_list_store_clear (store);
list = vinagre_bookmarks_get_all ();
while (list)
{
conn = (VinagreConnection *) list->data;
name = vinagre_connection_best_name (conn);
pixbuf = vinagre_connection_get_icon (conn);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
IMAGE_COL, pixbuf,
NAME_COL, name,
CONN_COL, conn,
-1);
list = list->next;
g_free (name);
if (pixbuf != NULL)
g_object_unref (pixbuf);
}
g_list_free (list);
}
/* vim: ts=8 */
syntax highlighted by Code2HTML, v. 0.9.1