Statistics
| Revision:

root / src / importcsv.c @ 1625

History | View | Annotate | Download (28.1 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2007 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23
24
#include "defs.h"
25
26
#include <glib.h>
27
#include <glib/gi18n.h>
28
#include <gdk/gdkkeysyms.h>
29
#include <gtk/gtkwindow.h>
30
#include <gtk/gtksignal.h>
31
#include <gtk/gtkvbox.h>
32
#include <gtk/gtklabel.h>
33
#include <gtk/gtkentry.h>
34
#include <gtk/gtktable.h>
35
#include <gtk/gtkbutton.h>
36
#include <gtk/gtkradiobutton.h>
37
#include <gtk/gtkhbbox.h>
38
#include <gtk/gtkcheckbutton.h>
39
#include <gtk/gtktogglebutton.h>
40
#include <gtk/gtkstatusbar.h>
41
#include <gtk/gtknotebook.h>
42
#include <gtk/gtkstock.h>
43
44
#include <stdio.h>
45
46
#include "addrbook.h"
47
#include "addressbook.h"
48
#include "addressitem.h"
49
#include "filesel.h"
50
#include "gtkutils.h"
51
#include "stock_pixmap.h"
52
#include "prefs_common.h"
53
#include "manage_window.h"
54
#include "mgutils.h"
55
#include "importcsv.h"
56
#include "codeconv.h"
57
#include "utils.h"
58
59
#define IMPORTCSV_GUESS_NAME "CSV Import"
60
61
#define PAGE_FILE_INFO             0
62
#define PAGE_ATTRIBUTES            1
63
#define PAGE_FINISH                2
64
65
#define IMPORTCSV_WIDTH           420
66
#define IMPORTCSV_HEIGHT          320
67
68
#define FIELDS_N_COLS              3
69
#define FIELDS_COL_WIDTH_SELECT    10
70
#define FIELDS_COL_WIDTH_FIELD     140
71
#define FIELDS_COL_WIDTH_ATTRIB    140
72
73
typedef enum {
74
        FIELD_COL_SELECT  = 0,
75
        FIELD_COL_FIELD   = 1,
76
        FIELD_COL_ATTRIB  = 2
77
} ImpCSV_FieldColPos;
78
79
static struct _ImpCSVDlg {
80
        GtkWidget *window;
81
        GtkWidget *notebook;
82
        GtkWidget *file_entry;
83
        GtkWidget *name_entry;
84
        GtkWidget *comma_radiobtn;
85
        GtkWidget *tab_radiobtn;
86
        GtkWidget *clist_field;
87
        GtkWidget *check_select;
88
        GtkWidget *labelBook;
89
        GtkWidget *labelFile;
90
        GtkWidget *labelRecords;
91
        GtkWidget *btnPrev;
92
        GtkWidget *btnNext;
93
        GtkWidget *btnCancel;
94
        GtkWidget *statusbar;
95
        gint      status_cid;
96
        gint      rowCount;
97
        gchar     *nameBook;
98
        gchar     *fileName;
99
        gchar     delimiter;
100
        gboolean  cancelled;
101
} impcsv_dlg;
102
103
typedef enum {
104
        ATTR_FIRST_NAME,
105
        ATTR_LAST_NAME,
106
        ATTR_DISPLAY_NAME,
107
        ATTR_NICK_NAME,
108
        ATTR_EMAIL_ADDRESS,
109
        ATTR_REMARKS,
110
111
        N_CSV_ATTRIB
112
} ImpCSVAttribIndex;
113
114
static struct _ImpCSVAttrib {
115
        gchar *name;
116
        gchar *value;
117
        gint col;
118
        gboolean enabled;
119
} imp_csv_attrib[] = {
120
        {N_("First Name"),        NULL, 0, TRUE},
121
        {N_("Last Name"),        NULL, 1, TRUE},
122
        {N_("Display Name"),        NULL, 2, TRUE},
123
        {N_("Nick Name"),        NULL, 3, TRUE},
124
        {N_("E-Mail Address"),        NULL, 4, TRUE},
125
        {N_("Remarks"),                NULL, 5, TRUE}
126
};
127
128
static AddressBookFile *_importedBook_;
129
static AddressIndex *_imp_addressIndex_;
130
static gint importCount = 0;
131
static gint result;
132
133
static GdkPixmap *markxpm;
134
static GdkBitmap *markxpmmask;
135
136
static void imp_csv_status_show( gchar *msg ) {
137
        if( impcsv_dlg.statusbar != NULL ) {
138
                gtk_statusbar_pop( GTK_STATUSBAR(impcsv_dlg.statusbar), impcsv_dlg.status_cid );
139
                if( msg ) {
140
                        gtk_statusbar_push( GTK_STATUSBAR(impcsv_dlg.statusbar), impcsv_dlg.status_cid, msg );
141
                }
142
        }
143
}
144
145
static void imp_csv_message( void ) {
146
        gchar *sMsg = NULL;
147
        gint pageNum;
148
149
        pageNum = gtk_notebook_get_current_page( GTK_NOTEBOOK(impcsv_dlg.notebook) );
150
        if( pageNum == PAGE_FILE_INFO ) {
151
                sMsg = _( "Please specify address book name and file to import." );
152
        }
153
        else if( pageNum == PAGE_ATTRIBUTES ) {
154
                sMsg = _( "Select and reorder CSV field names to import." );
155
        }
156
        else if( pageNum == PAGE_FINISH ) {
157
                sMsg = _( "File imported." );
158
        }
159
        imp_csv_status_show( sMsg );
160
}
161
162
static gchar *imp_csv_guess_file( AddressBookFile *abf ) {
163
        gchar *newFile = NULL;
164
        GList *fileList = NULL;
165
        gint fileNum = 1;
166
        fileList = addrbook_get_bookfile_list( abf );
167
        if( fileList ) {
168
                fileNum = 1 + abf->maxValue;
169
        }
170
        newFile = addrbook_gen_new_file_name( fileNum );
171
        g_list_free( fileList );
172
        fileList = NULL;
173
        return newFile;
174
}
175
176
static gboolean imp_csv_load_fields( gchar *sFile ) {
177
        GtkCList *clist = GTK_CLIST(impcsv_dlg.clist_field);
178
        FILE *fp;
179
        gchar buf[BUFFSIZE];
180
        CharSet enc;
181
182
        g_return_val_if_fail(sFile != NULL, FALSE);
183
184
        impcsv_dlg.rowCount = 0;
185
        gtk_clist_clear( clist );
186
187
        enc = conv_check_file_encoding(sFile);
188
189
        if ((fp = g_fopen(sFile, "rb")) == NULL) {
190
                return FALSE;
191
        }
192
193
        if (fgets(buf, sizeof(buf), fp) != NULL) {
194
                gchar *str;
195
                gchar **strv;
196
                gchar *text[ FIELDS_N_COLS ];
197
                gint i;
198
                guint fields_len;
199
                guint data_len = 0;
200
                guint len;
201
                gint row;
202
203
                strretchomp(buf);
204
                if (enc == C_UTF_8)
205
                        str = g_strdup(buf);
206
                else
207
                        str = conv_localetodisp(buf, NULL);
208
                strv = strsplit_csv(str, impcsv_dlg.delimiter, 0);
209
                fields_len = sizeof(imp_csv_attrib) / sizeof(imp_csv_attrib[0]);
210
                while (strv[data_len])
211
                        ++data_len;
212
                len = MAX(fields_len, data_len);
213
214
                gtk_clist_freeze(clist);
215
216
                for (i = 0; i < len; i++) {
217
                        text[ FIELD_COL_SELECT ] = "";
218
                        if (i < data_len)
219
                                text[ FIELD_COL_FIELD  ] = strv[i];
220
                        else
221
                                text[ FIELD_COL_FIELD  ] = "";
222
                        if (i < fields_len)
223
                                text[ FIELD_COL_ATTRIB ] =
224
                                        gettext(imp_csv_attrib[i].name);
225
                        else
226
                                text[ FIELD_COL_ATTRIB ] = "";
227
                        row = gtk_clist_append(clist, text);
228
                        if (i < fields_len) {
229
                                imp_csv_attrib[i].value = NULL;
230
                                imp_csv_attrib[i].col = row;
231
                                gtk_clist_set_row_data
232
                                        (clist, row, &imp_csv_attrib[i]);
233
                                if (imp_csv_attrib[i].enabled)
234
                                        gtk_clist_set_pixmap(clist, row, FIELD_COL_SELECT, markxpm, markxpmmask);
235
                        }
236
                }
237
238
                gtk_clist_thaw(clist);
239
                gtk_widget_queue_resize(GTK_WIDGET(clist));
240
241
                g_strfreev(strv);
242
                g_free(str);
243
        }
244
245
        fclose(fp);
246
247
        return TRUE;
248
}
249
250
static void imp_csv_field_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event ) {
251
        if (event && event->type == GDK_2BUTTON_PRESS)
252
                return;
253
254
        if (column == FIELD_COL_SELECT) {
255
                struct _ImpCSVAttrib *attr;
256
                attr = gtk_clist_get_row_data( clist, row );
257
                if (attr) {
258
                        attr->enabled ^= TRUE;
259
                        if (attr->enabled)
260
                                gtk_clist_set_pixmap(clist, row, FIELD_COL_SELECT, markxpm, markxpmmask);
261
                        else
262
                                gtk_clist_set_text(clist, row, FIELD_COL_SELECT, "");
263
                }
264
        }
265
}
266
267
static void imp_csv_field_list_up( GtkWidget *button, gpointer data ) {
268
        GtkCList *clist = GTK_CLIST(impcsv_dlg.clist_field);
269
        gchar *text;
270
        gint row;
271
        struct _ImpCSVAttrib *src_attr;
272
        struct _ImpCSVAttrib *dest_attr;
273
        gchar *src_text;
274
        gchar *dest_text;
275
276
        if (!clist->selection) return;
277
278
        row = GPOINTER_TO_INT( clist->selection->data );
279
        if ( row > 0 && row < clist->rows ) {
280
                gtk_clist_freeze( clist );
281
282
                src_attr = gtk_clist_get_row_data( clist, row );
283
                dest_attr = gtk_clist_get_row_data( clist, row - 1 );
284
285
                gtk_clist_row_move( clist, row, row - 1 );
286
287
                gtk_clist_get_text( clist, row, FIELD_COL_FIELD, &text );
288
                src_text = g_strdup( text );
289
                gtk_clist_get_text( clist, row - 1, FIELD_COL_FIELD, &text );
290
                dest_text = g_strdup( text );
291
                gtk_clist_set_text( clist, row - 1, FIELD_COL_FIELD, src_text );
292
                gtk_clist_set_text( clist, row, FIELD_COL_FIELD, dest_text );
293
                g_free( dest_text );
294
                g_free( src_text );
295
296
                if ( src_attr )
297
                        src_attr->col = row - 1;
298
                if ( dest_attr )
299
                        dest_attr->col = row;
300
301
                gtk_clist_thaw( clist );
302
303
                if (gtk_clist_row_is_visible(clist, row - 1)
304
                        != GTK_VISIBILITY_FULL)
305
                        gtk_clist_moveto(clist, row - 1, 0, 0.5, 0);
306
        }
307
}
308
309
static void imp_csv_field_list_down( GtkWidget *button, gpointer data ) {
310
        GtkCList *clist = GTK_CLIST(impcsv_dlg.clist_field);
311
        gchar *text;
312
        gint row;
313
        struct _ImpCSVAttrib *src_attr;
314
        struct _ImpCSVAttrib *dest_attr;
315
        gchar *src_text;
316
        gchar *dest_text;
317
318
        if (!clist->selection) return;
319
320
        row = GPOINTER_TO_INT( clist->selection->data );
321
        if ( row >= 0 && row < clist->rows - 1 ) {
322
                gtk_clist_freeze( clist );
323
324
                src_attr = gtk_clist_get_row_data( clist, row );
325
                dest_attr = gtk_clist_get_row_data( clist, row + 1 );
326
327
                gtk_clist_row_move( clist, row, row + 1 );
328
329
                gtk_clist_get_text( clist, row, FIELD_COL_FIELD, &text );
330
                src_text = g_strdup( text );
331
                gtk_clist_get_text( clist, row + 1, FIELD_COL_FIELD, &text );
332
                dest_text = g_strdup( text );
333
                gtk_clist_set_text( clist, row + 1, FIELD_COL_FIELD, src_text );
334
                gtk_clist_set_text( clist, row, FIELD_COL_FIELD, dest_text );
335
                g_free( dest_text );
336
                g_free( src_text );
337
338
                if ( src_attr )
339
                        src_attr->col = row + 1;
340
                if ( dest_attr )
341
                        dest_attr->col = row;
342
343
                gtk_clist_thaw( clist );
344
345
                if (gtk_clist_row_is_visible(clist, row + 1)
346
                        != GTK_VISIBILITY_FULL)
347
                        gtk_clist_moveto(clist, row + 1, 0, 0.5, 0);
348
        }
349
}
350
351
static gint imp_csv_import_data( gchar *csvFile, AddressCache *cache ) {
352
        FILE *fp;
353
        gchar buf[BUFFSIZE];
354
        gint i;
355
        gchar **strv;
356
        CharSet enc;
357
        guint fields_len;
358
        gchar *firstName = NULL;
359
        gchar *lastName = NULL;
360
        gchar *fullName = NULL;
361
        gchar *nickName = NULL;
362
        gchar *address = NULL;
363
        gchar *remarks = NULL;
364
        ItemPerson *person;
365
        ItemEMail *email;
366
        gint count = 0;
367
368
        g_return_val_if_fail( csvFile != NULL, MGU_BAD_ARGS );
369
370
        addrcache_clear( cache );
371
        cache->dataRead = FALSE;
372
373
        enc = conv_check_file_encoding(csvFile);
374
375
        if ((fp = g_fopen(csvFile, "rb")) == NULL) {
376
                return;
377
        }
378
379
        fields_len = sizeof(imp_csv_attrib) / sizeof(imp_csv_attrib[0]);
380
381
        while (fgets(buf, sizeof(buf), fp) != NULL) {
382
                gchar *str;
383
                guint col, cols = 0;
384
385
                strretchomp(buf);
386
                if (enc == C_UTF_8)
387
                        str = g_strdup(buf);
388
                else
389
                        str = conv_localetodisp(buf, NULL);
390
                strv = strsplit_csv(str, impcsv_dlg.delimiter, 0);
391
                while (strv[cols])
392
                        ++cols;
393
394
                for (i = 0; i < fields_len; i++) {
395
                        if (!imp_csv_attrib[i].enabled)
396
                                continue;
397
                        col = imp_csv_attrib[i].col;
398
                        if (col >= cols || !*strv[col])
399
                                continue;
400
                        imp_csv_attrib[i].value = strv[col];
401
                }
402
403
                firstName = imp_csv_attrib[ATTR_FIRST_NAME].value;
404
                lastName  = imp_csv_attrib[ATTR_LAST_NAME].value;
405
                fullName  = imp_csv_attrib[ATTR_DISPLAY_NAME].value;
406
                nickName  = imp_csv_attrib[ATTR_NICK_NAME].value;
407
                address   = imp_csv_attrib[ATTR_EMAIL_ADDRESS].value;
408
                remarks   = imp_csv_attrib[ATTR_REMARKS].value;
409
410
                if (!fullName && !firstName && !lastName && address)
411
                        fullName = address;
412
413
                person = addritem_create_item_person();
414
                addritem_person_set_common_name( person, fullName );
415
                addritem_person_set_first_name( person, firstName );
416
                addritem_person_set_last_name( person, lastName );
417
                addritem_person_set_nick_name( person, nickName );
418
                addrcache_id_person( cache, person );
419
                addrcache_add_person( cache, person );
420
421
                if (address) {
422
                        email = addritem_create_item_email();
423
                        addritem_email_set_address( email, address );
424
                        addritem_email_set_remarks( email, remarks );
425
                        addrcache_id_email( cache, email );
426
                        addrcache_person_add_email( cache, person, email );
427
                }
428
429
                for (i = 0; i < fields_len; i++)
430
                        imp_csv_attrib[i].value = NULL;
431
                g_strfreev(strv);
432
                g_free(str);
433
434
                count++;
435
        }
436
437
        fclose(fp);
438
439
        cache->modified = FALSE;
440
        cache->dataRead = TRUE;
441
        importCount = count;
442
443
        return MGU_SUCCESS;
444
}
445
446
/*
447
* Move off fields page.
448
* return: TRUE if OK to move off page.
449
*/
450
static gboolean imp_csv_field_move() {
451
        gboolean retVal = FALSE;
452
        gchar *newFile;
453
        AddressBookFile *abf = NULL;
454
455
        if( _importedBook_ ) {
456
                addrbook_free_book( _importedBook_ );
457
        }
458
459
        abf = addrbook_create_book();
460
        addrbook_set_path( abf, _imp_addressIndex_->filePath );
461
        addrbook_set_name( abf, impcsv_dlg.nameBook );
462
        newFile = imp_csv_guess_file( abf );
463
        addrbook_set_file( abf, newFile );
464
        g_free( newFile );
465
466
        /* Import data into file */
467
        if( imp_csv_import_data( impcsv_dlg.fileName, abf->addressCache ) == MGU_SUCCESS ) {
468
                addrbook_save_data( abf );
469
                abf->dirtyFlag = TRUE;
470
                _importedBook_ = abf;
471
                retVal = TRUE;
472
        }
473
        else {
474
                addrbook_free_book( abf );
475
        }
476
477
        return retVal;
478
}
479
480
/*
481
* Move off fields page.
482
* return: TRUE if OK to move off page.
483
*/
484
static gboolean imp_csv_file_move() {
485
        gboolean retVal = FALSE;
486
        gchar *sName;
487
        gchar *sFile;
488
        gchar *sMsg = NULL;
489
        gboolean errFlag = FALSE;
490
491
        sFile = gtk_editable_get_chars( GTK_EDITABLE(impcsv_dlg.file_entry), 0, -1 );
492
        g_strchug( sFile ); g_strchomp( sFile );
493
494
        sName = gtk_editable_get_chars( GTK_EDITABLE(impcsv_dlg.name_entry), 0, -1 );
495
        g_strchug( sName ); g_strchomp( sName );
496
497
        g_free( impcsv_dlg.nameBook );
498
        g_free( impcsv_dlg.fileName );
499
        impcsv_dlg.nameBook = sName;
500
        impcsv_dlg.fileName = sFile;
501
502
        gtk_entry_set_text( GTK_ENTRY(impcsv_dlg.file_entry), sFile );
503
        gtk_entry_set_text( GTK_ENTRY(impcsv_dlg.name_entry), sName );
504
505
        if (gtk_toggle_button_get_active
506
                (GTK_TOGGLE_BUTTON(impcsv_dlg.comma_radiobtn))) {
507
                impcsv_dlg.delimiter = ',';
508
        } else {
509
                impcsv_dlg.delimiter = '\t';
510
        }
511
512
        if( *sFile == '\0'|| strlen( sFile ) < 1 ) {
513
                sMsg = _( "Please select a file." );
514
                gtk_widget_grab_focus(impcsv_dlg.file_entry);
515
                errFlag = TRUE;
516
        }
517
518
        if( *sName == '\0'|| strlen( sName ) < 1 ) {
519
                if( ! errFlag ) sMsg = _( "Address book name must be supplied." );
520
                gtk_widget_grab_focus(impcsv_dlg.name_entry);
521
                errFlag = TRUE;
522
        }
523
524
        if( ! errFlag ) {
525
                gchar *sFSFile;
526
                sFSFile = conv_filename_from_utf8( sFile );
527
                if ( ! imp_csv_load_fields( sFSFile ) ) {
528
                        sMsg = _( "Error reading CSV fields." );
529
                } else {
530
                        retVal = TRUE;
531
                }
532
                g_free( sFSFile );
533
        }
534
        imp_csv_status_show( sMsg );
535
536
        return retVal;
537
}
538
539
/*
540
 * Display finish page.
541
 */
