← Back to team overview

gtg-user team mailing list archive

My GTD-style setup for GTG + KDE

 

Hey Folks!

Getting things done is a philosophy for productivity management which I suppose inspired the name for Getting things Gnome. I have been working with GTD for years (in numerous different software settings) and recently decided to give GTG a shot. Despite the name similarity, I found it far from obvious to use GTG in my implementation of a GTD workflow. It took me quite some effort in terms of configuration and writing scripts to figure out a good way to use GTG to implement my GTD-style working habits. Here's an attempt to make that easier for the next guy.
My description is based on GTG 0.2.4 and Kubuntu 9.10.

* Contexts

"Context" in GTD is a way to classify a project or action such that you are only confronted with those projects and actions which you can actually do in the current location or situation. My first obstacle in using GTG was the implementation of context. Although there is no "context" concept in GTG, the functionality can be achieved with the concept of tags. For instance, the tags corresponding to context are in my case @office, @internet, @home, @city, @anywhere. Note that if you right click on a tag in the tag list you can toggle "Visible in workview" such that you can untoggle the contexts which are not active at the moment.

* The inbox

The "inbox" is an important concept in GTD. That's where you throw things which you don't want to forget but also do not want to "process" at this moment. In GTG, my inbox are those tasks without any tags. In this way I can quickly add stuff to the inbox with the quick-add text field, and I can see the inbox by selecting "Tasks with no tag" in the tags sidebar. (More on quickly adding to stuff to inbox below.)

* Seamless access to todo-lists

David Allen stresses the importance of having an effortless system. If it takes me effort to access a todo-list, i.e., GTG in this case, I often find myself resisting using it. I want to be to able to access GTG quickly and quickly jump back and forth between a screen with GTG and a screen where I am currently working. This can be achieved with virtual desktops and global keyboard shortcuts. I set it up in KDE as follows.
 1) Make sure you have the "pager" widget on your panel.
2) Right click on the pager, select "Configure desktops.." and set "Number of desktops" equal to two 3) Start System settings -> Keyboard and Mouse -> Global keyboard shortcuts
 4) Select KDE component "Kwin".
5) Scroll down and click "Switch to desktop 1". Click on "None" and press "F11" on your keyboard 6) Repeat step 5 with "Switch to desktop 2" and "F12" and apply the settings.

In this way you can switch between desktop 1 and 2 using the keys F11 and F12. I start GTG in desktop 2 and do work on desktop 1.

* Effortless adding to inbox

In order to really use the inbox without thinking about it, I personally have to able to add stuff to it with just one keyboard combination. This can also be achieved with KDE:

  Add Action input:
    * Go to System Settings > Input Actions.
* In the selection area, do right click > New Global Shortcut > Command/URL. * Go to the Action tab and enter /usr/bin/gtg_new_task * Go to the Trigger tab and click on a keyboard shortcut. I use the "Home" key on my keyboard With the above procedure, you can at any point in time get a GTG new task window. I press "Home", write new inbox entry, and press esc, in order to add a new entry.

Since I also want the new task window to be centered (and in focus) I also configure special window behavior: * Make sure you have a gtg new task window open
    * Go to "Configure window behavior -> Window-specific"
* Click New -> Detect window properties and click on the new task window
    * In the Geometry tab: set Placement -> Force -> centered
    * In the preference tab: set Keep above -> Force -> Check
    * In the preference tab: set Accept focus -> Force -> Check
* In the Workarounds tab: set Focus stealing prevention -> Force -> None (!)

* Weekly review adding script:

As a part of my weekly review I have a number of actions (subtasks) and a project (task) which are things I want add, e.g., "Do sports 1", "Do sports 2", "Water plants (wednesday)", "Do stretching exercise 1", "Do stretching exercise 2", etc. This is quite long list in my case.

Although there is a possibility to write a script which adds a number of tasks at once (using the command gtg_new_task), it was not sufficient for my purposes. I want my weekly tasks to be subtasks of "Weekly" and I want them to be tagged "weekly".

I achieved that with minor programming tricks. The attached python script, which is a modification of gtg_new_task, takes all the lines and in a specified file and adds them in as subtasks to a new task "Weekly" and tagged as Weekly. Use it with the command

  ./add_wr_tasks weekly2.txt

