#include "QFramework/TQTreeFormulaObservable.h"
#include "QFramework/TQUtils.h"

#include "QFramework/TQSample.h"

// #define _DEBUG_
#include "QFramework/TQLibrary.h"

///////////////////////////////////////////////////////////////////////////////////////////////
//
// TQTreeFormulaObservable:
//
// When you specify an arithmetic expression using some branch names
// in a cut definition file, in a histogram definition file, in an
// event list definition file or somewhere in the code, ultimately,
// TQObservable::getObservable will be called on your expression and
// check if another observable with the same expression already exists
// - in which case it will return a pointer to that one - or if it
// needs to instantiate a new TQObservable. In the latter case, it
// will usually instantiate a TQTreeFormulaObservable, which
// internerally uses a TTreeFormula to retrieve its data from the
// tree, but there are other observable classes as well.
//
///////////////////////////////////////////////////////////////////////////////////////////////

/*@observable: [TQTreeFormulaObservable] The TQTreeFormulaObservable employs ROOT's TTreeFormula
    to extract information from the TTree (in case of xAODs: the transient tree). It is 
    automatically created from any expression that neither matches any existing Observable nor
    causes any other Observable to be automatically created (instantiated). The expression
    from which it is instantiated is used as the expression forwarded to the internal TTreeFormula.
    An excetion to this is the case where the expression starts with 'VecBranch' followed by
    a TTreeFormula compatible expression enclosed in parentheses (). In this case the expression
    in between the parentheses is provided to the TTreeFormula but instead of only evaluating the
    first entry of the TTreeFormula the Observable will provide all possible evaluations (per event,
    the number of valid evaluations is determined based on TTreeFormula::GetNdata()).
    It therefore turns into a VectorObservable. Please note that this prohibits the direct use in 
    situations that require a scalar value (e.g. cuts or (event) weight expressions)!

*/

ClassImp(TQTreeFormulaObservable)

//______________________________________________________________________________________________

TQTreeFormulaObservable::TQTreeFormulaObservable() :
TQTreeObservable()
{
  // default constructor
}

//______________________________________________________________________________________________

TQTreeFormulaObservable::TQTreeFormulaObservable(const TString& expression,
  bool vectorObs): TQTreeObservable(expression)
{
  // default constructor
  DEBUGclass("constructor called with expression '%s'",expression.Data());
  this->setExpression(expression);
  this->fVectorObs = vectorObs;
}

//______________________________________________________________________________________________

