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

Last change on this file was 19691, checked in by westram, 2 weeks ago
  • reintegrates 'macros' into 'trunk'
    • fixes macro IDs for mergetool (completing #870).
      • most common problem:
        • several modules were reused (twice) for items of same type, but in different databases.
        • auto-generated IDs were identical.
  • adds: log:branches/macros@19667:19690
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 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 <arb_str.h>
19#include <cctype>
20#include <aw_msg.hxx>
21#include <arb_global_defs.h>
22#include <TreeAwars.hxx>
23
24#define ta_assert(cond) arb_assert(cond)
25
26#define AWAR_TREE_SOURCE "tmp/ad_tree/tree_source"
27#define AWAR_TREE_DEST   "tmp/ad_tree/tree_dest"
28
29namespace TreeAdmin {
30
31    void create_awars(AW_root *root, AW_default aw_def, bool registerTreeAwar) {
32        AW_awar *awar_srcTree = root->awar_string(AWAR_TREE_SOURCE, NULp, aw_def)->set_srt(SRT_AUTOCORRECT_TREENAME);
33        if (registerTreeAwar) AWT_registerTreeAwarSimple(awar_srcTree);
34        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)
35    }
36    AW_awar *source_tree_awar(AW_root *root) {
37        return root->awar(AWAR_TREE_SOURCE);
38    }
39    AW_awar *dest_tree_awar(AW_root *root) {
40        return root->awar(AWAR_TREE_DEST);
41    }
42
43    AW_awar *Spec::tree_awar(AW_root *awr) const {
44        return awr->awar(awar_selected_tree);
45    }
46
47    void delete_tree_cb(AW_window *aww, const Spec *spec) {
48        AW_awar    *awar_tree = spec->tree_awar(aww->get_root());
49        char       *name      = awar_tree->read_string();
50        GBDATA     *gb_main   = spec->get_gb_main();
51        GB_ERROR    error     = NULp;
52        GBDATA     *gb_tree;
53
54        // 1. TA: switch to next tree
55        {
56            GB_transaction ta(gb_main);
57            gb_tree = GBT_find_tree(gb_main, name);
58            if (!gb_tree) error = "Please select tree to delete";
59            else {
60                AWT_announce_tree_deleted(name);
61                GBDATA *gb_next = GBT_find_next_tree(gb_tree);
62                awar_tree->write_string(gb_next ? GBT_get_tree_name(gb_next) : NO_TREE_SELECTED);
63            }
64            error = ta.close(error);
65        }
66
67        // 2. TA: delete old tree
68        if (!error) {
69            GB_transaction ta(gb_main);
70            error = GB_delete(gb_tree);
71            error = ta.close(error);
72        }
73
74        if (error) {
75            aw_message(error);
76            awar_tree->write_string(name); // switch back to failed tree
77        }
78
79        free(name);
80    }
81
82    static GB_ERROR tree_append_remark(GBDATA *gb_tree, const char *add_to_remark) {
83        GB_ERROR  error       = NULp;
84        GBDATA   *gb_remark   = GB_search(gb_tree, "remark", GB_STRING);
85        if (!gb_remark) error = GB_await_error();
86        else {
87            char *old_remark       = GB_read_string(gb_remark);
88            if (!old_remark) error = GB_await_error();
89            else {
90                GBS_strstruct new_remark(2000);
91
92                new_remark.cat(old_remark);
93                new_remark.put('\n');
94                new_remark.cat(add_to_remark);
95
96                error = GB_write_string(gb_remark, new_remark.get_data());
97            }
98            free(old_remark);
99        }
100        return error;
101    }
102
103    static void tree_copy_or_rename_cb(AW_window *aww, bool do_copy, const Spec& spec) {
104        AW_root  *aw_root   = aww->get_root();
105        AW_awar  *awar_tree = spec.tree_awar(aw_root);
106        char     *source    = awar_tree->read_string();
107        char     *dest      = aw_root->awar(AWAR_TREE_DEST)->read_string();
108        GB_ERROR  error     = NULp;
109
110        if (!error && !dest[0]) error = "Please enter new tree name";
111        if (!error) {
112            GBDATA *gb_main = spec.get_gb_main();
113            error           = GB_begin_transaction(gb_main);
114            if (!error) {
115                if (do_copy) {
116                    error = GBT_copy_tree(gb_main, source, dest);
117                    if (!error) {
118                        GBDATA *gb_new_tree = GBT_find_tree(gb_main, dest);
119                        ta_assert(gb_new_tree);
120                        error = tree_append_remark(gb_new_tree, GBS_global_string("[created as copy of '%s']", source));
121                    }
122                }
123                else {
124                    error = GBT_rename_tree(gb_main, source, dest);
125                    if (!error) AWT_announce_tree_renamed(source, dest);
126                }
127            }
128
129            if (!error) awar_tree->write_string(dest);
130            error = GB_end_transaction(gb_main, error);
131        }
132
133        aww->hide_or_notify(error);
134
135        free(dest);
136        free(source);
137    }
138
139    static void tree_rename_cb(AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, false, *spec); }
140    static void tree_copy_cb  (AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, true, *spec);  }
141
142    static void current_as_dest_treename_cb(AW_window *aww, const Spec *spec) {
143        AW_root    *awr  = aww->get_root();
144        dest_tree_awar(awr)->write_string(spec->tree_awar(awr)->read_char_pntr());
145    }
146
147    static void make_dest_treename_unique_cb(AW_window *aww, const Spec *spec) {
148        // generated a unique treename
149        AW_root *awr       = aww->get_root();
150        AW_awar *awar_dest = awr->awar(AWAR_TREE_DEST);
151
152        char *name = awar_dest->read_string();
153        int   len  = strlen(name);
154
155        for (int p = len-1; p >= 0; --p) {
156            bool auto_modified = isdigit(name[p]) || name[p] == '_';
157            if (!auto_modified) break;
158            name[p] = 0;
159        }
160
161        {
162            GBDATA         *gb_main = spec->get_gb_main();
163            GB_transaction  ta(gb_main);
164
165            if (!GBT_find_tree(gb_main, name)) {
166                awar_dest->write_string("");
167                awar_dest->write_string(name);
168            }
169            else {
170                for (int i = 2; ; i++) {
171                    const char *testName = GBS_global_string("%s_%i", name, i);
172                    if (!GBT_find_tree(gb_main, testName)) { // found unique name
173                        awar_dest->write_string(testName);
174                        break;
175                    }
176                }
177            }
178        }
179
180        free(name);
181    }
182
183    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) {
184        AW_window_simple *aws = new AW_window_simple;
185        aws->init(root, win_id, win_title);
186
187        aws->at(10, 10);
188        aws->auto_space(10, 10);
189
190        aws->at_newline();
191        aws->label("Current:");
192        aws->callback(makeWindowCallback(current_as_dest_treename_cb, spec));
193        aws->at_attach_to(true, false, -10, 25);
194        aws->create_button("use_current", spec->tree_awar(aws->get_root())->awar_name);
195
196        aws->at_newline();
197        aws->label("New:    ");
198        aws->at_attach_to(true, false, -10, 30);
199        aws->create_input_field(AWAR_TREE_DEST);
200
201        aws->at_newline();
202        aws->callback(makeWindowCallback(go_cb, spec));
203        aws->create_autosize_button("GO", go_label, "");
204
205        aws->callback(AW_POPDOWN);
206        aws->create_autosize_button("CLOSE", "Abort", "A");
207
208        aws->callback(makeWindowCallback(make_dest_treename_unique_cb, spec));
209        aws->create_autosize_button("UNIQUE", "Unique name", "U");
210
211        aws->at_newline();
212
213        return aws;
214    }
215
216
217    AW_window *create_rename_window(AW_root *root, const Spec *spec, const char *specialized) {
218        AW_window  *aww;
219        const char *button_label = "Rename Tree";
220        if (specialized[0]) { // non-empty -> create specialized rename window which may be used twice from same parent window
221            char *id    = ARB_strupper(GBS_global_string_copy("RENAME_%s_TREE", specialized));
222            char *title = GBS_global_string_copy("Rename %s tree", specialized);
223            aww         = create_copy_or_rename_window(root, id, title, button_label, tree_rename_cb, spec);
224            free(title);
225            free(id);
226        }
227        else {
228            aww = create_copy_or_rename_window(root, "RENAME_TREE", "Rename tree", button_label, tree_rename_cb, spec);
229        }
230        return aww;
231    }
232    AW_window *create_copy_window(AW_root *root, const Spec *spec) {
233        return create_copy_or_rename_window(root, "COPY_TREE",   "Copy Tree",   "Copy Tree",   tree_copy_cb, spec);
234    }
235
236
237};
238
Note: See TracBrowser for help on using the repository browser.