[Evolution-hackers] Comments on a patch for todo-conduit.c - categories



(cc'd to gnome-pilot list - this is an evolution conduit)

For quite a while, I've really needed the categories in the Tasks list to sync
between my PalmOS PDA and Evolution. I finally spent some time getting it
*mostly* working. Attached is the patch. I'm looking for comments on how it
works and some help to get it completely working. It's 95% of the way there.

The main problems: when using e_categories_add(), I can't get the categories to
show up in the task-editor page or in the search bar until the Evolution client
is restarted (data server need not be). The search bar shouldn't be too hard (I
think), but I couldn't figure out why the task-editor page wouldn't show the
new categories.

Here's how it basically works:
- Copy from pilot
  - done in the function add_record
  - If the category from the PDA doesn't exist in the eds, I add it using
    e_categories_add()
  - I set the category of that task to just the category from the PDA
  - Problems:
    - UI doesn't see categories addition until restart of evolution
    - if a syncrhonize is done, it's *possible* to lose categories. I tried to
      remedy this by using e_cal_component_get_categories_list, but it wasn't
      working properly and memory was getting messed up (even if I didn't free
      anything). Unknown as to why.
- Copy to pilot
  - mainly uses local_record_from_comp
  - dlp_ReadRecordById doesn't work in this case - don't know why, but it
    doesn't
  - We do have the ToDoAppInfo, which holds the CategoryAppInfo
  - if 1 of the categories from Evolution's Tasks matches (string comparison)
    a category from the PDA, set the category to that index
  - if we find no matches between Evolution's categories and the PDA's, then
    see if there's an empty space in the category list. A space is empty if the
    strlen() of the name is 0. If space is empty, copy the first 15 characters
    of Evolution's category into the PDA category space and set the ID to be
    a PC-added category (starts at 128 according to the API).
  - if no match is found, but no space is empty, then the category is set to
    0, which is the Unfiled category (this is how the PalmOS DB seems to work)
  - Since we're modifying the ToDoAppInfo struct, we need to write this back
    to the PalmOS. This is done in post_sync() using dlp_WriteAppBlock.
- Synchronize
  - this is a combination of the two. Gnome-Pilot seems to take care of whether
    to call add_record or replace_record or delete_record where appropriate.
  - I have not changed compare or match - they seem to be working just fine.

A small change outside of categories: Priorites 2 and 3 are "normal"
priorities. Normal should be the most common priority, and since we don't have
a 1-to-1 matching between priority types, I think this makes sense. (At least,
I was wondering why I had so many "High" priorities - I'd rather switch to a
5-layer priority schedule, but I know Exchange uses the same as Evolution's).

I'm looking for help on how to solve the problems above. I'm also looking for
comments on what people think of the category matching/syncrhonizing.

An improvement would to have specific Evolution categories designated as
"Pilot" categories, assuming that pilot support was built-in. Maybe an EPlugin
would be good for this. This is probably beyond the time I have now, though.

Let me know what you think,
Nathan Owens



		
__________________________________ 
Do you Yahoo!? 
Yahoo! Mail - Find what you need with new enhanced search. 
http://info.mail.yahoo.com/mail_250
--- evolution-2.3.1/calendar/conduits/todo/todo-conduit.c	2004-08-25 22:12:07.000000000 -0400
+++ work_evo-2.3.1/calendar/conduits/todo/todo-conduit.c	2005-06-07 18:40:41.000000000 -0400
@@ -31,6 +31,7 @@
 #include <libecal/e-cal-types.h>
 #include <libecal/e-cal.h>
 #include <libecal/e-cal-time-util.h>
+#include <libedataserver/e-categories.h>
 #include <pi-source.h>
 #include <pi-socket.h>
 #include <pi-dlp.h>
@@ -82,6 +83,8 @@ struct _EToDoLocalRecord {
 	struct ToDo *todo;
 };
 
+int lastDesktopUniqueID;
+
 static void
 todoconduit_destroy_record (EToDoLocalRecord *local) 
 {
@@ -566,6 +569,55 @@ local_record_to_pilot_record (EToDoLocal
 }
 
 /*
+ * Adds a category to the category app info structure (name and ID),
+ * sets category->renamed[i] to true if possible to rename.
+ * 
+ * This will be packed and written to the app info block during post_sync.
+ */
+ 
+static int
+add_category_if_possible(char *cat_to_add, struct CategoryAppInfo *category)
+{
+	int i, j;
+	int retval = 0; // 0 is the Unfiled category
+	
+	for(i=0; i<16; i++){
+		// if strlen is 0, then the category is empty
+		// the PalmOS doesn't let 0-length strings for
+		// categories
+		if(strlen(category->name[i]) == 0){
+			int cat_to_add_len = strlen(cat_to_add);
+			retval = i;
+			
+			/* only 15 characters for category, 16th is
+			 * '\0' can't do direct mem transfer due to
+			 * declaration type
+			 */
+			for(j=0; j<cat_to_add_len; j++)
+				category->name[i][j] = cat_to_add[j];
+
+			for(j=cat_to_add_len; j<16; j++)
+				category->name[i][j] = '\0';
+			
+			category->ID[i] = lastDesktopUniqueID;
+			lastDesktopUniqueID++;
+			
+			category->renamed[i] = TRUE;
+			
+			LOG(g_message("*** adding category '%s', ID %d ***",
+				category->name[i], category->ID[i]));
+			break;
+		}
+	}
+	
+	if(retval == 0){
+		LOG(g_message("*** not adding category - category list already full ***"));
+	}
+	
+	return retval;
+}
+
+/*
  * converts a ECalComponent object to a EToDoLocalRecord
  */
 static void
@@ -605,7 +657,42 @@ local_record_from_comp (EToDoLocalRecord
 					ctxt->dbi->db_handle,
 					local->local.ID, &record, 
 					NULL, NULL, NULL, &cat) > 0) {
-			local->local.category = cat;			
+			local->local.category = cat;
+		}
+	}
+	
+	/*
+	 * Grab category from existing category list in ctxt->ai.category
+	 */
+	if(local->local.category == 0){
+		GSList *categ_list_head, *categ_list_cur;
+		int cat = -1;
+		int i;
+		
+		e_cal_component_get_categories_list(comp, &categ_list_head);
+		
+		categ_list_cur = categ_list_head;
+		while (categ_list_cur && cat == -1)
+		{	
+			for(i=0; i<16; i++){
+				if(strcmp((char *)categ_list_cur->data,
+					  ctxt->ai.category.name[i]) == 0){
+					cat = i;
+					break;
+				}
+			}
+			
+			categ_list_cur = g_slist_next(categ_list_cur);
+		}
+		
+		if(cat != -1){
+			local->local.category = cat;
+		}
+		else{
+			local->local.category =
+				add_category_if_possible(
+					(char *)(categ_list_head->data),
+					&(ctxt->ai.category));
 		}
 	}
 
