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