tools: added -i charset support to btardump
[barry.git] / src / vtodo.cc
blob628f52c54f80c512c1910d77742c665bece373f1
1 //
2 // \file vtodo.cc
3 // Conversion routines for vtodos (VCALENDAR, etc)
4 //
6 /*
7 Copyright (C) 2008-2009, Nicolas VIVIEN
8 Copyright (C) 2006-2010, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "vtodo.h"
24 //#include "trace.h"
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <glib.h>
28 #include <string.h>
29 #include <sstream>
31 namespace Barry { namespace Sync {
33 //////////////////////////////////////////////////////////////////////////////
34 // Utility functions
36 namespace {
37 static void ToLower(std::string &str)
39 size_t i = 0;
40 while( i < str.size() ) {
41 str[i] = tolower(str[i]);
42 i++;
47 //////////////////////////////////////////////////////////////////////////////
48 // vTodo
50 vTodo::vTodo(vTimeConverter &vtc)
51 : m_vtc(vtc)
52 , m_gTodoData(0)
56 vTodo::~vTodo()
58 if( m_gTodoData ) {
59 g_free(m_gTodoData);
63 bool vTodo::HasMultipleVTodos() const
65 int count = 0;
66 b_VFormat *format = const_cast<b_VFormat*>(Format());
67 GList *attrs = format ? b_vformat_get_attributes(format) : 0;
68 for( ; attrs; attrs = attrs->next ) {
69 b_VFormatAttribute *attr = (b_VFormatAttribute*) attrs->data;
70 if( strcasecmp(b_vformat_attribute_get_name(attr), "BEGIN") == 0 &&
71 strcasecmp(b_vformat_attribute_get_nth_value(attr, 0), "VTODO") == 0 )
73 count++;
76 return count > 1;
80 // Main conversion routine for converting from Barry::Task to
81 // a vTodo string of data.
82 const std::string& vTodo::ToTask(const Barry::Task &task)
84 // Trace trace("vTodo::ToTask");
85 std::ostringstream oss;
86 task.Dump(oss);
87 // trace.logf("ToTask, initial Barry record: %s", oss.str().c_str());
89 // start fresh
90 Clear();
91 SetFormat( b_vformat_new() );
92 if( !Format() )
93 throw ConvertError("resource error allocating vformat");
95 // store the Barry object we're working with
96 m_BarryTask = task;
98 // begin building vCalendar data
99 AddAttr(NewAttr("PRODID", "-//OpenSync//NONSGML Barry Task Record//EN"));
100 AddAttr(NewAttr("BEGIN", "VTODO"));
101 AddAttr(NewAttr("SEQUENCE", "0"));
102 AddAttr(NewAttr("SUMMARY", task.Summary.c_str()));
103 AddAttr(NewAttr("DESCRIPTION", task.Notes.c_str()));
104 AddAttr(NewAttr("CATEGORIES", ToStringList(task.Categories).c_str()));
106 // Status
107 if (task.StatusFlag == Barry::Task::InProgress)
108 AddAttr(NewAttr("STATUS", "IN-PROCESS"));
109 else if (task.StatusFlag == Barry::Task::Completed)
110 AddAttr(NewAttr("STATUS", "COMPLETED"));
111 else if (task.StatusFlag == Barry::Task::Deferred)
112 AddAttr(NewAttr("STATUS", "CANCELLED"));
113 else if (task.StatusFlag == Barry::Task::Waiting)
114 AddAttr(NewAttr("STATUS", "NEEDS-ACTION"));
116 // Priority
117 if (task.PriorityFlag == Barry::Task::High)
118 AddAttr(NewAttr("PRIORITY", "3"));
119 else if (task.PriorityFlag == Barry::Task::Normal)
120 AddAttr(NewAttr("PRIORITY", "5"));
121 else
122 AddAttr(NewAttr("PRIORITY", "7"));
124 // StartTime
125 if( task.StartTime ) {
126 AddAttr(NewAttr("DTSTART",
127 m_vtc.unix2vtime(&task.StartTime).c_str()));
130 // DueTime DueFlag
131 if( task.DueDateFlag ) {
132 AddAttr(NewAttr("DUE",
133 m_vtc.unix2vtime(&task.DueTime).c_str()));
136 // FIXME - add a truly globally unique "UID" string?
138 AddAttr(NewAttr("END", "VTODO"));
140 // generate the raw VTODO data
141 m_gTodoData = b_vformat_to_string(Format(), VFORMAT_TODO_20);
142 m_vTodoData = m_gTodoData;
144 // trace.logf("ToTask, resulting vtodo data: %s", m_vTodoData.c_str());
145 return m_vTodoData;
148 // Main conversion routine for converting from vTodo data string
149 // to a Barry::Task object.
150 const Barry::Task& vTodo::ToBarry(const char *vtodo, uint32_t RecordId)
152 using namespace std;
154 // Trace trace("vTodo::ToBarry");
155 // trace.logf("ToBarry, working on vtodo data: %s", vtodo);
157 // we only handle vTodo data with one vtodo block
158 if( HasMultipleVTodos() )
159 throw ConvertError("vCalendar data contains more than one VTODO block, unsupported");
161 // start fresh
162 Clear();
164 // store the vTodo raw data
165 m_vTodoData = vtodo;
167 // create format parser structures
168 SetFormat( b_vformat_new_from_string(vtodo) );
169 if( !Format() )
170 throw ConvertError("resource error allocating vtodo");
172 string summary = GetAttr("SUMMARY", "/vtodo");
173 // trace.logf("SUMMARY attr retrieved: %s", summary.c_str());
174 if( summary.size() == 0 ) {
175 summary = "<blank subject>";
176 // trace.logf("ERROR: bad data, blank SUMMARY: %s", vtodo);
179 string notes = GetAttr("DESCRIPTION", "/vtodo");
180 // trace.logf("DESCRIPTION attr retrieved: %s", notes.c_str());
182 string status = GetAttr("STATUS", "/vtodo");
183 // trace.logf("STATUS attr retrieved: %s", status.c_str());
185 string priority = GetAttr("PRIORITY", "/vtodo");
186 // trace.logf("PRIORITY attr retrieved: %s", priority.c_str());
188 string start = GetAttr("DTSTART", "/vtodo");
189 // trace.logf("DTSTART attr retrieved: %s", start.c_str());
191 string due = GetAttr("DUE", "/vtodo");
192 // trace.logf("DUE attr retrieved: %s", due.c_str());
196 // Now, run checks and convert into Barry object
199 // FIXME - we are assuming that any non-UTC timestamps
200 // in the vcalendar record will be in the current timezone...
201 // This is wrong! fix this later.
203 // Also, we current ignore any time zone
204 // parameters that might be in the vcalendar format... this
205 // must be fixed.
208 Barry::Task &rec = m_BarryTask;
209 rec.SetIds(Barry::Task::GetDefaultRecType(), RecordId);
211 // Categories
213 rec.Categories = GetValueVector("CATEGORIES","/vtodo");
215 // SUMMARY & DESCRIPTION fields
216 rec.Summary = summary;
217 rec.Notes = notes;
219 // STATUS field
220 if (status.size()) {
221 ToLower(status);
223 const char *s = status.c_str();
225 if (strstr(s, "in-process"))
226 rec.StatusFlag = Barry::Task::InProgress;
227 else if (strstr(s, "completed"))
228 rec.StatusFlag = Barry::Task::Completed;
229 else if (strstr(s, "cancelled"))
230 rec.StatusFlag = Barry::Task::Deferred;
231 else if (strstr(s, "needs-action"))
232 rec.StatusFlag = Barry::Task::Waiting;
233 else
234 rec.StatusFlag = Barry::Task::NotStarted;
237 // PRIORITY field
238 if (priority.size()) {
239 ToLower(priority);
241 const char *s = priority.c_str();
243 const int val = atoi(s);
245 if (val < 4)
246 rec.PriorityFlag = Barry::Task::High;
247 else if (val < 7)
248 rec.PriorityFlag = Barry::Task::Normal;
249 else
250 rec.PriorityFlag = Barry::Task::Low;
254 // STARTTIME & DUETIME
255 if (start.size()) {
256 rec.StartTime = m_vtc.vtime2unix(start.c_str());
259 if (due.size()) {
260 rec.DueDateFlag = true;
261 rec.DueTime = m_vtc.vtime2unix(due.c_str());
264 std::ostringstream oss;
265 m_BarryTask.Dump(oss);
266 // trace.logf("ToBarry, resulting Barry record: %s", oss.str().c_str());
267 return m_BarryTask;
270 // Transfers ownership of m_gTaskData to the caller.
271 char* vTodo::ExtractVTodo()
273 char *ret = m_gTodoData;
274 m_gTodoData = 0;
275 return ret;
278 void vTodo::Clear()
280 vBase::Clear();
281 m_vTodoData.clear();
282 m_BarryTask.Clear();
284 if( m_gTodoData ) {
285 g_free(m_gTodoData);
286 m_gTodoData = 0;
290 }} // namespace Barry::Sync