// Shows all tasks and actions grepped from all notes in a single list // (C) 2007 Eduard Weissmann // GNU GPL using System; using System.Collections; using Mono.Unix; using Gtk; using Tomboy; using System.IO; using System.Xml; using System.Text.RegularExpressions; [PluginInfo( "Tasks List", "0.2", "Eduard Weissmann", "Show all tasks and action items grepped from all notes in a single list", WebSite = "http://www.ediweissmann.com/taskslist/", PreferencesWidget = typeof (TasksListPluginPreferences) )] public class TaskListPlugin : NotePlugin { public const string TASK_KEYWORD = "/apps/tomboy/taskslistplugin_task_keyword"; public const string TASK_KEYWORD_DEFAULT = "TODO:"; public static string taskKeyword = TASK_KEYWORD_DEFAULT; public const string NOTE_TITLE = "/apps/tomboy/taskslistplugin_note_title"; public const string NOTE_TITLE_DEFAULT = "*** Tasks list"; public static string tasksListNoteTitle = NOTE_TITLE_DEFAULT; public static bool initialized = false; private static Regex stripTags = new Regex("<[^>]*>", RegexOptions.Compiled | RegexOptions.CultureInvariant); public TaskListPlugin () : base () { } public static void LoadSettings () { taskKeyword = (string)Preferences.Get(TASK_KEYWORD); tasksListNoteTitle = (string)Preferences.Get(NOTE_TITLE); if(taskKeyword == null){ taskKeyword = TASK_KEYWORD_DEFAULT; } if(tasksListNoteTitle == null){ tasksListNoteTitle = NOTE_TITLE_DEFAULT; } } public static void SaveSettings () { Preferences.Set(TASK_KEYWORD, taskKeyword); Preferences.Set(NOTE_TITLE, tasksListNoteTitle); } public bool TasksListNoteExists () { foreach (Note note in Manager.Notes) { if (note.Title.Equals (tasksListNoteTitle)){ return true; } } return false; } public Task[] SearchNotesForTasks () { ArrayList tasks = new ArrayList(); foreach (Note note in Manager.Notes) { if(! note.Title.Equals (tasksListNoteTitle)) tasks.AddRange(CheckNoteForTasks(note, taskKeyword, true)); } return (Task[])tasks.ToArray(typeof(Task)); } public ArrayList CheckNoteForTasks (Note note, string taskKeyword, bool match_case) { // Logger.Log ("Checking note {0} for tasks",note.Title); string[] end_delimiters = {"\n",""}; ArrayList tasks = new ArrayList(); string encoded_word = XmlEncoder.Encode (taskKeyword); string note_text = note.XmlContent; if (!match_case) note_text = note_text.ToLower (); int index = note_text.IndexOf (encoded_word); while (index > -1){ Task t = new Task (); string taskTitle = note_text.Substring (index+encoded_word.Length); int endIndex = -1; foreach( string delim in end_delimiters ){ if(endIndex > 0) break; else endIndex = taskTitle.IndexOf(delim); } if(endIndex > 0){ taskTitle = taskTitle.Substring (0, endIndex); taskTitle = stripTags.Replace(taskTitle, String.Empty); t.title = taskTitle; t.note = note; tasks.Add(t); // Logger.Log ("Found task \"{0}\" in note \"{1}\"",t.title, t.note.Title); note_text = note_text.Substring (index+encoded_word.Length+endIndex); index = note_text.IndexOf (encoded_word); } else { break; } } return tasks; } public string CreateTasksListNoteContent() { // Logger.Log ("Creating tasks list note content."); const string base_xml = "" + "{0}\n\n" + "{1}\n\n" + "\n"+ "{2}" + ""; string tasks_xml = ""; Task[] tasks = SearchNotesForTasks (); if(tasks.Length == 0) tasks_xml = Catalog.GetString ("No tasks found"); else { foreach (Task t in tasks){ tasks_xml += XmlEncoder.Encode(taskKeyword)+" "+t.title+ " ("+t.note.Title+")"; tasks_xml += "\n"; } } string final_xml = string.Format (base_xml, XmlEncoder.Encode (tasksListNoteTitle), tasks_xml, XmlEncoder.Encode (Catalog.GetString ("Don't edit this note. The contents is generated each time note is opened."))); return final_xml; } public Note CreateTasksListNote () { // Logger.Log ("Creating tasks list note."); string final_xml = CreateTasksListNoteContent(); Note tasksListNote = null; try { tasksListNote = Manager.Create (tasksListNoteTitle, final_xml); } catch (Exception e) { // Logger.Error ("TasksListPLugin could not create \"{0}\": {1}", tasksListNoteTitle, e.Message); tasksListNote = null; } return tasksListNote; } protected override void Initialize () { if(! initialized){ initialized = true; LoadSettings (); if(! TasksListNoteExists ()) CreateTasksListNote (); } } protected override void Shutdown () { } protected override void OnNoteOpened () { if(this.Note.Title.Equals (tasksListNoteTitle)){ this.Note.Window.WindowStateEvent += new WindowStateEventHandler(OnWindowStateEvent); } } protected void OnWindowStateEvent (object sender, Gtk.WindowStateEventArgs args) { if (!this.Note.Window.Visible){ // Logger.Log ("Not visible, return"); return; } bool is_iconified = (args.Event.NewWindowState == Gdk.WindowState.Iconified); bool is_withdrawn = (args.Event.NewWindowState == Gdk.WindowState.Withdrawn); bool window_visible = (!is_iconified && !is_withdrawn); if(window_visible){ // Logger.Log ("Window visible, generating content for note"); this.Note.XmlContent = CreateTasksListNoteContent (); } } } class TasksListPluginPreferences : Gtk.VBox { Gtk.Label example; Gtk.Entry keywordEntry; Gtk.HBox box; public TasksListPluginPreferences () : base (false, 12) { Gtk.Label label = new Gtk.Label ( Catalog.GetString ( "Keyword marking tasks:")); label.UseMarkup = true; label.Xalign = 0; label.Wrap = false; label.Show (); PackStart (label); keywordEntry = new Gtk.Entry(TaskListPlugin.taskKeyword); keywordEntry.Show(); keywordEntry.Changed += new EventHandler (OnKeywordEntryChanged); keywordEntry.FocusOutEvent += OnEditingDone; PackStart (keywordEntry); Gtk.Label dummy = new Gtk.Label(""+Catalog.GetString("Example:")+" "); dummy.UseMarkup = true; dummy.Xalign = 0; example = new Gtk.Label (XmlEncoder.Encode (keywordEntry.Text)+" "+Catalog.GetString("This is a task")); example.UseMarkup = true; example.Xalign = 0; example.Wrap = true; example.Justify = Gtk.Justification.Left; example.Show (); box = new Gtk.HBox(); box.PackStart(dummy, false, false, 0); box.PackStart(example, false, false, 0); PackStart (box, false, false, 0); ShowAll (); } void OnKeywordEntryChanged(object sender, System.EventArgs args){ // TODO: why this doesn't work with markup? example.Text = keywordEntry.Text.Trim()+" "+Catalog.GetString("This is a task"); TaskListPlugin.taskKeyword = keywordEntry.Text.Trim(); } void OnEditingDone(object sender, System.EventArgs args){ TaskListPlugin.SaveSettings(); } } public class Task { public Note note; public string title; }