-
Notifications
You must be signed in to change notification settings - Fork 169
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add & implement org.gnome.GTG.Tasks DBus interface
Introducing org.gnome.GTG.Tasks, an DBus interface to manage tasks. This is very much inspired by the old "DBus Wrapper", that implemented org.gnome.GTGTasks (I think), but this is in some ways different: * Do actions in batches * Only handle tasks, no UI stuff (actions can replace some)
- Loading branch information
Showing
7 changed files
with
360 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
|
||
# Implementation of the org.gnome.GTG.Tasks interface | ||
|
||
from gi.repository import GLib | ||
from GTG.core.logger import log | ||
from GTG.core.search import parse_search_query, InvalidQuery | ||
from GTG.core.dates import Date | ||
from .dbus import DBusInterfaceImplService, DBusReturnError | ||
|
||
|
||
def _task_to_dict(task): | ||
d = { | ||
"id": task.get_id(), | ||
"status": task.get_status(), | ||
"title": task.get_title(), | ||
"duedate": str(task.get_due_date()), # TODO: Check if str(Date) is correct | ||
"startdate": str(task.get_start_date()), # TODO: Check if str(Date) is correct | ||
"donedate": str(task.get_closed_date()), # TODO: Check if str(Date) is correct | ||
"tags": task.get_tags_name(), | ||
"text": task.get_text(), | ||
"subtasks": task.get_children(), | ||
"parents": task.get_parents(), | ||
} | ||
return d | ||
|
||
_task_dict_to_variant_type = { | ||
"id": 's', | ||
"status": 's', | ||
"title": 's', | ||
"duedate": 's', | ||
"startdate": 's', | ||
"donedate": 's', | ||
"tags": 'as', | ||
"text": 's', | ||
"subtasks": 'as', | ||
"parents": 'as', | ||
} | ||
|
||
def _task_dict_to_variant(task_dict): | ||
"""Convert an task dict to a variant dict to be submitted over DBus""" | ||
d = dict(task_dict) | ||
for name, vtype in _task_dict_to_variant_type.items(): | ||
if name in task_dict: | ||
d[name] = GLib.Variant(vtype, task_dict[name]) | ||
return d # Not GLib.Variant("a{sv}", d) because it'll break later | ||
# return GLib.Variant("a{sv}", d) | ||
|
||
def _task_to_variant(task): | ||
"""Convert an task object to a variant dict to be submitted over DBus""" | ||
return _task_dict_to_variant(_task_to_dict(task)) | ||
|
||
def _variant_to_task_dict(task_variant): | ||
"""Convert an variant dict to a task""" | ||
return task_variant.unpack() | ||
|
||
|
||
class DBusImplTasks(DBusInterfaceImplService): | ||
INTERFACE_NAME = 'org.gnome.GTG.Tasks' | ||
|
||
def __init__(self, req): | ||
super().__init__() | ||
self.req = req | ||
|
||
tree = req.get_main_view() | ||
# TODO: Register signals | ||
# tree.register_cllbck('node-added', lambda tid, _: | ||
# self.TaskAdded(tid)) | ||
# tree.register_cllbck('node-modified', lambda tid, _: | ||
# self.TaskModified(tid)) | ||
# tree.register_cllbck('node-deleted', lambda tid, _: | ||
# self.TaskDeleted(tid)) | ||
|
||
def GetTasks(self, tids): | ||
log.debug(f"Doing GetTasks({tids})") | ||
# TODO: Improve on better error message on missing tasks or something | ||
# Current: Fehler: GDBus.Error:python.AttributeError: 'NoneType' object has no attribute 'get_id' | ||
return [_task_to_variant(self.req.get_task(tid)) for tid in tids] | ||
|
||
def GetActiveTasks(self): | ||
log.debug(f"Doing GetActiveTasks()") | ||
return self.GetTasksFiltered(['active', 'workable']) | ||
|
||
def GetTaskIdsFiltered(self, filters): | ||
log.debug(f"Doing GetTasksFiltered({filters})") | ||
tree = self.req.get_tasks_tree().get_basetree() | ||
view = tree.get_viewtree() | ||
for filter in filters: | ||
if filter[0] == '!': | ||
view.apply_filter(filter[1:], parameters={'negate': 1}) | ||
else: | ||
view.apply_filter(filter) | ||
return view.get_all_nodes() # TODO: Check what it returns (type-wise) | ||
|
||
def GetTasksFiltered(self, filters): | ||
log.debug(f"Doing GetTasksFiltered({filters})") | ||
return self.GetTasks(self.GetTaskIdsFiltered(filters)) | ||
|
||
def SearchTaskIds(self, query): | ||
log.debug(f"Doing SearchTaskIds({query})") | ||
tree = self.req.get_tasks_tree().get_basetree() | ||
view = tree.get_viewtree() | ||
try: | ||
search = parse_search_query(query) | ||
view.apply_filter('search', parameters=search) | ||
tasks = view.get_all_nodes() | ||
if tasks: | ||
return tasks | ||
except InvalidQuery: | ||
raise DBusReturnError("gtg.InvalidQuery", "Invalid Query: " + str(query)) | ||
return [] | ||
|
||
def SearchTasks(self, query): | ||
log.debug(f"Doing SearchTasks({query})") | ||
return self.GetTasks(self.SearchTaskIds(query)) | ||
|
||
def HasTasks(self, tids): | ||
log.debug(f"Doing HasTasks({tids})") | ||
return {tid: self.req.has_task(tid) for tid in tids} | ||
|
||
def DeleteTasks(self, tids): | ||
log.debug(f"Doing DeleteTasks({tids})") | ||
d = {} | ||
for tid in tids: | ||
if self.req.has_task(tid): | ||
self.req.delete_task(tid) | ||
d[tid] = True | ||
else: | ||
d[tid] = False | ||
return d | ||
|
||
def NewTasks(self, tasks): | ||
log.debug(f"Doing NewTasks({tasks})") | ||
return [] # TODO: Implement this | ||
|
||
def ModifyTasks(self, patches): | ||
log.debug(f"Doing ModifyTasks({patches})") | ||
r = [] | ||
for patch in patches: | ||
r.append(_task_to_variant(self._modify_task(patch))) | ||
return r | ||
|
||
def _modify_task(self, patch): | ||
"""Modify a single task and return it""" | ||
task = self.req.get_task(patch["id"]) | ||
if "title" in patch: | ||
task.set_title(patch["task"]) | ||
if "text" in patch: | ||
task.set_text(patch["text"]) | ||
if "duedate" in patch: | ||
task.set_due_date(Date.parse(patch["due_date"])) | ||
if "startdate" in patch: | ||
task.set_start_date(Date.parse(patch["start_date"])) | ||
if "donedate" in patch: | ||
pass # TODO | ||
if "tags" in patch: | ||
pass # TODO | ||
if "childrens" in patch: | ||
pass # TODO | ||
if "parents" in patch: | ||
pass # TODO | ||
return task | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
configure_file( | ||
input: rdnn_name + '.Tasks.xml', | ||
output: rdnn_name + '.Tasks.xml', | ||
copy: true, | ||
install: true, | ||
install_dir: dbusinterfacesdir | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> | ||
<node name="/org/gnome/GTG"> | ||
<!-- | ||
org.gnome.GTG.Tasks: | ||
@short_description: Manage GTG Tasks | ||
Interface that GTG implements to let other applications view and edit | ||
tasks. | ||
An common type used here would be the so-called "task dict(ionary)" or | ||
{sv}. It means it is a map of string to generic values. They could | ||
contain: | ||
* id (s): The id the task can be identified | ||
* title (s): Title of the task | ||
* status (i): 0: Unknown, 1: Open, 2: Closed | ||
* text (s): Text content of the task | ||
* duedate (s): Due date in ISO TODO, or a fuzzy date "now", "soon", "someday" | ||
* startdate (s): Start date in ISO TODO, or a fuzzy date "now", "soon", "someday" | ||
* donedate (s): When the task was finished, in ISO TODO | ||
* tags (as): Tasks the task has, without @ | ||
* subtasks (as): Subtasks as UIDs the task contains | ||
* parent (s): ID of the parent task (empty or non-existent means root) | ||
--> | ||
<interface name="org.gnome.GTG.Tasks"> | ||
<!-- | ||
GetTasks: | ||
@uids: An array of Task UIDs, whose info should be retrieved | ||
@tasks: An dictionary of UIDs to their task dictionary. | ||
TODO: API documentation | ||
--> | ||
<method name="GetTasks"> | ||
<arg name="uids" type="as" direction="in"/> | ||
<arg name="tasks" type="aa{sv}" direction="out"/> | ||
<!-- <arg name="tasks" type="a{sa{sv}}" direction="out"/> --> | ||
</method> | ||
|
||
<!-- | ||
GetTasks: | ||
@tasks: An array of tasks dictionary that are currently active. | ||
TODO: API documentation, explain what active means | ||
Refer to the interface description for the task dict values. | ||
--> | ||
<method name="GetActiveTasks"> | ||
<arg name="tasks" type="aa{sv}" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
GetTaskIdsFiltered: | ||
@filter: Filters to apply, also see filters_bank documentation | ||
@task_ids: Filtered tasks ids matching the specified filters | ||
TODO: API documentation | ||
Also see the GetTaskFiltered method to find more about filters. | ||
--> | ||
<method name="GetTaskIdsFiltered"> | ||
<arg name="filter" type="as" direction="in"/> | ||
<arg name="tasks_ids" type="as" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
GetTasksFiltered: | ||
@filter: Filters to apply, also see filters_bank documentation | ||
@tasks: Filtered tasks dicts matching the specified filters | ||
TODO: API documentation, possibly explain some of filters_bank | ||
--> | ||
<method name="GetTasksFiltered"> | ||
<arg name="filter" type="as" direction="in"/> | ||
<arg name="tasks" type="aa{sv}" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
SearchTasks: | ||
@query: Search for tasks, like search bar with special options | ||
@tasks: Filtered tasks ids matching the specified filters | ||
TODO: API documentation, possibly explain some of the specials | ||
(If used, need to check) | ||
--> | ||
<method name="SearchTaskIds"> | ||
<arg name="query" type="s" direction="in"/> | ||
<arg name="tasks" type="as" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
SearchTasks: | ||
@query: Search for tasks, like search bar with special options | ||
@tasks: Filtered tasks dicts matching the specified filters | ||
TODO: API documentation, possibly explain some of the specials | ||
(If used, need to check) | ||
--> | ||
<method name="SearchTasks"> | ||
<arg name="query" type="s" direction="in"/> | ||
<arg name="tasks" type="aa{sv}" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
HasTasks: | ||
@tids: Array of task IDs to check | ||
@successful: Map of task IDs to a boolean indicating it exists | ||
TODO: API documentation | ||
--> | ||
<method name="HasTasks"> | ||
<arg name="tids" type="as" direction="in"/> | ||
<arg name="present" type="a{sb}" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
DeleteTasks: | ||
@task_ids: Array of task IDs to delete | ||
@successful: Map of task IDs to a boolean indication success deleting | ||
TODO: API documentation | ||
--> | ||
<method name="DeleteTasks"> | ||
<arg name="task_ids" type="as" direction="in"/> | ||
<arg name="successful" type="a{sb}" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
NewTasks: | ||
@data: Array of task dictionaries to add | ||
@ids: Array of the new task IDs for the tasks | ||
TODO: API documentation | ||
--> | ||
<method name="NewTasks"> | ||
<arg name="data" type="aa{sv}" direction="in"/> | ||
<arg name="ids" type="as" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
ModifyTasks: | ||
@patch: Array of task dictionaries to update, uses the tid | ||
@resulting: TODO | ||
TODO: API documentation | ||
--> | ||
<method name="ModifyTasks"> | ||
<arg name="patch" type="aa{sv}" direction="in"/> | ||
<arg name="result" type="aa{sv}" direction="out"/> | ||
</method> | ||
|
||
<!-- | ||
TaskAdded: | ||
@tid: Task ID that has been added | ||
TODO: API documentation | ||
--> | ||
<signal name="TaskAdded"> | ||
<arg name="tid" type="s"/> | ||
</signal> | ||
|
||
<!-- | ||
TaskAdded: | ||
@tid: Task ID that has been modified | ||
TODO: API documentation | ||
--> | ||
<signal name="TaskModified"> | ||
<arg name="tid" type="s"/> | ||
</signal> | ||
|
||
<!-- | ||
TaskAdded: | ||
@tid: Task ID that has been deleted | ||
TODO: API documentation | ||
--> | ||
<signal name="TaskDeleted"> | ||
<arg name="tid" type="s"/> | ||
</signal> | ||
</interface> | ||
</node> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,3 +34,4 @@ configure_file( | |
) | ||
|
||
subdir('icons') | ||
subdir('dbus') |
Oops, something went wrong.