Add unfinished construct of error memory viewer

This commit is contained in:
Mario Hüttel 2020-11-19 22:36:54 +01:00
parent 37bc397e9a
commit 67d59928c9
8 changed files with 367 additions and 0 deletions

3
error-mem-viewer/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.ui~
*.user
*.user*

View File

@ -0,0 +1,26 @@
project(error-mem-viewer)
cmake_minimum_required(VERSION 2.8)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(GTK_MOD REQUIRED gmodule-2.0)
aux_source_directory("src" SRCES)
include_directories("include" ${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${GTK_MOD_INCLUDE_DIRS})
add_subdirectory(resources)
set(SOURCE_GENERATED
${CMAKE_CURRENT_BINARY_DIR}/resources/resources.c
)
SET_SOURCE_FILES_PROPERTIES(${SOURCE_GENERATED} PROPERTIES GENERATED 1)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${GTK_MOD_LINK_DIRS})
add_definitions(${GLIB2_CFLAGS_OTHER} ${GTK_MOD_CFLAGS_OTHER})
add_executable(${PROJECT_NAME} ${SRCES} ${SOURCE_GENERATED})
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${GTK_MOD_LDFLAGS})
add_dependencies(${PROJECT_NAME} glib-resources)

View File

@ -0,0 +1,15 @@
#ifndef _ERR_MEM_VIEWER_ADDRESS_CELL_RENDERER_H_
#define _ERR_MEM_VIEWER_ADDRESS_CELL_RENDERER_H_
#include <gtk/gtk.h>
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(ErrMemViewAddressCellRenderer, err_mem_view_address_cell_renderer, ERR_MEM_VIEW, ADDRESS_CELL_RENDERER, GtkCellRendererText)
#define ERR_MEM_VIEW_TYPE_ADDRESS_CELL_RENDERER (err_mem_view_address_cell_renderer_get_type())
GtkCellRenderer *err_mem_view_address_cell_renderer_new();
G_END_DECLS
#endif /* _ERR_MEM_VIEWER_ADDRESS_CELL_RENDERER_H_ */

View File

