[almanah] core: Undo/redo feature



commit e54e3b8aa0979f123b159c6d854fff66b9a3f1cc
Author: Andreas Gruhler <andreas gruhler uzh ch>
Date:   Mon Aug 22 15:27:25 2016 +0100

    core: Undo/redo feature
    
    Replaces GtkTextBuffer by GtkSourceBuffer (and GtkTextView by
    GtkSourceView) and implements undo/redo functionality. Undo/redo
    is mapped to Ctrl+Z and Ctrl+Shift+Z keyboard shortcuts.
    
    This adds a dependency on gtksourceview-3.0.
    
    https://github.com/alvaropg/almanah/pull/1

 configure.ac      |    1 +
 src/application.c |    2 +
 src/main-window.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++------
 src/ui/almanah.ui |    2 +-
 4 files changed, 54 insertions(+), 8 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 88df7f3..da74de1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,7 @@ PKG_CHECK_MODULES(STANDARD, glib-2.0
                             gmodule-2.0
                             gthread-2.0
                             gio-2.0 >= $GIO_MIN_VERSION
+                            gtksourceview-3.0
                             sqlite3
                             cairo
                             atk
diff --git a/src/application.c b/src/application.c
index b350475..e7ab9df 100644
--- a/src/application.c
+++ b/src/application.c
@@ -292,6 +292,8 @@ startup (GApplication *application)
        add_accelerator(GTK_APPLICATION (application), "win.hyperlink", "<Primary>H");
        add_accelerator(GTK_APPLICATION (application), "win.insert-time", "<Primary>T");
        add_accelerator(GTK_APPLICATION (application), "win.important", "<Primary>M");
+       add_accelerator(GTK_APPLICATION (application), "win.undo", "<Primary>Z");
+       add_accelerator(GTK_APPLICATION (application), "win.redo", "<Primary><Shift>Z");
 }
 
 /* Nullify our pointer to the main window when it gets destroyed (e.g. when we quit) so that we don't then 
try
diff --git a/src/main-window.c b/src/main-window.c
index 925826b..62b0f2a 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -25,6 +25,7 @@
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
+#include <gtksourceview/gtksource.h>
 #ifdef ENABLE_SPELL_CHECKING
 #include <gtkspell/gtkspell.h>
 #endif /* ENABLE_SPELL_CHECKING */
@@ -60,8 +61,8 @@ static void save_window_state (AlmanahMainWindow *self);
 static void restore_window_state (AlmanahMainWindow *self);
 static gboolean mw_delete_event_cb (GtkWindow *window, gpointer user_data);
 static void mw_entry_buffer_cursor_position_cb (GObject *object, GParamSpec *pspec, AlmanahMainWindow 
*main_window);
-static void mw_entry_buffer_insert_text_cb (GtkTextBuffer *text_buffer, GtkTextIter *start, gchar *text, 
gint len, AlmanahMainWindow *main_window);
-static void mw_entry_buffer_insert_text_after_cb (GtkTextBuffer *text_buffer, GtkTextIter *start, gchar 
*text, gint len, AlmanahMainWindow *main_window);
+static void mw_entry_buffer_insert_text_cb (GtkSourceBuffer *text_buffer, GtkTextIter *start, gchar *text, 
gint len, AlmanahMainWindow *main_window);
+static void mw_entry_buffer_insert_text_after_cb (GtkSourceBuffer *text_buffer, GtkTextIter *start, gchar 
*text, gint len, AlmanahMainWindow *main_window);
 static void mw_entry_buffer_has_selection_cb (GObject *object, GParamSpec *pspec, AlmanahMainWindow 
*main_window);
 
 static void mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryType type_id, 
AlmanahMainWindow *main_window);
@@ -84,6 +85,10 @@ void mw_bold_toggle_cb            (GSimpleAction *action, GVariant *parameter, g
 void mw_italic_toggle_cb          (GSimpleAction *action, GVariant *parameter, gpointer user_data);
 void mw_underline_toggle_cb       (GSimpleAction *action, GVariant *parameter, gpointer user_data);
 void mw_hyperlink_toggle_cb       (GSimpleAction *action, GVariant *parameter, gpointer user_data);
+static void mw_undo_cb            (GSimpleAction *action, GVariant *parameter, gpointer user_data);
+static void mw_redo_cb            (GSimpleAction *action, GVariant *parameter, gpointer user_data);
+
+static void mw_source_buffer_notify_can_undo_redo_cb (GObject *obj, GParamSpec *pspec, gpointer user_data);
 
 void mw_events_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn 
*column, AlmanahMainWindow *main_window);
 