542
static void imp_csv_finish_show() {
543
        gchar *sMsg;
544
        gchar *name;
545
546
        name = gtk_editable_get_chars( GTK_EDITABLE(impcsv_dlg.name_entry), 0, -1 );
547
        gtk_label_set_text( GTK_LABEL(impcsv_dlg.labelBook), name );
548
        g_free( name );
549
        gtk_label_set_text( GTK_LABEL(impcsv_dlg.labelFile), impcsv_dlg.fileName );
550
        gtk_label_set_text( GTK_LABEL(impcsv_dlg.labelRecords), itos( importCount ) );
551
        gtk_widget_set_sensitive( impcsv_dlg.btnPrev, FALSE );
552
        gtk_widget_set_sensitive( impcsv_dlg.btnNext, FALSE );
553
        if( result == MGU_SUCCESS ) {
554
                sMsg = _( "CSV file imported successfully." );
555
        }
556
        else {
557
                sMsg = mgu_error2string( result );
558
        }
559
        imp_csv_status_show( sMsg );
560
        gtk_button_set_label(GTK_BUTTON(impcsv_dlg.btnCancel), GTK_STOCK_CLOSE);
561
        gtk_widget_grab_focus(impcsv_dlg.btnCancel);
562
}
563
564
static void imp_csv_prev( GtkWidget *widget ) {
565
        gint pageNum;
566
567
        pageNum = gtk_notebook_get_current_page( GTK_NOTEBOOK(impcsv_dlg.notebook) );
568
        if( pageNum == PAGE_ATTRIBUTES ) {
569
                /* Goto file page stuff */
570
                gtk_notebook_set_current_page(
571
                        GTK_NOTEBOOK(impcsv_dlg.notebook), PAGE_FILE_INFO );
572
                gtk_widget_set_sensitive( impcsv_dlg.btnPrev, FALSE );
573
        }
574
        imp_csv_message();
575
}
576
577
static void imp_csv_next( GtkWidget *widget ) {
578
        gint pageNum;
579
580
        pageNum = gtk_notebook_get_current_page( GTK_NOTEBOOK(impcsv_dlg.notebook) );
581
        if( pageNum == PAGE_FILE_INFO ) {
582
                /* Goto attributes stuff */
583
                if( imp_csv_file_move() ) {
584
                        gtk_notebook_set_current_page(
585
                                GTK_NOTEBOOK(impcsv_dlg.notebook), PAGE_ATTRIBUTES );
586
                        imp_csv_message();
587
                        gtk_widget_set_sensitive( impcsv_dlg.btnPrev, TRUE );
588
                }
589
                else {
590
                        gtk_widget_set_sensitive( impcsv_dlg.btnPrev, FALSE );
591
                }
592
        }
593
        else if( pageNum == PAGE_ATTRIBUTES ) {
594
                /* Goto finish stuff */
595
                if( imp_csv_field_move() ) {
596
                        gtk_notebook_set_current_page(
597
                                GTK_NOTEBOOK(impcsv_dlg.notebook), PAGE_FINISH );
598
                        imp_csv_finish_show();
599
                }
600
        }
601
}
602
603
static void imp_csv_cancel( GtkWidget *widget, gpointer data ) {
604
        gint pageNum;
605
606
        pageNum = gtk_notebook_get_current_page( GTK_NOTEBOOK(impcsv_dlg.notebook) );
607
        if( pageNum != PAGE_FINISH ) {
608
                impcsv_dlg.cancelled = TRUE;
609
        }
610
        gtk_main_quit();
611
}
612
613
static void imp_csv_file_select( void ) {
614
        gchar *sSelFile;
615
616
        sSelFile = filesel_select_file( _("Select CSV File"), NULL,
617
                                        GTK_FILE_CHOOSER_ACTION_OPEN );
618
        if (sSelFile) {
619
                gchar *sUTF8File;
620
                sUTF8File = conv_filename_to_utf8( sSelFile );
621
                gtk_entry_set_text( GTK_ENTRY(impcsv_dlg.file_entry), sUTF8File );
622
                g_free( sUTF8File );
623
                g_free( sSelFile );
624
        }
625
}
626
627
static gint imp_csv_delete_event( GtkWidget *widget, GdkEventAny *event, gpointer data ) {
628
        imp_csv_cancel( widget, data );
629
        return TRUE;
630
}
631
632
static gboolean imp_csv_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer data ) {
633
        if (event && event->keyval == GDK_Escape) {
634
                imp_csv_cancel( widget, data );
635
        }
636
        return FALSE;
637
}
638
639
static void imp_csv_page_file( gint pageNum, gchar *pageLbl ) {
640
        GtkWidget *vbox;
641
        GtkWidget *table;
642
        GtkWidget *label;
643
        GtkWidget *file_entry;
644
        GtkWidget *name_entry;
645
        GtkWidget *file_btn;
646
        GtkWidget *hbox;
647
        GtkWidget *comma_radiobtn;
648
        GtkWidget *tab_radiobtn;
649
        gint top;
650
651
        vbox = gtk_vbox_new(FALSE, 4);
652
        gtk_container_add( GTK_CONTAINER( impcsv_dlg.notebook ), vbox );
653
        gtk_container_set_border_width( GTK_CONTAINER (vbox), 4 );
654
655
        label = gtk_label_new( pageLbl );
656
        gtk_widget_show( label );
657
        gtk_notebook_set_tab_label(
658
                GTK_NOTEBOOK( impcsv_dlg.notebook ),
659
                gtk_notebook_get_nth_page(
660
                        GTK_NOTEBOOK( impcsv_dlg.notebook ), pageNum ),
661
                label );
662
663
        table = gtk_table_new(2, 3, FALSE);
664
        gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
665
        gtk_container_set_border_width( GTK_CONTAINER(table), 6 );
666
        gtk_table_set_row_spacings(GTK_TABLE(table), 8);
667
        gtk_table_set_col_spacings(GTK_TABLE(table), 8);
668
669
        /* First row */
670
        top = 0;
671
        label = gtk_label_new(_("Address Book"));
672
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
673
                GTK_FILL, 0, 0, 0);
