Re : [RFCT] (request for comment and testing ;-)



On 25.08.2004 19:29:57, manu wrote:
	Hi all,
I have a patch that implements relative dates (ie instead of specifying an interval of absolute dates you can say that you want to match from 15 days before the running date to the running date, or several months/years before...). I would like to know if some of you are interested by the feature and would like to test it (it is a patch that applies against CVS or any 2.2.x). BTW I think this feature would be more useful if coupled to a way to ask filters to be run every month/year or so, so that relative dates filtering will actually be used to do regular "clean-ups" of mailboxes.
Bye
Manu

And here is the patch ...
Bye
Manu
--- ../balsa-HEAD/balsa/libbalsa/filter.h	2004-05-11 12:24:47.000000000 -0600
+++ balsa/libbalsa/filter.h	2004-08-15 13:37:08.000000000 -0600
@@ -66,6 +66,19 @@
                     * matches if any subcondition matches. */
 } ConditionMatchType;
 
+typedef enum {
+    DATE_ABSOLUTE=0, /* Dates are absolute */
+    DATE_DAYS,     /* Offset units: days */
+                   /* MUST BE ONE !!*/
+    DATE_MONTHS,   /*               months */
+    DATE_YEARS     /*               years */
+} ConditionDateType;
+
+/* Special value for offsets to specify that you want the date
+   interval to be unbounded */
+
+#define DATE_INFTY 10000
+
 struct _LibBalsaCondition {
     gboolean negate; /* negate the result of the condition. */
     ConditionMatchType type;
@@ -91,8 +104,21 @@
         } regex;
         /* CONDITION_DATE */
 	struct {
-	    time_t date_low,date_high; /* for CONDITION_DATE            */
-                                       /* (date_high==0=>no high limit) */
+	    ConditionDateType dates_type; /* gives the significance of the 
+					     following fields */
+	    time_t date_low,date_high;    /* (date_high==0=>no high limit) */
+	    gint offset_low, offset_high; /* Offset relative to the current
+					     date, they are <=0 as in general
+					     you don't have mails in the future
+					     Special value to specify that
+					     you want your interval to be
+					     unbounded on one side:
+					     DATE_INFTY
+					  */
+	    /* Note: the offset in months and years will work like that:
+	       if the current date is Feb 15, 2004, then if offset_low=-2 and 
+	       offset_high is -1, and units are months, then the date interval
+	       is Dec 1, 2003 - Jan 31, 2004. */
 	} date;
         /* CONDITION_FLAG */
 	LibBalsaMessageFlag flags;
@@ -114,8 +140,6 @@
                                                  unsigned headers,
                                                  gchar *str,
                                                  gchar *user_header);
