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 |