@ -0,0 +1,9 @@
add_custom_target(glib-resources DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/resources.c")
add_custom_command(DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/*.ui"
"${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/resources.c"
COMMAND
glib-compile-resources --target="${CMAKE_CURRENT_BINARY_DIR}/resources.c" --sourcedir="${CMAKE_CURRENT_SOURCE_DIR}" --generate-source "${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
)

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.1 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="main-window">
<property name="name">main-window</property>
<property name="can-focus">False</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="error-mem-tree-view">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="header-bar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="title" translatable="yes">Error Memory Viewer</property>
<property name="subtitle" translatable="yes">Reflow Controller Error Memory Viewer</property>
<property name="show-close-button">True</property>
<child>
<object class="GtkButton" id="open-button">
<property name="label">gtk-open</property>
<property name="name">open-button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="open_button_clicked_cb" swapped="no"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/gui">
<file compressed="true" alias="main">main-window.ui</file>
</gresource>
</gresources>

View File

@ -0,0 +1,81 @@
#include <error-mem-viewer/err-mem-viewer-address-cell-renderer.h>
#include <string.h>
struct _ErrMemViewAddressCellRenderer {
GtkCellRendererText base;
};
enum {
PROP_HEXNUM = 1,
PROP_COUNT
};
G_DEFINE_TYPE(ErrMemViewAddressCellRenderer, err_mem_view_address_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
static void err_mem_view_address_cell_renderer_init(ErrMemViewAddressCellRenderer *self)
{
(void)self;
}
static void convert_gvalue_uint_to_string(const GValue *in, GValue *out)
{
uint32_t val;
char text[32];
if (!in || !out)
return;
g_value_init(out, G_TYPE_STRING);
val = g_value_get_uint(in);
snprintf(text, sizeof(text), "0x%08x", val);
g_value_set_string(out, text);
}
static void err_mem_view_address_cell_renderer_set_property(GObject *obj, guint param_id, const GValue *value, GParamSpec *pspec)
{
GValue val = G_VALUE_INIT;
switch (param_id) {
case PROP_HEXNUM:
convert_gvalue_uint_to_string(value, &val);
g_object_set_property(obj, "text", &val);
g_value_unset(&val);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
}
}
static void err_mem_view_address_cell_renderer_get_property(GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
(void)value;
switch (param_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
}
}
static GParamSpec *properties[PROP_COUNT];
void err_mem_view_address_cell_renderer_class_init(ErrMemViewAddressCellRendererClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->set_property = err_mem_view_address_cell_renderer_set_property;
oclass->get_property = err_mem_view_address_cell_renderer_get_property;
properties[PROP_HEXNUM] = g_param_spec_uint("hex-num", "hex-num", "Hex number to display", 0U, UINT_MAX, 0U, G_PARAM_WRITABLE);
g_object_class_install_properties(oclass, PROP_COUNT, properties);
}
GtkCellRenderer *err_mem_view_address_cell_renderer_new()
{
return GTK_CELL_RENDERER(g_object_new(ERR_MEM_VIEW_TYPE_ADDRESS_CELL_RENDERER, NULL));
}

178
error-mem-viewer/src/main.c Normal file
View File

@ -0,0 +1,178 @@
#include <gtk/gtk.h>
#include <glib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <error-mem-viewer/err-mem-viewer-address-cell-renderer.h>
enum memory_view_columns {
MEM_VIEW_COL_ADDRESS = 0,
MEM_VIEW_COL_DATA,
MEM_VIEW_COL_INTERPRETATION,
MEM_VIEW_COLUMN_COUNT
};
struct application_data {
GtkWidget *borrowed_main_window;
GtkTreeView *borrowed_tree_view;
GtkHeaderBar *borrowed_header_bar;
const char *error_memory_data;
size_t file_size;
};
static void tree_view_show_error_memory(GtkTreeView *tree_view, const char *memory, size_t len)
{
GtkListStore *store;
GtkTreeIter _iter;
GtkTreeIter *iter = &_iter;
store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view));
if (store) {
for (unsigned int i = 0; i < 0xFFFF; i+=4) {
gtk_list_store_append(store, iter);
gtk_list_store_set(store, iter, MEM_VIEW_COL_ADDRESS, i, MEM_VIEW_COL_INTERPRETATION, "Test", MEM_VIEW_COL_DATA, i % 12, -1);
}
}
}
void setup_tree_view(GtkTreeView *tree_view)
{
GtkListStore *list_store;
GtkCellRenderer *string_renderer;
GtkCellRenderer *hex_renderer;
GtkTreeViewColumn *column;
g_return_if_fail(GTK_IS_TREE_VIEW(tree_view));
list_store = gtk_list_store_new(MEM_VIEW_COLUMN_COUNT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(list_store));
string_renderer = gtk_cell_renderer_text_new();
hex_renderer = err_mem_view_address_cell_renderer_new();
column = gtk_tree_view_column_new_with_attributes("Address", hex_renderer, "hex-num", MEM_VIEW_COL_ADDRESS, NULL);
gtk_tree_view_append_column(tree_view, column);
column = gtk_tree_view_column_new_with_attributes("Data", hex_renderer, "hex-num", MEM_VIEW_COL_DATA, NULL);
gtk_tree_view_append_column(tree_view, column);
column = gtk_tree_view_column_new_with_attributes("Interpretation", string_renderer, "text", MEM_VIEW_COL_INTERPRETATION, NULL);
gtk_tree_view_append_column(tree_view, column);
}
static int64_t get_file_size(int file)
{
off_t size;
if (!file)
return -1L;
size = lseek(file, 0, SEEK_END);
if (size == (off_t)-1)
return -1;
return (int64_t)size;
}
static const char *map_file_to_memory(const char *name, size_t *detected_size)
{
const char *ret = NULL;
int file;
int64_t file_size;
file = open(name, O_RDONLY);
if (file < 0)
goto exit;
file_size = get_file_size(file);
if (file_size < 0)
goto exit;
if (detected_size)
*detected_size = (size_t)file_size;
ret = (const char *)mmap(NULL, (size_t)file_size, PROT_READ, MAP_SHARED, file, (off_t)0L);
exit:
return ret;
}
G_MODULE_EXPORT
void open_button_clicked_cb(GtkButton *button, gpointer *user_data)
{
struct application_data *data = (struct application_data *)user_data;
(void)button;
GtkDialog *dialog;
gint res;
gchar *filename;
dialog = GTK_DIALOG(gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(data->borrowed_main_window),
GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL,
"Open", GTK_RESPONSE_ACCEPT,
NULL));
res = gtk_dialog_run(dialog);
if (res == GTK_RESPONSE_ACCEPT) {
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
data->error_memory_data = map_file_to_memory(filename, &data->file_size);
if (!data->error_memory_data) {
g_warning("File could not be loaded");
g_free(filename);
goto ret_destroy_dialog;
}
gtk_header_bar_set_subtitle(data->borrowed_header_bar, filename);
g_free(filename);
}
tree_view_show_error_memory(data->borrowed_tree_view, data->error_memory_data, data->file_size);
ret_destroy_dialog:
gtk_widget_destroy(GTK_WIDGET(dialog));
}
static void app_activated(GApplication *app, gpointer user_data)
{
(void)user_data;
GtkBuilder *builder;
GtkWindow *main_window;
static struct application_data data;
builder = gtk_builder_new_from_resource("/gui/main");
main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window"));
data.borrowed_main_window = GTK_WIDGET(main_window);
data.error_memory_data = NULL;
data.borrowed_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "error-mem-tree-view"));
data.borrowed_header_bar = GTK_HEADER_BAR(gtk_builder_get_object(builder, "header-bar"));
setup_tree_view(data.borrowed_tree_view);
gtk_builder_connect_signals(builder, &data);
g_object_unref(builder);
gtk_application_add_window(GTK_APPLICATION(app), main_window);
gtk_widget_show(GTK_WIDGET(main_window));
}
static int start_gui(int argc, char **argv)
{
int ret = 0;
GtkApplication *g_app;
/* Create a new G application which will start a completely new process for each call to the program (NON_UNIQUE) instead
* of creating an additional window in the same process
*/
g_app = gtk_application_new("de.shimatta.reflow.error-mem-viewer", G_APPLICATION_NON_UNIQUE);
g_signal_connect(g_app, "activate", G_CALLBACK(app_activated), NULL);
ret = g_application_run(G_APPLICATION(g_app), argc, argv);
g_object_unref(g_app);
return ret;
}
int main(int argc, char **argv)
{
return start_gui(argc, argv);
}