-LibBalsaCondition* libbalsa_condition_new_date(gboolean negated,
-                                               time_t *from, time_t *to);
 LibBalsaCondition* libbalsa_condition_new_bool_ptr(gboolean negated,
                                                    ConditionMatchType cmt,
                                                    LibBalsaCondition *left,
--- ../balsa-HEAD/balsa/libbalsa/filter.c	2004-07-09 08:14:27.000000000 -0600
+++ balsa/libbalsa/filter.c	2004-08-18 22:31:06.000000000 -0600
@@ -253,6 +253,116 @@
 
 /*--------- Filtering functions -------------------------------*/
 
+/* Calculation the correct date by being careful
+   with daylight saving time
+*/
+
+static time_t
+modified_mktime(struct tm * date)
+{
+    time_t result;
+
+    date->tm_isdst = 0;
+    result = mktime(date);
+    /* Check if the date corresponds to daylight summer time
+       If yes result is off by 1 hour==3600 sec.
+     */
+    if (date->tm_isdst>0) result -= 3600;
+    return result;
+}
+
+static time_t
+calc_absolute_date(ConditionDateType type, gint offset,
+		   time_t today, gboolean end)
+{
+    struct tm tmp;
+
+    /* Special value to indicate you don't want to bound the interval */
+    if (offset == DATE_INFTY)
+	return 0;
+    localtime_r(&today, &tmp);
+    tmp.tm_sec = 0;
+    tmp.tm_min = 0;
+    tmp.tm_hour = 0;
+
+    /* Do not worry about the overflows,
+       mktime takes care of that */
+    switch (type) {
+    case DATE_DAYS:
+	tmp.tm_mday += offset;
+	if (end)
+	    return modified_mktime(&tmp) + 24 * 3600-1;
+	else return modified_mktime(&tmp);
+    case DATE_MONTHS:
+	tmp.tm_mon += offset;
+	if (!end) {
+	    tmp.tm_mday = 1;
+	    return modified_mktime(&tmp);
+	}
+	tmp.tm_mon++;
+	tmp.tm_mday = 1;
+	/* We want to match until 23:59:59 */
+	return modified_mktime(&tmp)-1;
+    case DATE_YEARS:
+	tmp.tm_year += offset;
+	if (!end) {
+	    tmp.tm_mday = 1;
+	    tmp.tm_mon = 0;
+	    return modified_mktime(&tmp);
+	}
+	tmp.tm_mon = 11;
+	tmp.tm_mday = 31;
+	return modified_mktime(&tmp) + 24*3600-1;
+    case DATE_ABSOLUTE:
+	return (time_t) -1;
+    }
+    return (time_t) -1;
+}
+
+static gboolean
+prepare_condition_date(LibBalsaCondition * cond)
+{
+    switch (cond->type) {
+    case CONDITION_STRING:
+    case CONDITION_REGEX:
+    case CONDITION_FLAG:
+    case CONDITION_NONE:
+	return TRUE;
+    case CONDITION_DATE:
+	if (cond->match.date.dates_type == DATE_ABSOLUTE)
+	    return TRUE;
+        cond->match.date.date_low =
+	    calc_absolute_date(cond->match.date.dates_type,
+			       cond->match.date.offset_low,
+			       time(NULL),
+			       FALSE);
+        cond->match.date.date_high =
+	    calc_absolute_date(cond->match.date.dates_type,
+			       cond->match.date.offset_high,
+			       time(NULL),
+			       TRUE);
+	/* DEBUG STUFF, please leave it in place because
+	   those date manipulation are a real PITA,
+	   they could use more debug later :(
+	   localtime_r(&(cond->match.date.date_low), &tmp);
+	   g_print("Dates calculated: %d %d %d %d %d %d\n",tmp.tm_mday,tmp.tm_mon,tmp.tm_year, tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+	   localtime_r(&(cond->match.date.date_high), &tmp);
+	   g_print("Dates calculated: %d %d %d %d %d %d\n",tmp.tm_mday,tmp.tm_mon,tmp.tm_year, tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+	*/
+	return ((cond->match.date.date_low>=0) &&
+		(cond->match.date.date_high>=0));
+    case CONDITION_AND:
+    case CONDITION_OR:
+	return prepare_condition_date(cond->match.andor.left) &&
+	    prepare_condition_date(cond->match.andor.right);
+    }
+    /* To avoid warnings */
+    return FALSE;
+}
+
+/* Must be called before running filters because you need to recompute
+   dates in case the filters use relative ones.
+*/
 gint
 filters_prepare_to_run(GSList * filters)
 {
@@ -266,8 +376,13 @@
                                      _("Invalid filter: %s"),fil->name);
 	    ok=FALSE;
 	}
-	else if (!FILTER_CHKFLAG(fil,FILTER_COMPILED))
-	    ok=libbalsa_filter_compile_regexs(fil);
+	else {
+	    if (!FILTER_CHKFLAG(fil,FILTER_COMPILED))
+		ok=libbalsa_filter_compile_regexs(fil);
+	    /* Lookup all condition involving dates to compute
+	       absolute dates from relative offsets */
+	    ok = prepare_condition_date(fil->condition);
+	}
     }
 
     return ok;
