summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2004-11-05 14:18:54 +0000
committerAlexander Larsson <alexl@src.gnome.org>2004-11-05 14:18:54 +0000
commit6c3b21c4d928d14ca926504ceb87f4c2e017050e (patch)
tree089e5d0a2ec0a57356ee49e6d38cab682bc1b93c
parentca4e49eb4b08f298ff532f2e8f6c2afabd3887e5 (diff)
downloadnautilus-6c3b21c4d928d14ca926504ceb87f4c2e017050e.tar.gz
Fix crash when switching view.
2004-11-05 Alexander Larsson <alexl@redhat.com> * src/file-manager/fm-list-view.c: Fix crash when switching view. * src/nautilus-history-sidebar.c: Some cleanups * src/nautilus-navigation-window.c: Fix unref-null warning * src/Makefile.am: * src/nautilus-application.c: * src/nautilus-notes-sidebar.[ch]: Add notes sidebar widget, based on old component * components/Makefile.am (SUBDIRS): Remove notes
-rw-r--r--ChangeLog19
-rw-r--r--components/Makefile.am1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/file-manager/fm-list-view.c84
-rw-r--r--src/nautilus-application.c2
-rw-r--r--src/nautilus-history-sidebar.c74
-rw-r--r--src/nautilus-navigation-window.c4
-rw-r--r--src/nautilus-notes-sidebar.c447
-rw-r--r--src/nautilus-notes-sidebar.h49
9 files changed, 603 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index dcec5e5c1..dfee830dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2004-11-05 Alexander Larsson <alexl@redhat.com>
+ * src/file-manager/fm-list-view.c:
+ Fix crash when switching view.
+
+ * src/nautilus-history-sidebar.c:
+ Some cleanups
+
+ * src/nautilus-navigation-window.c:
+ Fix unref-null warning
+
+ * src/Makefile.am:
+ * src/nautilus-application.c:
+ * src/nautilus-notes-sidebar.[ch]:
+ Add notes sidebar widget, based on old component
+
+ * components/Makefile.am (SUBDIRS):
+ Remove notes
+
+2004-11-05 Alexander Larsson <alexl@redhat.com>
+
* components/Makefile.am:
Remove stuff that are now replaced or not needed anymore.
diff --git a/components/Makefile.am b/components/Makefile.am
index 6106a59f3..5188faeca 100644
--- a/components/Makefile.am
+++ b/components/Makefile.am
@@ -1,7 +1,6 @@
NULL=
SUBDIRS = \
- notes \
throbber \
emblem \
image_properties \
diff --git a/src/Makefile.am b/src/Makefile.am
index b2c0b14a3..ee92af322 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,8 @@ nautilus_SOURCES = \
nautilus-navigation-window-menus.c \
nautilus-navigation-window.c \
nautilus-navigation-window.h \
+ nautilus-notes-sidebar.c \
+ nautilus-notes-sidebar.h \
nautilus-profiler.c \
nautilus-profiler.h \
nautilus-property-browser.c \
diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c
index aa1779531..a1a18d4bb 100644
--- a/src/file-manager/fm-list-view.c
+++ b/src/file-manager/fm-list-view.c
@@ -456,7 +456,7 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
view = FM_LIST_VIEW (callback_data);
tree_view = GTK_TREE_VIEW (widget);
tree_view_class = GTK_WIDGET_GET_CLASS (tree_view);
- selection = gtk_tree_view_get_selection(tree_view);
+ selection = gtk_tree_view_get_selection (tree_view);
if (event->window != gtk_tree_view_get_bin_window (tree_view)) {
return FALSE;
@@ -492,6 +492,8 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
allow_drag = FALSE;
if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
&path, NULL, NULL, NULL)) {
+ /* Keep track of path of last click so double clicks only happen
+ * on the same item */
if ((event->button == 1 || event->button == 2) &&
event->type == GDK_BUTTON_PRESS) {
if (view->details->double_click_path[1]) {
@@ -503,9 +505,9 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
if (event->type == GDK_2BUTTON_PRESS) {
/* Double clicking does not trigger a D&D action. */
view->details->drag_button = 0;
- call_parent = TRUE;
if (view->details->double_click_path[1] &&
gtk_tree_path_compare (view->details->double_click_path[0], view->details->double_click_path[1]) == 0) {
+ /* NOTE: Activation can actually destroy the view if we're switching */
if (!button_event_modifies_selection (event)) {
if ((event->button == 1 || event->button == 3)) {
activate_selected_items (view);
@@ -522,46 +524,48 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
}
}
}
- }
-
- /* We're going to filter out some situations where
- * we can't let the default code run because all
- * but one row would be would be deselected. We don't
- * want that; we want the right click menu or single
- * click to apply to everything that's currently selected. */
-
- if (event->button == 3 && gtk_tree_selection_path_is_selected (selection, path)) {
- call_parent = FALSE;
- }
-
- if ((event->button == 1 || event->button == 2) &&
- ((event->state & GDK_CONTROL_MASK) != 0 ||
- (event->state & GDK_SHIFT_MASK) == 0)) {
- view->details->row_selected_on_button_down = gtk_tree_selection_path_is_selected (selection, path);
- if (view->details->row_selected_on_button_down) {
- call_parent = FALSE;
- } else if ((event->state & GDK_CONTROL_MASK) != 0) {
+ tree_view_class->button_press_event (widget, event);
+ } else {
+
+ /* We're going to filter out some situations where
+ * we can't let the default code run because all
+ * but one row would be would be deselected. We don't
+ * want that; we want the right click menu or single
+ * click to apply to everything that's currently selected. */
+
+ if (event->button == 3 && gtk_tree_selection_path_is_selected (selection, path)) {
call_parent = FALSE;
- gtk_tree_selection_select_path (selection, path);
+ }
+
+ if ((event->button == 1 || event->button == 2) &&
+ ((event->state & GDK_CONTROL_MASK) != 0 ||
+ (event->state & GDK_SHIFT_MASK) == 0)) {
+ view->details->row_selected_on_button_down = gtk_tree_selection_path_is_selected (selection, path);
+ if (view->details->row_selected_on_button_down) {
+ call_parent = FALSE;
+ } else if ((event->state & GDK_CONTROL_MASK) != 0) {
+ call_parent = FALSE;
+ gtk_tree_selection_select_path (selection, path);
+ }
+ }
+
+ if (call_parent) {
+ tree_view_class->button_press_event (widget, event);
+ } else if (gtk_tree_selection_path_is_selected (selection, path)) {
+ gtk_widget_grab_focus (widget);
+ }
+
+ if ((event->button == 1 || event->button == 2) &&
+ event->type == GDK_BUTTON_PRESS) {
+ view->details->drag_started = FALSE;
+ view->details->drag_button = event->button;
+ view->details->drag_x = event->x;
+ view->details->drag_y = event->y;
+ }
+
+ if (event->button == 3) {
+ do_popup_menu (widget, view, event);
}
- }
-
- if (call_parent) {
- tree_view_class->button_press_event (widget, event);
- } else if (gtk_tree_selection_path_is_selected (selection, path)) {
- gtk_widget_grab_focus (widget);
- }
-
- if ((event->button == 1 || event->button == 2) &&
- event->type == GDK_BUTTON_PRESS) {
- view->details->drag_started = FALSE;
- view->details->drag_button = event->button;
- view->details->drag_x = event->x;
- view->details->drag_y = event->y;
- }
-
- if (event->button == 3) {
- do_popup_menu (widget, view, event);
}
gtk_tree_path_free (path);
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 9c89cedae..35cf77782 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -37,6 +37,7 @@
#include "file-manager/fm-tree-view.h"
#include "nautilus-information-panel.h"
#include "nautilus-history-sidebar.h"
+#include "nautilus-notes-sidebar.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -175,6 +176,7 @@ nautilus_application_instance_init (NautilusApplication *application)
/* register sidebars */
nautilus_information_panel_register ();
nautilus_history_sidebar_register ();
+ nautilus_notes_sidebar_register ();
}
NautilusApplication *
diff --git a/src/nautilus-history-sidebar.c b/src/nautilus-history-sidebar.c
index eaba273f3..74e4e1ba1 100644
--- a/src/nautilus-history-sidebar.c
+++ b/src/nautilus-history-sidebar.c
@@ -68,7 +68,7 @@ G_DEFINE_TYPE_WITH_CODE (NautilusHistorySidebar, nautilus_history_sidebar, GTK_T
nautilus_history_sidebar_iface_init));
static void
-update_history (NautilusHistorySidebar *view)
+update_history (NautilusHistorySidebar *sidebar)
{
GtkListStore *store;
GtkTreeSelection *selection;
@@ -78,11 +78,11 @@ update_history (NautilusHistorySidebar *view)
char *name;
GList *l, *history;
- store = GTK_LIST_STORE (gtk_tree_view_get_model (view->tree_view));
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (sidebar->tree_view));
gtk_list_store_clear (store);
- history = nautilus_window_info_get_history (view->window);
+ history = nautilus_window_info_get_history (sidebar->window);
for (l = history; l != NULL; l = l->next) {
bookmark = nautilus_bookmark_copy (l->data);
@@ -102,7 +102,7 @@ update_history (NautilusHistorySidebar *view)
}
eel_g_object_list_free (history);
- selection = GTK_TREE_SELECTION (gtk_tree_view_get_selection (view->tree_view));
+ selection = GTK_TREE_SELECTION (gtk_tree_view_get_selection (sidebar->tree_view));
if (gtk_tree_model_get_iter_root (GTK_TREE_MODEL (store), &iter)) {
gtk_tree_selection_select_iter (selection, &iter);
@@ -111,9 +111,9 @@ update_history (NautilusHistorySidebar *view)
static void
history_changed_callback (GObject *signaller,
- NautilusHistorySidebar *view)
+ NautilusHistorySidebar *sidebar)
{
- update_history (view);
+ update_history (sidebar);
}
static void
@@ -122,13 +122,13 @@ row_activated_callback (GtkTreeView *tree_view,
GtkTreeViewColumn *column,
gpointer user_data)
{
- NautilusHistorySidebar *view;
+ NautilusHistorySidebar *sidebar;
GtkTreeModel *model;
GtkTreeIter iter;
NautilusBookmark *bookmark;
char *uri;
- view = NAUTILUS_HISTORY_SIDEBAR (user_data);
+ sidebar = NAUTILUS_HISTORY_SIDEBAR (user_data);
model = gtk_tree_view_get_model (tree_view);
if (!gtk_tree_model_get_iter (model, &iter, path)) {
@@ -141,34 +141,34 @@ row_activated_callback (GtkTreeView *tree_view,
/* Navigate to the clicked location. */
uri = nautilus_bookmark_get_uri (NAUTILUS_BOOKMARK (bookmark));
nautilus_window_info_open_location
- (view->window,
+ (sidebar->window,
uri, NAUTILUS_WINDOW_OPEN_ACCORDING_TO_MODE, 0, NULL);
g_free (uri);
}
static void
-update_click_policy (NautilusHistorySidebar *view)
+update_click_policy (NautilusHistorySidebar *sidebar)
{
int policy;
policy = eel_preferences_get_enum (NAUTILUS_PREFERENCES_CLICK_POLICY);
eel_gtk_tree_view_set_activate_on_single_click
- (view->tree_view, policy == NAUTILUS_CLICK_POLICY_SINGLE);
+ (sidebar->tree_view, policy == NAUTILUS_CLICK_POLICY_SINGLE);
}
static void
click_policy_changed_callback (gpointer user_data)
{
- NautilusHistorySidebar *view;
+ NautilusHistorySidebar *sidebar;
- view = NAUTILUS_HISTORY_SIDEBAR (user_data);
+ sidebar = NAUTILUS_HISTORY_SIDEBAR (user_data);
- update_click_policy (view);
+ update_click_policy (sidebar);
}
static void
-nautilus_history_sidebar_init (NautilusHistorySidebar *view)
+nautilus_history_sidebar_init (NautilusHistorySidebar *sidebar)
{
GtkTreeView *tree_view;
GtkTreeViewColumn *col;
@@ -204,43 +204,43 @@ nautilus_history_sidebar_init (NautilusHistorySidebar *view)
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view),
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (view), NULL);
- gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (view), NULL);
- gtk_container_add (GTK_CONTAINER (view), GTK_WIDGET (tree_view));
- gtk_widget_show (GTK_WIDGET (view));
+ gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
+ gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
+ gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view));
+ gtk_widget_show (GTK_WIDGET (sidebar));
- view->tree_view = tree_view;
+ sidebar->tree_view = tree_view;
selection = gtk_tree_view_get_selection (tree_view);
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
g_signal_connect_object
(tree_view, "row_activated",
- G_CALLBACK (row_activated_callback), view, 0);
+ G_CALLBACK (row_activated_callback), sidebar, 0);
g_signal_connect_object (nautilus_signaller_get_current (),
"history_list_changed",
- G_CALLBACK (history_changed_callback), view, 0);
+ G_CALLBACK (history_changed_callback), sidebar, 0);
eel_preferences_add_callback (NAUTILUS_PREFERENCES_CLICK_POLICY,
click_policy_changed_callback,
- view);
- update_click_policy (view);
+ sidebar);
+ update_click_policy (sidebar);
}
static void
nautilus_history_sidebar_finalize (GObject *object)
{
- NautilusHistorySidebar *view;
+ NautilusHistorySidebar *sidebar;
- view = NAUTILUS_HISTORY_SIDEBAR (object);
+ sidebar = NAUTILUS_HISTORY_SIDEBAR (object);
eel_preferences_remove_callback (NAUTILUS_PREFERENCES_CLICK_POLICY,
click_policy_changed_callback,
- view);
+ sidebar);
G_OBJECT_CLASS (nautilus_history_sidebar_parent_class)->finalize (object);
}
@@ -286,24 +286,24 @@ nautilus_history_sidebar_iface_init (NautilusSidebarIface *iface)
}
static void
-nautilus_history_sidebar_set_parent_window (NautilusHistorySidebar *view,
+nautilus_history_sidebar_set_parent_window (NautilusHistorySidebar *sidebar,
NautilusWindowInfo *window)
{
- view->window = window;
- update_history (view);
+ sidebar->window = window;
+ update_history (sidebar);
}
static NautilusSidebar *
nautilus_history_sidebar_create (NautilusWindowInfo *window)
{
- NautilusHistorySidebar *view;
+ NautilusHistorySidebar *sidebar;
- view = g_object_new (nautilus_history_sidebar_get_type (), NULL);
- nautilus_history_sidebar_set_parent_window (view, window);
- g_object_ref (view);
- gtk_object_sink (GTK_OBJECT (view));
+ sidebar = g_object_new (nautilus_history_sidebar_get_type (), NULL);
+ nautilus_history_sidebar_set_parent_window (sidebar, window);
+ g_object_ref (sidebar);
+ gtk_object_sink (GTK_OBJECT (sidebar));
- return NAUTILUS_SIDEBAR (view);
+ return NAUTILUS_SIDEBAR (sidebar);
}
static NautilusSidebarInfo history_sidebar = {
diff --git a/src/nautilus-navigation-window.c b/src/nautilus-navigation-window.c
index 44b5186db..b75e48872 100644
--- a/src/nautilus-navigation-window.c
+++ b/src/nautilus-navigation-window.c
@@ -989,7 +989,9 @@ side_panel_image_changed_callback (NautilusSidebar *side_panel,
nautilus_side_pane_set_panel_image (NAUTILUS_NAVIGATION_WINDOW (window)->sidebar,
GTK_WIDGET (side_panel),
icon);
- g_object_unref (icon);
+ if (icon != NULL) {
+ g_object_unref (icon);
+ }
}
void
diff --git a/src/nautilus-notes-sidebar.c b/src/nautilus-notes-sidebar.c
new file mode 100644
index 000000000..8edbe53f1
--- /dev/null
+++ b/src/nautilus-notes-sidebar.c
@@ -0,0 +1,447 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * Nautilus
+ *
+ * Copyright (C) 2000, 2001 Eazel, Inc.
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Andy Hertzfeld <andy@eazel.com>
+ *
+ */
+
+/* notes sidebar panel -- allows editing per-directory notes */
+
+#include <config.h>
+
+#include "nautilus-notes-sidebar.h"
+
+#include <eel/eel-debug.h>
+#include <eel/eel-gtk-extensions.h>
+#include <eel/eel-string.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtktextbuffer.h>
+#include <gtk/gtktextview.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <bonobo/bonobo-property-bag.h>
+#include <libnautilus-private/nautilus-file-attributes.h>
+#include <libnautilus-private/nautilus-file.h>
+#include <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-metadata.h>
+#include <libnautilus-private/nautilus-clipboard.h>
+#include <libnautilus-private/nautilus-bonobo-extensions.h>
+#include <libnautilus-private/nautilus-sidebar-factory.h>
+#include <libnautilus-private/nautilus-theme.h>
+
+#define SAVE_TIMEOUT (3 * 1000)
+
+static void load_note_text_from_metadata (NautilusFile *file,
+ NautilusNotesSidebar *notes);
+static void notes_save_metainfo (NautilusNotesSidebar *notes);
+static void nautilus_notes_sidebar_iface_init (NautilusSidebarIface *iface);
+static void on_changed (GtkEditable *editable,
+ NautilusNotesSidebar *notes);
+
+typedef struct {
+ GtkScrolledWindowClass parent;
+} NautilusNotesSidebarClass;
+
+G_DEFINE_TYPE_WITH_CODE (NautilusNotesSidebar, nautilus_notes_sidebar, GTK_TYPE_SCROLLED_WINDOW,
+ G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR,
+ nautilus_notes_sidebar_iface_init));
+
+
+struct _NautilusNotesSidebarDetails {
+ NautilusWindowInfo *window;
+ GtkWidget *note_text_field;
+ GtkTextBuffer *text_buffer;
+ char *uri;
+ NautilusFile *file;
+ guint save_timeout_id;
+ char *previous_saved_text;
+ GdkPixbuf *icon;
+};
+
+static gboolean
+schedule_save_callback (gpointer data)
+{
+ NautilusNotesSidebar *notes;
+
+ notes = data;
+
+ /* Zero out save_timeout_id so no one will try to cancel our
+ * in-progress timeout callback.
+ */
+ notes->details->save_timeout_id = 0;
+
+ notes_save_metainfo (notes);
+
+ return FALSE;
+}
+
+static void
+cancel_pending_save (NautilusNotesSidebar *notes)
+{
+ if (notes->details->save_timeout_id != 0) {
+ g_source_remove (notes->details->save_timeout_id);
+ notes->details->save_timeout_id = 0;
+ }
+}
+
+static void
+schedule_save (NautilusNotesSidebar *notes)
+{
+ cancel_pending_save (notes);
+
+ notes->details->save_timeout_id = g_timeout_add (SAVE_TIMEOUT, schedule_save_callback, notes);
+}
+
+/* notifies event listeners if the notes data actually changed */
+static void
+set_saved_text (NautilusNotesSidebar *notes, char *new_notes)
+{
+ char *old_text;
+
+ old_text = notes->details->previous_saved_text;
+ notes->details->previous_saved_text = new_notes;
+
+ if (eel_strcmp (old_text, new_notes) != 0) {
+ g_signal_emit_by_name (NAUTILUS_SIDEBAR (notes),
+ "tab_icon_changed");
+ }
+
+ g_free (old_text);
+}
+
+/* save the metainfo corresponding to the current uri, if any, into the text field */
+static void
+notes_save_metainfo (NautilusNotesSidebar *notes)
+{
+ char *notes_text;
+ GtkTextIter start_iter;
+ GtkTextIter end_iter;
+
+ if (notes->details->file == NULL) {
+ return;
+ }
+
+ cancel_pending_save (notes);
+
+ /* Block the handler, so we don't respond to our own change.
+ */
+ g_signal_handlers_block_matched (notes->details->file,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (load_note_text_from_metadata),
+ notes);
+
+ gtk_text_buffer_get_start_iter (notes->details->text_buffer, &start_iter);
+ gtk_text_buffer_get_end_iter (notes->details->text_buffer, &end_iter);
+ notes_text = gtk_text_buffer_get_text (notes->details->text_buffer,
+ &start_iter,
+ &end_iter,
+ FALSE);
+
+ nautilus_file_set_metadata (notes->details->file,
+ NAUTILUS_METADATA_KEY_ANNOTATION,
+ NULL, notes_text);
+
+ g_signal_handlers_unblock_matched (notes->details->file,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (load_note_text_from_metadata),
+ notes);
+
+ set_saved_text (notes, notes_text);
+}
+
+static void
+load_note_text_from_metadata (NautilusFile *file,
+ NautilusNotesSidebar *notes)
+{
+ char *saved_text;
+
+ g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (notes->details->file == file);
+
+ saved_text = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_ANNOTATION, "");
+
+ /* This fn is called for any change signal on the file, so make sure that the
+ * metadata has actually changed.
+ */
+ if (eel_strcmp (saved_text, notes->details->previous_saved_text) != 0) {
+ set_saved_text (notes, saved_text);
+ cancel_pending_save (notes);
+
+ /* Block the handler, so we don't respond to our own change.
+ */
+ g_signal_handlers_block_matched (notes->details->text_buffer,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (on_changed),
+ notes);
+ gtk_text_buffer_set_text (notes->details->text_buffer, saved_text, -1);
+ g_signal_handlers_unblock_matched (notes->details->text_buffer,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (on_changed),
+ notes);
+ } else {
+ g_free (saved_text);
+ }
+}
+
+static void
+done_with_file (NautilusNotesSidebar *notes)
+{
+ cancel_pending_save (notes);
+
+ if (notes->details->file != NULL) {
+ nautilus_file_monitor_remove (notes->details->file, notes);
+ g_signal_handlers_disconnect_matched (notes->details->file,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (load_note_text_from_metadata),
+ notes);
+ nautilus_file_unref (notes->details->file);
+ }
+}
+
+static void
+notes_load_metainfo (NautilusNotesSidebar *notes)
+{
+ NautilusFileAttributes attributes;
+
+ done_with_file (notes);
+ notes->details->file = nautilus_file_get (notes->details->uri);
+
+ /* Block the handler, so we don't respond to our own change.
+ */
+ g_signal_handlers_block_matched (notes->details->text_buffer,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (on_changed),
+ notes);
+ gtk_text_buffer_set_text (notes->details->text_buffer, "", -1);
+ g_signal_handlers_unblock_matched (notes->details->text_buffer,
+ G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL,
+ G_CALLBACK (on_changed),
+ notes);
+
+ if (notes->details->file == NULL) {
+ return;
+ }
+
+ attributes = NAUTILUS_FILE_ATTRIBUTE_METADATA;
+ nautilus_file_monitor_add (notes->details->file, notes, attributes);
+
+ if (nautilus_file_check_if_ready (notes->details->file, attributes)) {
+ load_note_text_from_metadata (notes->details->file, notes);
+ }
+
+ g_signal_connect (notes->details->file, "changed",
+ G_CALLBACK (load_note_text_from_metadata), notes);
+}
+
+static void
+loading_uri_callback (NautilusSidebar *sidebar,
+ const char *location,
+ NautilusNotesSidebar *notes)
+{
+ if (strcmp (notes->details->uri, location) != 0) {
+ notes_save_metainfo (notes);
+ g_free (notes->details->uri);
+ notes->details->uri = g_strdup (location);
+ notes_load_metainfo (notes);
+ }
+}
+
+static gboolean
+on_text_field_focus_out_event (GtkWidget *widget,
+ GdkEventFocus *event,
+ gpointer callback_data)
+{
+ NautilusNotesSidebar *notes;
+
+ notes = callback_data;
+ notes_save_metainfo (notes);
+ return FALSE;
+}
+
+static void
+on_changed (GtkEditable *editable, NautilusNotesSidebar *notes)
+{
+ schedule_save (notes);
+}
+
+static void
+nautilus_notes_sidebar_init (NautilusNotesSidebar *sidebar)
+{
+ char *image_path;
+ NautilusNotesSidebarDetails *details;
+
+ details = g_new0 (NautilusNotesSidebarDetails, 1);
+ sidebar->details = details;
+
+ details->uri = g_strdup ("");
+
+ image_path = nautilus_theme_get_image_path ("note-indicator.png");
+ if (image_path) {
+ details->icon = gdk_pixbuf_new_from_file (image_path, NULL);
+ g_free (image_path);
+ }
+
+ /* create the text container */
+ details->text_buffer = gtk_text_buffer_new (NULL);
+ details->note_text_field = gtk_text_view_new_with_buffer (details->text_buffer);
+
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (details->note_text_field), TRUE);
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (details->note_text_field),
+ GTK_WRAP_WORD);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sidebar),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
+ gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
+ gtk_container_add (GTK_CONTAINER (sidebar), details->note_text_field);
+
+ g_signal_connect (details->note_text_field, "focus_out_event",
+ G_CALLBACK (on_text_field_focus_out_event), sidebar);
+ g_signal_connect (details->text_buffer, "changed",
+ G_CALLBACK (on_changed), sidebar);
+
+ gtk_widget_show_all (GTK_WIDGET (sidebar));
+
+ /* handle selections */
+#ifdef GNOME2_CONVERSION_COMPLETE
+ nautilus_clipboard_set_up_editable_in_control
+ (GTK_EDITABLE (notes->note_text_field),
+ nautilus_view_get_bonobo_control (notes->view),
+ FALSE);
+#endif
+}
+
+static void
+nautilus_notes_sidebar_finalize (GObject *object)
+{
+ NautilusNotesSidebar *sidebar;
+
+ sidebar = NAUTILUS_NOTES_SIDEBAR (object);
+
+ done_with_file (sidebar);
+ if (sidebar->details->icon != NULL) {
+ g_object_unref (sidebar->details->icon);
+ }
+ g_free (sidebar->details->uri);
+ g_free (sidebar->details->previous_saved_text);
+ g_free (sidebar->details);
+
+ G_OBJECT_CLASS (nautilus_notes_sidebar_parent_class)->finalize (object);
+}
+
+
+static void
+nautilus_notes_sidebar_class_init (NautilusNotesSidebarClass *class)
+{
+ G_OBJECT_CLASS (class)->finalize = nautilus_notes_sidebar_finalize;
+}
+
+static const char *
+nautilus_notes_sidebar_get_sidebar_id (NautilusSidebar *sidebar)
+{
+ return NAUTILUS_NOTES_SIDEBAR_ID;
+}
+
+static char *
+nautilus_notes_sidebar_get_tab_label (NautilusSidebar *sidebar)
+{
+ return g_strdup (_("Notes"));
+}
+
+static GdkPixbuf *
+nautilus_notes_sidebar_get_tab_icon (NautilusSidebar *sidebar)
+{
+ NautilusNotesSidebar *notes;
+
+ notes = NAUTILUS_NOTES_SIDEBAR (sidebar);
+
+ if (notes->details->previous_saved_text != NULL &&
+ notes->details->previous_saved_text[0] != '\0') {
+ return g_object_ref (notes->details->icon);
+ }
+
+ return NULL;
+}
+
+static void
+nautilus_notes_sidebar_is_visible_changed (NautilusSidebar *sidebar,
+ gboolean is_visible)
+{
+ /* Do nothing */
+}
+
+static void
+nautilus_notes_sidebar_iface_init (NautilusSidebarIface *iface)
+{
+ iface->get_sidebar_id = nautilus_notes_sidebar_get_sidebar_id;
+ iface->get_tab_label = nautilus_notes_sidebar_get_tab_label;
+ iface->get_tab_icon = nautilus_notes_sidebar_get_tab_icon;
+ iface->is_visible_changed = nautilus_notes_sidebar_is_visible_changed;
+}
+
+static void
+nautilus_notes_sidebar_set_parent_window (NautilusNotesSidebar *sidebar,
+ NautilusWindowInfo *window)
+{
+ sidebar->details->window = window;
+
+ g_signal_connect_object (window, "loading_uri",
+ G_CALLBACK (loading_uri_callback), sidebar, 0);
+
+ g_free (sidebar->details->uri);
+ sidebar->details->uri = nautilus_window_info_get_current_location (window);
+ notes_load_metainfo (sidebar);
+}
+
+static NautilusSidebar *
+nautilus_notes_sidebar_create (NautilusWindowInfo *window)
+{
+ NautilusNotesSidebar *sidebar;
+
+ sidebar = g_object_new (nautilus_notes_sidebar_get_type (), NULL);
+ nautilus_notes_sidebar_set_parent_window (sidebar, window);
+ g_object_ref (sidebar);
+ gtk_object_sink (GTK_OBJECT (sidebar));
+
+ return NAUTILUS_SIDEBAR (sidebar);
+}
+
+static NautilusSidebarInfo notes_sidebar = {
+ NAUTILUS_NOTES_SIDEBAR_ID,
+ nautilus_notes_sidebar_create,
+};
+
+void
+nautilus_notes_sidebar_register (void)
+{
+ nautilus_sidebar_factory_register (&notes_sidebar);
+}
+
diff --git a/src/nautilus-notes-sidebar.h b/src/nautilus-notes-sidebar.h
new file mode 100644
index 000000000..3aa1707f7
--- /dev/null
+++ b/src/nautilus-notes-sidebar.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * Nautilus
+ *
+ * Copyright (C) 1999, 2000, 2004 Red Hat, Inc.
+ * Copyright (C) 2000, 2001 Eazel, Inc.
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Andy Hertzfeld <andy@eazel.com>
+ * Alexander Larsson <alexl@redhat.com>
+ */
+#ifndef _NAUTILUS_NOTES_SIDEBAR_H
+#define _NAUTILUS_NOTES_SIDEBAR_H
+
+#include <gtk/gtktreeview.h>
+#include <libnautilus-private/nautilus-view.h>
+#include <libnautilus-private/nautilus-window-info.h>
+#include <gtk/gtkscrolledwindow.h>
+
+#define NAUTILUS_NOTES_SIDEBAR_ID "NautilusNotesSidebar"
+
+#define NAUTILUS_TYPE_NOTES_SIDEBAR (nautilus_notes_sidebar_get_type ())
+#define NAUTILUS_NOTES_SIDEBAR(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_NOTES_SIDEBAR, NautilusNotesSidebar))
+
+typedef struct _NautilusNotesSidebarDetails NautilusNotesSidebarDetails;
+
+typedef struct {
+ GtkScrolledWindow parent;
+ NautilusNotesSidebarDetails *details;
+} NautilusNotesSidebar;
+
+GType nautilus_notes_sidebar_get_type (void);
+void nautilus_notes_sidebar_register (void);
+
+#endif