674
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
675
676
        name_entry = gtk_entry_new();
677
        gtk_table_attach(GTK_TABLE(table), name_entry, 1, 2, top, (top + 1),
678
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
679
680
        /* Second row */
681
        top = 1;
682
        label = gtk_label_new(_("File Name"));
683
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
684
                GTK_FILL, 0, 0, 0);
685
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
686
687
        file_entry = gtk_entry_new();
688
        gtk_table_attach(GTK_TABLE(table), file_entry, 1, 2, top, (top + 1),
689
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
690
691
        file_btn = gtk_button_new_with_label(_(" ... "));
692
        gtk_table_attach(GTK_TABLE(table), file_btn, 2, 3, top, (top + 1),
693
                GTK_FILL, 0, 3, 0);
694
695
        hbox = gtk_hbox_new(FALSE, 8);
696
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
697
        gtk_container_set_border_width( GTK_CONTAINER (hbox), 4 );
698
699
        comma_radiobtn = gtk_radio_button_new_with_label
700
                (NULL, _("Comma-separated"));
701
        gtk_box_pack_start(GTK_BOX(hbox), comma_radiobtn, FALSE, FALSE, 0);
702
703
        tab_radiobtn = gtk_radio_button_new_with_label_from_widget
704
                (GTK_RADIO_BUTTON(comma_radiobtn), _("Tab-separated"));
705
        gtk_box_pack_start(GTK_BOX(hbox), tab_radiobtn, FALSE, FALSE, 0);
706
707
        gtk_widget_show_all(vbox);
708
709
        /* Button handler */
710
        g_signal_connect(G_OBJECT(file_btn), "clicked",
711
                         G_CALLBACK(imp_csv_file_select), NULL);
712
713
        impcsv_dlg.file_entry = file_entry;
714
        impcsv_dlg.name_entry = name_entry;
715
        impcsv_dlg.comma_radiobtn = comma_radiobtn;
716
        impcsv_dlg.tab_radiobtn = tab_radiobtn;
717
}
718
719
static void imp_csv_page_fields( gint pageNum, gchar *pageLbl ) {
720
        GtkWidget *vbox;
721
        GtkWidget *hbox;
722
723
        GtkWidget *label;
724
        GtkWidget *clist_swin;
725
        GtkWidget *clist_field;
726
727
        GtkWidget *btn_vbox;
728
        GtkWidget *btn_vbox1;
729
        GtkWidget *up_btn;
730
        GtkWidget *down_btn;
731
732
        gchar *titles[ FIELDS_N_COLS ];
733
        gint i;
734
735
        titles[ FIELD_COL_SELECT ] = _("S");
736
        titles[ FIELD_COL_FIELD  ] = _("CSV Field");
737
        titles[ FIELD_COL_ATTRIB ] = _("Address Book Field");
738
739
        vbox = gtk_vbox_new(FALSE, 4);
740
        gtk_container_add( GTK_CONTAINER( impcsv_dlg.notebook ), vbox );
741
        gtk_container_set_border_width( GTK_CONTAINER (vbox), 4 );
742
743
        label = gtk_label_new( pageLbl );
744
        gtk_widget_show( label );
745
        gtk_notebook_set_tab_label(
746
                GTK_NOTEBOOK( impcsv_dlg.notebook ),
747
                gtk_notebook_get_nth_page(GTK_NOTEBOOK( impcsv_dlg.notebook ), pageNum ),
748
                label );
749
750
        hbox = gtk_hbox_new( FALSE, 0 );
751
        gtk_box_pack_start( GTK_BOX( vbox ), hbox, FALSE, FALSE, 4 );
752
753
        label = gtk_label_new
754
                ( _("Reorder address book fields with the Up and Down button.") );
755
        gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 0 );