--- ../balsa-HEAD/balsa/libbalsa/filter-funcs.c	2004-08-16 08:56:28.000000000 -0600
+++ balsa/libbalsa/filter-funcs.c	2004-08-15 15:46:46.000000000 -0600
@@ -49,7 +49,7 @@
 	if(*str == '"')
 	  ++str;
     } else {
-        while(*++str && !isspace((int)*str))
+        while(*++str && !g_ascii_isspace((int)*str))
             g_string_append_c(res, *str);
     }
     *pstr = str;
@@ -121,64 +121,95 @@
     cond->match.string.user_header = user_header;
     return cond;
 }
-LibBalsaCondition*
-libbalsa_condition_new_date(gboolean negated, time_t *from, time_t *to)
-{
-    LibBalsaCondition *cond;
-    cond = g_new(LibBalsaCondition,1);
-    cond->negate = negated;
-    cond->type = CONDITION_STRING;
-    cond->type = CONDITION_DATE;
-    cond->match.date.date_low  = from ? *from : 0;
-    cond->match.date.date_high = to   ? *to   : 0;
-    return cond;
-}
 
 static LibBalsaCondition*
 libbalsa_condition_new_date_parse(gboolean negated, gchar **string)
 {
     LibBalsaCondition *cond;
-    gchar *hi, *lo = get_quoted_string(string);
-    time_t tlo, thi;
+    gchar *hi, *lo;
+    time_t tlo = 0, thi = 0;
+    gint offset_low = 0, offset_high = 0;
+    ConditionDateType type = DATE_ABSOLUTE;
     struct tm date;
 
-    if(lo == NULL)
-        return NULL;
-    if(*(*string)++ != ' ') {
-        g_free(lo);
-        return NULL;
-    }
-    hi=get_quoted_string(string);
-    if(hi == NULL) {
-        g_free(lo);
-        return NULL;
-    }
-
-    /* strptime with our format will not set time, only date */
+    while (**string!='\0' && g_ascii_isspace(**string)) (*string)++;
+    if (**string=='\0')
+	return NULL;
+    lo = *string;
+    while (**string!='\0' && !g_ascii_isspace(**string)) (*string)++;
     date.tm_sec = 0;
     date.tm_min = 0;
     date.tm_hour = 0;
-
-    if(*lo == '\0')
-       tlo = 0;
-    else {
-        strptime(lo, "%Y-%m-%d", &date);
-        tlo = mktime(&date);
-    }
-    if(*hi == '\0')
-       thi =  0;
-    else {
-        strptime(hi, "%Y-%m-%d", &date);
-        thi = mktime(&date) + 24*3600 - 1 /* 24*3600 - 1 = 23:59:59 */;
+    switch (toupper(*lo)) {
+    case 'A': /* Absolute dates */
+	if (g_ascii_strncasecmp(lo+1, "BSOLUTE", *string-lo-1))
+	    return NULL;
+	(*string)++;
+	lo = get_quoted_string(string);
+	if(lo == NULL)
+	    return NULL;
+	if(*((*string)++) != ' ') {
+	    g_free(lo);
+	    return NULL;
+	}
+	hi = get_quoted_string(string);
+	if(hi == NULL) {
+	    g_free(lo);
+	    return NULL;
+	}
+	if(*lo == '\0')
+	    tlo = 0;
+	else {
+	    strptime(lo, "%Y-%m-%d", &date);
+	    tlo = mktime(&date);
+	}
+	if(*hi == '\0')
+	    thi =  0;
+	else {
+	    strptime(hi, "%Y-%m-%d", &date);
+	    thi = mktime(&date) + 24*3600 - 1 /* 24*3600 - 1 = 23:59:59 */;
+	}
+	g_free(lo);
+	g_free(hi);
+	break;
+    case 'D': /* Offset are in days */
+	if (g_ascii_strncasecmp(lo+1, "AYS", *string-lo-1))
+	    return NULL;
+	type = DATE_DAYS;
+	offset_low = g_ascii_strtod(*string, string);
+	if (!g_ascii_isspace(**string))
+	    return NULL;
+	offset_high = g_ascii_strtod(*string, string);
+	break;
+    case 'M': /* Offest are in months */
+	if (g_ascii_strncasecmp(lo+1, "ONTHS", *string-lo-1))
+	    return NULL;
+	type = DATE_MONTHS;
+	offset_low =  g_ascii_strtod(*string, string);
+	if (!g_ascii_isspace(**string))
+	    return NULL;
+	offset_high = g_ascii_strtod(*string, string);
+	break;
+    case 'Y': /* Offest are in years */
+	if (g_ascii_strncasecmp(lo+1, "EARS", *string-lo-1))
+	    return NULL;
+	type = DATE_YEARS;
+	offset_low =  g_ascii_strtod(*string, string);
+	if (!g_ascii_isspace(**string))
+	    return NULL;
+	offset_high =  g_ascii_strtod(*string, string);
+	break;
+    default:
+	return NULL;
     }
-        
     cond = g_new(LibBalsaCondition,1);
     cond->negate = negated;
     cond->type = CONDITION_DATE;
+    cond->match.date.dates_type = type;
     cond->match.date.date_low  = tlo;
     cond->match.date.date_high = thi;
-    g_free(lo);
-    g_free(hi);
+    cond->match.date.offset_low  = offset_low;
+    cond->match.date.offset_high = offset_high;
     return cond;
 }
 
@@ -315,17 +346,37 @@
 	break;
     case CONDITION_DATE:
         g_string_append(res, "DATE ");
-	if (cond->match.date.date_low) {
-	    localtime_r(&cond->match.date.date_low, &date);
-	    strftime(str,sizeof(str),"%Y-%m-%d", &date);
-	} else str[0]='\0';
-        append_quoted_string(res, str);
-        g_string_append_c(res, ' ');
-	if (cond->match.date.date_high) {
-	    localtime_r(&cond->match.date.date_high, &date);
-	    strftime(str,sizeof(str),"%Y-%m-%d", &date);
-	} else str[0]='\0';
-        append_quoted_string(res, str);
+	if (cond->match.date.dates_type == DATE_ABSOLUTE) {
+	    g_string_append(res, "ABSOLUTE ");
+	    if (cond->match.date.date_low) {
+		localtime_r(&cond->match.date.date_low, &date);
+		strftime(str,sizeof(str),"%Y-%m-%d", &date);
+	    } else str[0]='\0';
+	    append_quoted_string(res, str);
+	    g_string_append_c(res, ' ');
+	    if (cond->match.date.date_high) {
+		localtime_r(&cond->match.date.date_high, &date);
+		strftime(str,sizeof(str),"%Y-%m-%d", &date);
+	    } else str[0]='\0';
+	    append_quoted_string(res, str);
+	} else {
+	    switch (cond->match.date.dates_type) {
+	    case DATE_DAYS:
+		g_string_append(res, "DAYS ");
+		break;
+	    case DATE_MONTHS:
+		g_string_append(res, "MONTHS ");
+		break;
+	    case DATE_YEARS:
+		g_string_append(res, "YEARS ");
+		break;
+	    case DATE_ABSOLUTE:
+		/* To avoid compiler warning */
+		break;
+	    }
+	    g_string_append_printf(res, "%d %d", cond->match.date.offset_low,
+				   cond->match.date.offset_high);
+	}
 	break;
     case CONDITION_FLAG:
         g_string_append_printf(res, "FLAG %u", cond->match.flags);
@@ -447,8 +498,11 @@
 #endif
         break;
     case CONDITION_DATE:
+	new_cnd->match.date.dates_type = cnd->match.date.dates_type;
         new_cnd->match.date.date_low  = cnd->match.date.date_low;
         new_cnd->match.date.date_high = cnd->match.date.date_high;
+        new_cnd->match.date.offset_low  = cnd->match.date.offset_low;
+        new_cnd->match.date.offset_high = cnd->match.date.offset_high;
         break;
     case CONDITION_FLAG:
         new_cnd->match.flags=cnd->match.flags;

--- ../balsa-HEAD/balsa/src/filter-edit-callbacks.c	2004-06-06 15:43:42.000000000 -0600
+++ balsa/src/filter-edit-callbacks.c	2004-08-18 22:52:26.000000000 -0600
@@ -94,6 +94,16 @@
 /* widgets for the type notebook date page */
 GtkWidget *fe_type_date_label;
 GtkWidget *fe_type_date_low_entry,*fe_type_date_high_entry;
+GtkWidget * fe_type_date_off_low;
+GtkWidget * fe_type_date_off_high;
+GtkWidget * fe_type_date_abs_box,* fe_type_date_rel_box;
+GtkWidget * fe_type_date_abs_bton, * fe_type_date_rel_bton,
+    * fe_type_date_units;
+option_list fe_dates_units[] = {
+    {N_("DAYS"), DATE_DAYS, NULL},
+    {N_("MONTHS"), DATE_MONTHS, NULL},
+    {N_("YEARS"), DATE_YEARS, NULL}
+};
 
 /* widgets for the type notebook regex page */
 GtkTreeView *fe_type_regex_list;
@@ -363,6 +373,21 @@
     condition_has_changed=TRUE;
 }
 
