fileout.c File Reference


Detailed Description

Export routines.

Author:
Copyright 2006-2007 Neil Williams <linux@codehelp.co.uk>

Copyright 1999 Robert Lissner

Definition in file fileout.c.

#include "config.h"
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gtkextra/gtksheet.h>
#include "types.h"
#include "dialog_initial.h"
#include "dim_list_menu.h"
#include "edit.h"
#include "filein.h"
#include "main.h"
#include "report.h"

Go to the source code of this file.

Enumerations

enum  QlCloseMode { QL_CLOSE, QL_QUIT }
enum  QlPrintType { QL_PRINT_NONE, QL_PRINT_ALL, QL_PRINT_LIT, QL_PRINT_FILTER }

Functions

static void all_data_clicked (GtkWidget G_GNUC_UNUSED *w, gpointer G_GNUC_UNUSED data)
static void filter_data_clicked (GtkWidget G_GNUC_UNUSED *w, gpointer G_GNUC_UNUSED data)
static void highlighted_data_clicked (GtkWidget G_GNUC_UNUSED *w, gpointer G_GNUC_UNUSED data)
static void ask_about_all (QlTabData *tab, GtkWidget *chooser)
static void remove_ql_chars (gchar *text)
static void print_field_cb (gpointer G_GNUC_UNUSED field_index, gpointer field_ptr, gpointer user_data)
static void write_ql_file (QlTabData *tab, FILE *f)
static void write_html (QlTabData *tab, FILE *f)
static void write_delimited (QlTabData *tab, FILE *f, gchar separator)
static void write_all_types (QlTabData *tab, gchar *name)
static void update_title (gchar G_GNUC_UNUSED *filename, QlTabData *tab)
static void any_save (QlTabData *tab)
gboolean ask_about_save (QlTabData *tab)
void close_file (GtkAction G_GNUC_UNUSED *w, gpointer data)
gboolean exit_action (GtkAction G_GNUC_UNUSED *a, gpointer data)
gboolean file_exit (GtkWidget *w, GdkEvent G_GNUC_UNUSED *event, gpointer G_GNUC_UNUSED data)
void file_export (GtkAction G_GNUC_UNUSED *w, gpointer data)
void save_as (GtkAction G_GNUC_UNUSED *w, gpointer data)
void save_file (GtkAction G_GNUC_UNUSED *w, gpointer data)

Variables

QlCloseMode close_mode
GtkSheetRange write_range
static QlPrintType print_all = QL_PRINT_NONE


Enumeration Type Documentation

enum QlCloseMode

Enumerator:
QL_CLOSE  closing one notebook tab
QL_QUIT  quitting QuickList completely

Definition at line 43 of file fileout.c.

00044 {
00046     QL_CLOSE,
00048     QL_QUIT
00049 } QlCloseMode;

enum QlPrintType

Enumerator:
QL_PRINT_NONE  default
QL_PRINT_ALL  print the entire sheet
QL_PRINT_LIT  print only those cells that are selected.
QL_PRINT_FILTER  print cells that match the active filter.

Definition at line 56 of file fileout.c.

00057 {
00059     QL_PRINT_NONE,
00061     QL_PRINT_ALL,
00063     QL_PRINT_LIT,
00065     QL_PRINT_FILTER
00066 } QlPrintType;


Function Documentation

static void ask_about_all ( QlTabData tab,
GtkWidget *  chooser 
) [static]

These buttons offer to export less than the whole file

Definition at line 90 of file fileout.c.