756
        gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
757
        gtk_label_set_line_wrap( GTK_LABEL( label ), TRUE );
758
759
        hbox = gtk_hbox_new( FALSE, 4 );
760
        gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 0 );
761
762
        clist_swin = gtk_scrolled_window_new( NULL, NULL );
763
        gtk_box_pack_start( GTK_BOX(hbox), clist_swin, TRUE, TRUE, 0 );
764
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
765
                                       GTK_POLICY_AUTOMATIC,
766
                                       GTK_POLICY_ALWAYS);
767
768
        clist_field = gtk_clist_new_with_titles( FIELDS_N_COLS, titles );
769
        gtk_container_add( GTK_CONTAINER(clist_swin), clist_field );
770
        gtk_clist_set_selection_mode( GTK_CLIST(clist_field), GTK_SELECTION_BROWSE );
771
        gtk_clist_set_column_width(
772
                        GTK_CLIST(clist_field), FIELD_COL_SELECT, FIELDS_COL_WIDTH_SELECT );
773
        gtk_clist_set_column_width(
774
                        GTK_CLIST(clist_field), FIELD_COL_FIELD, FIELDS_COL_WIDTH_FIELD );
775
        gtk_clist_set_column_width(
776
                        GTK_CLIST(clist_field), FIELD_COL_ATTRIB, FIELDS_COL_WIDTH_ATTRIB );
