source: tags/svn.1.5.4/NTREE/ad_trees.cxx

Last change on this file was 8393, checked in by westram, 12 years ago
  • cppchecked (1.53)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.7 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ad_trees.cxx                                      //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "ad_trees.hxx"
12#include "nt_tree_cmp.hxx"
13
14#include <TreeRead.h>
15#include <TreeWrite.h>
16#include <awt_sel_boxes.hxx>
17#include <aw_window.hxx>
18#include <aw_awars.hxx>
19#include <aw_edit.hxx>
20#include <aw_file.hxx>
21#include <aw_msg.hxx>
22#include <aw_root.hxx>
23#include <arbdbt.h>
24#include <arb_strbuf.h>
25#include <arb_file.h>
26
27#define nt_assert(bed) arb_assert(bed)
28
29extern GBDATA *GLOBAL_gb_main;
30
31static const char *AWAR_TREE_DEST     = "tmp/ad_tree/tree_dest";
32static const char *AWAR_TREE_SECURITY = "tmp/ad_tree/tree_security";
33static const char *AWAR_TREE_REM      = "tmp/ad_tree/tree_rem";
34
35#define AWAR_TREE_EXPORT           "tmp/ad_tree/export_tree"
36#define AWAR_TREE_IMPORT           "tmp/ad_tree/import_tree"
37#define AWAR_NODE_INFO_ONLY_MARKED "tmp/ad_tree/import_only_marked_node_info"
38#define AWAR_TREE_EXPORT_SAVE      "ad_tree/export_tree"
39
40#define AWAR_TREE_EXPORT_FILTER             AWAR_TREE_EXPORT "/filter"
41#define AWAR_TREE_EXPORT_FORMAT             AWAR_TREE_EXPORT_SAVE "/format"
42#define AWAR_TREE_EXPORT_NDS                AWAR_TREE_EXPORT_SAVE "/NDS"
43#define AWAR_TREE_EXPORT_INCLUDE_BOOTSTRAPS AWAR_TREE_EXPORT_SAVE "/bootstraps"
44#define AWAR_TREE_EXPORT_INCLUDE_BRANCHLENS AWAR_TREE_EXPORT_SAVE "/branchlens"
45#define AWAR_TREE_EXPORT_INCLUDE_GROUPNAMES AWAR_TREE_EXPORT_SAVE "/groupnames"
46#define AWAR_TREE_EXPORT_HIDE_FOLDED_GROUPS AWAR_TREE_EXPORT_SAVE "/hide_folded"
47#define AWAR_TREE_EXPORT_QUOTEMODE          AWAR_TREE_EXPORT_SAVE "/quote_mode"
48#define AWAR_TREE_EXPORT_REPLACE            AWAR_TREE_EXPORT_SAVE "/replace"
49
50static void tree_vars_callback(AW_root *aw_root) // Map tree vars to display objects
51{
52    if (GLOBAL_gb_main) {
53        GB_push_transaction(GLOBAL_gb_main);
54        char *treename = aw_root->awar(AWAR_TREE_NAME)->read_string();
55        GBDATA *ali_cont = GBT_get_tree(GLOBAL_gb_main, treename);
56        if (!ali_cont) {
57            aw_root->awar(AWAR_TREE_SECURITY)->unmap();
58            aw_root->awar(AWAR_TREE_REM)->unmap();
59        }
60        else {
61            GBDATA *tree_prot = GB_search(ali_cont, "security", GB_FIND);
62            if (!tree_prot) GBT_readOrCreate_int(ali_cont, "security", GB_read_security_write(ali_cont));
63            tree_prot         = GB_search(ali_cont, "security", GB_INT);
64
65            GBDATA *tree_rem = GB_search(ali_cont, "remark",   GB_STRING);
66            aw_root->awar(AWAR_TREE_SECURITY)->map(tree_prot);
67            aw_root->awar(AWAR_TREE_REM)     ->map(tree_rem);
68        }
69        char *suffix = aw_root->awar(AWAR_TREE_EXPORT_FILTER)->read_string();
70        char *fname  = GBS_string_eval(treename, GBS_global_string("*=*1.%s:tree_*=*1", suffix), 0);
71        aw_root->awar(AWAR_TREE_EXPORT "/file_name")->write_string(fname); // create default file name
72        free(fname);
73        free(suffix);
74        GB_pop_transaction(GLOBAL_gb_main);
75        free(treename);
76    }
77}
78//  update import tree name depending on file name
79static void tree_import_callback(AW_root *aw_root) {
80    GB_transaction  dummy(GLOBAL_gb_main);
81    char           *treename        = aw_root->awar(AWAR_TREE_IMPORT "/file_name")->read_string();
82    char           *treename_nopath = strrchr(treename, '/');
83
84    if (treename_nopath) {
85        ++treename_nopath;
86    }
87    else {
88        treename_nopath = treename;
89    }
90
91    char *fname = GBS_string_eval(treename_nopath, "*.tree=tree_*1:*.ntree=tree_*1:*.xml=tree_*1:.=", 0);
92    aw_root->awar(AWAR_TREE_IMPORT "/tree_name")->write_string(fname);
93
94    free(fname);
95    free(treename);
96}
97
98
99static void ad_tree_set_security(AW_root *aw_root)
100{
101    if (GLOBAL_gb_main) {
102        GB_transaction dummy(GLOBAL_gb_main);
103        char *treename = aw_root->awar(AWAR_TREE_NAME)->read_string();
104        GBDATA *ali_cont = GBT_get_tree(GLOBAL_gb_main, treename);
105        if (ali_cont) {
106            long prot = aw_root->awar(AWAR_TREE_SECURITY)->read_int();
107            long old;
108            old = GB_read_security_delete(ali_cont);
109            GB_ERROR error = 0;
110            if (old != prot) {
111                error = GB_write_security_delete(ali_cont, prot);
112                if (!error)
113                    error = GB_write_security_write(ali_cont, prot);
114            }
115            if (error) aw_message(error);
116        }
117        free(treename);
118    }
119}
120
121enum ExportTreeType {
122    AD_TREE_EXPORT_FORMAT_NEWICK,
123    AD_TREE_EXPORT_FORMAT_XML,
124    AD_TREE_EXPORT_FORMAT_NEWICK_PRETTY,
125};
126
127enum ExportNodeType {
128    AD_TREE_EXPORT_NODE_SPECIES_NAME,
129    AD_TREE_EXPORT_NODE_NDS
130};
131
132static void update_filter_cb(AW_root *root) {
133    const char *filter_type = 0;
134
135    switch (ExportTreeType(root->awar(AWAR_TREE_EXPORT_FORMAT)->read_int())) {
136        case AD_TREE_EXPORT_FORMAT_XML: filter_type = "xml"; break;
137        case AD_TREE_EXPORT_FORMAT_NEWICK:
138        case AD_TREE_EXPORT_FORMAT_NEWICK_PRETTY:
139            switch (ExportNodeType(root->awar(AWAR_TREE_EXPORT_NDS)->read_int())) {
140                case AD_TREE_EXPORT_NODE_SPECIES_NAME:  filter_type = "tree"; break;
141                case AD_TREE_EXPORT_NODE_NDS:           filter_type = "ntree"; break;
142                default: nt_assert(0); break;
143            }
144            break;
145        default: nt_assert(0); break;
146    }
147
148    nt_assert(filter_type);
149    root->awar(AWAR_TREE_EXPORT_FILTER)->write_string(filter_type);
150}
151
152void create_trees_var(AW_root *aw_root, AW_default aw_def)
153{
154    AW_awar *awar_tree_name = aw_root->awar_string(AWAR_TREE_NAME,        0,  aw_def)->set_srt(GBT_TREE_AWAR_SRT);
155    aw_root->awar_string(AWAR_TREE_DEST,        0,  aw_def) ->set_srt(GBT_TREE_AWAR_SRT);
156    aw_root->awar_int(AWAR_TREE_SECURITY,       0,  aw_def);
157    aw_root->awar_string(AWAR_TREE_REM,         0,  aw_def);
158
159    AW_create_fileselection_awars(aw_root, AWAR_TREE_EXPORT, "", ".tree", "treefile", aw_def);
160    aw_root->awar_int(AWAR_TREE_EXPORT_FORMAT, AD_TREE_EXPORT_FORMAT_NEWICK, aw_def)-> add_callback(update_filter_cb);
161    aw_root->awar_int(AWAR_TREE_EXPORT_NDS,  AD_TREE_EXPORT_NODE_SPECIES_NAME, aw_def)-> add_callback(update_filter_cb);
162
163    aw_root->awar_int(AWAR_TREE_EXPORT_INCLUDE_BOOTSTRAPS,  0, aw_def);
164    aw_root->awar_int(AWAR_TREE_EXPORT_INCLUDE_BRANCHLENS,  1, aw_def);
165    aw_root->awar_int(AWAR_TREE_EXPORT_HIDE_FOLDED_GROUPS,  0, aw_def);
166    aw_root->awar_int(AWAR_TREE_EXPORT_INCLUDE_GROUPNAMES,  1, aw_def);
167    aw_root->awar_int(AWAR_TREE_EXPORT_QUOTEMODE, TREE_SINGLE_QUOTES, aw_def); // old default behavior
168    aw_root->awar_int(AWAR_TREE_EXPORT_REPLACE, 0, aw_def); // old default behavior
169
170    AW_create_fileselection_awars(aw_root, AWAR_TREE_IMPORT, "", ".tree", "treefile", aw_def);
171
172    aw_root->awar_string(AWAR_TREE_IMPORT "/tree_name", "tree_",    aw_def) ->set_srt(GBT_TREE_AWAR_SRT);
173
174    aw_root->awar(AWAR_TREE_IMPORT "/file_name")->add_callback(tree_import_callback);
175    awar_tree_name->add_callback(tree_vars_callback);
176    awar_tree_name->map(AWAR_TREE);
177    aw_root->awar(AWAR_TREE_SECURITY)->add_callback(ad_tree_set_security);
178
179    aw_root->awar_int(AWAR_NODE_INFO_ONLY_MARKED, 0,    aw_def);
180
181    update_filter_cb(aw_root);
182    tree_vars_callback(aw_root);
183}
184
185static void tree_rename_cb(AW_window *aww) {
186    AW_root  *aw_root   = aww->get_root();
187    AW_awar  *awar_tree = aw_root->awar(AWAR_TREE_NAME);
188    char     *source    = awar_tree->read_string();
189    char     *dest      = aw_root->awar(AWAR_TREE_DEST)->read_string();
190    GB_ERROR  error     = GBT_check_tree_name(dest);
191
192    if (!error) {
193        error = GB_begin_transaction(GLOBAL_gb_main);
194        if (!error) {
195            GBDATA *gb_tree_data = GB_search(GLOBAL_gb_main, "tree_data", GB_CREATE_CONTAINER);
196
197            if (!gb_tree_data) error = GB_await_error();
198            else {
199                GBDATA *gb_tree_name = GB_entry(gb_tree_data, source);
200                GBDATA *gb_dest      = GB_entry(gb_tree_data, dest);
201
202                if (gb_dest) error = GBS_global_string("Tree '%s' already exists", dest);
203                else if (!gb_tree_name) error = "Please select a tree";
204                else {
205                    GBDATA *gb_new_tree = GB_create_container(gb_tree_data, dest);
206
207                    if (!gb_new_tree) error = GB_await_error();
208                    else {
209                        error = GB_copy(gb_new_tree, gb_tree_name);
210                        if (!error) error = GB_delete(gb_tree_name);
211                    }
212                }
213            }
214        }
215
216        if (!error) awar_tree->write_string(dest);
217        error = GB_end_transaction(GLOBAL_gb_main, error);
218    }
219
220    aww->hide_or_notify(error);
221
222    free(dest);
223    free(source);
224}
225
226static GB_ERROR tree_append_remark(GBDATA *gb_tree, const char *add_to_remark) {
227    GB_ERROR  error       = 0;
228    GBDATA   *gb_remark   = GB_search(gb_tree, "remark", GB_STRING);
229    if (!gb_remark) error = GB_await_error();
230    else {
231        char *old_remark       = GB_read_string(gb_remark);
232        if (!old_remark) error = GB_await_error();
233        else {
234            GBS_strstruct *new_remark = GBS_stropen(2000);
235
236            GBS_strcat(new_remark, old_remark);
237            GBS_chrcat(new_remark, '\n');
238            GBS_strcat(new_remark, add_to_remark);
239
240            error = GB_write_string(gb_remark, GBS_mempntr(new_remark));
241
242            GBS_strforget(new_remark);
243        }
244        free(old_remark);
245    }
246    return error;
247}
248
249static void tree_copy_cb(AW_window *aww) {
250    char     *source = aww->get_root()->awar(AWAR_TREE_NAME)->read_string();
251    char     *dest   = aww->get_root()->awar(AWAR_TREE_DEST)->read_string();
252    GB_ERROR  error  = GBT_check_tree_name(dest);
253
254    if (!error) {
255        error = GB_begin_transaction(GLOBAL_gb_main);
256        if (!error) {
257            GBDATA *gb_tree_data     = GB_search(GLOBAL_gb_main, "tree_data", GB_CREATE_CONTAINER);
258            if (!gb_tree_data) error = GB_await_error();
259            else {
260                GBDATA *gb_tree_name = GB_entry(gb_tree_data, source);
261                GBDATA *gb_dest      = GB_entry(gb_tree_data, dest);
262
263                if (gb_dest) error = GBS_global_string("Tree '%s' already exists", dest);
264                else if (!gb_tree_name) error = "Please select a tree";
265                else {
266                    gb_dest             = GB_create_container(gb_tree_data, dest);
267                    if (!gb_dest) error = GB_await_error();
268                    else {
269                        error = GB_copy(gb_dest, gb_tree_name);
270                        if (!error) error = tree_append_remark(gb_dest, GBS_global_string("[created as copy of '%s']", source));
271                    }
272                }
273            }
274        }
275        error = GB_end_transaction(GLOBAL_gb_main, error);
276    }
277
278    aww->hide_or_notify(error);
279
280    free(dest);
281    free(source);
282}
283
284static void tree_save_cb(AW_window *aww) {
285    AW_root  *aw_root   = aww->get_root();
286    char     *tree_name = aw_root->awar(AWAR_TREE_NAME)->read_string();
287
288    GB_ERROR error = 0;
289
290    if (!tree_name || !strlen(tree_name)) {
291        error = "Please select a tree first";
292    }
293    else {
294        char *fname   = aw_root->awar(AWAR_TREE_EXPORT "/file_name")->read_string();
295        char *db_name = aw_root->awar(AWAR_DB_NAME)->read_string();
296
297        bool                use_NDS    = ExportNodeType(aw_root->awar(AWAR_TREE_EXPORT_NDS)->read_int()) == AD_TREE_EXPORT_NODE_NDS;
298        ExportTreeType      exportType = static_cast<ExportTreeType>(aw_root->awar(AWAR_TREE_EXPORT_FORMAT)->read_int());
299        TREE_node_text_gen *node_gen   = use_NDS ? new TREE_node_text_gen(make_node_text_init, make_node_text_nds) : 0;
300
301        switch (exportType) {
302            case AD_TREE_EXPORT_FORMAT_XML:
303                error = TREE_write_XML(GLOBAL_gb_main, db_name, tree_name, node_gen,
304                                       aw_root->awar(AWAR_TREE_EXPORT_HIDE_FOLDED_GROUPS)->read_int(),
305                                       fname);
306                break;
307
308            case AD_TREE_EXPORT_FORMAT_NEWICK:
309            case AD_TREE_EXPORT_FORMAT_NEWICK_PRETTY:
310                TREE_node_quoting quoteMode = TREE_node_quoting(aw_root->awar(AWAR_TREE_EXPORT_QUOTEMODE)->read_int());
311                if (aw_root->awar(AWAR_TREE_EXPORT_REPLACE)->read_int()) {
312                    quoteMode = TREE_node_quoting(quoteMode|TREE_FORCE_REPLACE);
313                }
314
315                error = TREE_write_Newick(GLOBAL_gb_main, tree_name, node_gen,
316                                          aw_root->awar(AWAR_TREE_EXPORT_INCLUDE_BRANCHLENS)->read_int(),
317                                          aw_root->awar(AWAR_TREE_EXPORT_INCLUDE_BOOTSTRAPS)->read_int(),
318                                          aw_root->awar(AWAR_TREE_EXPORT_INCLUDE_GROUPNAMES)->read_int(),
319                                          exportType == AD_TREE_EXPORT_FORMAT_NEWICK_PRETTY,
320                                          quoteMode,
321                                          fname);
322                break;
323        }
324
325        AW_refresh_fileselection(aw_root, AWAR_TREE_EXPORT);
326
327        delete node_gen;
328        free(db_name);
329        free(fname);
330    }
331
332    aww->hide_or_notify(error);
333    free(tree_name);
334}
335
336static AW_window *create_tree_export_window(AW_root *root)
337{
338    AW_window_simple *aws = new AW_window_simple;
339    aws->init(root, "SAVE_TREE", "TREE SAVE");
340    aws->load_xfig("sel_box_user2.fig");
341
342    aws->callback((AW_CB0)AW_POPDOWN);
343    aws->at("close");
344    aws->create_button("CLOSE", "CLOSE", "C");
345
346    aws->at("help");
347    aws->callback(AW_POPUP_HELP, (AW_CL)"tr_export.hlp");
348    aws->create_button("HELP", "HELP", "H");
349
350    aws->at("user");
351    aws->create_option_menu(AWAR_TREE_EXPORT_FORMAT, 0, 0);
352    aws->insert_option("NEWICK TREE FORMAT",                   "N", AD_TREE_EXPORT_FORMAT_NEWICK);
353    aws->insert_option("NEWICK TREE FORMAT (pretty, but big)", "P", AD_TREE_EXPORT_FORMAT_NEWICK_PRETTY);
354    aws->insert_option("ARB_XML TREE FORMAT",                  "X", AD_TREE_EXPORT_FORMAT_XML);
355    aws->update_option_menu();
356
357    AW_create_fileselection(aws, AWAR_TREE_EXPORT "");
358
359    aws->at("user2");
360    aws->auto_space(10, 10);
361    aws->label("Nodetype");
362    aws->create_toggle_field(AWAR_TREE_EXPORT_NDS, 1);
363    aws->insert_default_toggle("Species name", "S", 0);
364    aws->insert_toggle("NDS", "N", 1);
365    aws->update_toggle_field();
366
367    aws->at_newline(); aws->label("Save branch lengths"); aws->create_toggle(AWAR_TREE_EXPORT_INCLUDE_BRANCHLENS);
368    aws->at_newline(); aws->label("Save bootstrap values"); aws->create_toggle(AWAR_TREE_EXPORT_INCLUDE_BOOTSTRAPS);
369    aws->at_newline(); aws->label("Save group names"); aws->create_toggle(AWAR_TREE_EXPORT_INCLUDE_GROUPNAMES);
370    aws->at_newline(); aws->label("Hide folded groups (XML only)"); aws->create_toggle(AWAR_TREE_EXPORT_HIDE_FOLDED_GROUPS);
371
372    aws->at_newline(); aws->label("Name quoting (Newick only)");
373    aws->create_option_menu(AWAR_TREE_EXPORT_QUOTEMODE, 0, 0);
374    aws->insert_option("none",            "n", TREE_DISALLOW_QUOTES);
375    aws->insert_option("single",          "s", TREE_SINGLE_QUOTES);
376    aws->insert_option("double",          "d", TREE_DOUBLE_QUOTES);
377    aws->insert_option("single (forced)", "i", TREE_SINGLE_QUOTES|TREE_FORCE_QUOTES);
378    aws->insert_option("double (forced)", "o", TREE_DOUBLE_QUOTES|TREE_FORCE_QUOTES);
379    aws->update_option_menu();
380
381    aws->at_newline(); aws->label("Replace problem chars"); aws->create_toggle(AWAR_TREE_EXPORT_REPLACE);
382
383    aws->at_newline();
384    aws->callback(tree_save_cb);
385    aws->create_button("SAVE", "SAVE", "o");
386
387    aws->callback((AW_CB0)AW_POPDOWN);
388    aws->create_button("CANCEL", "CANCEL", "C");
389
390    aws->window_fit();
391    update_filter_cb(root);
392
393    return aws;
394}
395
396static char *readXmlTree(char *fname) {
397    // create a temp file
398    char tempFile[]  = "newickXXXXXX";
399    int createTempFile = mkstemp(tempFile);
400
401    if (createTempFile) {
402        GBS_strstruct *buf = GBS_stropen(strlen(fname));
403
404        // extract path from fname in order to place a copy of dtd file required to validate xml file
405        {
406            char *tmpFname = strdup(fname);
407            for (char *tok = strtok(tmpFname, "/"); tok;) {
408                char *tmp = tok;
409                tok = strtok(0, "/");
410                if (tok) {
411                    GBS_strcat(buf, "/");
412                    GBS_strcat(buf, tmp);
413                }
414            }
415            free(tmpFname);
416        }
417
418        char *path = GBS_strclose(buf);
419
420        // linking arb_tree.dtd file to the Path from where xml file is loaded
421#if defined(WARN_TODO)
422#warning fix hack
423#endif
424        char *command = GBS_global_string_copy("ln -s %s/lib/dtd/arb_tree.dtd %s/.", GB_getenvARBHOME(), path);
425        GB_xcmd(command, false, true);
426
427        // execute xml2newick to convert xml format tree to newick format tree
428        command = GBS_global_string_copy("xml2newick %s %s", fname, tempFile);
429        GB_xcmd(command, false, true);
430
431        free(command);
432        free(path);
433
434        // return newick format tree file
435        return strdup(tempFile);
436    }
437    else {
438        printf("Failed to create Temporary File to Parse xml file!\n");
439        return 0;
440    }
441}
442
443static void tree_load_cb(AW_window *aww) {
444    GB_ERROR  error     = 0;
445    AW_root  *aw_root   = aww->get_root();
446    char     *tree_name = aw_root->awar(AWAR_TREE_IMPORT "/tree_name")->read_string();
447
448    {
449        char *pcTreeFormat = aw_root->awar(AWAR_TREE_IMPORT "/filter")->read_string();
450        char *fname        = aw_root->awar(AWAR_TREE_IMPORT "/file_name")->read_string();
451        char *scaleWarning = 0;
452        char *tree_comment = 0;
453
454        GBT_TREE *tree;
455        if (strcmp(pcTreeFormat, "xml") == 0) {
456            char *tempFname = readXmlTree(fname);
457            tree = TREE_load(tempFname, sizeof(GBT_TREE), &tree_comment, 1, &scaleWarning);
458            GB_unlink_or_warn(tempFname, NULL);
459            free(tempFname);
460        }
461        else {
462            tree = TREE_load(fname, sizeof(GBT_TREE), &tree_comment, 1, &scaleWarning);
463        }
464
465        if (!tree) error = GB_await_error();
466        else {
467            if (scaleWarning) GBT_message(GLOBAL_gb_main, scaleWarning);
468
469            GB_transaction ta(GLOBAL_gb_main);
470            error = GBT_write_tree(GLOBAL_gb_main, 0, tree_name, tree);
471
472            if (!error && tree_comment) {
473                error = GBT_write_tree_rem(GLOBAL_gb_main, tree_name, tree_comment);
474            }
475
476            if (error) error = ta.close(error);
477            else aw_root->awar(AWAR_TREE)->write_string(tree_name); // show new tree
478
479            GBT_delete_tree(tree);
480        }
481
482        free(scaleWarning);
483        free(tree_comment);
484        free(fname);
485        free(pcTreeFormat);
486    }
487
488    aww->hide_or_notify(error);
489    free(tree_name);
490}
491
492static AW_window *create_tree_import_window(AW_root *root)
493{
494    AW_window_simple *aws = new AW_window_simple;
495    aws->init(root, "LOAD_TREE", "TREE LOAD");
496    aws->load_xfig("sel_box_tree.fig");
497
498    aws->callback((AW_CB0)AW_POPDOWN);
499    aws->at("close");
500    aws->create_button("CLOSE", "CLOSE", "C");
501
502    aws->at("format");
503    aws->label("Tree Format :");
504    aws->create_option_menu(AWAR_TREE_IMPORT "/filter");
505    aws->insert_default_option("Newick", "t", "tree");
506    aws->insert_option("XML", "x", "xml");
507    aws->update_option_menu();
508
509    aws->at("user");
510    aws->label("tree_name:");
511    aws->create_input_field(AWAR_TREE_IMPORT "/tree_name", 15);
512
513    AW_create_fileselection(aws, AWAR_TREE_IMPORT "");
514
515    aws->at("save2");
516    aws->callback(tree_load_cb);
517    aws->create_button("LOAD", "LOAD", "o");
518
519    aws->callback((AW_CB0)AW_POPDOWN);
520    aws->at("cancel2");
521    aws->create_button("CANCEL", "CANCEL", "C");
522
523    aws->window_fit();
524
525    return (AW_window *)aws;
526}
527
528static AW_window *create_tree_rename_window(AW_root *root)
529{
530    AW_window_simple *aws = new AW_window_simple;
531    aws->init(root, "RENAME_TREE", "TREE RENAME");
532    aws->load_xfig("ad_al_si.fig");
533
534    aws->callback((AW_CB0)AW_POPDOWN);
535    aws->at("close");
536    aws->create_button("CLOSE", "CLOSE", "C");
537
538    aws->at("label");
539    aws->create_autosize_button(0, "Please enter the new name\nof the tree");
540
541    aws->at("input");
542    aws->create_input_field(AWAR_TREE_DEST, 15);
543
544    aws->at("ok");
545    aws->callback(tree_rename_cb);
546    aws->create_button("GO", "GO", "G");
547
548    return (AW_window *)aws;
549}
550
551static AW_window *create_tree_copy_window(AW_root *root)
552{
553    AW_window_simple *aws = new AW_window_simple;
554    aws->init(root, "COPY_TREE", "TREE COPY");
555    aws->load_xfig("ad_al_si.fig");
556
557    aws->callback((AW_CB0)AW_POPDOWN);
558    aws->at("close");
559    aws->create_button("CLOSE", "CLOSE", "C");
560
561    aws->at("label");
562    aws->create_autosize_button(0, "Please enter the name\nof the new tree");
563
564    aws->at("input");
565    aws->create_input_field(AWAR_TREE_DEST, 15);
566
567    aws->at("ok");
568    aws->callback(tree_copy_cb);
569    aws->create_button("GO", "GO", "G");
570
571    return (AW_window *)aws;
572}
573
574static void ad_move_tree_info(AW_window *aww, AW_CL mode) {
575    /* mode == 0 -> move info (=overwrite info from source tree)
576     * mode == 1 -> compare info
577     * mode == 2 -> add info
578     */
579
580    bool compare_node_info      = mode==1;
581    bool delete_old_nodes       = mode==0;
582    bool nodes_with_marked_only = (mode==0 || mode==2) && aww->get_root()->awar(AWAR_NODE_INFO_ONLY_MARKED)->read_int();
583
584    char     *log_file = 0;
585    GB_ERROR  error    = 0;
586
587    if (!compare_node_info) {
588        // move or add node-info writes a log file (containing errors)
589        // compare_node_info only sets remark branches
590        char *log_name       = GB_unique_filename("arb_node", "log");
591        log_file             = GB_create_tempfile(log_name);
592        if (!log_file) error = GB_await_error();
593        free(log_name);
594    }
595
596    if (!error) {
597        char *t1 = aww->get_root()->awar(AWAR_TREE_NAME)->read_string();
598        char *t2 = aww->get_root()->awar(AWAR_TREE_DEST)->read_string();
599
600        AWT_move_info(GLOBAL_gb_main, t1, t2, log_file, compare_node_info, delete_old_nodes, nodes_with_marked_only);
601        if (log_file) {
602            AW_edit(log_file);
603            GB_remove_on_exit(log_file);
604        }
605
606        free(t2);
607        free(t1);
608    }
609
610    if (error) aw_message(error);
611    else aww->hide();
612
613    free(log_file);
614}
615
616static AW_window *create_tree_diff_window(AW_root *root) {
617    static AW_window_simple *aws = 0;
618    if (aws) return aws;
619    GB_transaction dummy(GLOBAL_gb_main);
620    aws = new AW_window_simple;
621    aws->init(root, "CMP_TOPOLOGY", "COMPARE TREE TOPOLOGIES");
622    aws->load_xfig("ad_tree_cmp.fig");
623
624    aws->callback(AW_POPDOWN);
625    aws->at("close");
626    aws->create_button("CLOSE", "CLOSE", "C");
627
628    aws->callback(AW_POPUP_HELP, (AW_CL)"tree_diff.hlp");
629    aws->at("help");
630    aws->create_button("HELP", "HELP", "H");
631
632    root->awar_string(AWAR_TREE_NAME);
633    root->awar_string(AWAR_TREE_DEST);
634
635    aws->at("tree1");
636    awt_create_selection_list_on_trees(GLOBAL_gb_main, (AW_window *)aws, AWAR_TREE_NAME);
637    aws->at("tree2");
638    awt_create_selection_list_on_trees(GLOBAL_gb_main, (AW_window *)aws, AWAR_TREE_DEST);
639
640    aws->button_length(20);
641
642    aws->at("move");
643    aws->callback(ad_move_tree_info, 1); // compare
644    aws->create_button("CMP_TOPOLOGY", "COMPARE TOPOLOGY");
645
646    return aws;
647}
648static AW_window *create_tree_cmp_window(AW_root *root) {
649    static AW_window_simple *aws = 0;
650    if (aws) return aws;
651    GB_transaction dummy(GLOBAL_gb_main);
652    aws = new AW_window_simple;
653    aws->init(root, "COPY_NODE_INFO_OF_TREE", "TREE COPY INFO");
654    aws->load_xfig("ad_tree_cmp.fig");
655
656    aws->callback(AW_POPDOWN);
657    aws->at("close");
658    aws->create_button("CLOSE", "CLOSE", "C");
659
660    aws->callback(AW_POPUP_HELP, (AW_CL)"tree_cmp.hlp");
661    aws->at("help");
662    aws->create_button("HELP", "HELP", "H");
663
664    root->awar_string(AWAR_TREE_NAME);
665    root->awar_string(AWAR_TREE_DEST);
666
667    aws->at("tree1");
668    awt_create_selection_list_on_trees(GLOBAL_gb_main, (AW_window *)aws, AWAR_TREE_NAME);
669    aws->at("tree2");
670    awt_create_selection_list_on_trees(GLOBAL_gb_main, (AW_window *)aws, AWAR_TREE_DEST);
671
672    aws->at("move");
673    aws->callback(ad_move_tree_info, 0); // move
674    aws->create_button("COPY_INFO", "COPY INFO");
675
676    aws->at("cmp");
677    aws->callback(ad_move_tree_info, 2); // add
678    aws->create_button("ADD_INFO", "ADD INFO");
679
680    aws->at("only_marked");
681    aws->label("only info containing marked species");
682    aws->create_toggle(AWAR_NODE_INFO_ONLY_MARKED);
683
684    return aws;
685}
686static void ad_tr_delete_cb(AW_window *aww) {
687    AW_awar *awar_tree = aww->get_root()->awar(AWAR_TREE_NAME);
688    char    *name      = awar_tree->read_string();
689
690    // 1. switch to next tree
691    {
692        GB_transaction ta(GLOBAL_gb_main);
693        char *newname = GBT_get_name_of_next_tree(GLOBAL_gb_main, name);
694
695        awar_tree->write_string(!newname || (strcmp(newname, name) == 0) ? "" : newname);
696        free(newname);
697    }
698
699    // 2. delete old tree
700    {
701        GB_ERROR  error   = GB_begin_transaction(GLOBAL_gb_main);
702        GBDATA   *gb_tree = GBT_get_tree(GLOBAL_gb_main, name);
703        if (gb_tree) {
704            char *newname = GBT_get_name_of_next_tree(GLOBAL_gb_main, name);
705            error = GB_delete(gb_tree);
706            if (!error && newname) {
707                awar_tree->write_string(strcmp(newname, name) == 0 ? "" : newname);
708            }
709            free(newname);
710        }
711        else {
712            error = "Please select a tree first";
713        }
714
715        error = GB_end_transaction(GLOBAL_gb_main, error);
716        if (error) {
717            aw_message(error);
718            awar_tree->write_string(name); // switch back to failed tree
719        }
720    }
721
722    free(name);
723}
724
725static void create_tree_last_window(AW_window *aww) {
726    GB_ERROR  error  = 0;
727    char     *source = aww->get_root()->awar(AWAR_TREE_NAME)->read_string();
728
729    GB_begin_transaction(GLOBAL_gb_main);
730
731    GBDATA *gb_tree_data = GB_search(GLOBAL_gb_main, "tree_data", GB_CREATE_CONTAINER);
732    GBDATA *gb_tree_name = GB_entry(gb_tree_data, source);
733
734    if (!gb_tree_name) {
735        error = GB_export_error("No tree selected.");
736    }
737    else {
738        GBDATA *gb_dest   = GB_create_container(gb_tree_data, source);
739        error             = GB_copy(gb_dest, gb_tree_name);
740        if (!error) error = GB_delete(gb_tree_name);
741    }
742
743    if (!error) GB_commit_transaction(GLOBAL_gb_main);
744    else GB_abort_transaction(GLOBAL_gb_main);
745
746    if (error) aw_message(error);
747
748    free(source);
749}
750
751static void move_tree_pos(AW_window *aww, AW_CL cl_offset) {
752    // moves the tree in the list of trees
753    int   offset = (int)cl_offset;
754
755    if (offset == 9999) {
756        create_tree_last_window(aww);
757    }
758    else {
759        aw_message("Not implemented yet.");
760        // @@@ FIXME: implement other cases
761    }
762}
763
764AW_window *create_trees_window(AW_root *aw_root) {
765    static AW_window_simple *aws = 0;
766    if (!aws) {
767        aws = new AW_window_simple;
768        aws->init(aw_root, "TREE_ADMIN", "TREE ADMIN");
769        aws->load_xfig("ad_tree.fig");
770
771        aws->callback(AW_POPDOWN);
772        aws->at("close");
773        aws->create_button("CLOSE", "CLOSE", "C");
774
775        aws->callback(AW_POPUP_HELP, (AW_CL)"treeadm.hlp");
776        aws->at("help");
777        aws->create_button("HELP", "HELP", "H");
778
779        aws->button_length(20);
780
781        aws->at("delete");
782        aws->callback(ad_tr_delete_cb);
783        aws->create_button("DELETE", "Delete", "D");
784
785        aws->at("rename");
786        aws->callback(AW_POPUP, (AW_CL)create_tree_rename_window, 0);
787        aws->create_button("RENAME", "Rename", "R");
788
789        aws->at("copy");
790        aws->callback(AW_POPUP, (AW_CL)create_tree_copy_window, 0);
791        aws->create_button("COPY", "Copy", "C");
792
793        aws->at("move");
794        aws->callback(AW_POPUP, (AW_CL)create_tree_cmp_window, 0);
795        aws->create_button("MOVE_NODE_INFO", "Move node info", "C");
796
797        aws->at("cmp");
798        aws->callback(AW_POPUP, (AW_CL)create_tree_diff_window, 0);
799        aws->sens_mask(AWM_EXP);
800        aws->create_button("CMP_TOPOLOGY", "Compare topology", "T");
801        aws->sens_mask(AWM_ALL);
802
803        aws->at("export");
804        aws->callback(AW_POPUP, (AW_CL)create_tree_export_window, 0);
805        aws->create_button("EXPORT", "Export", "E");
806
807        aws->at("import");
808        aws->callback(AW_POPUP, (AW_CL)create_tree_import_window, 0);
809        aws->create_button("IMPORT", "Import", "I");
810
811        aws->button_length(0);
812
813#if defined(DEBUG)
814#if defined(WARN_TODO)
815#warning implement tree move buttons
816#endif
817        aws->at("upall");
818        aws->callback(move_tree_pos, (AW_CL)-9999);
819        aws->create_button("moveUpAll", "#moveUpAll.bitmap", 0);
820
821        aws->at("up");
822        aws->callback(move_tree_pos, (AW_CL)-1);
823        aws->create_button("moveUp", "#moveUp.bitmap", 0);
824
825        aws->at("down");
826        aws->callback(move_tree_pos, (AW_CL)1);
827        aws->create_button("moveDown", "#moveDown.bitmap", 0);
828#endif // DEBUG
829
830        aws->at("downall");
831        aws->callback(move_tree_pos, (AW_CL)9999);
832        aws->create_button("moveDownAll", "#moveDownAll.bitmap", 0);
833
834
835        aws->at("list");
836        awt_create_selection_list_on_trees(GLOBAL_gb_main, (AW_window *)aws, AWAR_TREE_NAME);
837
838        aws->at("security");
839        aws->create_option_menu(AWAR_TREE_SECURITY);
840        aws->insert_option("0", "0", 0);
841        aws->insert_option("1", "1", 1);
842        aws->insert_option("2", "2", 2);
843        aws->insert_option("3", "3", 3);
844        aws->insert_option("4", "4", 4);
845        aws->insert_option("5", "5", 5);
846        aws->insert_default_option("6", "6", 6);
847        aws->update_option_menu();
848
849        aws->at("rem");
850        aws->create_text_field(AWAR_TREE_REM);
851    }
852
853    return (AW_window *)aws;
854}
Note: See TracBrowser for help on using the repository browser.