GTG

Merge lp:~gtg-user/gtg/uri-support into lp:~gtg/gtg/old-trunk

Proposed by Luca Invernizzi
Status: Merged
Merged at revision: 880
Proposed branch: lp:~gtg-user/gtg/uri-support
Merge into: lp:~gtg/gtg/old-trunk
Diff against target: 276 lines (+98/-32)
5 files modified
CHANGELOG (+1/-0)
GTG/__init__.py (+10/-0)
GTG/gtg.py (+21/-11)
GTG/gtk/browser/browser.py (+2/-1)
GTG/gtk/manager.py (+64/-20)
To merge this branch: bzr merge lp:~gtg-user/gtg/uri-support
Reviewer Review Type Date Requested Status
Gtg developers Pending
Review via email: mp+32643@code.launchpad.net

This proposal supersedes a proposal from 2010-08-09.

Description of the change

GTG support for URIs of the format gtg://<gtg-task-id>
These URIs are useful for putting tasks links in other programs (e.g, in a tomboy note).
I'm currently using it in the Zeitgeist backend, to let the tasks registered in Zeitgeist and shown through the Activity Journal to be clickable.

On every start, GTG checks if GNOME knows about this kind of URI and, if not, puts itself as an application capable of handling those. Therefore, you can use
xdg-open gtg://<gtg-task-id>.

Tomboy has the same kind of feature through a note:// URI.

To post a comment you must log in.
Revision history for this message
Luca Invernizzi (invernizzi) wrote : Posted in a previous version of this proposal

Ps: the last commits messages have the very meaningful name of "a" because I had to do a series of cherrypicking. Only the file that's picked matters.

lp:~gtg-user/gtg/uri-support updated
874. By Luca Invernizzi

GTG can be opened just with some TaskEditor windows

Revision history for this message
Luca Invernizzi (invernizzi) wrote :

I've just added the support for opening GTG without the task browser (if some uris are given).
If the browser was already open, it stays open, and if ./gtg is executed while in browserless mode, it opens the browser.
We're getting tomboysh :)

lp:~gtg-user/gtg/uri-support updated
875. By Luca Invernizzi

