source: branches/stable/SL/TREE_ADMIN/TreeAdmin.cxx

Last change on this file was 17160, checked in by westram, 6 years ago
  • reintegrates 'group' into 'trunk'
    • misc. cleanup:
      • group related functions now all accessible via menu of 1st ntree window
      • DRY selection of 2 trees
      • warn if annotated tree isnt visible
      • fix mnemonics
      • fix error handling (compare taxonomy)
      • unittest comments added to tree remarks
      • names
  • adds: log:branches/group@17139:17159
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.2 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : TreeAdmin.cxx                                   //
4//   Purpose   : Common tree admin functionality                 //
5//                                                               //
6//   Coded by Ralf Westram (coder@reallysoft.de) in April 2012   //
7//   Institute of Microbiology (Technical University Munich)     //
8//   http://www.arb-home.de/                                     //
9//                                                               //
10// ============================================================= //
11
12#include "TreeAdmin.h"
13#include <aw_window.hxx>
14#include <aw_root.hxx>
15#include <aw_awar.hxx>
16#include <arbdbt.h>
17#include <arb_strbuf.h>
18#include <cctype>
19#include <aw_msg.hxx>
20#include <arb_global_defs.h>
21#include <awt_TreeAwars.hxx>
22
23#define ta_assert(cond) arb_assert(cond)
24
25#define AWAR_TREE_SOURCE "tmp/ad_tree/tree_source"
26#define AWAR_TREE_DEST   "tmp/ad_tree/tree_dest"
27
28namespace TreeAdmin {
29
30    void create_awars(AW_root *root, AW_default aw_def, bool registerTreeAwar) {
31        AW_awar *awar_srcTree = root->awar_string(AWAR_TREE_SOURCE, NULp, aw_def)->set_srt(SRT_AUTOCORRECT_TREENAME);
32        if (registerTreeAwar) AWT_registerTreeAwarSimple(awar_srcTree);
33        root->awar_string(AWAR_TREE_DEST, NULp, aw_def)->set_srt(SRT_AUTOCORRECT_TREENAME); // no need to register (awar also used for 'new name' in renames via GUI)
34    }
35    AW_awar *source_tree_awar(AW_root *root) {
36        return root->awar(AWAR_TREE_SOURCE);
37    }
38    AW_awar *dest_tree_awar(AW_root *root) {
39        return root->awar(AWAR_TREE_DEST);
40    }
41
42    AW_awar *Spec::tree_awar(AW_root *awr) const {
43        return awr->awar(awar_selected_tree);
44    }
45
46    void delete_tree_cb(AW_window *aww, const Spec *spec) {
47        AW_awar    *awar_tree = spec->tree_awar(aww->get_root());
48        char       *name      = awar_tree->read_string();
49        GBDATA     *gb_main   = spec->get_gb_main();
50        GB_ERROR    error     = NULp;
51        GBDATA     *gb_tree;
52
53        // 1. TA: switch to next tree
54        {
55            GB_transaction ta(gb_main);
56            gb_tree = GBT_find_tree(gb_main, name);
57            if (!gb_tree) error = "Please select tree to delete";
58            else {
59                AWT_announce_tree_deleted(name);
60                GBDATA *gb_next = GBT_find_next_tree(gb_tree);
61                awar_tree->write_string(gb_next ? GBT_get_tree_name(gb_next) : NO_TREE_SELECTED);
62            }
63            error = ta.close(error);
64        }
65
66        // 2. TA: delete old tree
67        if (!error) {
68            GB_transaction ta(gb_main);
69            error = GB_delete(gb_tree);
70            error = ta.close(error);
71        }
72
73        if (error) {
74            aw_message(error);
75            awar_tree->write_string(name); // switch back to failed tree
76        }
77
78        free(name);
79    }
80   
81    static GB_ERROR tree_append_remark(GBDATA *gb_tree, const char *add_to_remark) {
82        GB_ERROR  error       = NULp;
83        GBDATA   *gb_remark   = GB_search(gb_tree, "remark", GB_STRING);
84        if (!gb_remark) error = GB_await_error();
85        else {
86            char *old_remark       = GB_read_string(gb_remark);
87            if (!old_remark) error = GB_await_error();
88            else {
89                GBS_strstruct *new_remark = GBS_stropen(2000);
90
91                GBS_strcat(new_remark, old_remark);
92                GBS_chrcat(new_remark, '\n');
93                GBS_strcat(new_remark, add_to_remark);
94
95                error = GB_write_string(gb_remark, GBS_mempntr(new_remark));
96
97                GBS_strforget(new_remark);
98            }
99            free(old_remark);
100        }
101        return error;
102    }
103
104    static void tree_copy_or_rename_cb(AW_window *aww, bool do_copy, const Spec& spec) {
105        AW_root  *aw_root   = aww->get_root();
106        AW_awar  *awar_tree = spec.tree_awar(aw_root);
107        char     *source    = awar_tree->read_string();
108        char     *dest      = aw_root->awar(AWAR_TREE_DEST)->read_string();
109        GB_ERROR  error     = NULp;
110
111        if (!error && !dest[0]) error = "Please enter new tree name";
112        if (!error) {
113            GBDATA *gb_main = spec.get_gb_main();
114            error           = GB_begin_transaction(gb_main);
115            if (!error) {
116                if (do_copy) {
117                    error = GBT_copy_tree(gb_main, source, dest);
118                    if (!error) {
119                        GBDATA *gb_new_tree = GBT_find_tree(gb_main, dest);
120                        ta_assert(gb_new_tree);
121                        error = tree_append_remark(gb_new_tree, GBS_global_string("[created as copy of '%s']", source));
122                    }
123                }
124                else {
125                    error = GBT_rename_tree(gb_main, source, dest);
126                    if (!error) AWT_announce_tree_renamed(source, dest);
127                }
128            }
129
130            if (!error) awar_tree->write_string(dest);
131            error = GB_end_transaction(gb_main, error);
132        }
133
134        aww->hide_or_notify(error);
135
136        free(dest);
137        free(source);
138    }
139
140    static void tree_rename_cb(AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, false, *spec); }
141    static void tree_copy_cb  (AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, true, *spec);  }
142
143    static void current_as_dest_treename_cb(AW_window *aww, const Spec *spec) {
144        AW_root    *awr  = aww->get_root();
145        dest_tree_awar(awr)->write_string(spec->tree_awar(awr)->read_char_pntr());
146    }
147
148    static void make_dest_treename_unique_cb(AW_window *aww, const Spec *spec) {
149        // generated a unique treename
150        AW_root *awr       = aww->get_root();
151        AW_awar *awar_dest = awr->awar(AWAR_TREE_DEST);
152
153        char *name = awar_dest->read_string();
154        int   len  = strlen(name);
155
156        for (int p = len-1; p >= 0; --p) {
157            bool auto_modified = isdigit(name[p]) || name[p] == '_';
158            if (!auto_modified) break;
159            name[p] = 0;
160        }
161
162        {
163            GBDATA         *gb_main = spec->get_gb_main();
164            GB_transaction  ta(gb_main);
165
166            if (!GBT_find_tree(gb_main, name)) {
167                awar_dest->write_string("");
168                awar_dest->write_string(name);
169            }
170            else {
171                for (int i = 2; ; i++) {
172                    const char *testName = GBS_global_string("%s_%i", name, i);
173                    if (!GBT_find_tree(gb_main, testName)) { // found unique name
174                        awar_dest->write_string(testName);
175                        break;
176                    }
177                }
178            }
179        }
180
181        free(name);
182    }
183
184    static AW_window *create_copy_or_rename_window(AW_root *root, const char *win_id, const char *win_title, const char *go_label, void (*go_cb)(AW_window*, const Spec*), const Spec *spec) {
185        AW_window_simple *aws = new AW_window_simple;
186        aws->init(root, win_id, win_title);
187
188        aws->at(10, 10);
189        aws->auto_space(10, 10);
190
191        aws->at_newline();
192        aws->label("Current:");
193        aws->callback(makeWindowCallback(current_as_dest_treename_cb, spec));
194        aws->at_attach_to(true, false, -10, 25);
195        aws->create_button("use_current", spec->tree_awar(aws->get_root())->awar_name);
196
197        aws->at_newline();
198        aws->label("New:    ");
199        aws->at_attach_to(true, false, -10, 30);
200        aws->create_input_field(AWAR_TREE_DEST);
201
202        aws->at_newline();
203        aws->callback(makeWindowCallback(go_cb, spec));
204        aws->create_autosize_button("GO", go_label, "");
205
206        aws->callback(AW_POPDOWN);
207        aws->create_autosize_button("CLOSE", "Abort", "A");
208
209        aws->callback(makeWindowCallback(make_dest_treename_unique_cb, spec));
210        aws->create_autosize_button("UNIQUE", "Unique name", "U");
211   
212        aws->at_newline();
213
214        return aws;
215    }
216
217   
218    AW_window *create_rename_window(AW_root *root, const Spec *spec) {
219        return create_copy_or_rename_window(root, "RENAME_TREE", "Rename Tree", "Rename Tree", tree_rename_cb, spec);
220    }
221    AW_window *create_copy_window(AW_root *root, const Spec *spec) {
222        return create_copy_or_rename_window(root, "COPY_TREE",   "Copy Tree",   "Copy Tree",   tree_copy_cb, spec);
223    }
224
225   
226};
227
Note: See TracBrowser for help on using the repository browser.