This is the first time I do anything in python, so a lot of stuff is hardcoded. It is also very far from being ready to be included in GTG and could be (AFAIU) replaced in version 0.3 by the import script or something similar.

* Some unresolved issues and inconveniences:

Processing the inbox requires that I "move" tasks which do not have tag to become a subtask of another task (in GTD terminology a "project"). The only way I know how to this is in GTG is with drag and drop. This requires me to switch to "All tasks", find the unprocessed inbox entry and drag it to the correct task. It would be nice if there would be a way to easier do that.

I have also not found a way to implement a "Someday maybe list". Currently, I have a tag and a task called "someday maybe" where I put those entries. In this implementation, the distinction between a "someday maybe entry" and an "action" (or project) is not quite sufficient for my workflow. Someday maybe entries are things which I don't want see except during the weekly review. With the current implementation, they pop up once in a while when I'm just editing my lists, stealing a bit of my attention. This is more serious than it sounds since my someday maybe list consists of many "heavy" entries.

The same holds for a "reference list".

Does anyone have a better "someday maybe" or "reference" solution?

Best regards,

Elias


PS Thanks to all the GTG-developers. The GTG implementation seems very clean. It was (with very little effort) possible to adapt the python+dbus script without previously having worked with either python or dbus.

#!/usr/bin/python
# export PYTHONPATH=/usr/share/gtg/
# -*- coding:utf-8 -*-

# -----------------------------------------------------------------------------
# Getting Things Gnome! - A personal organizer for the GNOME desktop
# Copyright (c) 2008,2009 Lionel Dricot & Bertrand Rousseau
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------

"""
This script creates tasks specfied in the first parameter. GTG should be running
"""

import re
import sys
sys.path.append('/usr/share/gtg'); # Hardcoded!
import dbus
import cgi
import getopt
import datetime


from GTG import _


def parse_line(txt):
    now = datetime.datetime.now()
    return now.strftime(txt)
    

def my_add_task(filename, body) :
    #We will connect on the session bus
    bus = dbus.SessionBus()
    liste = bus.list_names()
    busname = "org.GTG"
    remote_object = bus.get_object(busname,"/org/GTG")
    timi = dbus.Interface(remote_object,dbus_interface="org.GTG")

    # Time to do the adding of subtasks

    f = open(filename, 'r')
    ttv=[]
    main_name="Weekly"
    for line in f:
        subject_regex = re.compile("^>\s*(.*)$", re.M | re.I)
        txt=line
        if subject_regex.search(line):
            txt=subject_regex.findall(line)[0]
            txt=parse_line(txt)
            print "Adding task:",txt
            tt=timi.new_task('Active', txt, '','','',['@Weekly'],'', '')
            ttv.append(tt.get('id'))
        else:
            # Save the name of the main task
            subject_regex = re.compile("^\s*(.*)$", re.M | re.I)
            txt=subject_regex.findall(line)[0]
            if (len(txt)>0):
                txt=parse_line(txt)
                main_name=txt
                print "Setting main task:",txt

    # Add main tas
    wr=timi.new_task('Active', main_name, '','','',['@Weekly'],'', ttv)


    

def usage():
    print _("Usage: %s  [-h | --help] filename") % sys.argv[0]
        
if __name__ == '__main__':
    interactive = False
    #Command line options handling
    try:
        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        usage()
        sys.exit(2)
    for o, a in opts:
        if o in ("-i", "--interactive"):
            interactive = True
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        else:
            assert False, "unhandled option"

    title = " ".join(args)
    if interactive:
        optlist, args = getopt.getopt(args, 'i::')
        body = sys.stdin.read()
        subject_regex = re.compile("^Subject: (.*)$", re.M | re.I)
        if subject_regex.search(body):
            subject = subject_regex.findall(body)[0]
            title = title + ": " + subject
    else:
        body = ""
    my_add_task(title, cgi.escape(body))


Weekly activities (added %b %d)
> Do Sports 1
> Do Sports 2
> Water the plants
> Clean the kitchen
> Read "the voice"

Follow ups