[gnote] Use separate builtin app plugin for link management on create/delete/rename
- From: Aurimas Černius <aurimasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnote] Use separate builtin app plugin for link management on create/delete/rename
- Date: Mon, 8 Jun 2020 19:17:09 +0000 (UTC)
commit 5a0bf562d09f80564a69a13bacca535aa5d394bc
Author: Aurimas Černius <aurisc4 gmail com>
Date: Mon Jun 8 22:16:50 2020 +0300
Use separate builtin app plugin for link management on create/delete/rename
src/addinmanager.cpp | 29 +++++-
src/watchers.cpp | 283 +++++++++++++++++++++++++++++----------------------
src/watchers.hpp | 42 +++++---
3 files changed, 219 insertions(+), 135 deletions(-)
---
diff --git a/src/addinmanager.cpp b/src/addinmanager.cpp
index 722aba72..537dc2e5 100644
--- a/src/addinmanager.cpp
+++ b/src/addinmanager.cpp
@@ -1,7 +1,7 @@
/*
* gnote
*
- * Copyright (C) 2010-2017,2019 Aurimas Cernius
+ * Copyright (C) 2010-2017,2019-2020 Aurimas Cernius
* Copyright (C) 2009, 2010 Debarshi Ray
* Copyright (C) 2009 Hubert Figuiere
*
@@ -72,6 +72,31 @@ namespace gnote {
} \
} while(0)
+#define SETUP_APP_ADDIN(key, KEY, klass) \
+ do { \
+ if(key == KEY) { \
+ Glib::RefPtr<Gio::Settings> settings = m_preferences \
+ .get_schema_settings(Preferences::SCHEMA_GNOTE); \
+ if(settings->get_boolean(key)) { \
+ auto iter = m_app_addins.find(typeid(klass).name()); \
+ if(iter != m_app_addins.end()) { \
+ iter->second->initialize(); \
+ } \
+ else { \
+ auto addin = klass::create(); \
+ m_app_addins.insert(std::make_pair(typeid(klass).name(), addin)); \
+ addin->initialize(m_gnote, m_note_manager); \
+ } \
+ } \
+ else { \
+ auto addin = m_app_addins.find(typeid(klass).name()); \
+ if(addin != m_app_addins.end()) { \
+ addin->second->shutdown(); \
+ } \
+ } \
+ } \
+ } while(0)
+
namespace {
template <typename AddinType>
Glib::ustring get_id_for_addin(const AbstractAddin & addin, const std::map<Glib::ustring, AddinType*> &
addins)
@@ -270,6 +295,7 @@ namespace {
REGISTER_BUILTIN_NOTE_ADDIN(NoteUrlWatcher);
}
if(settings->get_boolean(Preferences::ENABLE_AUTO_LINKS)) {
+ REGISTER_APP_ADDIN(AppLinkWatcher);
REGISTER_BUILTIN_NOTE_ADDIN(NoteLinkWatcher);
}
if(settings->get_boolean(Preferences::ENABLE_WIKIWORDS)) {
@@ -573,6 +599,7 @@ namespace {
{
SETUP_NOTE_ADDIN(key, Preferences::ENABLE_URL_LINKS, NoteUrlWatcher);
SETUP_NOTE_ADDIN(key, Preferences::ENABLE_AUTO_LINKS, NoteLinkWatcher);
+ SETUP_APP_ADDIN(key, Preferences::ENABLE_AUTO_LINKS, AppLinkWatcher);
SETUP_NOTE_ADDIN(key, Preferences::ENABLE_WIKIWORDS, NoteWikiWatcher);
}
diff --git a/src/watchers.cpp b/src/watchers.cpp
index af201337..ecede1bc 100644
--- a/src/watchers.cpp
+++ b/src/watchers.cpp
@@ -1,7 +1,7 @@
/*
* gnote
*
- * Copyright (C) 2010-2015,2017,2019 Aurimas Cernius
+ * Copyright (C) 2010-2015,2017,2019-2020 Aurimas Cernius
* Copyright (C) 2010 Debarshi Ray
* Copyright (C) 2009 Hubert Figuiere
*
@@ -756,217 +756,256 @@ namespace gnote {
////////////////////////////////////////////////////////////////////////
- bool NoteLinkWatcher::s_text_event_connected = false;
-
- NoteAddin * NoteLinkWatcher::create()
+ ApplicationAddin *AppLinkWatcher::create()
{
- return new NoteLinkWatcher;
+ return new AppLinkWatcher;
}
-
- void NoteLinkWatcher::initialize ()
+ AppLinkWatcher::AppLinkWatcher()
+ : m_initialized(false)
{
- m_on_note_deleted_cid = manager().signal_note_deleted.connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_note_deleted));
- m_on_note_added_cid = manager().signal_note_added.connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_note_added));
- m_on_note_renamed_cid = manager().signal_note_renamed.connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_note_renamed));
-
- m_link_tag = get_note()->get_tag_table()->get_link_tag();
- m_broken_link_tag = get_note()->get_tag_table()->get_broken_link_tag();
}
+ void AppLinkWatcher::initialize()
+ {
+ if(m_initialized) {
+ return;
+ }
+ m_initialized = true;
+ m_on_note_deleted_cid = note_manager().signal_note_deleted.connect(
+ sigc::mem_fun(*this, &AppLinkWatcher::on_note_deleted));
+ m_on_note_added_cid = note_manager().signal_note_added.connect(
+ sigc::mem_fun(*this, &AppLinkWatcher::on_note_added));
+ m_on_note_renamed_cid = note_manager().signal_note_renamed.connect(
+ sigc::mem_fun(*this, &AppLinkWatcher::on_note_renamed));
+ }
- void NoteLinkWatcher::shutdown ()
+ void AppLinkWatcher::shutdown()
{
+ m_initialized = false;
m_on_note_deleted_cid.disconnect();
m_on_note_added_cid.disconnect();
m_on_note_renamed_cid.disconnect();
}
+ bool AppLinkWatcher::initialized()
+ {
+ return m_initialized;
+ }
- void NoteLinkWatcher::on_note_opened ()
+ void AppLinkWatcher::on_note_added(const NoteBase::Ptr & added)
{
- // NOTE: This avoid multiple link opens
- // now that notes always perform TagTable
- // sharing. This is because if the TagTable is shared,
- // we will connect to the same Tag's event source each
- // time a note is opened, and get called multiple times
- // for each button press. Fixes bug #305813.
- if (!s_text_event_connected) {
- m_link_tag->signal_activate().connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_link_tag_activated));
- m_broken_link_tag->signal_activate().connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_link_tag_activated));
- s_text_event_connected = true;
+ for(auto & note : note_manager().get_notes()) {
+ if(added == note) {
+ continue;
+ }
+
+ if(!contains_text(note, added->get_title())) {
+ continue;
+ }
+
+ // Highlight previously unlinked text
+ auto n = std::static_pointer_cast<Note>(note);
+ auto buffer = n->get_buffer();
+ highlight_in_block(note_manager(), n, buffer->begin(), buffer->end());
}
- get_buffer()->signal_insert().connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_insert_text));
- get_buffer()->signal_apply_tag().connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_apply_tag));
- get_buffer()->signal_erase().connect(
- sigc::mem_fun(*this, &NoteLinkWatcher::on_delete_range));
}
-
- bool NoteLinkWatcher::contains_text(const Glib::ustring & text)
+ void AppLinkWatcher::on_note_deleted(const NoteBase::Ptr & deleted)
{
- Glib::ustring body = get_note()->text_content().lowercase();
- Glib::ustring match = text.lowercase();
+ auto link_tag = std::static_pointer_cast<Note>(deleted)->get_tag_table()->get_link_tag();
+ auto broken_link_tag = std::static_pointer_cast<Note>(deleted)->get_tag_table()->get_broken_link_tag();
- return body.find(match) != Glib::ustring::npos;
- }
+ for(auto & note : note_manager().get_notes()) {
+ if(deleted == note) {
+ continue;
+ }
+ if(!contains_text(note, deleted->get_title())) {
+ continue;
+ }
- void NoteLinkWatcher::on_note_added(const NoteBase::Ptr & added)
- {
- if (added == get_note()) {
- return;
- }
+ Glib::ustring old_title_lower = deleted->get_title().lowercase();
+ auto buffer = std::static_pointer_cast<Note>(note)->get_buffer();
- if (!contains_text (added->get_title())) {
- return;
- }
+ // Turn all link:internal to link:broken for the deleted note.
+ utils::TextTagEnumerator enumerator(buffer, link_tag);
+ while(enumerator.move_next()) {
+ const utils::TextRange & range(enumerator.current());
+ if(enumerator.current().text().lowercase() != old_title_lower)
+ continue;
- // Highlight previously unlinked text
- highlight_in_block (get_buffer()->begin(), get_buffer()->end());
+ buffer->remove_tag(link_tag, range.start(), range.end());
+ buffer->apply_tag(broken_link_tag, range.start(), range.end());
+ }
+ }
}
- void NoteLinkWatcher::on_note_deleted(const NoteBase::Ptr & deleted)
+ void AppLinkWatcher::on_note_renamed(const NoteBase::Ptr & renamed, const Glib::ustring & /*old_title*/)
{
- if (deleted == get_note()) {
- return;
- }
+ for(auto & note : note_manager().get_notes()) {
+ if(renamed == note) {
+ continue;
+ }
- if (!contains_text (deleted->get_title())) {
- return;
+ // Highlight previously unlinked text
+ if(contains_text(note, renamed->get_title())) {
+ auto n = std::static_pointer_cast<Note>(note);
+ auto buffer = n->get_buffer();
+ highlight_note_in_block(note_manager(), n, std::static_pointer_cast<Note>(renamed), buffer->begin(),
buffer->end());
+ }
}
+ }
- Glib::ustring old_title_lower = deleted->get_title().lowercase();
+ bool AppLinkWatcher::contains_text(const NoteBase::Ptr & note, const Glib::ustring & text)
+ {
+ Glib::ustring body = std::static_pointer_cast<Note>(note)->text_content().lowercase();
+ Glib::ustring match = text.lowercase();
- // Turn all link:internal to link:broken for the deleted note.
- utils::TextTagEnumerator enumerator(get_buffer(), m_link_tag);
- while (enumerator.move_next()) {
- const utils::TextRange & range(enumerator.current());
- if (enumerator.current().text().lowercase() != old_title_lower)
- continue;
+ return body.find(match) != Glib::ustring::npos;
+ }
- get_buffer()->remove_tag (m_link_tag, range.start(), range.end());
- get_buffer()->apply_tag (m_broken_link_tag, range.start(), range.end());
+ void AppLinkWatcher::highlight_in_block(NoteManagerBase & note_manager, const Note::Ptr & note, const
Gtk::TextIter & start, const Gtk::TextIter & end)
+ {
+ TrieHit<NoteBase::WeakPtr>::ListPtr hits = note_manager.find_trie_matches(start.get_slice(end));
+ for(TrieHit<NoteBase::WeakPtr>::List::const_iterator iter = hits->begin(); iter != hits->end(); ++iter) {
+ do_highlight(note_manager, note, **iter, start, end);
}
}
-
- void NoteLinkWatcher::on_note_renamed(const NoteBase::Ptr& renamed, const Glib::ustring& /*old_title*/)
+ void AppLinkWatcher::highlight_note_in_block(NoteManagerBase & note_manager, const Note::Ptr & note, const
NoteBase::Ptr & find_note, const Gtk::TextIter & start, const Gtk::TextIter & end)
{
- if (renamed == get_note()) {
- return;
- }
+ Glib::ustring buffer_text = start.get_text(end).lowercase();
+ Glib::ustring find_title_lower = find_note->get_title().lowercase();
+ int idx = 0;
- // Highlight previously unlinked text
- if (contains_text (renamed->get_title())) {
- highlight_note_in_block(std::static_pointer_cast<Note>(renamed), get_buffer()->begin(),
get_buffer()->end());
+ while (true) {
+ idx = buffer_text.find(find_title_lower, idx);
+ if (idx < 0)
+ break;
+
+ TrieHit<NoteBase::WeakPtr> hit(idx, idx + find_title_lower.length(), find_title_lower, find_note);
+ do_highlight(note_manager, note, hit, start, end);
+
+ idx += find_title_lower.length();
}
}
-
- void NoteLinkWatcher::do_highlight(const TrieHit<NoteBase::WeakPtr> & hit,
- const Gtk::TextIter & start,
- const Gtk::TextIter &)
+ void AppLinkWatcher::do_highlight(NoteManagerBase & note_manager, const Note::Ptr & note, const
TrieHit<NoteBase::WeakPtr> & hit, const Gtk::TextIter & start, const Gtk::TextIter &)
{
// Some of these checks should be replaced with fixes to
// TitleTrie.FindMatches, probably.
- if (hit.value().expired()) {
+ if(hit.value().expired()) {
DBG_OUT("DoHighlight: null pointer error for '%s'." , hit.key().c_str());
return;
}
- if (!manager().find(hit.key())) {
- DBG_OUT ("DoHighlight: '%s' links to non-existing note." ,
- hit.key().c_str());
+ if(!note_manager.find(hit.key())) {
+ DBG_OUT("DoHighlight: '%s' links to non-existing note." , hit.key().c_str());
return;
}
NoteBase::Ptr hit_note(hit.value());
- if (hit.key().lowercase() != hit_note->get_title().lowercase()) { // == 0 if same string
- DBG_OUT ("DoHighlight: '%s' links wrongly to note '%s'." ,
- hit.key().c_str(),
- hit_note->get_title().c_str());
+ if(hit.key().lowercase() != hit_note->get_title().lowercase()) { // == 0 if same string
+ DBG_OUT("DoHighlight: '%s' links wrongly to note '%s'." , hit.key().c_str(),
hit_note->get_title().c_str());
return;
}
- if (hit_note == get_note())
+ if(hit_note == note)
return;
Gtk::TextIter title_start = start;
- title_start.forward_chars (hit.start());
+ title_start.forward_chars(hit.start());
Gtk::TextIter title_end = start;
- title_end.forward_chars (hit.end());
+ title_end.forward_chars(hit.end());
// Only link against whole words/phrases
- if ((!title_start.starts_word () && !title_start.starts_sentence ()) ||
+ if((!title_start.starts_word() && !title_start.starts_sentence()) ||
(!title_end.ends_word() && !title_end.ends_sentence())) {
return;
}
// Don't create links inside URLs
- if(get_note()->get_tag_table()->has_link_tag(title_start)) {
+ if(note->get_tag_table()->has_link_tag(title_start)) {
return;
}
- DBG_OUT ("Matching Note title '%s' at %d-%d...",
- hit.key().c_str(), hit.start(), hit.end());
+ DBG_OUT("Matching Note title '%s' at %d-%d...", hit.key().c_str(), hit.start(), hit.end());
- get_note()->get_tag_table()->foreach(
- [this, title_start, title_end](const Glib::RefPtr<Gtk::TextTag> & tag) {
- remove_link_tag(tag, title_start, title_end);
+ auto link_tag = note->get_tag_table()->get_link_tag();
+ note->get_tag_table()->foreach(
+ [note, title_start, title_end](const Glib::RefPtr<Gtk::TextTag> & tag) {
+ remove_link_tag(note, tag, title_start, title_end);
});
- get_buffer()->apply_tag (m_link_tag, title_start, title_end);
+ note->get_buffer()->apply_tag(link_tag, title_start, title_end);
}
- void NoteLinkWatcher::remove_link_tag(const Glib::RefPtr<Gtk::TextTag> & tag,
- const Gtk::TextIter & start, const Gtk::TextIter & end)
+ void AppLinkWatcher::remove_link_tag(const Note::Ptr & note, const Glib::RefPtr<Gtk::TextTag> & tag, const
Gtk::TextIter & start, const Gtk::TextIter & end)
{
NoteTag::Ptr note_tag = NoteTag::Ptr::cast_dynamic(tag);
- if (note_tag && note_tag->can_activate()) {
- get_buffer()->remove_tag(note_tag, start, end);
+ if(note_tag && note_tag->can_activate()) {
+ note->get_buffer()->remove_tag(note_tag, start, end);
}
}
- void NoteLinkWatcher::highlight_note_in_block (const NoteBase::Ptr & find_note,
- const Gtk::TextIter & start,
- const Gtk::TextIter & end)
+
+ ////////////////////////////////////////////////////////////////////////
+
+ bool NoteLinkWatcher::s_text_event_connected = false;
+
+ NoteAddin * NoteLinkWatcher::create()
{
- Glib::ustring buffer_text = start.get_text(end).lowercase();
- Glib::ustring find_title_lower = find_note->get_title().lowercase();
- int idx = 0;
+ return new NoteLinkWatcher;
+ }
- while (true) {
- idx = buffer_text.find(find_title_lower, idx);
- if (idx < 0)
- break;
- TrieHit<NoteBase::WeakPtr> hit(idx, idx + find_title_lower.length(),
- find_title_lower, find_note);
- do_highlight (hit, start, end);
+ void NoteLinkWatcher::initialize ()
+ {
+ m_link_tag = get_note()->get_tag_table()->get_link_tag();
+ m_broken_link_tag = get_note()->get_tag_table()->get_broken_link_tag();
+ }
- idx += find_title_lower.length();
- }
+ void NoteLinkWatcher::shutdown ()
+ {
}
+ void NoteLinkWatcher::on_note_opened ()
+ {
+ // NOTE: This avoid multiple link opens
+ // now that notes always perform TagTable
+ // sharing. This is because if the TagTable is shared,
+ // we will connect to the same Tag's event source each
+ // time a note is opened, and get called multiple times
+ // for each button press. Fixes bug #305813.
+ if (!s_text_event_connected) {
+ m_link_tag->signal_activate().connect(
+ sigc::mem_fun(*this, &NoteLinkWatcher::on_link_tag_activated));
+ m_broken_link_tag->signal_activate().connect(
+ sigc::mem_fun(*this, &NoteLinkWatcher::on_link_tag_activated));
+ s_text_event_connected = true;
+ }
+ get_buffer()->signal_insert().connect(
+ sigc::mem_fun(*this, &NoteLinkWatcher::on_insert_text));
+ get_buffer()->signal_apply_tag().connect(
+ sigc::mem_fun(*this, &NoteLinkWatcher::on_apply_tag));
+ get_buffer()->signal_erase().connect(
+ sigc::mem_fun(*this, &NoteLinkWatcher::on_delete_range));
+ }
+
+
+ void NoteLinkWatcher::do_highlight(const TrieHit<NoteBase::WeakPtr> & hit, const Gtk::TextIter & start,
const Gtk::TextIter & end)
+ {
+ AppLinkWatcher::do_highlight(manager(), get_note(), hit, start, end);
+ }
+
void NoteLinkWatcher::highlight_in_block(const Gtk::TextIter & start,
const Gtk::TextIter & end)
{
- TrieHit<NoteBase::WeakPtr>::ListPtr hits = manager().find_trie_matches (start.get_slice (end));
- for(TrieHit<NoteBase::WeakPtr>::List::const_iterator iter = hits->begin();
- iter != hits->end(); ++iter) {
- do_highlight (**iter, start, end);
- }
+ AppLinkWatcher::highlight_in_block(manager(), get_note(), start, end);
}
void NoteLinkWatcher::unhighlight_in_block(const Gtk::TextIter & start,
diff --git a/src/watchers.hpp b/src/watchers.hpp
index cce0a5df..b74fc3f7 100644
--- a/src/watchers.hpp
+++ b/src/watchers.hpp
@@ -1,7 +1,7 @@
/*
* gnote
*
- * Copyright (C) 2010-2015,2017,2019 Aurimas Cernius
+ * Copyright (C) 2010-2015,2017,2019-2020 Aurimas Cernius
* Copyright (C) 2009 Hubert Figuiere
*
* This program is free software: you can redistribute it and/or modify
@@ -39,6 +39,7 @@ extern "C" {
#include <gtkmm/textiter.h>
#include <gtkmm/texttag.h>
+#include "applicationaddin.hpp"
#include "noteaddin.hpp"
#include "triehit.hpp"
#include "utils.hpp"
@@ -47,6 +48,7 @@ namespace gnote {
class Preferences;
class NoteEditor;
+ class NoteManagerBase;
class NoteTag;
class NoteRenameWatcher
@@ -177,6 +179,33 @@ namespace gnote {
};
+ class AppLinkWatcher
+ : public ApplicationAddin
+ {
+ public:
+ static ApplicationAddin *create();
+ static void highlight_in_block(NoteManagerBase &, const Note::Ptr &, const Gtk::TextIter &, const
Gtk::TextIter &);
+ static void do_highlight(NoteManagerBase &, const Note::Ptr &, const TrieHit<NoteBase::WeakPtr> &, const
Gtk::TextIter & ,const Gtk::TextIter &);
+ static void remove_link_tag(const Note::Ptr & note, const Glib::RefPtr<Gtk::TextTag> & tag, const
Gtk::TextIter & start, const Gtk::TextIter & end);
+
+ AppLinkWatcher();
+ virtual void initialize() override;
+ virtual void shutdown() override;
+ virtual bool initialized() override;
+ private:
+ static bool contains_text(const NoteBase::Ptr & note, const Glib::ustring & text);
+ static void highlight_note_in_block(NoteManagerBase &, const Note::Ptr &, const NoteBase::Ptr &, const
Gtk::TextIter &, const Gtk::TextIter &);
+ void on_note_added(const NoteBase::Ptr &);
+ void on_note_deleted(const NoteBase::Ptr &);
+ void on_note_renamed(const NoteBase::Ptr&, const Glib::ustring&);
+
+ bool m_initialized;
+ sigc::connection m_on_note_deleted_cid;
+ sigc::connection m_on_note_added_cid;
+ sigc::connection m_on_note_renamed_cid;
+ };
+
+
class NoteLinkWatcher
: public NoteAddin
{
@@ -187,21 +216,13 @@ namespace gnote {
virtual void on_note_opened() override;
private:
- bool contains_text(const Glib::ustring & text);
- void on_note_added(const NoteBase::Ptr &);
- void on_note_deleted(const NoteBase::Ptr &);
- void on_note_renamed(const NoteBase::Ptr&, const Glib::ustring&);
void do_highlight(const TrieHit<NoteBase::WeakPtr> & , const Gtk::TextIter &,const Gtk::TextIter &);
- void highlight_note_in_block (const NoteBase::Ptr &, const Gtk::TextIter &,
- const Gtk::TextIter &);
void highlight_in_block(const Gtk::TextIter &,const Gtk::TextIter &);
void unhighlight_in_block(const Gtk::TextIter &,const Gtk::TextIter &);
void on_delete_range(const Gtk::TextIter &,const Gtk::TextIter &);
void on_insert_text(const Gtk::TextIter &, const Glib::ustring &, int);
void on_apply_tag(const Glib::RefPtr<Gtk::TextBuffer::Tag> & tag,
const Gtk::TextIter & start, const Gtk::TextIter &end);
- void remove_link_tag(const Glib::RefPtr<Gtk::TextTag> & tag,
- const Gtk::TextIter & start, const Gtk::TextIter & end);
bool open_or_create_link(const NoteEditor &, const Gtk::TextIter &,const Gtk::TextIter &);
bool on_link_tag_activated(const NoteEditor &,
@@ -210,9 +231,6 @@ namespace gnote {
NoteTag::Ptr m_link_tag;
NoteTag::Ptr m_broken_link_tag;
- sigc::connection m_on_note_deleted_cid;
- sigc::connection m_on_note_added_cid;
- sigc::connection m_on_note_renamed_cid;
static bool s_text_event_connected;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]