00091 {
00092     GtkWidget *all_data;
00093     GtkWidget *filter_data;
00094     GtkWidget *highlighted_data;
00095     GtkWidget *hbox;
00096 
00097     print_all = QL_PRINT_ALL;
00098     hbox = gtk_hbox_new (FALSE, 5);
00099     all_data = gtk_radio_button_new_with_label (NULL, _("Entire file"));
00100     gtk_box_pack_start (GTK_BOX (hbox), all_data, FALSE, FALSE, 0);
00101     g_signal_connect (all_data, "clicked",
00102         G_CALLBACK (all_data_clicked), NULL);
00103 
00104     filter_data = gtk_radio_button_new_with_label
00105         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (all_data)),
00106         _("Allowed by filter"));
00107     if (!tab->file->filter_ptr)
00108         gtk_widget_set_sensitive (filter_data, FALSE);
00109     gtk_box_pack_start (GTK_BOX (hbox), filter_data, FALSE, FALSE, 0);
00110     g_signal_connect (filter_data, "clicked",
00111         G_CALLBACK (filter_data_clicked), NULL);
00112 
00113     highlighted_data = gtk_radio_button_new_with_label
00114         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (all_data)),
00115         _("Highlighted cells"));
00116     gtk_box_pack_start (GTK_BOX (hbox), highlighted_data, FALSE, FALSE, 0);
00117     g_signal_connect (highlighted_data, "clicked",
00118         G_CALLBACK (highlighted_data_clicked), NULL);
00119 
00120     /* there can only be a selection if some cells are selected, more than one */
00121     if (tab->view->dialog_mode == MODE_SAVE ||
00122         (tab->view->sel_type == SELECT_ENTRY || 
00123             tab->view->sel_type != SELECT_COLUMN))
00124         gtk_widget_set_sensitive (highlighted_data, FALSE);
00125     gtk_widget_show_all (hbox);
00126     gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(chooser), hbox);
00127 }                               /* end of ask_about_all */

gboolean ask_about_save ( QlTabData tab  ) 

This dialogue box is called by the close and quit routines to just ask if the front file should be saved onto disk before the window is closed.

Returns:
TRUE to continue with quicklist, FALSE to quit.
Bug:
should indicate what kind of data is new: fields, sort patterns, filters or reports.

Definition at line 597 of file fileout.c.

