All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 =
187  *reinterpret_cast<const ParamContent* const *>(v1);
188  const ParamContent* two =
189  *reinterpret_cast<const ParamContent* const *>(v2);
190  return strcmp(one->GetName(), two->GetName());
191 }
192 
193 // Find all editable parameters used within tesseract and create a
194 // SVMenuNode tree from it.
195 // TODO (wanke): This is actually sort of hackish.
196 SVMenuNode* ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) {
197  SVMenuNode* mr = new SVMenuNode();
198  ParamContent_LIST vclist;
199  ParamContent_IT vc_it(&vclist);
200  // Amount counts the number of entries for a specific char*.
201  // TODO(rays) get rid of the use of std::map.
202  std::map<const char*, int> amount;
203 
204  // Add all parameters to a list.
205  int v, i;
206  int num_iterations = (tess->params() == NULL) ? 1 : 2;
207  for (v = 0; v < num_iterations; ++v) {
208  tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params();
209  for (i = 0; i < vec->int_params.size(); ++i) {
210  vc_it.add_after_then_move(new ParamContent(vec->int_params[i]));
211  }
212  for (i = 0; i < vec->bool_params.size(); ++i) {
213  vc_it.add_after_then_move(new ParamContent(vec->bool_params[i]));
214  }
215  for (i = 0; i < vec->string_params.size(); ++i) {
216  vc_it.add_after_then_move(new ParamContent(vec->string_params[i]));
217  }
218  for (i = 0; i < vec->double_params.size(); ++i) {
219  vc_it.add_after_then_move(new ParamContent(vec->double_params[i]));
220  }
221  }
222 
223  // Count the # of entries starting with a specific prefix.
224  for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
225  ParamContent* vc = vc_it.data();
226  STRING tag;
227  STRING tag2;
228  STRING tag3;
229 
230  GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
231  amount[tag.string()]++;
232  amount[tag2.string()]++;
233  amount[tag3.string()]++;
234  }
235 
236  vclist.sort(ParamContent::Compare); // Sort the list alphabetically.
237 
238  SVMenuNode* other = mr->AddChild("OTHER");
239 
240  // go through the list again and this time create the menu structure.
241  vc_it.move_to_first();
242  for (vc_it.mark_cycle_pt(); !vc_it.cycled_list(); vc_it.forward()) {
243  ParamContent* vc = vc_it.data();
244  STRING tag;
245  STRING tag2;
246  STRING tag3;
247  GetPrefixes(vc->GetName(), &tag, &tag2, &tag3);
248 
249  if (amount[tag.string()] == 1) {
250  other->AddChild(vc->GetName(), vc->GetId(), vc->GetValue().string(),
251  vc->GetDescription());
252  } else { // More than one would use this submenu -> create submenu.
253  SVMenuNode* sv = mr->AddChild(tag.string());
254  if ((amount[tag.string()] <= MAX_ITEMS_IN_SUBMENU) ||
255  (amount[tag2.string()] <= 1)) {
256  sv->AddChild(vc->GetName(), vc->GetId(),
257  vc->GetValue().string(), vc->GetDescription());
258  } else { // Make subsubmenus.
259  SVMenuNode* sv2 = sv->AddChild(tag2.string());
260  sv2->AddChild(vc->GetName(), vc->GetId(),
261  vc->GetValue().string(), vc->GetDescription());
262  }
263  }
264  }
265  return mr;
266 }
267 
268 // Event listener. Waits for SVET_POPUP events and processes them.
269 void ParamsEditor::Notify(const SVEvent* sve) {
270  if (sve->type == SVET_POPUP) { // only catch SVET_POPUP!
271  char* param = sve->parameter;
272  if (sve->command_id == writeCommands[0]) {
273  WriteParams(param, false);
274  } else if (sve->command_id == writeCommands[1]) {
275  WriteParams(param, true);
276  } else {
278  sve->command_id);
279  vc->SetValue(param);
280  sv_window_->AddMessage("Setting %s to %s",
281  vc->GetName(), vc->GetValue().string());
282  }
283  }
284 }
285 
286 // Integrate the parameters editor as popupmenu into the existing scrollview
287 // window (usually the pg editor). If sv == null, create a new empty
288 // empty window and attach the parameters editor to that window (ugly).
290  ScrollView* sv) {
291  if (sv == NULL) {
292  const char* name = "ParamEditorMAIN";
293  sv = new ScrollView(name, 1, 1, 200, 200, 300, 200);
294  }
295 
296  sv_window_ = sv;
297 
298  //Only one event handler per window.
299  //sv->AddEventHandler((SVEventHandler*) this);
300 
301  SVMenuNode* svMenuRoot = BuildListOfAllLeaves(tess);
302 
303  STRING paramfile;
304  paramfile = tess->datadir;
305  paramfile += VARDIR; // parameters dir
306  paramfile += "edited"; // actual name
307 
308  SVMenuNode* std_menu = svMenuRoot->AddChild ("Build Config File");
309 
310  writeCommands[0] = nrParams+1;
311  std_menu->AddChild("All Parameters", writeCommands[0],
312  paramfile.string(), "Config file name?");
313 
314  writeCommands[1] = nrParams+2;
315  std_menu->AddChild ("changed_ Parameters Only", writeCommands[1],
316  paramfile.string(), "Config file name?");
317 
318  svMenuRoot->BuildMenu(sv, false);
319 }
320 
321 
322 // Write all (changed_) parameters to a config file.
323 void ParamsEditor::WriteParams(char *filename,
324  bool changes_only) {
325  FILE *fp; // input file
326  char msg_str[255];
327  // if file exists
328  if ((fp = fopen (filename, "rb")) != NULL) {
329  fclose(fp);
330  sprintf (msg_str, "Overwrite file " "%s" "? (Y/N)", filename);
331  int a = sv_window_->ShowYesNoDialog(msg_str);
332  if (a == 'n') { return; } // dont write
333  }
334 
335 
336  fp = fopen (filename, "wb"); // can we write to it?
337  if (fp == NULL) {
338  sv_window_->AddMessage("Cant write to file " "%s" "", filename);
339  return;
340  }
341 
342  for (std::map<int, ParamContent*>::iterator iter = vcMap.begin();
343  iter != vcMap.end();
344  ++iter) {
345  ParamContent* cur = iter->second;
346  if (!changes_only || cur->HasChanged()) {
347  fprintf(fp, "%-25s %-12s # %s\n",
348  cur->GetName(), cur->GetValue().string(), cur->GetDescription());
349  }
350  }
351  fclose(fp);
352 }
353 #endif
STRING GetValue() const
Definition: paramsd.cpp:135
#define VARDIR
Definition: paramsd.cpp:44
#define ELISTIZE(CLASSNAME)
Definition: elst.h:994
void BuildMenu(ScrollView *sv, bool menu_bar=true)
Definition: svmnode.cpp:121
bool HasChanged()
Definition: paramsd.h:72
ParamContent()
Definition: paramsd.h:57
int command_id
Definition: scrollview.h:70
int GetId()
Definition: paramsd.h:71
void AddMessage(const char *format,...)
Definition: scrollview.cpp:567
#define MAX_ITEMS_IN_SUBMENU
Definition: paramsd.cpp:45
void set_value(BOOL8 value)
Definition: params.h:179
const char * name_str() const
Definition: params.h:117
void set_value(double value)
Definition: params.h:232
void Notify(const SVEvent *sve)
Definition: paramsd.cpp:269
static ParamContent * GetParamContentById(int id)
Definition: paramsd.cpp:91
STRING datadir
Definition: ccutil.h:67
name_table name
GenericVector< IntParam * > int_params
Definition: params.h:44
void SetValue(const char *val)
Definition: paramsd.cpp:154
const char * GetName() const
Definition: paramsd.cpp:116
char * parameter
Definition: scrollview.h:71
const char * info_str() const
Definition: params.h:118
GenericVector< BoolParam * > bool_params
Definition: params.h:45
ParamsVectors * params()
Definition: ccutil.h:65
void add_str_int(const char *str, int number)
Definition: strngs.cpp:376
GenericVector< DoubleParam * > double_params
Definition: params.h:47
void set_value(inT32 value)
Definition: params.h:155
ParamsEditor(tesseract::Tesseract *, ScrollView *sv=NULL)
Definition: paramsd.cpp:289
#define TRUE
Definition: capi.h:28
SVEventType type
Definition: scrollview.h:64
Definition: strngs.h:44
void add_str_double(const char *str, double number)
Definition: strngs.cpp:386
tesseract::ParamsVectors * GlobalParams()
Definition: params.cpp:33
#define NULL
Definition: host.h:144
SVMenuNode * AddChild(const char *txt)
Definition: svmnode.cpp:59
const char * string() const
Definition: strngs.cpp:193
static int Compare(const void *v1, const void *v2)
Definition: paramsd.cpp:185
int ShowYesNoDialog(const char *msg)
Definition: scrollview.cpp:753
const char * GetDescription() const
Definition: paramsd.cpp:126
GenericVector< StringParam * > string_params
Definition: params.h:46
const char * string() const
Definition: params.h:203
void set_value(const STRING &value)
Definition: params.h:208