bool TQTreeFormulaObservable::initializeSelf(){
  // initialize the formula of this observable
  DEBUGclass("initializing...");
  if(fExpression.IsNull()){
    ERRORclass("expression is NULL, terminating");
    return false;
  }

  if(!this->fTree){
    DEBUGclass("no tree, terminating");
    return false;
  }
 
  TString expr;
  TString fullExpr = this->getCompiledExpression(fSample);
  if (this->fVectorObs) {
    TQStringUtils::removeLeadingText(fullExpr, "VecBranch");
    TQStringUtils::readBlanksAndNewlines(fullExpr);
    TQStringUtils::readBlock(fullExpr, expr, "()[]{}", "\"\"''");
  } else {
    expr = fullExpr;
  }

  // under some circumstances, it is necessary to call TTreeFormula::GetNdata() on each event
  // here, we check whether any of these conditions are given to not waste any performance
  this->fcallGetNdata = false;
  // https://root.cern.ch/phpBB3/viewtopic.php?f=14&t=16775&p=72308
  if(expr.Contains("MinIf")) this->fcallGetNdata = true;
  // https://sft.its.cern.ch/jira/browse/ROOT-7465
  if(expr.Contains("[")) this->fcallGetNdata = true;

  if (this->fVectorObs) this->fcallGetNdata = true;

  // if the formula is extremly long put a safe guard in terms of number of operators
  int totalNop = expr.CountChar('*') + expr.CountChar('/') + expr.CountChar('+') + expr.CountChar('-') + expr.CountChar('(');
  if (totalNop> 400){
    TTreeFormula::SetMaxima(10000,1000,1000);
  }

  DEBUGclass("for observable '%s', creating formula with expression '%s'",this->GetName(),expr.Data());
  //  if(!gAllowErrorMessages) TQLibrary::redirect_stdout("/dev/null");
  this->fFormula = new TTreeFormula(this->GetName(),expr.Data(),this->fTree);
  //  if(!gAllowErrorMessages) TQLibrary::restore_stdout();
  
  if(!this->fFormula || !this->fFormula->GetTree()){
    ERRORclass("An error occured while creating the formula for TTreeFormulaObservable with expression '%s' created from raw expression '%s'.",expr.Data(),this->getExpression().Data());
    ERRORclass("This could have multiple reasons: Either you used a non-existing branch name or misspelled it. If parts of the (raw) expression are not supposed to be read as branch name(s) but, e.g., a dedicated (custom) observable then the creation of this instance of TQTreeFormulaObservable was performed erroneously. When an observable is requested the following steps listed below are attempted. The default fallback is the creation of a TTreeFormulaObservable.");
    TString expression(this->getExpression());
    expression.ReplaceAll("\\","");
    TString incarnation = TQObservable::unreplaceBools(TQObservable::compileExpression(this->getExpression(),this->fSample,true));
    TString obsname(TQObservable::makeObservableName(expression));
    TString incname(TQObservable::makeObservableName(incarnation));
    ERRORclass("The following steps have been attempted in the observable retrieval:");
    ERRORclass("1) Trying to find a) existing observable with name matching '%s' or",incname.Data());
    ERRORclass("                  b) already existing and initialized observable with activeExpression matching '%s' or",incarnation.Data()); 
    ERRORclass("                  c) already existing and UNinitialized observable expression matching '%s' or",expression.Data()); 
    ERRORclass("2) Trying to find existing observable instances which would yield a compiledExpression matching '%s' if initialized with the provided tags (tags see above). either such an observable was not found or the best match has a factory (in which case we do not clone an existing instance but ask the factory to create a new instance.",incarnation.Data());
    ERRORclass("3) No factory but the TQTreeFormulaObservable one managed to produce a working observable instance."); 
    ERRORclass("A few points to try:");
    ERRORclass("- Are there some square brackets missing? Subexpressions inside [...] are considered as a subobservable. If multiple levels of [] are present this is evaluated recursively. Instead of 'myCustomObservable + myBranchName/1000.' you should write '[myCustomObservable] + [myBranchName]/1000.' .\n The same applies if none of the involved sub expressions corresponds to a branch name:" );
    ERRORclass("- Did you forget to inject an instance of your custom observable at runtime via TQObservable::addObservable? Some analysis packages do this via small python snippets.");
    return false;
  } else {
    DEBUGclass("successfully initialized observable");
  }

  if (totalNop> 400) TTreeFormula::SetMaxima(1000,1000,1000);

  return true;
}

//______________________________________________________________________________________________

bool TQTreeFormulaObservable::finalizeSelf(){
  // finalize self, delete TTreeFormula member
  if (fFormula) {
    delete fFormula;
    fFormula = 0;
  }
  return true;
}

//______________________________________________________________________________________________

TString TQTreeFormulaObservable::getActiveExpression() const {
  // retrieve the expression associated with this observable
  if(this->fFormula){
      if (this->fVectorObs) {
        return TString("VecBranch(") + this->fFormula->GetTitle() + ")";
      } else {
        return this->fFormula->GetTitle();
      }
  }
  return TQStringUtils::emptyString;
}

//______________________________________________________________________________________________

TQTreeFormulaObservable::~TQTreeFormulaObservable(){
  if(this->fFormula) delete this->fFormula;
}

//______________________________________________________________________________________________

double TQTreeFormulaObservable::getValueAt(int index) const {
  // retrieve the value of this tree observable
  // return NaN in case of failure
  if(!this->fFormula){
    WARNclass("in observable '%s', returning NaN!",this->GetName());
    return std::numeric_limits<double>::quiet_NaN();
  }
  
  if(this->fcallGetNdata){
    // if we really need to, we call this function
    if(fFormula->GetNdata() == 0){
      return std::numeric_limits<double>::quiet_NaN();
    }
  }
  
#ifdef _DEBUG_
  try {
#endif
    // actually calculate the value
    const double retval = fFormula->EvalInstance(index);
    // return the result
    DEBUGclass("retrieved value '%f' from expression '%s'",retval,this->getActiveExpression().Data());
    return retval;
#ifdef _DEBUG_
  } catch (std::exception& e){
    ERRORclass("in observable '%s', encountered error: %s",this->getActiveExpression().Data(),e.what());
  }
  return std::numeric_limits<double>::quiet_NaN();
#endif
}

int TQTreeFormulaObservable::getNevaluations() const {
  return fFormula->GetNdata();
}

//______________________________________________________________________________________________

