diff options
Diffstat (limited to 'report.c')
-rw-r--r-- | report.c | 536 |
1 files changed, 410 insertions, 126 deletions
@@ -1,6 +1,6 @@ /* * HardInfo - Displays System Information - * Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@linuxmag.com.br> + * Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@linuxmag.com.br> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,67 +20,72 @@ #include <stdio.h> #include <string.h> #include <shell.h> +#include <iconcache.h> #include <hardinfo.h> +#include <config.h> static ReportDialog *report_dialog_new(GtkTreeModel *model, GtkWidget *parent); static void set_all_active(ReportDialog *rd, gboolean setting); -static void -report_html_header(ReportContext *ctx) +static FileTypes file_types[] = { + { "HTML (*.html)", "text/html", ".html", report_context_html_new }, + { "Plain Text (*.txt)", "text/plain", ".txt", report_context_text_new }, + { NULL, NULL, NULL, NULL } +}; + +void +report_header(ReportContext *ctx) { - fprintf(ctx->stream, - "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Final//EN\">\n" \ - "<html><head>\n" \ - "<title>HardInfo System Report</title>\n" \ - "<style>\n" \ - "body { background: #fff }\n" \ - ".title { font: bold 130%% serif; color: #0066FF; padding: 30px 0 10px 0 }\n" \ - ".stitle { font: bold 100%% sans-serif; color: #0044DD; padding: 30px 0 10px 0 }\n" \ - ".sstitle{ font: bold 80%% serif; color: #000000; background: #efefef }\n" \ - ".field { font: 80%% sans-serif; color: #000000; padding: 2px; padding-left: 50px }\n" \ - ".value { font: 80%% sans-serif; color: #505050 }\n" \ - "</style>\n" \ - "</head><body>\n" \ - "<table width=\"100%%\"><tbody>"); + ctx->header(ctx); } -static void -report_html_footer(ReportContext *ctx) +void +report_footer(ReportContext *ctx) { - fprintf(ctx->stream, - "</tbody></table></body></html>"); + ctx->footer(ctx); } -static void -report_html_title(ReportContext *ctx, gchar *text) +void +report_title(ReportContext *ctx, gchar *text) { - fprintf(ctx->stream, - "<tr><td colspan=\"2\" class=\"title\">%s</td></tr>\n", text); + ctx->title(ctx, text); } -static void -report_html_subtitle(ReportContext *ctx, gchar *text) +void +report_subtitle(ReportContext *ctx, gchar *text) { - fprintf(ctx->stream, - "<tr><td colspan=\"2\" class=\"stitle\">%s</td></tr>\n", text); + ctx->subtitle(ctx, text); } -static void -report_html_subsubtitle(ReportContext *ctx, gchar *text) + +void +report_subsubtitle(ReportContext *ctx, gchar *text) { - fprintf(ctx->stream, - "<tr><td colspan=\"2\" class=\"sstitle\">%s</td></tr>\n", text); + ctx->subsubtitle(ctx, text); } -static void -report_html_key_value(ReportContext *ctx, gchar *key, gchar *value) +void +report_key_value(ReportContext *ctx, gchar *key, gchar *value) { - fprintf(ctx->stream, - "<tr><td class=\"field\">%s</td>" \ - "<td class=\"value\">%s</td></tr>\n", key, value); + ctx->keyvalue(ctx, key, value); } -static void -report_html_table(ReportContext *ctx, gchar *text) +void +report_context_configure(ReportContext *ctx, GKeyFile *keyfile) +{ + /* FIXME: sometime in the future we'll save images in the report. this + flag will be set if we should support that. + + so i don't forget how to encode the images inside the html files: + http://en.wikipedia.org/wiki/Data:_URI_scheme */ + + ctx->is_image_enabled = (g_key_file_get_boolean(keyfile, + "$ShellParam$", + "ViewType", + NULL) == SHELL_VIEW_PROGRESS); +} + +void +report_table(ReportContext *ctx, gchar *text) { GKeyFile *key_file = g_key_file_new(); gchar **groups; @@ -94,50 +99,56 @@ report_html_table(ReportContext *ctx, gchar *text) gchar **keys; gint j; - if (groups[i][0] == '$') + if (groups[i][0] == '$') { + report_context_configure(ctx, key_file); continue; + } group = groups[i]; - keys = g_key_file_get_keys(key_file, group, NULL, NULL); tmpgroup = g_strdup(group); strend(group, '#'); - report_html_subsubtitle(ctx, group); + report_subsubtitle(ctx, group); - for (j = 0; keys[j]; j++) { - gchar *key = keys[j]; - gchar *value; - - value = g_key_file_get_value(key_file, tmpgroup, key, NULL); - - if (g_utf8_validate(key, -1, NULL) && g_utf8_validate(value, -1, NULL)) { - strend(key, '#'); - - if (g_str_equal(value, "...")) { - g_free(value); - if (!(value = ctx->entry->fieldfunc(key))) { - value = g_strdup("..."); +#if 0 + if (ctx->is_image_enabled) { + report_embed_image(ctx, key_file, group); + } else { +#endif + keys = g_key_file_get_keys(key_file, tmpgroup, NULL, NULL); + for (j = 0; keys[j]; j++) { + gchar *key = keys[j]; + gchar *value; + + value = g_key_file_get_value(key_file, tmpgroup, key, NULL); + + if (g_utf8_validate(key, -1, NULL) && g_utf8_validate(value, -1, NULL)) { + strend(key, '#'); + + if (g_str_equal(value, "...")) { + g_free(value); + if (!(value = ctx->entry->fieldfunc(key))) { + value = g_strdup("..."); + } + } + + if (*key == '$') { + report_key_value(ctx, strchr(key + 1, '$') + 1, value); + } else { + report_key_value(ctx, key, value); } - } - - if (*key == '$') { - gchar **tmp; - - tmp = g_strsplit(++key, "$", 0); - report_html_key_value(ctx, tmp[1], value); - g_strfreev(tmp); - } else { - report_html_key_value(ctx, key, value); - } - + + } + + g_free(value); } - g_free(value); - } - + g_strfreev(keys); +#if 0 + } +#endif g_free(tmpgroup); - g_strfreev(keys); } g_strfreev(groups); @@ -145,43 +156,213 @@ report_html_table(ReportContext *ctx, gchar *text) } static void -report_generate_child(ReportContext *ctx, GtkTreeIter *iter) +report_html_header(ReportContext *ctx) { - ShellModuleEntry *entry; - gboolean selected; + if (ctx->output) + g_free(ctx->output); - gtk_tree_model_get(ctx->rd->model, iter, TREE_COL_SEL, &selected, -1); - if (!selected) - return; + ctx->output = g_strdup_printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Final//EN\">\n" \ + "<html><head>\n" \ + "<title>HardInfo (%s) System Report</title>\n" \ + "<style>\n" \ + " body { background: #fff }\n" \ + " .title { font: bold 130%% serif; color: #0066FF; padding: 30px 0 10px 0 }\n" \ + " .stitle { font: bold 100%% sans-serif; color: #0044DD; padding: 30px 0 10px 0 }\n" \ + " .sstitle{ font: bold 80%% serif; color: #000000; background: #efefef }\n" \ + " .field { font: 80%% sans-serif; color: #000000; padding: 2px; padding-left: 50px }\n" \ + " .value { font: 80%% sans-serif; color: #505050 }\n" \ + "</style>\n" \ + "</head><body>\n" \ + "<table width=\"100%%\"><tbody>", VERSION); +} + +static void +report_html_footer(ReportContext *ctx) +{ + ctx->output = g_strconcat(ctx->output, + "</tbody></table></body></html>", + NULL); +} + +static void +report_html_title(ReportContext *ctx, gchar *text) +{ + ctx->output = g_strdup_printf("%s" \ + "<tr><td colspan=\"2\" class=\"titl" \ + "e\">%s</td></tr>\n", + ctx->output, text); +} + +static void +report_html_subtitle(ReportContext *ctx, gchar *text) +{ + ctx->output = g_strdup_printf("%s" \ + "<tr><td colspan=\"2\" class=\"stit" \ + "le\">%s</td></tr>\n", + ctx->output, text); +} + +static void +report_html_subsubtitle(ReportContext *ctx, gchar *text) +{ + ctx->output = g_strdup_printf("%s" \ + "<tr><td colspan=\"2\" class=\"ssti" \ + "tle\">%s</td></tr>\n", + ctx->output, text); +} + +static void +report_html_key_value(ReportContext *ctx, gchar *key, gchar *value) +{ + ctx->output = g_strdup_printf("%s" \ + "<tr><td class=\"field\">%s</td>" \ + "<td class=\"value\">%s</td></tr>\n", + ctx->output, key, value); +} + +static void +report_text_header(ReportContext *ctx) +{ + if (ctx->output) + g_free(ctx->output); + + ctx->output = g_strdup(""); +} + +static void +report_text_footer(ReportContext *ctx) +{ +} + +static void +report_text_title(ReportContext *ctx, gchar *text) +{ + gchar *str = (gchar*)ctx->output; + int i = strlen(text); - gtk_tree_model_get(ctx->rd->model, iter, TREE_COL_DATA, &entry, -1); + str = g_strdup_printf("%s\n%s\n", str, text); + for (; i; i--) + str = g_strconcat(str, "*", NULL); + + str = g_strconcat(str, "\n\n", NULL); + ctx->output = str; +} + +static void +report_text_subtitle(ReportContext *ctx, gchar *text) +{ + gchar *str = ctx->output; + int i = strlen(text); - ctx->entry = entry; + str = g_strdup_printf("%s\n%s\n", str, text); + for (; i; i--) + str = g_strconcat(str, "-", NULL); + + str = g_strconcat(str, "\n\n", NULL); + ctx->output = str; +} - report_html_subtitle(ctx, entry->name); - report_html_table(ctx, entry->func(entry->number)); +static void +report_text_subsubtitle(ReportContext *ctx, gchar *text) +{ + ctx->output = g_strdup_printf("%s-%s-\n", ctx->output, text); } static void -report_generate_children(ReportContext *ctx, GtkTreeIter *iter) +report_text_key_value(ReportContext *ctx, gchar *key, gchar *value) { - GtkTreeModel *model = ctx->rd->model; - gchar *name; + if (strlen(value)) + ctx->output = g_strdup_printf("%s%s\t\t: %s\n", ctx->output, key, value); + else + ctx->output = g_strdup_printf("%s%s\n", ctx->output, key); +} - gtk_tree_model_get(model, iter, TREE_COL_NAME, &name, -1); - report_html_title(ctx, name); +static GSList * +report_create_module_list_from_dialog(ReportDialog *rd) +{ + ShellModule *module; + GSList *modules = NULL; + GtkTreeModel *model = rd->model; + GtkTreeIter iter; - if (gtk_tree_model_iter_has_child(model, iter)) { - gint children = gtk_tree_model_iter_n_children(model, iter); - gint i; + gtk_tree_model_get_iter_first(model, &iter); + do { + gboolean selected; + gchar *name; - for (i = 0; i < children; i++) { - GtkTreeIter child; + gtk_tree_model_get(model, &iter, TREE_COL_SEL, &selected, -1); + if (!selected) + continue; - gtk_tree_model_iter_nth_child(model, &child, iter, i); - report_generate_child(ctx, &child); + module = g_new0(ShellModule, 1); + + gtk_tree_model_get(model, &iter, TREE_COL_NAME, &name, -1); + module->name = name; + module->entries = NULL; + + if (gtk_tree_model_iter_has_child(model, &iter)) { + ShellModuleEntry *entry; + + gint children = gtk_tree_model_iter_n_children(model, &iter); + gint i; + + for (i = 0; i < children; i++) { + GtkTreeIter child; + + gtk_tree_model_iter_nth_child(model, &child, &iter, i); + + gtk_tree_model_get(model, &child, TREE_COL_SEL, &selected, -1); + if (!selected) + continue; + + gtk_tree_model_get(model, &child, TREE_COL_DATA, &entry, -1); + module->entries = g_slist_append(module->entries, entry); + } } + + modules = g_slist_append(modules, module); + } while (gtk_tree_model_iter_next(rd->model, &iter)); + + return modules; +} + +static void +report_create_inner_from_module_list(ReportContext *ctx, GSList *modules) +{ + for (; modules; modules = modules->next) { + ShellModule *module = (ShellModule *) modules->data; + GSList *entries; + + if (!params.gui_running) + fprintf(stderr, "\033[40;32m%s\033[0m\n", module->name); + + report_title(ctx, module->name); + + for (entries = module->entries; entries; entries = entries->next) { + ShellModuleEntry *entry = (ShellModuleEntry *) entries->data; + + if (!params.gui_running) + fprintf(stderr, "\033[2K\033[40;32;1m %s\033[0m\n", entry->name); + + ctx->entry = entry; + report_subtitle(ctx, entry->name); + module_entry_scan(entry); + report_table(ctx, module_entry_function(entry)); + } + } +} + +void report_module_list_free(GSList *modules) +{ + GSList *m; + + for (m = modules; m; m = m->next) { + ShellModule *module = (ShellModule *) m->data; + + g_slist_free(module->entries); } + + g_slist_free(modules); } static gchar * @@ -196,55 +377,151 @@ report_get_filename(void) GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); -#if GTK_CHECK_VERSION(2,8,0) - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), - TRUE); -#endif - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), - "hardinfo report.html"); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "hardinfo report"); + + file_chooser_add_filters(dialog, file_types); + file_chooser_open_expander(dialog); if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - } - + gchar *ext = file_chooser_get_extension(dialog, file_types); + filename = file_chooser_build_filename(dialog, ext); + } gtk_widget_destroy (dialog); return filename; } +ReportContext* +report_context_html_new() +{ + ReportContext *ctx; + + ctx = g_new0(ReportContext, 1); + ctx->header = report_html_header; + ctx->footer = report_html_footer; + ctx->title = report_html_title; + ctx->subtitle = report_html_subtitle; + ctx->subsubtitle = report_html_subsubtitle; + ctx->keyvalue = report_html_key_value; + + ctx->output = g_strdup(""); + ctx->format = REPORT_FORMAT_HTML; + + return ctx; +} + +ReportContext* +report_context_text_new() +{ + ReportContext *ctx; + + ctx = g_new0(ReportContext, 1); + ctx->header = report_text_header; + ctx->footer = report_text_footer; + ctx->title = report_text_title; + ctx->subtitle = report_text_subtitle; + ctx->subsubtitle = report_text_subsubtitle; + ctx->keyvalue = report_text_key_value; + + ctx->output = g_strdup(""); + ctx->format = REPORT_FORMAT_TEXT; + + return ctx; +} + +void +report_context_free(ReportContext *ctx) +{ + g_free(ctx->output); + g_free(ctx); +} + +void +report_create_from_module_list(ReportContext *ctx, GSList *modules) +{ + report_header(ctx); + + report_create_inner_from_module_list(ctx, modules); + report_module_list_free(modules); + + report_footer(ctx); +} + +gchar * +report_create_from_module_list_format(GSList *modules, ReportFormat format) +{ + ReportContext *(*create_context)(); + ReportContext *ctx; + gchar *retval; + + if (format >= N_REPORT_FORMAT) + return NULL; + + create_context = file_types[format].data; + if (!create_context) + return NULL; + + ctx = create_context(); + + report_create_from_module_list(ctx, modules); + retval = g_strdup(ctx->output); + + report_context_free(ctx); + + return retval; +} + static gboolean report_generate(ReportDialog *rd) { - GtkTreeIter iter; - GtkTreeModel *model; + GSList *modules; ReportContext *ctx; + ReportContext *(*create_context)(); gchar *file; FILE *stream; - file = report_get_filename(); - if (!file) + if (!(file = report_get_filename())) return FALSE; - stream = fopen(file, "w+"); - if (!stream) + + if (!(stream = fopen(file, "w+"))) { + g_free(file); return FALSE; + } + + create_context = file_types_get_data_by_name(file_types, file); - model = rd->model; - ctx = g_new0(ReportContext, 1); - ctx->rd = rd; - ctx->stream = stream; + if (!create_context) { + g_warning("Cannot create ReportContext. Programming bug?"); + g_free(file); + return FALSE; + } - report_html_header(ctx); + ctx = create_context(); + modules = report_create_module_list_from_dialog(rd); - gtk_tree_model_get_iter_first(model, &iter); + report_create_from_module_list(ctx, modules); + fputs(ctx->output, stream); + fclose(stream); - do { - report_generate_children(ctx, &iter); - } while (gtk_tree_model_iter_next(model, &iter)); - - report_html_footer(ctx); + if (ctx->format == REPORT_FORMAT_HTML) { + GtkWidget *dialog; + dialog = gtk_message_dialog_new(NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + "Open the report with your web browser?"); + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + GTK_STOCK_NO, GTK_RESPONSE_REJECT, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + open_url(file); + + gtk_widget_destroy(dialog); + } - fclose(ctx->stream); - g_free(ctx); + report_context_free(ctx); + g_free(file); return TRUE; } @@ -353,10 +630,11 @@ static ReportDialog GtkWidget *button8; GtkWidget *button7; GtkWidget *label; + GtkWidget *hbox; GtkTreeViewColumn *column; GtkCellRenderer *cr_text, *cr_pbuf, *cr_toggle; - + rd = g_new0(ReportDialog, 1); dialog = gtk_dialog_new(); @@ -373,14 +651,21 @@ static ReportDialog gtk_container_set_border_width(GTK_CONTAINER(dialog1_vbox), 4); gtk_widget_show(dialog1_vbox); + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(dialog1_vbox), hbox, FALSE, FALSE, 0); + label = gtk_label_new("<big><b>Generate Report</b></big>\n" \ "Please choose the information that you wish " \ "to view in your report:"); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_label_set_use_markup(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(dialog1_vbox), label, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(hbox), + icon_cache_get_image("report-large.png"), + FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0); + gtk_widget_show_all(hbox); scrolledwindow2 = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow2); @@ -439,7 +724,6 @@ static ReportDialog gtk_button_box_set_layout(GTK_BUTTON_BOX(dialog1_action_area), GTK_BUTTONBOX_END); - button8 = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_widget_show(button8); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button8, |