ARB
NT_group_search.cxx
Go to the documentation of this file.
1 // ============================================================= //
2 // //
3 // File : NT_group_search.cxx //
4 // Purpose : GUI for group search //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in April 2017 //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================= //
10 
11 #include "NT_group_search.h"
12 #include "NT_local.h"
13 #include "ad_trees.h"
14 
15 #include <group_search.h>
16 #include <TreeDisplay.hxx>
17 
18 #include <awt_config_manager.hxx>
19 #include <awt_sel_boxes.hxx>
20 
21 #include <aw_select.hxx>
22 #include <aw_root.hxx>
23 #include <aw_awar.hxx>
24 #include <aw_msg.hxx>
25 #include <aw_awar_defs.hxx>
26 
27 #include <ad_cb_prot.h>
28 
29 using namespace std;
30 
31 #if defined(DEVEL_RALF) && 0
32 #define TRACE(msg) fprintf(stderr, "TRACE: %s\n", (msg))
33 #else // !DEVEL_RALF
34 #define TRACE(msg)
35 #endif
36 
37 // --------------------------------
38 // AWARs for group search
39 
40 #define GS_AWARS "group_search/"
41 #define GS_AWARS_DUPS GS_AWARS "dup/"
42 #define GS_AWARS_TMP "tmp/" GS_AWARS
43 
44 #define AWAR_MAYBE_INVALID_GROUP GS_AWARS_TMP "sellist" // may point to deleted or unlisted group
45 #define AWAR_SELECTED_RESULT_GROUP GS_AWARS_TMP "selected" // bound to AWAR_MAYBE_INVALID_GROUP, but never points to deleted or unlisted group
46 #define AWAR_GROUP_HIT_COUNT GS_AWARS_TMP "hits"
47 #define AWAR_SELECTED_GROUP_NAME GS_AWARS_TMP "selname"
48 #define AWAR_RESULTING_GROUP_NAME GS_AWARS_TMP "resname"
49 #define AWAR_TREE_SELECTED GS_AWARS_TMP "treesel"
50 #define AWAR_RESULT_ORDER GS_AWARS_TMP "order"
51 
52 #define AWAR_SEARCH_WHICH_TREES GS_AWARS "trees"
53 #define AWAR_SEARCH_MODE GS_AWARS "mode"
54 #define AWAR_MATCH_MODE GS_AWARS "match"
55 #define AWAR_MARK_TARGET GS_AWARS "markwhat"
56 #define AWAR_RENAME_EXPRESSION GS_AWARS "aci"
57 
58 #define AWAR_DUPLICATE_MODE GS_AWARS_DUPS "mode"
59 #define AWAR_DUP_TREE_MODE GS_AWARS_DUPS "locmode"
60 #define AWAR_DUP_NAME_MATCH GS_AWARS_DUPS "namematch"
61 #define AWAR_DUP_MIN_CLUSTER_SIZE GS_AWARS_DUPS "clustsize"
62 #define AWAR_DUP_MIN_WORDS GS_AWARS_DUPS "minwords"
63 #define AWAR_DUP_IGNORE_CASE GS_AWARS_DUPS "ignore_case"
64 #define AWAR_DUP_EXCLUDED_WORDS GS_AWARS_DUPS "excluded"
65 #define AWAR_DUP_WORD_SEPARATORS GS_AWARS_DUPS "separators"
66 
67 #define AWARFORMAT_CRIT_OPERATOR GS_AWARS "op%i"
68 #define AWARFORMAT_CRIT_KEY GS_AWARS "key%i"
69 #define AWARFORMAT_CRIT_EQUALS GS_AWARS "equals%i"
70 #define AWARFORMAT_CRIT_MATCHES GS_AWARS "match%i"
71 
72 #define MAX_CRITERIA 3
73 
74 inline const char *criterion_awar_name(const char *format, int crit) {
75  gs_assert(crit>=1 && crit<=MAX_CRITERIA);
76  return GBS_global_string(format, crit);
77 }
78 
83 };
84 
89 };
90 
91 // ---------------------
92 // data for UI
93 
94 class GroupUIdata : virtual Noncopyable {
95  GBDATA *gb_main;
96  SmartPtr<GroupSearch> group_search;
97  bool show_tree_name; // show treename in result list?
98  AW_selection_list *result_list;
99  AW_selection *tree_list;
100 
101  void update_search_filters();
102  void update_search_range();
103  void update_duplicate_settings();
104 
105  void refresh_hit_count(size_t count) {
106  AW_root::SINGLETON->awar(AWAR_GROUP_HIT_COUNT)->write_int(count); // update hit count
107  }
108  void result_order_changed_cb(AW_root *awr) {
109  if (group_search.isSet()) {
111  group_search->addSortCriterion(crit);
112  refill_result_list();
113  }
114  }
115  void result_list_awar_changed_cb(AW_root *awr);
116  void selected_group_name_changed_cb(AW_root *awr);
117  void selected_group_changed_cb(AW_root *awr);
118  void update_resulting_groupname_cb(AW_root *awr);
119 
120  // callback wrappers:
121  static void refresh_result_list_cb(GroupSearch*, GroupUIdata *data) { data->refill_result_list(); }
122  static void cleanup_on_exit(GBDATA*, GroupUIdata *data) { data->cleanup(); }
123  static void result_order_changed_cb(AW_root *awr, GroupUIdata *data) { data->result_order_changed_cb(awr); }
124  static void result_list_awar_changed_cb(AW_root *awr, GroupUIdata *data) { data->result_list_awar_changed_cb(awr); }
125  static void selected_group_name_changed_cb(AW_root *awr, GroupUIdata *data) { data->selected_group_name_changed_cb(awr); }
126  static void selected_group_changed_cb(AW_root *awr, GroupUIdata *data) { data->selected_group_changed_cb(awr); }
127  static void update_resulting_groupname_cb(AW_root *awr, GroupUIdata *data) { data->update_resulting_groupname_cb(awr); }
128 
129  void install_callbacks(AW_root *awr) {
130  awr->awar(AWAR_RESULT_ORDER) ->add_callback(makeRootCallback(GroupUIdata::result_order_changed_cb, this));
131  awr->awar(AWAR_MAYBE_INVALID_GROUP) ->add_callback(makeRootCallback(GroupUIdata::result_list_awar_changed_cb, this));
132  awr->awar(AWAR_SELECTED_GROUP_NAME) ->add_callback(makeRootCallback(GroupUIdata::selected_group_name_changed_cb, this));
133  awr->awar(AWAR_SELECTED_RESULT_GROUP)->add_callback(makeRootCallback(GroupUIdata::selected_group_changed_cb, this));
134  awr->awar(AWAR_RENAME_EXPRESSION) ->add_callback(makeRootCallback(GroupUIdata::update_resulting_groupname_cb, this));
135  }
136  void remove_callbacks(AW_root *awr) {
137  awr->awar(AWAR_RESULT_ORDER) ->remove_callback(makeRootCallback(GroupUIdata::result_order_changed_cb, this));
138  awr->awar(AWAR_MAYBE_INVALID_GROUP) ->remove_callback(makeRootCallback(GroupUIdata::result_list_awar_changed_cb, this));
139  awr->awar(AWAR_SELECTED_GROUP_NAME) ->remove_callback(makeRootCallback(GroupUIdata::selected_group_name_changed_cb, this));
140  awr->awar(AWAR_SELECTED_RESULT_GROUP)->remove_callback(makeRootCallback(GroupUIdata::selected_group_changed_cb, this));
141  awr->awar(AWAR_RENAME_EXPRESSION) ->remove_callback(makeRootCallback(GroupUIdata::update_resulting_groupname_cb, this));
142  }
143 
144 public:
145  GroupUIdata(GBDATA *gb_main_) :
146  gb_main(gb_main_),
147  show_tree_name(false),
148  result_list(NULp)
149  {
150  GB_atclose_callback(gb_main, makeDatabaseCallback(GroupUIdata::cleanup_on_exit, this));
151  }
152 
153  void initialize() { // called after popup
154  if (group_search.isNull()) { // avoid reinit if group-search-menu-entry is pressed while group-search-window is still open
155  TRACE("initialize GroupUIdata");
156  group_search = new GroupSearch(gb_main, makeGroupSearchCallback(GroupUIdata::refresh_result_list_cb, this));
157  install_callbacks(AW_root::SINGLETON);
158  }
159  }
160 
161  GBDATA *get_gb_main() const { return gb_main; }
162 
163  void announce_result_list(AW_selection_list *result_list_) { result_list = result_list_; }
164  void announce_tree_select_list(AW_selection *tree_list_) { tree_list = tree_list_; }
165 
166  void cleanup() { // called on popdown
167  TRACE("cleanup GroupUIdata");
168  remove_callbacks(AW_root::SINGLETON);
169  group_search.setNull();
170  clear_result_list();
171  }
172 
173  void run_search() {
174  update_search_filters();
175  update_search_range();
176  update_duplicate_settings();
177 
178  {
181  group_search->perform_search(mode);
182  }
183  refill_result_list();
184  }
185 
186  void refill_result_list();
187  void remove_selected_result();
188  void remove_all_results();
189  void clear_result_list();
190 
192  AW_scalar awar_value = result_list->get_awar_value();
193  int idx = result_list->get_index_of(awar_value);
194 
195  return idx == -1 ? NULp : awar_value.get_pointer();
196  }
197 
198  // modify groups
199  void delete_selected_group();
200  void delete_listed_groups();
201 
202  void rename_selected_group();
203  void rename_listed_groups();
204 
205  void toggle_selected_group_folding();
206  void change_listed_groups_folding(GroupFoldingMode mode);
207 
208  void mark_species(GroupMarkMode mode);
209 };
210 
212  refresh_hit_count(0);
213 
214  result_list->clear();
215  result_list->insert_default("<none>", (GBDATA*)NULp);
216  result_list->update();
217 }
219  const QueriedGroups& foundGroups = group_search->get_results();
220 
222  AW_awar *awar_sel = awr->awar(AWAR_SELECTED_RESULT_GROUP);
223 
224  if (foundGroups.empty()) {
225  clear_result_list();
226  awar_sel->write_pointer(NULp);
227  }
228  else {
230 
231  GBDATA *gb_sellist_group = awr->awar(AWAR_MAYBE_INVALID_GROUP)->read_pointer();
232  bool seen_selected = false;
233 
234  refresh_hit_count(foundGroups.size());
235 
236  result_list->clear();
237  for (FoundGroupCIter g = foundGroups.begin(); g != foundGroups.end(); ++g) {
238  const char *display = foundGroups.get_group_display(*g, show_tree_name);
239  GBDATA *gb_group = g->get_pointer();
240 
241  result_list->insert(display, gb_group);
242 
243  if (gb_group == gb_sellist_group) seen_selected = true;
244  }
245  result_list->insert_default("<none>", (GBDATA*)NULp);
246  result_list->update();
247 
248  awar_sel->rewrite_pointer(seen_selected ? gb_sellist_group : NULp);
249  }
250 }
251 
252 void GroupUIdata::update_search_filters() {
254 
255  group_search->forgetQExpressions();
256  for (int crit = 1; crit<=MAX_CRITERIA; ++crit) {
260  const char *expression = awr->awar(criterion_awar_name(AWARFORMAT_CRIT_MATCHES, crit))->read_char_pntr();
261 
262  group_search->addQueryExpression(op, type, mtype, expression);
263  }
264 }
265 
266 void GroupUIdata::update_search_range() {
269  TreeNameSet trees;
270 
271  switch (range) {
272  case SEARCH_ALL_TREES: break; // empty set means "all trees"
273  case SEARCH_CURRENT_TREE: {
274  const char *currentTree = awr->awar(AWAR_TREE_NAME)->read_char_pntr();
275  if (currentTree[0]) trees.insert(currentTree);
276  break;
277  }
279  if (tree_list) {
280  StrArray tree_names;
281  tree_list->get_values(tree_names);
282  for (int t = 0; tree_names[t]; ++t) {
283  trees.insert(tree_names[t]);
284  }
285  }
286  break;
287  }
288  if (trees.empty() && range != SEARCH_ALL_TREES) {
289  aw_message("No tree selected -> searching all trees instead");
290  }
291  group_search->setSearchRange(trees);
292  show_tree_name = trees.size() != 1; // (0->all)
293 }
294 
295 void GroupUIdata::update_duplicate_settings() {
298 
299  if (dmode == DONT_MIND_DUPLICATES) {
300  group_search->forgetDupCriteria();
301  }
302  else {
303  gs_assert(dmode == ONLY_UNIQUE || dmode == ONLY_DUPLICATES);
304 
307 
308  int minClusterSize = awr->awar(AWAR_DUP_MIN_CLUSTER_SIZE)->read_int();
309  bool listDups = dmode == ONLY_DUPLICATES;
311 
312  if (nametype == DNC_WHOLENAME) {
313  group_search->setDupCriteria(listDups, nametype, sens, treetype, minClusterSize);
314  }
315  else {
316  int minWords = awr->awar(AWAR_DUP_MIN_WORDS)->read_int();
317  const char *excludedWords = awr->awar(AWAR_DUP_EXCLUDED_WORDS)->read_char_pntr();
318  const char *wordSeparators = awr->awar(AWAR_DUP_WORD_SEPARATORS)->read_char_pntr();
319 
320  group_search->setDupCriteria(listDups, nametype, sens, minWords, excludedWords, wordSeparators, treetype, minClusterSize);
321  }
322  }
323 }
324 
325 
327  int selidx = result_list->get_index_of_selected();
328  if (selidx != -1) { // group is selected
329  result_list->move_selection(1);
330  result_list->delete_element_at(selidx);
331  result_list->update();
332  group_search->remove_hit(selidx);
333  }
334 }
336  group_search->forget_results();
337  refill_result_list();
338 }
339 
341  int sel = result_list->get_index_of_selected();
342  if (sel != -1) { // group is selected
343  result_list->select_default(); // avoid invalid access to group deleted below
344  aw_message_if(group_search->delete_group(sel));
345  }
346 }
347 
349  if (group_search->has_results()) {
350  result_list->select_default(); // avoid invalid access to group deleted below
351  aw_message_if(group_search->delete_found_groups());
352  }
353 }
354 
355 // callback wrappers:
356 static void popdown_search_window_cb(AW_window*, GroupUIdata *data) { data->cleanup(); }
357 static void runGroupSearch_cb(AW_window*, GroupUIdata *data) { data->run_search(); }
359 static void clear_results_cb(AW_window*, GroupUIdata *data) { data->remove_all_results(); }
366 static void group_mark_cb(AW_window*, GroupUIdata *data, GroupMarkMode mode) { data->mark_species(mode); }
367 
368 
369 TREE_canvas *NT_get_canvas_showing_tree(const char *tree_name, bool forceDisplay) {
370  // search whether any canvas shows the tree 'tree_name'.
371  // if yes -> return that canvas
372  // if no -> if forceDisplay==false -> return NULp
373  // else -> search first visible canvas + switch tree -> return that canvas
374 
375  TREE_canvas *ntw = NULp;
376  {
377  TREE_canvas *first_vis = NULp;
378 
379  for (int ci = 0; ci<MAX_NT_WINDOWS && !ntw; ++ci) {
381  if (tc && tc->is_shown()) { // @@@ does not detect iconified windows
382  if (!first_vis) first_vis = tc;
383  if (strcmp(tc->get_awar_tree()->read_char_pntr(), tree_name) == 0) ntw = tc;
384  }
385  }
386 
387  if (!ntw && forceDisplay) {
388  if (!first_vis) {
389  first_vis = NT_get_canvas_by_index(0);
390  first_vis->aww->activate(); // popup first (if all windows hidden)
391  }
392  ntw = first_vis;
393  nt_assert(ntw);
394  ntw->get_awar_tree()->write_string(tree_name);
395  }
396  }
397 
398  return ntw;
399 }
400 
402  // detect tree containing group
403  // + use NT_get_canvas_showing_tree to force display of that tree
404 
405  TREE_canvas *ntw = NULp;
406  {
407  GB_transaction ta(gb_group);
408 
409  GBDATA *gb_tree = GB_get_father(gb_group);
410  char *tree_name = GB_read_key(gb_tree);
411 
412  ntw = NT_get_canvas_showing_tree(tree_name, true); // forces display of 'tree_name'
413 
414  free(tree_name);
415  }
416 
417  return ntw;
418 }
419 
420 static bool inside_group_selection = false;
421 
422 void GroupUIdata::result_list_awar_changed_cb(AW_root *awr) {
423  LocallyModify<bool> avoid_recursion(inside_group_selection, true);
424 
425  GBDATA *gb_group = awr->awar(AWAR_MAYBE_INVALID_GROUP)->read_pointer();
426  TRACE(GBS_global_string("result_list_awar_changed_cb to %p", gb_group));
427 
428  if (gb_group) {
429  TREE_canvas *ntw = get_canvas_able_to_show(gb_group);
430 
431  GB_transaction ta(gb_group);
432  ntw->get_graphic_tree()->select_group(gb_group);
433 
434  awr->awar(AWAR_SELECTED_RESULT_GROUP)->rewrite_pointer(get_selected_group());
435  }
436  else {
437  // @@@ why need extra refresh here?
438  // @@@ does not auto-fold
439  // both should be handled by deselect_group?!
440  TREE_canvas *ntw = NT_get_canvas_by_index(0); // use any canvas here
441  AWT_auto_refresh force(ntw);
443  ntw->request_refresh();
444 
446  }
447 }
448 
450  if (!inside_group_selection) {
451  LocallyModify<bool> avoid_recursion(inside_group_selection, true);
452 
453  GBDATA *gb_group = awr->awar(AWAR_GROUP)->read_pointer();
454  TRACE(GBS_global_string("selected_group_changed_by_canvas_cb to %p", gb_group));
455  if (gb_group) {
457  }
458  }
459 }
460 
461 static bool nameChangedByGroupChange = false;
462 
463 void GroupUIdata::selected_group_changed_cb(AW_root *awr) {
464  GBDATA *gb_group = awr->awar(AWAR_SELECTED_RESULT_GROUP)->read_pointer();
465  TRACE(GBS_global_string("selected_group_changed_cb to %p", gb_group));
466 
467  LocallyModify<bool> ignoreNameChange(nameChangedByGroupChange, true);
468 
469  const char *name = "";
470  if (gb_group) {
471  GB_transaction ta(gb_group);
472  name = FoundGroup(gb_group).get_name();
473  }
475  // ensure update of rename-result even if a group-change did NOT change the name (because both groups have same name)
476  update_resulting_groupname_cb(awr);
477 }
478 
479 void GroupUIdata::update_resulting_groupname_cb(AW_root *awr) {
480  TRACE("update_resulting_groupname_cb");
481 
482  char *curr_name = awr->awar(AWAR_SELECTED_GROUP_NAME)->read_string();
483  char *acisrt = awr->awar(AWAR_RENAME_EXPRESSION)->read_string();
484 
486  int idx = result_list->get_index_of_selected();
487  char *result = GS_calc_resulting_groupname(gb_main, group_search->get_results(), idx, curr_name, acisrt, error);
488 
489  if (result) {
490  error.expect_no_error();
491  if (!result[0]) { // empty result (will be skipped in batch-rename)
492  result = strdup("<empty result> => group would be skipped in batch-rename");
493  }
494  }
495  else {
496  result = strdup(error.deliver()); // show error in result field
497  }
499 
500  free(result);
501  free(acisrt);
502  free(curr_name);
503 }
504 
505 void GroupUIdata::selected_group_name_changed_cb(AW_root *awr) {
506  if (!nameChangedByGroupChange) {
507  GB_ERROR error = NULp;
508  AW_awar *awar_selected_result = awr->awar(AWAR_SELECTED_RESULT_GROUP);
509  GBDATA *gb_group = awar_selected_result->read_pointer();
510 
511  if (!gb_group) error = "select a group to rename it";
512  else {
513  char *new_name = GBS_trim(awr->awar(AWAR_SELECTED_GROUP_NAME)->read_char_pntr());
514  if (!new_name[0]) error = "empty group name not allowed";
515  else {
516  GB_transaction ta(gb_group);
517  error = GBT_write_name_to_groupData(gb_group, false, new_name, true);
518  }
519  }
520 
521  if (error) {
522  aw_message(error);
523  awar_selected_result->touch(); // refill groupname inputfield
524  }
525  }
526 }
527 
529  int sel = result_list->get_index_of_selected();
530  if (sel != -1) { // group is selected
532  aw_message_if(group_search->rename_group(sel, acisrt).deliver());
533  // Note: no refresh needed here (triggered by taxonomy callbacks)
534  }
535 }
536 
538  if (group_search.isNull()) {
539  aw_message("Please rerun group search");
540  return;
541  }
542  if (group_search->has_results()) {
544  aw_message_if(group_search->rename_found_groups(acisrt).deliver());
545  // Note: no refresh needed here (triggered by taxonomy callbacks)
546  }
547 }
548 
550  int sel = result_list->get_index_of_selected();
551  if (sel != -1) { // group is selected
552  ARB_ERROR error = group_search->fold_group(sel, GFM_TOGGLE);
553  aw_message_if(error);
554  if (!error) AW_root::SINGLETON->awar(AWAR_GROUP)->touch(); // trigger recenter + refresh of changed group
555  }
556 }
557 
559  if (group_search->has_results() || (foldmode & GFM_COLLAPSE_REST)) {
560  ARB_ERROR error = group_search->fold_found_groups(foldmode);
561  aw_message_if(error);
562  if (!error) {
563  AW_root::SINGLETON->awar(AWAR_GROUP)->write_pointer(NULp); // deselect group (otherwise wont fold subtree containing selected)
564  AW_root::SINGLETON->awar(AWAR_TREE_REFRESH)->touch(); // force expose of all trees (triggers reload if DB-changes)
565  }
566  }
567 }
568 
570  GMT_ALL_SPECIES, // targets all species in DB
571  GMT_SELECTED_GROUP, // targets all species contained in SELECTED group
572  GMT_ANY_GROUP, // targets all species contained in ANY listed group
573  GMT_ALL_GROUPS, // targets all species contained in ALL listed groups
574 };
575 
578  bool anyGroup = false;
581 
582  switch (target) {
583  case GMT_ALL_SPECIES:
584  GBT_mark_all(gb_main, int(mode));
585  break;
586 
587  case GMT_SELECTED_GROUP: {
588  int sel = result_list->get_index_of_selected();
589  if (sel != -1) {
590  error = group_search->set_marks_in_group(sel, mode);
591  }
592  else {
593  error = "Please select a group";
594  }
595 
596  break;
597  }
598  case GMT_ANY_GROUP:
599  anyGroup = true;
600  // fall-through
601  case GMT_ALL_GROUPS:
602  if (group_search->has_results()) {
603  error = group_search->set_marks_in_found_groups(mode, anyGroup ? UNITE : INTERSECT);
604  }
605  else {
606  error = "No results listed";
607  }
608  break;
609  }
610 
611  error = ta.close(error);
612  aw_message_if(error.deliver());
613 }
614 
616  aw_root->awar_pointer(AWAR_MAYBE_INVALID_GROUP, NULp, props);
617  aw_root->awar_pointer(AWAR_SELECTED_RESULT_GROUP, NULp, props);
618 
619  CriterionType deftype[MAX_CRITERIA] = {
620  CT_NAME,
621  CT_SIZE,
622  CT_MARKED_PC,
623  };
624 
625  for (int crit = 1; crit<=MAX_CRITERIA; ++crit) {
626  if (crit>1) {
628  }
629  aw_root->awar_int (criterion_awar_name(AWARFORMAT_CRIT_KEY, crit), deftype[crit-1], props);
631  aw_root->awar_string(criterion_awar_name(AWARFORMAT_CRIT_MATCHES, crit), crit == 1 ? "*" : "", props);
632  }
633 
634  aw_root->awar_string(AWAR_SELECTED_GROUP_NAME, "", props);
635  aw_root->awar_string(AWAR_RENAME_EXPRESSION, "", props);
636  aw_root->awar_string(AWAR_RESULTING_GROUP_NAME, "???", props);
637  aw_root->awar_string(AWAR_TREE_SELECTED, "", props);
638 
640  "and or"
641  " branch group clade subsection"
642  " order family genus"
643  " incertae sedis"
644  " other unknown unclassified miscellaneous"
645  , props);
646  aw_root->awar_string(AWAR_DUP_WORD_SEPARATORS, ",; /()[]_", props);
647 
648  aw_root->awar_int(AWAR_GROUP_HIT_COUNT, 0, props);
650  aw_root->awar_int(AWAR_SEARCH_MODE, GSM_FIND, props);
651  aw_root->awar_int(AWAR_MATCH_MODE, GSM_MATCH, props);
653  aw_root->awar_int(AWAR_DUP_TREE_MODE, DLC_SAME_TREE, props);
654  aw_root->awar_int(AWAR_DUP_MIN_CLUSTER_SIZE, 2, props)->set_min(2);
655  aw_root->awar_int(AWAR_DUP_NAME_MATCH, DNC_WHOLENAME, props);
656  aw_root->awar_int(AWAR_DUP_IGNORE_CASE, 1, props);
657  aw_root->awar_int(AWAR_DUP_MIN_WORDS, 2, props)->set_min(1);
658  aw_root->awar_int(AWAR_RESULT_ORDER, GSC_NONE, props);
659  aw_root->awar_int(AWAR_MARK_TARGET, GMT_SELECTED_GROUP, props);
660 
661  // perma-callbacks:
663  // more callbacks are installed above in .@install_callbacks
664 }
665 
667  AW_window_simple *aws = new AW_window_simple;
668 
669  aw_root->awar(AWAR_SEARCH_WHICH_TREES)->write_int(SEARCH_SELECTED_TREES); // switch target-range to 'selected trees'
670 
671  aws->init(aw_root, "GROUP_TREES", "Select trees to search");
672  aws->load_xfig("group_trees.fig");
673 
674  aws->callback(AW_POPDOWN);
675  aws->at("close");
676  aws->create_button("CLOSE", "CLOSE", "C");
677 
678  aws->callback(makeHelpCallback("group_trees.hlp"));
679  aws->at("help");
680  aws->create_button("HELP", "HELP", "H");
681 
682  aws->at("list");
684  AW_selection *selected_trees = awt_create_subset_selection_list(aws, all_trees->get_sellist(), "selected", "add", "sort");
685 
686  data->announce_tree_select_list(selected_trees);
687 
688  return aws;
689 }
690 
692  AW_window_simple *aws = new AW_window_simple;
693  aws->init(awr, "RENAME_GROUPS", "Rename taxonomic groups");
694 
695  const int PAD = 10;
696 
697  aws->at(PAD, PAD);
698  aws->auto_space(PAD/2, PAD/2);
699 
700  aws->button_length(7);
701 
702  aws->callback(AW_POPDOWN);
703  aws->create_button("CLOSE", "Close", "C");
704 
705  aws->at_shift(450, 0); // defines minimum window width
706 
707  aws->at_attach(-PAD, 0);
708  aws->callback(makeHelpCallback("group_rename.hlp"));
709  aws->create_button("HELP", "Help", "H");
710  aws->at_unattach();
711 
712  const int IF_YSIZE = 32; // lineheight of attached input field
713 
714  const int LABEL_LENGTH = 27;
715  const int FIELD_LENGTH = 40; // startup-length (chars)
716 
717  aws->label_length(LABEL_LENGTH);
718 
719  aws->at_newline();
720  int sy = aws->get_at_yposition();
721 
722  aws->at_attach_to(true, false, -PAD, IF_YSIZE);
723  aws->label("Selected group name:");
724  aws->create_input_field(AWAR_SELECTED_GROUP_NAME, FIELD_LENGTH);
725 
726  aws->at_newline();
727  int inputlineHeight = aws->get_at_yposition()-sy;
728 
729  aws->at_attach_to(true, false, -PAD, IF_YSIZE);
730  aws->label("Modify using ACI/SRT:");
731  aws->create_input_field(AWAR_RENAME_EXPRESSION, FIELD_LENGTH);
732  aws->at_unattach();
733 
734  aws->at_newline();
735  int rx, ry;
736  aws->get_at_position(&rx, &ry);
737  aws->at_shift(0, inputlineHeight); // reserve space for "Resulting group name"
738 
739  int by = aws->get_at_yposition();
740  aws->at_attach(0, -PAD);
741  aws->callback(makeWindowCallback(rename_selected_group_cb, data));
742  aws->create_autosize_button(NULp, "Apply to\nselected group");
743  aws->at_attach(0, -PAD);
744  aws->callback(makeWindowCallback(rename_listed_groups_cb, data));
745  aws->create_autosize_button(NULp, "Apply to all\nlisted groups");
746  aws->at_unattach();
747 
748  aws->at_newline();
749  int bheight = aws->get_at_yposition()-by;
750 
751  aws->at(rx, ry);
752  aws->at_attach_to(true, true, -PAD, -(PAD+bheight));
753  aws->label("Resulting group name:");
754  aws->create_button(NULp, AWAR_RESULTING_GROUP_NAME, NULp, "+");
755  aws->at_unattach();
756 
757  aws->window_fit();
758 
759  return aws;
760 }
761 
763  AW_window_simple *aws = new AW_window_simple;
764  aws->init(awr, "DUP_CONFIG", "Configure group duplicate search");
765 
766  const int PAD = 10;
767  const int IF_YSIZE = 32; // lineheight of attached input field
768 
769  aws->at(PAD, PAD);
770  aws->auto_space(PAD/2, PAD/2);
771 
772  aws->button_length(7);
773 
774  aws->callback(AW_POPDOWN);
775  aws->create_button("CLOSE", "Close", "C");
776 
777  const int LONG_LABEL_LENGTH = 30;
778  const int SHORT_LABEL_LENGTH = 15;
779  const int LONG_FIELD_LENGTH = 40; // used for string input field
780  const int SHORT_FIELD_LENGTH = 7; // used for numeric input fields
781 
782  aws->label_length(LONG_LABEL_LENGTH);
783 
784  aws->at_newline();
785  aws->label("Min. size of duplicate cluster:");
786  aws->create_input_field(AWAR_DUP_MIN_CLUSTER_SIZE, SHORT_FIELD_LENGTH);
787 
788  aws->at_newline();
789  aws->label("Search duplicates");
790  aws->create_option_menu(AWAR_DUP_TREE_MODE, true);
791  aws->insert_default_option("inside same tree", "s", DLC_SAME_TREE);
792  aws->insert_option ("in different trees", "d", DLC_DIFF_TREE);
793  aws->insert_option ("anywhere", "a", DLC_ANYWHERE);
794  aws->update_option_menu();
795 
796  aws->at_newline();
797  aws->label("Ignore case?");
798  aws->create_toggle(AWAR_DUP_IGNORE_CASE);
799 
800  aws->at_newline();
801  aws->create_toggle_field(AWAR_DUP_NAME_MATCH, "Duplicates are names that", "N");
802  aws->insert_default_toggle("match whole name", "n", DNC_WHOLENAME);
803  aws->insert_toggle ("match wordwise", "w", DNC_WORDWISE);
804  aws->update_toggle_field();
805 
806  aws->at_newline();
807  aws->label("Min. number of matching words");
808  aws->create_input_field(AWAR_DUP_MIN_WORDS, SHORT_FIELD_LENGTH);
809 
810  aws->at_newline();
811  aws->label("Word separators");
812  aws->create_input_field(AWAR_DUP_WORD_SEPARATORS, 2*SHORT_FIELD_LENGTH);
813 
814  aws->at_newline();
815  aws->label_length(SHORT_LABEL_LENGTH);
816  aws->at_attach_to(true, false, -PAD, IF_YSIZE);
817  aws->label("Ignored words");
818  aws->create_input_field(AWAR_DUP_EXCLUDED_WORDS, LONG_FIELD_LENGTH);
819 
820  aws->window_fit();
821  return aws;
822 }
823 
825  { AWAR_SEARCH_WHICH_TREES, "searched_trees" },
826  { AWAR_SEARCH_MODE, "search_mode" },
827  { AWAR_MATCH_MODE, "match_mode" },
828 
829  { AWAR_DUPLICATE_MODE, "dup_mode" },
830  { AWAR_DUP_TREE_MODE, "dup_tree_mode" },
831  { AWAR_DUP_MIN_CLUSTER_SIZE, "dup_min_size" },
832  { AWAR_DUP_NAME_MATCH, "dup_match_mode" },
833  { AWAR_DUP_IGNORE_CASE, "dup_ignore_case" },
834  { AWAR_DUP_MIN_WORDS, "dup_min_words" },
835  { AWAR_DUP_EXCLUDED_WORDS, "dup_excluded_words" },
836  { AWAR_DUP_WORD_SEPARATORS, "dup_word_separators" },
837 
838  { AWAR_MARK_TARGET, "mark_target" },
839  { AWAR_RENAME_EXPRESSION, "rename_script" },
840 
841  { NULp, NULp },
842 };
843 
845  def.add(group_search_config_mapping); // fixed parameters
846 
847  for (int crit = 1; crit<=MAX_CRITERIA; ++crit) {
848  if (crit>1) {
849  def.add(criterion_awar_name(AWARFORMAT_CRIT_OPERATOR, crit), "op", crit);
850  }
851  def.add(criterion_awar_name(AWARFORMAT_CRIT_KEY, crit), "sel", crit);
852  def.add(criterion_awar_name(AWARFORMAT_CRIT_EQUALS, crit), "eq", crit);
853  def.add(criterion_awar_name(AWARFORMAT_CRIT_MATCHES, crit), "expr", crit);
854  }
855 }
856 
858  { "*tagged_find", "Search expression for \"tagged\" groupnames", "dup_mode='0';eq1='0';expr1='*[*]*';match_mode='0';op2='2';op3='2';sel1='0'" },
859  { "*tags_remove_all", "Expression for batch-rename:\n- removes any prefix(es) in \"[..]\" from groupnames", "rename_script='/\\\\[.*\\\\]//'" },
860  { "*tag_prefix", "Expression for batch-rename:\n- adds prefix \"[TAG] \" to groupnames", "rename_script='\"[TAG] \";dd'" },
861  { "*swap_AND_names", "Batch-rename:\n \"X and Y\" -> \"Y and X\"\n \"X, Y and Z\" -> \"Z, X and Y\" ...", "rename_script=':* and *=*2 and *1:* and *, *=*1, *2 and *3:*, * and *, *=*1, *2, *3 and *4'" },
862  { "*rename_enumerated", "Batch-rename:\n- appends running number to group-name\n (using hitlist order)", "rename_script='dd;\"_\";command(\"\\\\\"00\\\\\";hitidx|merge|tail(3)\")'" },
863  { "*remove_numeric_suffix", "Batch-rename:\n- removes numeric suffixes \n like \"_1\", \"_003\"", "rename_script='/_[0-9]+$//'" },
864 
865  { "*undo_groupXfer_report", "undo group rename applied by \"Move groups\":\n * remove prefix \"XFRD_\"\n * remove penalty suffix", "rename_script='command(\"/^XFRD_//\")|command(\"/\\\\\\\\{penalty.*\\\\\\\\}$//\")'" },
866 
867  { NULp, NULp, NULp }
868 };
869 
871  static AW_window *awgs = NULp;
872  static GroupUIdata data(gb_main);
873 
874  data.initialize();
875 
876  if (!awgs) {
877  AW_window_simple *aws = new AW_window_simple;
878  AW_root *aw_root = aw_parent->get_root();
879 
880  aws->init(aw_root, "GROUP_SEARCH", "Search taxonomic groups");
881  aws->load_xfig("group_search.fig");
882 
883  aws->button_length(7);
884 
885  aws->at("close");
886  aws->callback(AW_POPDOWN);
887  aws->create_button("CLOSE", "Close", "C");
888 
889  aws->at("help");
890  aws->callback(makeHelpCallback("group_search.hlp"));
891  aws->create_button("HELP", "Help", "H");
892 
893  aws->at("config");
894  AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "group_search", makeConfigSetupCallback(create_search_config_setup_cb), NULp, predefined_group_search);
895 
896  aws->at("trees");
897  aws->create_option_menu(AWAR_SEARCH_WHICH_TREES, true);
898  aws->insert_default_option("current tree", "c", SEARCH_CURRENT_TREE);
899  aws->insert_option ("selected trees", "s", SEARCH_SELECTED_TREES);
900  aws->insert_option ("all trees", "a", SEARCH_ALL_TREES);
901  aws->update_option_menu();
902 
903  aws->at("select");
904  aws->callback(makeCreateWindowCallback(create_tree_select_window_cb, &data));
905  aws->create_autosize_button("select_trees", "(select)");
906 
907  aws->at("mode");
908  aws->create_option_menu(AWAR_SEARCH_MODE, true);
909  aws->insert_default_option("list", "l", GSM_FIND);
910  aws->insert_option ("add", "a", GSM_ADD);
911  aws->insert_option ("keep", "k", GSM_KEEP);
912  aws->insert_option ("remove", "r", GSM_REMOVE);
913  aws->update_option_menu();
914 
915  aws->at("not");
916  aws->create_option_menu(AWAR_MATCH_MODE, true);
917  aws->insert_default_option("match", "m", GSM_MATCH);
918  aws->insert_option ("don't match", "d", GSM_MISMATCH);
919  aws->update_option_menu();
920 
921  aws->at("dups");
922  aws->create_option_menu(AWAR_DUPLICATE_MODE, true);
923  aws->insert_default_option("No", "n", DONT_MIND_DUPLICATES);
924  aws->insert_option ("duplicate groups only", "d", ONLY_DUPLICATES);
925  aws->insert_option ("unique groups only", "u", ONLY_UNIQUE);
926  aws->update_option_menu();
927 
928  aws->at("dupconf");
929  aws->callback(create_dup_config_window_cb);
930  aws->create_autosize_button("config_dup", "Configure");
931 
932  WindowCallback search_wcb = makeWindowCallback(runGroupSearch_cb, &data);
933 
934  for (int crit = 1; crit<=MAX_CRITERIA; ++crit) {
935  if (crit>1) {
936  aws->at(GBS_global_string("op%i", crit));
937  aws->create_option_menu(criterion_awar_name(AWARFORMAT_CRIT_OPERATOR, crit), true);
938  aws->insert_option ("and", "a", CO_AND);
939  aws->insert_option ("or", "o", CO_OR);
940  aws->insert_default_option("ign", "i", CO_IGNORE);
941  aws->update_option_menu();
942  }
943 
944  aws->at(GBS_global_string("crit%i", crit));
945  aws->create_option_menu(criterion_awar_name(AWARFORMAT_CRIT_KEY, crit), true);
946  aws->insert_default_option("groupname", "g", CT_NAME);
947  aws->insert_option ("parent", "p", CT_PARENT_DIRECT);
948  aws->insert_option ("parent (any)", "a", CT_PARENT_ANY);
949  aws->insert_option ("parent (all)", "l", CT_PARENT_ALL);
950  aws->insert_option ("nesting", "n", CT_NESTING_LEVEL);
951  aws->insert_option ("folded", "f", CT_FOLDED);
952  aws->insert_option ("size", "s", CT_SIZE);
953  aws->insert_option ("marked", "m", CT_MARKED);
954  aws->insert_option ("marked%", "%", CT_MARKED_PC);
955  aws->insert_option ("zombies", "z", CT_ZOMBIES);
956  aws->insert_option ("AID", "A", CT_AID);
957  aws->insert_option ("keeled", "k", CT_KEELED);
958  aws->update_option_menu();
959 
960  aws->at(GBS_global_string("eq%i", crit));
961  aws->create_toggle(criterion_awar_name(AWARFORMAT_CRIT_EQUALS, crit), "#equal.xpm", "#notEqual.xpm");
962 
963  aws->at(GBS_global_string("content%i", crit));
964  aws->d_callback(search_wcb); // ENTER in search field
965  aws->create_input_field(criterion_awar_name(AWARFORMAT_CRIT_MATCHES, crit));
966  }
967 
968  aws->button_length(18);
969 
970  aws->at("doquery");
971  aws->callback(search_wcb);
972  aws->create_button("SEARCH", "Search", "S", "+");
973 
974  aws->button_length(13);
975 
976  aws->at("count");
977  aws->label("Hits:");
978  aws->create_button(NULp, AWAR_GROUP_HIT_COUNT, NULp, "+");
979 
980  aws->at("result");
981  aws->d_callback(makeWindowCallback(double_click_group_cb, &data));
982  AW_selection_list *result_list = aws->create_selection_list(AWAR_MAYBE_INVALID_GROUP, true);
983  data.announce_result_list(result_list);
984  data.clear_result_list();
985 
986  aws->at("order");
987  aws->create_option_menu(AWAR_RESULT_ORDER, true);
988  aws->insert_default_option("unsorted", "u", GSC_NONE);
989  aws->insert_option ("by name", "n", GSC_NAME);
990  aws->insert_option ("by nesting", "g", GSC_NESTING);
991  aws->insert_option ("by size", "s", GSC_SIZE);
992  aws->insert_option ("by marked", "m", GSC_MARKED);
993  aws->insert_option ("by marked%", "%", GSC_MARKED_PC);
994  aws->insert_option ("by treename", "t", GSC_TREENAME);
995  aws->insert_option ("by treeorder", "o", GSC_TREEORDER);
996  aws->insert_option ("by hit", "h", GSC_HIT_REASON);
997  aws->insert_option ("by cluster", "c", GSC_CLUSTER);
998  aws->insert_option ("by AID", "A", GSC_AID);
999  aws->insert_option ("by keeled", "k", GSC_KEELED);
1000  aws->insert_option ("reverse", "r", GSC_REVERSE);
1001  aws->update_option_menu();
1002 
1003  // actions (results):
1004  aws->button_length(6);
1005 
1006  aws->at("remhit");
1007  aws->callback(makeWindowCallback(remove_hit_cb, &data));
1008  aws->create_button("rm_sel", "Remove");
1009 
1010  aws->at("clear");
1011  aws->callback(makeWindowCallback(clear_results_cb, &data));
1012  aws->create_button("clear", "Clear");
1013 
1014  // actions (groups):
1015  // ..... rename
1016  aws->at("rename");
1017  aws->callback(makeCreateWindowCallback(create_group_rename_window_cb, &data));
1018  aws->create_button("rename", "Rename ...");
1019 
1020  // ..... expand/collapse
1021  aws->at("expand");
1022  aws->callback(makeWindowCallback(listed_groups_folding_cb, &data, GFM_EXPANDREC));
1023  aws->create_button("expand_listed", "Expand listed");
1024 
1025  aws->at("expcol");
1026  aws->callback(makeWindowCallback(listed_groups_folding_cb, &data, GFM_EXPANDREC_COLLREST));
1027  aws->create_button("explst_collrest", "Expand listed\ncollapse rest");
1028 
1029  aws->at("expparent");
1030  aws->callback(makeWindowCallback(listed_groups_folding_cb, &data, GFM_EXPANDPARENTS));
1031  aws->create_button("expand_parents", "Expand parents");
1032 
1033  aws->at("collapse");
1034  aws->callback(makeWindowCallback(listed_groups_folding_cb, &data, GFM_COLLAPSE));
1035  aws->create_button("collapse_listed", "Collapse listed");
1036 
1037  // ..... delete
1038  aws->at("delete");
1039  aws->callback(makeWindowCallback(delete_selected_group_cb, &data));
1040  aws->create_button("del_sel", "Destroy\nselected group");
1041 
1042  aws->at("dellisted");
1043  aws->callback(makeWindowCallback(delete_listed_groups_cb, &data));
1044  aws->create_button("del_listed", "Destroy all\nlisted groups");
1045 
1046  // ..... mark/unmark
1047  aws->at("mark");
1048  aws->callback(makeWindowCallback(group_mark_cb, &data, GMM_MARK));
1049  aws->create_button("mark", "Mark");
1050  aws->at("unmark");
1051  aws->callback(makeWindowCallback(group_mark_cb, &data, GMM_UNMARK));
1052  aws->create_button("unmark", "Unmark");
1053  aws->at("inv");
1054  aws->callback(makeWindowCallback(group_mark_cb, &data, GMM_INVERT));
1055  aws->create_button("invert", "Inv");
1056 
1057  aws->at("mwhich"); // needs to be created AFTER delete buttons
1058  aws->create_option_menu(AWAR_MARK_TARGET, true);
1059  aws->insert_default_option("selected", "s", GMT_SELECTED_GROUP);
1060  aws->insert_option ("any listed", "l", GMT_ANY_GROUP);
1061  aws->insert_option ("all listed", "a", GMT_ALL_GROUPS);
1062  aws->insert_option ("database", "d", GMT_ALL_SPECIES);
1063  aws->update_option_menu();
1064 
1065  // trigger cleanup on popdown:
1066  aws->on_hide(makeWindowCallback(popdown_search_window_cb, &data));
1067  awgs = aws;
1068  }
1069 
1070  awgs->activate();
1071 }
1072 
DupTreeCriterionType
Definition: group_search.h:303
GB_ERROR rewrite_pointer(GBDATA *aw_pointer)
static void rename_listed_groups_cb(AW_window *, GroupUIdata *data)
AWT_graphic_tree * get_graphic_tree() const
#define AWAR_DUP_MIN_WORDS
static AW_window * create_group_rename_window_cb(AW_root *awr, GroupUIdata *data)
string result
GB_TYPES type
static AWT_config_mapping_def group_search_config_mapping[]
GBDATA * get_pointer() const
Definition: aw_scalar.hxx:73
const char * get_group_display(const FoundGroup &g, bool show_tree_name) const
void change_listed_groups_folding(GroupFoldingMode mode)
void add(const char *awar_name, const char *config_name)
AliDataPtr format(AliDataPtr data, const size_t wanted_len, GB_ERROR &error)
Definition: insdel.cxx:615
static void double_click_group_cb(AW_window *, GroupUIdata *data)
GBDATA * read_pointer() const
Definition: AW_awar.cxx:194
char * GB_read_key(GBDATA *gbd)
Definition: arbdb.cxx:1626
static void group_mark_cb(AW_window *, GroupUIdata *data, GroupMarkMode mode)
#define AWAR_MARK_TARGET
#define AWAR_SELECTED_GROUP_NAME
static AW_window * create_tree_select_window_cb(AW_root *aw_root, GroupUIdata *data)
bool empty() const
Definition: group_search.h:266
void GB_atclose_callback(GBDATA *gbd, const DatabaseCallback &atClose)
Definition: ad_cb.cxx:458
void announce_tree_select_list(AW_selection *tree_list_)
void addSortCriterion(GroupSortCriterion gsc)
#define AWAR_DUP_EXCLUDED_WORDS
GB_ERROR write_pointer(GBDATA *aw_pointer)
void delete_listed_groups()
void request_refresh()
Definition: awt_canvas.hxx:362
void remove_selected_result()
void at(int x, int y)
Definition: AW_at.cxx:93
AW_selection * awt_create_subset_selection_list(AW_window *aww, AW_selection_list *parent_selection, const char *at_box, const char *at_add, const char *at_sort, bool autocorrect_subselection, SubsetChangedCb subChanged_cb, AW_CL cl_user)
const char * criterion_awar_name(const char *format, int crit)
static bool inside_group_selection
#define AWAR_DUP_NAME_MATCH
void rename_listed_groups()
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const StoreConfigCallback &store_cb, const RestoreConfigCallback &load_or_reset_cb, const char *macro_id, const AWT_predefined_config *predef)
long read_int() const
Definition: AW_awar.cxx:187
#define MAX_CRITERIA
static void popdown_search_window_cb(AW_window *, GroupUIdata *data)
#define AWAR_SELECTED_RESULT_GROUP
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
#define AWAR_TREE_SELECTED
#define AWAR_DUPLICATE_MODE
STL namespace.
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
GroupSortCriterion
Definition: group_search.h:237
#define AWARFORMAT_CRIT_EQUALS
bool isNull() const
test if SmartPtr is NULp
Definition: smartptr.h:248
TREE_canvas * NT_get_canvas_by_index(int idx)
Definition: NT_extern.cxx:942
static void listed_groups_folding_cb(AW_window *, GroupUIdata *data, GroupFoldingMode mode)
void announce_result_list(AW_selection_list *result_list_)
#define AWAR_GROUP
Definition: ad_trees.h:19
void setNull()
set SmartPtr to NULp
Definition: smartptr.h:251
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1696
void activate()
Definition: aw_window.hxx:354
static AW_window * create_dup_config_window_cb(AW_root *awr)
static void remove_hit_cb(AW_window *, GroupUIdata *data)
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:234
const char * read_char_pntr() const
Definition: AW_awar.cxx:171
static void selected_group_changed_by_canvas_cb(AW_root *awr)
void mark_species(GroupMarkMode mode)
static AW_root * SINGLETON
Definition: aw_root.hxx:102
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
GroupSearchMode
Definition: group_search.h:320
GroupMarkTarget
void popup_group_search_window(AW_window *aw_parent, GBDATA *gb_main)
#define AWAR_DUP_MIN_CLUSTER_SIZE
GB_ERROR deliver() const
Definition: arb_error.h:114
static TREE_canvas * get_canvas_able_to_show(GBDATA *gb_group)
#define AWAR_SEARCH_MODE
#define AWAR_DUP_IGNORE_CASE
bool isSet() const
test if SmartPtr is not NULp
Definition: smartptr.h:245
#define AWAR_MATCH_MODE
TreeSearchRange
#define TRACE(msg)
static void delete_listed_groups_cb(AW_window *, GroupUIdata *data)
#define AWAR_TREE_NAME
Definition: ad_trees.h:18
#define false
Definition: ureadseq.h:13
DupNameCriterionType
Definition: group_search.h:297
char * GBS_trim(const char *str)
Definition: adstring.cxx:961
#define MAX_NT_WINDOWS
Definition: NT_local.h:31
int get_index_of(const AW_scalar &searched_value)
Definition: AW_select.cxx:303
void touch()
Definition: AW_awar.cxx:210
static void error(const char *msg)
Definition: mkptypes.cxx:96
std::set< std::string > TreeNameSet
Definition: group_search.h:318
#define AWAR_TREE_REFRESH
void expect_no_error() const
Definition: arb_error.h:136
TREE_canvas * NT_get_canvas_showing_tree(const char *tree_name, bool forceDisplay)
FoundGroupCIter end() const
Definition: group_search.h:277
static void mark_species(TreeNode *node, Store_species **extra_marked_species)
Definition: NT_edconf.cxx:442
char * read_string() const
Definition: AW_awar.cxx:201
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
static void delete_selected_group_cb(AW_window *, GroupUIdata *data)
char * GS_calc_resulting_groupname(GBDATA *gb_main, const QueriedGroups &queried, int hit_idx, const char *input_name, const char *acisrt, ARB_ERROR &error)
GB_CASE
Definition: arb_core.h:30
AW_awar * remove_callback(const RootCallback &cb)
Definition: AW_awar.cxx:527
DuplicateMode
#define nt_assert(cond)
Definition: NT_local.h:27
FoundGroupContainer::const_iterator FoundGroupCIter
Definition: group_search.h:234
static void clear_results_cb(AW_window *, GroupUIdata *data)
#define AWARFORMAT_CRIT_KEY
AW_DB_selection * awt_create_TREE_selection_list(GBDATA *gb_main, AW_window *aws, const char *varname, bool fallback2default)
#define AWAR_RESULTING_GROUP_NAME
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:32
#define AWAR_DUP_WORD_SEPARATORS
#define AWARFORMAT_CRIT_MATCHES
#define gs_assert(cond)
Definition: group_search.h:48
#define AWAR_DUP_TREE_MODE
static void rename_selected_group_cb(AW_window *, GroupUIdata *data)
static void create_search_config_setup_cb(AWT_config_definition &def)
void delete_selected_group()
CriterionMatch
Definition: group_search.h:82
FoundGroupCIter begin() const
Definition: group_search.h:275
const char * get_name() const
void toggle_selected_group_folding()
void aw_message(const char *msg)
Definition: AW_status.cxx:932
#define AWARFORMAT_CRIT_OPERATOR
AW_root * get_root()
Definition: aw_window.hxx:348
CriterionType
Definition: group_search.h:86
#define AWAR_RESULT_ORDER
#define NULp
Definition: cxxforward.h:97
GB_ERROR GBT_write_name_to_groupData(GBDATA *gb_group, bool createNameEntry, const char *new_group_name, bool pedantic)
Definition: adtree.cxx:279
size_t size() const
Definition: group_search.h:265
GB_ERROR write_string(const char *aw_string)
GroupFoldingMode
Definition: group_search.h:52
static void runGroupSearch_cb(AW_window *, GroupUIdata *data)
void GBT_mark_all(GBDATA *gb_main, int flag)
Definition: aditem.cxx:291
GroupUIdata(GBDATA *gb_main_)
GB_transaction ta(gb_var)
GBDATA * gb_main
Definition: adname.cxx:33
GBDATA * get_selected_group() const
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
#define AWAR_MAYBE_INVALID_GROUP
#define AWAR_RENAME_EXPRESSION
AW_window * aww
Definition: awt_canvas.hxx:337
bool is_shown() const
Definition: awt_canvas.hxx:397
void rename_selected_group()
void perform_search(GroupSearchMode mode)
AW_awar * awar_pointer(const char *var_name, GBDATA *default_value=NULp, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:590
void remove_all_results()
GroupMarkMode
Definition: group_search.h:66
GBDATA * get_gb_main() const
AW_awar * get_awar_tree() const
#define AW_ROOT_DEFAULT
Definition: aw_base.hxx:106
#define AWAR_GROUP_HIT_COUNT
GB_ERROR write_int(long aw_int)
#define AWAR_SEARCH_WHICH_TREES
void create_group_search_awars(AW_root *aw_root, AW_default props)
void clear_result_list()
AW_scalar get_awar_value() const
Definition: AW_select.cxx:274
AW_selection_list * get_sellist()
Definition: aw_select.hxx:196
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
static AWT_predefined_config predefined_group_search[]
void refill_result_list()
static bool nameChangedByGroupChange
CriterionOperator
Definition: group_search.h:77
AW_awar * set_min(float min)
Definition: aw_awar.hxx:145