| Line | Revision | Contents |
| 1 | 258 | import gobject, dbus.glib, dbus, dbus.service |
| 2 | ||
| 3 | 259 | BUSNAME = "org.GTG" |
| 4 | ||
| 5 | 258 | def dsanitize(data): |
| 6 | 259 | # Clean up a dict so that it can be transmitted through D-Bus |
| 7 | 258 | for k, v in data.items(): |
| 8 | 259 | # Manually specify an arbitrary content type for empty Python arrays |
| 9 | # because D-Bus can't handle the type conversion for empty arrays |
|
| 10 | 258 | if not v and isinstance(v, list): |
| 11 | data[k] = dbus.Array([], "s") |
|
| 12 | 259 | # D-Bus has no concept of a null or empty value so we have to convert None |
| 13 | # types to something else. I use an empty string because it has the same |
|
| 14 | # behavior as None in a Python conditional expression |
|
| 15 | 258 | elif v == None: |
| 16 | data[k] = "" |
|
| 17 | ||
| 18 | return data |
|
| 19 | ||
| 20 | def task_to_dict(task): |
|
| 21 | 259 | # Translate a task object into a D-Bus dictionary |
| 22 | 258 | return dbus.Dictionary(dsanitize({ |
| 23 | "id": task.get_id(), |
|
| 24 | "status": task.get_status(), |
|
| 25 | "title": task.get_title(), |
|
| 26 | "duedate": task.get_due_date(), |
|
| 27 | "startdate": task.get_start_date(), |
|
| 28 | "donedate": task.get_closed_date(), |
|
| 29 | "tags": task.get_tags_name(), |
|
| 30 | "text": task.get_text(), |
|
| 31 | "subtask": task.get_subtasks_tid(), |
|
| 32 | }), signature="sv") |
|
| 33 | ||
| 34 | class DBusTaskWrapper(dbus.service.Object): |
|
| 35 | 259 | # D-Bus service object that exposes GTG's task store to third-party apps |
| 36 | 258 | def __init__(self, req, ui): |
| 37 | 259 | # Attach the object to D-Bus |
| 38 | 258 | self.bus = dbus.SessionBus() |
| 39 | 259 | bus_name = dbus.service.BusName(BUSNAME, bus=self.bus) |
| 40 | dbus.service.Object.__init__(self, bus_name, "/org/GTG") |
|
| 41 | 258 | self.req = req |
| 42 | self.ui = ui |
|
| 43 | ||
| 44 | 259 | @dbus.service.method(BUSNAME) |
| 45 | 258 | def get_task_ids(self): |
| 46 | 259 | # Retrieve a list of task ID values |
| 47 | 258 | return self.req.get_tasks_list(status=["Active", "Done"], started_only=False) |
| 48 | ||
| 49 | 259 | @dbus.service.method(BUSNAME) |
| 50 | 258 | def get_task(self, tid): |
| 51 | 259 | # Retrieve a specific task by ID and return the data |
| 52 | 258 | return task_to_dict(self.req.get_task(tid)) |
| 53 | ||
| 54 | 259 | @dbus.service.method(BUSNAME) |
| 55 | 258 | def get_tasks(self): |
| 56 | 259 | # Retrieve a list of task data dicts |
| 57 | 258 | return [self.get_task(id) for id in self.get_task_ids()] |
| 58 | ||
| 59 | 259 | @dbus.service.method(BUSNAME, in_signature="asasbb") |
| 60 | 258 | def get_task_ids_filtered(self, tags, status, started_only, is_root): |
| 61 | 259 | # Retrieve a list of task IDs filtered by specified parameters |
| 62 | 258 | ids = self.req.get_tasks_list(tags, status, False, started_only, is_root) |
| 63 | 259 | # If there are no matching tasks, return an empty D-Bus array |
| 64 | 258 | return ids if ids else dbus.Array([], "s") |
| 65 | ||
| 66 | 259 | @dbus.service.method(BUSNAME, in_signature="asasbb") |
| 67 | 258 | def get_tasks_filtered(self, tags, status, started_only, is_root): |
| 68 | 259 | # Retrieve a list of task data discts filtered by specificed parameters |
| 69 | 258 | tasks = self.get_task_ids_filtered(tags, status, started_only, is_root) |
| 70 | 259 | # If no tasks match the filter, return an empty D-Bus array |
| 71 | 258 | return [self.get_task(id) for id in tasks] if tasks else dbus.Array([], "s") |
| 72 | ||
| 73 | 259 | @dbus.service.method(BUSNAME) |
| 74 | 258 | def has_task(self, tid): |
| 75 | return self.req.has_task(tid) |
|
| 76 | ||
| 77 | 259 | @dbus.service.method(BUSNAME) |
| 78 | 258 | def delete_task(self, tid): |
| 79 | self.req.delete_task(tid) |
|
| 80 | ||
| 81 | 259 | @dbus.service.method(BUSNAME, in_signature="sssssassas") |
| 82 | 258 | def new_task(self, status, title, duedate, startdate, donedate, tags, text, subtasks): |
| 83 | 259 | # Generate a new task object and return the task data as a dict |
| 84 | 258 | nt = self.req.new_task() |
| 85 | for sub in subtasks: nt.add_subtask(sub) |
|
| 86 | for tag in tags: nt.add_tag(tag) |
|
| 87 | nt.set_status(status, donedate=donedate) |
|
| 88 | nt.set_title(title) |
|
| 89 | nt.set_due_date(duedate) |
|
| 90 | nt.set_start_date(startdate) |
|
| 91 | nt.set_text(text) |
|
| 92 | return task_to_dict(nt) |
|
| 93 | ||
| 94 | 259 | @dbus.service.method(BUSNAME) |
| 95 | 258 | def modify_task(self, tid, task_data): |
| 96 | 259 | # Apply supplied task data to the task object with the specified ID |
| 97 | 258 | task = self.req.get_task(tid) |
| 98 | task.set_status(task_data["status"], donedate=task_data["donedate"]) |
|
| 99 | task.set_title(task_data["title"]) |
|
| 100 | task.set_due_date(task_data["duedate"]) |
|
| 101 | task.set_start_date(task_data["startdate"]) |
|
| 102 | task.set_text(task_data["text"]) |
|
| 103 | ||
| 104 | for tag in task_data["tags"]: task.add_tag(tag) |
|
| 105 | for sub in task_data["subtask"]: task.add_subtask(sub) |
|
| 106 | return task_to_dict(task) |
|
| 107 | ||
| 108 | 259 | @dbus.service.method(BUSNAME) |
| 109 | 258 | def open_task_editor(self, tid): |
| 110 | self.ui.open_task(tid) |
|
| 111 | ||
| 112 | 259 | @dbus.service.method(BUSNAME) |
| 113 | 258 | def hide_task_browser(self): |
| 114 | self.ui.window.hide() |
|
| 115 | |
|
| 116 | 259 | @dbus.service.method(BUSNAME) |
| 117 | 258 | def show_task_browser(self): |
| 118 | self.ui.window.present() |
|
| 119 | self.ui.window.move(self.ui.priv["window_xpos"], self.ui.priv["window_ypos"]) |
|
| 120 | 259 |
Loggerhead 1.10 is a web-based interface for Bazaar branches