00598 {
00599     GtkWidget * ask_dlg;
00600     gboolean ret;
00601     gint result;
00602 
00603     ret = FALSE;
00604     /* no tabs, no data to save */
00605     if (!tab)
00606         return FALSE;
00607     if (gtk_notebook_get_current_page (tab->qlc->notebook) < 0)
00608         return FALSE;
00609     if (!check_if_changed(tab))
00610         return FALSE;
00611     ask_dlg = gtk_message_dialog_new (GTK_WINDOW(tab->qlc->parent),
00612         GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
00613         GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
00614         "%s", _("This file has been changed. "
00615             "Do you want to save it to disk?"));
00616     gtk_dialog_add_buttons (GTK_DIALOG(ask_dlg),
00617         GTK_STOCK_YES, GTK_RESPONSE_YES,
00618         GTK_STOCK_NO,  GTK_RESPONSE_NO,
00619         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
00620     
00621     result = gtk_dialog_run (GTK_DIALOG (ask_dlg));
00622     switch (result)
00623     {
00624         case GTK_RESPONSE_YES:
00625         {
00626             /* if user said Yes, save the file */
00627             any_save (tab);
00628             break;
00629         }
00630         case GTK_RESPONSE_NO:
00631         {
00632             gint tab_index;
00633             tab_index = gtk_notebook_get_current_page (tab->qlc->notebook);
00634             gtk_notebook_remove_page (tab->qlc->notebook, tab_index);
00635             if (tab->file->file_path)
00636                 g_free (tab->file->file_path);
00637             tab->file->file_path = NULL;
00638             break;
00639         }
00640         case GTK_RESPONSE_CANCEL :
00641             ret = TRUE;
00642             break;
00643     }
00644     gtk_widget_destroy (ask_dlg);
00645     return ret;
00646 }                               /* End of ask_about_save */

static void print_field_cb ( gpointer G_GNUC_UNUSED  field_index,
gpointer  field_ptr,
gpointer  user_data 
) [static]

<

Bug:
stop passing FILE pointers around.

Definition at line 149 of file fileout.c.

00150 {
00151     QlFieldInfo * field = (QlFieldInfo*)field_ptr;
00152     FILE * f; 
00153     f = (FILE*)user_data;
00154 
00155     remove_ql_chars (field->name);
00156     fprintf (f, "FIELD %u %u %u %u %u %u %u %u %s\n",
00157         field->type,
00158         field->formatting,
00159         field->decimal_places,
00160         field->justification,
00161         field->sheet_column,
00162         field->width,
00163         field->unused1,
00164         field->unused2, 
00165         field->name);
00166 }

static void remove_ql_chars ( gchar *  text  )  [static]

Routine removes backslash and trailing blanks, which are of no value.

Todo:
Replace with glib functions g_strchug and g_strchomp

Definition at line 135 of file fileout.c.

00136 {
00137     gchar *linebufp = text;
00138     while (*linebufp)
00139     {
00140         if (*linebufp == '\\')
00141             *linebufp = '/';
00142         linebufp++;
00143     }
00144     linebufp--;                 /* skip back over ending zero */
00145     linebufp = g_strstrip (linebufp); /* removes trailing blanks */
00146 }                               /* end of remove_ql_chars */

void save_file ( GtkAction G_GNUC_UNUSED *  w,
gpointer  data 
)

Write the file onto disk with its present file path

Definition at line 732 of file fileout.c.

00733 {
00734     QlContext * qlc;
00735     QlTabData * tab;
00736 
00737     qlc = ql_get_context (GTK_WIDGET(data));
00738     tab = ql_get_tabdata (qlc);
00739     print_all = QL_PRINT_ALL;
00740     if ((tab->file->current_file == QL_NO_FILE) ||
00741         (tab->view->dialog_mode == MODE_NEW))
00742     {
00743         tab->file->current_file = tab->file->file_type = QL_OLD_QLF;
00744         tab->view->dialog_mode = MODE_NEW;
00745         any_save (tab);
00746     }
00747     else
00748     {
00749         tab->file->file_type = QL_OLD_QLF;
00750         tab->view->dialog_mode = MODE_SAVE;
00751         save_as (NULL, data);
00752     }
00753 }

static void write_all_types ( QlTabData tab,
gchar *  name 
) [static]

This puts all file types onto disk

Todo:
stop using f

Todo:
stop passing f

Todo:
stop passing f

Todo:
stop passing f

Definition at line 411 of file fileout.c.

00412 {
00413     FILE * f;
00414     gchar * backup_name;
00415     gchar * fullpath;
00416 
00417     g_return_if_fail (tab);
00418     g_return_if_fail (tab->file->file_type > QL_NO_FILE);
00419 
00420     tab->file->file_name = name;
00421     fullpath = tab->file->file_path;
00422 
00423     backup_name = g_strconcat (fullpath, "~", NULL);
00424     rename (fullpath, backup_name);
00425 
00426     /* determine if whole file is to be written */
00427     write_range.row0 = write_range.col0 = 0;
00428     write_range.rowi = tab->file->last_row - 1;
00429     write_range.coli = tab->file->last_field;
00430     if (print_all == QL_PRINT_LIT)      /* highlighted */
00431         write_range = tab->view->sel_range;
00432 
00433     f = NULL;
00434     switch (tab->file->file_type)
00435     {
00436         case QL_OLD_QLF:
00437         {
00438             if (!g_str_has_suffix(fullpath, "qlf"))
00439             {
00440                 fullpath = g_strconcat (fullpath, ".qlf", NULL);
00441             }
00442             if (!(f = fopen (fullpath, "w")))
00443             {
00444                 level1_error (tab, _("Can't write the file.  Strange.")); 
00445                 return;
00446             }
00448             write_ql_file (tab, f);
00449             tab->file->file_name = g_path_get_basename (fullpath);
00450             tab->file->file_path = fullpath;
00451             tab->file->changed = FALSE;
00452             break;
00453         }
00454         case QL_EXPORT_HTML:
00455         {
00456             if (!g_str_has_suffix(name, "html"))
00457             {
00458                 name = g_strconcat (name, ".html", NULL);
00459             }
00460             if (!(f = fopen (name, "w")))
00461             {
00462                 level1_error (tab, _("Can't write the file.  Strange.")); 
00463                 return;
00464             }
00466             write_html (tab, f);
00467             tab->file->file_name = name;
00468             break;
00469         }
00470         case QL_CSV:
00471         {
00472             if (!g_str_has_suffix(name, "csv"))
00473             {
00474                 name = g_strconcat (name, ".csv", NULL);
00475             }
00476             if (!(f = fopen (name, "w")))
00477             {
00478                 level1_error (tab, _("Can't write the file.  Strange.")); 
00479                 return;
00480             }
00482             write_delimited (tab, f, ',');
00483             tab->file->file_name = name;
00484             break;
00485         }
00486         case QL_TSV:
00487         {
00488             if (!g_str_has_suffix(name, "tsv"))
00489             {
00490                 name = g_strconcat (name, ".tsv", NULL);
00491             }
00492             if (!(f = fopen (name, "w")))
00493             {
00494                 level1_error (tab, _("Can't write the file.  Strange.")); 
00495                 return;
00496             }
00498             write_delimited (tab, f, '\t');
00499             tab->file->file_name = name;
00500             break;
00501         }
00502         default:
00503             break;
00504     }
00505     fclose (f);
00506     dim_all_menus (tab->qlc);
00507 }                               /* end of write_all_types */

static void write_delimited ( QlTabData tab,
FILE *  f,
gchar  separator 
) [static]

Write the file onto disk with called char as a separator.

Todo:
replace this static buffer!

Definition at line 371 of file fileout.c.

00372 {
00374     gchar linebuf[4096];
00375     gchar *text;
00376     gint32 rowx;
00377     gint16 colx;                /* indexes into array */
00378     gint x, y;
00379     gboolean first_in_row;
00380 
00381     /* NOW WRITE THE DATA RECORDS.  Last row is always empty. */
00382     for (rowx = write_range.row0; rowx < write_range.rowi; rowx++)
00383     {
00384         if (print_all != QL_PRINT_ALL && !row_is_visible (tab, rowx))
00385             continue;
00386         first_in_row = TRUE;
00387         for (colx = write_range.col0; colx <= write_range.coli; colx++)
00388         {
00389             text = gtk_sheet_cell_get_text (tab->view->sheet, rowx, colx);
00390             if (!first_in_row)
00391                 fprintf (f, "%c", separator);
00392             first_in_row = FALSE;
00393             if (text)
00394             {
00395                 x = y = 0;      /* remove separator characters from data */
00396                 do
00397                 {
00398                     if (text[x] != separator)
00399                         linebuf[y++] = text[x];
00400                 }
00401                 while (text[x++]);  /* stop at end of string */
00402                 fprintf (f, "%s", linebuf);
00403             }
00404         }
00405         fprintf (f, "\n");      /* write nothing if nothing there */
00406     }
00407 }                               /* end of write_delimited */

static void write_html ( QlTabData tab,
FILE *  f 
) [static]

Todo:
replace with gtkhtml.
In effect, create a dummy report that includes all sheet data.

Definition at line 311 of file fileout.c.

00312 {
00313     gchar *text;
00314     gint32 rowx;
00315     gint16 fieldx;
00316     gint16 justification;
00317     QlFieldInfo * field;
00318     gint16 colx = 0;            /* indexes into array */
00319 
00320     /* Output Head Info Stuff */
00321     fprintf (f,
00322         "<html>\n"
00323         "<head>\n"
00324         "<title>%s</title>\n"
00325         "<meta name=\"Generator\" content=\"QUICKLIST %s\">\n"
00326         "</head>\n\n"
00327         "<body bgcolor=\"#ffffff\">\n"
00328         "<table width=\"2\">\n" "  <tr>\n", 
00329         tab->file->file_path, VERSION);
00330     for (colx = write_range.col0; colx <= write_range.coli; colx++)
00331     {
00332         fieldx = tab->file->col_to_field[colx];
00333         field = ql_get_fieldinfo (tab, fieldx);
00334         fprintf (f, "    <th>%s</th>\n", field->name);
00335     }
00336     fprintf (f, "  </tr>\n");
00337 
00338     for (rowx = write_range.row0; rowx <= write_range.rowi; rowx++)
00339     {
00340         if (print_all != 'A' && !row_is_visible (tab, rowx))
00341             continue;
00342         fprintf (f, "  <tr>\n");
00343         for (colx = write_range.col0; colx <= write_range.coli; colx++)
00344         {
00345             text = gtk_sheet_cell_get_text (tab->view->sheet, rowx, colx);
00346             fputs ("<td>", f);
00347             if (text)
00348             {
00349                 fieldx = tab->file->col_to_field[colx];
00350                 field = ql_get_fieldinfo (tab, fieldx);
00351                 justification = field->justification;
00352                 if (justification == GTK_JUSTIFY_CENTER)
00353                     fputs ("<center>", f);
00354                 else if (justification == GTK_JUSTIFY_RIGHT)
00355                     fputs ("<right>", f);
00356                 fprintf (f, "%s", text);
00357                 if (justification == GTK_JUSTIFY_CENTER)
00358                     fputs ("</center>", f);
00359                 else if (justification == GTK_JUSTIFY_RIGHT)
00360                     fputs ("</right>", f);
00361             }
00362             fputs ("</td>\n", f);
00363         }
00364         fprintf (f, "  </tr>\n");
00365     }
00366     fprintf (f, "</table>\n</body>\n</html>\n");
00367 }                               /* end of html output */

static void write_ql_file ( QlTabData tab,
FILE *  f 
) [static]

Write the file onto disk. Called by save, save_as, close, quit

Bug:
stop passing f, just pass the filename, if at all.

indexes into array

try to not write trailing slashes

try to not write blank records

Definition at line 171 of file fileout.c.

00172 {
00173     gchar *text;
00174     gint32 rowx;
00175     gint16 fieldx = 0;
00176     gint16 sortx = 0;
00177     gint16 filterx = 0;
00178     gint16 subx = 0;
00179     gint16 reportx = 0;
00181     gint16 colx = 0;
00183     gint16 blank_fields;
00185     gboolean got_data;
00186 
00187     g_return_if_fail (tab);
00188     get_window_size_loc (GTK_WIDGET (tab->qlc->parent));
00189 
00190     fprintf (f, "QUICKLIST %s 06/10/99 %u %u %u %u %u %u %u %u\n",
00191         VERSION,
00192         tab->file->last_field + 1,
00193         tab->file->sort_ct,
00194         tab->file->filter_ct,
00195         tab->file->report_ct, tab->view->width, tab->view->height, 
00196         tab->view->x, tab->view->y);
00197     ql_fieldinfo_foreach (tab, print_field_cb, f);
00198 /*
00199     for (fieldx = 0; fieldx <= tab->file->last_field; fieldx++)
00200     {
00201         remove_ql_chars (tab->file->fields[fieldx]->name);
00202         fprintf (f, "FIELD %u %u %u %u %u %u %u %u %s\n",
00203             tab->file->fields[fieldx]->type,
00204             tab->file->fields[fieldx]->formatting,
00205             tab->file->fields[fieldx]->decimal_places,
00206             tab->file->fields[fieldx]->justification,
00207             tab->file->fields[fieldx]->sheet_column,
00208             tab->file->fields[fieldx]->width,
00209             tab->file->fields[fieldx]->unused1,
00210             tab->file->fields[fieldx]->unused2, 
00211             tab->file->fields[fieldx]->name);
00212     }
00213 */
00214     for (sortx = 0; sortx < tab->file->sort_ct; sortx++)
00215     {
00216         remove_ql_chars (tab->file->sorts[sortx].name);
00217         fprintf (f, "SORT %u %u %s\\",
00218             tab->file->sorts[sortx].unused1,
00219             tab->file->sorts[sortx].unused2, 
00220             tab->file->sorts[sortx].name);
00221         for (subx = 0; subx < tab->file->sorts[sortx].line_ct; subx++)
00222             fprintf (f, " %u %u",
00223                 tab->file->sorts[sortx].line[subx].field,
00224                 tab->file->sorts[sortx].line[subx].ascending);
00225         fprintf (f, "\n");
00226     }                           /* end of printing one sort record */
00227 
00228     /* Here we need to write a filter. */
00229     for (filterx = 0; filterx < tab->file->filter_ct; filterx++)
00230     {
00231         remove_ql_chars (tab->file->filters[filterx].name);
00232         fprintf (f, "FILTER %d %d %s",
00233             tab->file->filters[filterx].by_and,
00234             tab->file->filters[filterx].use_nocase,
00235             tab->file->filters[filterx].name);
00236         for (subx = 0; subx < tab->file->filters[filterx].line_ct; subx++)
00237         {
00238             fprintf (f, "\\%u %u",
00239                 tab->file->filters[filterx].line[subx].field,
00240                 tab->file->filters[filterx].line[subx].type);
00241             remove_ql_chars (tab->file->filters[filterx].line[subx].compare);
00242             fprintf (f, " %s", tab->file->filters[filterx].line[subx].compare);
00243         }
00244         fprintf (f, "\n");      /* Finish off the filter */
00245     }
00246 
00247     /* Now a report column */
00248     for (reportx = 0; reportx < tab->file->report_ct; reportx++)
00249     {
00250         for (colx = 0; colx <= tab->file->reports[reportx].last_column; colx++)
00251             fprintf (f, "COLUMN %u %u %u %u %u %u\n",
00252                 tab->file->reports[reportx].column[colx].field,
00253                 tab->file->reports[reportx].column[colx].width,
00254                 tab->file->reports[reportx].column[colx].group,
00255                 tab->file->reports[reportx].column[colx].total,
00256                 tab->file->reports[reportx].column[colx].unused1,
00257                 tab->file->reports[reportx].column[colx].unused2);
00258 
00259         remove_ql_chars (tab->file->reports[reportx].name);
00260         fprintf (f, "REPORT %i %i %u %u %s\\\\\n",
00261             tab->file->reports[reportx].sort,
00262             tab->file->reports[reportx].filter,
00263             tab->file->reports[reportx].width,
00264             tab->file->reports[reportx].height, 
00265             tab->file->reports[reportx].name);
00266 
00267     }                           /* end of writing report columns and report records */
00268     fprintf (f, "DATA 0 0\n");
00269 
00270     /* NOW WRITE THE DATA RECORDS.  Last row is always empty. 
00271        The logic is difficult enough that I use an intermediate variable */
00272     for (rowx = 0; rowx < tab->file->last_row; rowx++)
00273     {
00274         gint last_field;
00275         got_data = FALSE;       /* to not write empty records */
00276         blank_fields = 0;       /* to not write trailing \\\\\ */
00277         last_field = ql_get_last_field (tab);
00278         for (fieldx = 0; fieldx <= last_field; fieldx++)
00279         {
00280             QlFieldInfo * field;
00281             field = ql_get_fieldinfo (tab, fieldx);
00282             colx = field->sheet_column;
00283             text = gtk_sheet_cell_get_text (tab->view->sheet, rowx, colx);
00284             if (text)
00285             {
00286                 while (blank_fields)
00287                 {               /* write the skipped blank fields */
00288                     fprintf (f, "\\");
00289                     blank_fields--;
00290                 }
00291 
00292                 remove_ql_chars (text);
00293                 fprintf (f, "%s\\", text);
00294                 got_data = TRUE;
00295             }
00296             else
00297                 blank_fields++;
00298         }
00299         if (got_data)
00300             fprintf (f, "\n");  /* write nothing if nothing there */
00301     }
00302     fprintf (f, "\n");          /* write nothing if nothing there */
00303     tab->file->changed = FALSE;
00304 }


Variable Documentation

GtkSheetRange write_range

for writing less than whole file

Definition at line 54 of file fileout.c.


Generated on Mon Jan 28 22:02:10 2008 for quicklist by  doxygen 1.5.4