Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-05 22:48:11

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWInterface
0004 // Class  :     FWPSetTableManager
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:
0010 //         Created:  Mon Feb 28 17:06:54 CET 2011
0011 //
0012 
0013 #include <map>
0014 #include <stdexcept>
0015 
0016 #include "Fireworks/FWInterface/src/FWPSetTableManager.h"
0017 #include "Fireworks/FWInterface/src/FWPSetCellEditor.h"
0018 #include "Fireworks/TableWidget/interface/FWTabularWidget.h"
0019 #include "Fireworks/TableWidget/interface/GlobalContexts.h"
0020 #include "Fireworks/Core/interface/fwLog.h"
0021 
0022 #include "FWCore/Framework/interface/ScheduleInfo.h"
0023 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0024 #include "FWCore/Utilities/interface/Exception.h"
0025 //
0026 // constants, enums and typedefs
0027 //
0028 
0029 //
0030 // static data member definitions
0031 //
0032 
0033 // FIXME: copied from Entry.cc should find a way to use the original
0034 //        table.
0035 struct TypeTrans {
0036   TypeTrans();
0037 
0038   typedef std::vector<std::string> CodeMap;
0039   CodeMap table_;
0040   std::map<std::string, char> type2Code_;
0041 };
0042 
0043 TypeTrans::TypeTrans() : table_(255) {
0044   table_['b'] = "vBool";
0045   table_['B'] = "bool";
0046   table_['i'] = "vint32";
0047   table_['I'] = "int32";
0048   table_['u'] = "vuint32";
0049   table_['U'] = "uint32";
0050   table_['l'] = "vint64";
0051   table_['L'] = "int64";
0052   table_['x'] = "vuint64";
0053   table_['X'] = "uint64";
0054   table_['s'] = "vstring";
0055   table_['S'] = "string";
0056   table_['d'] = "vdouble";
0057   table_['D'] = "double";
0058   table_['p'] = "vPSet";
0059   table_['P'] = "PSet";
0060   table_['T'] = "path";
0061   table_['F'] = "FileInPath";
0062   table_['t'] = "InputTag";
0063   table_['v'] = "VInputTag";
0064   table_['g'] = "ESInputTag";
0065   table_['G'] = "VESInputTag";
0066   table_['e'] = "VEventID";
0067   table_['E'] = "EventID";
0068   table_['m'] = "VLuminosityBlockID";
0069   table_['M'] = "LuminosityBlockID";
0070   table_['a'] = "VLuminosityBlockRange";
0071   table_['A'] = "LuminosityBlockRange";
0072   table_['r'] = "VEventRange";
0073   table_['R'] = "EventRange";
0074 
0075   for (CodeMap::const_iterator itCode = table_.begin(), itCodeEnd = table_.end(); itCode != itCodeEnd; ++itCode) {
0076     type2Code_[*itCode] = (itCode - table_.begin());
0077   }
0078 }
0079 
0080 static TypeTrans const sTypeTranslations;
0081 
0082 //
0083 // constructors and destructor
0084 //
0085 
0086 FWPSetTableManager::FWPSetTableManager() : m_selectedRow(-1) {
0087   TGGC *hc = new TGGC(FWTextTableCellRenderer::getDefaultHighlightGC());
0088   hc->SetForeground(0xdddddd);
0089 
0090   m_renderer.setHighlightContext(hc);
0091 
0092   recalculateVisibility();
0093   visualPropertiesChanged();
0094 }
0095 
0096 FWPSetTableManager::~FWPSetTableManager() {}
0097 
0098 //==============================================================================
0099 //==============================================================================
0100 //========== IMPORT CMSSW CONFIG TO TABLE ======================================
0101 //==============================================================================
0102 //==============================================================================
0103 
0104 void FWPSetTableManager::handlePSetEntry(edm::ParameterSetEntry &entry, const std::string &key) {
0105   PSetData data;
0106   data.label = key;
0107   data.tracked = entry.isTracked();
0108   data.level = m_parentStack.size();
0109   data.parent = m_parentStack.back();
0110   data.type = 'P';
0111   data.module = m_modules.size() - 1;
0112   data.path = m_paths.size() - 1;
0113   data.pset = &entry.psetForUpdate();
0114   data.editable = false;
0115   m_parentStack.push_back(m_entries.size());
0116   m_entries.push_back(data);
0117 
0118   handlePSet(data.pset);
0119   m_parentStack.pop_back();
0120 }
0121 
0122 void FWPSetTableManager::handleVPSetEntry(edm::VParameterSetEntry &entry, const std::string &key) {
0123   PSetData data;
0124   data.label = key;
0125   data.tracked = entry.isTracked();
0126   data.level = m_parentStack.size();
0127   data.parent = m_parentStack.back();
0128   data.type = 'p';
0129   data.module = m_modules.size() - 1;
0130   data.path = m_paths.size() - 1;
0131   data.editable = false;
0132   m_parentStack.push_back(m_entries.size());
0133   m_entries.push_back(data);
0134 
0135   std::stringstream ss;
0136 
0137   for (size_t i = 0, e = entry.vpset().size(); i != e; ++i) {
0138     ss.str("");
0139     ss << key << "[" << i << "]";
0140     PSetData vdata;
0141     vdata.label = ss.str();
0142     vdata.tracked = entry.isTracked();
0143     vdata.level = m_parentStack.size();
0144     vdata.parent = m_parentStack.back();
0145     vdata.module = m_modules.size() - 1;
0146     vdata.path = m_paths.size() - 1;
0147     vdata.editable = false;
0148     vdata.pset = &entry.vpsetForUpdate()[i];
0149     m_parentStack.push_back(m_entries.size());
0150     m_entries.push_back(vdata);
0151     handlePSet(&entry.vpsetForUpdate()[i]);
0152     m_parentStack.pop_back();
0153   }
0154   m_parentStack.pop_back();
0155 }
0156 
0157 void FWPSetTableManager::handlePSet(edm::ParameterSet *psp) {
0158   edm::ParameterSet &ps = *psp;
0159 
0160   typedef edm::ParameterSet::table::const_iterator TIterator;
0161   for (TIterator i = ps.tbl().begin(), e = ps.tbl().end(); i != e; ++i)
0162     handleEntry(i->second, i->first);
0163 
0164   typedef edm::ParameterSet::psettable::const_iterator PSIterator;
0165   for (PSIterator i = ps.psetTable().begin(), e = ps.psetTable().end(); i != e; ++i)
0166     handlePSetEntry(const_cast<edm::ParameterSetEntry &>(i->second), i->first);
0167 
0168   typedef edm::ParameterSet::vpsettable::const_iterator VPSIterator;
0169   for (VPSIterator i = ps.vpsetTable().begin(), e = ps.vpsetTable().end(); i != e; ++i)
0170     handleVPSetEntry(const_cast<edm::VParameterSetEntry &>(i->second), i->first);
0171 }
0172 
0173 template <class T>
0174 void FWPSetTableManager::createScalarString(PSetData &data, T v) {
0175   std::stringstream ss;
0176   ss << v;
0177   data.value = ss.str();
0178   m_entries.push_back(data);
0179 }
0180 
0181 template <typename T>
0182 void FWPSetTableManager::createVectorString(FWPSetTableManager::PSetData &data, const T &v, bool quotes) {
0183   std::stringstream ss;
0184   ss << "[";
0185   for (size_t ii = 0, ie = v.size(); ii != ie; ++ii) {
0186     if (quotes)
0187       ss << "\"";
0188     ss << v[ii];
0189     if (quotes)
0190       ss << "\"";
0191     if (ii + 1 != ie)
0192       ss << ", ";
0193   }
0194   ss << "]";
0195   data.value = ss.str();
0196   m_entries.push_back(data);
0197 }
0198 
0199 void FWPSetTableManager::handleEntry(const edm::Entry &entry, const std::string &key) {
0200   std::stringstream ss;
0201   FWPSetTableManager::PSetData data;
0202   data.label = key;
0203   data.tracked = entry.isTracked();
0204   data.type = entry.typeCode();
0205   data.level = m_parentStack.size();
0206   data.parent = m_parentStack.back();
0207   data.module = m_modules.size() - 1;
0208   data.type = entry.typeCode();
0209   if (data.label[0] == '@')
0210     data.editable = false;
0211   else
0212     data.editable = true;
0213 
0214   switch (entry.typeCode()) {
0215     case 'b': {
0216       data.value = entry.getBool() ? "True" : "False";
0217       m_entries.push_back(data);
0218       break;
0219     }
0220     case 'B': {
0221       data.value = entry.getBool() ? "True" : "False";
0222       m_entries.push_back(data);
0223       break;
0224     }
0225     case 'i': {
0226       createVectorString(data, entry.getVInt32(), false);
0227       break;
0228     }
0229     case 'I': {
0230       createScalarString(data, entry.getInt32());
0231       break;
0232     }
0233     case 'u': {
0234       createVectorString(data, entry.getVUInt32(), false);
0235       break;
0236     }
0237     case 'U': {
0238       createScalarString(data, entry.getUInt32());
0239       break;
0240     }
0241     case 'l': {
0242       createVectorString(data, entry.getVInt64(), false);
0243       break;
0244     }
0245     case 'L': {
0246       createScalarString(data, entry.getInt32());
0247       break;
0248     }
0249     case 'x': {
0250       createVectorString(data, entry.getVUInt64(), false);
0251       break;
0252     }
0253     case 'X': {
0254       createScalarString(data, entry.getUInt64());
0255       break;
0256     }
0257     case 's': {
0258       createVectorString(data, entry.getVString(), false);
0259       break;
0260     }
0261     case 'S': {
0262       createScalarString(data, entry.getString());
0263       break;
0264     }
0265     case 'd': {
0266       createVectorString(data, entry.getVDouble(), false);
0267       break;
0268     }
0269     case 'D': {
0270       createScalarString(data, entry.getDouble());
0271       break;
0272     }
0273     case 'p': {
0274       // Matevz ???
0275       throw std::runtime_error("FWPSetTableManager::handleEntryGet, entry type 'p' not expected.");
0276       // std::vector<edm::ParameterSet> psets = entry.getVPSet();
0277       // for (size_t psi = 0, pse = psets.size(); psi != pse; ++psi)
0278       //    handlePSet(psets[psi]);
0279       break;
0280     }
0281     case 'P': {
0282       // Matevz ???
0283       throw std::runtime_error("FWPSetTableManager::handleEntry, entry type 'P not expected.");
0284       // handlePSet(entry.getPSet());
0285       break;
0286     }
0287     case 't': {
0288       data.value = entry.getInputTag().encode();
0289       m_entries.push_back(data);
0290       break;
0291     }
0292     case 'v': {
0293       std::vector<std::string> tags;
0294       tags.resize(entry.getVInputTag().size());
0295       for (size_t iti = 0, ite = tags.size(); iti != ite; ++iti)
0296         tags[iti] = entry.getVInputTag()[iti].encode();
0297       createVectorString(data, tags, true);
0298       break;
0299     }
0300     case 'g': {
0301       data.value = entry.getESInputTag().encode();
0302       m_entries.push_back(data);
0303       break;
0304     }
0305     case 'G': {
0306       std::vector<std::string> tags;
0307       tags.resize(entry.getVESInputTag().size());
0308       for (size_t iti = 0, ite = tags.size(); iti != ite; ++iti)
0309         tags[iti] = entry.getVESInputTag()[iti].encode();
0310       createVectorString(data, tags, true);
0311       break;
0312     }
0313     case 'F': {
0314       createScalarString(data, entry.getFileInPath().relativePath());
0315       break;
0316     }
0317     case 'e': {
0318       data.editable = false;
0319       std::vector<edm::EventID> ids;
0320       ids.resize(entry.getVEventID().size());
0321       for (size_t iri = 0, ire = ids.size(); iri != ire; ++iri)
0322         ids[iri] = entry.getVEventID()[iri];
0323       createVectorString(data, ids, true);
0324       break;
0325     }
0326     case 'E': {
0327       data.editable = false;
0328       createScalarString(data, entry.getEventID());
0329       break;
0330     }
0331     case 'm': {
0332       data.editable = false;
0333       std::vector<edm::LuminosityBlockID> ids;
0334       ids.resize(entry.getVLuminosityBlockID().size());
0335       for (size_t iri = 0, ire = ids.size(); iri != ire; ++iri)
0336         ids[iri] = entry.getVLuminosityBlockID()[iri];
0337       createVectorString(data, ids, true);
0338       break;
0339     }
0340     case 'M': {
0341       data.editable = false;
0342       createScalarString(data, entry.getLuminosityBlockID());
0343       break;
0344     }
0345     case 'a': {
0346       data.editable = false;
0347       std::vector<edm::LuminosityBlockRange> ranges;
0348       ranges.resize(entry.getVLuminosityBlockRange().size());
0349       for (size_t iri = 0, ire = ranges.size(); iri != ire; ++iri)
0350         ranges[iri] = entry.getVLuminosityBlockRange()[iri];
0351       createVectorString(data, ranges, true);
0352       break;
0353     }
0354     case 'A': {
0355       data.editable = false;
0356       createScalarString(data, entry.getLuminosityBlockRange());
0357       break;
0358     }
0359     case 'r': {
0360       data.editable = false;
0361       std::vector<edm::EventRange> ranges;
0362       ranges.resize(entry.getVEventRange().size());
0363       for (size_t iri = 0, ire = ranges.size(); iri != ire; ++iri)
0364         ranges[iri] = entry.getVEventRange()[iri];
0365       createVectorString(data, ranges, true);
0366       break;
0367     }
0368     case 'R': {
0369       data.editable = false;
0370       createScalarString(data, entry.getEventRange());
0371       break;
0372     }
0373     default: {
0374       break;
0375     }
0376   }
0377 }
0378 
0379 /* the actual structure of the model will not change, only
0380    its contents, because of the way CMSSW is designed,
0381    hence this method only needs to be called once.
0382    */
0383 void FWPSetTableManager::updateSchedule(const edm::ScheduleInfo *info) {
0384   if (!m_entries.empty())
0385     return;
0386   // Execute only once since the schedule itself
0387   // cannot be altered.
0388   assert(m_availablePaths.empty());
0389   info->availablePaths(m_availablePaths);
0390 
0391   for (size_t i = 0, e = m_availablePaths.size(); i != e; ++i) {
0392     PSetData pathEntry;
0393     const std::string &pathName = m_availablePaths[i];
0394     pathEntry.label = pathName;
0395     m_pathIndex.insert(std::make_pair(pathName, m_paths.size()));
0396 
0397     pathEntry.value = "Path";
0398     pathEntry.level = 0;
0399     pathEntry.parent = -1;
0400     pathEntry.path = i;
0401     pathEntry.editable = false;
0402 
0403     PathInfo pathInfo;
0404     pathInfo.entryId = m_entries.size();
0405     pathInfo.passed = false;
0406     pathInfo.moduleStart = m_modules.size();
0407     m_paths.push_back(pathInfo);
0408 
0409     m_parentStack.push_back(m_entries.size());
0410     m_entries.push_back(pathEntry);
0411 
0412     std::vector<std::string> pathModules;
0413     info->modulesInPath(pathName, pathModules);
0414 
0415     for (size_t mi = 0, me = pathModules.size(); mi != me; ++mi) {
0416       PSetData moduleEntry;
0417 
0418       const edm::ParameterSet *ps = info->parametersForModule(pathModules[mi]);
0419 
0420       const edm::ParameterSet::table &pst = ps->tbl();
0421       const edm::ParameterSet::table::const_iterator ti = pst.find("@module_edm_type");
0422       if (ti == pst.end())
0423         moduleEntry.value = "Unknown module name";
0424       else
0425         moduleEntry.value = ti->second.getString();
0426 
0427       moduleEntry.label = pathModules[mi];
0428       moduleEntry.parent = m_parentStack.back();
0429       moduleEntry.level = m_parentStack.size();
0430       moduleEntry.module = mi;
0431       moduleEntry.path = i;
0432       moduleEntry.editable = false;
0433 
0434       ModuleInfo moduleInfo;
0435       moduleInfo.path = m_paths.size() - 1;
0436       moduleInfo.entry = m_entries.size();
0437       moduleInfo.passed = false;
0438       moduleInfo.dirty = false;
0439       moduleInfo.orig_pset = new edm::ParameterSet(*ps);
0440       moduleInfo.current_pset = new edm::ParameterSet(*ps);
0441       m_modules.push_back(moduleInfo);
0442 
0443       moduleEntry.pset = moduleInfo.current_pset;
0444 
0445       m_parentStack.push_back(m_entries.size());
0446       m_entries.push_back(moduleEntry);
0447       handlePSet(moduleEntry.pset);
0448       m_parentStack.pop_back();
0449     }
0450     m_paths.back().moduleEnd = m_modules.size();
0451     m_parentStack.pop_back();
0452   }
0453 
0454   // Nothing is expanded by default.
0455   for (size_t i = 0, e = m_entries.size(); i != e; ++i)
0456     m_entries[i].expandedUser = false;
0457 
0458   m_filter = "";
0459 
0460   recalculateVisibility();
0461 }  //updateSchedule
0462 
0463 /** Update the status of a given path. This is the information 
0464     that changes on event by event basis.
0465    */
0466 void FWPSetTableManager::update(std::vector<PathUpdate> &pathUpdates) {
0467   // Reset all the path / module status information, so that
0468   // by default paths and modules are considered "not passed".
0469   for (size_t pi = 0, pe = m_paths.size(); pi != pe; ++pi)
0470     m_paths[pi].passed = false;
0471   for (size_t mi = 0, me = m_modules.size(); mi != me; ++mi)
0472     m_modules[mi].passed = false;
0473 
0474   // Update whether or not a given path / module passed selection.
0475   for (size_t pui = 0, pue = pathUpdates.size(); pui != pue; ++pui) {
0476     PathUpdate &update = pathUpdates[pui];
0477     std::map<std::string, size_t>::const_iterator index = m_pathIndex.find(update.pathName);
0478     if (index == m_pathIndex.end()) {
0479       fwLog(fwlog::kError) << "Path " << update.pathName << "cannot be found!" << std::endl;
0480       continue;
0481     }
0482     PathInfo &pathInfo = m_paths[index->second];
0483     pathInfo.passed = update.passed;
0484 
0485     for (size_t mi = pathInfo.moduleStart, me = pathInfo.moduleEnd; mi != me; ++mi) {
0486       ModuleInfo &moduleInfo = m_modules[mi];
0487       moduleInfo.passed = update.passed || ((mi - pathInfo.moduleStart) < update.choiceMaker);
0488     }
0489   }
0490 
0491   implSort(-1, true);
0492 }
0493 
0494 //==============================================================================
0495 //==============================================================================
0496 //=============== CELL EDITOR ACTIONS ==========================================
0497 //==============================================================================
0498 //==============================================================================
0499 
0500 void FWPSetTableManager::setCellValueEditor(FWPSetCellEditor *editor) {
0501   m_editor = editor;
0502   m_renderer.setCellEditor(m_editor);
0503 }
0504 
0505 /** Does not apply changes and closes window. */
0506 void FWPSetTableManager::cancelEditor() {
0507   if (!m_editor)
0508     return;
0509 
0510   //  printf("FWPSetTableManager::cancelEditor() \n");
0511   setSelection(-1, -1, 0);
0512   m_editor->UnmapWindow();
0513 }
0514 
0515 /** This is invoked every single time the
0516        editor contents must be applied to the selected entry in the pset. 
0517        @return true on success. 
0518 */
0519 bool FWPSetTableManager::applyEditor() {
0520   if (!m_editor)
0521     return false;
0522 
0523   if (m_selectedRow == -1 || m_selectedColumn != 1)
0524     return false;
0525 
0526   //  printf("FWPSetTableManager::applyEditor() \n");
0527   PSetData &data = m_entries[m_row_to_index[m_selectedRow]];
0528   PSetData &parent = m_entries[data.parent];
0529   bool success = false;
0530   try {
0531     success = m_editor->apply(data, parent);
0532 
0533     if (success) {
0534       data.value = m_editor->GetText();
0535       m_modules[data.module].dirty = true;
0536       setSelection(-1, -1, 0);
0537       m_editor->UnmapWindow();
0538       // ???
0539       // copy current to orig
0540     } else {
0541       // ???
0542       // set current from orig? reimport module ... hmmh, hard.
0543     }
0544   } catch (cms::Exception &e) {
0545     m_editor->SetForegroundColor(gVirtualX->GetPixel(kRed));
0546   }
0547   return success;
0548 }
0549 
0550 //==============================================================================
0551 //==============================================================================
0552 //========  TABLE UI MNG (virutals FWTableManagerBase virtuals, etc.)   =========
0553 //==============================================================================
0554 //==============================================================================
0555 const std::string FWPSetTableManager::title() const { return "Modules & their parameters"; }
0556 
0557 std::vector<std::string> FWPSetTableManager::getTitles() const {
0558   std::vector<std::string> returnValue;
0559   returnValue.reserve(numberOfColumns());
0560   returnValue.push_back("Label");
0561   returnValue.push_back("Value");
0562   return returnValue;
0563 }
0564 
0565 int FWPSetTableManager::selectedRow() const { return m_selectedRow; }
0566 
0567 int FWPSetTableManager::selectedColumn() const { return m_selectedColumn; }
0568 
0569 bool FWPSetTableManager::rowIsSelected(int row) const { return m_selectedRow == row; }
0570 
0571 int FWPSetTableManager::unsortedRowNumber(int unsorted) const { return unsorted; }
0572 
0573 int FWPSetTableManager::numberOfRows() const { return m_row_to_index.size(); }
0574 
0575 int FWPSetTableManager::numberOfColumns() const { return 2; }
0576 
0577 void FWPSetTableManager::setSelection(int iRow, int iColumn, int mask) {
0578   // printf("set selection %d %d mode %d\n", iRow, iColumn, mask);
0579 
0580   // Nothing changes if we clicked selected
0581   // twice the same cell.
0582   if (iRow == m_selectedRow && iColumn == m_selectedColumn)
0583     return;
0584 
0585   // Otherwise update the selection information
0586   // and notify observers.
0587   m_selectedRow = iRow;
0588   m_selectedColumn = iColumn;
0589   if (iColumn == 1 && iRow > 0) {
0590     int unsortedRow = m_row_to_index[iRow];
0591     const PSetData &data = m_entries[unsortedRow];
0592     if (m_editor && data.editable) {
0593       m_editor->MoveResize(0, cellHeight() * iRow, m_editor->GetWidth(), m_editor->GetHeight());
0594       m_editor->MapWindow();
0595       m_editor->SetText(data.value.c_str());
0596       m_editor->SetFocus();
0597       m_editor->SetCursorPosition(data.value.size() - 1);
0598     }
0599   } else {
0600     if (m_editor)
0601       m_editor->UnmapWindow();
0602   }
0603   visualPropertiesChanged();
0604 }
0605 
0606 std::vector<unsigned int> FWPSetTableManager::maxWidthForColumns() const {
0607   std::vector<unsigned int> ww = FWTableManagerBase::maxWidthForColumns();
0608   if (ww.size() > 1 && ww[1] > 0) {
0609     // printf("dim W %d \n",ww[1]);
0610     // printf("dim H %d \n",cellHeight());
0611     if (m_editor)
0612       m_editor->MoveResize(m_editor->GetX(), m_editor->GetY(), ww[1], cellHeight());
0613   }
0614   return ww;
0615 }
0616 
0617 void FWPSetTableManager::implSort(int, bool) {}
0618 //______________________________________________________________________________
0619 
0620 void FWPSetTableManager::setExpanded(int row) {
0621   if (row == -1)
0622     return;
0623 
0624   int index = rowToIndex()[row];
0625   PSetData &data = m_entries[index];
0626 
0627   if (m_filter.empty() == false && data.childMatches == false)
0628     return;
0629 
0630   if (m_filter.empty())
0631     data.expandedUser = !data.expandedUser;
0632   else
0633     data.expandedFilter = !data.expandedFilter;
0634 
0635   recalculateVisibility();
0636   dataChanged();
0637   visualPropertiesChanged();
0638 }
0639 
0640 //______________________________________________________________________________
0641 
0642 FWTableCellRendererBase *FWPSetTableManager::cellRenderer(int iSortedRowNumber, int iCol) const {
0643   const static size_t maxSize = 512;  // maximum string length
0644 
0645   static TGGC boldGC(fireworks::boldGC());
0646   static TGGC italicGC(fireworks::italicGC());
0647   static TGGC defaultGC(FWTextTableCellRenderer::getDefaultGC());
0648 
0649   const static Pixel_t gray = 0x777777;
0650   const static Pixel_t red = gVirtualX->GetPixel(kRed - 5);
0651   const static Pixel_t green = gVirtualX->GetPixel(kGreen - 5);
0652 
0653   // return in case if nothing maches filter
0654   if (static_cast<int>(m_row_to_index.size()) <= iSortedRowNumber) {
0655     m_renderer.setData(std::string(), false);
0656     return &m_renderer;
0657   }
0658 
0659   int unsortedRow = m_row_to_index[iSortedRowNumber];
0660   const PSetData &data = m_entries[unsortedRow];
0661 
0662   std::string value;
0663   std::string label;
0664   TGGC *gc = nullptr;
0665   if (data.level == 0) {
0666     const PathInfo &path = m_paths[data.path];
0667     label = data.label + " (" + data.value + ")";
0668     gc = &boldGC;
0669     gc->SetForeground(path.passed ? green : red);
0670   } else if (data.level == 1) {
0671     // "passed" means if module made decision on path
0672     const ModuleInfo &module = m_modules[m_paths[data.path].moduleStart + data.module];
0673     label = data.label + " (" + data.value + ")";
0674     gc = (TGGC *)&boldGC;
0675     gc->SetForeground(module.passed ? green : red);
0676   } else {
0677     if (data.type > 0)
0678       label = data.label + " (" + sTypeTranslations.table_[data.type] + ")";
0679     else
0680       label = data.label;
0681     value = data.value;
0682 
0683     if (data.editable) {
0684       gc = &defaultGC;
0685     } else {
0686       gc = &italicGC;
0687       gc->SetForeground(gray);
0688     }
0689   }
0690 
0691   // check string size and cut it if necessary (problems with X11)
0692   if (iCol == 1 && value.size() >= maxSize) {
0693     if (iSortedRowNumber == m_selectedRow)
0694       fwLog(fwlog::kWarning) << "label: " << label << " has too long value " << value << std::endl << std::endl;
0695 
0696     value = value.substr(0, maxSize);
0697     value += "[truncated]";
0698     gc->SetForeground(gVirtualX->GetPixel(kMagenta));
0699   }
0700 
0701   // debug
0702   // label = Form("%s m[%d] childm[%d] ", label.c_str(), data.matches, data.childMatches);
0703 
0704   // set text attributes
0705   m_renderer.setGraphicsContext(gc);
0706   bool selected = data.matches && (m_filter.empty() == false);
0707   m_renderer.setData(iCol ? value : label, selected);
0708 
0709   // set  tree attributes
0710   bool isParent = false;
0711   bool isOpen = false;
0712   int indent = 0;
0713   if (iCol == 0) {
0714     if (m_filter.empty()) {
0715       size_t nextIdx = unsortedRow + 1;
0716       isParent = (nextIdx < m_entries.size() && m_entries[nextIdx].parent == (size_t)unsortedRow);
0717       isOpen = data.expandedUser;
0718     } else {
0719       isParent = data.childMatches;
0720       isOpen = data.expandedFilter && data.childMatches;
0721     }
0722 
0723     indent = data.level * 10;
0724     if (!isParent)
0725       indent += FWTextTreeCellRenderer::iconWidth();
0726   }
0727   m_renderer.setIsParent(isParent);
0728   m_renderer.setIsOpen(isOpen);
0729   m_renderer.setIndentation(indent);
0730 
0731   // If we are rendering the selected cell,
0732   // we show the editor.
0733   bool showEdit =
0734       (iCol == 1 && iSortedRowNumber == m_selectedRow && iCol == m_selectedColumn && value.size() < maxSize);
0735   m_renderer.showEditor(data.editable && showEdit);
0736 
0737   return &m_renderer;
0738 }  // cellRender()
0739 
0740 //______________________________________________________________________________
0741 
0742 void FWPSetTableManager::updateFilter(const char *filter) {
0743   m_filter = filter;
0744 
0745   if (m_filter.empty()) {
0746     // collapse entries when filter is removed
0747     for (size_t i = 0, e = m_entries.size(); i != e; ++i)
0748       m_entries[i].expandedFilter = false;
0749   } else {
0750     // Decide whether or not items match the filter.
0751     for (size_t i = 0, e = m_entries.size(); i != e; ++i) {
0752       PSetData &data = m_entries[i];
0753 
0754       // First of all decide whether or not we match
0755       // the filter.
0756       if (strstr(data.label.c_str(), m_filter.c_str()) || strstr(data.value.c_str(), m_filter.c_str()))
0757         data.matches = true;
0758       else
0759         data.matches = false;
0760     }
0761 
0762     // We reset whether or not a given parent has children that match the
0763     // filter, and we recompute the whole information by checking all the
0764     // children.
0765     for (size_t i = 0, e = m_entries.size(); i != e; ++i)
0766       m_entries[i].childMatches = false;
0767 
0768     std::vector<int> stack;
0769     int previousLevel = 0;
0770     for (size_t i = 0, e = m_entries.size(); i != e; ++i) {
0771       PSetData &data = m_entries[i];
0772       // Top level.
0773       if (data.parent == (size_t)-1) {
0774         previousLevel = 0;
0775         // std::cout << "reset stack for top level " << data.label << std::endl;
0776         stack.clear();
0777         continue;
0778       }
0779       // If the level is greater than the previous one,
0780       // it means we are among the children of the
0781       // previous level, hence we push the parent to
0782       // the stack.
0783       // If the level is not greater than the previous
0784       // one it means we have popped out n levels of
0785       // parents, where N is the difference between the
0786       // new and the old level. In this case we
0787       // pop up N parents from the stack.
0788       if (data.level > previousLevel)
0789         stack.push_back(data.parent);
0790       else
0791         for (size_t pi = 0, pe = previousLevel - data.level; pi != pe; ++pi)
0792           stack.pop_back();
0793 
0794       if (data.matches && m_entries[stack.back()].childMatches == false) {
0795         //  printf("match for %s with level %d\n",data.label.c_str(), data.level );
0796         for (size_t pi = 0, pe = stack.size(); pi != pe; ++pi) {
0797           //    printf("set child match to parent %s with level %d \n",m_entries[stack[pi]].label.c_str(), m_entries[stack[pi]].level);
0798           m_entries[stack[pi]].childMatches = true;
0799         }
0800       }
0801 
0802       previousLevel = data.level;
0803     }
0804 
0805     // expand to matching children
0806     for (size_t i = 0, e = m_entries.size(); i != e; ++i)
0807       m_entries[i].expandedFilter = m_entries[i].childMatches;
0808   }
0809 
0810   recalculateVisibility();
0811 
0812   dataChanged();
0813 }  // updateFilter()
0814 
0815 //______________________________________________________________________________
0816 
0817 void FWPSetTableManager::recalculateVisibility() {
0818   m_row_to_index.clear();
0819 
0820   // Decide about visibility.
0821   // * If the items are toplevel and they match the filter, they get shown
0822   //   in any case.
0823   // * If the item or any of its children match the filter, the item
0824   //   is visible.
0825   // * If the filter is empty and the parent is expanded.
0826   for (size_t i = 0, e = m_entries.size(); i != e; ++i) {
0827     PSetData &data = m_entries[i];
0828     if (data.parent == ((size_t)-1)) {
0829       data.visible = data.childMatches || data.matches || m_filter.empty();
0830     } else {
0831       if (m_filter.empty()) {
0832         data.visible = m_entries[data.parent].expandedUser && m_entries[data.parent].visible;
0833       } else {
0834         if (data.level < 2)
0835           data.visible = m_entries[data.parent].expandedFilter && m_entries[data.parent].visible &&
0836                          (data.matches || data.childMatches);
0837         else
0838           data.visible = m_entries[data.parent].expandedFilter && m_entries[data.parent].visible;
0839       }
0840     }
0841   }
0842 
0843   // Put in the index only the entries which are visible.
0844   for (size_t i = 0, e = m_entries.size(); i != e; ++i)
0845     if (m_entries[i].visible)
0846       m_row_to_index.push_back(i);
0847 }