/
githubmirror
/
libreport
Обзор
Документация
Войти
/
githubmirror
/
libreport
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/gtk-helpers/problem_details_widget.c
373 строки
12 KB
Matěj Grabovský
Purge commented-out code
13 авг 2020, 13:02
13 авг 2020, 13:02
ab28fd5
Код
Авторство
О чём код?
/* Copyright (C) 2014 ABRT Team Copyright (C) 2014 RedHat inc. 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "problem_details_widget.h" #include "internal_libreport_gtk.h" #include "internal_libreport.h" #define EXPLICIT_ITEMS \ CD_DUMPDIR, \ FILENAME_TIME, \ FILENAME_LAST_OCCURRENCE, \ FILENAME_UID, \ FILENAME_USERNAME, \ FILENAME_TYPE, \ FILENAME_COMMENT, \ FILENAME_ANALYZER #define ORDERED_ITEMS \ FILENAME_EXPLOITABLE, \ FILENAME_NOT_REPORTABLE, \ FILENAME_REASON, \ FILENAME_BACKTRACE, \ FILENAME_CRASH_FUNCTION, \ FILENAME_CMDLINE, \ FILENAME_EXECUTABLE, \ FILENAME_PACKAGE, \ FILENAME_COMPONENT, \ FILENAME_PID, \ FILENAME_PWD, \ FILENAME_HOSTNAME, \ FILENAME_COUNT static GtkCssProvider *g_provider = NULL; static const char *items_orderlist[] = { ORDERED_ITEMS, NULL, }; static const char *items_auto_blacklist[] = { EXPLICIT_ITEMS, ORDERED_ITEMS, FILENAME_PKG_NAME, FILENAME_PKG_VERSION, FILENAME_PKG_RELEASE, FILENAME_PKG_ARCH, FILENAME_PKG_EPOCH, NULL, }; struct ProblemDetailsWidgetPrivate { gulong rows; problem_data_t *problem_data; }; G_DEFINE_TYPE_WITH_PRIVATE(ProblemDetailsWidget, problem_details_widget, GTK_TYPE_GRID) static void problem_details_widget_finalize(GObject *object); static void load_css_style() { g_provider = gtk_css_provider_new(); gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(g_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); const gchar *data = "#value {font-family: monospace;}"; gtk_css_provider_load_from_data(g_provider, data, -1, NULL); g_object_unref (g_provider); } static void problem_details_widget_class_init(ProblemDetailsWidgetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = problem_details_widget_finalize; } static void problem_details_widget_finalize(GObject *object) { ProblemDetailsWidget *self; self = PROBLEM_DETAILS_WIDGET(object); self->priv->problem_data = (void *)0xdeadbeaf; G_OBJECT_CLASS(problem_details_widget_parent_class)->finalize(object); } static gulong problem_details_widget_append_row(ProblemDetailsWidget *self) { gtk_grid_insert_row(GTK_GRID(self), self->priv->rows); return self->priv->rows++; } static void problem_details_widget_add_single_line(ProblemDetailsWidget *self, const char *name, const char *content) { if (g_provider == NULL) load_css_style(); GtkWidget *label = gtk_label_new(name); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_START); GtkWidget *value = gtk_label_new(content); gtk_label_set_selectable(GTK_LABEL(value), TRUE); gtk_label_set_line_wrap(GTK_LABEL(value), TRUE); gtk_label_set_line_wrap_mode(GTK_LABEL(value), GTK_WRAP_WORD); gtk_widget_set_halign(value, GTK_ALIGN_START); gtk_widget_set_hexpand(value, TRUE); gtk_widget_set_name(GTK_WIDGET(value), "value"); gtk_widget_set_margin_start(label, 20); gtk_widget_set_margin_end(label, 20); gtk_widget_set_margin_start(value, 5); const gulong row = problem_details_widget_append_row(self); gtk_grid_attach(GTK_GRID(self), label, 0, row, 1, 1); gtk_grid_attach(GTK_GRID(self), value, 1, row, 1, 1); } static void problem_details_widget_add_multi_line(ProblemDetailsWidget *self, const char *name, const char *content) { if (g_provider == NULL) load_css_style(); GtkWidget *value = gtk_label_new(content); gtk_widget_set_halign(value, GTK_ALIGN_START); if (strcmp(name, FILENAME_COMMENT) == 0 || strcmp(name, FILENAME_REASON) == 0) { gtk_label_set_line_wrap(GTK_LABEL(value), TRUE); gtk_label_set_line_wrap_mode(GTK_LABEL(value), GTK_WRAP_WORD); gtk_widget_set_margin_bottom(value, 12); } gtk_label_set_selectable(GTK_LABEL(value), TRUE); gtk_widget_set_name(GTK_WIDGET(value), "value"); GtkWidget *expander = gtk_expander_new(name); gtk_widget_set_hexpand(expander, TRUE); gtk_container_add(GTK_CONTAINER(expander), value); const gulong row = problem_details_widget_append_row(self); gtk_grid_attach(GTK_GRID(self), expander, 0, row, 2, 1); } static void problem_details_widget_add_binary(ProblemDetailsWidget *self, const char *label, const char *path) { struct stat statbuf; statbuf.st_size = 0; if (stat(path, &statbuf) != 0) { log_warning("File '%s' does not exist", path); return; } g_autofree gchar *size = g_format_size_full((long long)statbuf.st_size, G_FORMAT_SIZE_IEC_UNITS); g_autofree char *msg = g_strdup_printf(_("$DATA_DIRECTORY/%s (binary file, %s)"), label, size); problem_details_widget_add_single_line(self, label, msg); } static void problem_details_widget_add_time_stamp(ProblemDetailsWidget *self, const char *label, const char *stamp) { struct tm tm; memset(&tm, 0, sizeof(struct tm)); const char *ret = strptime(stamp, "%s", &tm); if (ret == NULL || ret[0] != '\0') return; char buf[255]; strftime(buf, sizeof(buf), "%F %T", &tm); problem_details_widget_add_single_line(self, label, buf); } static void problem_details_widget_add_problem_item(ProblemDetailsWidget *self, const char *name, problem_item *item) { if (item->flags & CD_FLAG_TXT) { if (strchr(item->content, '\n') == NULL) problem_details_widget_add_single_line(self, name, item->content); else problem_details_widget_add_multi_line(self, name, item->content); } else if (item->flags & CD_FLAG_BIN) problem_details_widget_add_binary(self, name, item->content); else log_warning("Unsupported file type"); } /* Callback for GHashTable */ static void problem_data_entry_to_grid_row_one_line(const char *item_name, problem_item *item, ProblemDetailsWidget *self) { if (((item->flags & CD_FLAG_TXT) && (strchr(item->content, '\n') == NULL)) && !libreport_is_in_string_list(item_name, items_auto_blacklist)) problem_details_widget_add_single_line(self, item_name, item->content); } static void problem_data_entry_to_grid_row_multi_line(const char *item_name, problem_item *item, ProblemDetailsWidget *self) { if (((item->flags & CD_FLAG_TXT) && (strchr(item->content, '\n') != NULL)) && !libreport_is_in_string_list(item_name, items_auto_blacklist)) problem_details_widget_add_multi_line(self, item_name, item->content); } static void problem_data_entry_to_grid_row_binary(const char *item_name, problem_item *item, ProblemDetailsWidget *self) { if ((item->flags & CD_FLAG_BIN) && !libreport_is_in_string_list(item_name, items_auto_blacklist)) problem_details_widget_add_binary(self, item_name, item->content); } static void problem_details_widget_populate(ProblemDetailsWidget *self) { { /* Explicit order */ for (const char **iter = items_orderlist; *iter; ++iter) { struct problem_item *item = problem_data_get_item_or_NULL( self->priv->problem_data, *iter); if (item == NULL) continue; problem_details_widget_add_problem_item(self, *iter, item); } } { /* comment: */ const char *dd = problem_data_get_content_or_NULL( self->priv->problem_data, FILENAME_COMMENT); if (dd) problem_details_widget_add_multi_line(self, FILENAME_COMMENT, dd); } { /* First occurence: 2014-08-26 11:08 */ const char *ts = problem_data_get_content_or_NULL( self->priv->problem_data, FILENAME_TIME); if (ts) problem_details_widget_add_time_stamp(self, "first_occurence", ts); } { /* Last occurence: 2014-08-27 11:08 */ const char *ts = problem_data_get_content_or_NULL( self->priv->problem_data, FILENAME_LAST_OCCURRENCE); if (ts) problem_details_widget_add_time_stamp(self, "last_occurence", ts); } { /* User: login(UID) */ const char *uid = problem_data_get_content_or_NULL( self->priv->problem_data, FILENAME_UID); const char *username = problem_data_get_content_or_NULL( self->priv->problem_data, "username"); g_autofree char *line = NULL; if (uid && username) line = g_strdup_printf("%s (%s)", username, uid); else if (!uid && !username) line = g_strdup("unknown user"); else line = g_strdup_printf("%s", uid ? uid : username); problem_details_widget_add_single_line(self, "user", line); } { /* Type/Analyzer: CCpp */ const char *type = problem_data_get_content_or_NULL( self->priv->problem_data, FILENAME_TYPE); const char *analyzer = problem_data_get_content_or_NULL( self->priv->problem_data, FILENAME_ANALYZER); g_autofree char *label = NULL; g_autofree char *line = NULL; if (type != NULL && analyzer != NULL) { if (strcmp(type, analyzer) != 0) { label = g_strdup("type/analyzer"); line = g_strdup_printf("%s/%s", type, analyzer); } else { label = g_strdup("type"); line = g_strdup(type); } } else { label = g_strdup(type ? "type" : "anlyzer"); line = g_strdup(type ? type : analyzer); } problem_details_widget_add_single_line(self, label, line); } g_hash_table_foreach(self->priv->problem_data, (GHFunc)problem_data_entry_to_grid_row_one_line, self); { /* data directory: */ const char *dd = problem_data_get_content_or_NULL( self->priv->problem_data, CD_DUMPDIR); if (dd) problem_details_widget_add_single_line(self, "data_directory", dd); /* show binaries below the data_directory entry */ g_hash_table_foreach(self->priv->problem_data, (GHFunc)problem_data_entry_to_grid_row_binary, self); } g_hash_table_foreach(self->priv->problem_data, (GHFunc)problem_data_entry_to_grid_row_multi_line, self); } static void problem_details_widget_init(ProblemDetailsWidget *self) { self->priv = problem_details_widget_get_instance_private(self); self->priv->rows = 0; self->priv->problem_data = NULL; } ProblemDetailsWidget * problem_details_widget_new(problem_data_t *problem) { INITIALIZE_LIBREPORT(); GObject *object = g_object_new(TYPE_PROBLEM_DETAILS_WIDGET, NULL); ProblemDetailsWidget *self = PROBLEM_DETAILS_WIDGET(object); self->priv->problem_data = problem; problem_details_widget_populate(self); gtk_widget_show_all(GTK_WIDGET(self)); return self; }