double TQTreeFormulaObservable::getValue() const {
  // retrieve the value of this tree observable
  // return NaN in case of failure
  if(!this->fFormula){
    WARNclass("in observable '%s', returning NaN!",this->GetName());
    return std::numeric_limits<double>::quiet_NaN();
  }
  
  if(this->fcallGetNdata){
    // if we really need to, we call this function
    if(fFormula->GetNdata() == 0){
      return std::numeric_limits<double>::quiet_NaN();
    }
  }
  
#ifdef _DEBUG_
  try {
#endif
    // actually calculate the value
    const double retval = fFormula->EvalInstance();
    // return the result
    DEBUGclass("retrieved value '%f' from expression '%s'",retval,this->getActiveExpression().Data());
    return retval;
#ifdef _DEBUG_
  } catch (std::exception& e){
    ERRORclass("in observable '%s', encountered error: %s",this->getActiveExpression().Data(),e.what());
  }
  return std::numeric_limits<double>::quiet_NaN();
#endif
}

//______________________________________________________________________________________________

TObjArray* TQTreeFormulaObservable::getBranchNames() const {
  // retrieve the list of branch names 
  // ownership of the list belongs to the caller of the function
  return TQUtils::getBranchNames(this->getCompiledExpression(this->fSample));
}

//______________________________________________________________________________________________

const TString& TQTreeFormulaObservable::getExpression() const {
  // retrieve the expression associated with this observable
  if (this->fVectorObs) {
    this->fFullExpression = "VecBranch(" + this->fExpression + ")";
  } else {
    this->fFullExpression = this->fExpression;
  }
  return this->fFullExpression;
}

//______________________________________________________________________________________________

bool TQTreeFormulaObservable::hasExpression() const {
  // check if this observable type knows expressions (default false)
  return true;
}

//______________________________________________________________________________________________

void TQTreeFormulaObservable::setExpression(const TString& expr){
  // set the expression to a given string
  this->fExpression = TQStringUtils::compactify(expr);
}

//______________________________________________________________________________________________

