mirror of
https://gitlab.gnome.org/GNOME/eog
synced 2024-10-19 06:24:34 +00:00
f499965144
2002-02-03 Jens Finke <jens@triq.net> * eog-window.c (eog_window_drag_data_received): Use new gnome vfs API to extract filenames. This fixes drag'n'drop handling for Gnome2.
1054 lines
27 KiB
C
1054 lines
27 KiB
C
/* Eye of Gnome image viewer - main window widget
|
|
*
|
|
* Copyright (C) 2000 The Free Software Foundation
|
|
*
|
|
* Author: Federico Mena-Quintero <federico@gnu.org>
|
|
* Jens Finke <jens@gnome.org>
|
|
*
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <config.h>
|
|
#include <math.h>
|
|
#include <gnome.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gconf/gconf-client.h>
|
|
#include <bonobo-activation/bonobo-activation.h>
|
|
#include <bonobo/Bonobo.h>
|
|
#include <bonobo/bonobo-window.h>
|
|
#include <libgnomeui/gnome-window-icon.h>
|
|
#include <libgnomevfs/gnome-vfs.h>
|
|
#include "eog-preferences.h"
|
|
#include "eog-window.h"
|
|
#include "util.h"
|
|
#include "Eog.h"
|
|
|
|
/* Default size for windows */
|
|
|
|
#define DEFAULT_WINDOW_WIDTH 200
|
|
#define DEFAULT_WINDOW_HEIGHT 200
|
|
|
|
#define EOG_VIEWER_CONTROL_IID "OAFIID:GNOME_EOG_Control"
|
|
|
|
/* Private part of the Window structure */
|
|
struct _EogWindowPrivate {
|
|
/* Our GConf client */
|
|
GConfClient *client;
|
|
|
|
/* control frame */
|
|
BonoboControlFrame *ctrl_frame;
|
|
|
|
/* vbox */
|
|
GtkWidget *box;
|
|
|
|
/* statusbar */
|
|
GtkWidget *statusbar;
|
|
|
|
/* Window scrolling policy type */
|
|
GtkPolicyType sb_policy;
|
|
|
|
/* GConf client notify id's */
|
|
guint sb_policy_notify_id;
|
|
};
|
|
|
|
static void eog_window_class_init (EogWindowClass *class);
|
|
static void eog_window_init (EogWindow *window);
|
|
|
|
static gint eog_window_delete (GtkWidget *widget, GdkEventAny *event);
|
|
static gint eog_window_key_press (GtkWidget *widget, GdkEventKey *event);
|
|
static void eog_window_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
|
|
GtkSelectionData *selection_data, guint info, guint time);
|
|
|
|
static BonoboWindowClass *parent_class;
|
|
|
|
/* The list of all open windows */
|
|
static GList *window_list;
|
|
|
|
/* Drag target types */
|
|
enum {
|
|
TARGET_URI_LIST
|
|
};
|
|
|
|
|
|
|
|
/* Brings attention to a window by raising it and giving it focus */
|
|
static void
|
|
raise_and_focus (GtkWidget *widget)
|
|
{
|
|
g_assert (GTK_WIDGET_REALIZED (widget));
|
|
gdk_window_show (widget->window);
|
|
gtk_widget_grab_focus (widget);
|
|
}
|
|
|
|
/* Settings/Preferences callback */
|
|
static void
|
|
verb_Preferences_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|
{
|
|
EogWindow *window;
|
|
EogPreferences *preferences;
|
|
|
|
g_return_if_fail (user_data != NULL);
|
|
g_return_if_fail (EOG_IS_WINDOW (user_data));
|
|
|
|
window = EOG_WINDOW (user_data);
|
|
|
|
preferences = eog_preferences_new (window);
|
|
|
|
if (preferences != NULL)
|
|
gnome_dialog_run_and_close (GNOME_DIALOG (preferences));
|
|
}
|
|
|
|
static void
|
|
verb_FileNewWindow_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|
{
|
|
GtkWidget *win;
|
|
|
|
win = eog_window_new ();
|
|
|
|
gtk_widget_show (win);
|
|
}
|
|
|
|
static void
|
|
verb_FileOpen_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|
{
|
|
eog_window_open_dialog (EOG_WINDOW (user_data));
|
|
}
|
|
|
|
static void
|
|
verb_FileCloseWindow_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|
{
|
|
eog_window_close (EOG_WINDOW (user_data));
|
|
}
|
|
|
|
static void
|
|
verb_FileExit_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|
{
|
|
GList *l;
|
|
EogWindow *w;
|
|
|
|
/* Destroy windows and exit */
|
|
for (l = window_list; l != NULL; l = l->next) {
|
|
w = EOG_WINDOW (l->data);
|
|
gtk_widget_destroy (GTK_WIDGET (w));
|
|
}
|
|
g_list_free (window_list);
|
|
window_list = NULL;
|
|
|
|
bonobo_main_quit ();
|
|
}
|
|
|
|
static void
|
|
verb_HelpAbout_cb (BonoboUIComponent *uic, gpointer user_data, const char *cname)
|
|
{
|
|
static GtkWidget *about;
|
|
static const char *authors[] = {
|
|
"Federico Mena-Quintero",
|
|
"Martin Baulig",
|
|
"Arik Devens",
|
|
"Jens Finke",
|
|
"Michael Meeks",
|
|
"Lutz Mueller",
|
|
NULL
|
|
};
|
|
|
|
if (!about) {
|
|
about = gnome_about_new (
|
|
_("Eye of Gnome"),
|
|
VERSION,
|
|
_("Copyright (C) 2000-2002 The Free Software Foundation"),
|
|
_("The GNOME image viewing and cataloging program"),
|
|
authors,
|
|
NULL, /* char **documentors */
|
|
NULL, /* char *translators */
|
|
NULL);
|
|
gtk_signal_connect (GTK_OBJECT (about), "destroy",
|
|
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
|
|
&about);
|
|
}
|
|
|
|
gtk_widget_show_now (about);
|
|
raise_and_focus (about);
|
|
}
|
|
|
|
static void
|
|
activate_uri_cb (BonoboControlFrame *control_frame, const char *uri, gboolean relative, gpointer data)
|
|
{
|
|
EogWindow *window;
|
|
char *path;
|
|
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
window = EOG_WINDOW (eog_window_new ());
|
|
|
|
if (g_strncasecmp ("file:", uri, 5) == 0)
|
|
path = g_strdup ((uri+5));
|
|
else
|
|
path = g_strdup (uri);
|
|
|
|
eog_window_open (window, path);
|
|
gtk_widget_show (GTK_WIDGET (window));
|
|
|
|
g_free (path);
|
|
}
|
|
|
|
GType
|
|
eog_window_get_type (void)
|
|
{
|
|
static GType eog_window_type = 0;
|
|
|
|
if (!eog_window_type) {
|
|
static const GTypeInfo eog_window_info =
|
|
{
|
|
sizeof (EogWindowClass),
|
|
NULL, /* base_init */
|
|
NULL, /* base_finalize */
|
|
(GClassInitFunc) eog_window_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (EogWindow),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) eog_window_init,
|
|
};
|
|
|
|
eog_window_type = g_type_register_static (BONOBO_TYPE_WINDOW,
|
|
"EogWindow",
|
|
&eog_window_info, 0);
|
|
}
|
|
|
|
return eog_window_type;
|
|
}
|
|
|
|
/* Destroy handler for windows */
|
|
static void
|
|
eog_window_destroy (GtkObject *object)
|
|
{
|
|
EogWindow *window;
|
|
EogWindowPrivate *priv;
|
|
|
|
g_return_if_fail (object != NULL);
|
|
g_return_if_fail (EOG_IS_WINDOW (object));
|
|
|
|
if (getenv ("DEBUG_EOG"))
|
|
g_message ("Destroying EogWindow...");
|
|
|
|
window = EOG_WINDOW (object);
|
|
priv = window->priv;
|
|
|
|
if (priv->ctrl_frame != NULL) {
|
|
bonobo_object_unref (BONOBO_OBJECT (priv->ctrl_frame));
|
|
priv->ctrl_frame = NULL;
|
|
}
|
|
|
|
/* Clean up GConf-related stuff */
|
|
if (priv->client) {
|
|
gconf_client_notify_remove (priv->client, priv->sb_policy_notify_id);
|
|
gconf_client_remove_dir (priv->client, "/apps/eog", NULL);
|
|
g_object_unref (G_OBJECT (priv->client));
|
|
priv->client = NULL;
|
|
}
|
|
|
|
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
|
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
|
}
|
|
|
|
static void
|
|
eog_window_finalize (GObject *object)
|
|
{
|
|
EogWindow *window;
|
|
|
|
g_return_if_fail (EOG_IS_WINDOW (object));
|
|
|
|
window = EOG_WINDOW (object);
|
|
g_free (window->priv);
|
|
window->priv = NULL;
|
|
|
|
if (G_OBJECT_CLASS (parent_class)->finalize)
|
|
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
|
|
}
|
|
|
|
/* Class initialization function for windows */
|
|
static void
|
|
eog_window_class_init (EogWindowClass *class)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
GtkObjectClass *object_class;
|
|
GtkWidgetClass *widget_class;
|
|
|
|
gobject_class = (GObjectClass *) class;
|
|
object_class = (GtkObjectClass *) class;
|
|
widget_class = (GtkWidgetClass *) class;
|
|
|
|
parent_class = g_type_class_peek_parent (class);
|
|
|
|
object_class->destroy = eog_window_destroy;
|
|
gobject_class->finalize = eog_window_finalize;
|
|
|
|
widget_class->delete_event = eog_window_delete;
|
|
widget_class->key_press_event = eog_window_key_press;
|
|
widget_class->drag_data_received = eog_window_drag_data_received;
|
|
}
|
|
|
|
/* Handler for changes on the window sb policy */
|
|
static void
|
|
sb_policy_changed_cb (GConfClient *client, guint notify_id, GConfEntry *entry, gpointer data)
|
|
{
|
|
/* EogWindow *window;
|
|
EogWindowPrivate *priv;
|
|
|
|
window = EOG_WINDOW (data);
|
|
priv = window->priv;
|
|
|
|
priv->sb_policy = gconf_value_get_int (entry->value);
|
|
|
|
gtk_scroll_frame_set_policy (GTK_SCROLL_FRAME (priv->ui), priv->sb_policy, priv->sb_policy);*/
|
|
}
|
|
|
|
/* Object initialization function for windows */
|
|
static void
|
|
eog_window_init (EogWindow *window)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
|
|
priv = g_new0 (EogWindowPrivate, 1);
|
|
window->priv = priv;
|
|
|
|
priv->client = gconf_client_get_default ();
|
|
|
|
gconf_client_add_dir (priv->client, "/apps/eog",
|
|
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
|
|
|
|
priv->sb_policy_notify_id = gconf_client_notify_add (
|
|
priv->client, "/apps/eog/window/sb_policy",
|
|
sb_policy_changed_cb, window,
|
|
NULL, NULL);
|
|
|
|
priv->sb_policy = gconf_client_get_int (
|
|
priv->client, "/apps/eog/window/sb_policy",
|
|
NULL);
|
|
|
|
window_list = g_list_prepend (window_list, window);
|
|
|
|
gtk_window_set_policy (GTK_WINDOW (window), TRUE, TRUE, FALSE);
|
|
}
|
|
|
|
/* delete_event handler for windows */
|
|
static gint
|
|
eog_window_delete (GtkWidget *widget, GdkEventAny *event)
|
|
{
|
|
eog_window_close (EOG_WINDOW (widget));
|
|
return TRUE;
|
|
}
|
|
|
|
/* Key press handler for windows */
|
|
static gint
|
|
eog_window_key_press (GtkWidget *widget, GdkEventKey *event)
|
|
{
|
|
gint result;
|
|
|
|
result = FALSE;
|
|
|
|
if (GTK_WIDGET_CLASS (parent_class)->key_press_event)
|
|
result = (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
|
|
|
|
if (result)
|
|
return result;
|
|
|
|
switch (event->keyval) {
|
|
case GDK_Q:
|
|
case GDK_q:
|
|
verb_FileExit_cb (NULL, widget, NULL);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Returns whether a window has an image loaded in it */
|
|
static gboolean
|
|
eog_window_has_contents (EogWindow *window)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
|
|
g_return_val_if_fail (EOG_IS_WINDOW (window), FALSE);
|
|
|
|
priv = window->priv;
|
|
|
|
return (bonobo_control_frame_get_widget (priv->ctrl_frame) != NULL);
|
|
}
|
|
|
|
static GnomeUIInfo drag_ask_popup_menu [] = {
|
|
GNOMEUIINFO_ITEM_NONE (N_("Open in new window"), NULL, NULL),
|
|
GNOMEUIINFO_ITEM_NONE (N_("Open in this window"), NULL, NULL),
|
|
GNOMEUIINFO_SEPARATOR,
|
|
GNOMEUIINFO_ITEM_STOCK (N_("Cancel"), NULL , NULL, GNOME_STOCK_BUTTON_CANCEL),
|
|
GNOMEUIINFO_END
|
|
};
|
|
|
|
|
|
/* Drag_data_received handler for windows */
|
|
static void
|
|
eog_window_drag_data_received (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
gint x, gint y,
|
|
GtkSelectionData *selection_data,
|
|
guint info, guint time)
|
|
{
|
|
EogWindow *window;
|
|
EogWindowPrivate *priv;
|
|
GList *filenames = NULL;
|
|
GList *l;
|
|
gboolean need_new_window = TRUE;
|
|
|
|
window = EOG_WINDOW (widget);
|
|
priv = window->priv;
|
|
|
|
if (info != TARGET_URI_LIST)
|
|
return;
|
|
|
|
if (context->suggested_action == GDK_ACTION_ASK) {
|
|
GtkWidget *menu = gnome_popup_menu_new (drag_ask_popup_menu);
|
|
int i = gnome_popup_menu_do_popup_modal (menu, NULL, NULL,
|
|
NULL, NULL, NULL);
|
|
gtk_object_unref (GTK_OBJECT (menu));
|
|
switch (i) {
|
|
case 0:
|
|
need_new_window = TRUE;
|
|
break;
|
|
case 1:
|
|
need_new_window = FALSE;
|
|
break;
|
|
default:
|
|
return;
|
|
break;
|
|
}
|
|
} else {
|
|
/* The first image is opened in the same window only if the
|
|
* current window has no image in it.
|
|
*/
|
|
need_new_window = eog_window_has_contents (window);
|
|
}
|
|
|
|
filenames = gnome_vfs_uri_list_parse (selection_data->data);
|
|
|
|
for (l = filenames; l; l = l->next) {
|
|
GtkWidget *new_window;
|
|
char *filename;
|
|
|
|
g_assert (l->data != NULL);
|
|
filename = gnome_vfs_uri_to_string (l->data, GNOME_VFS_URI_HIDE_NONE);
|
|
|
|
if (need_new_window)
|
|
new_window = eog_window_new ();
|
|
else
|
|
new_window = GTK_WIDGET (window);
|
|
|
|
if (eog_window_open (EOG_WINDOW (new_window), filename)) {
|
|
gtk_widget_show_now (new_window);
|
|
need_new_window = TRUE;
|
|
} else {
|
|
open_failure_dialog (GTK_WINDOW (new_window), filename);
|
|
|
|
if (new_window != GTK_WIDGET (window))
|
|
gtk_widget_destroy (new_window);
|
|
}
|
|
}
|
|
|
|
gnome_vfs_uri_list_free (filenames);
|
|
}
|
|
|
|
/**
|
|
* eog_window_new:
|
|
* @void:
|
|
*
|
|
* Creates a new main window.
|
|
*
|
|
* Return value: A newly-created main window.
|
|
**/
|
|
GtkWidget *
|
|
eog_window_new (void)
|
|
{
|
|
EogWindow *window;
|
|
BonoboUIContainer *uic;
|
|
|
|
window = EOG_WINDOW (g_object_new (EOG_TYPE_WINDOW, NULL));
|
|
|
|
uic = bonobo_ui_container_new ();
|
|
bonobo_window_construct (BONOBO_WINDOW (window), uic, "eog", _("Eye Of Gnome"));
|
|
|
|
eog_window_construct (window);
|
|
|
|
return GTK_WIDGET (window);
|
|
}
|
|
|
|
/* Sets the window as a drag destination */
|
|
static void
|
|
set_drag_dest (EogWindow *window)
|
|
{
|
|
static const GtkTargetEntry drag_types[] = {
|
|
{ "text/uri-list", 0, TARGET_URI_LIST }
|
|
};
|
|
|
|
gtk_drag_dest_set (GTK_WIDGET (window),
|
|
GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
|
|
drag_types,
|
|
sizeof (drag_types) / sizeof (drag_types[0]),
|
|
GDK_ACTION_COPY | GDK_ACTION_ASK);
|
|
}
|
|
|
|
|
|
static BonoboUIVerb eog_app_verbs[] = {
|
|
BONOBO_UI_VERB ("FileNewWindow", verb_FileNewWindow_cb),
|
|
BONOBO_UI_VERB ("FileOpen", verb_FileOpen_cb),
|
|
BONOBO_UI_VERB ("FileCloseWindow", verb_FileCloseWindow_cb),
|
|
BONOBO_UI_VERB ("FileExit", verb_FileExit_cb),
|
|
BONOBO_UI_VERB ("Preferences", verb_Preferences_cb),
|
|
BONOBO_UI_VERB ("HelpAbout", verb_HelpAbout_cb),
|
|
BONOBO_UI_VERB_END
|
|
};
|
|
|
|
|
|
/**
|
|
* window_construct:
|
|
* @window: A window widget.
|
|
*
|
|
* Constructs the window widget.
|
|
**/
|
|
void
|
|
eog_window_construct (EogWindow *window)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
BonoboUIContainer *ui_container;
|
|
BonoboUIComponent *ui_comp;
|
|
gchar *fname;
|
|
GdkGeometry geometry;
|
|
|
|
g_return_if_fail (window != NULL);
|
|
g_return_if_fail (EOG_IS_WINDOW (window));
|
|
|
|
priv = window->priv;
|
|
|
|
ui_container = bonobo_window_get_ui_container (BONOBO_WINDOW (window));
|
|
|
|
bonobo_ui_engine_config_set_path (
|
|
bonobo_window_get_ui_engine (BONOBO_WINDOW (window)),
|
|
"/eog-shell/UIConf/kvps");
|
|
|
|
priv->box = GTK_WIDGET (gtk_vbox_new (FALSE, 0));
|
|
gtk_widget_show (priv->box);
|
|
bonobo_window_set_contents (BONOBO_WINDOW (window), priv->box);
|
|
|
|
/* add menu and toolbar */
|
|
ui_comp = bonobo_ui_component_new ("eog");
|
|
bonobo_ui_component_set_container (ui_comp,
|
|
BONOBO_OBJREF (ui_container), NULL);
|
|
|
|
fname = bonobo_ui_util_get_ui_fname (NULL, "eog-shell-ui.xml");
|
|
if (fname && g_file_exists (fname)) {
|
|
bonobo_ui_util_set_ui (ui_comp, NULL, "eog-shell-ui.xml", "EOG", NULL);
|
|
bonobo_ui_component_add_verb_list_with_data (ui_comp, eog_app_verbs, window);
|
|
} else {
|
|
g_error (N_("Can't find eog-shell-ui.xml.\n"));
|
|
}
|
|
g_free (fname);
|
|
|
|
/* add statusbar */
|
|
priv->statusbar = gnome_appbar_new (FALSE, TRUE, GNOME_PREFERENCES_NEVER);
|
|
gtk_box_pack_end (GTK_BOX (priv->box), GTK_WIDGET (priv->statusbar),
|
|
FALSE, FALSE, 0);
|
|
gtk_widget_show (GTK_WIDGET (priv->statusbar));
|
|
|
|
/* add control frame interface */
|
|
priv->ctrl_frame = bonobo_control_frame_new (BONOBO_OBJREF (ui_container));
|
|
bonobo_control_frame_set_autoactivate (priv->ctrl_frame, FALSE);
|
|
g_signal_connect (G_OBJECT (priv->ctrl_frame), "activate_uri",
|
|
(GtkSignalFunc) activate_uri_cb, NULL);
|
|
|
|
set_drag_dest (window);
|
|
|
|
/* set default geometry */
|
|
gtk_window_set_default_size (GTK_WINDOW (window),
|
|
DEFAULT_WINDOW_WIDTH,
|
|
DEFAULT_WINDOW_HEIGHT);
|
|
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
|
}
|
|
|
|
/**
|
|
* window_close:
|
|
* @window: A window.
|
|
*
|
|
* Closes a window with confirmation, and exits the main loop if this was the
|
|
* last window in the list.
|
|
**/
|
|
void
|
|
eog_window_close (EogWindow *window)
|
|
{
|
|
g_return_if_fail (window != NULL);
|
|
g_return_if_fail (EOG_IS_WINDOW (window));
|
|
|
|
window_list = g_list_remove (window_list, window);
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (window));
|
|
|
|
if (!window_list)
|
|
bonobo_main_quit ();
|
|
}
|
|
|
|
/* Open image dialog */
|
|
|
|
/* Opens an image in a new window */
|
|
static void
|
|
open_new_window (EogWindow *window, const char *filename)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
GtkWidget *new_window;
|
|
|
|
priv = window->priv;
|
|
|
|
if (!eog_window_has_contents (window))
|
|
new_window = GTK_WIDGET (window);
|
|
else
|
|
new_window = eog_window_new ();
|
|
|
|
if (eog_window_open (EOG_WINDOW (new_window), filename)) {
|
|
gtk_widget_show_now (new_window);
|
|
raise_and_focus (new_window);
|
|
} else {
|
|
open_failure_dialog (GTK_WINDOW (new_window), filename);
|
|
|
|
if (new_window != GTK_WIDGET (window))
|
|
gtk_widget_destroy (new_window);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* window_open_dialog:
|
|
* @window: A window.
|
|
*
|
|
* Creates an "open image" dialog for a window.
|
|
**/
|
|
void
|
|
eog_window_open_dialog (EogWindow *window)
|
|
{
|
|
char *filename;
|
|
EogWindowPrivate *priv;
|
|
|
|
g_return_if_fail (EOG_IS_WINDOW (window));
|
|
|
|
priv = window->priv;
|
|
|
|
/* FIXME: we should specify only image mime types */
|
|
filename = bonobo_file_selector_open (
|
|
GTK_WINDOW (window), FALSE, _("Open Image"), NULL, NULL);
|
|
|
|
if (filename) {
|
|
if (gconf_client_get_bool (priv->client, "/apps/eog/window/open_new_window", NULL))
|
|
open_new_window (window, filename);
|
|
else if (!eog_window_open (window, filename))
|
|
open_failure_dialog (GTK_WINDOW (window), filename);
|
|
g_free (filename);
|
|
}
|
|
}
|
|
|
|
static void
|
|
property_changed_cb (BonoboListener *listener,
|
|
char *event_name,
|
|
CORBA_any *any,
|
|
CORBA_Environment *ev,
|
|
gpointer user_data)
|
|
{
|
|
EogWindow *window;
|
|
|
|
window = EOG_WINDOW (user_data);
|
|
|
|
if (!g_strcasecmp (event_name, "Bonobo/Property:change:window/title"))
|
|
gtk_window_set_title (GTK_WINDOW (window),
|
|
BONOBO_ARG_GET_STRING (any));
|
|
else if (!g_strcasecmp (event_name,
|
|
"Bonobo/Property:change:window/status"))
|
|
gnome_appbar_set_status (GNOME_APPBAR (window->priv->statusbar),
|
|
BONOBO_ARG_GET_STRING (any));
|
|
}
|
|
|
|
static void
|
|
check_for_control_properties (EogWindow *window)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
Bonobo_PropertyBag pb;
|
|
gchar *title;
|
|
CORBA_Environment ev;
|
|
gchar *mask = NULL;
|
|
|
|
priv = window->priv;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
pb = bonobo_control_frame_get_control_property_bag (priv->ctrl_frame, &ev);
|
|
if (pb == CORBA_OBJECT_NIL)
|
|
goto on_error;
|
|
|
|
/* set window title */
|
|
title = bonobo_pbclient_get_string (pb, "window/title", &ev);
|
|
if (title != NULL) {
|
|
gtk_window_set_title (GTK_WINDOW (window), title);
|
|
g_free (title);
|
|
mask = g_strdup ("Bonobo/Property:change:window/title");
|
|
} else {
|
|
g_warning (_("Control doesn't support window_title property."));
|
|
gtk_window_set_title (GTK_WINDOW (window), "Eye of Gnome");
|
|
}
|
|
|
|
/* set status bar text */
|
|
title = bonobo_pbclient_get_string (pb, "window/status", &ev);
|
|
if (title != NULL) {
|
|
gchar *temp;
|
|
gnome_appbar_set_status (GNOME_APPBAR (priv->statusbar),
|
|
title);
|
|
g_free (title);
|
|
/* append status_text property to list of properties to listen */
|
|
temp = g_strjoin (",", mask, "Bonobo/Property:change:window/status", NULL);
|
|
g_free (mask);
|
|
mask = temp;
|
|
} else {
|
|
g_warning (_("Control doesn't support status_text property."));
|
|
}
|
|
|
|
/* register for further changes */
|
|
if (mask) {
|
|
g_print ("add listener: %s\n", mask);
|
|
bonobo_event_source_client_add_listener (pb,
|
|
(BonoboListenerCallbackFn)property_changed_cb,
|
|
mask, NULL, window);
|
|
g_free (mask);
|
|
}
|
|
|
|
bonobo_object_release_unref (pb, &ev);
|
|
CORBA_exception_free (&ev);
|
|
return;
|
|
|
|
on_error:
|
|
g_warning (_("Control doesn't have properties"));
|
|
gtk_window_set_title (GTK_WINDOW (window), "Eye of Gnome");
|
|
}
|
|
|
|
static Bonobo_Control
|
|
get_viewer_control (GnomeVFSURI *uri, GnomeVFSFileInfo *info)
|
|
{
|
|
Bonobo_Control control;
|
|
Bonobo_PersistFile pfile;
|
|
CORBA_Environment ev;
|
|
gchar *text_uri;
|
|
|
|
g_return_val_if_fail (uri != NULL, CORBA_OBJECT_NIL);
|
|
g_return_val_if_fail (info != NULL, CORBA_OBJECT_NIL);
|
|
|
|
/* check for valid mime_type */
|
|
if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) == 0) {
|
|
g_warning (_("Couldn't retrieve mime type for file."));
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
/* get control component */
|
|
control = bonobo_get_object (EOG_VIEWER_CONTROL_IID,
|
|
"Bonobo/Control", &ev);
|
|
if (BONOBO_EX (&ev) || (control == CORBA_OBJECT_NIL))
|
|
goto ctrl_error;
|
|
|
|
/* get PersistFile interface */
|
|
pfile = Bonobo_Unknown_queryInterface (control, "IDL:Bonobo/PersistFile:1.0", &ev);
|
|
if (BONOBO_EX (&ev) || (pfile == CORBA_OBJECT_NIL))
|
|
goto persist_file_error;
|
|
|
|
/* load the file */
|
|
text_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
|
|
Bonobo_PersistFile_load (pfile, text_uri, &ev);
|
|
bonobo_object_release_unref (pfile, NULL);
|
|
g_free (text_uri);
|
|
if (BONOBO_EX (&ev))
|
|
goto persist_file_error;
|
|
|
|
/* clean up */
|
|
CORBA_exception_free (&ev);
|
|
|
|
return control;
|
|
|
|
/* error handling */
|
|
persist_file_error:
|
|
bonobo_object_release_unref (control, NULL);
|
|
|
|
ctrl_error:
|
|
if (BONOBO_EX (&ev))
|
|
g_error ("%s", bonobo_exception_get_text (&ev));
|
|
|
|
CORBA_exception_free (&ev);
|
|
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
static Bonobo_Control
|
|
get_collection_control (GnomeVFSURI *uri, GnomeVFSFileInfo *info)
|
|
{
|
|
Bonobo_Unknown unknown_obj;
|
|
Bonobo_Control control;
|
|
GNOME_EOG_ImageCollection collection;
|
|
CORBA_Environment ev;
|
|
GNOME_EOG_URI eog_uri;
|
|
|
|
g_return_val_if_fail (uri != NULL, CORBA_OBJECT_NIL);
|
|
g_return_val_if_fail (info != NULL, CORBA_OBJECT_NIL);
|
|
|
|
/* activate component */
|
|
CORBA_exception_init (&ev);
|
|
unknown_obj = (Bonobo_Unknown) bonobo_activation_activate
|
|
("repo_ids.has_all(['IDL:GNOME/EOG/ImageCollection:1.0', 'IDL:Bonobo/Control:1.0'])",
|
|
NULL, 0, NULL, &ev);
|
|
if (unknown_obj == CORBA_OBJECT_NIL) return CORBA_OBJECT_NIL;
|
|
|
|
/* get collection image interface */
|
|
collection = Bonobo_Unknown_queryInterface (unknown_obj, "IDL:GNOME/EOG/ImageCollection:1.0", &ev);
|
|
if (collection == CORBA_OBJECT_NIL) {
|
|
Bonobo_Unknown_unref (unknown_obj, &ev);
|
|
CORBA_Object_release (unknown_obj, &ev);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
/* set uri */
|
|
eog_uri = (CORBA_char*) gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
|
|
GNOME_EOG_ImageCollection_openURI (collection, eog_uri, &ev);
|
|
g_free (eog_uri);
|
|
|
|
Bonobo_Unknown_unref (collection, &ev);
|
|
CORBA_Object_release (collection, &ev);
|
|
|
|
/* get Control interface */
|
|
control = Bonobo_Unknown_queryInterface (unknown_obj, "IDL:Bonobo/Control:1.0", &ev);
|
|
if (control == CORBA_OBJECT_NIL) {
|
|
Bonobo_Unknown_unref (unknown_obj, &ev);
|
|
CORBA_Object_release (unknown_obj, &ev);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
/* clean up */
|
|
Bonobo_Unknown_unref (unknown_obj, &ev);
|
|
CORBA_Object_release (unknown_obj, &ev);
|
|
CORBA_exception_free (&ev);
|
|
|
|
return control;
|
|
}
|
|
|
|
static Bonobo_Control
|
|
get_collection_control_list (GList *text_uri_list)
|
|
{
|
|
Bonobo_Unknown unknown_obj;
|
|
Bonobo_Control control;
|
|
GNOME_EOG_ImageCollection collection;
|
|
CORBA_Environment ev;
|
|
GNOME_EOG_URIList *uri_list;
|
|
GList *uri;
|
|
gint length, i;
|
|
|
|
g_return_val_if_fail (text_uri_list != NULL, CORBA_OBJECT_NIL);
|
|
|
|
/* activate component */
|
|
CORBA_exception_init (&ev);
|
|
unknown_obj = (Bonobo_Unknown) bonobo_activation_activate
|
|
("repo_ids.has_all(['IDL:GNOME/EOG/ImageCollection:1.0', 'IDL:Bonobo/Control:1.0'])",
|
|
NULL, 0, NULL, &ev);
|
|
if (unknown_obj == CORBA_OBJECT_NIL) return CORBA_OBJECT_NIL;
|
|
|
|
/* get collection image interface */
|
|
collection = Bonobo_Unknown_queryInterface (unknown_obj, "IDL:GNOME/EOG/ImageCollection:1.0", &ev);
|
|
if (collection == CORBA_OBJECT_NIL) {
|
|
Bonobo_Unknown_unref (unknown_obj, &ev);
|
|
CORBA_Object_release (unknown_obj, &ev);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
/* create string sequence */
|
|
length = g_list_length (text_uri_list);
|
|
uri_list = GNOME_EOG_URIList__alloc ();
|
|
uri_list->_maximum = length;
|
|
uri_list->_length = length;
|
|
uri_list->_buffer = CORBA_sequence_GNOME_EOG_URI_allocbuf (length);
|
|
uri = text_uri_list;
|
|
for (i = 0; i < length; i++) {
|
|
g_print ("List uri: %s\n", (gchar*) uri->data);
|
|
uri_list->_buffer[i] = CORBA_string_dup ((gchar*)uri->data);
|
|
uri = uri->next;
|
|
}
|
|
CORBA_sequence_set_release (uri_list, CORBA_TRUE);
|
|
|
|
/* set uris */
|
|
GNOME_EOG_ImageCollection_openURIList (collection, uri_list, &ev);
|
|
|
|
Bonobo_Unknown_unref (collection, &ev);
|
|
CORBA_Object_release (collection, &ev);
|
|
|
|
/* get Control interface */
|
|
control = Bonobo_Unknown_queryInterface (unknown_obj, "IDL:Bonobo/Control:1.0", &ev);
|
|
if (control == CORBA_OBJECT_NIL) {
|
|
Bonobo_Unknown_unref (unknown_obj, &ev);
|
|
CORBA_Object_release (unknown_obj, &ev);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
/* clean up */
|
|
Bonobo_Unknown_unref (unknown_obj, &ev);
|
|
CORBA_Object_release (unknown_obj, &ev);
|
|
CORBA_exception_free (&ev);
|
|
|
|
return control;
|
|
}
|
|
|
|
static void
|
|
add_control_to_ui (EogWindow *window, Bonobo_Control control)
|
|
{
|
|
GtkWidget *widget;
|
|
EogWindowPrivate *priv;
|
|
CORBA_Environment ev;
|
|
|
|
g_return_if_fail (window != NULL);
|
|
g_return_if_fail (EOG_IS_WINDOW (window));
|
|
|
|
priv = window->priv;
|
|
CORBA_exception_init (&ev);
|
|
|
|
bonobo_control_frame_bind_to_control (priv->ctrl_frame, control, &ev);
|
|
widget = bonobo_control_frame_get_widget (priv->ctrl_frame);
|
|
|
|
if (!widget) {
|
|
g_warning ("Could not create a widget from the control!");
|
|
return;
|
|
}
|
|
gtk_container_add (GTK_CONTAINER (priv->box), widget);
|
|
gtk_widget_show (widget);
|
|
|
|
bonobo_control_frame_control_activate (priv->ctrl_frame);
|
|
|
|
CORBA_exception_free (&ev);
|
|
|
|
/* retrieve control properties and install listeners */
|
|
check_for_control_properties (window);
|
|
}
|
|
|
|
/**
|
|
* window_open:
|
|
* @window: A window.
|
|
* @filename: An path to the object to load (image/directory).
|
|
*
|
|
* Opens an image file and puts it into a window. Even if loading fails, the
|
|
* image structure will be created and put in the window.
|
|
*
|
|
* Return value: TRUE on success, FALSE otherwise.
|
|
**/
|
|
gboolean
|
|
eog_window_open (EogWindow *window, const char *text_uri)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
Bonobo_Control control;
|
|
GnomeVFSResult result;
|
|
GnomeVFSFileInfo *info;
|
|
GnomeVFSURI *uri;
|
|
|
|
g_return_val_if_fail (window != NULL, FALSE);
|
|
g_return_val_if_fail (EOG_IS_WINDOW (window), FALSE);
|
|
g_return_val_if_fail (text_uri != NULL, FALSE);
|
|
|
|
priv = window->priv;
|
|
|
|
uri = gnome_vfs_uri_new (text_uri);
|
|
|
|
/* obtain file infos */
|
|
info = gnome_vfs_file_info_new ();
|
|
g_print ("URI: %s\n", gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE));
|
|
result = gnome_vfs_get_file_info_uri (uri, info,
|
|
GNOME_VFS_FILE_INFO_DEFAULT |
|
|
GNOME_VFS_FILE_INFO_FOLLOW_LINKS |
|
|
GNOME_VFS_FILE_INFO_GET_MIME_TYPE);
|
|
if (result != GNOME_VFS_OK) {
|
|
g_warning (_("Error while obtaining file informations."));
|
|
return FALSE;
|
|
}
|
|
|
|
/* get appropriate control */
|
|
if (info->type == GNOME_VFS_FILE_TYPE_REGULAR)
|
|
control = get_viewer_control (uri, info);
|
|
else if (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY)
|
|
control = get_collection_control (uri, info);
|
|
else {
|
|
gchar *str;
|
|
str = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
|
|
g_warning ("Couldn't handle: %s.\n", str);
|
|
g_free (str);
|
|
return FALSE;
|
|
}
|
|
|
|
/* add it to the user interface */
|
|
add_control_to_ui (window, control);
|
|
bonobo_object_release_unref (control, NULL);
|
|
|
|
/* clean up */
|
|
gnome_vfs_file_info_unref (info);
|
|
gnome_vfs_uri_unref (uri);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
gboolean
|
|
eog_window_open_list (EogWindow *window, GList *text_uri_list)
|
|
{
|
|
EogWindowPrivate *priv;
|
|
Bonobo_Control control;
|
|
|
|
g_return_val_if_fail (window != NULL, FALSE);
|
|
g_return_val_if_fail (EOG_IS_WINDOW (window), FALSE);
|
|
g_return_val_if_fail (text_uri_list != NULL, FALSE);
|
|
|
|
priv = window->priv;
|
|
|
|
/* get appropriate control */
|
|
control = get_collection_control_list (text_uri_list);
|
|
|
|
/* add it to the user interface */
|
|
add_control_to_ui (window, control);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bonobo_PropertyControl
|
|
eog_window_get_property_control (EogWindow *window, CORBA_Environment *ev)
|
|
{
|
|
Bonobo_Control control;
|
|
Bonobo_PropertyControl prop_control;
|
|
|
|
g_return_val_if_fail (window != NULL, CORBA_OBJECT_NIL);
|
|
g_return_val_if_fail (EOG_IS_WINDOW (window), CORBA_OBJECT_NIL);
|
|
|
|
control = bonobo_control_frame_get_control (window->priv->ctrl_frame);
|
|
if (control == CORBA_OBJECT_NIL) return CORBA_OBJECT_NIL;
|
|
|
|
prop_control = Bonobo_Unknown_queryInterface (control,
|
|
"IDL:Bonobo/PropertyControl:1.0", ev);
|
|
return prop_control;
|
|
}
|