diff options
author | Alexander Larsson <alexl@redhat.com> | 2004-11-05 14:18:54 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2004-11-05 14:18:54 +0000 |
commit | 6c3b21c4d928d14ca926504ceb87f4c2e017050e (patch) | |
tree | 089e5d0a2ec0a57356ee49e6d38cab682bc1b93c | |
parent | ca4e49eb4b08f298ff532f2e8f6c2afabd3887e5 (diff) | |
download | nautilus-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-- | ChangeLog | 19 | ||||
-rw-r--r-- | components/Makefile.am | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/file-manager/fm-list-view.c | 84 | ||||
-rw-r--r-- | src/nautilus-application.c | 2 | ||||
-rw-r--r-- | src/nautilus-history-sidebar.c | 74 | ||||
-rw-r--r-- | src/nautilus-navigation-window.c | 4 | ||||
-rw-r--r-- | src/nautilus-notes-sidebar.c | 447 | ||||
-rw-r--r-- | src/nautilus-notes-sidebar.h | 49 |
9 files changed, 603 insertions, 79 deletions
@@ -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 (¬es_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 |