+/* Callback to grey/ungrey corresponding widgets when you
+   have selected a different type of dates: absolute/relative
+   Calls fe_condition_changed_cb
+ */
+
+static void
+fe_date_type_changed_cb(GtkWidget * w, gpointer throwaway)
+{
+    gboolean abs =
+	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_type_date_abs_bton));
+    fe_condition_changed_cb(NULL, NULL);
+    gtk_widget_set_sensitive(fe_type_date_abs_box, abs);
+    gtk_widget_set_sensitive(fe_type_date_rel_box, !abs);
+}
+
 /*
  *  void fe_match_fields_buttons_cb(GtkWidget * widget, gpointer data)
  *
@@ -484,34 +509,57 @@
         }
         break;
     case CONDITION_DATE:
-        c_str = gtk_entry_get_text(GTK_ENTRY(fe_type_date_low_entry));
-        if (c_str && c_str[0]!='\0') {
-            (void) strptime("00:00:00","%T",&date);
-            p=(gchar *)strptime(c_str,"%x",&date);
-            if (!p || *p!='\0') {
-                balsa_information(LIBBALSA_INFORMATION_ERROR,
-                                  _("Low date is incorrect"));
-                return FALSE;
-            }
-            new_cnd->match.date.date_low=mktime(&date);
-        }
-        c_str = gtk_entry_get_text(GTK_ENTRY(fe_type_date_high_entry));
-        if (c_str && c_str[0]!='\0') {
-            (void) strptime("23:59:59","%T",&date);
-            p=(gchar *)strptime(c_str,"%x",&date);
-            if (!p || *p!='\0') {
-                balsa_information(LIBBALSA_INFORMATION_ERROR,
-                                  _("High date is incorrect"));
-                return FALSE;
-            }
-            new_cnd->match.date.date_high=mktime(&date);
-        }
-        if (new_cnd->match.date.date_low >
-            new_cnd->match.date.date_high) {
-            balsa_information(LIBBALSA_INFORMATION_ERROR,
-                              _("Low date is greater than high date"));
-            return FALSE;
-        }
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fe_type_date_abs_bton))) {
+	    new_cnd->match.date.dates_type = DATE_ABSOLUTE;
+	    c_str = gtk_entry_get_text(GTK_ENTRY(fe_type_date_low_entry));
+	    if (c_str && c_str[0]!='\0') {
+		(void) strptime("00:00:00","%T",&date);
+		p=(gchar *)strptime(c_str,"%x",&date);
+		if (!p || *p!='\0') {
+		    balsa_information(LIBBALSA_INFORMATION_ERROR,
+				      _("Low date is incorrect"));
+		    return FALSE;
+		}
+		new_cnd->match.date.date_low=mktime(&date);
+	    }
+	    c_str = gtk_entry_get_text(GTK_ENTRY(fe_type_date_high_entry));
+	    if (c_str && c_str[0]!='\0') {
+		(void) strptime("23:59:59","%T",&date);
+		p=(gchar *)strptime(c_str,"%x",&date);
+		if (!p || *p!='\0') {
+		    balsa_information(LIBBALSA_INFORMATION_ERROR,
+				      _("High date is incorrect"));
+		    return FALSE;
+		}
+		new_cnd->match.date.date_high=mktime(&date);
+	    }
+	    if (new_cnd->match.date.date_low >
+		new_cnd->match.date.date_high) {
+		balsa_information(LIBBALSA_INFORMATION_ERROR,
+				  _("Low date is greater than high date"));
+		return FALSE;
+	    }
+	}
+	else {
+	    GtkWidget * menu;
+
+	     new_cnd->match.date.offset_low =
+		 -gtk_spin_button_get_value(GTK_SPIN_BUTTON(fe_type_date_off_low));
+	     new_cnd->match.date.offset_high =
+		 -gtk_spin_button_get_value(GTK_SPIN_BUTTON(fe_type_date_off_high));
+	    if (new_cnd->match.date.offset_low >
+		new_cnd->match.date.offset_high) {
+		balsa_information(LIBBALSA_INFORMATION_ERROR,
+				  _("Low date is greater than high date"));
+		return FALSE;
+	    }
+	    /* Retrieve the selected item in the search type menu */
+	    menu =
+		gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(fe_type_date_units))));
+	    /* Set the type associated with the selected item */
+	    new_cnd->match.date.dates_type =
+		GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu),"value"));
+	}
         break;
     case CONDITION_FLAG:
     case CONDITION_NONE:
@@ -683,19 +731,33 @@
 #endif
         break;
     case CONDITION_DATE:
-        if (cnd->match.date.date_low==0) str[0]='\0';
-        else {
-            localtime_r(&cnd->match.date.date_low, &date);
-            strftime(str, sizeof(str), xformat, &date);
-        }
-        gtk_entry_set_text(GTK_ENTRY(fe_type_date_low_entry),str);
-        if (cnd->match.date.date_high==0) str[0]='\0';
-        else {
-            localtime_r(&cnd->match.date.date_high, &date);
-            strftime(str,sizeof(str), xformat, &date);
-        }
-        gtk_entry_set_text(GTK_ENTRY(fe_type_date_high_entry),str);
-        fe_update_label(fe_type_date_label, &date_label);
+	if (cnd->match.date.dates_type == DATE_ABSOLUTE) {
+	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_type_date_abs_bton), TRUE);
+	    if (cnd->match.date.date_low==0) str[0]='\0';
+	    else {
+		localtime_r(&cnd->match.date.date_low, &date);
+		strftime(str, sizeof(str), xformat, &date);
+	    }
+	    gtk_entry_set_text(GTK_ENTRY(fe_type_date_low_entry),str);
+	    if (cnd->match.date.date_high==0) str[0]='\0';
+	    else {
+		localtime_r(&cnd->match.date.date_high, &date);
+		strftime(str,sizeof(str), xformat, &date);
+	    }
+	    gtk_entry_set_text(GTK_ENTRY(fe_type_date_high_entry),str);
+	}
+	else {
+	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fe_type_date_rel_bton), TRUE);
+	    gtk_option_menu_set_history(GTK_OPTION_MENU(fe_type_date_units), 
+					cnd->match.date.dates_type-1);
+	    gtk_spin_button_set_digits(GTK_SPIN_BUTTON(fe_type_date_off_low),0);
+	    gtk_spin_button_set_value(GTK_SPIN_BUTTON(fe_type_date_off_low),
+				      -cnd->match.date.offset_low);
+	    gtk_spin_button_set_value(GTK_SPIN_BUTTON(fe_type_date_off_high),
+				      -cnd->match.date.offset_high);
+	}
+	fe_update_label(fe_type_date_label, &date_label);
+	fe_date_type_changed_cb((GtkWidget *)NULL, NULL);
         break;
     case CONDITION_FLAG:
         for (row=0;row<2;row++)
@@ -890,41 +952,110 @@
 
     /* The date page of the notebook */
 
-    page = gtk_table_new(5, 3, FALSE);
+    page = gtk_table_new(3, 3, FALSE);
     gtk_notebook_append_page(GTK_NOTEBOOK(fe_type_notebook), page, NULL);
 
     fe_type_date_label = 
         gtk_label_new(_("Match when date is in the interval:"));
     gtk_table_attach(GTK_TABLE(page),
                      fe_type_date_label,
-                     0, 5, 0, 1,
+                     0, 3, 0, 1,
                      GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
+    fe_type_date_abs_bton
+	= gtk_radio_button_new_with_label(NULL,
+					  _("Absolute dates"));
+    g_signal_connect(G_OBJECT(fe_type_date_abs_bton), "toggled",
+                     G_CALLBACK(fe_date_type_changed_cb), NULL);
+    gtk_table_attach(GTK_TABLE(page),
+                     fe_type_date_abs_bton,
+                     0, 1, 1, 2,
+                     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
+    fe_type_date_rel_bton =
+	gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(fe_type_date_abs_bton),
+						    _("Relative dates"));
+    g_signal_connect(G_OBJECT(fe_type_date_rel_bton), "toggled",
+                     G_CALLBACK(fe_date_type_changed_cb), NULL);
+    gtk_table_attach(GTK_TABLE(page),
+                     fe_type_date_rel_bton,
+                     0, 1, 2, 3,
+                     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
+					    
+    fe_type_date_abs_box = gtk_hbox_new(TRUE, 5);
+    gtk_table_attach(GTK_TABLE(page),
+                     fe_type_date_abs_box,
+                     1, 2, 1, 2,
+                     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_abs_box),
+		       gtk_label_new(_("Between:")),
+		       TRUE, TRUE, 0);
     fe_type_date_low_entry = gtk_entry_new();
     g_signal_connect(G_OBJECT(fe_type_date_low_entry), "changed",
                      G_CALLBACK(fe_condition_changed_cb), NULL);
-    gtk_table_attach(GTK_TABLE(page),
-                     fe_type_date_low_entry,
-                     0, 2, 1, 2,
-                     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_abs_box),
+		       fe_type_date_low_entry,
+		       TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_abs_box),
+		       gtk_label_new(_("And:")),
+		       TRUE, TRUE, 0);
     fe_type_date_high_entry = gtk_entry_new();
     g_signal_connect(G_OBJECT(fe_type_date_high_entry), "changed",
                      G_CALLBACK(fe_condition_changed_cb), NULL);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_abs_box),
+		       fe_type_date_high_entry,
+		       TRUE, TRUE, 0);
+    fe_type_date_rel_box = gtk_hbox_new(TRUE, 5);
     gtk_table_attach(GTK_TABLE(page),
-                     fe_type_date_high_entry,
-                     3, 5, 1, 2,
-                     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
+                     fe_type_date_rel_box,
+                     1, 2, 2, 3,
+                     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_rel_box),
+		       gtk_label_new(_("Between:")),
+		       TRUE, TRUE, 0);
+    fe_type_date_off_low =
+	gtk_spin_button_new_with_range(-10000, 10000, 1);
+    gtk_spin_button_set_digits(GTK_SPIN_BUTTON(fe_type_date_off_low),0);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(fe_type_date_off_low),0);
+    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(fe_type_date_off_low), TRUE);
+    g_signal_connect(G_OBJECT(fe_type_date_off_low), "changed",
+                     G_CALLBACK(fe_condition_changed_cb), NULL);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_rel_box),
+		       fe_type_date_off_low,
+		       TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_rel_box),
+		       gtk_label_new(_("And:")),
+		       TRUE, TRUE, 0);
+    fe_type_date_off_high =
+	gtk_spin_button_new_with_range(-10000, 10000, 1);
+    gtk_spin_button_set_digits(GTK_SPIN_BUTTON(fe_type_date_off_high),0);
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(fe_type_date_off_high),0);
+    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(fe_type_date_off_high), TRUE);
+    g_signal_connect(G_OBJECT(fe_type_date_off_high), "changed",
+                     G_CALLBACK(fe_condition_changed_cb), NULL);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_rel_box),
+		       fe_type_date_off_high,
+		       TRUE, TRUE, 0);
+    fe_type_date_units =
+	fe_build_option_menu(fe_dates_units,
+			     ELEMENTS(fe_dates_units),
+			     G_CALLBACK(fe_condition_changed_cb));
+    gtk_box_pack_start(GTK_BOX(fe_type_date_rel_box),
+		       fe_type_date_units,
+		       TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(fe_type_date_rel_box),
+		       gtk_label_new(_("before the running date")),
+		       TRUE, TRUE, 0);
 
     button = gtk_button_new_with_label(_("Inside/outside the date interval"));
     g_signal_connect(G_OBJECT(button), "clicked",
                      G_CALLBACK(fe_negate_condition), NULL);
     gtk_table_attach(GTK_TABLE(page),
                      button,
-                     0, 5, 2, 3,
+                     0, 5, 3, 4,
                      GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
 
     gtk_table_attach(GTK_TABLE(page),
                      fe_date_sample(),
-                     0, 5, 3, 4,
+                     0, 5, 4, 5,
                      GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
 
     /* The flag page of the notebook */
@@ -1133,6 +1264,8 @@
                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                         GTK_STOCK_HELP, GTK_RESPONSE_HELP,
                                         NULL);
+	/* FIXME: Need to do something about the SIZE of this dialog box,
+	   it is way too big! */
         g_object_add_weak_pointer(G_OBJECT(condition_dialog),
                                   (gpointer) &condition_dialog);
 
--- ../balsa-HEAD/balsa/src/filter-edit-dialog.c	2004-01-11 09:55:17.000000000 -0700
+++ balsa/src/filter-edit-dialog.c	2004-08-15 11:51:29.000000000 -0600
@@ -268,8 +268,8 @@
 		     GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 5, 5);
 
     fe_op_codes_option_menu = fe_build_option_menu(fe_op_codes,
-						ELEMENTS(fe_op_codes),
-						NULL);
+						   ELEMENTS(fe_op_codes),
+						   NULL);
     gtk_box_pack_start(GTK_BOX(box), fe_op_codes_option_menu, FALSE, FALSE,
 		       2);
 
--- ../balsa-HEAD/balsa/src/filter-edit.h	2003-01-20 16:02:07.000000000 -0700
+++ balsa/src/filter-edit.h	2004-08-15 11:53:30.000000000 -0600
@@ -50,7 +50,7 @@
 
 /* button callbacks */
 void fe_dialog_response(GtkWidget * widget, gint response,
-			      gpointer data);
+			gpointer data);
 
 /* helper */
 GtkWidget *fe_build_option_menu(option_list options[], gint num,

Attachment: pgp7xbQAcjW6u.pgp
Description: PGP signature



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