summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/taskmanager.cc265
-rw-r--r--src/taskmanager.h185
-rw-r--r--src/tasktree.cc213
-rw-r--r--src/tasktree.h69
4 files changed, 732 insertions, 0 deletions
diff --git a/src/taskmanager.cc b/src/taskmanager.cc
new file mode 100644
index 0000000..590c5b8
--- /dev/null
+++ b/src/taskmanager.cc
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * task.cc
+ *
+ * Fri Feb 24 08:16:30 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Munia 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 Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "taskmanager.h"
+
+#include <stdio.h>
+
+#define ROOT_ID 0
+#define LOSTFOUND_ID 1
+#define FINISHED_ID 2
+#define BACKLOG_ID 3
+#define PROJECTS_ID 4
+#define FIRST_TASK_ID 10
+
+TaskManager::TaskManager() {
+ idCount = FIRST_TASK_ID;
+
+ task_t t;
+ t.title = "root";
+ tree.insertAsChild(0, ROOT_ID, t);
+
+ t.title = "Finished";
+ tree.insertAsChild(ROOT_ID, FINISHED_ID, t);
+
+ t.title = "Backlog";
+ tree.insertAsChild(ROOT_ID, FINISHED_ID, t);
+
+ t.title = "Lost+Found";
+ tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t);
+
+ t.title = "Projects";
+ tree.insertAsChild(ROOT_ID, PROJECTS_ID, t);
+}
+
+TaskManager::~TaskManager() {
+}
+
+taskid_t TaskManager::createId() {
+ return idCount++;
+}
+
+task_t TaskManager::createTask() {
+ task_t t;
+
+ t.id = createId();
+
+ return t;
+}
+
+TaskIdList TaskManager::moveTask(taskid_t id, taskid_t to)
+ throw (std::exception) {
+ TaskIdList affectedTasks;
+
+ try {
+ affectedTasks = tree.move(id, to);
+ goto finish;
+ }
+ catch (std::exception& e) {
+
+ }
+
+ finish:
+ return affectedTasks;
+}
+
+TaskIdList TaskManager::deleteTask(taskid_t id)
+ throw (std::exception) {
+ TaskIdList affectedTasks;
+
+ try {
+ affectedTasks = tree.remove(id);
+ goto finish;
+ }
+ catch(std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return affectedTasks;
+}
+
+TaskIdList TaskManager::updateTask(taskid_t id, task_t t)
+ throw (std::exception) {
+
+ TaskIdList affectedTasks;
+
+ try {
+ affectedTasks = tree.updateData(id, t);
+ goto finish;
+ }
+ catch (std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return affectedTasks;
+}
+
+TaskIdList TaskManager::addTask(task_t t, taskid_t id, taskid_t parentid)
+ throw (std::exception) {
+ TaskIdList affectedTasks;
+
+ try {
+ affectedTasks = tree.insertAsChild(parentid, id, t);
+ goto finish;
+ }
+ catch (std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return affectedTasks;
+}
+
+/*
+TaskIdList TaskManager::ancestorList(taskid_t id)
+ throw (std::exception) {
+ TaskIdList ancestors;
+
+ try {
+ ancestors = tree.ancestorList(id);
+ goto finish;
+ }
+ catch (std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return ancestors;
+}
+*/
+
+#if 0
+TaskList tasklist;
+
+task_t create_task(std::string title, std::string desc) {
+
+ task_t t;
+ t.parent_id = current_id_count();
+ t.title = title;
+ t.desc = desc;
+ t.id = id_count; id_count++;
+
+ return t;
+}
+
+TaskList load_tasklist_from_file(std::string file) {
+ TaskList list;
+
+ // create MuniaDb class which handles tasks, db-flush and db-init.
+
+ return list;
+}
+
+bool save_tasklist_to_file(TaskList list, std::string file) {
+
+ FILE* fp;
+
+ if(! (fp = fopen(file.c_str(), "w"))) {
+ return false;
+ }
+
+ if(!fprintf(fp, "<tasklist>\n")) {
+ fclose(fp);
+ return false;
+ }
+
+ TaskList::iterator it;
+ for(it = tasklist.begin(); it != tasklist.end(); it++) {
+ task_t t = *it;
+ int r = 1;
+
+// printf("Flushing task %d\n", t.id);
+
+ r |= fprintf(fp, " <task id=\"%d\" parent_id=\"%d\">\n", t.id, t.parent_id);
+ r |= fprintf(fp, " <title>%s</title>\n", xml_encode(t.title).c_str());
+ r |= fprintf(fp, " <desc>%s</desc>\n", xml_encode(t.desc).c_str());
+ r |= fprintf(fp, " </task>)\n");
+
+ if(!r) {
+ fclose(fp);
+ return false;
+ }
+ }
+
+ if(!fprintf(fp, "</tasklist>\n")) {
+ fclose(fp);
+ return false;
+ }
+
+ fclose(fp);
+ return true;
+}
+
+static void delete_task(task_t t, TaskList& graveyard);
+
+static void delete_children(task_t t, TaskList& graveyard) {
+ TaskList::iterator it;
+ for(it = tasklist.begin(); it != tasklist.end(); it++) {
+ if(it->parent_id == t.id) {
+ delete_task(*it, graveyard);
+ }
+ }
+}
+
+
+static void delete_task(task_t t, TaskList& graveyard) {
+
+ TaskList::iterator it;
+ for(it = tasklist.begin(); it != tasklist.end(); it++) {
+ if(it->id == t.id) {
+ break;
+ }
+ }
+
+ if(it != tasklist.end()) {
+ graveyard.push_back(*it);
+ delete_children(*it, graveyard);
+ }
+
+}
+
+void delete_task(int id, TaskList& graveyard) {
+ task_t t;
+ t.id = id;
+ delete_task(t, graveyard);
+
+ for(TaskList::iterator it = graveyard.begin();
+ it != graveyard.end(); it++) {
+
+ for(TaskList::iterator it_tl = tasklist.begin();
+ it_tl != tasklist.end(); it_tl++) {
+
+ if(it_tl->id == it->id) {
+ tasklist.erase(it_tl);
+ break;
+ }
+ }
+ }
+}
+#endif
diff --git a/src/taskmanager.h b/src/taskmanager.h
new file mode 100644
index 0000000..fb8c965
--- /dev/null
+++ b/src/taskmanager.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * taskmanager.h
+ *
+ * Fri Feb 24 08:16:29 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng & Jonas Suhr Christensen
+ * deva@aasimon.org & jsc@umbraculum.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Munia 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 Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __MUNIA_TASKMANAGER_H__
+#define __MUNIA_TASKMANAGER_H__
+
+#include <list>
+#include <string>
+#include <stdio.h>
+#include <exception>
+
+#include "task.h"
+#include "tasktree.h"
+
+class TaskManager {
+public:
+ TaskManager();
+ ~TaskManager();
+ task_t createTask();
+
+ TaskIdList addTask(task_t t, taskid_t, taskid_t parentid) throw (std::exception);
+ TaskIdList updateTask(taskid_t id, task_t task) throw (std::exception);
+ TaskIdList deleteTask(taskid_t id) throw (std::exception);
+ TaskIdList moveTask(taskid_t id, taskid_t newParent) throw (std::exception);
+
+private:
+ // TaskIdList ancestorList(taskid_t task);
+ taskid_t createId();
+
+ TaskTree tree;
+ taskid_t idCount;
+};
+
+#if 0
+
+/*
+Task:
+ id
+ subtasks
+// tags
+ title
+ description
+// primary_assignment
+// secondary_assignment
+
+
+Protocol:
+
+Server -> client:
+ update [id] [title] [description];
+ move [id] [x] [y];
+ add [id] [title] [description] [x] [y];
+ del [id]
+
+Client -> server:
+ update [id] [title] [description];
+ move [id] [x] [y];
+ add [title] [description] [x] [y];
+ del [id]
+
+title and description are " encapsulated utf-8 string with " escaped with a backslash.
+x and y are integers as strings
+id are an integer as a string
+ */
+
+/*
+typedef struct {
+ int x, y;
+ int id;
+ std::string title;
+ std::string desc;
+} task_t;
+*/
+/*
+protocol:
+ add_task title description parent_id
+ del_task id
+ update_task id title description
+ move_task id parent
+ copy_task id parent
+*/
+
+
+
+//typedef std::list<task_t> TaskList;
+
+class CompareByParentid {
+public:
+ bool operator()(const task_t &a, const task_t &b) const {
+ return a.parent_id < b.parent_id;
+ }
+};
+
+
+
+
+class TaskList : public std::list<task_t>{
+public:
+ TaskList() {}
+ ~TaskList(){}
+
+ void insert(task_t t) {
+ if(t.id == t.parent_id) return;
+ printf("inserting task %d with parent %d\n", t.id, t.parent_id);
+
+ if(t.parent_id == -1) {
+ std::list<task_t>::push_front(t);
+ return;
+ }
+
+ std::list<task_t>::iterator it;
+ for(it = begin(); it != end(); ++it) {
+ printf("\tcomparing %d and %d\n", t.parent_id, it->id);
+ if(t.parent_id == it->id) {
+ break;
+ }
+ }
+ assert(it != end());
+
+ std::list<task_t>::insert(++it, t);
+
+// std::list<task_t>::push_back(t);
+// std::list<task_t>::sort(CompareByParentid());
+
+ }
+
+ void move(task_t t) {
+ std::list<task_t>::iterator it;
+ for(it = begin(); it != end(); it++) {
+ if(t.id == it->id) {
+ break;
+ }
+ }
+ assert(it != end());
+ // if(it != end()) {
+ std::list<task_t>::erase(it);
+ // }
+ insert(t);
+ }
+
+ void push_back(task_t t) {
+ insert(t);
+ }
+
+private:
+ std::list<task_t> list;
+};
+
+
+extern TaskList tasklist;
+
+//typedef std::priority_queue<task_t, std::vector<task_t>, CompareByParentid> TaskList;
+
+task_t create_task(std::string title, std::string desc,
+ /*int x, int y*/ int parent_id);
+
+TaskList load_tasklist_from_file(std::string file);
+bool save_tasklist_to_file(TaskList t, std::string file);
+#endif
+
+#endif/*__MUNIA_TASK_H__*/
diff --git a/src/tasktree.cc b/src/tasktree.cc
new file mode 100644
index 0000000..e44efee
--- /dev/null
+++ b/src/tasktree.cc
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * tasktree.cc
+ *
+ * Tue Mar 27 11:07:48 CEST 2012
+ * Copyright 2012 Jonas Suhr Christensen
+ * jsc@umbraculum.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Munia 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 Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "tasktree.h"
+
+#include "debug.h"
+
+
+TaskTree::TaskTree() {
+ root = NULL;
+}
+
+TaskTree::~TaskTree() {
+ // cleanup tree
+}
+
+TaskIdList TaskTree::insertAsChild(taskid_t parentid, taskid_t id, task_t data)
+ throw (std::exception) {
+
+ TaskIdList affectedNodes;
+
+ // Initialize
+ if(!root) {
+ node_t* node = createNode(id);
+ root = node;
+
+ affectedNodes.push_back(id);
+
+ goto finish;
+ }
+
+ try {
+ node_t* parent = id2node.at(parentid);
+ node_t* child = createNode(id);
+ child->data = data;
+ insertChild(parent, child);
+
+ affectedNodes.push_back(parentid);
+ affectedNodes.push_back(id);
+
+ goto finish;
+ }
+ catch(std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return affectedNodes;
+}
+
+TaskIdList TaskTree::remove(taskid_t id)
+ throw (std::exception) {
+ //todo: move all childrin to lost+found
+ WARN(tasktree, "Feature not implemneted yet\n");
+ TaskIdList affectedNodes;
+ return affectedNodes;
+}
+
+TaskIdList TaskTree::move(taskid_t id, taskid_t toid)
+ throw (std::exception) {
+
+ TaskIdList affectedNodes;
+
+ try {
+ node_t* child = id2node.at(id);
+ node_t* newparent = id2node.at(toid);
+
+ if(!child->parent) {
+ throw std::exception();
+ }
+
+ child->parent->children.remove(child);
+ newparent->children.push_back(child);
+
+ affectedNodes.push_back(id);
+ affectedNodes.push_back(child->parent->id);
+ affectedNodes.push_back(toid);
+
+ goto finish;
+ }
+ catch(std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return affectedNodes;
+}
+
+TaskIdList TaskTree::updateData(taskid_t id, task_t t)
+ throw (std::exception) {
+
+ TaskIdList affectedNodes;
+
+ try {
+ node_t* node = id2node.at(id);
+ node->data = t;
+
+ affectedNodes.push_back(id);
+ goto finish;
+ }
+ catch(std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return affectedNodes;
+}
+
+task_t TaskTree::getData(taskid_t id)
+ throw (std::exception) {
+
+ task_t t;
+
+ try {
+ node_t* node = id2node.at(id);
+ t = node->data;
+ goto finish;
+ }
+ catch(std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return t;
+}
+
+TaskIdList TaskTree::ancestorList(taskid_t id)
+ throw (std::exception) {
+
+ TaskIdList ancestors;
+
+ try {
+ node_t* current = id2node.at(id);
+ while(current->parent) {
+ ancestors.push_back(current->parent->id);
+ current = current->parent;
+ }
+ goto finish;
+ }
+ catch(std::exception& e) {
+ throw e;
+ }
+
+ finish:
+ return ancestors;
+}
+
+node_t* TaskTree::createNode(taskid_t id) {
+ node_t* node = new node_t();
+ node->parent = NULL;
+ node->id = id;
+ id2node[id] = node;
+ return node;
+}
+
+void TaskTree::insertChild(node_t* parent, node_t* child) {
+ parent->children.push_back(child);
+ child->parent = parent;
+}
+
+
+
+#ifdef TEST_TASKTREE
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+#include <exception>
+
+TEST_BEGIN;
+
+TaskTree tree;
+
+task_t t;
+try {
+ tree.insertAsChild(-1, t);
+ }
+ catch(std::exeception& e) {
+ }
+
+// TODO: Put some testcode here (see test.h for usable macros).
+TEST_TRUE(false, "No tests yet!");
+
+TEST_END;
+
+#endif/*TEST_TASKTREE*/
diff --git a/src/tasktree.h b/src/tasktree.h
new file mode 100644
index 0000000..9a3a45f
--- /dev/null
+++ b/src/tasktree.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * tasktree.h
+ *
+ * Tue Mar 27 11:07:48 CEST 2012
+ * Copyright 2012 Jonas Suhr Christensen
+ * jsc@umbraculum.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Munia 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 Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __MUNIA_TASKTREE_H__
+#define __MUNIA_TASKTREE_H__
+
+#include <list>
+#include <map>
+#include <exception>
+
+#include "task.h"
+
+typedef struct node node_t;
+
+typedef std::list<struct node*> NodeList;
+
+struct node {
+ taskid_t id;
+ node_t* parent;
+ task_t data;
+ NodeList children;
+};
+
+class TaskTree {
+public:
+ TaskTree();
+ ~TaskTree();
+
+ TaskIdList insertAsChild(taskid_t parentid, taskid_t id, task_t data) throw (std::exception);
+ TaskIdList remove(taskid_t id) throw (std::exception);
+ TaskIdList move(taskid_t id, taskid_t newParentId) throw (std::exception);
+ TaskIdList updateData(taskid_t id, task_t t) throw (std::exception);
+ task_t getData(taskid_t id) throw (std::exception);
+
+ TaskIdList ancestorList(taskid_t id) throw (std::exception);
+
+private:
+ node_t* createNode(taskid_t id);
+ void insertChild(node_t* parent, node_t* child);
+
+ node_t* root;
+ std::map<int, node_t*> id2node;
+};
+
+#endif/*__MUNIA_TASKTREE_H__*/