aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--meson.build1
-rw-r--r--src/crystfel_gui.c456
-rw-r--r--src/gui_import.c505
-rw-r--r--src/gui_import.h38
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