source: branches/properties/AWTI/AWTI_export.cxx

Last change on this file was 18962, checked in by westram, 3 years ago
  • eliminate unused parameter fallback2default from create_option_menu.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.7 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : AWTI_export.cxx                                 //
4//   Purpose   :                                                 //
5//                                                               //
6//   Institute of Microbiology (Technical University Munich)     //
7//   http://www.arb-home.de/                                     //
8//                                                               //
9// ============================================================= //
10
11#include "awti_export.hxx"
12#include "awti_exp_local.hxx"
13#include "awti_edit.hxx"
14
15#include <xfergui.h>
16#include <FileWatch.h>
17#include <seqio.hxx>
18#include <AP_filter.hxx>
19#include <db_scanner.hxx>
20
21#include <aw_awars.hxx>
22#include <aw_file.hxx>
23#include <aw_msg.hxx>
24
25#include <arbdbt.h>
26#include <gb_aci.h>
27
28#include <arb_progress.h>
29#include <arb_strbuf.h>
30#include <arb_stdstring.h>
31
32#include <set>
33#include <string>
34
35using namespace SEQIO;
36
37static void export_go_cb(AW_window *aww, GBDATA *gb_main, adfiltercbstruct *acbs) {
38    awti_assert(!GB_have_error());
39
40    GB_transaction ta(gb_main);
41    arb_progress   progress("Exporting data");
42
43    AW_root *awr = aww->get_root();
44
45    int multiple       = awr->awar(AWAR_EXPORT_MULTIPLE_FILES)->read_int();
46    int cut_stop_codon = awr->awar(AWAR_EXPORT_CUTSTOP)->read_int();
47    int compress       = awr->awar(AWAR_EXPORT_COMPRESS)->read_int();
48
49    ExportWhich  which   = ExportWhich(awr->awar(AWAR_EXPORT_MARKED)->read_int());
50    AP_filter   *filter  = awt_get_filter(acbs);
51    const char  *ftsname = XFER_getFullFTS(awr->awar(AWAR_EXPORT_FTS)->read_char_pntr());
52
53    char *formname = awr->awar(AWAR_EXPORT_FORMATNAME)->read_string();
54    char *outname  = awr->awar(AWAR_EXPORT_FILENAME)->read_string();
55    char *db_name  = awr->awar(AWAR_DB_NAME)->read_string();
56
57    char *real_outname = NULp; // with suffix (name of first file if multiple)
58
59    GB_ERROR error = export_by_format(gb_main, which, NULp,
60                                      filter, cut_stop_codon, compress,
61                                      db_name, formname, ftsname,
62                                      outname, multiple, &real_outname);
63
64    if (error) aw_message(error);
65    if (real_outname) awr->awar(AWAR_EXPORT_FILENAME)->write_string(real_outname);
66
67    AW_refresh_fileselection(awr, AWAR_EXPORT_FILEBASE);
68
69    free(db_name);
70    free(real_outname);
71    free(outname);
72    free(formname);
73}
74
75static void avoid_empty_target_name(char*& nameOnly) {
76    static char *last_used_name = ARB_strdup("noname");
77    if (nameOnly) freedup(last_used_name, nameOnly);
78    else          nameOnly = ARB_strdup(last_used_name); // if name was lost (by changing directory) -> reuse last_used_name
79}
80
81static bool in_export_filename_changed_cb = false;
82static void export_filename_changed_cb(AW_root *aw_root) {
83    if (!in_export_filename_changed_cb) {
84        LocallyModify<bool> dont_recurse(in_export_filename_changed_cb, true);
85
86        AW_awar *awar_export = aw_root->awar(AWAR_EXPORT_FILENAME);
87        char    *exportname  = awar_export->read_string();
88
89        if (!GB_is_directory(exportname)) {
90            char *path, *nameOnly, *suffix;
91            GB_split_full_path(exportname, &path, NULp, &nameOnly, &suffix);
92
93            avoid_empty_target_name(nameOnly);
94
95            const char *new_exportname = GB_concat_path(path, GB_append_suffix(nameOnly, suffix));
96            if (new_exportname) awar_export->write_string(new_exportname);
97        }
98        free(exportname);
99    }
100}
101
102static void create_export_awars(AW_root *awr) {
103    {
104        GBS_strstruct path(500);
105        path.cat(GB_path_in_arbprop("filter"));
106        path.put(':');
107        path.cat(GB_path_in_ARBLIB("export"));
108
109        AW_create_fileselection_awars(awr, AWAR_EXPORT_FORMATBASE, path.get_data(), ".eft", "*");
110        AW_create_fileselection_awars(awr, AWAR_EXPORT_FILEBASE,   "",              "",     "noname");
111    }
112
113    awr->awar_string(AWAR_EXPORT_FORMAT_DESC, "<no format selected>");
114    awr->awar_string(AWAR_EXPORT_FTS);
115
116    awr->awar_int(AWAR_EXPORT_MULTIPLE_FILES);
117    awr->awar_int(AWAR_EXPORT_MARKED,   EBF_MARKED);
118    awr->awar_int(AWAR_EXPORT_COMPRESS, 1); // vertical gaps
119    awr->awar_int(AWAR_EXPORT_CUTSTOP);     // don't cut stop-codon
120
121    awt_create_filter_awars(awr, AW_ROOT_DEFAULT, AWAR_EXPORT_FILTER_NAME, AWAR_DEFAULT_ALIGNMENT);
122
123    awr->awar(AWAR_EXPORT_FILENAME)->add_callback(export_filename_changed_cb);
124}
125
126static void update_format_description_and_suffix(const char *eft) {
127    // called when export format has changed (filter content or selected filter)
128    // -> automatically correct filename suffix
129    // -> restrict view to suffix
130    // -> update description
131
132    ExportFormatInfo eft_info;
133    GB_ERROR         error = get_exportFormat_information(eft, eft_info);
134
135    AW_root *aw_root   = AW_root::SINGLETON;
136    AW_awar *awar_desc = aw_root->awar(AWAR_EXPORT_FORMAT_DESC);
137
138    if (error) awar_desc->write_string(error); // display format-errors in description field
139    else {
140        const char  *current_suffix  = eft_info.suffix.content(); // Note: current_suffix may be NULp.. is that ok?
141        static char *previous_suffix = NULp;
142
143        // modify export filename and view
144        AW_awar *awar_filter = aw_root->awar(AWAR_EXPORT_FILESUFFIX);
145        AW_awar *awar_export = aw_root->awar(AWAR_EXPORT_FILENAME);
146
147        awar_filter->write_string("");
148
149        char *exportname = awar_export->read_string();
150
151        {
152            LocallyModify<bool> dont_recurse(in_export_filename_changed_cb, true);
153
154            char *path, *nameOnly, *suffix;
155            GB_split_full_path(exportname, &path, NULp, &nameOnly, &suffix);
156
157            avoid_empty_target_name(nameOnly);
158
159            if (suffix) {
160                if (previous_suffix && ARB_stricmp(suffix, previous_suffix) == 0) freedup(suffix, current_suffix); // remove old suffix
161                else freedup(suffix, GB_append_suffix(suffix, current_suffix)); // don't know existing suffix -> append
162            }
163            else suffix = ARB_strdup(current_suffix);
164
165            const char *new_exportname = GB_concat_path(path, GB_append_suffix(nameOnly, suffix));
166            if (new_exportname) awar_export->write_string(new_exportname);
167
168            free(suffix);
169            free(nameOnly);
170            free(path);
171        }
172
173        free(exportname);
174
175        awar_filter->write_string(current_suffix);
176
177        // remember last applied suffix
178        freedup(previous_suffix, current_suffix);
179
180        // update description
181        if (eft_info.description.isSet()) awar_desc->write_string(&*eft_info.description);
182        else                              awar_desc->write_string("<no description>");
183    }
184}
185
186class ExportFieldTracker : public FieldTracker, virtual Noncopyable {
187    typedef std::set<std::string> StrSet;
188
189    StrSet tracked; // fields
190
191public:
192    ExportFieldTracker() {}
193    void track_field(const char *fieldname) OVERRIDE {
194        tracked.insert(fieldname);
195    }
196
197    void add_tracked_to(StrArray& addTo) const {
198        for (StrSet::const_iterator elem = tracked.begin(); elem != tracked.end(); ++elem) {
199            char *copy = ARB_stringdup(*elem);
200            addTo.put(copy);
201        }
202    }
203};
204
205class ExportFieldScanner : public AvailableFieldScanner {
206    RefPtr<GBDATA> gb_main;
207
208    static const char* fake_exported_sequence(GBDATA*, unsigned long *len, const char**) {
209        *len = 5;
210        return "faked";
211    }
212
213public:
214    ExportFieldScanner() : gb_main(NULp) {}
215
216    void scanFields(StrArray& fields, FieldsToScan whatToScan) const OVERRIDE {
217        if (whatToScan & SCAN_INPUT_FIELDS) {
218            if (gb_main) {
219                collectKeysRegisteredInDatabase(fields, gb_main, SPECIES_get_selector(), true, false);
220            }
221            else {
222                fields.put(ARB_strdup("<no known source database>"));
223            }
224        }
225
226        if (whatToScan & SCAN_OUTPUT_FIELDS) {
227            char *eft = AW_root::SINGLETON->awar(AWAR_EXPORT_FORMATNAME)->read_string();
228            if (eft[0]) {
229                GB_ERROR scan_error = NULp;
230                {
231                    char *eftName;
232                    GB_split_full_path(eft, NULp, &eftName, NULp, NULp);
233                    free(eftName);
234                }
235
236                if (gb_main) {
237                    GB_transaction ta(gb_main);
238
239                    ItemSelector&  itemtype             = SPECIES_get_selector();
240                    GBDATA        *gb_someSpecies       = itemtype.get_selected_item(gb_main, AW_root::SINGLETON);
241                    if (!gb_someSpecies) gb_someSpecies = MutableBoundItemSel(gb_main, itemtype).get_any_item();
242
243                    if (gb_someSpecies) {
244                        GB_ERROR  error = NULp;
245                        char     *form  = get_exportFormat_evalForm(eft, error);
246
247                        if (!error) {
248                            if (form) {
249                                // create 'callEnv' to track fields:
250                                ExportFieldTracker tracker;
251                                GBL_env            env(gb_main, "tree_faked");
252                                {
253                                    GBL_call_env callEnv(gb_someSpecies, env);
254
255                                    callEnv.useFieldTracker(&tracker);
256                                    GB_set_export_sequence_hook(fake_exported_sequence);
257
258                                    // evaluate form (causes fields to become tracked by 'tracker')
259                                    {
260                                        char *result = GBS_string_eval_in_env(" ", form, callEnv);
261                                        awti_assert(!GB_have_error()); // if eval reports error -> tracker did not see fields behind error-command
262                                        free(result);
263                                    }
264
265                                    GB_set_export_sequence_hook(NULp);
266                                }
267                                // collect tracked fields:
268                                tracker.add_tracked_to(fields);
269                            }
270                            else {
271                                scan_error = "unknown form access failure";
272                            }
273                        }
274                        else {
275                            scan_error = error;
276                        }
277                        free(form);
278                    }
279                    else {
280                        scan_error = "no species";
281                    }
282                }
283                else {
284                    scan_error = "no database";
285                }
286
287                if (scan_error) {
288                    fields.put(GBS_global_string_copy("<scan filter: %s>", scan_error));
289                }
290            }
291            else {
292                fields.put(ARB_strdup("<no export filter selected>"));
293            }
294            free(eft);
295        }
296    }
297
298    void announce_source_database(GBDATA *gb_src) { gb_main = gb_src; }
299};
300
301static ExportFieldScanner fieldScanner;
302
303AW_window *create_AWTC_export_window(AW_root *awr, GBDATA *gb_main) {
304    static AW_window_simple *aws = NULp;
305
306    if (!aws) {
307        create_export_awars(awr);
308
309        aws = new AW_window_simple;
310
311        aws->init(awr, "ARB_EXPORT", "ARB EXPORT");
312        aws->load_xfig("awt/export_db.fig");
313
314        aws->at("close");
315        aws->callback(AW_POPDOWN);
316        aws->create_button("CLOSE", "CLOSE", "C");
317
318        aws->at("help");
319        aws->callback(makeHelpCallback("arb_export.hlp"));
320        aws->create_button("HELP", "HELP", "H");
321
322        AW_create_fileselection(aws, AWAR_EXPORT_FILEBASE,   "f", "PWD",     ANY_DIR,    false); // select export filename
323        AW_create_fileselection(aws, AWAR_EXPORT_FORMATBASE, "",  "ARBHOME", MULTI_DIRS, false); // select export filter
324
325        aws->at("allmarked");
326        aws->create_option_menu(AWAR_EXPORT_MARKED);
327        aws->insert_option("all",    "a", EBF_ALL);
328        aws->insert_option("marked", "m", EBF_MARKED);
329        aws->update_option_menu();
330
331        aws->at("compress");
332        aws->create_option_menu(AWAR_EXPORT_COMPRESS);
333        aws->insert_option("no", "n", 0);
334        aws->insert_option("vertical gaps", "v", 1);
335        aws->insert_option("all gaps", "a", 2);
336        aws->update_option_menu();
337
338        aws->at("seqfilter");
339        adfiltercbstruct *filtercd = awt_create_select_filter(awr, gb_main, AWAR_EXPORT_FILTER_NAME);
340        aws->callback(makeCreateWindowCallback(awt_create_select_filter_win, filtercd));
341        aws->create_button("SELECT_FILTER", AWAR_EXPORT_FILTER_NAME);
342
343        aws->at("cutstop");
344        aws->create_toggle(AWAR_EXPORT_CUTSTOP);
345
346        aws->at("multiple");
347        aws->create_toggle(AWAR_EXPORT_MULTIPLE_FILES);
348
349        aws->at("desc");
350        aws->create_text_field(AWAR_EXPORT_FORMAT_DESC);
351
352        aws->at("go");
353        aws->highlight();
354        aws->callback(makeWindowCallback(export_go_cb, gb_main, filtercd));
355        aws->create_button("GO", "GO", "G", "+");
356
357        aws->at("test");
358        aws->callback(makeWindowCallback(AWTI_activate_export_test_window, gb_main, filtercd));
359        aws->create_button("TEST", "Test", "T");
360
361        aws->at("fts");
362        aws->callback(makeWindowCallback(XFER_select_RuleSet, AWAR_EXPORT_FTS, static_cast<AvailableFieldScanner*>(&fieldScanner)));
363        aws->create_button("SELECT_FTS", AWAR_EXPORT_FTS);
364
365        static FileWatch fwatch(AWAR_EXPORT_FORMATNAME, makeFileChangedCallback(update_format_description_and_suffix));
366        awr->awar(AWAR_EXPORT_FORMATNAME)->add_callback(makeRootCallback(XFER_refresh_available_fields, static_cast<AvailableFieldScanner*>(&fieldScanner), SCAN_OUTPUT_FIELDS));
367    }
368
369    fieldScanner.announce_source_database(gb_main);
370
371    return aws;
372}
Note: See TracBrowser for help on using the repository browser.