File: NodeCreationManager.cpp

package info (click to toggle)
dasher 4.11%2Bgit20130508.adc653-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 40,248 kB
  • ctags: 5,158
  • sloc: xml: 185,479; cpp: 32,301; sh: 11,207; makefile: 828; ansic: 483
file content (181 lines) | stat: -rw-r--r-- 7,336 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "DasherNode.h"
#include "DasherInterfaceBase.h"
#include "NodeCreationManager.h"
#include "MandarinAlphMgr.h"
#include "RoutingAlphMgr.h"
#include "ConvertingAlphMgr.h"
#include "ControlManager.h"
#include "Observable.h"

#include <string.h>

using namespace Dasher;

//Wraps the ParseFile of a provided Trainer, to setup progress notification
// - and then passes self, as a ProgressIndicator, to the Trainer's ParseFile method.
class ProgressNotifier : public AbstractParser, private CTrainer::ProgressIndicator {
public:
  ProgressNotifier(CDasherInterfaceBase *pInterface, CTrainer *pTrainer)
  : AbstractParser(pInterface), m_bSystem(false), m_bUser(false), m_pInterface(pInterface), m_pTrainer(pTrainer) { }
  void bytesRead(off_t n) {
    int iNewPercent = ((m_iStart + n)*100)/m_iStop;
    if (iNewPercent != m_iPercent) {
      m_pInterface->SetLockStatus(m_strDisplay, m_iPercent = iNewPercent);
    }
  }
  bool ParseFile(const string &strFilename, bool bUser) {
    m_iStart = 0;
    m_iStop = m_pInterface->GetFileSize(strFilename);
    if (m_iStop==0) return false;
    return AbstractParser::ParseFile(strFilename, bUser);
  }
  bool Parse(const string &strUrl, istream &in, bool bUser) {
    m_strDisplay = bUser ? _("Training on User Text") : _("Training on System Text");
    m_pInterface->SetLockStatus(m_strDisplay, m_iPercent=0);
    m_pTrainer->SetProgressIndicator(this);
    if (!m_pTrainer->Parse(strUrl, in, bUser)) return false;
    if (bUser) m_bUser=true; else m_bSystem=true;
    return true;
  }
  bool m_bSystem, m_bUser;
private:
  CDasherInterfaceBase *m_pInterface;
  CTrainer *m_pTrainer;
  off_t m_iStart, m_iStop;
  int m_iPercent;
  string m_strDisplay;
};