777
        gtkut_clist_set_redraw( GTK_CLIST(clist_field) );
778
779
        for( i = 0; i < FIELDS_N_COLS; i++ )
780
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist_field)->column[i].button, GTK_CAN_FOCUS);
781
782
        btn_vbox = gtk_vbox_new( FALSE, 0 );
783
        gtk_box_pack_start( GTK_BOX( hbox ), btn_vbox, FALSE, FALSE, 0 );
784
        gtk_container_set_border_width( GTK_CONTAINER (btn_vbox), 4 );
785
786
        btn_vbox1 = gtk_vbox_new( FALSE, 8 );
787
        gtk_box_pack_start( GTK_BOX( btn_vbox ), btn_vbox1, TRUE, FALSE, 0 );
788
789
        up_btn = gtk_button_new_with_label( _("Up") );
790
        gtk_box_pack_start( GTK_BOX( btn_vbox1 ), up_btn, FALSE, FALSE, 0 );
791
        down_btn = gtk_button_new_with_label( _("Down") );
792
        gtk_box_pack_start( GTK_BOX( btn_vbox1 ), down_btn, FALSE, FALSE, 0 );
793
794
        gtk_widget_show_all(vbox);
795
796
        g_signal_connect( G_OBJECT(clist_field), "select_row",
797
                          G_CALLBACK(imp_csv_field_list_selected), NULL );
