~ubuntu-branches/ubuntu/lucid/tomboy/lucid-proposed

1.1.7 by Sebastian Dröge
Import upstream version 0.5.0
1
using System;
2
using System.IO;
3
using System.Runtime.InteropServices;
4
using System.Text;
5
using System.Xml;
6
7
using Tomboy;
8
9
public class InsertBugAction : SplitterAction
10
{
11
	BugzillaLink Tag;
12
	int Offset;
13
	string Id;
14
15
	public InsertBugAction (Gtk.TextIter start,
16
	                        string id,
17
	                        Gtk.TextBuffer buffer,
18
				BugzillaLink tag)
19
	{
20
		Tag = tag;
21
		Id = id;
22
23
		Offset = start.Offset;
24
	}
25
26
	public override void Undo (Gtk.TextBuffer buffer)
27
	{
28
		// Tag images change the offset by one, but only when deleting.
29
		Gtk.TextIter start_iter = buffer.GetIterAtOffset (Offset);
30
		Gtk.TextIter end_iter = buffer.GetIterAtOffset (Offset + chop.Length + 1);
31
		buffer.Delete (ref start_iter, ref end_iter);
32
		buffer.MoveMark (buffer.InsertMark, buffer.GetIterAtOffset (Offset));
33
		buffer.MoveMark (buffer.SelectionBound, buffer.GetIterAtOffset (Offset));
34
35
		Tag.ImageLocation = null;
36
37
		ApplySplitTags (buffer);
38
	}
39
40
	public override void Redo (Gtk.TextBuffer buffer)
41
	{
42
		RemoveSplitTags (buffer);
43
44
		Gtk.TextIter cursor = buffer.GetIterAtOffset (Offset);
45
46
		Gtk.TextTag[] tags = {Tag};
47
		buffer.InsertWithTags (ref cursor, Id, tags);
48
49
		buffer.MoveMark (buffer.SelectionBound, buffer.GetIterAtOffset (Offset));
50
		buffer.MoveMark (buffer.InsertMark,
51
		                 buffer.GetIterAtOffset (Offset + chop.Length));
52
53
	}
54
55
	public override void Merge (EditAction action)
56
	{
57
		SplitterAction splitter = action as SplitterAction;
58
		this.splitTags = splitter.SplitTags;
59
		this.chop = splitter.Chop;
60
	}
61
62
	/*
63
	 * The internal listeners will create an InsertAction when the text
64
	 * is inserted.  Since it's ugly to have the bug insertion appear
65
	 * to the user as two items in the undo stack, have this item eat
66
	 * the other one.
67
	 */
68
	public override bool CanMerge (EditAction action)
69
	{
70
		InsertAction insert = action as InsertAction;
71
		if (insert == null) {
72
			return false;
73
		}
74
75
		if (String.Compare(Id, insert.Chop.Text) == 0) {
76
			return true;
77
		}
78
79
		return false;
80
	}
81
82
	public override void Destroy ()
83
	{
84
	}
85
}
86
87
public class BugzillaLink : DynamicNoteTag
88
{
89
	Gdk.Pixbuf Icon;
90
91
	public BugzillaLink ()
92
		: base ()
93
	{
94
	}
95
96
	public override void Initialize (string element_name)
97
	{
98
		base.Initialize (element_name);
99
100
		Underline = Pango.Underline.Single;
101
		Foreground = "blue";
102
		CanActivate = true;
103
		CanGrow = true;
104
		CanSpellCheck = false;
105
		CanSplit = false;
106
	}
107
108
	public string BugUrl
109
	{
110
		get { return (string) Attributes ["uri"]; }
111
		set { Attributes ["uri"] = value; }
112
	}
113
114
	protected override bool OnActivate (NoteEditor editor, Gtk.TextIter start, Gtk.TextIter end)
115
	{
116
		if (BugUrl != string.Empty) {
117
			Logger.Log ("Opening url '{0}'...", BugUrl);
118
			Gnome.Url.Show (BugUrl);
119
		}
120
		return true;
121
	}
122
123
	public override void Read (XmlTextReader xml, bool start)
124
	{
125
		base.Read (xml, start);
126
	}
127
128
	public override Gdk.Pixbuf Image
129
	{
130
		get
131
		{
132
			if (Icon != null)
133
				return Icon;
134
135
			System.Uri uri = new System.Uri(BugUrl);
136
			if (uri == null)
137
				return null;
138
139
			string host = uri.Host;
140
			string imageDir = "~/.tomboy/BugzillaIcons/";
141
142
			string imagePath = imageDir.Replace ("~", Environment.GetEnvironmentVariable ("HOME")) + host + ".png";
143
144
			try {
145
				Icon = new Gdk.Pixbuf (imagePath);
146
			} catch (GLib.GException) {
147
				Icon = new Gdk.Pixbuf(null, "stock_bug.png");
148
			}
149
150
			return Icon;
151
		}
152
	}
153
}
154
155
public class BugzillaPlugin : NotePlugin
156
{
157
	static int last_bug;
158
159
	static BugzillaPlugin ()
160
	{
161
		last_bug = -1;
162
	}
163
164
	protected override void Initialize ()
165
	{
166
		if (!Note.TagTable.IsDynamicTagRegistered ("link:bugzilla")) {
167
			Note.TagTable.RegisterDynamicTag ("link:bugzilla", typeof (BugzillaLink));
168
		}
169
	}
170
171
	protected override void Shutdown ()
172
	{
173
	}
174
175
	protected override void OnNoteOpened ()
176
	{
177
		Window.Editor.DragDataReceived += OnDragDataReceived;
178
	}
179
180
	[DllImport("libgobject-2.0.so.0")]
181
	static extern void g_signal_stop_emission_by_name (IntPtr raw, string name);
182
183
	[GLib.ConnectBefore]
184
	void OnDragDataReceived (object sender, Gtk.DragDataReceivedArgs args)
185
	{
186
		foreach (Gdk.Atom atom in args.Context.Targets) {
187
			if (atom.Name == "text/uri-list" ||
188
			    atom.Name == "_NETSCAPE_URL") {
189
				DropUriList (args);
190
				return;
191
			}
192
		}
193
	}
194
195
	void DropUriList (Gtk.DragDataReceivedArgs args)
196
	{
197
		string uriString = Encoding.UTF8.GetString (args.SelectionData.Data);
198
199
		if (uriString.IndexOf ("show_bug.cgi?id=") != -1) {
200
			if (InsertBug (uriString)) {
201
				Gtk.Drag.Finish (args.Context, true, false, args.Time);
202
				g_signal_stop_emission_by_name(Window.Editor.Handle,
203
							       "drag_data_received");
204
			}
205
		}
206
	}
207
208
	bool InsertBug(string uri)
209
	{
210
		try {
211
			string bug = uri.Substring (uri.IndexOf ("show_bug.cgi?id=") + 16);
212
			int id = int.Parse (bug);
213
			// Debounce.  I'm not sure why this is necessary :(
214
			if (id == last_bug) {
215
				last_bug = -1;
216
				return true;
217
			}
218
			last_bug = id;
219
220
			BugzillaLink link_tag = (BugzillaLink)
221
				Note.TagTable.CreateDynamicTag ("link:bugzilla");
222
			link_tag.BugUrl = uri;
223
224
			Gtk.TextIter cursor = Buffer.GetIterAtMark (Buffer.InsertMark);
225
226
			Buffer.Undoer.AddUndoAction (new InsertBugAction (cursor, bug, Buffer, link_tag));
227
228
			Gtk.TextTag[] tags = {link_tag};
229
			Buffer.InsertWithTags (ref cursor, bug, tags);
230
			return true;
231
		} catch {
232
			return false;
233
		}
234
	}
235
}
236