source: tags/arb_5.5/NTREE/NT_main.cxx

Last change on this file was 6143, checked in by westram, 15 years ago
  • backport [6141] (parts changing code, but only strings and comments)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.3 KB
Line 
1#include <string.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <arbdb.h>
5#include <arbdbt.h>
6#include <adGene.h>
7
8#include <servercntrl.h>
9#include <aw_root.hxx>
10#include <aw_device.hxx>
11#include <aw_window.hxx>
12#include <aw_awars.hxx>
13#include <aw_question.hxx>
14#include <aw_global.hxx>
15#include <awt_canvas.hxx>
16#include <awt_advice.hxx>
17
18#include <awt_tree.hxx>
19#include <awt_dtree.hxx>
20#include <awt.hxx>
21#include <awti_import.hxx>
22
23#include <mg_merge.hxx>
24
25#include "nt_internal.h"
26#include "ntree.hxx"
27#include "nt_cb.hxx"
28#include "NT_dbrepair.hxx"
29
30#include <arb_version.h>
31
32using namespace std;
33
34AW_HEADER_MAIN
35
36#define nt_assert(bed) arb_assert(bed)
37
38#define NT_SERVE_DB_TIMER 50
39#define NT_CHECK_DB_TIMER 200
40
41GBDATA *GLOBAL_gb_main;                             // global gb_main for arb_ntree
42NT_global GLOBAL_NT = { 0, 0, 0, false };
43
44// NT_format_all_alignments may be called after any operation which causes
45// unformatted alignments (e.g importing sequences)
46//
47// It tests all alignments whether they need to be formatted
48// and asks the user if they should be formatted.
49
50GB_ERROR NT_format_all_alignments(GBDATA *gb_main) {
51    GB_ERROR err = 0;
52    GB_push_transaction(gb_main);
53    GB_push_my_security(gb_main);
54
55    aw_status("Checking alignments");
56    err = GBT_check_data(gb_main, 0);
57
58    AW_repeated_question  question;
59    GBDATA               *gb_presets = GB_entry(gb_main,"presets");
60
61    question.add_help("prompt/format_alignments.hlp");
62
63    for (GBDATA *gb_ali = GB_entry(gb_presets,"alignment"); gb_ali && !err; gb_ali = GB_nextEntry(gb_ali)) {
64        GBDATA *gb_aligned = GB_search(gb_ali, "aligned", GB_INT);
65
66        if (GB_read_int(gb_aligned) == 0) { // sequences in alignment are not formatted
67            enum FormatAction {
68                FA_ASK_USER   = 0, // ask user
69                FA_FORMAT_ALL = 1, // format automatically w/o asking
70                FA_SKIP_ALL   = 2, // skip automatically w/o asking
71            };
72            FormatAction  format_action = FA_ASK_USER;
73            GBDATA       *gb_ali_name   = GB_entry(gb_ali,"alignment_name");
74            const char   *ali_name      = GB_read_char_pntr(gb_ali_name);
75
76            {
77                bool    is_ali_genom   = strcmp(ali_name, GENOM_ALIGNMENT) == 0;
78                GBDATA *gb_auto_format = GB_entry(gb_ali, "auto_format");
79
80                if (gb_auto_format) {
81                    format_action = FormatAction(GB_read_int(gb_auto_format));
82                    if (is_ali_genom) {
83                        if (format_action != FA_SKIP_ALL) {
84                            format_action = FA_SKIP_ALL; // always skip ali_genom
85                            err           = GB_write_int(gb_auto_format, FA_SKIP_ALL);
86                        }
87                    }
88                }
89                else if (is_ali_genom) {
90                    format_action = FA_SKIP_ALL;
91                    err           = GBT_write_int(gb_ali, "auto_format", FA_SKIP_ALL);  // always skip
92                }
93            }
94
95            bool perform_format = false;
96            if (!err) {
97                switch (format_action) {
98                    case FA_FORMAT_ALL: perform_format = true; break;
99                    case FA_SKIP_ALL:   perform_format = false; break;
100                    default: {
101                        char *qtext  = GBS_global_string_copy("Alignment '%s' is not formatted. Format?", ali_name);
102                        int   answer = question.get_answer(qtext, "Format,Skip,Always format,Always skip", "all", false);
103
104                        switch (answer) {
105                            case 2:
106                                err = GBT_write_int(gb_ali, "auto_format", FA_FORMAT_ALL);
107                                // fall-through
108                            case 0:
109                                perform_format = true;
110                                break;
111
112                            case 3:
113                                err = GBT_write_int(gb_ali, "auto_format", FA_SKIP_ALL);
114                                break;
115                        }
116
117                        free(qtext);
118                        break;
119                    }
120                }
121            }
122            if (!err && perform_format) {
123                aw_status(GBS_global_string("Formatting '%s'", ali_name));
124                GB_push_my_security(gb_main);
125                err = GBT_format_alignment(gb_main, ali_name);
126                GB_pop_my_security(gb_main);
127            }
128        }
129    }
130
131    GB_pop_my_security(gb_main);
132
133    return GB_end_transaction(gb_main, err);
134}
135
136
137// --------------------------------------------------------------------------------
138
139
140
141// called once on ARB_NTREE startup
142//
143static GB_ERROR nt_check_database_consistency() {
144    aw_openstatus("Checking database...");
145
146    GB_ERROR err = NT_format_all_alignments(GLOBAL_gb_main);
147    if (!err) err = NT_repair_DB(GLOBAL_gb_main);
148
149    aw_closestatus();
150    return err;
151}
152
153
154void serve_db_interrupt(AW_root *awr){
155    GB_BOOL succes = GBCMS_accept_calls(GLOBAL_gb_main,GB_FALSE);
156    while (succes){
157        awr->check_for_remote_command((AW_default)GLOBAL_gb_main,AWAR_NT_REMOTE_BASE);
158        succes = GBCMS_accept_calls(GLOBAL_gb_main,GB_TRUE);
159    }
160
161    awr->add_timed_callback(NT_SERVE_DB_TIMER,(AW_RCB)serve_db_interrupt,0,0);
162}
163
164void check_db_interrupt(AW_root *awr){
165    awr->check_for_remote_command((AW_default)GLOBAL_gb_main,AWAR_NT_REMOTE_BASE);
166    awr->add_timed_callback(NT_CHECK_DB_TIMER,(AW_RCB)check_db_interrupt,0,0);
167}
168
169GB_ERROR create_nt_window(AW_root *aw_root){
170    AW_window *aww;
171    GB_ERROR error = GB_request_undo_type(GLOBAL_gb_main, GB_UNDO_NONE);
172    if (error) aw_message(error);
173    nt_create_all_awars(aw_root,AW_ROOT_DEFAULT);
174    aww = create_nt_main_window(aw_root,0);
175    aww->show();
176    error = GB_request_undo_type(GLOBAL_gb_main, GB_UNDO_UNDO);
177    if (error) aw_message(error);
178    return error;
179}
180
181// after intro
182void nt_main_startup_main_window(AW_root *aw_root){
183    create_nt_window(aw_root);
184
185    if (GB_read_clients(GLOBAL_gb_main)==0) { // i am the server
186        GB_ERROR error = GBCMS_open(":",0,GLOBAL_gb_main);
187        if (error) {
188            aw_message(
189                       "THIS PROGRAM HAS PROBLEMS TO OPEN INTERCLIENT COMMUNICATION !!!\n"
190                       "(MAYBE THERE IS ALREADY ANOTHER SERVER RUNNING)\n\n"
191                       "You cannot use any EDITOR or other external SOFTWARE with this dataset!\n\n"
192                       "Advice: Close ARB again, open a console, type 'arb_clean' and restart arb.\n"
193                       "Caution: Any unsaved data in an eventually running ARB will be lost!\n");
194        }else{
195            aw_root->add_timed_callback(NT_SERVE_DB_TIMER,(AW_RCB)serve_db_interrupt,0,0);
196            error = nt_check_database_consistency();
197            if (error) aw_message(error);
198        }
199    }else{
200        aw_root->add_timed_callback(NT_CHECK_DB_TIMER,(AW_RCB)check_db_interrupt,0,0);
201    }
202}
203
204int main_load_and_startup_main_window(AW_root *aw_root) // returns 0 when successfull
205{
206
207    char *db_server = aw_root->awar(AWAR_DB_PATH)->read_string();
208    GLOBAL_gb_main = GBT_open(db_server,"rw","$(ARBHOME)/lib/pts/*");
209
210    if (!GLOBAL_gb_main) {
211        aw_popup_ok(GB_await_error());
212        return -1;
213    }
214
215    aw_root->awar(AWAR_DB_PATH)->write_string(db_server);
216
217#define MAXNAMELEN 35   
218    int len = strlen(db_server);
219    if (len>MAXNAMELEN) {
220        char *nameOnly = strrchr(db_server, '/');
221        if (nameOnly) {
222            nameOnly++;
223            len -= (nameOnly-db_server);
224            memmove(db_server, nameOnly, len+1);
225            if (len>MAXNAMELEN) {
226                strcpy(db_server+MAXNAMELEN-3, "...");
227            }
228        }
229    }
230#if defined(DEBUG)
231    AWT_announce_db_to_browser(GLOBAL_gb_main, GBS_global_string("ARB database (%s)", db_server));
232#endif // DEBUG
233
234    free(db_server);
235    nt_main_startup_main_window(aw_root);
236
237    return 0;
238}
239
240void nt_delete_database(AW_window *aww){
241    char *db_server = aww->get_root()->awar(AWAR_DB_PATH)->read_string();
242    if (strlen(db_server)){
243        if (aw_ask_sure(GBS_global_string("Are you sure to delete database %s\nNote: there is no way to undelete it afterwards", db_server))) {
244            GB_ERROR error = 0;
245            error = GB_delete_database(db_server);
246            if (error) {
247                aw_message(error);
248            }
249            else {
250                aww->get_root()->awar(AWAR_DB"filter")->touch();
251            }
252        }
253    }
254    else {
255        aw_message("No database selected");
256    }
257    free(db_server);
258}
259
260// after import !!!!!
261void main3(AW_root *aw_root)
262{
263
264    GLOBAL_NT.awr = aw_root;
265    create_nt_window(aw_root);
266
267    if (GB_read_clients(GLOBAL_gb_main)==0) {
268        GB_ERROR error = GBCMS_open(":",0,GLOBAL_gb_main);
269        if (error) {
270            aw_message("THIS PROGRAM IS NOT THE ONLY DB SERVER !!!\nDON'T USE ANY ARB PROGRAM !!!!");
271        }else{
272            aw_root->add_timed_callback(NT_SERVE_DB_TIMER, (AW_RCB)serve_db_interrupt,0,0);
273            error = nt_check_database_consistency();
274            if (error) aw_message(error);
275        }
276    }
277    return;
278}
279
280void nt_intro_start_old(AW_window *aws)
281{
282    aws->hide();
283    if (main_load_and_startup_main_window(aws->get_root())) {
284        aws->show();
285    }
286}
287
288void nt_intro_start_merge(AW_window *aws,AW_root *awr){
289    if (aws) awr = aws->get_root();
290    create_MG_main_window(awr);
291    if (aws) aws->hide();
292}
293
294void nt_intro_start_import(AW_window *aws)
295{
296    aws->hide();
297    aws->get_root()->awar_string( AWAR_DB_PATH )->write_string( "noname.arb");
298    aws->get_root()->awar_int(AWAR_READ_GENOM_DB, IMP_PLAIN_SEQUENCE); // Default toggle  in window  "Create&import" is Non-Genom
299    GLOBAL_gb_main = open_AWTC_import_window(aws->get_root(), "", true, 0, (AW_RCB)main3, 0, 0);
300}
301
302AW_window *nt_create_intro_window(AW_root *awr)
303{
304    AW_window_simple *aws = new AW_window_simple;
305    aws->init( awr, "ARB_INTRO", "ARB INTRO");
306    aws->load_xfig("arb_intro.fig");
307
308    aws->callback( (AW_CB0)exit);
309    aws->at("close");
310    aws->create_button("CANCEL","CANCEL","C");
311
312    aws->at("help");
313    aws->callback(AW_POPUP_HELP,(AW_CL)"arb_intro.hlp");
314    aws->create_button("HELP","HELP","H");
315
316    awt_create_selection_box(aws,"tmp/nt/arbdb");
317
318    aws->button_length(0);
319
320    aws->at("logo");
321    aws->create_button(0,"#logo.xpm");
322
323    aws->at("version");
324    aws->create_button(0, GBS_global_string("Version " ARB_VERSION), 0); // version
325
326    aws->at("copyright");
327    aws->create_button(0, GBS_global_string("(C) 1993-" ARB_BUILD_YEAR), 0);
328
329    //  aws->button_length(25);
330
331    aws->at("old");
332    aws->callback(nt_intro_start_old);
333    aws->create_autosize_button("OPEN_SELECTED","OPEN SELECTED","O");
334
335    aws->at("del");
336    aws->callback(nt_delete_database);
337    aws->create_autosize_button("DELETE_SELECTED","DELETE SELECTED");
338
339    aws->at("new_complex");
340    aws->callback(nt_intro_start_import);
341    aws->create_autosize_button("CREATE_AND_IMPORT","CREATE AND IMPORT","I");
342
343    aws->at("merge");
344    aws->callback((AW_CB1)nt_intro_start_merge,0);
345    aws->create_autosize_button("MERGE_TWO_DATABASES","MERGE TWO ARB DATABASES","O");
346
347    aws->at("expert");
348    aws->create_toggle(AWAR_EXPERT);
349
350    return (AW_window *)aws;
351}
352
353void AD_set_default_root(AW_root *aw_root);
354
355//  ----------------------------------------------------------
356//      static void AWAR_DB_PATH_changed_cb(AW_root *awr)
357//  ----------------------------------------------------------
358static void AWAR_DB_PATH_changed_cb(AW_root *awr) {
359    static int avoid_recursion = 0;
360
361    if (!avoid_recursion) {
362        avoid_recursion = 1;
363
364        char *value  = awr->awar(AWAR_DB_PATH)->read_string();
365        char *lslash = strrchr(value, '/');
366
367        char *name = lslash ? lslash+1 : value;
368#if defined(DEBUG)
369        printf("writing '%s' to AWAR_DB_NAME\n", name);
370#endif // DEBUG
371        awr->awar(AWAR_DB_NAME)->write_string(name);
372
373        if (lslash) {               // update value of directory
374            lslash[0] = 0;
375            awr->awar(AWAR_DB"directory")->write_string(value);
376            lslash[0] = '/';
377        }
378
379        free(value);
380
381        avoid_recursion = 0;
382    }
383}
384
385//  ---------------------------------------
386//      int main(int argc, char **argv)
387//  ---------------------------------------
388int main(int argc, char **argv)
389{
390    AW_root *aw_root;
391    AW_default aw_default;
392
393    const char *db_server =":";
394
395    unsigned long mtime = GB_time_of_file("$(ARBHOME)/lib/message");
396    unsigned long rtime = GB_time_of_file("$(HOME)/.arb_prop/msgtime");
397    if (mtime > rtime){
398        AWT_edit("${ARBHOME}/lib/message");
399        system("touch ${HOME}/.arb_prop/msgtime");
400    }
401    aw_initstatus();
402    GB_set_verbose();
403
404    aw_root       = new AW_root;
405    GLOBAL_NT.awr = aw_root;
406    AD_set_default_root(aw_root);                   // set default for AD_map_viewer (as long as no info-box was opened)
407
408    aw_default = aw_root->open_default(".arb_prop/ntree.arb");
409    aw_root->init_variables(aw_default);
410    aw_root->init_root("ARB_NT", false);
411
412    // create some early awars
413    // Note: normally you don't like to add your awar-init-function here, but into nt_create_all_awars()
414
415    aw_create_selection_box_awars(aw_root, AWAR_DB, "", ".arb", "noname.arb", aw_default);
416    aw_root->awar_string( AWAR_DB"type", "b", aw_default);
417
418    aw_root->awar_int(AWAR_EXPERT, 0, aw_default);
419
420    aw_root->awar_string(AWAR_DB_NAME, "noname.arb", aw_default);
421    aw_root->awar(AWAR_DB_PATH)->add_callback(AWAR_DB_PATH_changed_cb);
422
423    init_Advisor(aw_root, aw_default);
424
425    if (argc==3) {              // looks like merge
426        if (argv[1][0] != '-') { // not if first argument is a switch
427            MG_create_all_awars(aw_root,aw_default,argv[1],argv[2]);
428            nt_intro_start_merge(0,aw_root);
429            aw_root->main_loop();
430        }
431    }
432
433    bool  abort            = false;
434    bool  start_db_browser = true;
435    char *browser_startdir = strdup(".");
436
437    if (argc>=2) {
438        start_db_browser = false;
439
440        if (strcmp(argv[1], "--help")==0 ||
441            strcmp(argv[1], "-help")==0 ||
442            strcmp(argv[1], "-h")==0)
443        {
444            fprintf(stderr,
445                    "\n"
446                    "arb_ntree version " ARB_VERSION "\n"
447                    "(C) 1993-" ARB_BUILD_YEAR " Lehrstuhl fuer Mikrobiologie - TU Muenchen\n"
448                    "http://www.arb-home.de/\n"
449#if defined(SHOW_WHERE_BUILD)
450                    "(version build by: " ARB_BUILD_USER "@" ARB_BUILD_HOST ")\n"
451#endif // SHOW_WHERE_BUILD
452                    "\n"
453                    "Known command line arguments:\n"
454                    "\n"
455                    "db.arb             => start ARB_NTREE with database db.arb\n"
456                    ":                  => start ARB_NTREE and connect to existing db_server\n"
457                    "db1.arb db2.arb    => merge databases db1.arb and db2.arb\n"
458                    "-export            => connect to existing ARB server and export database to noname.arb\n"
459                    "-import file       => import 'file' into new database\n"
460                    "w/o arguments      => start database browser\n"
461                    "\n"
462                    );
463
464            exit(1);
465        }
466
467        if ( strcmp(argv[1],"-export")==0) {
468            MG_create_all_awars(aw_root,aw_default,":","noname.arb");
469            GLOBAL_gb_merge = GBT_open(":","rw",0);
470            if (!GLOBAL_gb_merge) {
471                aw_popup_ok(GB_await_error());
472                exit(0);
473            }
474#if defined(DEBUG)
475            AWT_announce_db_to_browser(GLOBAL_gb_merge, "Current database (:)");
476#endif // DEBUG
477
478            GLOBAL_gb_dest = GBT_open("noname.arb","cw",0);
479#if defined(DEBUG)
480            AWT_announce_db_to_browser(GLOBAL_gb_dest, "New database (noname.arb)");
481#endif // DEBUG
482
483            MG_start_cb2(NULL, aw_root, true, true);
484            aw_root->main_loop();
485        }
486
487        bool run_importer = false;
488        if (strcmp(argv[1], "-import") == 0) {
489            argv++;
490            run_importer = true;
491        }
492
493        db_server              = argv[1];
494        GB_ERROR load_file_err = 0;
495        if (!run_importer) load_file_err = GBT_check_arb_file(db_server);
496
497        if (load_file_err) {
498            int   answer    = -1;
499            char *full_path = AWT_unfold_path(db_server);
500
501            printf("load_file_err='%s'\n", load_file_err);
502
503            if (AWT_is_dir(full_path)) answer = 2; // autoselect browser
504
505            if (answer == -1) {
506                if (!AWT_is_file(full_path)) {
507                    const char *msg = GBS_global_string("'%s' is neither a known option nor a legal file- or directory-name.\n(Error: %s)",
508                                                        full_path, load_file_err);
509                    answer          = aw_question(msg, "Browser,Exit");
510
511                    switch (answer) { // map answer to codes used by aw_message below
512                        case 0: answer = 2; break; // Browse
513                        case 1: answer = 3; break; // Exit
514                        default : nt_assert(0);
515                    }
516                }
517                else {
518                    const char *msg = GBS_global_string("Your file is not an original arb file\n(%s)", load_file_err);
519                    answer          = aw_question(msg, "Continue (dangerous),Start Converter,Browser,Exit");
520                }
521            }
522
523            switch (answer) {
524                case 0: {        // Continue
525                    break;
526                }
527                case 1: {        // Start converter
528                    run_importer =  true;
529                    break;
530                }
531                case 2: {        // Browse
532                    char *dir = nulldup(full_path);
533                    while (dir && !AWT_is_dir(dir)) freeset(dir, AWT_extract_directory(dir));
534
535                    if (dir) {
536                        nt_assert(AWT_is_dir(dir));
537                        reassign(browser_startdir, dir);
538                        start_db_browser = true;
539                    }
540                    free(dir);
541                    break;
542                }
543                case 3: {        // Exit
544                    abort = true;
545                    break;
546                }
547                default: {
548                    break;
549                }
550            }
551            free(full_path);
552        }
553
554        if (run_importer) {
555            aw_root->awar_int(AWAR_READ_GENOM_DB, IMP_PLAIN_SEQUENCE);
556            GLOBAL_gb_main = open_AWTC_import_window(aw_root, db_server, true, 0, (AW_RCB)main3, 0, 0);
557            aw_root->main_loop();
558        }
559    }
560
561
562    if (start_db_browser) {
563        aw_root->awar(AWAR_DB"directory")->write_string(browser_startdir);
564        char *latest = GB_find_latest_file(browser_startdir, "/\\.(arb|a[0-9]{2})$/");
565        if (latest){
566            int l = strlen(latest);
567            latest[l-1] = 'b';
568            latest[l-2] = 'r';
569            latest[l-3] = 'a';
570            aw_root->awar(AWAR_DB_PATH)->write_string(latest);
571            free(latest);
572        }
573        AW_window *iws;
574        if (GLOBAL_NT.window_creator){
575            iws = GLOBAL_NT.window_creator(aw_root,0);
576        }else{
577            iws = nt_create_intro_window(aw_root);
578        }
579        iws->show();
580        aw_root->main_loop();
581    }
582
583    if (abort) {
584        printf("Aborting.\n");
585    }
586    else {
587        aw_root->awar(AWAR_DB_PATH)->write_string(db_server);
588        if (main_load_and_startup_main_window(aw_root)) return -1;
589        aw_root->main_loop();
590    }
591
592    return 0;
593}
Note: See TracBrowser for help on using the repository browser.