798
        g_signal_connect( G_OBJECT(up_btn), "clicked",
799
                          G_CALLBACK(imp_csv_field_list_up), NULL );
800
        g_signal_connect( G_OBJECT(down_btn), "clicked",
801
                          G_CALLBACK(imp_csv_field_list_down), NULL );
802
803
        impcsv_dlg.clist_field  = clist_field;
804
}
805
806
static void imp_csv_page_finish( gint pageNum, gchar *pageLbl ) {
807
        GtkWidget *vbox;
808
        GtkWidget *table;
809
        GtkWidget *label;
810
        GtkWidget *labelBook;
811
        GtkWidget *labelFile;
812
        GtkWidget *labelRecs;
813
        gint top;
814
815
        vbox = gtk_vbox_new(FALSE, 8);
816
        gtk_container_add( GTK_CONTAINER( impcsv_dlg.notebook ), vbox );
817
        gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
818
819
        label = gtk_label_new( pageLbl );
820
        gtk_widget_show( label );
821
        gtk_notebook_set_tab_label(
822
                GTK_NOTEBOOK( impcsv_dlg.notebook ),
823
                gtk_notebook_get_nth_page( GTK_NOTEBOOK( impcsv_dlg.notebook ), pageNum ), label );
824
825
        table = gtk_table_new(3, 2, FALSE);
826
        gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
827
        gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
828
        gtk_table_set_row_spacings(GTK_TABLE(table), 8);
829
        gtk_table_set_col_spacings(GTK_TABLE(table), 8 );
830
831
        /* First row */
832
        top = 0;
833
        label = gtk_label_new(_("Address Book :"));
834
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
835
        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
836
837
        labelBook = gtk_label_new("");
838
        gtk_table_attach(GTK_TABLE(table), labelBook, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
839
        gtk_misc_set_alignment(GTK_MISC(labelBook), 0, 0.5);
840
841
        /* Second row */
842
        top++;
843
        label = gtk_label_new(_("File Name :"));
844
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
845
        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
846
847
        labelFile = gtk_label_new("");
848
        gtk_table_attach(GTK_TABLE(table), labelFile, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
849
        gtk_misc_set_alignment(GTK_MISC(labelFile), 0, 0.5);
850
        gtk_label_set_line_wrap(GTK_LABEL(labelFile), TRUE);
851
852
        /* Third row */
853
        top++;
854
        label = gtk_label_new(_("Records :"));
855
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
856
        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
857
858
        labelRecs = gtk_label_new("");
859
        gtk_table_attach(GTK_TABLE(table), labelRecs, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
860
        gtk_misc_set_alignment(GTK_MISC(labelRecs), 0, 0.5);
861
862
        impcsv_dlg.labelBook    = labelBook;
863
        impcsv_dlg.labelFile    = labelFile;
864
        impcsv_dlg.labelRecords = labelRecs;
865
}
866
867
static void imp_csv_dialog_create() {
868
        GtkWidget *window;
869
        GtkWidget *vbox;
870
        GtkWidget *vnbox;
871
        GtkWidget *notebook;
872
        GtkWidget *hbbox;
873
        GtkWidget *btnPrev;
874
        GtkWidget *btnNext;
875
        GtkWidget *btnCancel;
876
        GtkWidget *hsbox;
877
        GtkWidget *statusbar;
878
879
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
880
        gtk_widget_set_size_request(window, IMPORTCSV_WIDTH, IMPORTCSV_HEIGHT );
881
        gtk_container_set_border_width( GTK_CONTAINER(window), 0 );
882
        gtk_window_set_title( GTK_WINDOW(window), _("Import CSV file into Address Book") );
883
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
884
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);        
885
        g_signal_connect(G_OBJECT(window), "delete_event",
886
                         G_CALLBACK(imp_csv_delete_event), NULL);
887
        g_signal_connect(G_OBJECT(window), "key_press_event",
888
                         G_CALLBACK(imp_csv_key_pressed), NULL);
889
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
890
891
        vbox = gtk_vbox_new(FALSE, 4);
892
        gtk_widget_show(vbox);
893
        gtk_container_add(GTK_CONTAINER(window), vbox);
894
895
        vnbox = gtk_vbox_new(FALSE, 4);
896
        gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
897
        gtk_widget_show(vnbox);
898
        gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
899
900
        /* Notebook */
901
        notebook = gtk_notebook_new();
902
        gtk_notebook_set_show_tabs( GTK_NOTEBOOK(notebook), FALSE );
903
        gtk_widget_show(notebook);
904
        gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
905
        gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
906
907
        /* Status line */
908
        hsbox = gtk_hbox_new(FALSE, 0);
909
        gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, 0);
910
        statusbar = gtk_statusbar_new();
911
        gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, 0);
912
913
        /* Button panel */
914
        gtkut_stock_button_set_create(&hbbox, &btnNext, _("Next"),
915
                                      &btnPrev, _("Prev"),
916
                                      &btnCancel, GTK_STOCK_CANCEL);
917
        gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(hbbox), btnCancel,
918
                                           TRUE);