DEFINE_OBSERVABLE_FACTORY(TQTreeFormulaObservable, TString expr) {
  // try to create an instance of this observable from the given expression
  TString origExpr = expr.Copy();
  if(TQStringUtils::removeLeadingText(expr, "VecBranch")) {
    TQStringUtils::readBlanksAndNewlines(expr);
    TString subExpr;
    if (TQStringUtils::readBlock(expr, subExpr, "()[]{}", "\"\"''") > 0) {
        //check if remaining subExpr is empty (up to whitespaces), otherwise
        //there is likely an error and we need to throw! (unless we find a
        //clean way to automatically fix the expression and re-inject it.
        if (!TQStringUtils::isEmpty(expr, true/*ignore blanks*/)) {
          //print an error to inform the user
          ERRORfunc("A known prefix for the VectorAux observable has been found in the expression '%s'. However, there seems to be a remainder after its expression block: '%s'. Did you forget to encapsulate the VecBranch(....) expression in square brackets '[...]'?", origExpr.Data(), expr.Data());
          return NULL;
        } else {
          return new TQTreeFormulaObservable(subExpr, true);
        }
    }
  }

  return new TQTreeFormulaObservable(expr);
}
 TQTreeFormulaObservable.cxx:1
 TQTreeFormulaObservable.cxx:2
 TQTreeFormulaObservable.cxx:3
 TQTreeFormulaObservable.cxx:4
 TQTreeFormulaObservable.cxx:5
 TQTreeFormulaObservable.cxx:6
 TQTreeFormulaObservable.cxx:7
 TQTreeFormulaObservable.cxx:8
 TQTreeFormulaObservable.cxx:9
 TQTreeFormulaObservable.cxx:10
 TQTreeFormulaObservable.cxx:11
 TQTreeFormulaObservable.cxx:12
 TQTreeFormulaObservable.cxx:13
 TQTreeFormulaObservable.cxx:14
 TQTreeFormulaObservable.cxx:15
 TQTreeFormulaObservable.cxx:16
 TQTreeFormulaObservable.cxx:17
 TQTreeFormulaObservable.cxx:18
 TQTreeFormulaObservable.cxx:19
 TQTreeFormulaObservable.cxx:20
 TQTreeFormulaObservable.cxx:21
 TQTreeFormulaObservable.cxx:22
 TQTreeFormulaObservable.cxx:23
 TQTreeFormulaObservable.cxx:24
 TQTreeFormulaObservable.cxx:25
 TQTreeFormulaObservable.cxx:26
 TQTreeFormulaObservable.cxx:27
 TQTreeFormulaObservable.cxx:28
 TQTreeFormulaObservable.cxx:29
 TQTreeFormulaObservable.cxx:30
 TQTreeFormulaObservable.cxx:31
 TQTreeFormulaObservable.cxx:32
 TQTreeFormulaObservable.cxx:33
 TQTreeFormulaObservable.cxx:34
 TQTreeFormulaObservable.cxx:35
 TQTreeFormulaObservable.cxx:36
 TQTreeFormulaObservable.cxx:37
 TQTreeFormulaObservable.cxx:38
 TQTreeFormulaObservable.cxx:39
 TQTreeFormulaObservable.cxx:40
 TQTreeFormulaObservable.cxx:41
 TQTreeFormulaObservable.cxx:42
 TQTreeFormulaObservable.cxx:43
 TQTreeFormulaObservable.cxx:44
 TQTreeFormulaObservable.cxx:45
 TQTreeFormulaObservable.cxx:46
 TQTreeFormulaObservable.cxx:47
 TQTreeFormulaObservable.cxx:48
 TQTreeFormulaObservable.cxx:49
 TQTreeFormulaObservable.cxx:50
 TQTreeFormulaObservable.cxx:51
 TQTreeFormulaObservable.cxx:52
 TQTreeFormulaObservable.cxx:53
 TQTreeFormulaObservable.cxx:54
 TQTreeFormulaObservable.cxx:55
 TQTreeFormulaObservable.cxx:56
 TQTreeFormulaObservable.cxx:57
 TQTreeFormulaObservable.cxx:58
 TQTreeFormulaObservable.cxx:59
 TQTreeFormulaObservable.cxx:60
 TQTreeFormulaObservable.cxx:61
 TQTreeFormulaObservable.cxx:62
 TQTreeFormulaObservable.cxx:63
 TQTreeFormulaObservable.cxx:64
 TQTreeFormulaObservable.cxx:65
 TQTreeFormulaObservable.cxx:66
 TQTreeFormulaObservable.cxx:67
 TQTreeFormulaObservable.cxx:68
 TQTreeFormulaObservable.cxx:69
 TQTreeFormulaObservable.cxx:70
 TQTreeFormulaObservable.cxx:71
 TQTreeFormulaObservable.cxx:72
 TQTreeFormulaObservable.cxx:73
 TQTreeFormulaObservable.cxx:74
 TQTreeFormulaObservable.cxx:75
 TQTreeFormulaObservable.cxx:76
 TQTreeFormulaObservable.cxx:77
 TQTreeFormulaObservable.cxx:78
 TQTreeFormulaObservable.cxx:79
 TQTreeFormulaObservable.cxx:80
 TQTreeFormulaObservable.cxx:81
 TQTreeFormulaObservable.cxx:82
 TQTreeFormulaObservable.cxx:83
 TQTreeFormulaObservable.cxx:84
 TQTreeFormulaObservable.cxx:85
 TQTreeFormulaObservable.cxx:86
 TQTreeFormulaObservable.cxx:87
 TQTreeFormulaObservable.cxx:88
 TQTreeFormulaObservable.cxx:89
 TQTreeFormulaObservable.cxx:90
 TQTreeFormulaObservable.cxx:91
 TQTreeFormulaObservable.cxx:92
 TQTreeFormulaObservable.cxx:93
 TQTreeFormulaObservable.cxx:94
 TQTreeFormulaObservable.cxx:95
 TQTreeFormulaObservable.cxx:96
 TQTreeFormulaObservable.cxx:97
 TQTreeFormulaObservable.cxx:98
 TQTreeFormulaObservable.cxx:99
 TQTreeFormulaObservable.cxx:100
 TQTreeFormulaObservable.cxx:101
 TQTreeFormulaObservable.cxx:102
 TQTreeFormulaObservable.cxx:103
 TQTreeFormulaObservable.cxx:104
 TQTreeFormulaObservable.cxx:105
 TQTreeFormulaObservable.cxx:106
 TQTreeFormulaObservable.cxx:107
 TQTreeFormulaObservable.cxx:108
 TQTreeFormulaObservable.cxx:109
 TQTreeFormulaObservable.cxx:110
 TQTreeFormulaObservable.cxx:111
 TQTreeFormulaObservable.cxx:112
 TQTreeFormulaObservable.cxx:113
 TQTreeFormulaObservable.cxx:114
 TQTreeFormulaObservable.cxx:115
 TQTreeFormulaObservable.cxx:116
 TQTreeFormulaObservable.cxx:117
 TQTreeFormulaObservable.cxx:118
 TQTreeFormulaObservable.cxx:119
 TQTreeFormulaObservable.cxx:120
 TQTreeFormulaObservable.cxx:121
 TQTreeFormulaObservable.cxx:122
 TQTreeFormulaObservable.cxx:123
 TQTreeFormulaObservable.cxx:124
 TQTreeFormulaObservable.cxx:125
 TQTreeFormulaObservable.cxx:126
 TQTreeFormulaObservable.cxx:127
 TQTreeFormulaObservable.cxx:128
 TQTreeFormulaObservable.cxx:129
 TQTreeFormulaObservable.cxx:130
 TQTreeFormulaObservable.cxx:131
 TQTreeFormulaObservable.cxx:132
 TQTreeFormulaObservable.cxx:133
 TQTreeFormulaObservable.cxx:134
 TQTreeFormulaObservable.cxx:135
 TQTreeFormulaObservable.cxx:136
 TQTreeFormulaObservable.cxx:137
 TQTreeFormulaObservable.cxx:138
 TQTreeFormulaObservable.cxx:139
 TQTreeFormulaObservable.cxx:140
 TQTreeFormulaObservable.cxx:141
 TQTreeFormulaObservable.cxx:142
 TQTreeFormulaObservable.cxx:143
 TQTreeFormulaObservable.cxx:144
 TQTreeFormulaObservable.cxx:145
 TQTreeFormulaObservable.cxx:146
 TQTreeFormulaObservable.cxx:147
 TQTreeFormulaObservable.cxx:148
 TQTreeFormulaObservable.cxx:149
 TQTreeFormulaObservable.cxx:150
 TQTreeFormulaObservable.cxx:151
 TQTreeFormulaObservable.cxx:152
 TQTreeFormulaObservable.cxx:153
 TQTreeFormulaObservable.cxx:154
 TQTreeFormulaObservable.cxx:155
 TQTreeFormulaObservable.cxx:156
 TQTreeFormulaObservable.cxx:157
 TQTreeFormulaObservable.cxx:158
 TQTreeFormulaObservable.cxx:159
 TQTreeFormulaObservable.cxx:160
 TQTreeFormulaObservable.cxx:161
 TQTreeFormulaObservable.cxx:162
 TQTreeFormulaObservable.cxx:163
 TQTreeFormulaObservable.cxx:164
 TQTreeFormulaObservable.cxx:165
 TQTreeFormulaObservable.cxx:166
 TQTreeFormulaObservable.cxx:167
 TQTreeFormulaObservable.cxx:168
 TQTreeFormulaObservable.cxx:169
 TQTreeFormulaObservable.cxx:170
 TQTreeFormulaObservable.cxx:171
 TQTreeFormulaObservable.cxx:172
 TQTreeFormulaObservable.cxx:173
 TQTreeFormulaObservable.cxx:174
 TQTreeFormulaObservable.cxx:175
 TQTreeFormulaObservable.cxx:176
 TQTreeFormulaObservable.cxx:177
 TQTreeFormulaObservable.cxx:178
 TQTreeFormulaObservable.cxx:179
 TQTreeFormulaObservable.cxx:180
 TQTreeFormulaObservable.cxx:181
 TQTreeFormulaObservable.cxx:182
 TQTreeFormulaObservable.cxx:183
 TQTreeFormulaObservable.cxx:184
 TQTreeFormulaObservable.cxx:185
 TQTreeFormulaObservable.cxx:186
 TQTreeFormulaObservable.cxx:187
 TQTreeFormulaObservable.cxx:188
 TQTreeFormulaObservable.cxx:189
 TQTreeFormulaObservable.cxx:190
 TQTreeFormulaObservable.cxx:191
 TQTreeFormulaObservable.cxx:192
 TQTreeFormulaObservable.cxx:193
 TQTreeFormulaObservable.cxx:194
 TQTreeFormulaObservable.cxx:195
 TQTreeFormulaObservable.cxx:196
 TQTreeFormulaObservable.cxx:197
 TQTreeFormulaObservable.cxx:198
 TQTreeFormulaObservable.cxx:199
 TQTreeFormulaObservable.cxx:200
 TQTreeFormulaObservable.cxx:201
 TQTreeFormulaObservable.cxx:202
 TQTreeFormulaObservable.cxx:203
 TQTreeFormulaObservable.cxx:204
 TQTreeFormulaObservable.cxx:205
 TQTreeFormulaObservable.cxx:206
 TQTreeFormulaObservable.cxx:207
 TQTreeFormulaObservable.cxx:208
 TQTreeFormulaObservable.cxx:209
 TQTreeFormulaObservable.cxx:210
 TQTreeFormulaObservable.cxx:211
 TQTreeFormulaObservable.cxx:212
 TQTreeFormulaObservable.cxx:213
 TQTreeFormulaObservable.cxx:214
 TQTreeFormulaObservable.cxx:215
 TQTreeFormulaObservable.cxx:216
 TQTreeFormulaObservable.cxx:217
 TQTreeFormulaObservable.cxx:218
 TQTreeFormulaObservable.cxx:219
 TQTreeFormulaObservable.cxx:220
 TQTreeFormulaObservable.cxx:221
 TQTreeFormulaObservable.cxx:222
 TQTreeFormulaObservable.cxx:223
 TQTreeFormulaObservable.cxx:224
 TQTreeFormulaObservable.cxx:225
 TQTreeFormulaObservable.cxx:226
 TQTreeFormulaObservable.cxx:227
 TQTreeFormulaObservable.cxx:228
 TQTreeFormulaObservable.cxx:229
 TQTreeFormulaObservable.cxx:230
 TQTreeFormulaObservable.cxx:231
 TQTreeFormulaObservable.cxx:232
 TQTreeFormulaObservable.cxx:233
 TQTreeFormulaObservable.cxx:234
 TQTreeFormulaObservable.cxx:235
 TQTreeFormulaObservable.cxx:236
 TQTreeFormulaObservable.cxx:237
 TQTreeFormulaObservable.cxx:238
 TQTreeFormulaObservable.cxx:239
 TQTreeFormulaObservable.cxx:240
 TQTreeFormulaObservable.cxx:241
 TQTreeFormulaObservable.cxx:242
 TQTreeFormulaObservable.cxx:243
 TQTreeFormulaObservable.cxx:244
 TQTreeFormulaObservable.cxx:245
 TQTreeFormulaObservable.cxx:246
 TQTreeFormulaObservable.cxx:247
 TQTreeFormulaObservable.cxx:248
 TQTreeFormulaObservable.cxx:249
 TQTreeFormulaObservable.cxx:250
 TQTreeFormulaObservable.cxx:251
 TQTreeFormulaObservable.cxx:252
 TQTreeFormulaObservable.cxx:253
 TQTreeFormulaObservable.cxx:254
 TQTreeFormulaObservable.cxx:255
 TQTreeFormulaObservable.cxx:256
 TQTreeFormulaObservable.cxx:257
 TQTreeFormulaObservable.cxx:258
 TQTreeFormulaObservable.cxx:259
 TQTreeFormulaObservable.cxx:260
 TQTreeFormulaObservable.cxx:261
 TQTreeFormulaObservable.cxx:262
 TQTreeFormulaObservable.cxx:263
 TQTreeFormulaObservable.cxx:264
 TQTreeFormulaObservable.cxx:265
 TQTreeFormulaObservable.cxx:266
 TQTreeFormulaObservable.cxx:267
 TQTreeFormulaObservable.cxx:268
 TQTreeFormulaObservable.cxx:269
 TQTreeFormulaObservable.cxx:270
 TQTreeFormulaObservable.cxx:271
 TQTreeFormulaObservable.cxx:272
 TQTreeFormulaObservable.cxx:273
 TQTreeFormulaObservable.cxx:274
 TQTreeFormulaObservable.cxx:275
 TQTreeFormulaObservable.cxx:276
 TQTreeFormulaObservable.cxx:277
 TQTreeFormulaObservable.cxx:278
 TQTreeFormulaObservable.cxx:279
 TQTreeFormulaObservable.cxx:280
 TQTreeFormulaObservable.cxx:281
 TQTreeFormulaObservable.cxx:282
 TQTreeFormulaObservable.cxx:283
 TQTreeFormulaObservable.cxx:284
 TQTreeFormulaObservable.cxx:285
 TQTreeFormulaObservable.cxx:286
 TQTreeFormulaObservable.cxx:287
 TQTreeFormulaObservable.cxx:288
 TQTreeFormulaObservable.cxx:289
 TQTreeFormulaObservable.cxx:290
 TQTreeFormulaObservable.cxx:291
 TQTreeFormulaObservable.cxx:292
 TQTreeFormulaObservable.cxx:293