merge w/ trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CHANGELOG'
--- CHANGELOG 2010-08-04 00:30:22 +0000
+++ CHANGELOG 2010-08-25 16:29:47 +0000
@@ -4,6 +4,7 @@
4 * Fixed bug with data consistency #579189, by Marko Kevac4 * Fixed bug with data consistency #579189, by Marko Kevac
5 * Added samba bugzilla to the bugzilla plugin, by Jelmer Vernoij5 * Added samba bugzilla to the bugzilla plugin, by Jelmer Vernoij
6 * Fixed bug #532392, a start date is later than a due date, by Volodymyr Floreskul6 * Fixed bug #532392, a start date is later than a due date, by Volodymyr Floreskul
7 * support for gtg:// URIs by Luca Invernizzi
78
82010-03-01 Getting Things GNOME! 0.2.292010-03-01 Getting Things GNOME! 0.2.2
9 * Autostart on login, by Luca Invernizzi10 * Autostart on login, by Luca Invernizzi
1011
=== modified file 'GTG/__init__.py'
--- GTG/__init__.py 2010-03-12 11:16:15 +0000
+++ GTG/__init__.py 2010-08-25 16:29:47 +0000
@@ -92,3 +92,13 @@
9292
93if os.path.isdir(os.path.join(config_home, 'gtg/plugins')):93if os.path.isdir(os.path.join(config_home, 'gtg/plugins')):
94 PLUGIN_DIR.append(os.path.join(config_home, 'gtg/plugins'))94 PLUGIN_DIR.append(os.path.join(config_home, 'gtg/plugins'))
95
96#Register GTG URI (temporary, it should be created by a schema upon installing)
97import gconf
98domain = "/desktop/gnome/url-handlers/gtg/"
99client = gconf.client_get_default()
100#this should work both in debugging mode and in deployed mode
101client.set_string(os.path.join(domain, "command"), "gtg %s")
102client.set_bool(os.path.join(domain, "enabled"), True)
103client.set_bool(os.path.join(domain, "needs_terminal"), False)
104
95105
=== modified file 'GTG/gtg.py'
--- GTG/gtg.py 2010-08-03 17:07:31 +0000
+++ GTG/gtg.py 2010-08-25 16:29:47 +0000
@@ -46,8 +46,8 @@
4646
47#=== IMPORT ===================================================================47#=== IMPORT ===================================================================
48import os48import os
49import sys
49import logging50import logging
50
51import dbus51import dbus
5252
53#our own imports53#our own imports
@@ -55,7 +55,7 @@
55from GTG import _55from GTG import _
56from GTG.core import CoreConfig56from GTG.core import CoreConfig
57from GTG.core.datastore import DataStore57from GTG.core.datastore import DataStore
58#from GTG.gtk.crashhandler import signal_catcher58from GTG.gtk.crashhandler import signal_catcher
59from GTG.gtk.manager import Manager59from GTG.gtk.manager import Manager
60from GTG.tools.logger import Log60from GTG.tools.logger import Log
6161
@@ -66,8 +66,11 @@
66#that's why we put the pid file in the data directory :66#that's why we put the pid file in the data directory :
67#we allow one instance of gtg by data directory.67#we allow one instance of gtg by data directory.
6868
69def check_instance(directory):69def check_instance(directory, uri_list = []):
70 """Check if gtg is already running."""70 """
71 Check if gtg is already running.
72 If so, open the tasks whose ids are in the uri_list
73 """
71 pidfile = os.path.join(directory, "gtg.pid")74 pidfile = os.path.join(directory, "gtg.pid")
72 if not os.path.exists(pidfile):75 if not os.path.exists(pidfile):
73 open(pidfile, "w").close()76 open(pidfile, "w").close()
@@ -83,6 +86,10 @@
83 d=dbus.SessionBus().get_object(CoreConfig.BUSNAME,\86 d=dbus.SessionBus().get_object(CoreConfig.BUSNAME,\
84 CoreConfig.BUSINTERFACE)87 CoreConfig.BUSINTERFACE)
85 d.show_task_browser()88 d.show_task_browser()
89 #if the user has specified a task to open, do that
90 for uri in uri_list:
91 if uri.startswith("gtg://"):
92 d.open_task_editor(uri[6:])
86 raise SystemExit93 raise SystemExit
87 94
88 #write the pid file95 #write the pid file
@@ -102,10 +109,10 @@
102 #To be more user friendly and get the logs of crashes, we show an apport109 #To be more user friendly and get the logs of crashes, we show an apport
103 # hooked window upon crashes110 # hooked window upon crashes
104 if options.no_crash_handler == False:111 if options.no_crash_handler == False:
105 #FIXME: Why is this disabled? Please comment when disabling functionality so we know. :-)112 with signal_catcher(manager.close_browser):
106 #with signal_catcher(manager.close_browser):113 manager.main(once_thru=options.boot_test, uri_list = args)
107 pass114 else:
108 manager.main(once_thru=options.boot_test)115 manager.main(once_thru=options.boot_test, uri_list = args)
109 core_main_quit(config, ds)116 core_main_quit(config, ds)
110117
111def core_main_init(options = None, args = None):118def core_main_init(options = None, args = None):
@@ -116,10 +123,11 @@
116 if options.debug:123 if options.debug:
117 Log.setLevel(logging.DEBUG)124 Log.setLevel(logging.DEBUG)
118 Log.debug("Debug output enabled.")125 Log.debug("Debug output enabled.")
119 Log.set_debugging_mode(True)126 else:
120127 Log.setLevel(logging.INFO)
128 Log.set_debugging_mode(options.debug)
121 config = CoreConfig()129 config = CoreConfig()
122 check_instance(config.get_data_dir())130 check_instance(config.get_data_dir(), args)
123 backends_list = BackendFactory().get_saved_backends_list()131 backends_list = BackendFactory().get_saved_backends_list()
124 # Load data store132 # Load data store
125 ds = DataStore()133 ds = DataStore()
@@ -145,6 +153,8 @@
145 # Ending the application: we save configuration153 # Ending the application: we save configuration
146 config.save()154 config.save()
147 ds.save(quit = True)155 ds.save(quit = True)
156 sys.exit(0)
157
148158
149#=== EXECUTION ================================================================159#=== EXECUTION ================================================================
150160
151161
=== modified file 'GTG/gtk/browser/browser.py'
--- GTG/gtk/browser/browser.py 2010-08-23 01:33:43 +0000
+++ GTG/gtk/browser/browser.py 2010-08-25 16:29:47 +0000
@@ -139,7 +139,8 @@
139 #Expand all the tasks in the taskview139 #Expand all the tasks in the taskview
140 self.task_tv.expand_all()140 self.task_tv.expand_all()
141 self.on_select_tag()141 self.on_select_tag()
142 self.window.show()142
143 self.window.hide()
143144
144### INIT HELPER FUNCTIONS #####################################################145### INIT HELPER FUNCTIONS #####################################################
145#146#
146147
=== modified file 'GTG/gtk/manager.py'
--- GTG/gtk/manager.py 2010-08-03 17:07:31 +0000
+++ GTG/gtk/manager.py 2010-08-25 16:29:47 +0000
@@ -39,10 +39,12 @@
39from GTG.core.plugins.engine import PluginEngine39from GTG.core.plugins.engine import PluginEngine
40from GTG.core.plugins.api import PluginAPI40from GTG.core.plugins.api import PluginAPI
41from GTG.tools.logger import Log41from GTG.tools.logger import Log
4242from GTG.gtk.backends_dialog import BackendsDialog
4343from GTG.backends.backendsignals import BackendSignals
4444
45class Manager:45
46
47class Manager(object):
46 48
4749
48 ############## init #####################################################50 ############## init #####################################################
@@ -58,6 +60,7 @@
58 # right now60 # right now
59 61
60 self.browser = None62 self.browser = None
63 self.gtk_terminate = False #if true, the gtk main is not started
61 self.pengine = None64 self.pengine = None
62 self.plugins = None65 self.plugins = None
63 self.plugin_api = None66 self.plugin_api = None
@@ -65,11 +68,9 @@
65 68
66 #Shared clipboard69 #Shared clipboard
67 self.clipboard = clipboard.TaskClipboard(self.req)70 self.clipboard = clipboard.TaskClipboard(self.req)
68 71
69 #Browser72 #Browser (still hidden)
70 #FIXME : the browser should not be built by default and should be a 73 self.browser = TaskBrowser(self.req, self, self.config)
71 # window like another and not necessary (like the editor)
72 self.open_browser()
73 74
74 #Plugins (that needs to be after the browser, this is ugly)75 #Plugins (that needs to be after the browser, this is ugly)
75 self.__init_plugin_engine()76 self.__init_plugin_engine()
@@ -80,6 +81,7 @@
80 #Preferences and Backends windows81 #Preferences and Backends windows
81 # Initialize dialogs82 # Initialize dialogs
82 self.preferences_dialog = None83 self.preferences_dialog = None
84 self.edit_backends_dialog = None
83 85
84 #DBus86 #DBus
85 DBusTaskWrapper(self.req, self)87 DBusTaskWrapper(self.req, self)
@@ -125,9 +127,8 @@
125 ############## Browser #################################################127 ############## Browser #################################################
126128
127 def open_browser(self):129 def open_browser(self):
128 if not self.browser:
129 self.browser = TaskBrowser(self.req, self, self.config)
130 Log.debug("Browser is open")130 Log.debug("Browser is open")
131 self.browser.show()
131132
132 #FIXME : the browser should not be the center of the universe.133 #FIXME : the browser should not be the center of the universe.
133 # In fact, we should build a system where view can register themselves134 # In fact, we should build a system where view can register themselves
@@ -190,12 +191,30 @@
190 #else, it close_task would be called once again 191 #else, it close_task would be called once again
191 #by editor.close192 #by editor.close
192 editor.close()193 editor.close()
193# else:194 self.check_quit_condition()
194 #FIXME: this one should be a debug statement195
195# print "the %s editor was already unregistered" %tid196 def check_quit_condition(self):
197 '''
198 checking if we need to shut down the whole GTG (if no window is open)
199 '''
200 if not self.is_browser_visible() and not self.opened_task:
201 #no need to live
202 print "AAAAAAAAAAA"
203 self.quit()
204 print self.opened_task
196 205
197################ Others dialog ############################################206################ Others dialog ############################################
198207
208 def open_edit_backends(self, sender = None, backend_id = None):
209 if not self.edit_backends_dialog:
210 self.edit_backends_dialog = BackendsDialog(self.req)
211 self.edit_backends_dialog.activate()
212 if backend_id != None:
213 self.edit_backends_dialog.show_config_for_backend(backend_id)
214
215 def configure_backend(self, backend_id):
216 self.open_edit_backends(None, backend_id)
217
199 def open_preferences(self, config_priv, sender=None):218 def open_preferences(self, config_priv, sender=None):
200 if not hasattr(self, "preferences"):219 if not hasattr(self, "preferences"):
201 self.preferences = PreferencesDialog(self.pengine, self.p_apis, \220 self.preferences = PreferencesDialog(self.pengine, self.p_apis, \
@@ -209,17 +228,42 @@
209 for t in tids:228 for t in tids:
210 if t in self.opened_task:229 if t in self.opened_task:
211 self.close_task(t)230 self.close_task(t)
231
232### URIS ###################################################################
233
234 def open_uri_list(self, unused, uri_list):
235 '''
236 Open the Editor windows of the tasks associated with the uris given.
237 Uris are of the form gtg://<taskid>
238 '''
239 print self.req.get_all_tasks_list()
240 for uri in uri_list:
241 if uri.startswith("gtg://"):
242 self.open_task(uri[6:])
243 #if no window was opened, we just quit
244 self.check_quit_condition()
245
212 246
213### MAIN ###################################################################247### MAIN ###################################################################
214 def main(self, once_thru=False):248
249 def main(self, once_thru = False, uri_list = []):
250 if uri_list:
251 #before opening the requested tasks, we make sure that all of them
252 #are loaded.
253 BackendSignals().connect('default-backend-loaded',
254 self.open_uri_list,
255 uri_list)
256 else:
257 self.open_browser()
258
215 gobject.threads_init()259 gobject.threads_init()
216 if once_thru:260 if not self.gtk_terminate:
217 gtk.main_iteration()261 if once_thru:
218 else:262 gtk.main_iteration()
219 gtk.main()263 else:
264 gtk.main()
220 return 0265 return 0
221 266
222
223 def quit(self,sender=None):267 def quit(self,sender=None):
224 gtk.main_quit()268 gtk.main_quit()
225 #save opened tasks and their positions.269 #save opened tasks and their positions.

Subscribers

People subscribed via source and target branches

to status/vote changes: