"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "Expense/expense.c" between
jpilot-1.8.2.tar.gz and jpilot-2_0_1.tar.gz

About: J-Pilot is a desktop organizer application for Palm Pilot (PalmOS) devices. Ported to GTK3.

expense.c  (jpilot-1.8.2):expense.c  (jpilot-2_0_1)
skipping to change at line 79 skipping to change at line 79
char * city; char * city;
char * attendees; char * attendees;
char * note; char * note;
}; };
*/ */
/* This is my wrapper to the expense structure so that I can put /* This is my wrapper to the expense structure so that I can put
* a few more fields in with it * a few more fields in with it
*/ */
struct MyExpense { struct MyExpense {
PCRecType rt; PCRecType rt;
unsigned int unique_id; unsigned int unique_id;
unsigned char attrib; unsigned char attrib;
struct Expense ex; struct Expense ex;
struct MyExpense *next; struct MyExpense *next;
}; };
struct currency_s { struct currency_s {
const char *country; const char *country;
int currency; int currency;
}; };
/******************************************************************************/ /******************************************************************************/
/* Global vars */ /* Global vars */
/******************************************************************************/ /******************************************************************************/
static struct currency_s glob_currency[MAX_CURRENCYS]={ static struct currency_s glob_currency[MAX_CURRENCYS] = {
{N_("Australia"), 0}, {N_("Australia"), 0},
{N_("Austria"), 1}, {N_("Austria"), 1},
{N_("Belgium"), 2}, {N_("Belgium"), 2},
{N_("Brazil"), 3}, {N_("Brazil"), 3},
{N_("Canada"), 4}, {N_("Canada"), 4},
{N_("Denmark"), 5}, {N_("Denmark"), 5},
{N_("EU (Euro)"), 133}, {N_("EU (Euro)"), 133},
{N_("Finland"), 6}, {N_("Finland"), 6},
{N_("France"), 7}, {N_("France"), 7},
{N_("Germany"), 8}, {N_("Germany"), 8},
{N_("Hong Kong"), 9}, {N_("Hong Kong"), 9},
{N_("Iceland"), 10}, {N_("Iceland"), 10},
{N_("India"), 24}, {N_("India"), 24},
{N_("Indonesia"), 25}, {N_("Indonesia"), 25},
{N_("Ireland"), 11}, {N_("Ireland"), 11},
{N_("Italy"), 12}, {N_("Italy"), 12},
{N_("Japan"), 13}, {N_("Japan"), 13},
{N_("Korea"), 26}, {N_("Korea"), 26},
{N_("Luxembourg"), 14}, {N_("Luxembourg"), 14},
{N_("Malaysia"), 27}, {N_("Malaysia"), 27},
{N_("Mexico"), 15}, {N_("Mexico"), 15},
{N_("Netherlands"), 16}, {N_("Netherlands"), 16},
{N_("New Zealand"), 17}, {N_("New Zealand"), 17},
{N_("Norway"), 18}, {N_("Norway"), 18},
{N_("P.R.C."), 28}, {N_("P.R.C."), 28},
{N_("Philippines"), 29}, {N_("Philippines"), 29},
{N_("Singapore"), 30}, {N_("Singapore"), 30},
{N_("Spain"), 19}, {N_("Spain"), 19},
{N_("Sweden"), 20}, {N_("Sweden"), 20},
{N_("Switzerland"), 21}, {N_("Switzerland"), 21},
{N_("Taiwan"), 32}, {N_("Taiwan"), 32},
{N_("Thailand"), 31}, {N_("Thailand"), 31},
{N_("United Kingdom"), 22}, {N_("United Kingdom"), 22},
{N_("United States"), 23} {N_("United States"), 23}
};
const char *date_formats[] = {
"%1$02d/%2$02d",
"%2$02d/%1$02d",
"%2$02d.%1$02d.",
"%2$02d-%1$02d",
"%1$02d/%2$02d",
"%1$02d.%2$02d.",
"%1$02d-%2$02d"
}; };
/* Left-hand side of GUI */ /* Left-hand side of GUI */
static struct sorted_cats sort_l[NUM_EXP_CAT_ITEMS]; static struct sorted_cats sort_l[NUM_EXP_CAT_ITEMS];
static GtkWidget *category_menu1; static GtkWidget *category_menu1;
/* Need two extra slots for the ALL category and Edit Categories... */
static GtkWidget *exp_cat_menu_item1[NUM_EXP_CAT_ITEMS+2];
static GtkWidget *scrolled_window; static GtkWidget *scrolled_window;
static GtkWidget *clist; static GtkTreeView *treeView;
static GtkListStore *listStore;
/* Right-hand side of GUI */ /* Right-hand side of GUI */
static GtkWidget *new_record_button; static GtkWidget *new_record_button;
static GtkWidget *apply_record_button; static GtkWidget *apply_record_button;
static GtkWidget *add_record_button; static GtkWidget *add_record_button;
static GtkWidget *delete_record_button; static GtkWidget *delete_record_button;
static GtkWidget *copy_record_button; static GtkWidget *copy_record_button;
static GtkWidget *table; static GtkWidget *grid;
static GtkWidget *category_menu2; static GtkWidget *category_menu2;
static GtkWidget *exp_cat_menu_item2[NUM_EXP_CAT_ITEMS];
static GtkWidget *menu_payment; static GtkWidget *menu_payment;
static GtkWidget *menu_item_payment[MAX_PAYMENTS];
static GtkWidget *menu_expense_type; static GtkWidget *menu_expense_type;
static GtkWidget *menu_item_expense_type[MAX_EXPENSE_TYPES];
static GtkWidget *menu_currency; static GtkWidget *menu_currency;
static GtkWidget *menu_item_currency[MAX_CURRENCYS];
static GtkWidget *spinner_mon, *spinner_day, *spinner_year; static GtkWidget *spinner_mon, *spinner_day, *spinner_year;
static GtkAdjustment *adj_mon, *adj_day, *adj_year; static GtkAdjustment *adj_mon, *adj_day, *adj_year;
static GtkWidget *entry_amount; static GtkWidget *entry_amount;
static GtkWidget *entry_vendor; static GtkWidget *entry_vendor;
static GtkWidget *entry_city; static GtkWidget *entry_city;
static GtkWidget *pane=NULL; static GtkWidget *pane = NULL;
#ifndef ENABLE_STOCK_BUTTONS #ifndef ENABLE_STOCK_BUTTONS
static GtkAccelGroup *accel_group; static GtkAccelGroup *accel_group;
#endif #endif
static GtkWidget *attendees; static GtkWidget *attendees;
static GObject *attendees_buffer; static GObject *attendees_buffer;
static GtkWidget *note; static GtkWidget *note;
static GObject *note_buffer; static GObject *note_buffer;
/* This is the category that is currently being displayed */ /* This is the category that is currently being displayed */
static int exp_category = CATEGORY_ALL; static int exp_category = CATEGORY_ALL;
static time_t plugin_last_time = 0; static time_t plugin_last_time = 0;
static int record_changed; static int record_changed;
static int clist_row_selected; static int row_selected;
static int clist_col_selected; static int column_selected;
static int connected=0; static int connected = 0;
static int glob_detail_type; static int glob_detail_type;
static int glob_detail_payment; static int glob_detail_payment;
static int glob_detail_currency_pos; static int glob_detail_currency_pos;
static struct MyExpense *glob_myexpense_list=NULL; static struct MyExpense *glob_myexpense_list = NULL;
enum {
EXPENSE_DATE_COLUMN_ENUM = 0,
EXPENSE_TYPE_COLUMN_ENUM,
EXPENSE_AMOUNT_COLUMN_ENUM,
EXPENSE_DATA_COLUMN_ENUM,
EXPENSE_BACKGROUND_COLOR_ENUM,
EXPENSE_BACKGROUND_COLOR_ENABLED_ENUM,
EXPENSE_NUM_COLS
};
/******************************************************************************/ /******************************************************************************/
/* Prototypes */ /* Prototypes */
/******************************************************************************/ /******************************************************************************/
static void display_records(void); static void display_records(void);
static void connect_changed_signals(int con_or_dis); static void connect_changed_signals(int con_or_dis);
static void cb_clist_selection(GtkWidget *clist,
gint row,
gint column,
GdkEventButton *event,
gpointer data);
static void cb_add_new_record(GtkWidget *widget, gpointer data); static void cb_add_new_record(GtkWidget *widget, gpointer data);
static void cb_pulldown_menu(GtkWidget *item, unsigned int value);
static int make_menu(const char *items[], int menu_index, GtkWidget **Poption_m static void cb_pulldown_menu(GtkComboBox *item, unsigned int value);
enu,
GtkWidget *menu_items[]); static int make_menu(const char *items[], int menu_index, GtkWidget **Poption_me
static int expense_find(int unique_id); nu);
static void cb_category(GtkWidget *item, int selection);
static int expense_find(int unique_id);
static void cb_category(GtkComboBox *item, int selection);
static int find_sort_cat_pos(int cat); static int find_sort_cat_pos(int cat);
static int find_menu_cat_pos(int cat); static int find_menu_cat_pos(int cat);
void addNewExpenseRecordToDataStructure(struct MyExpense *mexp, gpointer data);
void deleteExpense(struct MyExpense *mexp,gpointer data);
/******************************************************************************/ /******************************************************************************/
/* Start of code */ /* Start of code */
/******************************************************************************/ /******************************************************************************/
int plugin_unpack_cai_from_ai(struct CategoryAppInfo *cai, int plugin_unpack_cai_from_ai(struct CategoryAppInfo *cai,
unsigned char *ai_raw, int len) unsigned char *ai_raw, int len) {
{ struct ExpenseAppInfo ai;
struct ExpenseAppInfo ai; int r;
int r;
jp_logf(JP_LOG_DEBUG, "unpack_expense_cai_from_ai\n");
jp_logf(JP_LOG_DEBUG, "unpack_expense_cai_from_ai\n");
memset(&ai, 0, sizeof(ai));
memset(&ai, 0, sizeof(ai)); r = unpack_ExpenseAppInfo(&ai, ai_raw, (size_t) len);
r = unpack_ExpenseAppInfo(&ai, ai_raw, len); if (r <= 0) {
if (r <= 0) { jp_logf(JP_LOG_DEBUG, "unpack_ExpenseAppInfo failed %s %d\n", __FILE__,
jp_logf(JP_LOG_DEBUG, "unpack_ExpenseAppInfo failed %s %d\n", __FILE__, __ __LINE__);
LINE__); return EXIT_FAILURE;
return EXIT_FAILURE; }
} memcpy(cai, &(ai.category), sizeof(struct CategoryAppInfo));
memcpy(cai, &(ai.category), sizeof(struct CategoryAppInfo));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int plugin_pack_cai_into_ai(struct CategoryAppInfo *cai, int plugin_pack_cai_into_ai(struct CategoryAppInfo *cai,
unsigned char *ai_raw, int len) unsigned char *ai_raw, int len) {
{ struct ExpenseAppInfo ai;
struct ExpenseAppInfo ai; int r;
int r;
jp_logf(JP_LOG_DEBUG, "pack_expense_cai_into_ai\n");
jp_logf(JP_LOG_DEBUG, "pack_expense_cai_into_ai\n");
r = unpack_ExpenseAppInfo(&ai, ai_raw, (size_t) len);
r = unpack_ExpenseAppInfo(&ai, ai_raw, len); if (r <= 0) {
if (r <= 0) { jp_logf(JP_LOG_DEBUG, "unpack_ExpenseAppInfo failed %s %d\n", __FILE__,
jp_logf(JP_LOG_DEBUG, "unpack_ExpenseAppInfo failed %s %d\n", __FILE__, __ __LINE__);
LINE__); return EXIT_FAILURE;
return EXIT_FAILURE; }
} memcpy(&(ai.category), cai, sizeof(struct CategoryAppInfo));
memcpy(&(ai.category), cai, sizeof(struct CategoryAppInfo));
r = pack_ExpenseAppInfo(&ai, ai_raw, (size_t) len);
r = pack_ExpenseAppInfo(&ai, ai_raw, len); if (r <= 0) {
if (r <= 0) { jp_logf(JP_LOG_DEBUG, "pack_ExpenseAppInfo failed %s %d\n", __FILE__, __
jp_logf(JP_LOG_DEBUG, "pack_ExpenseAppInfo failed %s %d\n", __FILE__, __LI LINE__);
NE__); return EXIT_FAILURE;
return EXIT_FAILURE; }
}
return EXIT_SUCCESS;
return EXIT_SUCCESS; }
}
static gint sortDateColumn(GtkTreeModel *model,
static gint sort_compare_date(GtkCList *clist, GtkTreeIter *left,
gconstpointer ptr1, GtkTreeIter *right,
gconstpointer ptr2) gpointer columnId) {
{ gint sortcol = GPOINTER_TO_INT(columnId);
const GtkCListRow *row1, *row2; gint ret = 0;
struct MyExpense *mexp1, *mexp2; struct MyExpense *mexp1, *mexp2;
time_t time1, time2; time_t time1, time2;
switch (sortcol) {
row1 = (const GtkCListRow *) ptr1; case EXPENSE_DATE_COLUMN_ENUM: {
row2 = (const GtkCListRow *) ptr2; gtk_tree_model_get(GTK_TREE_MODEL(model), left, EXPENSE_DATA_COLUMN_
ENUM, &mexp1, -1);
mexp1 = row1->data; gtk_tree_model_get(GTK_TREE_MODEL(model), right, EXPENSE_DATA_COLUMN
mexp2 = row2->data; _ENUM, &mexp2, -1);
if(mexp1 == NULL && mexp2 == NULL){
time1 = mktime(&(mexp1->ex.date)); ret = 0;
time2 = mktime(&(mexp2->ex.date)); } else if(mexp1 == NULL && mexp2 != NULL){
ret = -1;
return(time1 - time2); }else if (mexp1 != NULL && mexp2 == NULL){
} ret = 1;
} else if (mexp1 != NULL && mexp2 != NULL) {
static void cb_clist_click_column(GtkWidget *clist, int column) time1 = mktime(&(mexp1->ex.date));
{ time2 = mktime(&(mexp2->ex.date));
struct MyExpense *mexp; ret = (gint) (time1 - time2);
unsigned int unique_id; }
}
/* Remember currently selected item and return to it after sort break;
* This is critically important because sorting without updating the default:
* global variable clist_row_selected can cause data loss */ break;
mexp = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected); }
if (mexp < (struct MyExpense *)CLIST_MIN_DATA) { return ret;
unique_id = 0;
} else { }
unique_id = mexp->unique_id;
} static void set_new_button_to(int new_state) {
jp_logf(JP_LOG_DEBUG, "set_new_button_to new %d old %d\n", new_state, record
/* Clicking on same column toggles ascending/descending sort */ _changed);
if (clist_col_selected == column)
{ if (record_changed == new_state) {
if (GTK_CLIST(clist)->sort_type == GTK_SORT_ASCENDING) { return;
gtk_clist_set_sort_type(GTK_CLIST (clist), GTK_SORT_DESCENDING); }
}
else { switch (new_state) {
gtk_clist_set_sort_type(GTK_CLIST (clist), GTK_SORT_ASCENDING); case MODIFY_FLAG:
} gtk_widget_show(copy_record_button);
} gtk_widget_show(apply_record_button);
else /* Always sort in ascending order when changing sort column */
{ gtk_widget_hide(add_record_button);
gtk_clist_set_sort_type(GTK_CLIST (clist), GTK_SORT_ASCENDING); gtk_widget_hide(delete_record_button);
} gtk_widget_hide(new_record_button);
break;
clist_col_selected = column; case NEW_FLAG:
gtk_widget_show(add_record_button);
gtk_clist_set_sort_column(GTK_CLIST(clist), column);
switch (column) { gtk_widget_hide(apply_record_button);
case EXP_DATE_COLUMN: /* Date column */ gtk_widget_hide(copy_record_button);
gtk_clist_set_compare_func(GTK_CLIST(clist), sort_compare_date); gtk_widget_hide(delete_record_button);
break; gtk_widget_hide(new_record_button);
default: /* All other columns can use GTK default sort function */ break;
gtk_clist_set_compare_func(GTK_CLIST(clist), NULL); case CLEAR_FLAG:
break; gtk_widget_show(delete_record_button);
} gtk_widget_show(copy_record_button);
gtk_clist_sort(GTK_CLIST(clist)); gtk_widget_show(new_record_button);
/* Return to previously selected item */ gtk_widget_hide(add_record_button);
expense_find(unique_id); gtk_widget_hide(apply_record_button);
} break;
default:
static void set_new_button_to(int new_state) return;
{ }
jp_logf(JP_LOG_DEBUG, "set_new_button_to new %d old %d\n", new_state, record_ record_changed = new_state;
changed); }
if (record_changed==new_state) { static void cb_record_changed(GtkWidget *widget, gpointer data) {
return; jp_logf(JP_LOG_DEBUG, "cb_record_changed\n");
}
if (record_changed == CLEAR_FLAG) {
switch (new_state) { connect_changed_signals(DISCONNECT_SIGNALS);
case MODIFY_FLAG: if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStore),NULL) > 0)
gtk_widget_show(copy_record_button); {
gtk_widget_show(apply_record_button); set_new_button_to(MODIFY_FLAG);
} else {
gtk_widget_hide(add_record_button); set_new_button_to(NEW_FLAG);
gtk_widget_hide(delete_record_button); }
gtk_widget_hide(new_record_button); }
break; }
case NEW_FLAG:
gtk_widget_show(add_record_button); static void connect_changed_signals(int con_or_dis) {
/* CONNECT */
gtk_widget_hide(apply_record_button); if ((con_or_dis == CONNECT_SIGNALS) && (!connected)) {
gtk_widget_hide(copy_record_button); jp_logf(JP_LOG_DEBUG, "Expense: connect_changed_signals\n");
gtk_widget_hide(delete_record_button); connected = 1;
gtk_widget_hide(new_record_button);
break; if(category_menu2){
case CLEAR_FLAG: g_signal_connect(G_OBJECT(category_menu2),"changed",G_CALLBACK(cb_re
gtk_widget_show(delete_record_button); cord_changed),NULL);
gtk_widget_show(copy_record_button); }
gtk_widget_show(new_record_button); if(menu_expense_type){
g_signal_connect(G_OBJECT(menu_expense_type),"changed",G_CALLBACK(cb
gtk_widget_hide(add_record_button); _record_changed),NULL);
gtk_widget_hide(apply_record_button); }
break; if(menu_payment){
default: g_signal_connect(G_OBJECT(menu_payment),"changed",G_CALLBACK(cb_reco
return; rd_changed),NULL);
} }
record_changed=new_state; if(menu_currency){
} g_signal_connect(G_OBJECT(menu_currency),"changed",G_CALLBACK(cb_rec
ord_changed),NULL);
static void cb_record_changed(GtkWidget *widget, gpointer data) }
{ g_signal_connect(G_OBJECT(spinner_mon), "changed",
jp_logf(JP_LOG_DEBUG, "cb_record_changed\n"); G_CALLBACK(cb_record_changed), NULL);
g_signal_connect(G_OBJECT(spinner_day), "changed",
if (record_changed==CLEAR_FLAG) { G_CALLBACK(cb_record_changed), NULL);
connect_changed_signals(DISCONNECT_SIGNALS); g_signal_connect(G_OBJECT(spinner_year), "changed",
if (GTK_CLIST(clist)->rows > 0) { G_CALLBACK(cb_record_changed), NULL);
set_new_button_to(MODIFY_FLAG); g_signal_connect(G_OBJECT(entry_amount), "changed",
} else { G_CALLBACK(cb_record_changed), NULL);
set_new_button_to(NEW_FLAG); g_signal_connect(G_OBJECT(entry_vendor), "changed",
} G_CALLBACK(cb_record_changed), NULL);
} g_signal_connect(G_OBJECT(entry_city), "changed",
} G_CALLBACK(cb_record_changed), NULL);
g_signal_connect(attendees_buffer, "changed",
static void connect_changed_signals(int con_or_dis) G_CALLBACK(cb_record_changed), NULL);
{ g_signal_connect(note_buffer, "changed",
int i; G_CALLBACK(cb_record_changed), NULL);
}
/* CONNECT */
if ((con_or_dis==CONNECT_SIGNALS) && (!connected)) { /* DISCONNECT */
jp_logf(JP_LOG_DEBUG, "Expense: connect_changed_signals\n"); if ((con_or_dis == DISCONNECT_SIGNALS) && (connected)) {
connected=1; jp_logf(JP_LOG_DEBUG, "Expense: disconnect_changed_signals\n");
connected = 0;
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) {
if (exp_cat_menu_item2[i]) { if(category_menu2) {
gtk_signal_connect(GTK_OBJECT(exp_cat_menu_item2[i]), "toggled", g_signal_handlers_disconnect_by_func(G_OBJECT(category_menu2), G_CAL
GTK_SIGNAL_FUNC(cb_record_changed), NULL); LBACK(cb_record_changed), NULL);
} }
}
for (i=0; i<MAX_EXPENSE_TYPES; i++) { if(menu_expense_type){
if (menu_item_expense_type[i]) { g_signal_handlers_disconnect_by_func(G_OBJECT(menu_expense_type),
gtk_signal_connect(GTK_OBJECT(menu_item_expense_type[i]), G_CALLBACK(cb_record_changed),
"toggled", NULL);
GTK_SIGNAL_FUNC(cb_record_changed), }
NULL); if(menu_payment){
} g_signal_handlers_disconnect_by_func(G_OBJECT(menu_payment),
} G_CALLBACK(cb_record_changed),
for (i=0; i<MAX_PAYMENTS; i++) { NULL);
if (menu_item_payment[i]) { }
gtk_signal_connect(GTK_OBJECT(menu_item_payment[i]), if(menu_currency){
"toggled", g_signal_handlers_disconnect_by_func(G_OBJECT(menu_currency),
GTK_SIGNAL_FUNC(cb_record_changed), G_CALLBACK(cb_record_changed),
NULL); NULL);
} }
}
for (i=0; i<MAX_CURRENCYS; i++) { g_signal_handlers_disconnect_by_func(G_OBJECT(spinner_mon),
if (menu_item_currency[i]) { G_CALLBACK(cb_record_changed), NULL);
gtk_signal_connect(GTK_OBJECT(menu_item_currency[i]), g_signal_handlers_disconnect_by_func(G_OBJECT(spinner_day),
"toggled", G_CALLBACK(cb_record_changed), NULL);
GTK_SIGNAL_FUNC(cb_record_changed), g_signal_handlers_disconnect_by_func(G_OBJECT(spinner_year),
NULL); G_CALLBACK(cb_record_changed), NULL);
} g_signal_handlers_disconnect_by_func(G_OBJECT(entry_amount),
} G_CALLBACK(cb_record_changed), NULL);
gtk_signal_connect(GTK_OBJECT(spinner_mon), "changed", g_signal_handlers_disconnect_by_func(G_OBJECT(entry_vendor),
GTK_SIGNAL_FUNC(cb_record_changed), NULL); G_CALLBACK(cb_record_changed), NULL);
gtk_signal_connect(GTK_OBJECT(spinner_day), "changed", g_signal_handlers_disconnect_by_func(G_OBJECT(entry_city),
GTK_SIGNAL_FUNC(cb_record_changed), NULL); G_CALLBACK(cb_record_changed), NULL);
gtk_signal_connect(GTK_OBJECT(spinner_year), "changed", g_signal_handlers_disconnect_by_func(attendees_buffer,
GTK_SIGNAL_FUNC(cb_record_changed), NULL); G_CALLBACK(cb_record_changed), NULL
gtk_signal_connect(GTK_OBJECT(entry_amount), "changed", );
GTK_SIGNAL_FUNC(cb_record_changed), NULL); g_signal_handlers_disconnect_by_func(note_buffer,
gtk_signal_connect(GTK_OBJECT(entry_vendor), "changed", G_CALLBACK(cb_record_changed), NULL
GTK_SIGNAL_FUNC(cb_record_changed), NULL); );
gtk_signal_connect(GTK_OBJECT(entry_city), "changed", }
GTK_SIGNAL_FUNC(cb_record_changed), NULL); }
g_signal_connect(attendees_buffer, "changed",
GTK_SIGNAL_FUNC(cb_record_changed), NULL); static void free_myexpense_list(struct MyExpense **PPmexp) {
g_signal_connect(note_buffer, "changed", struct MyExpense *mexp, *next_mexp;
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
} jp_logf(JP_LOG_DEBUG, "Expense: free_myexpense_list\n");
/* DISCONNECT */ for (mexp = *PPmexp; mexp; mexp = next_mexp) {
if ((con_or_dis==DISCONNECT_SIGNALS) && (connected)) { free_Expense(&(mexp->ex));
jp_logf(JP_LOG_DEBUG, "Expense: disconnect_changed_signals\n"); next_mexp = mexp->next;
connected=0; free(mexp);
}
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) { *PPmexp = NULL;
if (exp_cat_menu_item2[i]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(exp_cat_menu_item2[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NU
LL);
}
}
for (i=0; i<MAX_EXPENSE_TYPES; i++) {
if (menu_item_expense_type[i]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(menu_item_expense_type[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NU
LL);
}
}
for (i=0; i<MAX_PAYMENTS; i++) {
if (menu_item_payment[i]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(menu_item_payment[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NU
LL);
}
}
for (i=0; i<MAX_CURRENCYS; i++) {
if (menu_item_currency[i]) {
gtk_signal_disconnect_by_func(GTK_OBJECT(menu_item_currency[i]),
GTK_SIGNAL_FUNC(cb_record_changed), NU
LL);
}
}
gtk_signal_disconnect_by_func(GTK_OBJECT(spinner_mon),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
gtk_signal_disconnect_by_func(GTK_OBJECT(spinner_day),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
gtk_signal_disconnect_by_func(GTK_OBJECT(spinner_year),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
gtk_signal_disconnect_by_func(GTK_OBJECT(entry_amount),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
gtk_signal_disconnect_by_func(GTK_OBJECT(entry_vendor),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
gtk_signal_disconnect_by_func(GTK_OBJECT(entry_city),
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
g_signal_handlers_disconnect_by_func(attendees_buffer,
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
g_signal_handlers_disconnect_by_func(note_buffer,
GTK_SIGNAL_FUNC(cb_record_changed), NULL);
}
}
static void free_myexpense_list(struct MyExpense **PPmexp)
{
struct MyExpense *mexp, *next_mexp;
jp_logf(JP_LOG_DEBUG, "Expense: free_myexpense_list\n");
for (mexp = *PPmexp; mexp; mexp=next_mexp) {
free_Expense(&(mexp->ex));
next_mexp = mexp->next;
free(mexp);
}
*PPmexp=NULL;
} }
#define PLUGIN_MAJOR 1 #define PLUGIN_MAJOR 1
#define PLUGIN_MINOR 1 #define PLUGIN_MINOR 1
/* This is a mandatory plugin function. */ /* This is a mandatory plugin function. */
void plugin_version(int *major_version, int *minor_version) void plugin_version(int *major_version, int *minor_version) {
{ *major_version = PLUGIN_MAJOR;
*major_version = PLUGIN_MAJOR; *minor_version = PLUGIN_MINOR;
*minor_version = PLUGIN_MINOR;
} }
static int static_plugin_get_name(char *name, int len) static int static_plugin_get_name(char *name, int len) {
{ jp_logf(JP_LOG_DEBUG, "Expense: plugin_get_name\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_get_name\n"); snprintf(name, (size_t) len, "Expense %d.%d", PLUGIN_MAJOR, PLUGIN_MINOR);
snprintf(name, len, "Expense %d.%d", PLUGIN_MAJOR, PLUGIN_MINOR); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
/* This is a mandatory plugin function. */ /* This is a mandatory plugin function. */
int plugin_get_name(char *name, int len) int plugin_get_name(char *name, int len) {
{ return static_plugin_get_name(name, len);
return static_plugin_get_name(name, len);
} }
/* /*
* This is an optional plugin function. * This is an optional plugin function.
* This is the name that will show up in the plugins menu in J-Pilot. * This is the name that will show up in the plugins menu in J-Pilot.
*/ */
int plugin_get_menu_name(char *name, int len) int plugin_get_menu_name(char *name, int len) {
{ strncpy(name, _("Expense"), (size_t) len);
strncpy(name, _("Expense"), len); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
/* /*
* This is an optional plugin function. * This is an optional plugin function.
* This is the name that will show up in the plugins help menu in J-Pilot. * This is the name that will show up in the plugins help menu in J-Pilot.
* If this function is used then plugin_help must also be defined. * If this function is used then plugin_help must also be defined.
*/ */
int plugin_get_help_name(char *name, int len) int plugin_get_help_name(char *name, int len) {
{ g_snprintf(name, (gulong) len, _("About %s"), _("Expense"));
g_snprintf(name, len, _("About %s"), _("Expense")); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
/* /*
* This is an optional plugin function. * This is an optional plugin function.
* This is the palm database that will automatically be synced. * This is the palm database that will automatically be synced.
*/ */
int plugin_get_db_name(char *name, int len) int plugin_get_db_name(char *name, int len) {
{ strncpy(name, "ExpenseDB", (size_t) len);
strncpy(name, "ExpenseDB", len); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
/* /*
* A utility function for getting textual data from an enum. * A utility function for getting textual data from an enum.
*/ */
static char *get_entry_type(enum ExpenseType type) static char *get_entry_type(enum ExpenseType type) {
{ switch (type) {
switch(type) { case etAirfare:
case etAirfare: return _("Airfare");
return _("Airfare"); case etBreakfast:
case etBreakfast: return _("Breakfast");
return _("Breakfast"); case etBus:
case etBus: return _("Bus");
return _("Bus"); case etBusinessMeals:
case etBusinessMeals: return _("BusinessMeals");
return _("BusinessMeals"); case etCarRental:
case etCarRental: return _("CarRental");
return _("CarRental"); case etDinner:
case etDinner: return _("Dinner");
return _("Dinner"); case etEntertainment:
case etEntertainment: return _("Entertainment");
return _("Entertainment"); case etFax:
case etFax: return _("Fax");
return _("Fax"); case etGas:
case etGas: return _("Gas");
return _("Gas"); case etGifts:
case etGifts: return _("Gifts");
return _("Gifts"); case etHotel:
case etHotel: return _("Hotel");
return _("Hotel"); case etIncidentals:
case etIncidentals: return _("Incidentals");
return _("Incidentals"); case etLaundry:
case etLaundry: return _("Laundry");
return _("Laundry"); case etLimo:
case etLimo: return _("Limo");
return _("Limo"); case etLodging:
case etLodging: return _("Lodging");
return _("Lodging"); case etLunch:
case etLunch: return _("Lunch");
return _("Lunch"); case etMileage:
case etMileage: return _("Mileage");
return _("Mileage"); case etOther:
case etOther: return _("Other");
return _("Other"); case etParking:
case etParking: return _("Parking");
return _("Parking"); case etPostage:
case etPostage: return _("Postage");
return _("Postage"); case etSnack:
case etSnack: return _("Snack");
return _("Snack"); case etSubway:
case etSubway: return _("Subway");
return _("Subway"); case etSupplies:
case etSupplies: return _("Supplies");
return _("Supplies"); case etTaxi:
case etTaxi: return _("Taxi");
return _("Taxi"); case etTelephone:
case etTelephone: return _("Telephone");
return _("Telephone"); case etTips:
case etTips: return _("Tips");
return _("Tips"); case etTolls:
case etTolls: return _("Tolls");
return _("Tolls"); case etTrain:
case etTrain: return _("Train");
return _("Train"); default:
default: return NULL;
return NULL; }
} }
gboolean deleteExpenseRecord(GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data) {
int * i = gtk_tree_path_get_indices ( path ) ;
if(i[0] == row_selected){
struct MyExpense *mexp = NULL;
gtk_tree_model_get(model,iter,EXPENSE_DATA_COLUMN_ENUM,&mexp,-1);
deleteExpense(mexp,data);
return TRUE;
}
return FALSE;
}
void deleteExpense(struct MyExpense *mexp,gpointer data) {
int size;
unsigned char buf[0xFFFF];
buf_rec br;
int flag;
jp_logf(JP_LOG_DEBUG, "Expense: cb_delete\n");
flag = GPOINTER_TO_INT(data);
if (!mexp) {
return;
}
/* The record that we want to delete should be written to the pc file
* so that it can be deleted at sync time. We need the original record
* so that if it has changed on the pilot we can warn the user that
* the record has changed on the pilot. */
size = pack_Expense(&(mexp->ex), buf, 0xFFFF);
br.rt = mexp->rt;
br.unique_id = mexp->unique_id;
br.attrib = mexp->attrib;
br.buf = buf;
br.size = size;
if ((flag == MODIFY_FLAG) || (flag == DELETE_FLAG)) {
jp_delete_record("ExpenseDB", &br, DELETE_FLAG);
}
if (flag == DELETE_FLAG) {
/* when we redraw we want to go to the line above the deleted one */
if (row_selected > 0) {
row_selected--;
}
display_records();
}
} }
/* This function gets called when the "delete" button is pressed */ /* This function gets called when the "delete" button is pressed */
static void cb_delete(GtkWidget *widget, gpointer data) static void cb_delete(GtkWidget *widget, gpointer data) {
{ gtk_tree_model_foreach(GTK_TREE_MODEL(listStore), deleteExpenseRecord, data)
struct MyExpense *mexp; ;
int size; return;
unsigned char buf[0xFFFF];
buf_rec br;
int flag;
jp_logf(JP_LOG_DEBUG, "Expense: cb_delete\n");
flag=GPOINTER_TO_INT(data);
mexp = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected);
if (!mexp) {
return;
}
/* The record that we want to delete should be written to the pc file
* so that it can be deleted at sync time. We need the original record
* so that if it has changed on the pilot we can warn the user that
* the record has changed on the pilot. */
size = pack_Expense(&(mexp->ex), buf, 0xFFFF);
br.rt = mexp->rt;
br.unique_id = mexp->unique_id;
br.attrib = mexp->attrib;
br.buf = buf;
br.size = size;
if ((flag==MODIFY_FLAG) || (flag==DELETE_FLAG)) {
jp_delete_record("ExpenseDB", &br, DELETE_FLAG);
}
if (flag == DELETE_FLAG) {
/* when we redraw we want to go to the line above the deleted one */
if (clist_row_selected > 0) {
clist_row_selected--;
}
display_records();
}
} }
/* /*
* This is called when the "Clear" button is pressed. * This is called when the "Clear" button is pressed.
* It just clears out all the detail fields. * It just clears out all the detail fields.
*/ */
static void exp_clear_details(void) static void exp_clear_details(void) {
{ time_t ltime;
time_t ltime; struct tm *now;
struct tm *now; int new_cat;
int new_cat; int sorted_position;
int sorted_position;
jp_logf(JP_LOG_DEBUG, "Expense: exp_clear_details\n");
jp_logf(JP_LOG_DEBUG, "Expense: exp_clear_details\n");
time(&ltime);
time(&ltime); now = localtime(&ltime);
now = localtime(&ltime);
/* Disconnect signals to prevent callbacks while we change values */
/* Disconnect signals to prevent callbacks while we change values */ connect_changed_signals(DISCONNECT_SIGNALS);
connect_changed_signals(DISCONNECT_SIGNALS);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_mon), now->tm_mon + 1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_mon), now->tm_mon+1); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_day), now->tm_mday);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_day), now->tm_mday); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_year), now->tm_year + 1900
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_year), now->tm_year+1900); );
gtk_entry_set_text(GTK_ENTRY(entry_amount), ""); gtk_entry_set_text(GTK_ENTRY(entry_amount), "");
gtk_entry_set_text(GTK_ENTRY(entry_vendor), ""); gtk_entry_set_text(GTK_ENTRY(entry_vendor), "");
gtk_entry_set_text(GTK_ENTRY(entry_city), ""); gtk_entry_set_text(GTK_ENTRY(entry_city), "");
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(attendees_buffer), "", -1); gtk_text_buffer_set_text(GTK_TEXT_BUFFER(attendees_buffer), "", -1);
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(note_buffer), "", -1); gtk_text_buffer_set_text(GTK_TEXT_BUFFER(note_buffer), "", -1);
if (exp_category==CATEGORY_ALL) { if (exp_category == CATEGORY_ALL) {
new_cat = 0; new_cat = 0;
} else { } else {
new_cat = exp_category; new_cat = exp_category;
} }
sorted_position = find_sort_cat_pos(new_cat); sorted_position = find_sort_cat_pos(new_cat);
if (sorted_position<0) { if (sorted_position < 0) {
jp_logf(JP_LOG_WARN, _("Category is not legal\n")); jp_logf(JP_LOG_WARN, _("Category is not legal\n"));
} else { } else {
gtk_check_menu_item_set_active gtk_combo_box_set_active(GTK_COMBO_BOX(category_menu2),find_menu_cat_pos
(GTK_CHECK_MENU_ITEM(exp_cat_menu_item2[sorted_position]), TRUE); (sorted_position));
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu2), }
find_menu_cat_pos(sorted_position));
}
set_new_button_to(CLEAR_FLAG); set_new_button_to(CLEAR_FLAG);
connect_changed_signals(CONNECT_SIGNALS); connect_changed_signals(CONNECT_SIGNALS);
} }
/* returns position, position starts at zero */ /* returns position, position starts at zero */
static int currency_id_to_position(int currency) static int currency_id_to_position(int currency) {
{ int i;
int i; int found = 0;
int found=0;
for (i = 0; i < MAX_CURRENCYS; i++) {
for (i=0; i<MAX_CURRENCYS; i++) { if (glob_currency[i].currency == currency) {
if (glob_currency[i].currency==currency) { found = i;
found=i; break;
break; }
} }
} return found;
return found;
} }
/* returns currency id, position starts at zero */ /* returns currency id, position starts at zero */
static int position_to_currency_id(int position) static int position_to_currency_id(int position) {
{ if (position < MAX_CURRENCYS) {
if (position<MAX_CURRENCYS) { return glob_currency[position].currency;
return glob_currency[position].currency; } else {
} else { return 0;
return 0; }
} }
} gboolean
addNewExpenseRecord (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data) {
int * i = gtk_tree_path_get_indices ( path ) ;
if(i[0] == row_selected){
struct MyExpense *mexp = NULL;
gtk_tree_model_get(model,iter,EXPENSE_DATA_COLUMN_ENUM,&mexp,-1);
addNewExpenseRecordToDataStructure(mexp,data);
return TRUE;
}
return FALSE;
}
void addNewExpenseRecordToDataStructure(struct MyExpense *mexp, gpointer data) {
struct Expense ex;
buf_rec br;
const char *text;
unsigned char buf[0xFFFF];
int size;
int flag;
unsigned int unique_id = 0;
GtkTextIter start_iter;
GtkTextIter end_iter;
jp_logf(JP_LOG_DEBUG, "Expense: cb_add_new_record\n");
flag = GPOINTER_TO_INT(data);
if (flag == CLEAR_FLAG) {
exp_clear_details();
connect_changed_signals(DISCONNECT_SIGNALS);
set_new_button_to(NEW_FLAG);
return;
}
if ((flag != NEW_FLAG) && (flag != MODIFY_FLAG) && (flag != COPY_FLAG)) {
return;
}
if (flag == MODIFY_FLAG) {
if (!mexp) {
return;
}
unique_id = mexp->unique_id;
}
/* Grab details of record from widgets on right-hand side of screen */
ex.type = (enum ExpenseType) glob_detail_type;
ex.payment = (enum ExpensePayment) glob_detail_payment;
ex.currency = position_to_currency_id(glob_detail_currency_pos);
/* gtk_entry_get_text *does not* allocate memory */
text = gtk_entry_get_text(GTK_ENTRY(entry_amount));
ex.amount = (char *) text;
if (ex.amount[0] == '\0') {
ex.amount = NULL;
}
text = gtk_entry_get_text(GTK_ENTRY(entry_vendor));
ex.vendor = (char *) text;
if (ex.vendor[0] == '\0') {
ex.vendor = NULL;
}
text = gtk_entry_get_text(GTK_ENTRY(entry_city));
ex.city = (char *) text;
if (ex.city[0] == '\0') {
ex.city = NULL;
}
ex.date.tm_mon = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_mo
n)) - 1;
ex.date.tm_mday = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_d
ay));
ex.date.tm_year = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_y
ear)) - 1900;
ex.date.tm_hour = 12;
ex.date.tm_min = 0;
ex.date.tm_sec = 0;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(attendees_buffer), &start_iter, &
end_iter);
ex.attendees = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(attendees_buffer), &
start_iter, &end_iter, TRUE);
if (ex.attendees[0] == '\0') {
free(ex.attendees);
ex.attendees = NULL;
}
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(note_buffer), &start_iter, &end_i
ter);
ex.note = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(note_buffer), &start_iter
, &end_iter, TRUE);
if (ex.note[0] == '\0') {
free(ex.note);
ex.note = NULL;
}
/*
* The record must be packed into a palm record (blob of data)
* pack_Expense just happens to be already written in pilot-link,
* however, a pack function must be written for each record type.
*/
size = pack_Expense(&ex, buf, 0xFFFF);
if (ex.attendees) {
free(ex.attendees);
}
if (ex.note) {
free(ex.note);
}
/* This is a new record from the PC, and not yet on the palm */
br.rt = NEW_PC_REC;
/* jp_pc_write will give us a temporary PC unique ID. */
/* The palm will give us an "official" unique ID during the sync */
/* Any attributes go here. Usually just the category */
/* Get the category that is set from the menu */
if (GTK_IS_WIDGET(category_menu2)) {
br.attrib = get_selected_category_from_combo_box(GTK_COMBO_BOX(category_
menu2));
}
jp_logf(JP_LOG_DEBUG, "category is %d\n", br.attrib);
br.buf = buf;
br.size = size;
br.unique_id = 0;
if (flag == MODIFY_FLAG) {
cb_delete(NULL, data);
if ((mexp->rt == PALM_REC) || (mexp->rt == REPLACEMENT_PALM_REC)) {
/* This code is to keep the unique ID intact */
br.unique_id = unique_id;
br.rt = REPLACEMENT_PALM_REC;
}
}
/* Write out the record. It goes to the .pc3 file until it gets synced */
jp_pc_write("ExpenseDB", &br);
set_new_button_to(CLEAR_FLAG);
display_records();
return;
}
/* /*
* This function is called when the user presses the "Add" button. * This function is called when the user presses the "Add" button.
* We collect all of the data from the GUI and pack it into an expense * We collect all of the data from the GUI and pack it into an expense
* record and then write it out. * record and then write it out.
*/ */
static void cb_add_new_record(GtkWidget *widget, gpointer data) static void cb_add_new_record(GtkWidget *widget, gpointer data) {
{ if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(listStore), NULL) != 0) {
struct Expense ex; gtk_tree_model_foreach(GTK_TREE_MODEL(listStore), addNewExpenseRecord, d
buf_rec br; ata);
const char *text; }else {
unsigned char buf[0xFFFF]; /* no records exist in category yet. */
int size; addNewExpenseRecordToDataStructure(NULL,data);
int flag; }
int i;
unsigned int unique_id = 0;
struct MyExpense *mexp = NULL;
GtkTextIter start_iter;
GtkTextIter end_iter;
jp_logf(JP_LOG_DEBUG, "Expense: cb_add_new_record\n");
flag=GPOINTER_TO_INT(data);
if (flag==CLEAR_FLAG) {
exp_clear_details();
connect_changed_signals(DISCONNECT_SIGNALS);
set_new_button_to(NEW_FLAG);
return;
}
if ((flag!=NEW_FLAG) && (flag!=MODIFY_FLAG) && (flag!=COPY_FLAG)) {
return;
}
if (flag==MODIFY_FLAG) {
mexp = gtk_clist_get_row_data(GTK_CLIST(clist), clist_row_selected);
if (!mexp) {
return;
}
unique_id = mexp->unique_id;
}
/* Grab details of record from widgets on right-hand side of screen */
ex.type = glob_detail_type;
ex.payment = glob_detail_payment;
ex.currency = position_to_currency_id(glob_detail_currency_pos);
/* gtk_entry_get_text *does not* allocate memory */
text = gtk_entry_get_text(GTK_ENTRY(entry_amount));
ex.amount = (char *)text;
if (ex.amount[0]=='\0') {
ex.amount=NULL;
}
text = gtk_entry_get_text(GTK_ENTRY(entry_vendor));
ex.vendor = (char *)text;
if (ex.vendor[0]=='\0') {
ex.vendor=NULL;
}
text = gtk_entry_get_text(GTK_ENTRY(entry_city));
ex.city = (char *)text;
if (ex.city[0]=='\0') {
ex.city=NULL;
}
ex.date.tm_mon = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_mo
n)) - 1;;
ex.date.tm_mday = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_da
y));;
ex.date.tm_year = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner_ye
ar)) - 1900;;
ex.date.tm_hour = 12;
ex.date.tm_min = 0;
ex.date.tm_sec = 0;
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(attendees_buffer),&start_iter,&end
_iter);
ex.attendees = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(attendees_buffer),&st
art_iter,&end_iter,TRUE);
if (ex.attendees[0]=='\0') {
free(ex.attendees);
ex.attendees=NULL;
}
gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(note_buffer),&start_iter,&end_iter
);
ex.note = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(note_buffer),&start_iter,&
end_iter,TRUE);
if (ex.note[0]=='\0') {
free(ex.note);
ex.note=NULL;
}
/*
* The record must be packed into a palm record (blob of data)
* pack_Expense just happens to be already written in pilot-link,
* however, a pack function must be written for each record type.
*/
size = pack_Expense(&ex, buf, 0xFFFF);
if (ex.attendees) {
free(ex.attendees);
}
if (ex.note) {
free(ex.note);
}
/* This is a new record from the PC, and not yet on the palm */
br.rt = NEW_PC_REC;
/* jp_pc_write will give us a temporary PC unique ID. */
/* The palm will give us an "official" unique ID during the sync */
/* Any attributes go here. Usually just the category */
/* Get the category that is set from the menu */
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) {
if (GTK_IS_WIDGET(exp_cat_menu_item2[i])) {
if (GTK_CHECK_MENU_ITEM(exp_cat_menu_item2[i])->active) {
br.attrib = sort_l[i].cat_num;
break;
}
}
}
jp_logf(JP_LOG_DEBUG, "category is %d\n", br.attrib);
br.buf = buf;
br.size = size;
br.unique_id = 0;
if (flag==MODIFY_FLAG) {
cb_delete(NULL, data);
if ((mexp->rt==PALM_REC) || (mexp->rt==REPLACEMENT_PALM_REC)) {
/* This code is to keep the unique ID intact */
br.unique_id = unique_id;
br.rt = REPLACEMENT_PALM_REC;
}
}
/* Write out the record. It goes to the .pc3 file until it gets synced */
jp_pc_write("ExpenseDB", &br);
set_new_button_to(CLEAR_FLAG);
display_records();
return;
} }
/* /*
* This function just adds the record to the clist on the left side of * This function just adds the record to the treeView on the left side of
* the screen. * the screen.
*/ */
static int display_record(struct MyExpense *mexp, int at_row) static int display_record(struct MyExpense *mexp, int at_row, const char *datefo
{ rmat, GtkTreeIter *iter) {
char *Ptype; char *Ptype;
char date[12]; char date[12];
GdkColor color; GdkRGBA bgColor;
GdkColormap *colormap; gboolean showBgColor;
char *amount = "";
jp_logf(JP_LOG_DEBUG, "Expense: display_record\n");
jp_logf(JP_LOG_DEBUG, "Expense: display_record\n");
switch (mexp->rt) {
case NEW_PC_REC: switch (mexp->rt) {
case REPLACEMENT_PALM_REC: case NEW_PC_REC:
colormap = gtk_widget_get_colormap(clist); case REPLACEMENT_PALM_REC:
color.red = CLIST_NEW_RED; bgColor = get_color(LIST_NEW_RED, LIST_NEW_GREEN, LIST_NEW_BLUE);
color.green = CLIST_NEW_GREEN; showBgColor = TRUE;
color.blue = CLIST_NEW_BLUE; break;
gdk_color_alloc(colormap, &color); case DELETED_PALM_REC:
gtk_clist_set_background(GTK_CLIST(clist), at_row, &color); case DELETED_PC_REC:
break; bgColor = get_color(LIST_DEL_RED, LIST_DEL_GREEN, LIST_DEL_BLUE);
case DELETED_PALM_REC: showBgColor = TRUE;
case DELETED_PC_REC: break;
colormap = gtk_widget_get_colormap(clist); case MODIFIED_PALM_REC:
color.red = CLIST_DEL_RED; bgColor = get_color(LIST_MOD_RED, LIST_MOD_GREEN, LIST_MOD_BLUE);
color.green = CLIST_DEL_GREEN; showBgColor = TRUE;
color.blue = CLIST_DEL_BLUE; break;
gdk_color_alloc(colormap, &color); default:
gtk_clist_set_background(GTK_CLIST(clist), at_row, &color); if (mexp->attrib & dlpRecAttrSecret) {
break; bgColor = get_color(LIST_PRIVATE_RED, LIST_PRIVATE_GREEN, LIST_P
case MODIFIED_PALM_REC: RIVATE_BLUE);
colormap = gtk_widget_get_colormap(clist); showBgColor = TRUE;
color.red = CLIST_MOD_RED; } else {
color.green = CLIST_MOD_GREEN; showBgColor = FALSE;
color.blue = CLIST_MOD_BLUE; }
gdk_color_alloc(colormap, &color); }
gtk_clist_set_background(GTK_CLIST(clist), at_row, &color); gtk_list_store_append(listStore, iter);
break; sprintf(date, dateformat, mexp->ex.date.tm_mon + 1, mexp->ex.date.tm_mday);
default: Ptype = get_entry_type(mexp->ex.type);
if (mexp->attrib & dlpRecAttrSecret) { if (mexp->ex.amount) {
colormap = gtk_widget_get_colormap(clist); amount = mexp->ex.amount;
color.red = CLIST_PRIVATE_RED; }
color.green = CLIST_PRIVATE_GREEN; gtk_list_store_set(listStore, iter,
color.blue = CLIST_PRIVATE_BLUE; EXPENSE_DATE_COLUMN_ENUM, date,
gdk_color_alloc(colormap, &color); EXPENSE_TYPE_COLUMN_ENUM, Ptype,
gtk_clist_set_background(GTK_CLIST(clist), at_row, &color); EXPENSE_AMOUNT_COLUMN_ENUM, amount,
} else { EXPENSE_DATA_COLUMN_ENUM, mexp,
gtk_clist_set_background(GTK_CLIST(clist), at_row, NULL); EXPENSE_BACKGROUND_COLOR_ENUM, showBgColor ? &bgColor : N
} ULL,
} EXPENSE_BACKGROUND_COLOR_ENABLED_ENUM, showBgColor,
-1);
gtk_clist_set_row_data(GTK_CLIST(clist), at_row, mexp); return EXIT_SUCCESS;
}
sprintf(date, "%02d/%02d", mexp->ex.date.tm_mon+1, mexp->ex.date.tm_mday);
gtk_clist_set_text(GTK_CLIST(clist), at_row, 0, date); gboolean
selectExpenseRecordByRow(GtkTreeModel *model,
Ptype = get_entry_type(mexp->ex.type); GtkTreePath *path,
gtk_clist_set_text(GTK_CLIST(clist), at_row, 1, Ptype); GtkTreeIter *iter,
gpointer data) {
if (mexp->ex.amount) { int *i = gtk_tree_path_get_indices(path);
gtk_clist_set_text(GTK_CLIST(clist), at_row, 2, mexp->ex.amount); if (i[0] == row_selected) {
} GtkTreeSelection *selection = NULL;
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView));
gtk_tree_selection_select_path(selection, path);
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeView), path, gtk_tree_vie
w_get_column(treeView,EXPENSE_DATE_COLUMN_ENUM), FALSE, 1.0, 0.0);
return TRUE;
}
return EXIT_SUCCESS; return FALSE;
} }
/* /*
* This function lists the records in the clist on the left side of * This function lists the records in the treeView on the left side of
* the screen. * the screen.
*/ */
static void display_records(void) static void display_records(void) {
{ int num, i;
int num, i; int entries_shown;
int entries_shown; struct MyExpense *mexp;
struct MyExpense *mexp; GList *records;
GList *records; GList *temp_list;
GList *temp_list; buf_rec *br;
buf_rec *br; const char *dateformat = date_formats[get_pref_int_default(PREF_SHORTDATE, 0
gchar *empty_line[] = { "","","" }; )];
GtkTreeIter iter;
jp_logf(JP_LOG_DEBUG, "Expense: display_records\n");
jp_logf(JP_LOG_DEBUG, "Expense: display_records\n");
records=NULL;
records = NULL;
free_myexpense_list(&glob_myexpense_list);
free_myexpense_list(&glob_myexpense_list);
/* Clear left-hand side of window */
exp_clear_details(); /* Clear left-hand side of window */
exp_clear_details();
/* Freeze clist to prevent flicker during updating */ gtk_list_store_clear(GTK_LIST_STORE(listStore));
gtk_clist_freeze(GTK_CLIST(clist));
connect_changed_signals(DISCONNECT_SIGNALS); /* This function takes care of reading the Database for us */
gtk_signal_disconnect_by_func(GTK_OBJECT(clist), num = jp_read_DB_files("ExpenseDB", &records);
GTK_SIGNAL_FUNC(cb_clist_selection), NULL); if (-1 == num)
gtk_clist_clear(GTK_CLIST(clist)); return;
#ifdef __APPLE__
gtk_clist_thaw(GTK_CLIST(clist)); entries_shown = 0;
gtk_widget_hide(clist); for (i = 0, temp_list = records; temp_list; temp_list = temp_list->next, i++
gtk_widget_show_all(clist); ) {
gtk_clist_freeze(GTK_CLIST(clist)); if (temp_list->data) {
#endif br = temp_list->data;
} else {
/* This function takes care of reading the Database for us */
num = jp_read_DB_files("ExpenseDB", &records);
if (-1 == num)
return;
entries_shown = 0;
for (i=0, temp_list = records; temp_list; temp_list = temp_list->next, i++) {
if (temp_list->data) {
br=temp_list->data;
} else {
continue;
}
if (!br->buf) {
continue;
}
/* Since deleted and modified records are also returned and we don't
* want to see those we skip over them. */
if ((br->rt == DELETED_PALM_REC) ||
(br->rt == DELETED_PC_REC) ||
(br->rt == MODIFIED_PALM_REC) ) {
continue;
}
if (exp_category < NUM_EXP_CAT_ITEMS) {
if ( ((br->attrib & 0x0F) != exp_category) &&
exp_category != CATEGORY_ALL) {
continue; continue;
} }
} if (!br->buf) {
continue;
mexp = malloc(sizeof(struct MyExpense)); }
mexp->next = NULL;
mexp->attrib = br->attrib;
mexp->unique_id = br->unique_id;
mexp->rt = br->rt;
/* We need to unpack the record blobs from the database.
* unpack_Expense is already written in pilot-link, but normally
* an unpack must be written for each type of application */
if (unpack_Expense(&(mexp->ex), br->buf, br->size)!=0) {
gtk_clist_append(GTK_CLIST(clist), empty_line);
display_record(mexp, entries_shown);
entries_shown++;
}
/* Prepend entry at head of list */
mexp->next = glob_myexpense_list;
glob_myexpense_list = mexp;
}
jp_free_DB_records(&records);
/* Sort the clist */
gtk_clist_sort(GTK_CLIST(clist));
gtk_signal_connect(GTK_OBJECT(clist), "select_row",
GTK_SIGNAL_FUNC(cb_clist_selection), NULL);
/* Select the existing requested row, or row 0 if that is impossible */
if (clist_row_selected <= entries_shown) {
gtk_clist_select_row(GTK_CLIST(clist), clist_row_selected, 0);
if (!gtk_clist_row_is_visible(GTK_CLIST(clist), clist_row_selected)) {
gtk_clist_moveto(GTK_CLIST(clist), clist_row_selected, 0, 0.5, 0.0);
}
}
else
{
gtk_clist_select_row(GTK_CLIST(clist), 0, 0);
}
/* Unfreeze clist after all changes */
gtk_clist_thaw(GTK_CLIST(clist));
connect_changed_signals(CONNECT_SIGNALS); /* Since deleted and modified records are also returned and we don't
* want to see those we skip over them. */
if ((br->rt == DELETED_PALM_REC) ||
(br->rt == DELETED_PC_REC) ||
(br->rt == MODIFIED_PALM_REC)) {
continue;
}
if (exp_category < NUM_EXP_CAT_ITEMS) {
if (((br->attrib & 0x0F) != exp_category) &&
exp_category != CATEGORY_ALL) {
continue;
}
}
mexp = malloc(sizeof(struct MyExpense));
mexp->next = NULL;
mexp->attrib = br->attrib;
mexp->unique_id = br->unique_id;
mexp->rt = br->rt;
/* We need to unpack the record blobs from the database.
* unpack_Expense is already written in pilot-link, but normally
* an unpack must be written for each type of application */
if (unpack_Expense(&(mexp->ex), br->buf, br->size) != 0) {
display_record(mexp, entries_shown, dateformat, &iter);
entries_shown++;
}
/* Prepend entry at head of list */
mexp->next = glob_myexpense_list;
glob_myexpense_list = mexp;
}
jp_free_DB_records(&records);
/* Select the existing requested row, or row 0 if that is impossible */
if (row_selected <= entries_shown) {
gtk_tree_model_foreach(GTK_TREE_MODEL(listStore), selectExpenseRecordByR
ow, NULL);
} else {
row_selected = 0;
gtk_tree_model_foreach(GTK_TREE_MODEL(listStore), selectExpenseRecordByR
ow, NULL);
}
jp_logf(JP_LOG_DEBUG, "Expense: leave display_records\n"); jp_logf(JP_LOG_DEBUG, "Expense: leave display_records\n");
} }
/* Find position of category in sorted category array /* Find position of category in sorted category array
* via its assigned category number */ * via its assigned category number */
static int find_sort_cat_pos(int cat) static int find_sort_cat_pos(int cat) {
{ int i;
int i;
for (i = 0; i < NUM_EXP_CAT_ITEMS; i++) {
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) { if (sort_l[i].cat_num == cat) {
if (sort_l[i].cat_num==cat) { return i;
return i; }
} }
}
return -1; return -1;
} }
/* Find a category's position in the category menu. /* Find a category's position in the category menu.
* This is equal to the category number except for the Unfiled category. * This is equal to the category number except for the Unfiled category.
* The Unfiled category is always in the last position which changes as * The Unfiled category is always in the last position which changes as
* the number of categories changes */ * the number of categories changes */
static int find_menu_cat_pos(int cat) static int find_menu_cat_pos(int cat) {
{ int i;
int i;
if (cat != NUM_EXP_CAT_ITEMS - 1) {
if (cat != NUM_EXP_CAT_ITEMS-1) { return cat;
return cat; } else { /* Unfiled category */
} else { /* Unfiled category */ /* Count how many category entries are filled */
/* Count how many category entries are filled */ for (i = 0; i < NUM_EXP_CAT_ITEMS; i++) {
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) { if (!sort_l[i].Pcat[0]) {
if (!sort_l[i].Pcat[0]) { return i;
return i; }
} }
} return 0;
return 0; }
}
} }
static void cb_edit_cats(GtkWidget *widget, gpointer data) static void cb_edit_cats(GtkWidget *widget, gpointer data) {
{ struct ExpenseAppInfo ai;
struct ExpenseAppInfo ai; char full_name[256];
char full_name[256]; char buffer[65536];
char buffer[65536]; int num;
int num; size_t size;
size_t size; void *buf;
void *buf; struct pi_file *pf;
struct pi_file *pf;
jp_logf(JP_LOG_DEBUG, "cb_edit_cats\n"); jp_logf(JP_LOG_DEBUG, "cb_edit_cats\n");
jp_get_home_file_name("ExpenseDB.pdb", full_name, 250); jp_get_home_file_name("ExpenseDB.pdb", full_name, 250);
buf=NULL; buf = NULL;
memset(&ai, 0, sizeof(ai)); memset(&ai, 0, sizeof(ai));
pf = pi_file_open(full_name); pf = pi_file_open(full_name);
pi_file_get_app_info(pf, &buf, &size); pi_file_get_app_info(pf, &buf, &size);
num = unpack_ExpenseAppInfo(&ai, buf, size); num = unpack_ExpenseAppInfo(&ai, buf, size);
if (num <= 0) { if (num <= 0) {
jp_logf(JP_LOG_WARN, _("Error reading file: %s\n"), "ExpenseDB.pdb"); jp_logf(JP_LOG_WARN, _("Error reading file: %s\n"), "ExpenseDB.pdb");
return; return;
} }
pi_file_close(pf); pi_file_close(pf);
jp_edit_cats(widget, "ExpenseDB", &(ai.category)); jp_edit_cats(widget, "ExpenseDB", &(ai.category));
size = pack_ExpenseAppInfo(&ai, (unsigned char *)buffer, 65535); size = (size_t) pack_ExpenseAppInfo(&ai, (unsigned char *) buffer, 65535);
jp_pdb_file_write_app_block("ExpenseDB", buffer, size); jp_pdb_file_write_app_block("ExpenseDB", buffer, (int) size);
/* Force refresh and display of CATEGORY_ALL */ /* Force refresh and display of CATEGORY_ALL */
plugin_gui_refresh(-1); plugin_gui_refresh(-1);
} }
/* Called when left-hand category menu is used */ /* Called when left-hand category menu is used */
static void cb_category(GtkWidget *item, int selection) static void cb_category(GtkComboBox *item, int selection) {
{ int b;
int b; if (!item) return;
if (gtk_combo_box_get_active(GTK_COMBO_BOX(item)) < 0) {
if ((GTK_CHECK_MENU_ITEM(item))->active) { return;
if (exp_category == selection) { return; } }
int selectedItem = get_selected_category_from_combo_box(item);
b=dialog_save_changed_record_with_cancel(pane, record_changed); if (selectedItem == -1) {
if (b==DIALOG_SAID_1) { /* Cancel */ return;
int index, index2; }
if (exp_category==CATEGORY_ALL) { if (exp_category == selectedItem) { return; }
index = 0;
index2 = 0; b = dialog_save_changed_record_with_cancel(pane, record_changed);
} else { if (b == DIALOG_SAID_1) { /* Cancel */
index = find_sort_cat_pos(exp_category); int index, index2;
index2 = find_menu_cat_pos(index) + 1;
index += 1; if (exp_category == CATEGORY_ALL) {
} index = 0;
index2 = 0;
if (index<0) { } else {
index = find_sort_cat_pos(exp_category);
index2 = find_menu_cat_pos(index) + 1;
index += 1;
}
if (index < 0) {
jp_logf(JP_LOG_WARN, _("Category is not legal\n"));
} else {
gtk_combo_box_set_active(GTK_COMBO_BOX(category_menu1),index2);
}
return;
}
if (b == DIALOG_SAID_3) { /* Save */
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
}
if (selectedItem == CATEGORY_EDIT) {
cb_edit_cats(GTK_WIDGET(item), NULL);
} else {
exp_category = selectedItem;
}
jp_logf(JP_LOG_DEBUG, "cb_category() cat=%d\n", exp_category);
row_selected = 0;
display_records();
jp_logf(JP_LOG_DEBUG, "Leaving cb_category()\n");
}
static gboolean handleExpenseRowSelection(GtkTreeSelection *selection,
GtkTreeModel *model,
GtkTreePath *path,
gboolean path_currently_selected,
gpointer userdata) {
GtkTreeIter iter;
struct MyExpense *mexp;
int b;
int index, sorted_position;
int currency_position;
unsigned int unique_id = 0;
if ((gtk_tree_model_get_iter(model, &iter, path)) && (!path_currently_select
ed)) {
int *i = gtk_tree_path_get_indices(path);
row_selected = i[0];
gtk_tree_model_get(model, &iter, EXPENSE_DATA_COLUMN_ENUM, &mexp, -1);
jp_logf(JP_LOG_DEBUG, "Expense: handleExpenseRowSelection\n");
if ((record_changed == MODIFY_FLAG) || (record_changed == NEW_FLAG)) {
if (mexp != NULL) {
unique_id = mexp->unique_id;
}
/* We need to turn this "scroll with mouse held down" thing off */
button_set_for_motion(0);
b = dialog_save_changed_record(scrolled_window, record_changed);
if (b == DIALOG_SAID_2) {
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
}
set_new_button_to(CLEAR_FLAG);
if (unique_id) {
expense_find(unique_id);
}
return TRUE;
}
if (mexp == NULL) {
return TRUE;
}
set_new_button_to(CLEAR_FLAG);
/* Need to disconnect signals while changing values */
connect_changed_signals(DISCONNECT_SIGNALS);
index = mexp->attrib & 0x0F;
sorted_position = find_sort_cat_pos(index);
int pos = findSortedPostion(sorted_position, GTK_COMBO_BOX(category_menu
2));
if (pos != sorted_position && index != 0) {
/* Illegal category */
jp_logf(JP_LOG_DEBUG, "Category is not legal\n");
sorted_position = 0;
}
if (sorted_position < 0) {
jp_logf(JP_LOG_WARN, _("Category is not legal\n")); jp_logf(JP_LOG_WARN, _("Category is not legal\n"));
} else { }
gtk_check_menu_item_set_active gtk_combo_box_set_active(GTK_COMBO_BOX(category_menu2),find_menu_cat_pos
(GTK_CHECK_MENU_ITEM(exp_cat_menu_item1[index]), TRUE); (sorted_position));
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu1), index2)
; if (mexp->ex.type < MAX_EXPENSE_TYPES) {
} gtk_combo_box_set_active(GTK_COMBO_BOX(menu_expense_type),mexp->ex.t
ype);
return; } else {
} jp_logf(JP_LOG_WARN, _("Expense: Unknown expense type\n"));
if (b==DIALOG_SAID_3) { /* Save */ }
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); if (mexp->ex.payment < MAX_PAYMENTS) {
} gtk_combo_box_set_active(GTK_COMBO_BOX(menu_payment),mexp->ex.paymen
t);
if (selection==NUM_EXP_CAT_ITEMS+1) { } else {
cb_edit_cats(item, NULL); jp_logf(JP_LOG_WARN, _("Expense: Unknown payment type\n"));
} else { }
exp_category = selection; currency_position = currency_id_to_position(mexp->ex.currency);
}
jp_logf(JP_LOG_DEBUG, "cb_category() cat=%d\n", exp_category); gtk_combo_box_set_active(GTK_COMBO_BOX(menu_currency),currency_position)
;
clist_row_selected = 0;
display_records(); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_mon), mexp->ex.date.tm
jp_logf(JP_LOG_DEBUG, "Leaving cb_category()\n"); _mon + 1);
} gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_day), mexp->ex.date.tm
_mday);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_year), mexp->ex.date.t
m_year + 1900);
if (mexp->ex.amount) {
gtk_entry_set_text(GTK_ENTRY(entry_amount), mexp->ex.amount);
} else {
gtk_entry_set_text(GTK_ENTRY(entry_amount), "");
}
if (mexp->ex.vendor) {
gtk_entry_set_text(GTK_ENTRY(entry_vendor), mexp->ex.vendor);
} else {
gtk_entry_set_text(GTK_ENTRY(entry_vendor), "");
}
if (mexp->ex.city) {
gtk_entry_set_text(GTK_ENTRY(entry_city), mexp->ex.city);
} else {
gtk_entry_set_text(GTK_ENTRY(entry_city), "");
}
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(attendees_buffer), "", -1);
if (mexp->ex.attendees) {
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(attendees_buffer), mexp->ex
.attendees, -1);
}
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(note_buffer), "", -1);
if (mexp->ex.note) {
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(note_buffer), mexp->ex.note
, -1);
}
connect_changed_signals(CONNECT_SIGNALS);
jp_logf(JP_LOG_DEBUG, "Expense: leaving handleExpenseRowSelection\n");
}
return TRUE;
} }
/* /*
* This function just displays a record on the right hand side of the screen * All menus use this same callback function.
* (the details) after a row has been selected in the clist on the left.
*/ */
static void cb_clist_selection(GtkWidget *clist, static void cb_pulldown_menu(GtkComboBox *item, unsigned int value) {
gint row, int menu, sel;
gint column,
GdkEventButton *event,
gpointer data)
{
struct MyExpense *mexp;
int b;
int index, sorted_position;
int currency_position;
unsigned int unique_id = 0;
jp_logf(JP_LOG_DEBUG, "Expense: cb_clist_selection\n");
if ((record_changed==MODIFY_FLAG) || (record_changed==NEW_FLAG)) {
mexp = gtk_clist_get_row_data(GTK_CLIST(clist), row);
if (mexp!=NULL) {
unique_id = mexp->unique_id;
}
b=dialog_save_changed_record(scrolled_window, record_changed);
if (b==DIALOG_SAID_2) {
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
}
set_new_button_to(CLEAR_FLAG);
if (unique_id)
{
expense_find(unique_id);
} else {
clist_select_row(GTK_CLIST(clist), row, column);
}
return;
}
clist_row_selected = row;
mexp = gtk_clist_get_row_data(GTK_CLIST(clist), row);
if (mexp==NULL) {
return;
}
set_new_button_to(CLEAR_FLAG);
/* Need to disconnect signals while changing values */
connect_changed_signals(DISCONNECT_SIGNALS);
index = mexp->attrib & 0x0F;
sorted_position = find_sort_cat_pos(index);
if (exp_cat_menu_item2[sorted_position]==NULL) {
/* Illegal category */
jp_logf(JP_LOG_DEBUG, "Category is not legal\n");
sorted_position = 0;
}
if (sorted_position<0) {
jp_logf(JP_LOG_WARN, _("Category is not legal\n"));
} else {
gtk_check_menu_item_set_active
(GTK_CHECK_MENU_ITEM(exp_cat_menu_item2[sorted_position]), TRUE);
}
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu2),
find_menu_cat_pos(sorted_position));
if (mexp->ex.type < MAX_EXPENSE_TYPES) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
(menu_item_expense_type[mexp->ex.type]), TR
UE);
} else {
jp_logf(JP_LOG_WARN, _("Expense: Unknown expense type\n"));
}
if (mexp->ex.payment < MAX_PAYMENTS) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
(menu_item_payment[mexp->ex.payment]), TRUE
);
} else {
jp_logf(JP_LOG_WARN, _("Expense: Unknown payment type\n"));
}
currency_position = currency_id_to_position(mexp->ex.currency);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
(menu_item_currency[currency_position]), TRUE);
gtk_option_menu_set_history(GTK_OPTION_MENU(menu_expense_type), mexp->ex.type
);
gtk_option_menu_set_history(GTK_OPTION_MENU(menu_payment), mexp->ex.payment);
gtk_option_menu_set_history(GTK_OPTION_MENU(menu_currency), currency_position
);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_mon), mexp->ex.date.tm_mon+
1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_day), mexp->ex.date.tm_mday
);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_year), mexp->ex.date.tm_yea
r+1900);
if (mexp->ex.amount) {
gtk_entry_set_text(GTK_ENTRY(entry_amount), mexp->ex.amount);
} else {
gtk_entry_set_text(GTK_ENTRY(entry_amount), "");
}
if (mexp->ex.vendor) {
gtk_entry_set_text(GTK_ENTRY(entry_vendor), mexp->ex.vendor);
} else {
gtk_entry_set_text(GTK_ENTRY(entry_vendor), "");
}
if (mexp->ex.city) {
gtk_entry_set_text(GTK_ENTRY(entry_city), mexp->ex.city);
} else {
gtk_entry_set_text(GTK_ENTRY(entry_city), "");
}
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(attendees_buffer), "", -1);
if (mexp->ex.attendees) {
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(attendees_buffer), mexp->ex.atten
dees, -1);
}
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(note_buffer), "", -1);
if (mexp->ex.note) {
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(note_buffer), mexp->ex.note, -1);
}
connect_changed_signals(CONNECT_SIGNALS);
jp_logf(JP_LOG_DEBUG, "Expense: leaving cb_clist_selection\n"); jp_logf(JP_LOG_DEBUG, "Expense: cb_pulldown_menu\n");
}
/* if (!item)
* All menus use this same callback function. I use the value parameter return;
* to determine which menu was changed and which item was selected from it. if (gtk_combo_box_get_active(GTK_COMBO_BOX(item)) < 0){
*/ return;
static void cb_pulldown_menu(GtkWidget *item, unsigned int value) }
{
int menu, sel; sel = gtk_combo_box_get_active(GTK_COMBO_BOX(item));
menu = findSortedPostion(sel, GTK_COMBO_BOX(item));
jp_logf(JP_LOG_DEBUG, "Expense: cb_pulldown_menu\n"); switch (menu) {
case EXPENSE_TYPE:
if (!item) return; glob_detail_type = sel;
if (!(GTK_CHECK_MENU_ITEM(item))->active) return; break;
case EXPENSE_PAYMENT:
menu = (value & 0xFF00) >> 8; glob_detail_payment = sel;
sel = value & 0x00FF; break;
case EXPENSE_CURRENCY:
switch (menu) { glob_detail_currency_pos = sel;
case EXPENSE_TYPE: break;
glob_detail_type = sel; default:
break; break;
case EXPENSE_PAYMENT: }
glob_detail_payment = sel;
break;
case EXPENSE_CURRENCY:
glob_detail_currency_pos = sel;
break;
}
} }
/* /*
* Just a convenience function for passing in an array of strings and getting * Just a convenience function for passing in an array of strings and getting
* them all stuffed into a menu. * them all stuffed into a menu.
*/ */
static int make_menu(const char *items[], int menu_index, GtkWidget **Poption_me static int make_menu(const char *items[], int menu_index, GtkWidget **Poption_me
nu, nu) {
GtkWidget *menu_items[]) int i;
{
int i, item_num;
GSList *group;
GtkWidget *option_menu;
GtkWidget *menu_item;
GtkWidget *menu;
jp_logf(JP_LOG_DEBUG, "Expense: make_menu\n");
*Poption_menu = option_menu = gtk_option_menu_new();
menu = gtk_menu_new();
group = NULL;
for (i=0; items[i]; i++) {
menu_item = gtk_radio_menu_item_new_with_label(group, _(items[i]));
menu_items[i] = menu_item;
item_num = i;
gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
GTK_SIGNAL_FUNC(cb_pulldown_menu),
GINT_TO_POINTER(menu_index<<8 | item_num));
group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menu_item));
gtk_menu_append(GTK_MENU(menu), menu_item);
gtk_widget_show(menu_item);
}
gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
/* Make this one show up by default */
gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
gtk_widget_show(option_menu); jp_logf(JP_LOG_DEBUG, "Expense: make_menu\n");
GtkListStore *catListStore = gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_INT);
GtkTreeIter iter;
for (i = 0; items[i]; i++) {
gtk_list_store_append (catListStore, &iter);
gtk_list_store_set (catListStore, &iter, 0, _(items[i]), 1, menu_index,
-1);
}
*Poption_menu = gtk_combo_box_new_with_model(GTK_TREE_MODEL (catListStore));
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (*Poption_menu), renderer, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT (*Poption_menu), renderer,
"text", 0,
NULL);
g_signal_connect(G_OBJECT(*Poption_menu),"changed",G_CALLBACK(cb_pulldown_me
nu), NULL);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* /*
* This function makes all of the menus on the screen. * This function makes all of the menus on the screen.
*/ */
static void make_menus(void) static void make_menus(void) {
{ struct ExpenseAppInfo exp_app_info;
struct ExpenseAppInfo exp_app_info; unsigned char *buf;
unsigned char *buf; int buf_size;
int buf_size; int i;
int i; long char_set;
long char_set; char *cat_name;
char *cat_name;
const char *payment[MAX_PAYMENTS + 1] = {
const char *payment[MAX_PAYMENTS+1]={ N_("American Express"),
N_("American Express"), N_("Cash"),
N_("Cash"), N_("Check"),
N_("Check"), N_("Credit Card"),
N_("Credit Card"), N_("Master Card"),
N_("Master Card"), N_("Prepaid"),
N_("Prepaid"), N_("VISA"),
N_("VISA"), N_("Unfiled"),
N_("Unfiled"), NULL
NULL };
}; const char *expense_type[MAX_CURRENCYS + 1] = {
const char *expense_type[MAX_CURRENCYS+1]={ N_("Airfare"),
N_("Airfare"), N_("Breakfast"),
N_("Breakfast"), N_("Bus"),
N_("Bus"), N_("BusinessMeals"),
N_("BusinessMeals"), N_("CarRental"),
N_("CarRental"), N_("Dinner"),
N_("Dinner"), N_("Entertainment"),
N_("Entertainment"), N_("Fax"),
N_("Fax"), N_("Gas"),
N_("Gas"), N_("Gifts"),
N_("Gifts"), N_("Hotel"),
N_("Hotel"), N_("Incidentals"),
N_("Incidentals"), N_("Laundry"),
N_("Laundry"), N_("Limo"),
N_("Limo"), N_("Lodging"),
N_("Lodging"), N_("Lunch"),
N_("Lunch"), N_("Mileage"),
N_("Mileage"), N_("Other"),
N_("Other"), N_("Parking"),
N_("Parking"), N_("Postage"),
N_("Postage"), N_("Snack"),
N_("Snack"), N_("Subway"),
N_("Subway"), N_("Supplies"),
N_("Supplies"), N_("Taxi"),
N_("Taxi"), N_("Telephone"),
N_("Telephone"), N_("Tips"),
N_("Tips"), N_("Tolls"),
N_("Tolls"), N_("Train"),
N_("Train"), NULL
NULL };
}; const char *currency[MAX_CURRENCYS + 1];
const char *currency[MAX_CURRENCYS+1];
jp_logf(JP_LOG_DEBUG, "Expense: make_menus\n");
jp_logf(JP_LOG_DEBUG, "Expense: make_menus\n");
/* Point the currency array to the country names and NULL terminate it */
/* Point the currency array to the country names and NULL terminate it */ for (i = 0; i < MAX_CURRENCYS; i++) {
for (i=0; i<MAX_CURRENCYS; i++) { currency[i] = glob_currency[i].country;
currency[i]=glob_currency[i].country; }
} currency[MAX_CURRENCYS] = NULL;
currency[MAX_CURRENCYS]=NULL;
/* Do some category initialization */
/* Do some category initialization */
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) { /* This gets the application specific data out of the database for us.
exp_cat_menu_item2[i] = NULL; * We still need to write a function to unpack it from its blob form. */
} jp_get_app_info("ExpenseDB", &buf, &buf_size);
unpack_ExpenseAppInfo(&exp_app_info, buf, (size_t) buf_size);
/* This gets the application specific data out of the database for us. if (buf) {
* We still need to write a function to unpack it from its blob form. */ free(buf);
jp_get_app_info("ExpenseDB", &buf, &buf_size); }
unpack_ExpenseAppInfo(&exp_app_info, buf, buf_size);
if (buf) { get_pref(PREF_CHAR_SET, &char_set, NULL);
free(buf);
} for (i = 1; i < NUM_EXP_CAT_ITEMS; i++) {
cat_name = charset_p2newj(exp_app_info.category.name[i], 31, (int) char_
get_pref(PREF_CHAR_SET, &char_set, NULL); set);
strcpy(sort_l[i - 1].Pcat, cat_name);
for (i=1; i<NUM_EXP_CAT_ITEMS; i++) { free(cat_name);
cat_name = charset_p2newj(exp_app_info.category.name[i], 31, char_set); sort_l[i - 1].cat_num = i;
strcpy(sort_l[i-1].Pcat, cat_name); }
free(cat_name); /* put reserved 'Unfiled' category at end of list */
sort_l[i-1].cat_num = i; cat_name = charset_p2newj(exp_app_info.category.name[0], 31, (int) char_set)
} ;
/* put reserved 'Unfiled' category at end of list */ strcpy(sort_l[NUM_EXP_CAT_ITEMS - 1].Pcat, cat_name);
cat_name = charset_p2newj(exp_app_info.category.name[0], 31, char_set); free(cat_name);
strcpy(sort_l[NUM_EXP_CAT_ITEMS-1].Pcat, cat_name); sort_l[NUM_EXP_CAT_ITEMS - 1].cat_num = 0;
free(cat_name);
sort_l[NUM_EXP_CAT_ITEMS-1].cat_num = 0;
qsort(sort_l, NUM_EXP_CAT_ITEMS-1, sizeof(struct sorted_cats), cat_compare); qsort(sort_l, NUM_EXP_CAT_ITEMS - 1, sizeof(struct sorted_cats), cat_compare );
#ifdef JPILOT_DEBUG #ifdef JPILOT_DEBUG
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) { for (i=0; i<NUM_EXP_CAT_ITEMS; i++) {
printf("cat %d [%s]\n", sort_l[i].cat_num, sort_l[i].Pcat); printf("cat %d [%s]\n", sort_l[i].cat_num, sort_l[i].Pcat);
} }
#endif #endif
if ((exp_category != CATEGORY_ALL) && (exp_app_info.category.name[exp_categor if ((exp_category != CATEGORY_ALL) && (exp_app_info.category.name[exp_catego
y][0]=='\0')) { ry][0] == '\0')) {
exp_category=CATEGORY_ALL; exp_category = CATEGORY_ALL;
} }
make_category_menu(&category_menu1, exp_cat_menu_item1, make_category_menu(&category_menu1, sort_l, cb_category, TRUE, TRUE);
sort_l, cb_category, TRUE, TRUE); if(exp_category == CATEGORY_ALL){
/* Skip the ALL category for this menu */ gtk_combo_box_set_active(GTK_COMBO_BOX(category_menu1), 0);
make_category_menu(&category_menu2, exp_cat_menu_item2, }
sort_l, NULL, FALSE, FALSE); /* Skip the ALL category for this menu */
make_menu(payment, EXPENSE_PAYMENT, &menu_payment, menu_item_payment); make_category_menu(&category_menu2, sort_l, NULL, FALSE, FALSE);
make_menu(expense_type, EXPENSE_TYPE, &menu_expense_type, menu_item_expense_t
ype); make_menu(payment, EXPENSE_PAYMENT, &menu_payment);
make_menu(currency, EXPENSE_CURRENCY, &menu_currency, menu_item_currency); make_menu(expense_type, EXPENSE_TYPE, &menu_expense_type);
} make_menu(currency, EXPENSE_CURRENCY, &menu_currency);
}
/* returns 1 if found, 0 if not found */
static int expense_clist_find_id(GtkWidget *clist, gboolean
unsigned int unique_id, findExpenseRecord (GtkTreeModel *model,
int *found_at) GtkTreePath *path,
{ GtkTreeIter *iter,
int i, found; gpointer data) {
struct MyExpense *mexp; int uniqueId = GPOINTER_TO_INT(data);
if (uniqueId) {
jp_logf(JP_LOG_DEBUG, "Expense: expense_clist_find_id\n"); struct MyExpense *mexp = NULL;
*found_at = 0; gtk_tree_model_get(model,iter,EXPENSE_DATA_COLUMN_ENUM,&mexp,-1);
for (found = i = 0; i<=GTK_CLIST(clist)->rows; i++) { if(mexp->unique_id == uniqueId){
mexp = gtk_clist_get_row_data(GTK_CLIST(clist), i); GtkTreeSelection * selection = NULL;
if (!mexp) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView));
break; if(gtk_tree_selection_get_select_function(selection) == NULL) {
} gtk_tree_selection_set_select_function(selection, handleExpenseR
if (mexp->unique_id==unique_id) { owSelection, NULL, NULL);
found = TRUE; }
*found_at = i; gtk_tree_selection_select_path(selection, path);
break; gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeView), path, gtk_tree
} _view_get_column(treeView,EXPENSE_DATE_COLUMN_ENUM), FALSE, 1.0, 0.0);
} return TRUE;
}
return found; }
} return FALSE;
}
static int expense_find(int unique_id) static int expense_find(int unique_id) {
{ gtk_tree_model_foreach(GTK_TREE_MODEL(listStore), findExpenseRecord, GINT_TO
int r, found_at; _POINTER(unique_id));
return EXIT_SUCCESS;
jp_logf(JP_LOG_DEBUG, "Expense: expense_find, unique_id=%d\n",unique_id);
if (unique_id)
{
r = expense_clist_find_id(clist,
unique_id,
&found_at);
if (r) {
gtk_clist_select_row(GTK_CLIST(clist), found_at, 0);
if (!gtk_clist_row_is_visible(GTK_CLIST(clist), found_at)) {
gtk_clist_moveto(GTK_CLIST(clist), found_at, 0, 0.5, 0.0);
}
}
}
return EXIT_SUCCESS;
} }
/* /*
* This function is called by J-Pilot when the user selects this plugin * This function is called by J-Pilot when the user selects this plugin
* from the plugin menu, or from the search window when a search result * from the plugin menu, or from the search window when a search result
* record is chosen. In the latter case, unique ID will be set. This * record is chosen. In the latter case, unique ID will be set. This
* application should go directly to that record if the ID is set. * application should go directly to that record if the ID is set.
*/ */
int plugin_gui(GtkWidget *vbox, GtkWidget *hbox, unsigned int unique_id) int plugin_gui(GtkWidget *vbox, GtkWidget *hbox, unsigned int unique_id) {
{ GtkWidget *vbox1, *vbox2;
GtkWidget *vbox1, *vbox2; GtkWidget *hbox_temp;
GtkWidget *hbox_temp; GtkWidget *temp_vbox;
GtkWidget *temp_vbox; GtkWidget *label;
GtkWidget *label; GtkWidget *separator;
GtkWidget *separator; time_t ltime;
time_t ltime; struct tm *now;
struct tm *now; long ivalue;
long ivalue; long show_tooltips;
long show_tooltips; int i;
char *titles[]={"","",""}; int cycle_category = FALSE;
int i; int new_cat;
int cycle_category=FALSE; int index, index2;
int new_cat;
int index, index2; jp_logf(JP_LOG_DEBUG, "Expense: plugin gui started, unique_id=%d\n", unique_
id);
jp_logf(JP_LOG_DEBUG, "Expense: plugin gui started, unique_id=%d\n", unique_i
d); record_changed = CLEAR_FLAG;
record_changed = CLEAR_FLAG; if (difftime(time(NULL), plugin_last_time) > PLUGIN_MAX_INACTIVE_TIME) {
cycle_category = FALSE;
if (difftime(time(NULL), plugin_last_time) > PLUGIN_MAX_INACTIVE_TIME) { } else {
cycle_category = FALSE; cycle_category = TRUE;
} else { }
cycle_category = TRUE; /* reset time entered */
} plugin_last_time = time(NULL);
/* reset time entered */
plugin_last_time = time(NULL); /* called to display the result of a search */
if (unique_id) {
/* called to display the result of a search */ cycle_category = FALSE;
if (unique_id) { }
cycle_category = FALSE;
} row_selected = 0;
clist_row_selected = 0; time(&ltime);
now = localtime(&ltime);
time(&ltime);
now = localtime(&ltime); /************************************************************/
/* Build the GUI */
/************************************************************/
/* Build the GUI */ get_pref(PREF_SHOW_TOOLTIPS, &show_tooltips, NULL);
get_pref(PREF_SHOW_TOOLTIPS, &show_tooltips, NULL); /* Make the menus */
make_menus();
/* Make the menus */
make_menus(); pane = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
get_pref(PREF_EXPENSE_PANE, &ivalue, NULL);
pane = gtk_hpaned_new(); gtk_paned_set_position(GTK_PANED(pane), (gint) ivalue);
get_pref(PREF_EXPENSE_PANE, &ivalue, NULL);
gtk_paned_set_position(GTK_PANED(pane), ivalue); gtk_box_pack_start(GTK_BOX(hbox), pane, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox), pane, TRUE, TRUE, 5); /* left and right main boxes */
vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
/* left and right main boxes */ vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
vbox1 = gtk_vbox_new(FALSE, 0); gtk_paned_pack1(GTK_PANED(pane), vbox1, TRUE, FALSE);
vbox2 = gtk_vbox_new(FALSE, 0); gtk_paned_pack2(GTK_PANED(pane), vbox2, TRUE, FALSE);
gtk_paned_pack1(GTK_PANED(pane), vbox1, TRUE, FALSE);
gtk_paned_pack2(GTK_PANED(pane), vbox2, TRUE, FALSE);
gtk_widget_set_usize(GTK_WIDGET(vbox1), 0, 230); gtk_widget_set_size_request(GTK_WIDGET(vbox1), 0, 230);
gtk_widget_set_usize(GTK_WIDGET(vbox2), 0, 230); gtk_widget_set_size_request(GTK_WIDGET(vbox2), 0, 230);
/* Make accelerators for some buttons window */ /* Make accelerators for some buttons window */
#ifndef ENABLE_STOCK_BUTTONS #ifndef ENABLE_STOCK_BUTTONS
accel_group = gtk_accel_group_new(); accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(gtk_widget_get_toplevel(vbox)), accel_g gtk_window_add_accel_group(GTK_WINDOW(gtk_widget_get_toplevel(vbox)), accel_
roup); group);
#endif #endif
/************************************************************/ /************************************************************/
/* Left half of screen */ /* Left half of screen */
/* Make menu box for category menu */ /* Make menu box for category menu */
hbox_temp = gtk_hbox_new(FALSE, 0); hbox_temp = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(vbox1), hbox_temp, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox1), hbox_temp, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox_temp), category_menu1, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox_temp), category_menu1, TRUE, TRUE, 0);
/* Scrolled Window */ /* Scrolled Window */
scrolled_window = gtk_scrolled_window_new(NULL, NULL); scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0); gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(vbox1), scrolled_window, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox1), scrolled_window, TRUE, TRUE, 0);
/* Clist */ listStore = gtk_list_store_new(EXPENSE_NUM_COLS, G_TYPE_STRING, G_TYPE_STRIN
clist = gtk_clist_new_with_titles(3, titles); G, G_TYPE_STRING,
G_TYPE_POINTER, GDK_TYPE_RGBA, G_TYPE_BOOLEAN
gtk_clist_set_column_title(GTK_CLIST(clist), 0, _("Date")); );
gtk_clist_set_column_title(GTK_CLIST(clist), 1, _("Type")); treeView = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(listSto
gtk_clist_set_column_title(GTK_CLIST(clist), 2, _("Amount")); re)));
GtkCellRenderer *dateRenderer = gtk_cell_renderer_text_new();
/* auto resize is used in all the other application clists but here GtkCellRenderer *typeRenderer = gtk_cell_renderer_text_new();
* it produces a cramped layout so a minimum width is specified */ GtkCellRenderer *amountRenderer = gtk_cell_renderer_text_new();
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 0, TRUE); GtkTreeViewColumn *dateColumn = gtk_tree_view_column_new_with_attributes("Da
gtk_clist_set_column_min_width(GTK_CLIST(clist), 0, 44); te",
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 1, TRUE); dat
gtk_clist_set_column_min_width(GTK_CLIST(clist), 1, 100); eRenderer,
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 2, FALSE); "te
xt", EXPENSE_DATE_COLUMN_ENUM,
gtk_clist_column_titles_active(GTK_CLIST(clist)); "ce
gtk_signal_connect(GTK_OBJECT(clist), "click_column", ll-background-rgba",
GTK_SIGNAL_FUNC (cb_clist_click_column), NULL); EXP
ENSE_BACKGROUND_COLOR_ENUM,
gtk_signal_connect(GTK_OBJECT(clist), "select_row", "ce
GTK_SIGNAL_FUNC(cb_clist_selection), ll-background-set",
NULL); EXP
gtk_clist_set_shadow_type(GTK_CLIST(clist), SHADOW); ENSE_BACKGROUND_COLOR_ENABLED_ENUM,
gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE); NUL
L);
/* Restore previous sorting configuration */ GtkTreeViewColumn *typeColumn = gtk_tree_view_column_new_with_attributes("Ty
get_pref(PREF_EXPENSE_SORT_COLUMN, &ivalue, NULL); pe",
clist_col_selected = ivalue; typ
gtk_clist_set_sort_column(GTK_CLIST(clist), clist_col_selected); eRenderer,
switch (clist_col_selected) { "te
case EXP_DATE_COLUMN: /* Date column */ xt", EXPENSE_TYPE_COLUMN_ENUM,
gtk_clist_set_compare_func(GTK_CLIST(clist),sort_compare_date); "ce
break; ll-background-rgba",
default: /* All other columns can use GTK default sort function */ EXP
gtk_clist_set_compare_func(GTK_CLIST(clist),NULL); ENSE_BACKGROUND_COLOR_ENUM,
break; "ce
} ll-background-set",
get_pref(PREF_EXPENSE_SORT_ORDER, &ivalue, NULL); EXP
gtk_clist_set_sort_type(GTK_CLIST(clist), ivalue); ENSE_BACKGROUND_COLOR_ENABLED_ENUM,
NUL
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(clist)); L);
GtkTreeViewColumn *amountColumn = gtk_tree_view_column_new_with_attributes("
/************************************************************/ Amount",
/* Right half of screen */ a
hbox_temp = gtk_hbox_new(FALSE, 3); mountRenderer,
gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0); "
text", EXPENSE_AMOUNT_COLUMN_ENUM,
/* Delete, Copy, New, etc. buttons */ "
CREATE_BUTTON(delete_record_button, _("Delete"), DELETE, _("Delete the select cell-background-rgba",
ed record"), GDK_d, GDK_CONTROL_MASK, "Ctrl+D"); E
gtk_signal_connect(GTK_OBJECT(delete_record_button), "clicked", XPENSE_BACKGROUND_COLOR_ENUM,
GTK_SIGNAL_FUNC(cb_delete), "
GINT_TO_POINTER(DELETE_FLAG)); cell-background-set",
E
CREATE_BUTTON(copy_record_button, _("Copy"), COPY, _("Copy the selected recor XPENSE_BACKGROUND_COLOR_ENABLED_ENUM,
d"), GDK_c, GDK_CONTROL_MASK|GDK_SHIFT_MASK, "Ctrl+Shift+C") N
gtk_signal_connect(GTK_OBJECT(copy_record_button), "clicked", ULL);
GTK_SIGNAL_FUNC(cb_add_new_record), gtk_tree_view_column_set_sort_column_id(dateColumn, EXPENSE_DATE_COLUMN_ENUM
GINT_TO_POINTER(COPY_FLAG)); );
gtk_tree_view_column_set_sort_column_id(typeColumn, EXPENSE_TYPE_COLUMN_ENUM
CREATE_BUTTON(new_record_button, _("New Record"), NEW, _("Add a new record"), );
GDK_n, GDK_CONTROL_MASK, "Ctrl+N") gtk_tree_view_column_set_sort_column_id(amountColumn, EXPENSE_AMOUNT_COLUMN_
gtk_signal_connect(GTK_OBJECT(new_record_button), "clicked", ENUM);
GTK_SIGNAL_FUNC(cb_add_new_record),
GINT_TO_POINTER(CLEAR_FLAG)); gtk_tree_view_insert_column(treeView, dateColumn, EXPENSE_DATE_COLUMN_ENUM);
gtk_tree_view_insert_column(treeView, typeColumn, EXPENSE_TYPE_COLUMN_ENUM);
CREATE_BUTTON(add_record_button, _("Add Record"), ADD, _("Add the new record" gtk_tree_view_insert_column(treeView, amountColumn, EXPENSE_AMOUNT_COLUMN_EN
), GDK_Return, GDK_CONTROL_MASK, "Ctrl+Enter") UM);
gtk_signal_connect(GTK_OBJECT(add_record_button), "clicked", gtk_tree_view_column_set_clickable(dateColumn, gtk_true());
GTK_SIGNAL_FUNC(cb_add_new_record), gtk_tree_view_column_set_clickable(typeColumn, gtk_true());
GINT_TO_POINTER(NEW_FLAG)); gtk_tree_view_column_set_clickable(amountColumn, gtk_true());
gtk_tree_view_column_set_sizing(dateColumn, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_column_set_min_width(dateColumn, 44);
gtk_tree_view_column_set_sizing(typeColumn, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_column_set_min_width(typeColumn, 100);
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeVi
ew)),
GTK_SELECTION_BROWSE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
GtkTreeSelection *treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(
treeView));
gtk_tree_selection_set_select_function(treeSelection, handleExpenseRowSelect
ion, NULL, NULL);
gtk_widget_set_events(GTK_WIDGET(treeView), GDK_BUTTON1_MOTION_MASK);
g_signal_connect (G_OBJECT(treeView), "motion_notify_event",
G_CALLBACK(motion_notify_event), NULL);
g_signal_connect (G_OBJECT(treeView), "button-press-event",
G_CALLBACK(button_pressed_for_motion), NULL);
g_signal_connect (G_OBJECT(treeView), "button-release-event",
G_CALLBACK(button_released_for_motion), NULL);
/* Restore previous sorting configuration */
get_pref(PREF_EXPENSE_SORT_COLUMN, &ivalue, NULL);
column_selected = (int) ivalue;
for (int x = 0; x < EXPENSE_NUM_COLS - 3; x++) {
gtk_tree_view_column_set_sort_indicator(gtk_tree_view_get_column(GTK_TRE
E_VIEW(treeView), x), gtk_false());
}
gtk_tree_view_column_set_sort_indicator(gtk_tree_view_get_column(GTK_TREE_VI
EW(treeView), column_selected),
gtk_true());
get_pref(PREF_EXPENSE_SORT_ORDER, &ivalue, NULL);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(listStore), EXPENSE_DATE_C
OLUMN_ENUM, sortDateColumn,
GINT_TO_POINTER(EXPENSE_DATE_COLUMN_ENUM), N
ULL);
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(listStore), column_se
lected, (GtkSortType) ivalue);
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(treeView));
/************************************************************/
/* Right half of screen */
hbox_temp = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
gtk_box_pack_start(GTK_BOX(vbox2), hbox_temp, FALSE, FALSE, 0);
/* Delete, Copy, New, etc. buttons */
CREATE_BUTTON(delete_record_button, _("Delete"), DELETE, _("Delete the selec
ted record"), GDK_d, GDK_CONTROL_MASK,
"Ctrl+D")
g_signal_connect(G_OBJECT(delete_record_button), "clicked",
G_CALLBACK(cb_delete),
GINT_TO_POINTER(DELETE_FLAG));
CREATE_BUTTON(copy_record_button, _("Copy"), COPY, _("Copy the selected reco
rd"), GDK_c,
GDK_CONTROL_MASK | GDK_SHIFT_MASK, "Ctrl+Shift+C")
g_signal_connect(G_OBJECT(copy_record_button), "clicked",
G_CALLBACK(cb_add_new_record),
GINT_TO_POINTER(COPY_FLAG));
CREATE_BUTTON(new_record_button, _("New Record"), NEW, _("Add a new record")
, GDK_n, GDK_CONTROL_MASK, "Ctrl+N")
g_signal_connect(G_OBJECT(new_record_button), "clicked",
G_CALLBACK(cb_add_new_record),
GINT_TO_POINTER(CLEAR_FLAG));
CREATE_BUTTON(add_record_button, _("Add Record"), ADD, _("Add the new record
"), GDK_KEY_Return, GDK_CONTROL_MASK,
"Ctrl+Enter")
g_signal_connect(G_OBJECT(add_record_button), "clicked",
G_CALLBACK(cb_add_new_record),
GINT_TO_POINTER(NEW_FLAG));
#ifndef ENABLE_STOCK_BUTTONS #ifndef ENABLE_STOCK_BUTTONS
gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(GTK_BIN(add_record_button)->child)), gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(gtk_bin_get_child(GTK_BIN(add_recor
"label_high"); d_button)))),
"label_high");
#endif #endif
CREATE_BUTTON(apply_record_button, _("Apply Changes"), APPLY, _("Commit the m CREATE_BUTTON(apply_record_button, _("Apply Changes"), APPLY, _("Commit the
odifications"), GDK_Return, GDK_CONTROL_MASK, "Ctrl+Enter") modifications"), GDK_KEY_Return,
gtk_signal_connect(GTK_OBJECT(apply_record_button), "clicked", GDK_CONTROL_MASK, "Ctrl+Enter")
GTK_SIGNAL_FUNC(cb_add_new_record), g_signal_connect(G_OBJECT(apply_record_button), "clicked",
GINT_TO_POINTER(MODIFY_FLAG)); G_CALLBACK(cb_add_new_record),
GINT_TO_POINTER(MODIFY_FLAG));
#ifndef ENABLE_STOCK_BUTTONS #ifndef ENABLE_STOCK_BUTTONS
gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(GTK_BIN(apply_record_button)->child) gtk_widget_set_name(GTK_WIDGET(GTK_LABEL(gtk_bin_get_child(GTK_BIN(apply_rec
), ord_button)))),
"label_high"); "label_high");
#endif #endif
/*Separator */ /*Separator */
separator = gtk_hseparator_new(); separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
gtk_box_pack_start(GTK_BOX(vbox2), separator, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox2), separator, FALSE, FALSE, 5);
table = gtk_table_new(8, 2, FALSE); /* Grid */
gtk_box_pack_start(GTK_BOX(vbox2), table, FALSE, FALSE, 0); grid = gtk_grid_new();
gtk_grid_set_column_homogeneous(GTK_GRID(grid), FALSE);
/* Category Menu */ gtk_box_pack_start(GTK_BOX(vbox2), grid, TRUE, TRUE, 5);
label = gtk_label_new(_("Category:"));
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); /* Category Menu */
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), label = gtk_label_new(_("Category:"));
0, 1, 0, 1, GTK_FILL, GTK_FILL, 2, 0); gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(category_menu2), gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
1, 2, 0, 1); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
/* Type Menu */
label = gtk_label_new(_("Type:")); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 0, 1, 1);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), gtk_widget_set_halign(GTK_WIDGET(category_menu2), GTK_ALIGN_FILL);
0, 1, 1, 2, GTK_FILL, GTK_FILL, 2, 0); gtk_widget_set_valign(GTK_WIDGET(category_menu2), GTK_ALIGN_CENTER);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(menu_expense_type), gtk_widget_set_hexpand(GTK_WIDGET(category_menu2), TRUE);
1, 2, 1, 2);
gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(category_menu2), 1, 0, 2, 1);
/* Payment Menu */
label = gtk_label_new(_("Payment:")); /* Type Menu */
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); label = gtk_label_new(_("Type:"));
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
0, 1, 2, 3, GTK_FILL, GTK_FILL, 2, 0); gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(menu_payment), gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
1, 2, 2, 3); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
/* Currency Menu */ gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 1, 1, 1);
label = gtk_label_new(_("Currency:"));
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_widget_set_halign(GTK_WIDGET(menu_expense_type), GTK_ALIGN_FILL);
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), gtk_widget_set_valign(GTK_WIDGET(menu_expense_type), GTK_ALIGN_CENTER);
0, 1, 3, 4, GTK_FILL, GTK_FILL, 2, 0); gtk_widget_set_hexpand(GTK_WIDGET(menu_expense_type), TRUE);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(menu_currency),
1, 2, 3, 4); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(menu_expense_type), 1, 1, 2, 1);
/* Date Spinners */ /* Payment Menu */
label = gtk_label_new(_("Date:")); label = gtk_label_new(_("Payment:"));
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.8); gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
0, 1, 4, 5, GTK_FILL, GTK_FILL, 2, 0); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
hbox_temp = gtk_hbox_new(FALSE, 0);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(hbox_temp), gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 2, 1, 1);
1, 2, 4, 5);
gtk_widget_set_halign(GTK_WIDGET(menu_payment), GTK_ALIGN_FILL);
/* Month spinner */ gtk_widget_set_valign(GTK_WIDGET(menu_payment), GTK_ALIGN_CENTER);
temp_vbox = gtk_vbox_new(FALSE, 0); gtk_widget_set_hexpand(GTK_WIDGET(menu_payment), TRUE);
gtk_box_pack_start(GTK_BOX(hbox_temp), temp_vbox, FALSE, FALSE, 0);
label = gtk_label_new(_("Month:")); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(menu_payment), 1, 2, 2, 1);
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
gtk_box_pack_start(GTK_BOX(temp_vbox), label, FALSE, TRUE, 0); /* Currency Menu */
label = gtk_label_new(_("Currency:"));
adj_mon = GTK_ADJUSTMENT(gtk_adjustment_new(now->tm_mon+1, 1.0, 12.0, 1.0, gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
5.0, 0.0)); gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
spinner_mon = gtk_spin_button_new(adj_mon, 0, 0); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner_mon), FALSE); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner_mon), TRUE);
gtk_box_pack_start(GTK_BOX(temp_vbox), spinner_mon, FALSE, TRUE, 0); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 3, 1, 1);
/* Day spinner */ gtk_widget_set_halign(GTK_WIDGET(menu_currency), GTK_ALIGN_FILL);
temp_vbox = gtk_vbox_new(FALSE, 0); gtk_widget_set_valign(GTK_WIDGET(menu_currency), GTK_ALIGN_CENTER);
gtk_box_pack_start(GTK_BOX(hbox_temp), temp_vbox, FALSE, FALSE, 0); gtk_widget_set_hexpand(GTK_WIDGET(menu_currency), TRUE);
label = gtk_label_new(_("Day:"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(menu_currency), 1, 3, 2, 1);
gtk_box_pack_start(GTK_BOX(temp_vbox), label, FALSE, TRUE, 0);
/* Date Spinners */
adj_day = GTK_ADJUSTMENT(gtk_adjustment_new(now->tm_mday, 1.0, 31.0, 1.0, label = gtk_label_new(_("Date:"));
5.0, 0.0)); gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
spinner_day = gtk_spin_button_new(adj_day, 0, 0); gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner_day), FALSE); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner_day), TRUE); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
gtk_box_pack_start(GTK_BOX(temp_vbox), spinner_day, FALSE, TRUE, 0);
gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 4, 1, 1);
/* Year spinner */
temp_vbox = gtk_vbox_new(FALSE, 0); hbox_temp = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(hbox_temp), temp_vbox, FALSE, FALSE, 0); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(hbox_temp), 1, 4, 2, 1);
label = gtk_label_new(_("Year:"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); /* Month spinner */
gtk_box_pack_start(GTK_BOX(temp_vbox), label, FALSE, TRUE, 0); temp_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(hbox_temp), temp_vbox, FALSE, FALSE, 0);
adj_year = GTK_ADJUSTMENT(gtk_adjustment_new(now->tm_year+1900, 0.0, 2037.0, label = gtk_label_new(_("Month:"));
1.0, 100.0, 0.0)); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_START);
spinner_year = gtk_spin_button_new(adj_year, 0, 0); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner_year), FALSE); gtk_box_pack_start(GTK_BOX(temp_vbox), label, FALSE, TRUE, 0);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner_year), TRUE);
gtk_box_pack_start(GTK_BOX(temp_vbox), spinner_year, FALSE, TRUE, 0); adj_mon = GTK_ADJUSTMENT(gtk_adjustment_new(now->tm_mon + 1, 1.0, 12.0, 1.0,
gtk_widget_set_usize(spinner_year, 55, 0); 5.0, 0.0));
spinner_mon = gtk_spin_button_new(adj_mon, 0, 0);
/* Amount Entry */ gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner_mon), FALSE);
label = gtk_label_new(_("Amount:")); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner_mon), TRUE);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_box_pack_start(GTK_BOX(temp_vbox), spinner_mon, FALSE, TRUE, 0);
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label),
0, 1, 5, 6, GTK_FILL, GTK_FILL, 2, 0); /* Day spinner */
entry_amount = gtk_entry_new(); temp_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
entry_set_multiline_truncate(GTK_ENTRY(entry_amount), TRUE); gtk_box_pack_start(GTK_BOX(hbox_temp), temp_vbox, FALSE, FALSE, 0);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(entry_amount), label = gtk_label_new(_("Day:"));
1, 2, 5, 6); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_START);
gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
/* Vendor Entry */ gtk_box_pack_start(GTK_BOX(temp_vbox), label, FALSE, TRUE, 0);
label = gtk_label_new(_("Vendor:"));
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); adj_day = GTK_ADJUSTMENT(gtk_adjustment_new(now->tm_mday, 1.0, 31.0, 1.0,
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), 5.0, 0.0));
0, 1, 6, 7, GTK_FILL, GTK_FILL, 2, 0); spinner_day = gtk_spin_button_new(adj_day, 0, 0);
entry_vendor = gtk_entry_new(); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner_day), FALSE);
entry_set_multiline_truncate(GTK_ENTRY(entry_vendor), TRUE); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner_day), TRUE);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(entry_vendor), gtk_box_pack_start(GTK_BOX(temp_vbox), spinner_day, FALSE, TRUE, 0);
1, 2, 6, 7);
/* Year spinner */
/* City */ temp_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
label = gtk_label_new(_("City:")); gtk_box_pack_start(GTK_BOX(hbox_temp), temp_vbox, FALSE, FALSE, 0);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); label = gtk_label_new(_("Year:"));
gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_START);
0, 1, 7, 8, GTK_FILL, GTK_FILL, 2, 0); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
entry_city = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(temp_vbox), label, FALSE, TRUE, 0);
entry_set_multiline_truncate(GTK_ENTRY(entry_city), TRUE);
gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(entry_city), adj_year = GTK_ADJUSTMENT(gtk_adjustment_new(now->tm_year + 1900, 0.0, 2037.
1, 2, 7, 8); 0,
1.0, 100.0, 0.0));
/* Attendees */ spinner_year = gtk_spin_button_new(adj_year, 0, 0);
label = gtk_label_new(_("Attendees")); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner_year), FALSE);
gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner_year), TRUE);
gtk_box_pack_start(GTK_BOX(temp_vbox), spinner_year, FALSE, TRUE, 0);
/* Attendees textbox */ gtk_widget_set_size_request(spinner_year, 55, 0);
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
/*gtk_widget_set_usize(GTK_WIDGET(scrolled_window), 150, 0); */ /* Amount Entry */
gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0); label = gtk_label_new(_("Amount:"));
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
attendees = gtk_text_view_new();
attendees_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(attendees) gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 5, 1, 1);
));
gtk_text_view_set_editable(GTK_TEXT_VIEW(attendees), TRUE); entry_amount = gtk_entry_new();
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(attendees), GTK_WRAP_WORD); entry_set_multiline_truncate(GTK_ENTRY(entry_amount), TRUE);
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(attendees)); gtk_widget_set_halign(GTK_WIDGET(entry_amount), GTK_ALIGN_FILL);
gtk_widget_set_valign(GTK_WIDGET(entry_amount), GTK_ALIGN_CENTER);
label = gtk_label_new(_("Note")); gtk_widget_set_hexpand(GTK_WIDGET(entry_amount), TRUE);
gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_amount), 1, 5, 2, 1);
/* Note textbox */ /* Vendor Entry */
scrolled_window = gtk_scrolled_window_new(NULL, NULL); label = gtk_label_new(_("Vendor:"));
/*gtk_widget_set_usize(GTK_WIDGET(scrolled_window), 150, 0); */ gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0); gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
gtk_box_pack_start(GTK_BOX(vbox2), scrolled_window, TRUE, TRUE, 0);
gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 6, 1, 1);
note = gtk_text_view_new();
note_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(note))); entry_vendor = gtk_entry_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(note), TRUE); entry_set_multiline_truncate(GTK_ENTRY(entry_vendor), TRUE);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(note), GTK_WRAP_WORD); gtk_widget_set_halign(GTK_WIDGET(entry_vendor), GTK_ALIGN_FILL);
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(note)); gtk_widget_set_valign(GTK_WIDGET(entry_vendor), GTK_ALIGN_CENTER);
gtk_widget_set_hexpand(GTK_WIDGET(entry_vendor), TRUE);
gtk_widget_show_all(hbox); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_vendor), 1, 6, 2, 1);
gtk_widget_show_all(vbox);
/* City */
gtk_widget_hide(add_record_button); label = gtk_label_new(_("City:"));
gtk_widget_hide(apply_record_button); gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
if (cycle_category) { gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
/* First cycle exp_category var */ gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
if (exp_category == CATEGORY_ALL) {
new_cat = -1; gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 7, 1, 1);
} else {
new_cat = find_sort_cat_pos(exp_category); entry_city = gtk_entry_new();
} entry_set_multiline_truncate(GTK_ENTRY(entry_city), TRUE);
for (i=0; i<NUM_EXP_CAT_ITEMS; i++) { gtk_widget_set_halign(GTK_WIDGET(entry_city), GTK_ALIGN_FILL);
new_cat++; gtk_widget_set_valign(GTK_WIDGET(entry_city), GTK_ALIGN_CENTER);
if (new_cat >= NUM_EXP_CAT_ITEMS) { gtk_widget_set_hexpand(GTK_WIDGET(entry_city), TRUE);
exp_category = CATEGORY_ALL; gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(entry_city), 1, 7, 2, 1);
break;
} /* Attendees */
if ((sort_l[new_cat].Pcat) && (sort_l[new_cat].Pcat[0])) { label = gtk_label_new(_("Attendees"));
exp_category = sort_l[new_cat].cat_num; gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
break; gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
} gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
} gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
/* Then update menu with new exp_category */
if (exp_category==CATEGORY_ALL) { gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 8, 1, 1);
index = 0;
index2 = 0; /* Attendees textbox */
} else { scrolled_window = gtk_scrolled_window_new(NULL, NULL);
index = find_sort_cat_pos(exp_category); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GT
index2 = find_menu_cat_pos(index) + 1; K_SHADOW_OUT);
index += 1; gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0);
} gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
if (index<0) { GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
jp_logf(JP_LOG_WARN, _("Category is not legal\n")); gtk_widget_set_halign(GTK_WIDGET(scrolled_window), GTK_ALIGN_FILL);
} else { gtk_widget_set_valign(GTK_WIDGET(scrolled_window), GTK_ALIGN_FILL);
gtk_check_menu_item_set_active gtk_widget_set_hexpand(GTK_WIDGET(scrolled_window), TRUE);
(GTK_CHECK_MENU_ITEM(exp_cat_menu_item1[index]), TRUE); gtk_widget_set_vexpand(GTK_WIDGET(scrolled_window), TRUE);
gtk_option_menu_set_history(GTK_OPTION_MENU(category_menu1), index2); gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(scrolled_window), 1, 8, 2, 1);
}
} attendees = gtk_text_view_new();
else attendees_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(attendees
{ )));
exp_category = CATEGORY_ALL; gtk_text_view_set_editable(GTK_TEXT_VIEW(attendees), TRUE);
} gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(attendees), GTK_WRAP_WORD);
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(attendees));
/* The focus doesn't do any good on the application button */
gtk_widget_grab_focus(GTK_WIDGET(clist)); label = gtk_label_new(_("Note"));
gtk_widget_set_hexpand(GTK_WIDGET(label), FALSE);
jp_logf(JP_LOG_DEBUG, "Expense: calling display_records\n"); gtk_widget_set_vexpand(GTK_WIDGET(label), FALSE);
display_records(); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_END);
jp_logf(JP_LOG_DEBUG, "Expense: after display_records\n"); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_CENTER);
if (unique_id) { gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(label), 0, 9, 1, 1);
expense_find(unique_id);
} /* Note textbox */
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GT
K_SHADOW_OUT);
gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_halign(GTK_WIDGET(scrolled_window), GTK_ALIGN_FILL);
gtk_widget_set_valign(GTK_WIDGET(scrolled_window), GTK_ALIGN_FILL);
gtk_widget_set_hexpand(GTK_WIDGET(scrolled_window), TRUE);
gtk_widget_set_vexpand(GTK_WIDGET(scrolled_window), TRUE);
gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(scrolled_window), 1, 9, 2, 1);
note = gtk_text_view_new();
note_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(note)));
gtk_text_view_set_editable(GTK_TEXT_VIEW(note), TRUE);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(note), GTK_WRAP_WORD);
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(note));
gtk_widget_show_all(hbox);
gtk_widget_show_all(vbox);
gtk_widget_hide(add_record_button);
gtk_widget_hide(apply_record_button);
if (cycle_category) {
/* First cycle exp_category var */
if (exp_category == CATEGORY_ALL) {
new_cat = -1;
} else {
new_cat = find_sort_cat_pos(exp_category);
}
for (i = 0; i < NUM_EXP_CAT_ITEMS; i++) {
new_cat++;
if (new_cat >= NUM_EXP_CAT_ITEMS) {
exp_category = CATEGORY_ALL;
break;
}
if ((sort_l[new_cat].Pcat) && (sort_l[new_cat].Pcat[0])) {
exp_category = sort_l[new_cat].cat_num;
break;
}
}
/* Then update menu with new exp_category */
if (exp_category == CATEGORY_ALL) {
index = 0;
index2 = 0;
} else {
index = find_sort_cat_pos(exp_category);
index2 = find_menu_cat_pos(index) + 1;
index += 1;
}
if (index < 0) {
jp_logf(JP_LOG_WARN, _("Category is not legal\n"));
} else {
gtk_combo_box_set_active(GTK_COMBO_BOX(category_menu1),index2);
}
} else {
exp_category = CATEGORY_ALL;
}
/* The focus doesn't do any good on the application button */
gtk_widget_grab_focus(GTK_WIDGET(treeView));
jp_logf(JP_LOG_DEBUG, "Expense: calling display_records\n");
display_records();
jp_logf(JP_LOG_DEBUG, "Expense: after display_records\n");
if (unique_id) {
expense_find(unique_id);
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* /*
* This function is called by J-Pilot before switching to another application. * This function is called by J-Pilot before switching to another application.
* The plugin is expected to perform any desirable cleanup operations before * The plugin is expected to perform any desirable cleanup operations before
* its windows are terminated. Desirable actions include freeing allocated * its windows are terminated. Desirable actions include freeing allocated
* memory, storing state variables, etc. * memory, storing state variables, etc.
*/ */
int plugin_gui_cleanup(void) { int plugin_gui_cleanup(void) {
int b; int b;
jp_logf(JP_LOG_DEBUG, "Expense: plugin_gui_cleanup\n"); jp_logf(JP_LOG_DEBUG, "Expense: plugin_gui_cleanup\n");
b=dialog_save_changed_record(scrolled_window, record_changed); b = dialog_save_changed_record(scrolled_window, record_changed);
if (b==DIALOG_SAID_2) { if (b == DIALOG_SAID_2) {
cb_add_new_record(NULL, GINT_TO_POINTER(record_changed)); cb_add_new_record(NULL, GINT_TO_POINTER(record_changed));
} }
connect_changed_signals(DISCONNECT_SIGNALS); connect_changed_signals(DISCONNECT_SIGNALS);
free_myexpense_list(&glob_myexpense_list); free_myexpense_list(&glob_myexpense_list);
if (pane) { if (pane) {
/* Remove the accelerators */ /* Remove the accelerators */
#ifndef ENABLE_STOCK_BUTTONS #ifndef ENABLE_STOCK_BUTTONS
gtk_window_remove_accel_group(GTK_WINDOW(gtk_widget_get_toplevel(pane)), a ccel_group); gtk_window_remove_accel_group(GTK_WINDOW(gtk_widget_get_toplevel(pane)), accel_group);
#endif #endif
set_pref(PREF_EXPENSE_PANE, gtk_paned_get_position(GTK_PANED(pane)), NULL, set_pref(PREF_EXPENSE_PANE, gtk_paned_get_position(GTK_PANED(pane)), NUL
TRUE); L, TRUE);
pane = NULL; pane = NULL;
} }
set_pref(PREF_EXPENSE_SORT_COLUMN, clist_col_selected, NULL, TRUE); set_pref(PREF_EXPENSE_SORT_COLUMN, column_selected, NULL, TRUE);
set_pref(PREF_EXPENSE_SORT_ORDER, GTK_CLIST(clist)->sort_type, NULL, TRUE); set_pref(PREF_EXPENSE_SORT_ORDER, gtk_tree_view_column_get_sort_order(gtk_tr
ee_view_get_column(treeView, row_selected)), NULL, TRUE);
plugin_last_time = time(NULL); plugin_last_time = time(NULL);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* /*
* This is a plugin callback function that is executed when J-Pilot starts up. * This is a plugin callback function that is executed when J-Pilot starts up.
* base_dir is where J-Pilot is compiled to be installed at (e.g. /usr/local/) * base_dir is where J-Pilot is compiled to be installed at (e.g. /usr/local/)
*/ */
int plugin_startup(jp_startup_info *info) int plugin_startup(jp_startup_info *info) {
{ jp_init();
jp_init();
jp_logf(JP_LOG_DEBUG, "Expense: plugin_startup\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_startup\n"); if (info) {
if (info) { if (info->base_dir) {
if (info->base_dir) { jp_logf(JP_LOG_DEBUG, "Expense: base_dir = [%s]\n", info->base_dir);
jp_logf(JP_LOG_DEBUG, "Expense: base_dir = [%s]\n", info->base_dir); }
} }
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* /*
* This is a plugin callback function that is executed before a sync occurs. * This is a plugin callback function that is executed before a sync occurs.
* Any sync preperation can be done here. * Any sync preperation can be done here.
*/ */
int plugin_pre_sync(void) int plugin_pre_sync(void) {
{ jp_logf(JP_LOG_DEBUG, "Expense: plugin_pre_sync\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_pre_sync\n"); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
/* /*
* This is a plugin callback function that is executed during a sync. * This is a plugin callback function that is executed during a sync.
* Notice that I don't need to sync the Expense application. Since I used * Notice that I don't need to sync the Expense application. Since I used
* the plugin_get_db_name call to tell J-Pilot what to sync for me. It will * the plugin_get_db_name call to tell J-Pilot what to sync for me. It will
* be done automatically. * be done automatically.
*/ */
int plugin_sync(int sd) int plugin_sync(int sd) {
{ jp_logf(JP_LOG_DEBUG, "Expense: plugin_sync\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_sync\n"); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
static int add_search_result(const char *line, static int add_search_result(const char *line,
int unique_id, int unique_id,
struct search_result **sr) struct search_result **sr) {
{ struct search_result *temp_sr;
struct search_result *temp_sr;
jp_logf(JP_LOG_DEBUG, "Expense: add_search_result for [%s]\n", line);
jp_logf(JP_LOG_DEBUG, "Expense: add_search_result for [%s]\n", line);
temp_sr = malloc(sizeof(struct search_result));
temp_sr=malloc(sizeof(struct search_result)); if (!temp_sr) {
if (!temp_sr) { return EXIT_FAILURE;
return EXIT_FAILURE; }
} temp_sr->unique_id = (unsigned int) unique_id;
temp_sr->unique_id=unique_id; temp_sr->line = strdup(line);
temp_sr->line=strdup(line); temp_sr->next = *sr;
temp_sr->next = *sr; *sr = temp_sr;
*sr = temp_sr;
return 0; return 0;
} }
/* /*
* This function is called when the user does a search. It should return * This function is called when the user does a search. It should return
* records which match the search string. * records which match the search string.
*/ */
int plugin_search(const char *search_string, int case_sense, struct search_resul int plugin_search(const char *search_string, int case_sense, struct search_resul
t **sr) t **sr) {
{ GList *records;
GList *records; GList *temp_list;
GList *temp_list; buf_rec *br;
buf_rec *br; struct MyExpense mexp;
struct MyExpense mexp; int num, count;
int num, count; char *line;
char *line;
jp_logf(JP_LOG_DEBUG, "Expense: plugin_search\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_search\n");
records = NULL;
records = NULL; *sr = NULL;
*sr = NULL;
/* This function takes care of reading the Database for us */
/* This function takes care of reading the Database for us */ num = jp_read_DB_files("ExpenseDB", &records);
num = jp_read_DB_files("ExpenseDB", &records); if (-1 == num)
if (-1 == num) return 0;
return 0;
count = 0;
count = 0;
for (temp_list = records; temp_list; temp_list = temp_list->next) {
for (temp_list = records; temp_list; temp_list = temp_list->next) { if (temp_list->data) {
if (temp_list->data) { br = temp_list->data;
br=temp_list->data; } else {
} else { continue;
continue; }
} if (!br->buf) {
if (!br->buf) { continue;
continue; }
} /* Since deleted and modified records are also returned and we don't
/* Since deleted and modified records are also returned and we don't * want to see those we skip over them. */
* want to see those we skip over them. */ if ((br->rt == DELETED_PALM_REC) ||
if ((br->rt == DELETED_PALM_REC) || (br->rt == DELETED_PC_REC) ||
(br->rt == DELETED_PC_REC) || (br->rt == MODIFIED_PALM_REC)) {
(br->rt == MODIFIED_PALM_REC)) { continue;
continue; }
}
mexp.attrib = br->attrib;
mexp.attrib = br->attrib; mexp.unique_id = br->unique_id;
mexp.unique_id = br->unique_id; mexp.rt = br->rt;
mexp.rt = br->rt;
/* We need to unpack the record blobs from the database.
/* We need to unpack the record blobs from the database. * unpack_Expense is already written in pilot-link, but normally
* unpack_Expense is already written in pilot-link, but normally * an unpack must be written for each type of application */
* an unpack must be written for each type of application */ if (unpack_Expense(&(mexp.ex), br->buf, br->size) != 0) {
if (unpack_Expense(&(mexp.ex), br->buf, br->size)!=0) { line = NULL;
line = NULL;
if (jp_strstr(mexp.ex.amount, search_string, case_sense))
if (jp_strstr(mexp.ex.amount, search_string, case_sense)) line = mexp.ex.amount;
line = mexp.ex.amount;
if (jp_strstr(mexp.ex.vendor, search_string, case_sense))
if (jp_strstr(mexp.ex.vendor, search_string, case_sense)) line = mexp.ex.vendor;
line = mexp.ex.vendor;
if (jp_strstr(mexp.ex.city, search_string, case_sense))
if (jp_strstr(mexp.ex.city, search_string, case_sense)) line = mexp.ex.city;
line = mexp.ex.city;
if (jp_strstr(mexp.ex.attendees, search_string, case_sense))
if (jp_strstr(mexp.ex.attendees, search_string, case_sense)) line = mexp.ex.attendees;
line = mexp.ex.attendees;
if (jp_strstr(mexp.ex.note, search_string, case_sense))
if (jp_strstr(mexp.ex.note, search_string, case_sense)) line = mexp.ex.note;
line = mexp.ex.note;
if (line) {
if (line) { /* Add it to our result list */
/* Add it to our result list */ jp_logf(JP_LOG_DEBUG, "Expense: calling add_search_result\n");
jp_logf(JP_LOG_DEBUG, "Expense: calling add_search_result\n"); add_search_result(line, br->unique_id, sr);
add_search_result(line, br->unique_id, sr); jp_logf(JP_LOG_DEBUG, "Expense: back from add_search_result\n");
jp_logf(JP_LOG_DEBUG, "Expense: back from add_search_result\n"); count++;
count++; }
} free_Expense(&(mexp.ex));
free_Expense(&(mexp.ex)); }
} }
} jp_free_DB_records(&records);
jp_free_DB_records(&records);
return count;
return count; }
}
int plugin_help(char **text, int *width, int *height) {
int plugin_help(char **text, int *width, int *height) /* We could also pass back *text=NULL
{ * and implement whatever we wanted to here.
/* We could also pass back *text=NULL */
* and implement whatever we wanted to here. char plugin_name[200];
*/
char plugin_name[200]; static_plugin_get_name(plugin_name, sizeof(plugin_name));
*text = g_strdup_printf(
static_plugin_get_name(plugin_name, sizeof(plugin_name)); /*-------------------------------------------*/
*text = g_strdup_printf( _("%s\n"
/*-------------------------------------------*/ "\n"
_("%s\n" "Expense plugin for J-Pilot was written by\n"
"\n" "Judd Montgomery (c) 1999.\n"
"Expense plugin for J-Pilot was written by\n" "judd@jpilot.org, http://jpilot.org"
"Judd Montgomery (c) 1999.\n" ),
"judd@jpilot.org, http://jpilot.org" plugin_name
), );
plugin_name *height = 0;
); *width = 0;
*height = 0;
*width = 0;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/* /*
* This is a plugin callback function called after a sync. * This is a plugin callback function called after a sync.
*/ */
int plugin_post_sync(void) int plugin_post_sync(void) {
{ jp_logf(JP_LOG_DEBUG, "Expense: plugin_post_sync\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_post_sync\n"); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
/* /*
* This is a plugin callback function called during program exit. * This is a plugin callback function called during program exit.
*/ */
int plugin_exit_cleanup(void) int plugin_exit_cleanup(void) {
{ jp_logf(JP_LOG_DEBUG, "Expense: plugin_exit_cleanup\n");
jp_logf(JP_LOG_DEBUG, "Expense: plugin_exit_cleanup\n"); return EXIT_SUCCESS;
return EXIT_SUCCESS;
} }
 End of changes. 107 change blocks. 
1819 lines changed or deleted 1888 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)