| Thread Previous • Date Previous • Date Next • Thread Next |
Hi everybody, Firstly congratulations for this great little application. It s very very useful for me. The only problem I had is that my boss ask me at the end of the week an activities report about what my team did and what is plan the upcoming week. Unfortunately GTG doen't offer this "print feature" for the moment so i developed a little plugin to do that. Basically it does : - Export the tasks into a text file opened by gedit (or any other text editor) - You have the posibility to choose to print upcoming task only or done task only or both I'm really not a developper (first time i use python and gtk) so surely the code is not very pretty, but it seems to work for me and that why i wanted to share it with you. The choice to export it to gedit is that sometimes I don t want to report ALL the tasks written to my boss so with gedit I can re-arrange it, copy/paste to thunderbird, etc... If you want to print from gedit it s better to change the default size of font to 6 or 7 depending how many tasks you have. To install it you need the version 0.1.2-dev (installed with bzr branch lp:gtg) Than in gtg/GTG/plugins : - copy printTasksToFile.gtg-plugin And in gtg/GTG/plugins/printTasksToFile - copy the 3 other files Hope it could be useful to someone else, cheers, Benoit
Attachment:
printTasksToFile.gtg-plugin
Description: Binary data
# -*- coding: utf-8 -*- # Copyright (c) 2009 - Paulo Cabido <paulo.cabido@xxxxxxxxx> # # 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/>. import sys,os sys.path.insert(0,os.getcwd()) #sys.path.insert(0,os.path.dirname(os.path.abspath(__file__))) from printTasksToFile import pluginPrintTasksToFile
Attachment:
printTasks.glade
Description: Binary data
# -*- coding: utf-8 -*-
# Copyright (c) 2009 - Paulo Cabido <paulo.cabido@xxxxxxxxx>
#
# 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/>.
import os
import sys
import datetime
import time
from xml.dom import minidom
from time import strftime
from datetime import date
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
import gtk.glade
except:
sys.exit(1)
class pluginPrintTasksToFile:
def __init__(self):
self.menu_item = gtk.MenuItem("Print a list of tasks to a text file")
self.menu_item.connect('activate', self.onTesteMenu)
self.tb_button = gtk.ToolButton(gtk.STOCK_PRINT)
self.tb_button.set_label("Print to file")
self.tb_button.connect('clicked', self.onTbButton)
self.printString = ""
def printButton_clicked(self, source=None, event=None):
self.print_to_file(self.wTree.get_widget('programToExport').get_text())
return True
# plugin engine methods
def activate(self, plugin_api):
# add a menu item to the menu bar
plugin_api.add_menu_item(self.menu_item)
# saves the separator's index to later remove it
self.separator = plugin_api.add_toolbar_item(gtk.SeparatorToolItem())
# add a item (button) to the ToolBar
plugin_api.add_toolbar_item(self.tb_button)
# Get the requester and the plugin API
self.req = plugin_api.get_requester()
self.papi = plugin_api
def onTaskOpened(self, plugin_api):
# add a item (button) to the ToolBar
self.tb_Taskbutton = gtk.ToolButton(gtk.STOCK_EXECUTE)
self.tb_Taskbutton.connect('clicked', self.onTbTaskButton, plugin_api)
plugin_api.add_task_toolbar_item(gtk.SeparatorToolItem())
plugin_api.add_task_toolbar_item(self.tb_Taskbutton)
def deactivate(self, plugin_api):
plugin_api.remove_menu_item(self.menu_item)
plugin_api.remove_toolbar_item(self.tb_button)
plugin_api.remove_toolbar_item(None, self.separator)
def loadDialog(self):
# Loading of the GUI interface
path = os.path.dirname(os.path.abspath(__file__))
glade_file = os.path.join(path, "printTasks.glade")
self.wTree = gtk.glade.XML(glade_file, "printTasks")
self.dialog = self.wTree.get_widget("printTasks")
events = { 'on_printButton_clicked': self.printButton_clicked,
'delete': self.close_dialog }
self.wTree.signal_autoconnect(events)
#self.dialog.connect("delete_event", self.close_dialog)
#self.dialog.connect("response", self.close_dialog)
self.dialog.show_all()
##################################
# Export to FILE
def print_to_file(self, programToExport):
# Initiation of the string to export/print
self.printString = ""
# Print the "header of the document"
self.printString = self.printString + "\n--- DATE OF REPORT: "+strftime("%Y-%m-%d %H:%M:%S")+" ---"
# Print the active tasks if checked
if (self.wTree.get_widget('checkActiveTasks').get_active()):
self.print_active_tasks()
# Print the done tasks if checked
if (self.wTree.get_widget('checkDoneTasks').get_active()):
self.print_done_tasks()
fileName = "tasks_report.txt"
FILE = open(fileName,"w")
FILE.writelines(self.printString)
FILE.close()
# Launch the system command to open the text file
ret = os.system(programToExport + " " + fileName + " &")
#print "\n\n ***** "+str(ret)+" ****\n\n"
#if (ret != 0):
# self.wTree.get_widget('errorLbl').set_text("Error with the command")
#else:
self.dialog.destroy()
##################################
# Print all active tasks
def print_active_tasks(self):
self.printString = self.printString + "\n\n\n\n\n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "#### #### \n"
self.printString = self.printString + "#### INCOMING TASKS #### \n"
self.printString = self.printString + "#### #### \n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "\n\n"
rootTaskNumber = 0
# Get all tasks
for tid in self.papi.get_all_tasks():
task = self.req.get_task(tid)
# We only want the "root" tasks which are active
if (not task.has_parents()) and (task.status != task.STA_DONE) :
rootTaskNumber = rootTaskNumber + 1
# Print the root task
self.print_rootTask(task)
# Print the subtasks of this root task (recursively)
self.print_subtasks(task, 0, rootTaskNumber)
##########################################
# Print of root tasks
def print_rootTask(self, task):
taskTitle = task.get_title()
# Write the TITLE of the task
self.printString = self.printString + "\n\n\n**"+ "*"*len(taskTitle) +"**\n"
self.printString = self.printString + "* "+taskTitle+" *\n"
self.printString = self.printString + "**"+ "*"*len(taskTitle) +"**"
# Create the tags string
tagsStr = "* Tags:"
for t in task.get_tags():
tagsStr = tagsStr + t.get_name()
tagsStr = tagsStr.replace("@", " ") + " "
# Create the dates string
datesStr = "* Start: "
datesStr = datesStr + self.get_start_date(task)
datesStr = datesStr + " * End: "
datesStr = datesStr + self.get_due_date(task)
datesStr = datesStr + " *"
# Write the TAGS and DATES of the task
endDelimiter = len(tagsStr+datesStr)
if (endDelimiter > (len(taskTitle)+4)):
self.printString = self.printString+"*"*(endDelimiter-len(taskTitle)-4)+"\n"
self.printString = self.printString + tagsStr + datesStr + "\n"
else:
self.printString = self.printString + "\n" + tagsStr + datesStr + "\n"
self.printString = self.printString + "*"*(endDelimiter) + "\n"
# Write TEXT DESCRIPTION of the task
self.printString = self.printString + self.clean_task_text(task)
##########################################
# Print the active subtasks
def print_subtasks(self, rootTask, taskLevel, rootTaskNumber):
numSousTache = 0
for subtask in rootTask.get_subtasks():
# Print only active tasks
if (subtask.status != subtask.STA_DONE):
numSousTache = numSousTache+1
subTaskTitle = str(rootTaskNumber) + "." + str(numSousTache) + ") " + subtask.get_title()
self.printString = self.printString + "\n" + "\t"*taskLevel + subTaskTitle
tagsStr = ""
for t in subtask.get_tags():
tagsStr = tagsStr + t.get_name()
tagsStr = tagsStr.replace("@", " ")
self.printString = self.printString + " (Tags: "+tagsStr+" | Start: "+self.get_start_date(subtask)+" | End: "+self.get_due_date(subtask)+")\n"
self.printString = self.printString + "\t"*taskLevel + "=" * len(subTaskTitle) +"\n"
text = "\t"*taskLevel + self.clean_task_text(subtask)
text = text.replace("\n", "\n"+"\t"*taskLevel)
self.printString = self.printString + text
#recursive loop
self.print_subtasks(subtask, taskLevel+1, str(str(rootTaskNumber)+"."+str(numSousTache)))
##################################
# Print all done maintasks, organized by category
def print_done_tasks(self):
self.printString = self.printString + "\n\n\n\n\n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "#### #### \n"
self.printString = self.printString + "#### DONE TASKS #### \n"
self.printString = self.printString + "#### #### \n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "################################################################# \n"
self.printString = self.printString + "\n\n"
rootTaskNumber = 0
for tid in self.req.ds.all_tasks():
task = self.req.get_task(tid)
# Print only done tasks
if not task.has_parents():
#print("\n **** Tache principale : "+task.get_title())
rootTaskNumber = rootTaskNumber + 1
self.print_done_task(task, 0, rootTaskNumber)
#self.printString = self.printString + "\n **** Tache principale : " +
self.print_done_subtasks(task, 0, rootTaskNumber)
##################################
# Print ONE done task
def print_done_task(self, task, numSousTache, rootTaskNumber):
#Test to see if the task is not too old to be displayed (7 days for default)
#self.printString = self.printString + "\n" + task.get_title() + " ---- " + str(task.status) + " **** "+ str(task.has_parents())
if (task.status == task.STA_DONE):
daysBack = self.wTree.get_widget('daysBack').get_text()
dateDone = datetime.datetime(*time.strptime(task.get_closed_date(), "%Y-%m-%d")[0:5])
dateNow = datetime.datetime.today()
if (dateDone >= (dateNow-datetime.timedelta(days=int(daysBack)))):
#numSousTache = rootTask.get_task_index(task.get_id())+1
taskTitle = "\n" + str(rootTaskNumber) + "." + str(numSousTache) + ") " + task.get_title()
self.printString = self.printString + "\n" + taskTitle
tagsStr = ""
for t in task.get_tags():
tagsStr = tagsStr + t.get_name()
tagsStr = tagsStr.replace("@", " ")
self.printString = self.printString + " (Tags: "+tagsStr+" | Done: "+task.get_closed_date()+")\n"
self.printString = self.printString + "=" * len(str(taskTitle)) +"\n"
text = self.clean_task_text(task)
self.printString = self.printString + text
##################################
# Print all done subtasks
def print_done_subtasks(self, rootTask, taskLevel, rootTaskNumber):
numSousTache = 0
for subtask in rootTask.get_subtasks():
# Print only done tasks
if (subtask.status == subtask.STA_DONE):
#numSousTache = rootTask.get_task_index(subtask.get_id())+1
numSousTache = numSousTache+1
self.print_done_task(subtask, numSousTache, rootTaskNumber)
self.print_done_subtasks(subtask, taskLevel+1, str(str(rootTaskNumber)+"."+str(numSousTache)))
##########################################
# Remove the XML tags from the task description
# Remove also the subtasks enumeration (with the little array)
def clean_task_text(self, task):
text = task.get_text()
#Clear the <content> tag
text = text.replace("<content>", "")
text = text.replace("</content>", "")
#Clear the subtask lines (with the little arraw)
text = text.replace("→", "")
while text.find("<subtask>")>=0:
firstSubTask = text.find("<subtask>")-1
endSubTask = text.find("</subtask>")+len("</subtask>")+1
text = text[0:firstSubTask] + text[endSubTask:]
#Remove the tags
while text.find("<tag>")>=0:
firstSubTask = text.find("<tag>")
endSubTask = text.find("</tag>")+len("</tag>")+1
text = text[0:firstSubTask] + text[endSubTask:]
return text
##################################
# Return the start date, if no start date return "n/a"
def get_start_date(self, subtask):
if (subtask.get_start_date()==""):
return "n/a"
else:
return subtask.get_start_date()
##################################
# Return the start date, if no start date return "n/a"
def get_due_date(self, subtask):
if (subtask.get_due_date()==""):
return "n/a"
else:
return subtask.get_due_date()
def close_dialog(self, widget, data=None):
self.dialog.destroy()
return True
# plugin features
def onTesteMenu(self, widget):
self.loadDialog()
def onTbButton(self, widget):
self.loadDialog()
def onTbTaskButton(self, widget, plugin_api):
self.loadDialog()
| Thread Previous • Date Previous • Date Next • Thread Next |