@@ -94,8 +99,8 @@ void mw_desktop_interface_settings_changed (GSettings *settings, const gchar *ke
 
 struct _AlmanahMainWindowPrivate {
        GtkWidget *header_bar;
-       GtkTextView *entry_view;
-       GtkTextBuffer *entry_buffer;
+       GtkSourceView *entry_view;
+       GtkSourceBuffer *entry_buffer;
        AlmanahEntryTagsArea *entry_tags_area;
        AlmanahCalendarButton *calendar_button;
        GtkListStore *event_store;
@@ -137,7 +142,9 @@ static GActionEntry win_entries[] = {
        { "bold", NULL, NULL, "false", mw_bold_toggle_cb },
        { "italic", NULL, NULL, "false", mw_italic_toggle_cb },
        { "underline", NULL, NULL, "false", mw_underline_toggle_cb },
-       { "hyperlink", NULL, NULL, "false", mw_hyperlink_toggle_cb }
+       { "hyperlink", NULL, NULL, "false", mw_hyperlink_toggle_cb },
+       { "undo", mw_undo_cb },
+       { "redo", mw_redo_cb }
 };
 
 static void
@@ -288,6 +295,10 @@ almanah_main_window_new (AlmanahApplication *application)
        /* Similarly, make sure we're notified when there's a selection so we can change the status of 
cut/copy/paste actions */
        g_signal_connect (priv->entry_buffer, "notify::has-selection", G_CALLBACK 
(mw_entry_buffer_has_selection_cb), main_window);
 
+       /* Update the undo/redo actions when the undo/redo stack changes. */
+       g_signal_connect (priv->entry_buffer, "notify::can-undo", G_CALLBACK 
(mw_source_buffer_notify_can_undo_redo_cb), main_window);
+       g_signal_connect (priv->entry_buffer, "notify::can-redo", G_CALLBACK 
(mw_source_buffer_notify_can_undo_redo_cb), main_window);
+
        /* Set the storage to the tags area */
        storage_manager = almanah_application_dup_storage_manager (application);
        almanah_entry_tags_area_set_storage_manager (priv->entry_tags_area, storage_manager);
@@ -759,7 +770,7 @@ mw_entry_buffer_cursor_position_cb (__attribute__ ((unused)) GObject *object, __
 }
 
 static void
-mw_entry_buffer_insert_text_cb (__attribute__ ((unused)) GtkTextBuffer *text_buffer,
+mw_entry_buffer_insert_text_cb (__attribute__ ((unused)) GtkSourceBuffer *text_buffer,
                                __attribute__ ((unused)) GtkTextIter *start,
                                __attribute__ ((unused)) gchar *text,
                                __attribute__ ((unused)) gint len,
@@ -781,7 +792,7 @@ mw_entry_buffer_insert_text_cb (__attribute__ ((unused)) GtkTextBuffer *text_buf
 }
 
 static void
-mw_entry_buffer_insert_text_after_cb (GtkTextBuffer *text_buffer, GtkTextIter *end, __attribute__ ((unused)) 
gchar *text, gint len, AlmanahMainWindow *main_window)
+mw_entry_buffer_insert_text_after_cb (GtkSourceBuffer *text_buffer, GtkTextIter *end, __attribute__ 
((unused)) gchar *text, gint len, AlmanahMainWindow *main_window)
 {
        GtkTextIter start;
        AlmanahMainWindowPrivate *priv = main_window->priv;
@@ -1096,6 +1107,38 @@ mw_hyperlink_toggle_cb (GSimpleAction *action, GVariant *parameter, gpointer use
 }
 
 static void
+mw_undo_cb (GSimpleAction *action, GVariant *parameter, gpointer user_data)
+{
+       AlmanahMainWindow *main_window = ALMANAH_MAIN_WINDOW (user_data);
+
+       gtk_source_buffer_undo (main_window->priv->entry_buffer);
+}
+
+static void
+mw_redo_cb (GSimpleAction *action, GVariant *parameter, gpointer user_data)
+{
+       AlmanahMainWindow *main_window = ALMANAH_MAIN_WINDOW (user_data);
+
+       gtk_source_buffer_redo (main_window->priv->entry_buffer);
+}
+
+static void
+mw_source_buffer_notify_can_undo_redo_cb (GObject *obj, GParamSpec *pspec, gpointer user_data)
+{
+       AlmanahMainWindow *main_window = ALMANAH_MAIN_WINDOW (user_data);
+       GAction *action;
+
+       /* Update whether the undo and redo actions are enabled. */
+       action = g_action_map_lookup_action (G_ACTION_MAP (main_window), "undo");
+       g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
+                                    gtk_source_buffer_can_undo (main_window->priv->entry_buffer));
+
+       action = g_action_map_lookup_action (G_ACTION_MAP (main_window), "redo");
+       g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
+                                    gtk_source_buffer_can_redo (main_window->priv->entry_buffer));
+}
+
+static void
 clear_factory_events (AlmanahMainWindow *self, AlmanahEventFactoryType type_id)
 {
        GtkTreeIter iter;
diff --git a/src/ui/almanah.ui b/src/ui/almanah.ui
index afdaa42..d5d5eb4 100644
--- a/src/ui/almanah.ui
+++ b/src/ui/almanah.ui
@@ -116,7 +116,7 @@
                                                                        <class name="view"/>
                                                                </style>
                                                                <child>
-                                                                       <object class="GtkTextView" 
id="almanah_mw_entry_view">
+                                                                       <object class="GtkSourceView" 
id="almanah_mw_entry_view">
                                                                                <property 
name="width-request">500</property>
                                                                                <property 
name="can-focus">True</property>
                                                                                <property 
name="has-focus">True</property>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]