diff --git a/include/views/main_window.h b/include/views/main_window.h index 8598c44..7aac1ee 100644 --- a/include/views/main_window.h +++ b/include/views/main_window.h @@ -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, diff --git a/include/widgets/investigation_graph_view.h b/include/widgets/investigation_graph_view.h index 8cd9d49..ae316e4 100644 --- a/include/widgets/investigation_graph_view.h +++ b/include/widgets/investigation_graph_view.h @@ -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, diff --git a/include/widgets/workspace.h b/include/widgets/workspace.h index 65c3810..c4721cc 100644 --- a/include/widgets/workspace.h +++ b/include/widgets/workspace.h @@ -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, diff --git a/src/core/application.c b/src/core/application.c index 5e92949..687e1ff 100644 --- a/src/core/application.c +++ b/src/core/application.c @@ -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( diff --git a/src/views/main_window.c b/src/views/main_window.c index 84d29f1..0ad80d5 100644 --- a/src/views/main_window.c +++ b/src/views/main_window.c @@ -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, diff --git a/src/widgets/investigation_graph_view.c b/src/widgets/investigation_graph_view.c index 5853552..6522ebd 100644 --- a/src/widgets/investigation_graph_view.c +++ b/src/widgets/investigation_graph_view.c @@ -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, diff --git a/src/widgets/workspace.c b/src/widgets/workspace.c index 8221ca6..35f0c92 100644 --- a/src/widgets/workspace.c +++ b/src/widgets/workspace.c @@ -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,