source: branches/tree/MERGE/MG_trees.cxx

Last change on this file was 18732, checked in by westram, 3 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : MG_trees.cxx                                      //
4//   Purpose   : Merge trees between databases                     //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "merge.hxx"
12#include <TreeAdmin.h>
13#include <awt_sel_boxes.hxx>
14#include <aw_root.hxx>
15#include <aw_awar.hxx>
16#include <aw_msg.hxx>
17#include <arbdbt.h>
18#include <arb_global_defs.h>
19
20#define AWAR_TREE_NAME_SRC AWAR_MERGE_TMP_SRC "tree_name"
21#define AWAR_TREE_NAME_DST AWAR_MERGE_TMP_DST "tree_name"
22
23#define AWAR_TREE_XFER_WHAT AWAR_MERGE_TMP "xfer_what"
24#define AWAR_TREE_OVERWRITE AWAR_MERGE_TMP "overwrite"
25
26enum TREE_XFER_MODE {
27    XFER_SELECTED,
28    XFER_ALL,
29    XFER_MISSING,
30    XFER_EXISTING,
31};
32
33void MG_create_trees_awar(AW_root *aw_root, AW_default aw_def) {
34    aw_root->awar_string(AWAR_TREE_NAME_SRC, NO_TREE_SELECTED, aw_def);
35    aw_root->awar_string(AWAR_TREE_NAME_DST, NO_TREE_SELECTED, aw_def);
36
37    aw_root->awar_int(AWAR_TREE_XFER_WHAT, XFER_SELECTED, aw_def);
38    aw_root->awar_int(AWAR_TREE_OVERWRITE, 0,             aw_def);
39
40    TreeAdmin::create_awars(aw_root, aw_def, false);
41}
42
43static GB_ERROR transfer_tree(const char *tree_name, bool overwrite, const char *behind_name) {
44    // transfer tree 'tree_name' from DB1->DB2.
45    //
46    // if 'overwrite' is true and tree already exists, overwrite tree w/o changing its position.
47    //
48    // if tree does not exist, insert it behind tree 'behind_name'.
49    // if tree 'behind_name' does not exist or if 'behind_name' is NULp, insert at end.
50
51
52    GB_ERROR  error   = NULp;
53    GBDATA   *gb_tree = GBT_find_tree(GLOBAL_gb_src, tree_name);
54    if (!gb_tree) {
55        if (strcmp(tree_name, NO_TREE_SELECTED) == 0) {
56            error = "No tree selected in source DB";
57        }
58        else {
59            error = GBS_global_string("No tree '%s' in source DB", tree_name);
60        }
61    }
62    else {
63        GBDATA         *gb_at_tree = NULp;
64        GBT_ORDER_MODE  next_to    = GBT_BEHIND;
65
66        if (behind_name && strcmp(behind_name, NO_TREE_SELECTED) != 0) {
67            gb_at_tree = GBT_find_tree(GLOBAL_gb_dst, behind_name);
68            if (!gb_at_tree) {
69                error = GBS_global_string("Can't position tree behind '%s' (no such tree)", behind_name);
70            }
71        }
72
73        if (!error) {
74            GBDATA *gb_dest_tree = GBT_find_tree(GLOBAL_gb_dst, tree_name);
75            if (gb_dest_tree)  {
76                if (!overwrite) {
77                    error = GBS_global_string("Tree '%s' already exists in destination DB", tree_name);
78                }
79                else {
80                    // keep position of existing tree
81                    GBDATA *gb_tree_infrontof = GBT_tree_infrontof(gb_dest_tree);
82                    if (gb_tree_infrontof) {
83                        next_to    = GBT_BEHIND;
84                        gb_at_tree = gb_tree_infrontof;
85                    }
86                    else {
87                        GBDATA *gb_tree_behind = GBT_tree_behind(gb_dest_tree);
88                        next_to    = GBT_INFRONTOF;
89                        gb_at_tree = gb_tree_behind;
90                    }
91
92                    error = GB_delete(gb_dest_tree);
93                }
94            }
95        }
96
97        if (!error) {
98            GBDATA *gb_dest_tree_data     = GBT_get_tree_data(GLOBAL_gb_dst);
99            if (!gb_dest_tree_data) error = GB_await_error();
100            else {
101                GBDATA *gb_dest_tree     = GB_create_container(gb_dest_tree_data, tree_name);
102                if (!gb_dest_tree) error = GB_await_error();
103                else {
104                    error = GB_copy_dropProtectMarksAndTempstate(gb_dest_tree, gb_tree);
105                    if (!error) {
106                        if (!gb_at_tree) {
107                            gb_at_tree = GBT_find_bottom_tree(GLOBAL_gb_dst);
108                            next_to    = GBT_BEHIND;
109                        }
110                        if (gb_at_tree) {
111                            error = GBT_move_tree(gb_dest_tree, next_to, gb_at_tree);
112                        }
113                    }
114                }
115            }
116        }
117    }
118    return error;
119}
120
121static void MG_transfer_tree(AW_window *aww) {
122    AW_root *awr = aww->get_root();
123
124    TREE_XFER_MODE what = (TREE_XFER_MODE)awr->awar(AWAR_TREE_XFER_WHAT)->read_int();
125
126    AW_awar *awar_tree_source = awr->awar(AWAR_TREE_NAME_SRC);
127    AW_awar *awar_tree_dest   = awr->awar(AWAR_TREE_NAME_DST);
128
129    bool overwrite = awr->awar(AWAR_TREE_OVERWRITE)->read_int();
130
131    char *source_name = awar_tree_source->read_string();
132    char *behind_name = awar_tree_dest->read_string();
133
134    char *select_dst = NULp;
135
136    GB_ERROR error    = GB_begin_transaction(GLOBAL_gb_dst);
137    if (!error) error = GB_begin_transaction(GLOBAL_gb_src);
138
139    int xferd_missing  = 0;
140    int xferd_existing = 0;
141
142    if (!error) {
143        switch (what) {
144            case XFER_SELECTED:
145                error = transfer_tree(source_name, overwrite, behind_name);
146                if (!error) select_dst = ARB_strdup(source_name);
147                break;
148
149            case XFER_ALL:
150            case XFER_EXISTING:
151                for (GBDATA *gb_tree = GBT_find_top_tree(GLOBAL_gb_src); gb_tree && !error; gb_tree = GBT_tree_behind(gb_tree)) {
152                    const char *tree_name = GBT_get_tree_name(gb_tree);
153                    GBDATA     *gb_exists = GBT_find_tree(GLOBAL_gb_dst, tree_name);
154
155                    if (gb_exists) {
156                        xferd_existing++;
157                        error = transfer_tree(tree_name, overwrite, NULp);
158                    }
159                }
160                if (what == XFER_EXISTING) break;
161                FALLTHROUGH; // for XFER_ALL
162            case XFER_MISSING:
163                for (GBDATA *gb_tree = GBT_find_top_tree(GLOBAL_gb_src); gb_tree && !error; gb_tree = GBT_tree_behind(gb_tree)) {
164                    const char *tree_name = GBT_get_tree_name(gb_tree);
165                    GBDATA     *gb_exists = GBT_find_tree(GLOBAL_gb_dst, tree_name);
166
167                    if (!gb_exists) {
168                        error = transfer_tree(tree_name, false, behind_name);
169                        xferd_missing++;
170                        if (!select_dst) select_dst = ARB_strdup(tree_name); // select first missing in dest box
171                        freedup(behind_name, tree_name);
172                    }
173                }
174                break;
175        }
176    }
177
178    error = GB_end_transaction(GLOBAL_gb_dst, error);
179    GB_end_transaction_show_error(GLOBAL_gb_src, error, aw_message);
180
181    if (!error) {
182        if (select_dst) awar_tree_dest->write_string(select_dst);
183
184        if (what == XFER_SELECTED) {
185            GB_transaction  ta(GLOBAL_gb_src);
186            GBDATA         *gb_next = GBT_find_next_tree(GBT_find_tree(GLOBAL_gb_src, source_name));
187            awar_tree_source->write_string(gb_next ? GBT_get_tree_name(gb_next) : NO_TREE_SELECTED);
188        }
189
190        if (xferd_existing) {
191            if (xferd_missing) aw_message(GBS_global_string("Transferred %i existing and %i missing trees", xferd_existing, xferd_missing));
192            else aw_message(GBS_global_string("Transferred %i existing trees", xferd_existing));
193        }
194        else {
195            if (xferd_missing) aw_message(GBS_global_string("Transferred %i missing trees", xferd_missing));
196            else {
197                if (what != XFER_SELECTED) aw_message("No trees have been transferred");
198            }
199        }
200    }
201
202    free(select_dst);
203    free(behind_name);
204    free(source_name);
205}
206
207AW_window *MG_create_merge_trees_window(AW_root *awr) {
208    GB_ERROR error = MG_expect_renamed();
209    if (error) {
210        aw_message(error);
211        return NULp; // deny to open window before user has renamed species
212    }
213
214    AW_window_simple *aws = new AW_window_simple;
215
216    aws->init(awr, "MERGE_TREES", "MERGE TREES");
217    aws->load_xfig("merge/trees.fig");
218
219    aws->button_length(7);
220
221    aws->at("close");
222    aws->callback(AW_POPDOWN);
223    aws->create_button("CLOSE", "CLOSE", "C");
224
225    aws->at("help");
226    aws->callback(makeHelpCallback("mg_trees.hlp"));
227    aws->create_button("HELP", "HELP", "H");
228
229    aws->at("trees1");
230    awt_create_TREE_selection_list(GLOBAL_gb_src, aws, AWAR_TREE_NAME_SRC, true);
231
232    aws->at("trees2");
233    awt_create_TREE_selection_list(GLOBAL_gb_dst, aws, AWAR_TREE_NAME_DST, true);
234
235    static TreeAdmin::Spec src_spec(GLOBAL_gb_src, AWAR_TREE_NAME_SRC);
236    static TreeAdmin::Spec dst_spec(GLOBAL_gb_dst,  AWAR_TREE_NAME_DST);
237
238    aws->button_length(15);
239
240    aws->at("delete1");
241    aws->callback(makeWindowCallback(TreeAdmin::delete_tree_cb, &src_spec));
242    aws->create_button("DELETE TREE_DB1", "Delete Tree");
243
244    aws->at("delete2");
245    aws->callback(makeWindowCallback(TreeAdmin::delete_tree_cb, &dst_spec));
246    aws->create_button("DELETE_TREE_DB2", "Delete Tree");
247
248    aws->at("rename1");
249    aws->callback(makeCreateWindowCallback(TreeAdmin::create_rename_window, &src_spec));
250    aws->create_button("RENAME_TREE_DB1", "Rename Tree");
251
252    aws->at("rename2");
253    aws->callback(makeCreateWindowCallback(TreeAdmin::create_rename_window, &dst_spec));
254    aws->create_button("RENAME_TREE_DB2", "Rename Tree");
255
256    aws->at("transfer");
257    aws->callback(MG_transfer_tree);
258    aws->create_autosize_button("TRANSFER_TREE", "Transfer");
259
260    aws->at("xfer_what");
261    aws->create_option_menu(AWAR_TREE_XFER_WHAT, true);
262    aws->insert_default_option("selected tree",  "s", XFER_SELECTED);
263    aws->insert_option        ("all trees",      "a", XFER_ALL);
264    aws->insert_option        ("missing trees",  "m", XFER_MISSING);
265    aws->insert_option        ("existing trees", "e", XFER_EXISTING);
266    aws->update_option_menu();
267
268    aws->at("overwrite");
269    aws->label("Overwrite trees?");
270    aws->create_toggle(AWAR_TREE_OVERWRITE);
271
272    aws->button_length(0);
273    aws->shadow_width(1);
274    aws->at("icon");
275    aws->callback(makeHelpCallback("mg_trees.hlp"));
276    aws->create_button("HELP_MERGE", "#merge/icon.xpm");
277
278    return aws;
279}
280
Note: See TracBrowser for help on using the repository browser.