Merge lp:~michaelaquilina/synapse-project/tomboy-notes-plugin into lp:synapse-project

Proposed by Michael Aquilina on 2016-02-21
Status: Needs review
Proposed branch: lp:~michaelaquilina/synapse-project/tomboy-notes-plugin
Merge into: lp:synapse-project
Diff against target: 242 lines (+194/-0)
5 files modified
po/POTFILES.in (+1/-0)
po/POTFILES.skip (+1/-0)
src/plugins/Makefile.am (+1/-0)
src/plugins/tomboy-notes-plugin.vala (+190/-0)
src/ui/synapse-main.vala (+1/-0)
To merge this branch: bzr merge lp:~michaelaquilina/synapse-project/tomboy-notes-plugin
Reviewer Review Type Date Requested Status
Synapse core team 2016-02-21 Pending
Review via email: mp+286745@code.launchpad.net

Description of the change

This simple plugin adds support for searching and opening existing tomboy notes.

To post a comment you must log in.
Michael Aquilina (michaelaquilina) wrote :

This new plugin is a lot more simple than the pass plugin if you want to give it a quick look

Rico Tzschichholz (ricotz) wrote :

The clean up diff of "pass" should provide some hints which can be applied here too.

Also keep the files in Makefile.am in alphabetical order.
Cache values which are reused like "info.get_name ()"

637. By Michael Aquilina on 2016-03-03

Add tomboy notes plugin

Michael Aquilina (michaelaquilina) wrote :

Updated

Michael Aquilina (michaelaquilina) wrote :

any feedback on this?

Michael Aquilina (michaelaquilina) wrote :

@ricotz are we good to merge this in?

Unmerged revisions

637. By Michael Aquilina on 2016-03-03

