fix(graph): persist viewport while navigating

This commit is contained in:
grayTerminal-sh 2026-07-23 14:22:24 +02:00
parent 6b43379e75
commit ab6e04faea
7 changed files with 128 additions and 0 deletions

View file

@ -125,6 +125,7 @@ typedef void (*MainWindowGraphNodeMovedCallback)(
double y,
gpointer user_data
);
typedef void (*MainWindowGraphTransformChangedCallback)(gpointer user_data);
typedef void (*MainWindowExtractionDropCallback)(
const char *file_path,
@ -251,6 +252,10 @@ void main_window_set_graph_node_moved_callback(
MainWindowGraphNodeMovedCallback callback,
gpointer user_data
);
void main_window_set_graph_transform_changed_callback(
MainWindow *main_window,
MainWindowGraphTransformChangedCallback callback,
gpointer user_data);
void main_window_set_extraction_drop_callback(
MainWindow *main_window,

View file

@ -71,6 +71,10 @@ typedef void (*InvestigationGraphViewNodeMovedCallback)(
gpointer user_data
);
typedef void (*InvestigationGraphViewTransformChangedCallback)(
gpointer user_data
);
/** @brief Callback appelé lorsqu'une extraction est déposée sur le graphe. */
typedef void (*InvestigationGraphViewExtractionDropCallback)(
const char *file_path,
@ -177,6 +181,12 @@ void investigation_graph_view_set_node_moved_callback(
gpointer user_data
);
void investigation_graph_view_set_transform_changed_callback(
InvestigationGraphView *graph_view,
InvestigationGraphViewTransformChangedCallback callback,
gpointer user_data
);
void investigation_graph_view_set_extraction_drop_callback(
InvestigationGraphView *graph_view,
InvestigationGraphViewExtractionDropCallback callback,

View file

@ -55,6 +55,7 @@ typedef void (*WorkspaceGraphNodeMovedCallback)(
double y,
gpointer user_data
);
typedef void (*WorkspaceGraphTransformChangedCallback)(gpointer user_data);
typedef void (*WorkspaceExtractionDropCallback)(
const char *file_path,
@ -324,6 +325,10 @@ void workspace_set_graph_node_moved_callback(
WorkspaceGraphNodeMovedCallback callback,
gpointer user_data
);
void workspace_set_graph_transform_changed_callback(
Workspace *workspace,
WorkspaceGraphTransformChangedCallback callback,
gpointer user_data);
void workspace_set_extraction_drop_callback(
Workspace *workspace,

View file

@ -138,6 +138,7 @@ struct Application
InvestigationGraphLayout *graph_layout;
guint64 graph_load_generation;
gboolean graph_viewport_restored;
guint graph_viewport_save_source_id;
char *selected_evidence_identifier;
char *pending_relation_selection_identifier;
@ -278,6 +279,25 @@ static void application_save_graph_viewport(Application *application)
g_clear_error(&error);
}
static gboolean application_save_graph_viewport_timeout(gpointer user_data)
{
Application *application = user_data;
if (application == NULL) return G_SOURCE_REMOVE;
application->graph_viewport_save_source_id = 0U;
application_save_graph_viewport(application);
return G_SOURCE_REMOVE;
}
static void application_on_graph_transform_changed(gpointer user_data)
{
Application *application = user_data;
if (application == NULL) return;
if (application->graph_viewport_save_source_id != 0U)
g_source_remove(application->graph_viewport_save_source_id);
application->graph_viewport_save_source_id = g_timeout_add(
250U, application_save_graph_viewport_timeout, application);
}
static void application_restore_graph_viewport(Application *application)
{
GraphNodePositionDao *dao = NULL;
@ -2665,6 +2685,11 @@ static gboolean application_install_session(
application->tree_model
);
if (application->graph_viewport_save_source_id != 0U)
{
g_source_remove(application->graph_viewport_save_source_id);
application->graph_viewport_save_source_id = 0U;
}
application_save_graph_viewport(application);
investigation_session_close(
application->session
@ -7841,6 +7866,10 @@ static void application_on_activate(
application_on_graph_node_moved,
application
);
main_window_set_graph_transform_changed_callback(
application->main_window,
application_on_graph_transform_changed,
application);
main_window_set_extraction_drop_callback(
application->main_window, application_on_extraction_dropped,
application);
@ -8126,6 +8155,11 @@ void application_free(
application
);
if (application->graph_viewport_save_source_id != 0U)
{
g_source_remove(application->graph_viewport_save_source_id);
application->graph_viewport_save_source_id = 0U;
}
application_save_graph_viewport(application);
application_clear_graph(

View file

@ -125,6 +125,8 @@ struct MainWindow
gpointer
graph_node_moved_user_data;
MainWindowGraphTransformChangedCallback graph_transform_changed_callback;
gpointer graph_transform_changed_user_data;
MainWindowExtractionDropCallback extraction_drop_callback;
gpointer extraction_drop_user_data;
@ -514,6 +516,15 @@ static void main_window_on_graph_node_moved(
);
}
static void main_window_on_graph_transform_changed(gpointer user_data)
{
MainWindow *main_window = user_data;
if (main_window != NULL &&
main_window->graph_transform_changed_callback != NULL)
main_window->graph_transform_changed_callback(
main_window->graph_transform_changed_user_data);
}
static void main_window_on_extraction_dropped(const char *file_path,
const char *target_entity_identifier, gpointer user_data)
{
@ -978,6 +989,9 @@ MainWindow *main_window_new(
main_window_on_graph_node_moved,
main_window
);
workspace_set_graph_transform_changed_callback(
main_window->workspace, main_window_on_graph_transform_changed,
main_window);
workspace_set_extraction_drop_callback(main_window->workspace,
main_window_on_extraction_dropped, main_window);
@ -1803,6 +1817,16 @@ void main_window_set_graph_node_moved_callback(
user_data;
}
void main_window_set_graph_transform_changed_callback(
MainWindow *main_window,
MainWindowGraphTransformChangedCallback callback,
gpointer user_data)
{
if (main_window == NULL) return;
main_window->graph_transform_changed_callback = callback;
main_window->graph_transform_changed_user_data = user_data;
}
void main_window_set_extraction_drop_callback(
MainWindow *main_window,
MainWindowExtractionDropCallback callback,
@ -2070,6 +2094,8 @@ void main_window_free(
NULL,
NULL
);
workspace_set_graph_transform_changed_callback(
main_window->workspace, NULL, NULL);
workspace_set_reset_graph_layout_callback(
main_window->workspace,

View file

@ -121,6 +121,8 @@ struct InvestigationGraphView
InvestigationGraphViewNodeMovedCallback node_moved_callback;
gpointer node_moved_user_data;
InvestigationGraphViewTransformChangedCallback transform_changed_callback;
gpointer transform_changed_user_data;
InvestigationGraphViewExtractionDropCallback extraction_drop_callback;
gpointer extraction_drop_user_data;
@ -317,6 +319,10 @@ static void investigation_graph_view_zoom_at_point(
gtk_widget_queue_draw(
graph_view->drawing_area
);
if (graph_view->transform_changed_callback != NULL)
graph_view->transform_changed_callback(
graph_view->transform_changed_user_data);
}
/**
@ -513,6 +519,10 @@ static void investigation_graph_view_on_scale_changed(
gtk_widget_queue_draw(
graph_view->drawing_area
);
if (graph_view->transform_changed_callback != NULL)
graph_view->transform_changed_callback(
graph_view->transform_changed_user_data);
}
/**
@ -1201,6 +1211,10 @@ static void investigation_graph_view_on_drag_update(
graph_view->drag_origin_offset_y +
offset_y;
if (graph_view->transform_changed_callback != NULL)
graph_view->transform_changed_callback(
graph_view->transform_changed_user_data);
gtk_widget_queue_draw(
graph_view->drawing_area
);
@ -4462,6 +4476,16 @@ void investigation_graph_view_set_node_moved_callback(
user_data;
}
void investigation_graph_view_set_transform_changed_callback(
InvestigationGraphView *graph_view,
InvestigationGraphViewTransformChangedCallback callback,
gpointer user_data)
{
if (graph_view == NULL) return;
graph_view->transform_changed_callback = callback;
graph_view->transform_changed_user_data = user_data;
}
void investigation_graph_view_set_extraction_drop_callback(
InvestigationGraphView *graph_view,
InvestigationGraphViewExtractionDropCallback callback,

View file

@ -128,6 +128,8 @@ struct Workspace
gpointer
graph_node_moved_user_data;
WorkspaceGraphTransformChangedCallback graph_transform_changed_callback;
gpointer graph_transform_changed_user_data;
WorkspaceExtractionDropCallback extraction_drop_callback;
gpointer extraction_drop_user_data;
@ -749,6 +751,14 @@ static void workspace_on_graph_node_moved(
);
}
static void workspace_on_graph_transform_changed(gpointer user_data)
{
Workspace *workspace = user_data;
if (workspace != NULL && workspace->graph_transform_changed_callback != NULL)
workspace->graph_transform_changed_callback(
workspace->graph_transform_changed_user_data);
}
/**
* @brief Transmet la sélection du graphe au volet de détails.
*/
@ -1966,6 +1976,8 @@ Workspace *workspace_new(void)
workspace_on_graph_node_moved,
workspace
);
investigation_graph_view_set_transform_changed_callback(
workspace->graph_view, workspace_on_graph_transform_changed, workspace);
investigation_graph_view_set_extraction_drop_callback(
workspace->graph_view, workspace_on_extraction_dropped, workspace);
@ -3473,6 +3485,16 @@ void workspace_set_graph_node_moved_callback(
user_data;
}
void workspace_set_graph_transform_changed_callback(
Workspace *workspace,
WorkspaceGraphTransformChangedCallback callback,
gpointer user_data)
{
if (workspace == NULL) return;
workspace->graph_transform_changed_callback = callback;
workspace->graph_transform_changed_user_data = user_data;
}
void workspace_set_extraction_drop_callback(
Workspace *workspace,
WorkspaceExtractionDropCallback callback,
@ -3680,6 +3702,8 @@ void workspace_free(Workspace *workspace)
NULL,
NULL
);
investigation_graph_view_set_transform_changed_callback(
workspace->graph_view, NULL, NULL);
entity_details_panel_set_close_callback(
workspace->entity_details_panel,