gtg team mailing list archive
-
gtg team
-
Mailing list archive
-
Message #03680
[Merge] lp:~tomkadwill/gtg/untouched-plugin into lp:gtg
Tom Kadwill has proposed merging lp:~tomkadwill/gtg/untouched-plugin into lp:gtg.
Requested reviews:
Gtg developers (gtg)
For more details, see:
https://code.launchpad.net/~tomkadwill/gtg/untouched-plugin/+merge/132986
Added untouched-tasks plugin in response to bug #320589
--
https://code.launchpad.net/~tomkadwill/gtg/untouched-plugin/+merge/132986
Your team Gtg developers is requested to review the proposed merge of lp:~tomkadwill/gtg/untouched-plugin into lp:gtg.
=== modified file 'AUTHORS'
--- AUTHORS 2012-08-12 23:01:10 +0000
+++ AUTHORS 2012-11-05 22:34:19 +0000
@@ -109,3 +109,4 @@
* Abhiram <abhiram.ampabathina@xxxxxxxxx>
* Alan Gomes <alangalvino@xxxxxxxxx>
* Stefan Handschuh <https://launchpad.net/~handschuh> (no email provided)
+* Tom Kadwill <tomkadwill@xxxxxxxxx>
=== modified file 'CHANGELOG'
--- CHANGELOG 2012-11-01 16:34:04 +0000
+++ CHANGELOG 2012-11-05 22:34:19 +0000
@@ -56,6 +56,7 @@
* Remove use of liblarch's "transparent" concept (since it's been removed from liblarch), fixes bugs #1001962, #1001962, #1069257, #1069963: intermediary tags, counter initialization, and regressions caused by initial versions of the patch
* Fix for bug #1038662: Undefined due dates in subtasks should always stay undefined and displayed as such in the editor
* Fix for bug #1036695: Date constraints after drag and drop not applied
+ * Fix for bug #320589: Added untouched_tasks plugin
2012-02-13 Getting Things GNOME! 0.2.9
* Big refractorization of code, now using liblarch
=== added file 'GTG/plugins/untouched-tasks.gtg-plugin'
--- GTG/plugins/untouched-tasks.gtg-plugin 1970-01-01 00:00:00 +0000
+++ GTG/plugins/untouched-tasks.gtg-plugin 2012-11-05 22:34:19 +0000
@@ -0,0 +1,9 @@
+[GTG Plugin]
+Module=untouched_tasks
+Name=Untouched tasks
+Short-description="Keep track of tasks you haven't touched for a while."
+Description="""Assigns tasks that you haven't touched for a while with the @untouched tag."""
+Authors=Tom Kadwill <tomkadwill@xxxxxxxxx>
+Version=0.0.1
+Enabled=False
+Dependencies=gio, urllib
=== added directory 'GTG/plugins/untouched_tasks'
=== added file 'GTG/plugins/untouched_tasks/__init__.py'
--- GTG/plugins/untouched_tasks/__init__.py 1970-01-01 00:00:00 +0000
+++ GTG/plugins/untouched_tasks/__init__.py 2012-11-05 22:34:19 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012 - Tom Kadwill <tomkadwill@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/>.
+
+from GTG.plugins.untouched_tasks.untouchedTasks import pluginUntouchedTasks
+
+
+#suppress pyflakes warning (given by make lint)
+if False == True:
+ pluginUntouchedTasks()
=== added file 'GTG/plugins/untouched_tasks/untouchedTasks.py'
--- GTG/plugins/untouched_tasks/untouchedTasks.py 1970-01-01 00:00:00 +0000
+++ GTG/plugins/untouched_tasks/untouchedTasks.py 2012-11-05 22:34:19 +0000
@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012 - Tom Kadwill <tomkadwill@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
+import os
+import gio
+import gtk
+import urllib
+import datetime
+
+from GTG import _
+from GTG.tools.logger import Log
+from GTG.tools.dates import Date
+from threading import Timer
+from datetime import date, timedelta
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+except: # pylint: disable-msg=W0702
+ sys.exit(1)
+
+try:
+ import gtk
+except: # pylint: disable-msg=W0702
+ sys.exit(1)
+
+###################################
+
+class pluginUntouchedTasks:
+
+ DEFAULT_PREFERENCES = {'max_days': 30,
+ 'is_automatic': False,
+ 'show_menu_item': True}
+
+ PLUGIN_NAME = "untouched-tasks"
+
+ # In case of automatic removing tasks, the time
+ # between two runs of the cleaner function
+ TIME_BETWEEN_PURGES = 60 * 60
+
+ def __init__(self):
+ self.path = os.path.dirname(os.path.abspath(__file__))
+ #GUI initialization
+ self.builder = gtk.Builder()
+ self.builder.add_from_file(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)) + \
+ "/untouchedTasks.ui"))
+ self.preferences_dialog = self.builder.get_object("preferences_dialog")
+ self.pref_chbox_show_menu_item = \
+ self.builder.get_object("pref_chbox_show_menu_item")
+ self.pref_chbox_is_automatic = \
+ self.builder.get_object("pref_chbox_is_automatic")
+ self.pref_spinbtn_max_days = \
+ self.builder.get_object("pref_spinbtn_max_days")
+ SIGNAL_CONNECTIONS_DIC = {
+ "on_preferences_dialog_delete_event":
+ self.on_preferences_cancel,
+ "on_btn_preferences_cancel_clicked":
+ self.on_preferences_cancel,
+ "on_btn_preferences_ok_clicked":
+ self.on_preferences_ok,
+ }
+ self.builder.connect_signals(SIGNAL_CONNECTIONS_DIC)
+ self.menu_item = gtk.MenuItem("Add @untouched tag")
+ self.menu_item.connect('activate', self.add_untouched_tag)
+
+ def activate(self, plugin_api):
+ self.plugin_api = plugin_api
+ #preferences initialization
+ self.menu_item_is_shown = False
+ self.is_automatic = False
+ self.timer = None
+ self.preferences_load()
+ self.preferences_apply()
+ requester = self.plugin_api.get_requester()
+
+ def deactivate(self, plugin_api):
+ """
+ Deactivates the plugin.
+ """
+ #everything should be removed, in case a task is currently opened
+ try:
+ self.plugin_api.remove_task_toolbar_item(self.tb_Taskbutton)
+ except:
+ pass
+
+## HELPER FUNCTIONS ###########################################################
+ def __log(self, message):
+ Log.debug(message)
+
+## CORE FUNCTIONS #############################################################
+ def schedule_autopurge(self):
+ self.timer = Timer(self.TIME_BETWEEN_PURGES,
+ self.add_untouched_tag)
+ self.timer.setDaemon(True)
+ self.timer.start()
+ self.__log("Automatic untouched tasks check scheduled")
+
+ def cancel_autopurge(self):
+ if self.timer:
+ self.__log("Automatic untouched tasks check cancelled")
+ self.timer.cancel()
+
+ def add_untouched_tag(self, widget = None):
+ """
+ When the user presses the button.
+ """
+ self.__log("Starting process for adding @untouched tag")
+ today = datetime.datetime.now()
+ max_days = self.preferences["max_days"]
+ requester = self.plugin_api.get_requester()
+ closed_tree = requester.get_tasks_tree(name = 'inactive')
+ closed_tasks = [requester.get_task(tid) for tid in \
+ closed_tree.get_all_nodes()]
+ for task in closed_tasks:
+ modified_time = task.get_modified()
+ new_time = modified_time + datetime.timedelta(days=max_days)
+ if new_time < today:
+ self.__log('Adding @untouched tag to: "' + task.title +
+ '" as last time it was modified was ' + str(modified_time))
+ task.add_tag('@untouched')
+
+ #If automatic purging is on, schedule another run
+ if self.is_automatic:
+ self.schedule_autopurge()
+
+## Preferences methods ########################################################
+ def is_configurable(self):
+ """A configurable plugin should have this method and return True"""
+ return True
+
+ def configure_dialog(self, manager_dialog):
+ self.preferences_load()
+ self.preferences_dialog.set_transient_for(manager_dialog)
+ self.pref_chbox_is_automatic.set_active(
+ self.preferences["is_automatic"])
+ self.pref_chbox_show_menu_item.set_active(
+ self.preferences["show_menu_item"])
+ self.pref_spinbtn_max_days.set_value(
+ self.preferences["max_days"])
+ self.preferences_dialog.show_all()
+
+ def on_preferences_cancel(self, widget = None, data = None):
+ self.preferences_dialog.hide()
+ return True
+
+ def on_preferences_ok(self, widget = None, data = None):
+ self.preferences["is_automatic"] = \
+ self.pref_chbox_is_automatic.get_active()
+ self.preferences["show_menu_item"] = \
+ self.pref_chbox_show_menu_item.get_active()
+ self.preferences["max_days"] = \
+ self.pref_spinbtn_max_days.get_value()
+ self.preferences_apply()
+ self.preferences_store()
+ self.preferences_dialog.hide()
+
+ def preferences_load(self):
+ data = self.plugin_api.load_configuration_object(self.PLUGIN_NAME,
+ "preferences")
+ if data == None or type(data) != type(dict()):
+ self.preferences = self.DEFAULT_PREFERENCES
+ else:
+ self.preferences = data
+
+ def preferences_store(self):
+ self.plugin_api.save_configuration_object(self.PLUGIN_NAME,
+ "preferences", self.preferences)
+
+ def preferences_apply(self):
+ #Showing the GUI
+ if self.preferences['show_menu_item'] == True and \
+ self.menu_item_is_shown == False:
+ self.plugin_api.add_menu_item(self.menu_item)
+ self.menu_item_is_shown = True
+ elif self.preferences['show_menu_item'] == False and \
+ self.menu_item_is_shown == True:
+ self.plugin_api.remove_menu_item(self.menu_item)
+ self.menu_item_is_shown = False
+ #Auto-purge
+ if self.preferences['is_automatic'] == True and \
+ self.is_automatic == False:
+ self.is_automatic = True
+ # Run the first iteration immediately and schedule next iteration
+ self.add_untouched_tag()
+ elif self.preferences['is_automatic'] == False and \
+ self.is_automatic == True:
+ self.cancel_autopurge()
+ self.is_automatic = False
=== added file 'GTG/plugins/untouched_tasks/untouchedTasks.ui'
--- GTG/plugins/untouched_tasks/untouchedTasks.ui 1970-01-01 00:00:00 +0000
+++ GTG/plugins/untouched_tasks/untouchedTasks.ui 2012-11-05 22:34:19 +0000
@@ -0,0 +1,138 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAccelGroup" id="accelgroup1"/>
+ <object class="GtkWindow" id="preferences_dialog">
+ <property name="border_width">10</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="type_hint">dialog</property>
+ <signal name="delete_event" handler="on_preferences_dialog_delete_event"/>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Add @untouched tag to task after it has been left untouched for at least </property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="pref_spinbtn_max_days">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">3</property>
+ <property name="invisible_char">•</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="climb_rate">0.5</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> days</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pref_chbox_is_automatic">
+ <property name="label" translatable="yes">Add @untouched tag to old tasks automatically</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="image_position">top</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pref_chbox_show_menu_item">
+ <property name="label" translatable="yes">Add the "Plugins > Add @untouched plugin" menu item</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="image_position">top</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">21</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="spacing">50</property>
+ <child>
+ <object class="GtkButton" id="btn_preferences_cancel">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_btn_preferences_cancel_clicked"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_preferences_ok">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_btn_preferences_ok_clicked"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+</interface>
Follow ups