919
        gtkut_box_set_reverse_order(GTK_BOX(hbbox), FALSE);
920
        gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
921
        gtk_container_set_border_width(GTK_CONTAINER(hbbox), 4);
922
        gtk_widget_grab_default(btnNext);
923
924
        /* Button handlers */
925
        g_signal_connect(G_OBJECT(btnPrev), "clicked",
926
                         G_CALLBACK(imp_csv_prev), NULL);
927
        g_signal_connect(G_OBJECT(btnNext), "clicked",
928
                         G_CALLBACK(imp_csv_next), NULL);
929
        g_signal_connect(G_OBJECT(btnCancel), "clicked",
930
                         G_CALLBACK(imp_csv_cancel), NULL);
931
932
        gtk_widget_show_all(vbox);
933
934
        impcsv_dlg.window     = window;
935
        impcsv_dlg.notebook   = notebook;
936
        impcsv_dlg.btnPrev    = btnPrev;
937
        impcsv_dlg.btnNext    = btnNext;
938
        impcsv_dlg.btnCancel  = btnCancel;
939
        impcsv_dlg.statusbar  = statusbar;
940
        impcsv_dlg.status_cid = gtk_statusbar_get_context_id(
941
                        GTK_STATUSBAR(statusbar), "Import CSV Dialog" );
