[gnote] Make undo work on user actions



commit 4ba934fb5f27843628371c2e46190294b12b0513
Author: Aurimas Černius <aurisc4 gmail com>
Date:   Fri Apr 22 21:13:12 2016 +0300

    Make undo work on user actions
    
    Fixes Bug 747202

 src/noteeditor.cpp |   27 ++++++++++++++++++++-
 src/noteeditor.hpp |    7 ++++-
 src/undo.cpp       |   65 ++++++++++++++++++++++++++++++++++++++++++---------
 src/undo.hpp       |   21 ++++++++++++++++-
 4 files changed, 105 insertions(+), 15 deletions(-)
---
diff --git a/src/noteeditor.cpp b/src/noteeditor.cpp
index e348a40..ba54c1d 100644
--- a/src/noteeditor.cpp
+++ b/src/noteeditor.cpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2010-2013 Aurimas Cernius
+ * Copyright (C) 2010-2013,2016 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  *
  * This program is free software: you can redistribute it and/or modify
@@ -24,6 +24,7 @@
 #include "notebuffer.hpp"
 #include "noteeditor.hpp"
 #include "preferences.hpp"
+#include "undo.hpp"
 #include "utils.hpp"
 #include "debug.hpp"
 #include "sharp/string.hpp"
@@ -68,6 +69,9 @@ namespace gnote {
 
     signal_key_press_event().connect(sigc::mem_fun(*this, &NoteEditor::key_pressed), false);
     signal_button_press_event().connect(sigc::mem_fun(*this, &NoteEditor::button_pressed), false);
+
+    g_signal_connect(gobj(), "paste-clipboard", G_CALLBACK(paste_started), this);
+    g_signal_connect_after(gobj(), "paste-clipboard", G_CALLBACK(paste_ended), this);
   }
 
 
@@ -274,6 +278,27 @@ namespace gnote {
     return false;
   }
 
+  void NoteEditor::paste_started(GtkTextView*, NoteEditor *_this)
+  {
+    _this->on_paste_start();
+  }
+
+  void NoteEditor::paste_ended(GtkTextView*, NoteEditor *_this)
+  {
+    _this->on_paste_end();
+  }
+
+  void NoteEditor::on_paste_start()
+  {
+    auto buffer = NoteBuffer::Ptr::cast_static(get_buffer());
+    buffer->undoer().add_undo_action(new EditActionGroup(true));
+  }
+
+  void NoteEditor::on_paste_end()
+  {
+    auto buffer = NoteBuffer::Ptr::cast_static(get_buffer());
+    buffer->undoer().add_undo_action(new EditActionGroup(false));
+  }
 
 
 }
diff --git a/src/noteeditor.hpp b/src/noteeditor.hpp
index c58f7bf..46a2825 100644
--- a/src/noteeditor.hpp
+++ b/src/noteeditor.hpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2011,2013 Aurimas Cernius
+ * Copyright (C) 2011,2013,2016 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  *
  * This program is free software: you can redistribute it and/or modify
@@ -51,12 +51,17 @@ protected:
                                      guint info,  guint time) override;
 
 private:
+  static void paste_started(GtkTextView*, NoteEditor *_this);
+  static void paste_ended(GtkTextView*, NoteEditor *_this);
+
   Pango::FontDescription get_gnome_document_font_description();
   void on_font_setting_changed (const Glib::ustring & key);
   void update_custom_font_setting();
   void modify_font_from_string (const std::string & fontString);
   bool key_pressed (GdkEventKey * ev);
   bool button_pressed (GdkEventButton * ev);
+  void on_paste_start();
+  void on_paste_end();
 };
 
 
diff --git a/src/undo.cpp b/src/undo.cpp
index da410ff..c5f72e0 100644
--- a/src/undo.cpp
+++ b/src/undo.cpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2010 Aurimas Cernius
+ * Copyright (C) 2010,2016 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  *
  * This program is free software: you can redistribute it and/or modify
@@ -28,6 +28,32 @@
 
 namespace gnote {
 
+  EditActionGroup::EditActionGroup(bool start)
+    : m_start(start)
+  {
+  }
+
+  void EditActionGroup::undo(Gtk::TextBuffer*)
+  {
+  }
+
+  void EditActionGroup::redo(Gtk::TextBuffer*)
+  {
+  }
+
+  void EditActionGroup::merge(EditAction*)
+  {
+  }
+
+  bool EditActionGroup::can_merge(const EditAction*) const
+  {
+    return false;
+  }
+
+  void EditActionGroup::destroy()
+  {
+  }
+
   ChopBuffer::ChopBuffer(const Glib::RefPtr<Gtk::TextTagTable> & table)
     : Gtk::TextBuffer(table)
   {
@@ -602,19 +628,23 @@ namespace gnote {
                               std::stack<EditAction *> & push_to, bool is_undo)
   {
     if (!pop_from.empty()) {
-      EditAction *action = pop_from.top ();
-      pop_from.pop();
+      bool loop = false;
+      freeze_undo();
+      do {
+        EditAction *action = pop_from.top();
+        pop_from.pop();
+        EditActionGroup *group = dynamic_cast<EditActionGroup*>(action);
+        if(group) {
+          // in case of undo group-end is at the top, for redo it's the opposite
+          loop = is_undo ? !group->is_start() : group->is_start();
+        }
 
-      freeze_undo ();
-      if (is_undo) {
-        action->undo (m_buffer);
-      }
-      else {
-        action->redo (m_buffer);
-      }
-      thaw_undo ();
+        undo_redo_action(*action, is_undo);
+
+        push_to.push(action);
 
-      push_to.push (action);
+      } while(loop);
+      thaw_undo();
 
       // Lock merges until a new undoable event comes in...
       m_try_merge = false;
@@ -625,6 +655,17 @@ namespace gnote {
     }
   }
 
+
+  void UndoManager::undo_redo_action(EditAction & action, bool is_undo)
+  {
+    if(is_undo) {
+      action.undo(m_buffer);
+    }
+    else {
+      action.redo(m_buffer);
+    }
+  }
+
   
   void UndoManager::clear_action_stack(std::stack<EditAction *> & stack)
   {
diff --git a/src/undo.hpp b/src/undo.hpp
index b097e1c..59650e0 100644
--- a/src/undo.hpp
+++ b/src/undo.hpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2013 Aurimas Cernius
+ * Copyright (C) 2013,2016 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  *
  * This program is free software: you can redistribute it and/or modify
@@ -52,6 +52,24 @@ public:
   virtual void destroy () = 0;
 };
 
+class EditActionGroup
+  : public EditAction
+{
+public:
+  EditActionGroup(bool start);
+  virtual void undo(Gtk::TextBuffer *buffer) override;
+  virtual void redo(Gtk::TextBuffer *buffer) override;
+  virtual void merge(EditAction *action) override;
+  virtual bool can_merge(const EditAction *action) const override;
+  virtual void destroy() override;
+  bool is_start() const
+    {
+      return m_start;
+    }
+private:
+  bool m_start;
+};
+
 class ChopBuffer
   : public Gtk::TextBuffer
 {
@@ -237,6 +255,7 @@ public:
     }
 
   void undo_redo(std::stack<EditAction *> &, std::stack<EditAction *> &, bool);
+  void undo_redo_action(EditAction & action, bool);
   void clear_undo_history();
   void add_undo_action(EditAction * action);
 


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