Add tomboy notes plugin

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'po/POTFILES.in'
2--- po/POTFILES.in 2016-02-26 16:57:32 +0000
3+++ po/POTFILES.in 2016-03-03 12:14:31 +0000
4@@ -40,6 +40,7 @@
5 src/plugins/selection-plugin.vala
6 src/plugins/ssh-plugin.vala
7 src/plugins/system-management.vala
8+src/plugins/tomboy-notes-plugin.vala
9 src/plugins/xnoise-media-player-plugin.vala
10 src/plugins/zeitgeist-plugin.vala
11 src/plugins/zeitgeist-related.vala
12
13=== modified file 'po/POTFILES.skip'
14--- po/POTFILES.skip 2016-02-26 16:57:32 +0000
15+++ po/POTFILES.skip 2016-03-03 12:14:31 +0000
16@@ -41,6 +41,7 @@
17 src/plugins/selection-plugin.c
18 src/plugins/ssh-plugin.c
19 src/plugins/system-management.c
20+src/plugins/tomboy-notes-plugin.c
21 src/plugins/xnoise-media-player-plugin.c
22 src/plugins/zeitgeist-plugin.c
23 src/plugins/zeitgeist-related.c
24
25=== modified file 'src/plugins/Makefile.am'
26--- src/plugins/Makefile.am 2016-02-26 16:57:32 +0000
27+++ src/plugins/Makefile.am 2016-03-03 12:14:31 +0000
28@@ -50,6 +50,7 @@
29 rhythmbox-plugin.vala \
30 selection-plugin.vala \
31 test-slow-plugin.vala \
32+ tomboy-notes-plugin.vala \
33 xnoise-media-player-plugin.vala \
34 system-management.vala \
35 zeal-plugin.vala \
36
37=== added file 'src/plugins/tomboy-notes-plugin.vala'
38--- src/plugins/tomboy-notes-plugin.vala 1970-01-01 00:00:00 +0000
39+++ src/plugins/tomboy-notes-plugin.vala 2016-03-03 12:14:31 +0000
40@@ -0,0 +1,190 @@
41+/*
42+ * Copyright (C) 2011 Michael Aquilina <michaelaquilina@gmail.com>
43+ *
44+ * This program is free software; you can redistribute it and/or modify
45+ * it under the terms of the GNU General Public License as published by
46+ * the Free Software Foundation; either version 2 of the License, or
47+ * (at your option) any later version.
48+ *
49+ * This program is distributed in the hope that it will be useful,
50+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52+ * GNU General Public License for more details.
53+ *
54+ * You should have received a copy of the GNU General Public License
55+ * along with this program; if not, write to the Free Software
56+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
57+ *
58+ * Authored by Michael Aquilina <michaelaquilina@gmail.com>
59+ *
60+ */
61+
62+namespace Synapse
63+{
64+ public class TomboyNotesPlugin : Object, Activatable, ItemProvider
65+ {
66+ public bool enabled { get; set; default = true; }
67+
68+ private List<TomboyNoteMatch> notes;
69+ private FileMonitor tomboy_monitor;
70+
71+ public void activate ()
72+ {
73+ File note_storage = File.new_for_path (
74+ "%s/.local/share/tomboy".printf (Environment.get_home_dir ())
75+ );
76+ try {
77+ notes = list_tomboy_notes (note_storage);
78+ } catch (Error err) {
79+ warning ("%s", err.message);
80+ }
81+
82+ tomboy_monitor = note_storage.monitor (FileMonitorFlags.SEND_MOVED, null);
83+ tomboy_monitor.set_rate_limit (500);
84+ tomboy_monitor.changed.connect ( (src, dest, event) => {
85+ string src_path = src.get_path ();
86+ if (src_path.has_suffix (".note")) {
87+ message ("Reloading notes due to change in %s (%s)", src_path, event.to_string ());
88+ try {
89+ notes = list_tomboy_notes (note_storage);
90+ } catch (Error err) {
91+ warning ("Unable to list tomboy notes: %s", err.message);
92+ }
93+ }
94+ });
95+ }
96+
97+ public void deactivate ()
98+ {
99+ tomboy_monitor.cancel();
100+ }
101+
102+ static void register_plugin ()
103+ {
104+ PluginRegistry.get_default ().register_plugin (
105+ typeof (TomboyNotesPlugin),
106+ _("Tomboy Notes"),
107+ _("Search for tomboy notes."),
108+ "tomboy",
109+ register_plugin,
110+ Environment.find_program_in_path ("tomboy") != null,
111+ _("Tomboy Notes is not installed")
112+ );
113+ }
114+
115+ static construct
116+ {
117+ register_plugin ();
118+ }
119+
120+ public string? get_note_title (File note_file) throws Error {
121+ FileIOStream ios = note_file.open_readwrite ();
122+ FileInputStream @is = ios.input_stream as FileInputStream;
123+ DataInputStream dis = new DataInputStream (@is);
124+
125+ string line;
126+ while ((line = dis.read_line ()) != null) {
127+ if (Regex.match_simple ("<title>.*</title>", line)) {
128+ line = line.replace ("<title>", "");
129+ line = line.replace ("</title>", "");
130+ return line.strip ();
131+ }
132+ }
133+ dis.close();
134+ is.close();
135+ ios.close();
136+
137+ return null;
138+ }
139+
140+ private List<TomboyNoteMatch> list_tomboy_notes (File directory) throws Error {
141+ List<TomboyNoteMatch> result = new List<TomboyNoteMatch> ();
142+
143+ FileEnumerator enumerator = directory.enumerate_children (
144+ FileAttribute.STANDARD_NAME + "," +
145+ FileAttribute.STANDARD_TYPE,
146+ FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
147+ null
148+ );
149+
150+ FileInfo? info = null;
151+ while ((info = enumerator.next_file (null)) != null) {
152+ string file_name = info.get_name ();
153+ File note_file = directory.get_child (file_name);
154+
155+ if (info.get_file_type () == FileType.REGULAR && file_name.has_suffix (".note")) {
156+ try {
157+ var match = new TomboyNoteMatch(
158+ get_note_title (note_file),
159+ note_file.get_path ()
160+ );
161+ result.append (match);
162+ } catch (Error err) {
163+ warning ("%s", err.message);
164+ }
165+ }
166+ }
167+ return result;
168+ }
169+
170+ public bool handles_query (Query query)
171+ {
172+ return (QueryFlags.ACTIONS in query.query_type);
173+ }
174+
175+ public async ResultSet? search (Query query) throws SearchError
176+ {
177+ var matchers = Query.get_matchers_for_query (
178+ query.query_string, 0,
179+ RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS
180+ );
181+
182+ var results = new ResultSet ();
183+ foreach (unowned TomboyNoteMatch note in notes)
184+ {
185+ foreach (var matcher in matchers)
186+ {
187+ if (matcher.key.match (note.title)) {
188+ results.add (note, MatchScore.GOOD);
189+ break;
190+ }
191+ }
192+ }
193+
194+ // make sure this method is called before returning any results
195+ query.check_cancellable ();
196+ if (results.size > 0) {
197+ return results;
198+ } else {
199+ return null;
200+ }
201+ }
202+
203+ private class TomboyNoteMatch : ActionMatch
204+ {
205+ private string url;
206+
207+ public TomboyNoteMatch (string note_title, string url)
208+ {
209+ Object (title: note_title,
210+ description: _("Open Tomboy Note"),
211+ has_thumbnail: false,
212+ icon_name: "tomboy");
213+ this.url = url;
214+ }
215+
216+ public override void do_action ()
217+ {
218+ try
219+ {
220+ AppInfo ai = AppInfo.create_from_commandline (
221+ "tomboy --open-note %s".printf (url), "tomboy", 0
222+ );
223+ ai.launch (null, null);
224+ } catch (Error err) {
225+ warning ("%s", err.message);
226+ }
227+ }
228+ }
229+ }
230+}
231
232=== modified file 'src/ui/synapse-main.vala'
233--- src/ui/synapse-main.vala 2016-02-27 15:19:21 +0000
234+++ src/ui/synapse-main.vala 2016-03-03 12:14:31 +0000
235@@ -175,6 +175,7 @@
236 typeof (FileOpPlugin),
237 typeof (PidginPlugin),
238 typeof (ChatActions),
239+ typeof (TomboyNotesPlugin),
240 typeof (ZealPlugin),
241 #if HAVE_ZEITGEIST
242 typeof (ZeitgeistPlugin),