942
943
}
944
945
static void imp_csv_create() {
946
        imp_csv_dialog_create();
947
        imp_csv_page_file( PAGE_FILE_INFO, _( "File Info" ) );
948
        imp_csv_page_fields( PAGE_ATTRIBUTES, _( "Fields" ) );
949
        imp_csv_page_finish( PAGE_FINISH, _( "Finish" ) );
950
        gtk_widget_show_all( impcsv_dlg.window );
951
}
952
953
AddressBookFile *addressbook_imp_csv( AddressIndex *addrIndex ) {
954
        _importedBook_ = NULL;
955
        _imp_addressIndex_ = addrIndex;
956
957
        if( ! impcsv_dlg.window )
958
                imp_csv_create();
959
        impcsv_dlg.cancelled = FALSE;
960
        manage_window_set_transient(GTK_WINDOW(impcsv_dlg.window));
961
        gtk_widget_grab_default(impcsv_dlg.btnNext);
962
963
        gtk_entry_set_text( GTK_ENTRY(impcsv_dlg.name_entry), IMPORTCSV_GUESS_NAME );
964
        gtk_entry_set_text( GTK_ENTRY(impcsv_dlg.file_entry), "" );
965
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(impcsv_dlg.comma_radiobtn), TRUE );
966
        gtk_clist_clear( GTK_CLIST(impcsv_dlg.clist_field) );
967
        gtk_notebook_set_current_page( GTK_NOTEBOOK(impcsv_dlg.notebook), PAGE_FILE_INFO );
968
        gtk_widget_set_sensitive( impcsv_dlg.btnPrev, FALSE );
969
        gtk_widget_set_sensitive( impcsv_dlg.btnNext, TRUE );
970
        gtk_button_set_label( GTK_BUTTON(impcsv_dlg.btnCancel), GTK_STOCK_CANCEL );
971
        stock_pixmap_gdk( impcsv_dlg.window, STOCK_PIXMAP_MARK,
972
                          &markxpm, &markxpmmask );
973
        imp_csv_message();
974
        gtk_widget_grab_focus(impcsv_dlg.file_entry);
975
976
        impcsv_dlg.rowCount = 0;
977
        g_free( impcsv_dlg.nameBook );
978
        g_free( impcsv_dlg.fileName );
979
        impcsv_dlg.nameBook = NULL;
980
        impcsv_dlg.fileName = NULL;
981
        impcsv_dlg.delimiter = ',';
982
        importCount = 0;
983
984
        gtk_widget_show(impcsv_dlg.window);
985
986
        gtk_main();
987
        gtk_widget_hide(impcsv_dlg.window);
988
        _imp_addressIndex_ = NULL;
989
990
        g_free( impcsv_dlg.nameBook );
991
        g_free( impcsv_dlg.fileName );
992
        impcsv_dlg.nameBook = NULL;
993
        impcsv_dlg.fileName = NULL;
994
995
        if( impcsv_dlg.cancelled == TRUE ) return NULL;
996
        return _importedBook_;
997
}
998
999
/*
1000
* End of Source.
1001
*/
1002