CNodeCreationManager::CNodeCreationManager(CSettingsUser *pCreateFrom,
                                           Dasher::CDasherInterfaceBase *pInterface,
                                           const Dasher::CAlphIO *pAlphIO) : CSettingsUserObserver(pCreateFrom),
  m_pInterface(pInterface), m_pControlManager(NULL), m_pScreen(NULL) {

  const Dasher::CAlphInfo *pAlphInfo(pAlphIO->GetInfo(GetStringParameter(SP_ALPHABET_ID)));

  switch (pAlphInfo->m_iConversionID) {
    default:
      //TODO: Error reporting here
      //fall through to
    case 0: // No conversion required
      m_pAlphabetManager = new CAlphabetManager(this, pInterface, this, pAlphInfo);
      break;      
#ifdef JAPANESE
    case 1: {
      // Japanese
      CConversionManager *pConversionManager =
#ifdef _WIN32
      new CIMEConversionHelper;
#else
      new CCannaConversionHelper(this, pAlphInfo, GetLongParameter(LP_CONVERSION_TYPE), GetLongParameter(LP_CONVERSION_ORDER));
#endif
      //TODO ownership/deletion
      m_pAlphabetManager = new CConvertingAlphMgr(pInterface, this, pConversionManager, pAlphInfo, pLanguageModel);
      break;
    }
#endif
    case 2:
      //Mandarin Dasher!
      //(ACL) Modify AlphabetManager for Mandarin Dasher
      m_pAlphabetManager = new CMandarinAlphMgr(this, pInterface, this, pAlphInfo);
      break;
    case 3: //these differ only in that conversion id 3 assumes the route by which
    case 4: //the user writes a symbol, is not dependent on context (e.g. just user preference),
            //whereas 4 assumes it does depend on context (e.g. phonetic chinese)
      m_pAlphabetManager = new CRoutingAlphMgr(this, pInterface, this, pAlphInfo);
      break;
      //TODO: we could even just switch from standard alphmgr, to case 3, automatically
      // if the alphabet has repeated symbols; and thus do away with much of the "conversionid"
      // tag (just a flag for context-sensitivity, and maybe the start/stop delimiters?)
  }
  //all other configuration changes, etc., that might be necessary for a particular conversion mode,
  // are implemented by AlphabetManager subclasses overriding the following two methods:
  m_pAlphabetManager->Setup();
  m_pTrainer = m_pAlphabetManager->GetTrainer();
    
  if (!pAlphInfo->GetTrainingFile().empty()) {
    ProgressNotifier pn(pInterface, m_pTrainer);
    pInterface->ScanFiles(&pn,pAlphInfo->GetTrainingFile());
    if (!pn.m_bUser) {
      ///TRANSLATORS: These 3 messages will be displayed when the user has just chosen a new alphabet. The %s parameter will be the name of the alphabet.
      const char *msg = pn.m_bSystem ? _("No user training text found - if you have written in \"%s\" before, this means Dasher may not be learning from previous sessions")
      : _("No training text (user or system) found for \"%s\". Dasher will still work but entry will be slower. We suggest downloading a training text file from the Dasher website, or constructing your own.");
      pInterface->FormatMessageWithString(msg, pAlphInfo->GetID().c_str());
    }
    //3. Finished, so unlock.
    m_pInterface->SetLockStatus("", -1);
  }  else {
    pInterface->FormatMessageWithString(_("\"%s\" does not specify training file. Dasher will work but entry will be slower. Check you have the latest version of the alphabet definition."), pAlphInfo->GetID().c_str());
  }
#ifdef DEBUG_LM_READWRITE
  {
    //test...
    pLanguageModel->WriteToFile("test.model");
    CPPMLanguageModel *pLan = (CPPMLanguageModel *)pLanguageModel;
    CPPMLanguageModel *pLM2 = new CPPMLanguageModel(pEventHandler, pSettingsStore, pAlphInfo);
    pLM2->ReadFromFile("test.model");
    if (!pLan->eq(pLM2)) {
      std::cout << "Not equal!" << std::endl;
      pLM2->WriteToFile("test2.model");
    }
    delete pLM2;
  }
#endif

  HandleEvent(LP_ORIENTATION);
  updateControl();
}

CNodeCreationManager::~CNodeCreationManager() {
  delete m_pAlphabetManager;
  delete m_pTrainer;
  
  delete m_pControlManager;
}

void CNodeCreationManager::ChangeScreen(CDasherScreen *pScreen) {
  if (m_pScreen == pScreen) return;
  m_pScreen = pScreen;
  m_pAlphabetManager->MakeLabels(pScreen);
  if (m_pControlManager) m_pControlManager->ChangeScreen(pScreen);
}

void CNodeCreationManager::HandleEvent(int iParameter) {
  if (iParameter==BP_CONTROL_MODE) updateControl();
}

void CNodeCreationManager::updateControl() {
  delete m_pControlManager;
  unsigned long iControlSpace;
  //don't allow a control manager during Game Mode 
  if (GetBoolParameter(BP_CONTROL_MODE) && !m_pInterface->GetGameModule()) {
    m_pControlManager = new CControlManager(this, this, m_pInterface);
    if (m_pScreen) m_pControlManager->ChangeScreen(m_pScreen);
    iControlSpace = CDasherModel::NORMALIZATION / 20;
  } else {
    m_pControlManager = NULL;
    iControlSpace = 0;
  }
  m_iAlphNorm = CDasherModel::NORMALIZATION-iControlSpace;
}

void CNodeCreationManager::AddExtras(CDasherNode *pParent) {
  //control mode:
  DASHER_ASSERT(pParent->GetChildren().back()->Hbnd() == m_iAlphNorm);
  if (m_pControlManager) {
#ifdef _WIN32_WCE
    DASHER_ASSERT(false);
#endif
    //ACL leave offset as is - like its groupnode parent, but unlike its alphnode siblings,
    //the control node does not enter a symbol....
    CDasherNode *ctl = m_pControlManager->GetRoot(pParent, pParent->offset());
    ctl->Reparent(pParent, pParent->GetChildren().back()->Hbnd(), CDasherModel::NORMALIZATION);
  }
}

void 
CNodeCreationManager::ImportTrainingText(const std::string &strPath) {
  ProgressNotifier pn(m_pInterface, m_pTrainer);
  ifstream in(strPath.c_str(), ios::binary);
	pn.ParseFile(strPath, true);
}