diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | src/crystfel_gui.c | 456 | ||||
-rw-r--r-- | src/gui_import.c | 505 | ||||
-rw-r--r-- | src/gui_import.h | 38 |
5 files changed, 547 insertions, 455 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a698bfb1..7f6d8a72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,7 +397,7 @@ if (GTK_FOUND) src/gui_peaksearch.c src/gui_index.c src/gui_merge.c src/gui_backend_local.c src/gui_project.c src/crystfelindexingopts.c src/crystfelmergeopts.c src/crystfelsymmetryselector.c src/gtk-util-routines.c src/gui_fom.c - src/gui_export.c src/gui_ambi.c) + src/gui_export.c src/gui_ambi.c src/gui_import.c) if (HAVE_SLURM) set(CRYSTFEL_GUI_SOURCES ${CRYSTFEL_GUI_SOURCES} src/gui_backend_slurm.c) diff --git a/meson.build b/meson.build index ed68aa03..da524d0c 100644 --- a/meson.build +++ b/meson.build @@ -223,6 +223,7 @@ if gtkdep.found() 'src/crystfelmergeopts.c', 'src/crystfelsymmetryselector.c', 'src/gtk-util-routines.c', + 'src/gui_import.c', 'src/gui_peaksearch.c', 'src/gui_index.c', 'src/gui_merge.c', diff --git a/src/crystfel_gui.c b/src/crystfel_gui.c index 3034db19..e29548bd 100644 --- a/src/crystfel_gui.c +++ b/src/crystfel_gui.c @@ -49,6 +49,7 @@ #include "crystfelimageview.h" #include "crystfelimageview.h" #include "crystfel_gui.h" +#include "gui_import.h" #include "gui_peaksearch.h" #include "gui_index.h" #include "gui_merge.h" @@ -249,459 +250,6 @@ void update_imageview(struct crystfelproject *proj) } -static void add_all_events(struct crystfelproject *proj, - const char *filename, - const DataTemplate *dtempl) -{ - char **events; - int i; - int n_events; - - events = image_expand_frames(dtempl, filename, &n_events); - if ( events == NULL ) { - ERROR("Couldn't expand event list\n"); - return; - } - - for ( i=0; i<n_events; i++ ) { - add_file_to_project(proj, filename, events[i]); - free(events[i]); - } - free(events); -} - - -static void add_files(struct crystfelproject *proj, GFile *folder, - enum match_type_id type, - const DataTemplate *dtempl) -{ - GFileEnumerator *fenum; - GFileInfo *finfo; - GError *error = NULL; - - fenum = g_file_enumerate_children(folder, "standard::name,standard::type", - G_FILE_QUERY_INFO_NONE, - NULL, &error); - - do { - - GFile *file; - - finfo = g_file_enumerator_next_file(fenum, NULL, &error); - - if ( error != NULL ) { - STATUS("Error!\n"); - g_object_unref(fenum); - return; - } - - if ( finfo == NULL ) continue; - - file = g_file_get_child(folder, g_file_info_get_name(finfo)); - - if ( g_file_info_get_file_type(finfo) == G_FILE_TYPE_DIRECTORY ) { - - add_files(proj, file, type, dtempl); - - } else { - - char *bn = g_file_get_basename(file); - if ( match_filename(bn, type) ) { - add_all_events(proj, g_file_get_path(file), - dtempl); - } - - } - - g_object_unref(finfo); - - } while ( finfo != NULL ); - - g_object_unref(fenum); -} - - -static void add_frames_from_stream(Stream *st, - DataTemplate *dtempl, - struct crystfelproject *proj) -{ - do { - struct image *image; - image = stream_read_chunk(st, 0); - if ( image == NULL ) break; - add_file_to_project(proj, image->filename, image->ev); - image_free(image); - - } while ( 1 ); -} - - -struct finddata_ctx -{ - struct crystfelproject *proj; - GtkWidget *geom_file; - - /* "Select individual file" */ - GtkWidget *indiv; - GtkWidget *indiv_chooser; - - /* Read list of files */ - GtkWidget *list; /* "Import list" radio */ - GtkWidget *list_chooser; - - /* Search for files */ - GtkWidget *search; - GtkWidget *search_chooser; - GtkWidget *search_pattern; - - /* Load stream */ - GtkWidget *stream; - GtkWidget *stream_chooser; - - GtkWidget *dump; -}; - -enum import_mode -{ - IMPORT_FILES, - IMPORT_LIST, - IMPORT_SEARCH, - IMPORT_STREAM -}; - - -static enum import_mode import_mode(struct finddata_ctx *ctx) -{ - if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->indiv))) { - return IMPORT_FILES; - } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->list))) { - return IMPORT_LIST; - } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->search))) { - return IMPORT_SEARCH; - } else { - return IMPORT_STREAM; - } -} - - -static void finddata_typetoggle_sig(GtkWidget *radio, - struct finddata_ctx *ctx) -{ - gtk_widget_set_sensitive(ctx->indiv_chooser, FALSE); - gtk_widget_set_sensitive(ctx->list_chooser, FALSE); - gtk_widget_set_sensitive(ctx->search_chooser, FALSE); - gtk_widget_set_sensitive(ctx->search_pattern, FALSE); - gtk_widget_set_sensitive(ctx->stream_chooser, FALSE); - - gtk_widget_set_sensitive(ctx->geom_file, TRUE); - - switch ( import_mode(ctx) ) { - - case IMPORT_FILES : - gtk_widget_set_sensitive(ctx->indiv_chooser, TRUE); - break; - - case IMPORT_LIST : - gtk_widget_set_sensitive(ctx->list_chooser, TRUE); - break; - - case IMPORT_SEARCH : - gtk_widget_set_sensitive(ctx->search_chooser, TRUE); - gtk_widget_set_sensitive(ctx->search_pattern, TRUE); - break; - - case IMPORT_STREAM : - gtk_widget_set_sensitive(ctx->geom_file, FALSE); - gtk_widget_set_sensitive(ctx->stream_chooser, TRUE); - break; - } -} - - -static void import_via_search(struct finddata_ctx *ctx) -{ - GFile *top; - DataTemplate *dtempl; - char *geom_filename; - const char *type_id; - struct crystfelproject *proj = ctx->proj; - - geom_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->geom_file)); - if ( geom_filename == NULL ) return; - - top = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(ctx->search_chooser)); - if ( top == NULL ) return; - - dtempl = data_template_new_from_file(geom_filename); - if ( dtempl == NULL ) return; - - type_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(ctx->search_pattern)); - proj->data_search_pattern = decode_matchtype(type_id); - - /* Totally clean up the old list */ - clear_project_files(proj); - crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), - NULL); - - g_free(proj->geom_filename); - proj->geom_filename = geom_filename; - - data_template_free(proj->dtempl); - proj->dtempl = dtempl; - - g_free(proj->data_top_folder); - proj->data_top_folder = g_file_get_path(top); - - add_files(proj, top, proj->data_search_pattern, - proj->dtempl); - - g_object_unref(top); -} - - -static void import_stream(struct finddata_ctx *ctx) -{ - struct crystfelproject *proj = ctx->proj; - Stream *st; - char *stream_filename; - DataTemplate *dtempl; - const char *geom_str; - char **streams; - - stream_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->stream_chooser)); - if ( stream_filename == NULL ) return; - - st = stream_open_for_read(stream_filename); - if ( st == NULL ) return; - - geom_str = stream_geometry_file(st); - if ( geom_str == NULL ) { - ERROR("No geometry file\n"); - stream_close(st); - return; - } - - dtempl = data_template_new_from_string(geom_str); - if ( dtempl == NULL ) { - stream_close(st); - return; - } - - clear_project_files(proj); - crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), - NULL); - - data_template_free(proj->dtempl); - proj->dtempl = dtempl; - - /* Set some defaults for things we won't be using */ - g_free(proj->geom_filename); - proj->geom_filename = NULL; - g_free(proj->data_top_folder); - proj->data_top_folder = NULL; - proj->data_search_pattern = MATCH_EVERYTHING; - - add_frames_from_stream(st, proj->dtempl, proj); - proj->stream_filename = stream_filename; - stream_close(st); - - streams = malloc(sizeof(char *)); - if ( streams != NULL ) { - char *result_name = safe_basename(stream_filename); - streams[0] = strdup(stream_filename); - add_indexing_result(proj, result_name, streams, 1); - select_result(proj, result_name); - } - - crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview), - 1); -} - -static void finddata_response_sig(GtkWidget *dialog, gint resp, - struct finddata_ctx *ctx) -{ - struct crystfelproject *proj = ctx->proj; - - if ( (resp == GTK_RESPONSE_DELETE_EVENT) - || (resp == GTK_RESPONSE_CANCEL) ) - { - gtk_widget_destroy(dialog); - free(ctx); - return; - } - - switch ( import_mode(ctx) ) { - - case IMPORT_FILES : - /* FIXME */ - break; - - case IMPORT_LIST : - /* FIXME */ - break; - - case IMPORT_SEARCH : - import_via_search(ctx); - break; - - case IMPORT_STREAM : - import_stream(ctx); - break; - } - - proj->unsaved = 1; - proj->cur_frame = 0; - crystfel_image_view_reset_zoom(CRYSTFEL_IMAGE_VIEW(proj->imageview)); - update_imageview(proj); - - free(ctx); - gtk_widget_destroy(dialog); -} - - -static gint finddata_sig(GtkWidget *widget, struct crystfelproject *proj) -{ - GtkWidget *dialog; - GtkWidget *content_area; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - struct finddata_ctx *ctx; - - ctx = malloc(sizeof(struct finddata_ctx)); - if ( ctx == NULL ) return FALSE; - - ctx->proj = proj; - - dialog = gtk_dialog_new_with_buttons("Import data", - GTK_WINDOW(proj->window), - GTK_DIALOG_DESTROY_WITH_PARENT, - "Cancel", GTK_RESPONSE_CANCEL, - "Import", GTK_RESPONSE_ACCEPT, - NULL); - - vbox = gtk_vbox_new(FALSE, 0.0); - content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - gtk_container_add(GTK_CONTAINER(content_area), vbox); - gtk_container_set_border_width(GTK_CONTAINER(content_area), 8); - - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); - label = gtk_label_new("Geometry file:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0); - ctx->geom_file = gtk_file_chooser_button_new("Select geometry file", - GTK_FILE_CHOOSER_ACTION_OPEN); - if ( proj->geom_filename != NULL ) { - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->geom_file), - proj->geom_filename); - } - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->geom_file), TRUE, TRUE, 2.0); - - /* Select individual files */ - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); - ctx->indiv = gtk_radio_button_new_with_label(NULL, - "Select an individual file"); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv), - FALSE, FALSE, 4.0); - g_signal_connect(ctx->indiv, "toggled", - G_CALLBACK(finddata_typetoggle_sig), ctx); - ctx->indiv_chooser = gtk_file_chooser_button_new("Select file", - GTK_FILE_CHOOSER_ACTION_OPEN); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv_chooser), - FALSE, FALSE, 4.0); - - /* Pre-prepared list of files */ - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); - ctx->list = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), - "Read a list of files"); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list), - FALSE, FALSE, 4.0); - g_signal_connect(ctx->list, "toggled", - G_CALLBACK(finddata_typetoggle_sig), ctx); - ctx->list_chooser = gtk_file_chooser_button_new("Select the list of filenames", - GTK_FILE_CHOOSER_ACTION_OPEN); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list_chooser), - FALSE, FALSE, 4.0); - - /* Search in folder */ - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0); - gtk_widget_set_margin_top(hbox, 6.0); - ctx->search = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), - "Search for files in folder"); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search), - FALSE, FALSE, 4.0); - g_signal_connect(ctx->search, "toggled", - G_CALLBACK(finddata_typetoggle_sig), ctx); - ctx->search_chooser = gtk_file_chooser_button_new("Select a folder", - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - if ( proj->data_top_folder != NULL ) { - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->search_chooser), - proj->data_top_folder); - } - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_chooser), - TRUE, TRUE, 2.0); - - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_widget_set_margin_bottom(hbox, 6.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0); - label = gtk_label_new("Search pattern:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_widget_set_margin_start(label, 32); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0); - ctx->search_pattern = gtk_combo_box_text_new(); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_pattern), TRUE, TRUE, 2.0); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "everything", - "All files in folder and subfolders"); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "hdf5", - "All HDF5 files ('*.h5')"); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "lcls-cheetah-hdf5", - "Individual LCLS files from Cheetah ('LCLS*.h5')"); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cheetah-cxi", - "Multi-event CXI files from Cheetah ('*.cxi')"); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbf", - "Individual CBF files ('*.cbf')"); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbfgz", - "Individual gzipped CBF files ('*.cbf.gz')"); - gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->search_pattern), - proj->data_search_pattern); - - /* Load a stream */ - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); - ctx->stream = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), - "Load stream"); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream), - FALSE, FALSE, 4.0); - ctx->stream_chooser = gtk_file_chooser_button_new("Select stream file", - GTK_FILE_CHOOSER_ACTION_OPEN); - if ( proj->stream_filename != NULL ) { - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->stream_chooser), - proj->stream_filename); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctx->stream), TRUE); - } - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream_chooser), - TRUE, TRUE, 2.0); - - /* Replace data toggle */ - hbox = gtk_hbox_new(FALSE, 0.0); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); - ctx->dump = gtk_check_button_new_with_label("Replace all the current data"); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->dump), FALSE, FALSE, 4.0); - - g_signal_connect(dialog, "response", - G_CALLBACK(finddata_response_sig), ctx); - - gtk_window_set_default_size(GTK_WINDOW(dialog), 512, 0); - finddata_typetoggle_sig(ctx->search, ctx); - gtk_widget_show_all(dialog); - return FALSE; -} - - /* File->Quit */ static gint quit_sig(GtkWidget *widget, struct crystfelproject *proj) { @@ -1009,7 +557,7 @@ static void add_task_buttons(GtkWidget *vbox, struct crystfelproject *proj) { /* FIXME: All these icons are placeholders */ add_button(vbox, "Load data", "folder-pictures", - G_CALLBACK(finddata_sig), proj); + G_CALLBACK(import_sig), proj); add_button(vbox, "Peak detection", "edit-find", G_CALLBACK(peaksearch_sig), proj); add_button(vbox, "Index this frame", "system-run", diff --git a/src/gui_import.c b/src/gui_import.c new file mode 100644 index 00000000..ba5e44f8 --- /dev/null +++ b/src/gui_import.c @@ -0,0 +1,505 @@ +/* + * gui_import.c + * + * Data import to GUI + * + * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2021 Thomas White <taw@physics.org> + * + * This file is part of CrystFEL. + * + * CrystFEL 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 3 of the License, or + * (at your option) any later version. + * + * CrystFEL 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 CrystFEL. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdarg.h> +#include <stdio.h> +#include <getopt.h> +#include <string.h> +#include <gtk/gtk.h> +#include <assert.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include <datatemplate.h> + +#include "crystfelimageview.h" +#include "gui_project.h" +#include "crystfel_gui.h" + +#include "version.h" + +static void add_all_events(struct crystfelproject *proj, + const char *filename, + const DataTemplate *dtempl) +{ + char **events; + int i; + int n_events; + + events = image_expand_frames(dtempl, filename, &n_events); + if ( events == NULL ) { + ERROR("Couldn't expand event list\n"); + return; + } + + for ( i=0; i<n_events; i++ ) { + add_file_to_project(proj, filename, events[i]); + free(events[i]); + } + free(events); +} + + +static void add_files(struct crystfelproject *proj, GFile *folder, + enum match_type_id type, + const DataTemplate *dtempl) +{ + GFileEnumerator *fenum; + GFileInfo *finfo; + GError *error = NULL; + + fenum = g_file_enumerate_children(folder, "standard::name,standard::type", + G_FILE_QUERY_INFO_NONE, + NULL, &error); + + do { + + GFile *file; + + finfo = g_file_enumerator_next_file(fenum, NULL, &error); + + if ( error != NULL ) { + STATUS("Error!\n"); + g_object_unref(fenum); + return; + } + + if ( finfo == NULL ) continue; + + file = g_file_get_child(folder, g_file_info_get_name(finfo)); + + if ( g_file_info_get_file_type(finfo) == G_FILE_TYPE_DIRECTORY ) { + + add_files(proj, file, type, dtempl); + + } else { + + char *bn = g_file_get_basename(file); + if ( match_filename(bn, type) ) { + add_all_events(proj, g_file_get_path(file), + dtempl); + } + + } + + g_object_unref(finfo); + + } while ( finfo != NULL ); + + g_object_unref(fenum); +} + + +static void add_frames_from_stream(Stream *st, + DataTemplate *dtempl, + struct crystfelproject *proj) +{ + do { + struct image *image; + image = stream_read_chunk(st, 0); + if ( image == NULL ) break; + add_file_to_project(proj, image->filename, image->ev); + image_free(image); + + } while ( 1 ); +} + + +struct finddata_ctx +{ + struct crystfelproject *proj; + GtkWidget *geom_file; + + /* "Select individual file" */ + GtkWidget *indiv; + GtkWidget *indiv_chooser; + + /* Read list of files */ + GtkWidget *list; /* "Import list" radio */ + GtkWidget *list_chooser; + + /* Search for files */ + GtkWidget *search; + GtkWidget *search_chooser; + GtkWidget *search_pattern; + + /* Load stream */ + GtkWidget *stream; + GtkWidget *stream_chooser; + + GtkWidget *dump; +}; + +enum import_mode +{ + IMPORT_FILES, + IMPORT_LIST, + IMPORT_SEARCH, + IMPORT_STREAM +}; + + +static enum import_mode import_mode(struct finddata_ctx *ctx) +{ + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->indiv))) { + return IMPORT_FILES; + } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->list))) { + return IMPORT_LIST; + } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->search))) { + return IMPORT_SEARCH; + } else { + return IMPORT_STREAM; + } +} + + +static void finddata_typetoggle_sig(GtkWidget *radio, + struct finddata_ctx *ctx) +{ + gtk_widget_set_sensitive(ctx->indiv_chooser, FALSE); + gtk_widget_set_sensitive(ctx->list_chooser, FALSE); + gtk_widget_set_sensitive(ctx->search_chooser, FALSE); + gtk_widget_set_sensitive(ctx->search_pattern, FALSE); + gtk_widget_set_sensitive(ctx->stream_chooser, FALSE); + + gtk_widget_set_sensitive(ctx->geom_file, TRUE); + + switch ( import_mode(ctx) ) { + + case IMPORT_FILES : + gtk_widget_set_sensitive(ctx->indiv_chooser, TRUE); + break; + + case IMPORT_LIST : + gtk_widget_set_sensitive(ctx->list_chooser, TRUE); + break; + + case IMPORT_SEARCH : + gtk_widget_set_sensitive(ctx->search_chooser, TRUE); + gtk_widget_set_sensitive(ctx->search_pattern, TRUE); + break; + + case IMPORT_STREAM : + gtk_widget_set_sensitive(ctx->geom_file, FALSE); + gtk_widget_set_sensitive(ctx->stream_chooser, TRUE); + break; + } +} + + +static void import_via_search(struct finddata_ctx *ctx) +{ + GFile *top; + DataTemplate *dtempl; + char *geom_filename; + const char *type_id; + struct crystfelproject *proj = ctx->proj; + + geom_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->geom_file)); + if ( geom_filename == NULL ) return; + + top = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(ctx->search_chooser)); + if ( top == NULL ) return; + + dtempl = data_template_new_from_file(geom_filename); + if ( dtempl == NULL ) return; + + type_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(ctx->search_pattern)); + proj->data_search_pattern = decode_matchtype(type_id); + + /* Totally clean up the old list */ + clear_project_files(proj); + crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), + NULL); + + g_free(proj->geom_filename); + proj->geom_filename = geom_filename; + + data_template_free(proj->dtempl); + proj->dtempl = dtempl; + + g_free(proj->data_top_folder); + proj->data_top_folder = g_file_get_path(top); + + add_files(proj, top, proj->data_search_pattern, + proj->dtempl); + + g_object_unref(top); +} + + +static void import_stream(struct finddata_ctx *ctx) +{ + struct crystfelproject *proj = ctx->proj; + Stream *st; + char *stream_filename; + DataTemplate *dtempl; + const char *geom_str; + char **streams; + + stream_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->stream_chooser)); + if ( stream_filename == NULL ) return; + + st = stream_open_for_read(stream_filename); + if ( st == NULL ) return; + + geom_str = stream_geometry_file(st); + if ( geom_str == NULL ) { + ERROR("No geometry file\n"); + stream_close(st); + return; + } + + dtempl = data_template_new_from_string(geom_str); + if ( dtempl == NULL ) { + stream_close(st); + return; + } + + clear_project_files(proj); + crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), + NULL); + + data_template_free(proj->dtempl); + proj->dtempl = dtempl; + + /* Set some defaults for things we won't be using */ + g_free(proj->geom_filename); + proj->geom_filename = NULL; + g_free(proj->data_top_folder); + proj->data_top_folder = NULL; + proj->data_search_pattern = MATCH_EVERYTHING; + + add_frames_from_stream(st, proj->dtempl, proj); + proj->stream_filename = stream_filename; + stream_close(st); + + streams = malloc(sizeof(char *)); + if ( streams != NULL ) { + char *result_name = safe_basename(stream_filename); + streams[0] = strdup(stream_filename); + add_indexing_result(proj, result_name, streams, 1); + select_result(proj, result_name); + } + + crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview), + 1); +} + + +static void finddata_response_sig(GtkWidget *dialog, gint resp, + struct finddata_ctx *ctx) +{ + struct crystfelproject *proj = ctx->proj; + + if ( (resp == GTK_RESPONSE_DELETE_EVENT) + || (resp == GTK_RESPONSE_CANCEL) ) + { + gtk_widget_destroy(dialog); + free(ctx); + return; + } + + switch ( import_mode(ctx) ) { + + case IMPORT_FILES : + /* FIXME */ + break; + + case IMPORT_LIST : + /* FIXME */ + break; + + case IMPORT_SEARCH : + import_via_search(ctx); + break; + + case IMPORT_STREAM : + import_stream(ctx); + break; + } + + proj->unsaved = 1; + proj->cur_frame = 0; + crystfel_image_view_reset_zoom(CRYSTFEL_IMAGE_VIEW(proj->imageview)); + update_imageview(proj); + + free(ctx); + gtk_widget_destroy(dialog); +} + + +gint import_sig(GtkWidget *widget, struct crystfelproject *proj) +{ + GtkWidget *dialog; + GtkWidget *content_area; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + struct finddata_ctx *ctx; + + ctx = malloc(sizeof(struct finddata_ctx)); + if ( ctx == NULL ) return FALSE; + + ctx->proj = proj; + + dialog = gtk_dialog_new_with_buttons("Import data", + GTK_WINDOW(proj->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + "Cancel", GTK_RESPONSE_CANCEL, + "Import", GTK_RESPONSE_ACCEPT, + NULL); + + vbox = gtk_vbox_new(FALSE, 0.0); + content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + gtk_container_add(GTK_CONTAINER(content_area), vbox); + gtk_container_set_border_width(GTK_CONTAINER(content_area), 8); + + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + label = gtk_label_new("Geometry file:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0); + ctx->geom_file = gtk_file_chooser_button_new("Select geometry file", + GTK_FILE_CHOOSER_ACTION_OPEN); + if ( proj->geom_filename != NULL ) { + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->geom_file), + proj->geom_filename); + } + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->geom_file), TRUE, TRUE, 2.0); + + /* Select individual files */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->indiv = gtk_radio_button_new_with_label(NULL, + "Select an individual file"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv), + FALSE, FALSE, 4.0); + g_signal_connect(ctx->indiv, "toggled", + G_CALLBACK(finddata_typetoggle_sig), ctx); + ctx->indiv_chooser = gtk_file_chooser_button_new("Select file", + GTK_FILE_CHOOSER_ACTION_OPEN); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv_chooser), + FALSE, FALSE, 4.0); + + /* Pre-prepared list of files */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->list = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), + "Read a list of files"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list), + FALSE, FALSE, 4.0); + g_signal_connect(ctx->list, "toggled", + G_CALLBACK(finddata_typetoggle_sig), ctx); + ctx->list_chooser = gtk_file_chooser_button_new("Select the list of filenames", + GTK_FILE_CHOOSER_ACTION_OPEN); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list_chooser), + FALSE, FALSE, 4.0); + + /* Search in folder */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0); + gtk_widget_set_margin_top(hbox, 6.0); + ctx->search = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), + "Search for files in folder"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search), + FALSE, FALSE, 4.0); + g_signal_connect(ctx->search, "toggled", + G_CALLBACK(finddata_typetoggle_sig), ctx); + ctx->search_chooser = gtk_file_chooser_button_new("Select a folder", + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + if ( proj->data_top_folder != NULL ) { + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->search_chooser), + proj->data_top_folder); + } + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_chooser), + TRUE, TRUE, 2.0); + + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_widget_set_margin_bottom(hbox, 6.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0); + label = gtk_label_new("Search pattern:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_widget_set_margin_start(label, 32); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0); + ctx->search_pattern = gtk_combo_box_text_new(); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_pattern), TRUE, TRUE, 2.0); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "everything", + "All files in folder and subfolders"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "hdf5", + "All HDF5 files ('*.h5')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "lcls-cheetah-hdf5", + "Individual LCLS files from Cheetah ('LCLS*.h5')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cheetah-cxi", + "Multi-event CXI files from Cheetah ('*.cxi')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbf", + "Individual CBF files ('*.cbf')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbfgz", + "Individual gzipped CBF files ('*.cbf.gz')"); + gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->search_pattern), + proj->data_search_pattern); + + /* Load a stream */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->stream = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), + "Load stream"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream), + FALSE, FALSE, 4.0); + ctx->stream_chooser = gtk_file_chooser_button_new("Select stream file", + GTK_FILE_CHOOSER_ACTION_OPEN); + if ( proj->stream_filename != NULL ) { + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->stream_chooser), + proj->stream_filename); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctx->stream), TRUE); + } + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream_chooser), + TRUE, TRUE, 2.0); + + /* Replace data toggle */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->dump = gtk_check_button_new_with_label("Replace all the current data"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->dump), FALSE, FALSE, 4.0); + + g_signal_connect(dialog, "response", + G_CALLBACK(finddata_response_sig), ctx); + + gtk_window_set_default_size(GTK_WINDOW(dialog), 512, 0); + finddata_typetoggle_sig(ctx->search, ctx); + gtk_widget_show_all(dialog); + return FALSE; +} + + diff --git a/src/gui_import.h b/src/gui_import.h new file mode 100644 index 00000000..6d25a32e --- /dev/null +++ b/src/gui_import.h @@ -0,0 +1,38 @@ +/* + * gui_import.h + * + * Data import to GUI + * + * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2021 Thomas White <taw@physics.org> + * + * This file is part of CrystFEL. + * + * CrystFEL 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 3 of the License, or + * (at your option) any later version. + * + * CrystFEL 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 CrystFEL. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef GUI_IMPORT_H +#define GUI_IMPORT_H + +#include <gtk/gtk.h> + +#include "gui_project.h" + +extern gint import_sig(GtkWidget *widget, struct crystfelproject *proj); + +#endif |