def on_activate_task(self, uuid): if uuid is None: util.log("Activate new task dialog") New.show_task(self.database) else: util.log("Activate task {0}", uuid) task = self.database.get_task_info(uuid) Properties.show_task(self.database, task)
def setup_indicator(self): if UbuntuIndicator.is_available(): util.log("AppIndicator is available, using it.") self.indicator = UbuntuIndicator() else: util.log("AppIndicator is not available, using Gtk status icon.") self.indicator = GtkIndicator() self.indicator.on_add_task = self.on_add_task self.indicator.on_toggle = self.on_toggle_search self.indicator.on_stop_all = self.on_stop_all self.indicator.on_quit = self.on_quit self.indicator.on_pull = self.on_pull self.indicator.on_task_selected = self.on_task_selected
def show_existing_task(self, task): util.log("Showing task {0} ...", task.id()) self.uuid.set_text(str(task.id())) self.description.set_text(task.get_summary()) self.project.set_text(task["project"] or "") self.priority.set_text(str(task["priority"])) self.notes.set_text(task.get_description() or "") self.completed.set_active(task["status"] == "completed") if "start" in task: self.start.set_label("Stop") else: self.start.set_label("Start")
def add_task(self, properties): command = ["task", "add"] for k, v in properties.items(): if k == "summary": command.append(v) elif k in ("project", "priority"): command.append("%s:%s" % (k, v)) output = util.run_command(command) for _taskno in re.findall("Created task (\d+)", output): uuid = util.run_command(["task", _taskno, "uuid"]).strip() util.log("New task uuid: {0}", uuid) save_note(uuid, properties.get("description", "")) return uuid
def is_available(cls): if not HAVE_APPINDICATOR: util.log("No appindicator package.") return False # not installed user = os.getenv("USER") p = subprocess.Popen(["pgrep", "-u", user, "indicator-applet"], stdout=subprocess.PIPE) out = p.communicate()[0] if out.strip() == "": util.log("User %s has no indicator-applet running." % user) return False # not running return True
def on_timer(self): """Timer handler which updates the list of tasks and the status.""" gtk.timeout_add(FREQUENCY * 1000, self.on_timer) if self.database.modified_since(self.database_ts): util.log("Task database changed.") self.database.refresh() self.search_dialog.refresh() self.menu_add_tasks() self.database_ts = int(time.time()) self.started_at = [] for task in self.database.get_tasks(): if task.is_active() and not task.is_closed(): self.started_at.append(task.get_start_ts()) self.update_status()
def _on_row_changed(self, view): selection = view.get_selection() selection.set_mode(gtk.SELECTION_SINGLE) tree_model, tree_iter = selection.get_selected() if not tree_iter: self.selected_task_id = None self.selected_task = None else: self.selected_task_id = tree_model.get_value(tree_iter, 0) util.log("Selected task {0}", self.selected_task_id) self.selected_task = None for task in self.all_tasks: if str(task.id()) == self.selected_task_id: self.selected_task = task self.pmenu_edit.show() if task.is_closed(): self.pmenu_start.hide() self.pmenu_stop.hide() self.pmenu_done.hide() self.pmenu_restart.show() self.pmenu_links.show() elif task.is_active(): self.pmenu_start.hide() self.pmenu_stop.show() self.pmenu_done.show() self.pmenu_restart.hide() self.pmenu_links.show() else: # pending self.pmenu_start.show() self.pmenu_stop.hide() self.pmenu_done.show() self.pmenu_restart.hide() self.pmenu_links.show() if "://" not in task.get_summary(): self.pmenu_links.hide()
def show_existing_instance(): """ Open up the previous instance, if there is one. FIXME: use dbus. """ p = subprocess.Popen(["pgrep", "-f", "/task-indicator"], stdout=subprocess.PIPE) out = p.communicate()[0] for line in out.splitlines(): if line.strip().isdigit(): pid = int(line.strip()) if pid != os.getpid(): try: os.kill(pid, signal.SIGUSR1) util.log("Sent SIGUSR1 to process %u." % pid) return True except Exception, e: util.log("Error sending SIGUSR1 to process %u: %s" % (pid, e))
def merge_exported(self, tasks): """Merges data reported by task. This is primarily used to get real urgency, maybe something else in the future.""" out = util.run_command(["task", "rc.json.array=1", "export"]) _tasks = {} for em in json.loads(out): _tasks[em["uuid"]] = em for idx, task in enumerate(tasks): if task["uuid"] not in _tasks: util.log("Warning: task {0} not exported by TaskWarrior.", task["uuid"]) continue _task = _tasks[task["uuid"]] if "urgency" in _task: tasks[idx]["urgency"] = float(_task["urgency"]) return tasks
def update_task(self, task_id, properties): ts = int(time.time()) # Use fresh data for missing fields, to prevent status changes etc. params = self.get_task_info(task_id) params.update(properties) params["modified"] = ts util.log("Task update: {0}", params) cur = self.conn.cursor() cur.execute( "UPDATE tasks SET modified = ?, project = ?, summary = ?, priority = ?, status = ?, description = ? WHERE id = ?", (params["modified"], params["project"], params["summary"], params["priority"], params["status"], params["description"], task_id)) cur.execute( "INSERT INTO changes (task_id, ts, status, duration) VALUES (?, ?, ?, ?)", (task_id, ts, params["status"], 0)) self.conn.commit()
def set_task_status(self, task_id, status): util.log("Changing status of task {0} to {1}.", task_id, status) cur = self.conn.cursor() ts = int(time.time()) last = self.get_last_change(task_id) if last is not None: if status == last["status"]: return # no changes duration = ts - int(last["ts"]) cur.execute("UPDATE changes SET duration = ? WHERE id = ?", (duration, last["id"])) util.log( "Task {0} spent {1} seconds in status {2}, switching to {3}.", task_id, duration, last["status"], status) cur.execute("UPDATE tasks SET modified = ?, status = ? WHERE id = ?", (ts, status, task_id)) cur.execute( "INSERT INTO changes (task_id, ts, status) VALUES (?, ?, ?)", (task_id, ts, status)) self.conn.commit()
def load_data(self, database): """Reads the database file, parses it and returns a list of Task object instances, which contain all parsed data (values are unicode). This home-made parser returns raw timestamps, while 'task export' returns formatted UTC based dates which are hard to convert to timestamps to calculate activity duration, etc. TODO: find out a way to convert dates like '20130201T103640Z' to UNIX timestamp or at least a datetime. """ _start = time.time() if not os.path.exists(database): util.log("Database {0} does not exist.", database) return {} with open(database, "rb") as f: raw_data = f.read() tasks = [] for line in raw_data.rstrip().split("\n"): if not line.startswith("[") or not line.endswith("]"): raise ValueError("Unsupported file format " \ "in {0}".format(database)) task = Task() for kw in shlex.split(line[1:-1]): if ":" not in kw: util.log("Warning: malformed database token: {0}", kw) continue k, v = kw.split(":", 1) v = v.replace("\/", "/") # FIXME: must be a better way v = v.decode("utf-8") if k == "tags": v = v.split(",") task[k] = v tasks.append(task) tasks = self.merge_exported(tasks) util.log("Task database read in {0} seconds.", time.time() - _start) return tasks
def on_toggle(self): util.log("on_toggle not handled")
def start_task(self, task_id): util.log("Starting task {0}.", task_id) util.run_command(["task", task_id, "start"])
def get_tasks(self): if self._tasks is None: util.log("Reloading tasks.") self._tasks = self.load_tasks() return self._tasks
def handle(*args, **kwargs): util.log("Got signal USR1, showing the search dialog.") self.search_dialog.show_all()
def stop_task(self, task_id): util.log("Stopping task {0}.", task_id) util.run_command(["task", task_id, "stop"], fail=False)
def finish_task(self, task_id): util.log("Finishing task {0}.", task_id) util.run_command(["task", task_id, "stop"], fail=False) util.run_command(["task", task_id, "done"])
def on_task_selected(self, task): util.log("task selected: %s" % task) if task: dialogs.Properties.show_task(self.database, task)
def on_pull(self): util.log("on_pull not handled")
def restart_task(self, task_id): util.log("Restarting task {0}.", task_id) util.run_command(["task", task_id, "mod", "status:pending"]) util.run_command(["task", task_id, "start"])
def on_task_selected(self, task): util.log("on_task_selected not handled, %s" % task)
def on_stop_all(self): util.log("on_stop_all not handled")
def on_add_task(self): util.log("on_add_task not handled")
def setup_icon(self): util.log("WARNING: setup_icon not implimented")
def on_quit(self): util.log("on_quit not handled")