tesseract  4.0.0-1-g2a2b
paramsd.cpp
Go to the documentation of this file.
1 // File: paramsd.cpp
3 // Description: Tesseract parameter Editor
4 // Author: Joern Wanke
5 // Created: Wed Jul 18 10:05:01 PDT 2007
6 //
7 // (C) Copyright 2007, Google Inc.
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
19 //
20 // The parameters editor is used to edit all the parameters used within
21 // tesseract from the ui.
22 
23 // Include automatically generated configuration file if running autoconf.
24 #ifdef HAVE_CONFIG_H
25 #include "config_auto.h"
26 #endif
27 
28 #ifndef GRAPHICS_DISABLED
29 
30 #include "paramsd.h"
31 #include <cstdio> // for fclose, fopen, fprintf, sprintf, FILE
32 #include <cstdlib> // for atoi, strtod
33 #include <cstring> // for strcmp, strcspn, strlen, strncpy
34 #include <map> // for map, _Rb_tree_iterator, map<>::iterator
35 #include <memory> // for unique_ptr
36 #include <utility> // for pair
37 #include "genericvector.h" // for GenericVector
38 #include "params.h" // for ParamsVectors, StringParam, BoolParam
39 #include "scrollview.h" // for SVEvent, ScrollView, SVET_POPUP
40 #include "svmnode.h" // for SVMenuNode
41 #include "tesseractclass.h" // for Tesseract
42 
43 #define VARDIR "configs/" /*parameters files */
44 #define MAX_ITEMS_IN_SUBMENU 30
45 
46 // The following variables should remain static globals, since they
47 // are used by debug editor, which uses a single Tesseract instance.
48 //
49 // Contains the mappings from unique VC ids to their actual pointers.
50 static std::map<int, ParamContent*> vcMap;
51 static int nrParams = 0;
52 static int writeCommands[2];
53 
55 
56 // Constructors for the various ParamTypes.
57 ParamContent::ParamContent(tesseract::StringParam* it) {
58  my_id_ = nrParams;
59  nrParams++;
60  param_type_ = VT_STRING;
61  sIt = it;
62  vcMap[my_id_] = this;
63 }
64 // Constructors for the various ParamTypes.
66  my_id_ = nrParams;
67  nrParams++;
68  param_type_ = VT_INTEGER;
69  iIt = it;
70  vcMap[my_id_] = this;
71 }
72 // Constructors for the various ParamTypes.
74  my_id_ = nrParams;
75  nrParams++;
76  param_type_ = VT_BOOLEAN;
77  bIt = it;
78  vcMap[my_id_] = this;
79 }
80 // Constructors for the various ParamTypes.
82  my_id_ = nrParams;
83  nrParams++;
84  param_type_ = VT_DOUBLE;
85  dIt = it;
86  vcMap[my_id_] = this;
87 }
88 
89 // Gets a VC object identified by its ID.
91  return vcMap[id];
92 }
93 
94 // Copy the first N words from the source string to the target string.
95 // Words are delimited by "_".
96 void ParamsEditor::GetFirstWords(
97  const char *s, // source string
98  int n, // number of words
99  char *t // target string
100  ) {
101  int full_length = strlen(s);
102  int reqd_len = 0; // No. of chars requird
103  const char *next_word = s;
104 
105  while ((n > 0) && reqd_len < full_length) {
106  reqd_len += strcspn(next_word, "_") + 1;
107  next_word += reqd_len;
108  n--;
109  }
110  strncpy(t, s, reqd_len);
111  t[reqd_len] = '\0'; // ensure null terminal
112 }
113 
114 // Getter for the name.
115 const char* ParamContent::GetName() const {
116  if (param_type_ == VT_INTEGER) { return iIt->name_str(); }
117  else if (param_type_ == VT_BOOLEAN) { return bIt->name_str(); }
118  else if (param_type_ == VT_DOUBLE) { return dIt->name_str(); }
119  else if (param_type_ == VT_STRING) { return sIt->name_str(); }
120  else
121  return "ERROR: ParamContent::GetName()";
122 }
123 
124 // Getter for the description.
125 const char* ParamContent::GetDescription() const {
126  if (param_type_ == VT_INTEGER) { return iIt->info_str(); }
127  else if (param_type_ == VT_BOOLEAN) { return bIt->info_str(); }
128  else if (param_type_ == VT_DOUBLE) { return dIt->info_str(); }
129  else if (param_type_ == VT_STRING) { return sIt->info_str(); }
130  else return nullptr;
131 }
132 
133 // Getter for the value.
135  STRING result;
136  if (param_type_ == VT_INTEGER) {
137  result.add_str_int("", *iIt);
138  } else if (param_type_ == VT_BOOLEAN) {
139  result.add_str_int("", *bIt);
140  } else if (param_type_ == VT_DOUBLE) {
141  result.add_str_double("", *dIt);
142  } else if (param_type_ == VT_STRING) {
143  if (((STRING) * (sIt)).string() != nullptr) {
144  result = sIt->string();
145  } else {
146  result = "Null";
147  }
148  }
149  return result;
150 }
151 
152 // Setter for the value.
153 void ParamContent::SetValue(const char* val) {
154 // TODO (wanke) Test if the values actually are properly converted.
155 // (Quickly visible impacts?)
156  changed_ = true;
157  if (param_type_ == VT_INTEGER) {
158  iIt->set_value(atoi(val));
159  } else if (param_type_ == VT_BOOLEAN) {
160  bIt->set_value(atoi(val));
161  } else if (param_type_ == VT_DOUBLE) {
162  dIt->set_value(strtod(val, nullptr));
163  } else if (param_type_ == VT_STRING) {
164  sIt->set_value(val);
165  }
166 }
167 
168 // Gets the up to the first 3 prefixes from s (split by _).
169 // For example, tesseract_foo_bar will be split into tesseract,foo and bar.
170 void ParamsEditor::GetPrefixes(const char* s, STRING* level_one,
171  STRING* level_two,
172  STRING* level_three) {
173  std::unique_ptr<char[]> p(new char[1024]);
174  GetFirstWords(s, 1, p.get());
175  *level_one = p.get();
176  GetFirstWords(s, 2, p.get());
177  *level_two = p.get();
178  GetFirstWords(s, 3, p.get());
179  *level_three = p.get();
180 }
181 
182 // Compare two VC objects by their name.
183 int ParamContent::Compare(const void* v1, const void* v2) {
184  const ParamContent* one = *static_cast<const ParamContent* const*>(v1);
185  const ParamContent* two = *static_cast<const ParamContent* const*>(v2);
186  return strcmp(one->GetName(), two->GetName());
187 }
188 
189 // Find all editable parameters used within tesseract and create a
190 // SVMenuNode tree from it.
191 // TODO (wanke): This is actually sort of hackish.
192 SVMenuNode* ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) {
193  SVMenuNode* mr = new SVMenuNode();
194  ParamContent_LIST vclist;
195  ParamContent_IT vc_it(&vclist);
196  // Amount counts the number of entries for a specific char*.
197  // TODO(rays) get rid of the use of std::map.
198  std::map<const char*, int> amount;
199 
200  // Add all parameters to a list.
201  int v, i;
202  int num_iterations = (tess->params() == nullptr) ? 1 : 2;
203  for (v = 0; v < num_iterations; ++v) {
204  tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params();
205  for (i = 0; i < vec->int_params.size(); ++i) {
206  vc_it.add_after_then_move(new ParamContent(vec->int_params[i]));
207  }
208  for (i = 0; i < vec->bool_params.size(); ++i) {
209  vc_it.add_after_then_move(new ParamContent(vec->bool_params[i]));
210  }
211  for (i = 0; i < vec->string_params.size(); ++i) {
212  vc_it.add_after_then_move(new ParamContent(vec->string_params[i]));
213  }
214  for (i = 0; i < vec->double_params.size(); ++i) {
215  vc_it.add_after_then_move(new ParamContent(vec->double_params[i]));
216  }
217  }
218 
219  // Count the # of entries starting with a specific prefix.
220  for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
221  ParamContent* vc = vc_it.data();
222  STRING tag;
223  STRING tag2;
224  STRING tag3;
225 
226  GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
227  amount[tag.string()]++;
228  amount[tag2.string()]++;
229  amount[tag3.string()]++;
230  }
231 
232  vclist.sort(ParamContent::Compare); // Sort the list alphabetically.
233 
234  SVMenuNode* other = mr->AddChild("OTHER");
235 
236  // go through the list again and this time create the menu structure.
237  vc_it.move_to_first();
238  for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
239  ParamContent* vc = vc_it.data();
240  STRING tag;
241  STRING tag2;
242  STRING tag3;
243  GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
244 
245  if (amount[tag.string()] == 1) {
246  other->AddChild(vc->GetName(), vc->GetId(), vc->GetValue().string(),
247  vc->GetDescription());
248  } else { // More than one would use this submenu -> create submenu.
249  SVMenuNode* sv = mr->AddChild(tag.string());
250  if ((amount[tag.string()] <= MAX_ITEMS_IN_SUBMENU) ||
251  (amount[tag2.string()] <= 1)) {
252  sv->AddChild(vc->GetName(), vc->GetId(),
253  vc->GetValue().string(), vc->GetDescription());
254  } else { // Make subsubmenus.
255  SVMenuNode* sv2 = sv->AddChild(tag2.string());
256  sv2->AddChild(vc->GetName(), vc->GetId(),
257  vc->GetValue().string(), vc->GetDescription());
258  }
259  }
260  }
261  return mr;
262 }
263 
264 // Event listener. Waits for SVET_POPUP events and processes them.
265 void ParamsEditor::Notify(const SVEvent* sve) {
266  if (sve->type == SVET_POPUP) { // only catch SVET_POPUP!
267  char* param = sve->parameter;
268  if (sve->command_id == writeCommands[0]) {
269  WriteParams(param, false);
270  } else if (sve->command_id == writeCommands[1]) {
271  WriteParams(param, true);
272  } else {
274  sve->command_id);
275  vc->SetValue(param);
276  sv_window_->AddMessage("Setting %s to %s",
277  vc->GetName(), vc->GetValue().string());
278  }
279  }
280 }
281 
282 // Integrate the parameters editor as popupmenu into the existing scrollview
283 // window (usually the pg editor). If sv == null, create a new empty
284 // empty window and attach the parameters editor to that window (ugly).
286  ScrollView* sv) {
287  if (sv == nullptr) {
288  const char* name = "ParamEditorMAIN";
289  sv = new ScrollView(name, 1, 1, 200, 200, 300, 200);
290  }
291 
292  sv_window_ = sv;
293 
294  //Only one event handler per window.
295  //sv->AddEventHandler((SVEventHandler*) this);
296 
297  SVMenuNode* svMenuRoot = BuildListOfAllLeaves(tess);
298 
299  STRING paramfile;
300  paramfile = tess->datadir;
301  paramfile += VARDIR; // parameters dir
302  paramfile += "edited"; // actual name
303 
304  SVMenuNode* std_menu = svMenuRoot->AddChild ("Build Config File");
305 
306  writeCommands[0] = nrParams+1;
307  std_menu->AddChild("All Parameters", writeCommands[0],
308  paramfile.string(), "Config file name?");
309 
310  writeCommands[1] = nrParams+2;
311  std_menu->AddChild ("changed_ Parameters Only", writeCommands[1],
312  paramfile.string(), "Config file name?");
313 
314  svMenuRoot->BuildMenu(sv, false);
315 }
316 
317 
318 // Write all (changed_) parameters to a config file.
319 void ParamsEditor::WriteParams(char *filename,
320  bool changes_only) {
321  FILE *fp; // input file
322  char msg_str[255];
323  // if file exists
324  if ((fp = fopen (filename, "rb")) != nullptr) {
325  fclose(fp);
326  sprintf (msg_str, "Overwrite file " "%s" "? (Y/N)", filename);
327  int a = sv_window_->ShowYesNoDialog(msg_str);
328  if (a == 'n') {
329  return;
330  } // don't write
331  }
332 
333 
334  fp = fopen (filename, "wb"); // can we write to it?
335  if (fp == nullptr) {
336  sv_window_->AddMessage(
337  "Can't write to file "
338  "%s"
339  "",
340  filename);
341  return;
342  }
343 
344  for (std::map<int, ParamContent*>::iterator iter = vcMap.begin();
345  iter != vcMap.end();
346  ++iter) {
347  ParamContent* cur = iter->second;
348  if (!changes_only || cur->HasChanged()) {
349  fprintf(fp, "%-25s %-12s # %s\n",
350  cur->GetName(), cur->GetValue().string(), cur->GetDescription());
351  }
352  }
353  fclose(fp);
354 }
355 #endif // GRAPHICS_DISABLED
const char * GetDescription() const
Definition: paramsd.cpp:125
const char * info_str() const
Definition: params.h:117
const char * GetName() const
Definition: paramsd.cpp:115
int ShowYesNoDialog(const char *msg)
Definition: scrollview.cpp:748
GenericVector< IntParam * > int_params
Definition: params.h:44
GenericVector< BoolParam * > bool_params
Definition: params.h:45
const char * string() const
Definition: strngs.cpp:196
void set_value(const STRING &value)
Definition: params.h:207
GenericVector< StringParam * > string_params
Definition: params.h:46
static int Compare(const void *v1, const void *v2)
Definition: paramsd.cpp:183
#define MAX_ITEMS_IN_SUBMENU
Definition: paramsd.cpp:44
STRING GetValue() const
Definition: paramsd.cpp:134
const char * string() const
Definition: params.h:202
void Notify(const SVEvent *sve)
Definition: paramsd.cpp:265
void SetValue(const char *val)
Definition: paramsd.cpp:153
tesseract::ParamsVectors * GlobalParams()
Definition: params.cpp:32
const char * name_str() const
Definition: params.h:116
void add_str_double(const char *str, double number)
Definition: strngs.cpp:389
SVMenuNode * AddChild(const char *txt)
Definition: svmnode.cpp:58
#define ELISTIZE(CLASSNAME)
Definition: elst.h:961
SVEventType type
Definition: scrollview.h:64
ParamsVectors * params()
Definition: ccutil.h:62
ParamContent()=default
static ParamContent * GetParamContentById(int id)
Definition: paramsd.cpp:90
int GetId()
Definition: paramsd.h:76
void add_str_int(const char *str, int number)
Definition: strngs.cpp:379
GenericVector< DoubleParam * > double_params
Definition: params.h:47
Definition: strngs.h:45
STRING datadir
Definition: ccutil.h:64
int command_id
Definition: scrollview.h:70
void set_value(int32_t value)
Definition: params.h:154
char * parameter
Definition: scrollview.h:71
bool HasChanged()
Definition: paramsd.h:77
ParamsEditor(tesseract::Tesseract *, ScrollView *sv=nullptr)
Definition: paramsd.cpp:285
void BuildMenu(ScrollView *sv, bool menu_bar=true)
Definition: svmnode.cpp:120
void set_value(BOOL8 value)
Definition: params.h:178
void set_value(double value)
Definition: params.h:231
void AddMessage(const char *format,...)
Definition: scrollview.cpp:563
#define VARDIR
Definition: paramsd.cpp:43