SortedTodos: Todos.py

""" Functions, Constants, and utilities for WikidPad.WikiData.Todos

    Function genTodos(WikidPad, WikiWord) :
    - Opening a page called ToDo -> generates a list of ALL Todos with 'todo' in it
    - Opening a page called TodoWikidPad -> generates a list of all Todos with strings 'todo' AND 'WikidPad' in the text
    - Opening a page called TodoNEXT -> will generate a list of all Todos with strings 'todo' AND 'NEXT' in the text (including "todo.NEXT:")

    - The Todos are then sorted according to further categories if they contain any of a defined set of Tag Words like 'URGENT' , 'ASAP' , 'NEXT', etc.
    - Tag Words can be customised in the code (look for TAG LIST in todos.py)
    - Todos that have more than one Tag Word in it are displayed in the category that comes first in the TAG LIST, and not duplicated
      (although this can be easily changed)

"""


# TAGLIST:
# tags contains the a list of 'tags', special text that you can add to todo text to sort them into categories 
# .. when dynamically inserting the list of todos, they can then be sorted by category
# .. and  and displayed seperately under seperate TagHeaders.
#
# CUSTOMIZE:
# Modify this list to change the names of tags that you use, the headers you want for them, and order that the tag categories are displayed
#   tags is a List of tag items where each tag item is of the form:
#       ('TAG','TAGHEADER')
#       where TAG is the text searched for as a tag,
#       and TAGHEADER is the title displayed for that Tag Category
#   The order of items in the list is the order that they will be displayed on the dynamic page
#
# SPECIAL TAGS:
# Currently, tag '_spec.SPACER' in the tag list will add a spacer instead of a tag category
# to the dynamically generated page.
# Also, tag '_spec.NOTAGS' will indicate the position at which to include all todos with no tags.


tags = [('_spec.SPACER',''),
        ('HIGH','Tagged HIGH ! '),
        ('URGENT','Tagged URGENT ! '),
        ('_spec.SPACER',''),
        ('NEXT','Tagged Next'),
        ('_spec.SPACER',''),
        ('ASAP','Tagged ASAP'),
        ('SOON','Tagged Soon'),
        ('ThisWeek','Tagged for This Week'),
        ('_spec.SPACER',''),
        ('MEDIUM','Tagged as Medium'),
        ('WhenPossible','Tagged for When Possible'),
        ('_spec.SPACER',''),
        ('_spec.NOTAGS','UNTAGGED Todos'),
        ('_spec.SPACER',''),
        ('TimeToTime','Tagged for from time to time'),
        ('SOMEDAY','Tagged for Someday'),
        ('_spec.SPACER',''),
        ('LOW','Tagged as LOW'),
        ('VeryLow','Tagged as Very LOW') ]



def genTodos(wikidPad, wikiWord):
    """ Dynamically generates list of Todos (or other keywords) on openedWikiWord,
        .. where wikiWord is of the form ToDoSEARCHSTRING (SEARCHSTRING can be any text that you are looking for).
        Displays all todos containing 'todo' and the value of SEARCHSTRING.
        The Generated display is seperated into categories determined by the presence of Tags in the todo text.
        These Tags can be defined and ordered in the TAGS LIST above.
    """

    srchstr = wikiWord[4:]
    
    # get all todos with 'todo' and SearchString in them to seperate list to be used here:
    todosFull = wikidPad.wikiData.getTodos()
    todos = [todo for todo in todosFull if ('todo' in todo[1] and srchstr in todo[1])]

    # clean the page
    editor = wikidPad.editor
    editor.GotoLine(linesToSkip)
    editor.SetSelectionEnd(editor.GetLength())
    editor.ReplaceSelection("")

    # handle the page by displaying all keywords with srchstr:
    tagAdded = True    #used to stop two spacers in a row
    
    for tag in tags:
        wroteHeader = False   #used to make sure that header is written only once - in a non-empty category
        
        # handle special tag '_spec.SPACER' by writing SPACERs in the tag list:
        if tag[0] == '_spec.SPACER' and tagAdded:
            editor.AddText('\n' + ('-'*70) + '\n')
            tagAdded = False

        # handle special NOTAG in the tag list
        # This displays all untagged todos   :
        elif tag[0] == '_spec.NOTAGS':
            for todo in todos:
                foundTag = False
                for t in tags:
                    if t[0] in todo[1]:
                        foundTag = True
                        break
                    
                if not foundTag and todo[0] != 'DEL':
                    if not wroteHeader:
                        editor.AddText('\n++ ' + tag[1] + ' :\n')
                        wroteHeader = True
                    editor.AddText(' * '+ str(todo[1])+'\n')
                    todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                    tagAdded = True

        # handle normal Tags - write the todos for that tag:
        else:
            for todo in todos:
                if (tag[0] in todo[1]):
                    if not wroteHeader:
                        editor.AddText('\n++ ' + tag[1] + ' :\n')
                        wroteHeader = True
                    editor.AddText(' * '+ str(todo[1])+'\n')
                    todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                    tagAdded = True