@@ -682,6 +769,8 @@ local_record_from_uid (EToDoLocalRecord 
 	GError *error = NULL;
 
 	g_assert(local!=NULL);
+	
+	LOG(g_message("local_record_from_uid\n"));
 
 	if (e_cal_get_object (ctxt->client, uid, NULL, &icalcomp, &error)) {
 		comp = e_cal_component_new ();
@@ -711,7 +800,8 @@ static ECalComponent *
 comp_from_remote_record (GnomePilotConduitSyncAbs *conduit,
 			 GnomePilotRecord *remote,
 			 ECalComponent *in_comp,
-			 icaltimezone *timezone)
+			 icaltimezone *timezone,
+			 struct ToDoAppInfo *ai)
 {
 	ECalComponent *comp;
 	struct ToDo todo;
@@ -721,6 +811,7 @@ comp_from_remote_record (GnomePilotCondu
 	icaltimezone *utc_zone;
 	int priority;
 	char *txt;
+	char *category;
 	
 	g_return_val_if_fail (remote != NULL, NULL);
 
@@ -797,7 +888,7 @@ comp_from_remote_record (GnomePilotCondu
 		priority = 3;
 		break;
 	case 2:
-		priority = 4;
+		priority = 5;
 		break;
 	case 3:
 		priority = 5;
@@ -816,6 +907,20 @@ comp_from_remote_record (GnomePilotCondu
 		e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PRIVATE);
 	else
 		e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PUBLIC);
+	
+	
+	// set the category properly
+	category = ai->category.name[remote->category];
+	
+	
+	// TODO The Tasks editor page and search bar are not updated until
+	// a restart of the evolution client
+	if(e_categories_exist(category) == FALSE){
+		// add if it doesn't exist
+		e_categories_add(category, NULL, NULL, TRUE);
+	}
+	
+	e_cal_component_set_categories(comp, category);
 
 	e_cal_component_commit_sequence (comp);
 	
@@ -964,6 +1069,8 @@ pre_sync (GnomePilotConduit *conduit,
 	}
 	unpack_ToDoAppInfo (&(ctxt->ai), buf, len);
 	g_free (buf);
+	
+	lastDesktopUniqueID = 128;
 
 	check_for_slow_setting (conduit, ctxt);
 	if (ctxt->cfg->sync_type == GnomePilotConduitSyncTypeCopyToPilot
@@ -980,6 +1087,26 @@ post_sync (GnomePilotConduit *conduit,
 {
 	GList *changed;
 	gchar *filename, *change_id;
+	unsigned char *buf;
+	int dlpRetVal, len;
+
+	buf = (unsigned char*)g_malloc (0xffff);
+	
+	len = pack_ToDoAppInfo (&(ctxt->ai), buf, 0xffff);
+	
+	dlpRetVal = dlp_WriteAppBlock (dbi->pilot_socket, dbi->db_handle, 
+			      (unsigned char *)buf, len);
+	
+	g_free (buf);
+			      
+	if (dlpRetVal < 0) {
+		WARN (_("Could not write pilot's ToDo application block"));
+		WARN ("dlp_WriteAppBlock(...) = %d", dlpRetVal);
+		gnome_pilot_conduit_error (conduit,
+					   _("Could not write pilot's ToDo application block"));
+		return -1;
+	}
+	
 
 	LOG (g_message ( "post_sync: ToDo Conduit v.%s", CONDUIT_VERSION ));
 
@@ -1179,7 +1306,7 @@ add_record (GnomePilotConduitSyncAbs *co
 
 	LOG (g_message ( "add_record: adding %s to desktop\n", print_remote (remote) ));
 
-	comp = comp_from_remote_record (conduit, remote, ctxt->default_comp, ctxt->timezone);
+	comp = comp_from_remote_record (conduit, remote, ctxt->default_comp, ctxt->timezone, &(ctxt->ai));
 
 	/* Give it a new UID otherwise it will be the uid of the default comp */
 	uid = e_cal_component_gen_uid ();
@@ -1209,7 +1336,7 @@ replace_record (GnomePilotConduitSyncAbs
 	LOG (g_message ("replace_record: replace %s with %s\n",
 			print_local (local), print_remote (remote)));
 
-	new_comp = comp_from_remote_record (conduit, remote, local->comp, ctxt->timezone);
+	new_comp = comp_from_remote_record (conduit, remote, local->comp, ctxt->timezone, &(ctxt->ai));
 	g_object_unref (local->comp);
 	local->comp = new_comp;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]