source: trunk/SL/TREE_ADMIN/TreeAdmin.cxx

Last change on this file was 19339, checked in by westram, 2 years ago
  • reintegrates 'refactor' into 'trunk'
    • eliminates old interface of GBS_strstruct
    • add a few new unittests (editor-config string + some PT-SERVER-functions)
  • adds: log:branches/refactor@19300:19338
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 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(2000);
90
91                new_remark.cat(old_remark);
92                new_remark.put('\n');
93                new_remark.cat(add_to_remark);
94
95                error = GB_write_string(gb_remark, new_remark.get_data());
96            }
97            free(old_remark);
98        }
99        return error;
100    }
101
102    static void tree_copy_or_rename_cb(AW_window *aww, bool do_copy, const Spec& spec) {
103        AW_root  *aw_root   = aww->get_root();
104        AW_awar  *awar_tree = spec.tree_awar(aw_root);
105        char     *source    = awar_tree->read_string();
106        char     *dest      = aw_root->awar(AWAR_TREE_DEST)->read_string();
107        GB_ERROR  error     = NULp;
108
109        if (!error && !dest[0]) error = "Please enter new tree name";
110        if (!error) {
111            GBDATA *gb_main = spec.get_gb_main();
112            error           = GB_begin_transaction(gb_main);
113            if (!error) {
114                if (do_copy) {
115                    error = GBT_copy_tree(gb_main, source, dest);
116                    if (!error) {
117                        GBDATA *gb_new_tree = GBT_find_tree(gb_main, dest);
118                        ta_assert(gb_new_tree);
119                        error = tree_append_remark(gb_new_tree, GBS_global_string("[created as copy of '%s']", source));
120                    }
121                }
122                else {
123                    error = GBT_rename_tree(gb_main, source, dest);
124                    if (!error) AWT_announce_tree_renamed(source, dest);
125                }
126            }
127
128            if (!error) awar_tree->write_string(dest);
129            error = GB_end_transaction(gb_main, error);
130        }
131
132        aww->hide_or_notify(error);
133
134        free(dest);
135        free(source);
136    }
137
138    static void tree_rename_cb(AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, false, *spec); }
139    static void tree_copy_cb  (AW_window *aww, const Spec *spec) { tree_copy_or_rename_cb(aww, true, *spec);  }
140
141    static void current_as_dest_treename_cb(AW_window *aww, const Spec *spec) {
142        AW_root    *awr  = aww->get_root();
143        dest_tree_awar(awr)->write_string(spec->tree_awar(awr)->read_char_pntr());
144    }
145
146    static void make_dest_treename_unique_cb(AW_window *aww, const Spec *spec) {
147        // generated a unique treename
148        AW_root *awr       = aww->get_root();
149        AW_awar *awar_dest = awr->awar(AWAR_TREE_DEST);
150
151        char *name = awar_dest->read_string();
152        int   len  = strlen(name);
153
154        for (int p = len-1; p >= 0; --p) {
155            bool auto_modified = isdigit(name[p]) || name[p] == '_';
156            if (!auto_modified) break;
157            name[p] = 0;
158        }
159
160        {
161            GBDATA         *gb_main = spec->get_gb_main();
162            GB_transaction  ta(gb_main);
163
164            if (!GBT_find_tree(gb_main, name)) {
165                awar_dest->write_string("");
166                awar_dest->write_string(name);
167            }
168            else {
169                for (int i = 2; ; i++) {
170                    const char *testName = GBS_global_string("%s_%i", name, i);
171                    if (!GBT_find_tree(gb_main, testName)) { // found unique name
172                        awar_dest->write_string(testName);
173                        break;
174                    }
175                }
176            }
177        }
178
179        free(name);
180    }
181
182    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) {
183        AW_window_simple *aws = new AW_window_simple;
184        aws->init(root, win_id, win_title);
185
186        aws->at(10, 10);
187        aws->auto_space(10, 10);
188
189        aws->at_newline();
190        aws->label("Current:");
191        aws->callback(makeWindowCallback(current_as_dest_treename_cb, spec));
192        aws->at_attach_to(true, false, -10, 25);
193        aws->create_button("use_current", spec->tree_awar(aws->get_root())->awar_name);
194
195        aws->at_newline();
196        aws->label("New:    ");
197        aws->at_attach_to(true, false, -10, 30);
198        aws->create_input_field(AWAR_TREE_DEST);
199
200        aws->at_newline();
201        aws->callback(makeWindowCallback(go_cb, spec));
202        aws->create_autosize_button("GO", go_label, "");
203
204        aws->callback(AW_POPDOWN);
205        aws->create_autosize_button("CLOSE", "Abort", "A");
206
207        aws->callback(makeWindowCallback(make_dest_treename_unique_cb, spec));
208        aws->create_autosize_button("UNIQUE", "Unique name", "U");
209
210        aws->at_newline();
211
212        return aws;
213    }
214
215
216    AW_window *create_rename_window(AW_root *root, const Spec *spec) {
217        return create_copy_or_rename_window(root, "RENAME_TREE", "Rename Tree", "Rename Tree", tree_rename_cb, spec);
218    }
219    AW_window *create_copy_window(AW_root *root, const Spec *spec) {
220        return create_copy_or_rename_window(root, "COPY_TREE",   "Copy Tree",   "Copy Tree",   tree_copy_cb, spec);
221    }
222
223
224};
225
Note: See TracBrowser for help on using the repository browser.