CMS 3D CMS Logo

FWGUIEventDataAdder.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Core
4 // Class : FWGUIEventDataAdder
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Fri Jun 13 09:58:53 EDT 2008
11 //
12 
13 // system include files
14 #include <iostream>
15 #include <sigc++/signal.h>
16 #include <functional>
17 #include <algorithm>
18 #include <cctype>
19 #include <string>
20 
21 #include "TGFrame.h"
22 #include "TGTextEntry.h"
23 #include "TGButton.h"
24 #include "TGMsgBox.h"
25 #include "TClass.h"
26 #include "TFile.h"
27 #include "TTree.h"
28 #include "TBranch.h"
29 
30 // user include files
42 //
43 // constants, enums and typedefs
44 //
45 static const std::string &dataForColumn(const FWJobMetadataManager::Data &iData, int iCol) {
46  switch (iCol) {
47  case 0:
48  return iData.purpose_;
49  break;
50  case 4:
51  return iData.type_;
52  break;
53  case 1:
54  return iData.moduleLabel_;
55  break;
56  case 2:
57  return iData.productInstanceLabel_;
58  break;
59  case 3:
60  return iData.processName_;
61  break;
62  default:
63  break;
64  }
65  static const std::string s_blank;
66  return s_blank;
67 }
68 
69 static const unsigned int kNColumns = 5;
71 public:
73 
74  int numberOfRows() const override { return m_row_to_index.size(); }
75  int numberOfColumns() const override { return kNColumns; }
76 
81  virtual void sortWithFilter(const char *filter) {
82  m_filter = filter;
83  sort(-1, sortOrder());
84  dataChanged();
85  }
86 
87  int unsortedRowNumber(int iSortedRowNumber) const override { return m_row_to_index[iSortedRowNumber]; }
88 
89  void implSort(int col, bool sortOrder) override;
90  std::vector<std::string> getTitles() const override {
91  std::vector<std::string> returnValue;
92  returnValue.reserve(kNColumns);
93  returnValue.push_back("Purpose");
94  returnValue.push_back("Module Label");
95  returnValue.push_back("Product Instance Label");
96  returnValue.push_back("Process Name");
97  returnValue.push_back("C++ Class");
98  return returnValue;
99  }
100 
101  FWTableCellRendererBase *cellRenderer(int iSortedRowNumber, int iCol) const override {
102  if (static_cast<int>(m_row_to_index.size()) > iSortedRowNumber) {
103  int unsortedRow = m_row_to_index[iSortedRowNumber];
104  const FWJobMetadataManager::Data &data = (m_manager->usableData())[unsortedRow];
105 
106  m_renderer.setData(dataForColumn(data, iCol), m_selectedRow == unsortedRow);
107  } else {
108  m_renderer.setData(std::string(), false);
109  }
110  return &m_renderer;
111  }
112 
113  void setSelection(int row, int mask) {
114  if (mask == 4) {
115  if (row == m_selectedRow) {
116  row = -1;
117  }
118  }
119  changeSelection(row);
120  }
121 
122  virtual const std::string title() const { return "Viewable Collections"; }
123 
124  int selectedRow() const { return m_selectedRow; }
125  //virtual void sort (int col, bool reset = false);
126  virtual bool rowIsSelected(int row) const { return m_selectedRow == row; }
127 
128  void reset() {
129  changeSelection(-1);
130  m_row_to_index.clear();
131  m_row_to_index.reserve(m_manager->usableData().size());
132  for (unsigned int i = 0; i < m_manager->usableData().size(); ++i) {
133  m_row_to_index.push_back(i);
134  }
135  dataChanged();
136  }
137  sigc::signal<void(int)> indexSelected_;
138 
139 private:
140  void changeSelection(int iRow) {
141  if (iRow != m_selectedRow) {
142  m_selectedRow = iRow;
143  if (-1 == iRow) {
144  indexSelected_(-1);
145  } else {
146  indexSelected_(iRow);
147  }
149  }
150  }
152  std::vector<int> m_row_to_index;
156 };
157 
158 namespace {
159  void strip(std::string &source, const char *str) {
160  std::string remove(str);
161  while (true) {
162  size_t found = source.find(remove);
163  if (found == std::string::npos)
164  break;
165  source.erase(found, remove.size());
166  }
167  }
168 
186  class SortAndFilter {
187  public:
188  SortAndFilter(const char *filter, int column, bool order, const std::vector<FWJobMetadataManager::Data> &data)
189  : m_filter(filter), m_column(column), m_order(order), m_data(data) {
190  simplify(m_filter);
191  m_weights.resize(data.size());
192 
193  // Calculate whether or not all the entries match the given filter.
194  // This is done only once, since it's invariant under permutations
195  // of the data.
196  for (size_t i = 0, e = m_weights.size(); i != e; ++i)
197  m_weights[i] = matchesFilter(m_data[i]);
198  }
199 
203  static void simplify(std::string &str) {
204  std::transform(str.begin(), str.end(), str.begin(), tolower);
205  strip(str, "std::");
206  strip(str, "edm::");
207  strip(str, "vector<");
208  strip(str, "clonepolicy");
209  strip(str, "ownvector");
210  strip(str, "rangemap<");
211  strip(str, "strictweakordering<");
212  strip(str, "sortedcollection<");
213  strip(str, "reco::");
214  strip(str, "edmnew::");
215  }
216 
217  unsigned int matches(const std::string &str) const {
218  std::string up(str);
219  simplify(up);
220  const char *begin = up.c_str();
221 
222  // If the filter is empty, we consider anything as matching
223  // (i.e. it will not loop).
224  // If the filter is not empty but the string to be matched is, we
225  // consider it as if it was not matching.
226  if ((!m_filter.empty()) && str.empty())
227  return 0;
228 
229  // There are two level of matching. "Full string" and
230  // "All characters". "Full string" matches return an higher weight
231  // and therefore should appear on top.
232  if (strstr(begin, m_filter.c_str()))
233  return 2;
234 
235  return 0;
236  }
237 
243  unsigned int matchesFilter(const FWJobMetadataManager::Data &data) const {
244  std::vector<unsigned int> scores;
245  scores.reserve(10);
246  scores.push_back(matches(data.purpose_));
247  scores.push_back(matches(data.type_));
248  scores.push_back(matches(data.moduleLabel_));
249  scores.push_back(matches(data.productInstanceLabel_));
250  scores.push_back(matches(data.processName_));
251  std::sort(scores.begin(), scores.end());
252  return scores.back();
253  }
254 
258  bool operator()(const int &aIndex, const int &bIndex) {
259  // In case no column is selected, we sort by relevance of the
260  // filter.
261  if (m_column == -1)
262  return m_weights[aIndex] >= m_weights[bIndex];
263 
264  const FWJobMetadataManager::Data &a = m_data[aIndex];
265  const FWJobMetadataManager::Data &b = m_data[bIndex];
266 
267  if (m_order)
268  return dataForColumn(a, m_column) < dataForColumn(b, m_column);
269  else
270  return dataForColumn(a, m_column) > dataForColumn(b, m_column);
271  }
272 
273  private:
274  std::string m_filter;
275  int m_column;
276  bool m_order;
277 
278  const std::vector<FWJobMetadataManager::Data> &m_data;
279  std::vector<unsigned int> m_weights;
280  };
281 
282  void doSort(int column,
283  const char *filter,
284  bool descentSort,
285  const std::vector<FWJobMetadataManager::Data> &iData,
286  std::vector<int> &oRowToIndex) {
287  std::vector<int> ordered;
288  ordered.reserve(iData.size());
289 
290  for (size_t i = 0, e = iData.size(); i != e; ++i)
291  ordered.push_back(i);
292 
293  SortAndFilter sorter(filter, column, descentSort, iData);
294  // GE: Using std::sort does not work for some reason... Bah...
295  std::stable_sort(ordered.begin(), ordered.end(), sorter);
296 
297  oRowToIndex.clear();
298  oRowToIndex.reserve(ordered.size());
299  // Only keep track of the rows that match.
300  for (size_t i = 0, e = ordered.size(); i != e; ++i)
301  if (sorter.matchesFilter(iData[ordered[i]]) != 0)
302  oRowToIndex.push_back(ordered[i]);
303  }
304 } // namespace
305 
306 void DataAdderTableManager::implSort(int column, bool sortOrder) {
308 }
309 
310 //
311 // static data member definitions
312 //
313 
314 //
315 // constructors and destructor
316 //
317 
319  UInt_t iHeight,
320  FWEventItemsManager *iManager,
321  TGFrame *iParent,
322  FWJobMetadataManager *iMetadataManager)
323  : m_manager(iManager), m_metadataManager(iMetadataManager), m_parentFrame(iParent) {
325  createWindow();
326 }
327 
328 // FWGUIEventDataAdder::FWGUIEventDataAdder(const FWGUIEventDataAdder& rhs)
329 // {
330 // // do actual copying here;
331 // }
332 
334  /*
335  // m_frame->Cleanup();
336  // delete m_frame;
337  m_frame=0;
338  // delete m_tableWidget;
339  m_tableWidget=0;
340  delete m_tableManager;
341  m_tableManager=0;
342  */
343 }
344 
345 //
346 // assignment operators
347 //
348 // const FWGUIEventDataAdder& FWGUIEventDataAdder::operator=(const FWGUIEventDataAdder& rhs)
349 // {
350 // //An exception safe implementation is
351 // FWGUIEventDataAdder temp(rhs);
352 // swap(rhs);
353 //
354 // return *this;
355 // }
356 
357 //
358 // member functions
359 //
361  TClass *theClass = TClass::GetClass(m_type.c_str());
362  if (nullptr == theClass) {
363  return;
364  }
366  if (moduleLabel.empty()) {
367  return;
368  }
369 
370  const std::string name = m_name->GetText();
371  if (name.empty()) {
372  return;
373  }
374 
375  if (m_manager->find(name)) {
376  TString msg("Event item '");
377  msg += name;
378  msg += "' is already registered. Please use another name.";
379  fwLog(fwlog::kWarning) << msg.Data() << std::endl;
380  new TGMsgBox(gClient->GetDefaultRoot(), m_frame, "Error - Name conflict", msg, kMBIconExclamation, kMBOk);
381  return;
382  }
383 
384  int largest = -1;
385  if (m_manager->begin() != m_manager->end()) {
386  if (*(m_manager->begin()))
387  largest = (*(m_manager->begin()))->layer();
388  }
389  for (FWEventItemsManager::const_iterator it = m_manager->begin(), itEnd = m_manager->end(); it != itEnd; ++it) {
390  if ((*it) && largest < (*it)->layer()) {
391  largest = (*it)->layer();
392  }
393  }
394  ++largest;
396  if (m_doNotUseProcessName->IsOn() && m_doNotUseProcessName->IsEnabled()) {
397  processName = "";
398  }
400  theClass,
401  m_purpose,
403  moduleLabel,
405  processName,
406  "",
407  largest);
408  m_manager->add(desc);
409 }
410 
412  addNewItem();
413  windowIsClosing();
414 }
415 
417  // Map main frame
418  if (nullptr == m_frame) {
419  createWindow();
420  }
421  m_frame->MapWindow();
422 }
423 
425  m_name->SetText("");
426  m_search->SetText("");
427  m_purpose.clear();
428  m_type.clear();
429  m_moduleLabel.clear();
430  m_processName.clear();
431  m_productInstanceLabel.clear();
432  m_apply->SetEnabled(false);
433  m_applyAndClose->SetEnabled(false);
434 
435  m_frame->UnmapWindow();
436  m_frame->DontCallClose();
437 }
438 
442 }
443 
447  std::bind(&FWGUIEventDataAdder::newIndexSelected, this, std::placeholders::_1));
448 
449  m_frame = new TGTransientFrame(gClient->GetDefaultRoot(), m_parentFrame, 600, 400);
450  m_frame->Connect("CloseWindow()", "FWGUIEventDataAdder", this, "windowIsClosing()");
451 
452  FWDialogBuilder builder(m_frame);
453  TGTextButton *cancelButton, *resetButton;
454 
455  builder.indent(10)
456  .spaceDown(15)
457  .addLabel("Search:", 0)
458  .expand(false)
459  .spaceUp(4)
460  .floatLeft(4)
461  .addTextEntry("", &m_search)
462  .spaceUp(0)
463  .frameSpaceDown(10)
464  .addLabel("Viewable Collections", 8)
465  .frameSpaceDown(5)
467  .expand(true, true)
468  .addLabel("Name:", 0)
469  .expand(false)
470  .spaceUp(4)
471  .floatLeft(4)
472  .addTextEntry("", &m_name)
473  .spaceUp(0)
474  .floatLeft(4)
475  .addTextButton(" Reset ", &resetButton)
476  .expand(false, false)
477  .frameSpaceUpDown(5)
478  .addCheckbox(
479  "Do not use Process Name and "
480  "instead only get this data "
481  "from the most recent Process",
483  .frameSpaceDown(15)
484  .hSpacer()
485  .floatLeft(0)
486  .addTextButton(" Close ", &cancelButton)
487  .expand(false)
488  .floatLeft(4)
489  .addTextButton(" Add Data ", &m_apply)
490  .expand(false)
491  .floatLeft(4)
492  .addTextButton(" Add Data && Close ", &m_applyAndClose)
493  .expand(false)
494  .spaceRight(25)
495  .spaceDown(15);
496 
497  m_search->Connect("TextChanged(const char *)", "FWGUIEventDataAdder", this, "updateFilterString(const char *)");
498  m_search->SetEnabled(true);
502  m_tableWidget->Connect("rowClicked(Int_t,Int_t,Int_t,Int_t,Int_t)",
503  "FWGUIEventDataAdder",
504  this,
505  "rowClicked(Int_t,Int_t,Int_t,Int_t,Int_t)");
506 
508  m_name->SetState(true);
509  resetButton->SetEnabled(true);
510  resetButton->Connect("Clicked()", "FWGUIEventDataAdder", this, "resetNameEntry()");
511  m_doNotUseProcessName->SetState(kButtonDown);
512  cancelButton->Connect("Clicked()", "FWGUIEventDataAdder", this, "windowIsClosing()");
513  cancelButton->SetEnabled(true);
514  m_apply->Connect("Clicked()", "FWGUIEventDataAdder", this, "addNewItem()");
515  m_applyAndClose->Connect("Clicked()", "FWGUIEventDataAdder", this, "addNewItemAndClose()");
516 
517  m_frame->SetWindowName("Add Collection");
518  m_frame->MapSubwindows();
519  m_frame->Layout();
520 }
521 
528  m_tableManager->sort(0, true);
529 }
530 
532  m_name->SetText(m_apply->IsEnabled() ? m_moduleLabel.c_str() : "", kFALSE);
533 }
534 
535 void FWGUIEventDataAdder::newIndexSelected(int iSelectedIndex) {
536  if (-1 != iSelectedIndex) {
537  std::vector<FWJobMetadataManager::Data> &metadata = m_metadataManager->usableData();
538  m_purpose = metadata[iSelectedIndex].purpose_;
539  m_type = metadata[iSelectedIndex].type_;
540  std::string oldModuleLabel = m_moduleLabel;
541  m_moduleLabel = metadata[iSelectedIndex].moduleLabel_;
542  m_productInstanceLabel = metadata[iSelectedIndex].productInstanceLabel_;
543  m_processName = metadata[iSelectedIndex].processName_;
544 
545  if (strlen(m_name->GetText()) == 0 || oldModuleLabel == m_name->GetText()) {
546  m_name->SetText(m_moduleLabel.c_str());
547  }
548  m_apply->SetEnabled(true);
549  m_applyAndClose->SetEnabled(true);
550 
551  //Check to see if this is the last process, if it is then we can let the user decide
552  // to not use the process name when doing the lookup. This makes a saved configuration
553  // more robust. However, if they choose a collection not from the last process then we need the
554  // process name in order to correctly get the data they want
555  bool isMostRecentProcess = true;
556  int index = 0;
557  for (std::vector<FWJobMetadataManager::Data>::iterator it = metadata.begin(), itEnd = metadata.end();
558  it != itEnd && isMostRecentProcess;
559  ++it, ++index) {
560  if (index == iSelectedIndex) {
561  continue;
562  }
563  if (it->moduleLabel_ == m_moduleLabel && it->purpose_ == m_purpose && it->type_ == m_type &&
564  it->productInstanceLabel_ == m_productInstanceLabel) {
565  //see if this process is newer than the data requested
566 
567  for (size_t pni = 0, pne = m_metadataManager->processNamesInJob().size(); pni != pne; ++pni) {
569  if (m_processName == processName)
570  break;
571 
572  if (it->processName_ == processName) {
573  isMostRecentProcess = false;
574  break;
575  }
576  }
577  }
578  }
579  if (isMostRecentProcess) {
580  if (!m_doNotUseProcessName->IsEnabled()) {
581  m_doNotUseProcessName->SetEnabled(true);
582  }
583  } else {
584  //NOTE: must remember state before we get here because 'enable' and 'on' are mutually
585  // exlcusive :(
586  m_doNotUseProcessName->SetEnabled(false);
587  }
588  }
589 }
590 
591 void FWGUIEventDataAdder::rowClicked(Int_t iRow, Int_t iButton, Int_t iKeyMod, Int_t, Int_t) {
592  if (iButton == kButton1) {
593  m_tableManager->setSelection(iRow, iKeyMod);
594  }
595 }
596 
597 //
598 // const member functions
599 //
600 
601 //
602 // static member functions
603 //
FWDialogBuilder & spaceUp(size_t spacing=3)
size
Write out results.
Definition: BitonicSort.h:7
FWTextTableCellRenderer m_renderer
TGTextButton * m_applyAndClose
void implSort(int col, bool sortOrder) override
Called by &#39;sort&#39; method to actually handle the sorting of the rows. Arguments are the same as &#39;sort&#39;...
bool sortOrder(void)
The current sort order for the table.
void setSelection(int row, int mask)
FWEventItemsManager * m_manager
FWDialogBuilder & addTextButton(const char *text, TGTextButton **out=nullptr)
std::vector< int > m_row_to_index
void sort(int iCol, bool iSortOrder)
Call to have table sorted on values in column iCol with the sort order being descending if iSortOrder...
std::vector< std::string > & processNamesInJob()
void SetHeaderBackgroundColor(Pixel_t)
void dataChanged()
Classes which inherit from FWTableManagerBase must call this when their underlying data changes...
int numberOfColumns() const override
Number of columns in the table.
FWDialogBuilder & addLabel(const char *text, size_t fontSize=12, size_t weight=0, TGLabel **out=nullptr)
static const FWDisplayProperties defaultProperties
FWDialogBuilder & addCheckbox(const char *text, TGCheckButton **out=nullptr)
const FWEventItem * find(const std::string &iName) const
constexpr uint32_t mask
Definition: gpuClustering.h:26
void SetLineSeparatorColor(Pixel_t)
int unsortedRowNumber(int iSortedRowNumber) const override
when passed the index to the sorted order of the rows it returns the original row number from the und...
virtual const std::string title() const
FWJobMetadataManager * m_metadataManager
std::string m_productInstanceLabel
void disableGrowInWidth()
FWDialogBuilder & frameSpaceDown(size_t spacing=3)
FWGUIEventDataAdder(UInt_t w, UInt_t, FWEventItemsManager *, TGFrame *, FWJobMetadataManager *)
void updateFilterString(const char *str)
FWDialogBuilder & frameSpaceUpDown(size_t spacing=3)
virtual void sortWithFilter(const char *filter)
std::vector< std::string > getTitles() const override
returns the title names for each column
std::vector< Data > & usableData()
FWEventItem * add(const FWPhysicsObjectDesc &iItem, const FWConfiguration *pbConf=nullptr, bool doSetEvent=true)
TGCheckButton * m_doNotUseProcessName
TGTransientFrame * m_frame
int numberOfRows() const override
Number of rows in the table.
void SetBackgroundColor(Pixel_t) override
FWDialogBuilder & hSpacer(size_t size=0)
FWDialogBuilder & addTextEntry(const char *defaultText, TGTextEntry **out)
void setData(const std::string &, bool isSelected)
FWDialogBuilder & floatLeft(size_t spacing=3)
#define fwLog(_level_)
Definition: fwLog.h:45
double b
Definition: hdecay.h:118
tuple msg
Definition: mps_check.py:286
FWDialogBuilder & addTable(FWTableManagerBase *manager, FWTableWidget **out=nullptr)
FWDialogBuilder & expand(size_t expandX=true, size_t expandY=false)
FWTableCellRendererBase * cellRenderer(int iSortedRowNumber, int iCol) const override
sigc::signal< void(int)> indexSelected_
static const std::string & dataForColumn(const FWJobMetadataManager::Data &iData, int iCol)
virtual bool rowIsSelected(int row) const
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
double a
Definition: hdecay.h:119
void visualPropertiesChanged()
Classes which inherit from FWTableManagerBase must call this when how the data is shown (e...
col
Definition: cuy.py:1009
FWTableWidget * m_tableWidget
DataAdderTableManager * m_tableManager
const_iterator begin() const
NOTE: iterator is allowed to return a null object for items that have been removed.
void rowClicked(Int_t iRow, Int_t iButton, Int_t iKeyMod, Int_t, Int_t)
sigc::signal< void()> metadataChanged_
const_iterator end() const
#define str(s)
DataAdderTableManager(FWJobMetadataManager *manager)
FWDialogBuilder & indent(int left=2, int right=-1)
std::vector< FWEventItem * >::const_iterator const_iterator
static std::string const source
Definition: EdmProvDump.cc:49
FWDialogBuilder & spaceDown(size_t spacing=3)
FWJobMetadataManager * m_manager
static const unsigned int kNColumns
FWDialogBuilder & spaceRight(size_t spacing=3)
unsigned transform(const HcalDetId &id, unsigned transformCode)