CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 <boost/bind.hpp>
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 {
47  switch (iCol) {
48  case 0:
49  return iData.purpose_;
50  break;
51  case 4:
52  return iData.type_;
53  break;
54  case 1:
55  return iData.moduleLabel_;
56  break;
57  case 2:
58  return iData.productInstanceLabel_;
59  break;
60  case 3:
61  return iData.processName_;
62  break;
63  default:
64  break;
65  }
66  static const std::string s_blank;
67  return s_blank;
68 }
69 
70 static const unsigned int kNColumns = 5;
72 public:
74  m_manager(manager), m_selectedRow(-1), m_filter()
75  {
76  reset();
77  }
78 
79  virtual int numberOfRows() const override {
80  return m_row_to_index.size();
81  }
82  virtual int numberOfColumns() const override {
83  return kNColumns;
84  }
85 
90  virtual void sortWithFilter(const char *filter)
91  {
92  m_filter = filter;
93  sort(-1, sortOrder());
94  dataChanged();
95  }
96 
97  virtual int unsortedRowNumber(int iSortedRowNumber) const override {
98  return m_row_to_index[iSortedRowNumber];
99  }
100 
101  virtual void implSort(int col, bool sortOrder) override;
102  virtual std::vector<std::string> getTitles() const override {
103  std::vector<std::string> returnValue;
104  returnValue.reserve(kNColumns);
105  returnValue.push_back("Purpose");
106  returnValue.push_back("Module Label");
107  returnValue.push_back("Product Instance Label");
108  returnValue.push_back("Process Name");
109  returnValue.push_back("C++ Class");
110  return returnValue;
111  }
112 
113  virtual FWTableCellRendererBase* cellRenderer(int iSortedRowNumber, int iCol) const override
114  {
115 
116  if(static_cast<int>(m_row_to_index.size())>iSortedRowNumber) {
117  int unsortedRow = m_row_to_index[iSortedRowNumber];
118  const FWJobMetadataManager::Data& data = (m_manager->usableData())[unsortedRow];
119 
120  m_renderer.setData(dataForColumn(data,iCol),m_selectedRow==unsortedRow);
121  } else {
122  m_renderer.setData(std::string(),false);
123  }
124  return &m_renderer;
125  }
126 
127  void setSelection (int row, int mask) {
128  if(mask == 4) {
129  if( row == m_selectedRow) {
130  row = -1;
131  }
132  }
133  changeSelection(row);
134  }
135 
136  virtual const std::string title() const {
137  return "Viewable Collections";
138  }
139 
140  int selectedRow() const {
141  return m_selectedRow;
142  }
143  //virtual void sort (int col, bool reset = false);
144  virtual bool rowIsSelected(int row) const {
145  return m_selectedRow == row;
146  }
147 
148  void reset() {
149  changeSelection(-1);
150  m_row_to_index.clear();
151  m_row_to_index.reserve(m_manager->usableData().size());
152  for(unsigned int i =0; i < m_manager->usableData().size(); ++i) {
153  m_row_to_index.push_back(i);
154  }
155  dataChanged();
156  }
157  sigc::signal<void,int> indexSelected_;
158 private:
159  void changeSelection(int iRow) {
160  if(iRow != m_selectedRow) {
161  m_selectedRow=iRow;
162  if(-1 == iRow) {
163  indexSelected_(-1);
164  } else {
165  indexSelected_(iRow);
166  }
168  }
169  }
171  std::vector<int> m_row_to_index;
175 };
176 
177 namespace {
178 void strip(std::string &source, const char *str)
179  {
180  std::string remove(str);
181  while(true)
182  {
183  size_t found = source.find(remove);
184  if (found == std::string::npos)
185  break;
186  source.erase(found, remove.size());
187  }
188  }
189 
207  class SortAndFilter
208  {
209  public:
210  SortAndFilter(const char *filter, int column, bool order,
211  const std::vector<FWJobMetadataManager::Data> &data)
212  : m_filter(filter),
213  m_column(column),
214  m_order(order),
215  m_data(data)
216  {
217  simplify(m_filter);
218  m_weights.resize(data.size());
219 
220  // Calculate whether or not all the entries match the given filter.
221  // This is done only once, since it's invariant under permutations
222  // of the data.
223  for (size_t i = 0, e = m_weights.size(); i != e; ++i)
224  m_weights[i] = matchesFilter(m_data[i]);
225  }
226 
230  static void simplify(std::string &str)
231  {
232  std::transform(str.begin(), str.end(), str.begin(), tolower);
233  strip(str, "std::");
234  strip(str, "edm::");
235  strip(str, "vector<");
236  strip(str, "clonepolicy");
237  strip(str, "ownvector");
238  strip(str, "rangemap<");
239  strip(str, "strictweakordering<");
240  strip(str, "sortedcollection<");
241  strip(str, "reco::");
242  strip(str, "edmnew::");
243  }
244 
245  unsigned int matches(const std::string &str) const
246  {
247  std::string up(str);
248  simplify(up);
249  const char *begin = up.c_str();
250 
251  // If the filter is empty, we consider anything as matching
252  // (i.e. it will not loop).
253  // If the filter is not empty but the string to be matched is, we
254  // consider it as if it was not matching.
255  if ((!m_filter.empty()) && str.empty())
256  return 0;
257 
258  // There are two level of matching. "Full string" and
259  // "All characters". "Full string" matches return an higher weight
260  // and therefore should appear on top.
261  if (strstr(begin, m_filter.c_str()))
262  return 2;
263 
264  return 0;
265  }
266 
272  unsigned int matchesFilter(const FWJobMetadataManager::Data &data) const
273  {
274  std::vector<unsigned int> scores;
275  scores.reserve(10);
276  scores.push_back(matches(data.purpose_));
277  scores.push_back(matches(data.type_));
278  scores.push_back(matches(data.moduleLabel_));
279  scores.push_back(matches(data.productInstanceLabel_));
280  scores.push_back(matches(data.processName_));
281  std::sort(scores.begin(), scores.end());
282  return scores.back();
283  }
284 
288  bool operator()(const int &aIndex, const int &bIndex)
289  {
290  // In case no column is selected, we sort by relevance of the
291  // filter.
292  if (m_column == -1)
293  return m_weights[aIndex] >= m_weights[bIndex];
294 
295  const FWJobMetadataManager::Data &a = m_data[aIndex];
296  const FWJobMetadataManager::Data &b = m_data[bIndex];
297 
298  if (m_order)
299  return dataForColumn(a, m_column) < dataForColumn(b, m_column);
300  else
301  return dataForColumn(a, m_column) > dataForColumn(b, m_column);
302  }
303  private:
304  std::string m_filter;
305  int m_column;
306  bool m_order;
307 
308  const std::vector<FWJobMetadataManager::Data> &m_data;
309  std::vector<unsigned int> m_weights;
310  };
311 
312  void doSort(int column,
313  const char *filter,
314  bool descentSort,
315  const std::vector<FWJobMetadataManager::Data>& iData,
316  std::vector<int>& oRowToIndex)
317  {
318  std::vector<int> ordered;
319  ordered.reserve(iData.size());
320 
321  for (size_t i = 0, e = iData.size(); i != e; ++i)
322  ordered.push_back(i);
323 
324  SortAndFilter sorter(filter, column, descentSort, iData);
325  // GE: Using std::sort does not work for some reason... Bah...
326  std::stable_sort(ordered.begin(), ordered.end(), sorter);
327 
328  oRowToIndex.clear();
329  oRowToIndex.reserve(ordered.size());
330  // Only keep track of the rows that match.
331  for (size_t i = 0, e = ordered.size(); i != e; ++i)
332  if (sorter.matchesFilter(iData[ordered[i]]) != 0)
333  oRowToIndex.push_back(ordered[i]);
334  }
335 }
336 
337 void
338 DataAdderTableManager::implSort(int column, bool sortOrder)
339 {
340  doSort(column, m_filter.c_str(), sortOrder, m_manager->usableData(), m_row_to_index);
341 }
342 
343 //
344 // static data member definitions
345 //
346 
347 //
348 // constructors and destructor
349 //
350 
352  UInt_t iWidth,UInt_t iHeight,
353  FWEventItemsManager* iManager,
354  TGFrame* iParent,
355  FWJobMetadataManager *iMetadataManager)
356  :
357  m_manager(iManager),
358  m_metadataManager(iMetadataManager),
359  m_parentFrame(iParent)
360 {
362  createWindow();
363 }
364 
365 // FWGUIEventDataAdder::FWGUIEventDataAdder(const FWGUIEventDataAdder& rhs)
366 // {
367 // // do actual copying here;
368 // }
369 
371 {
372  /*
373  // m_frame->Cleanup();
374  // delete m_frame;
375  m_frame=0;
376  // delete m_tableWidget;
377  m_tableWidget=0;
378  delete m_tableManager;
379  m_tableManager=0;
380  */
381 }
382 
383 //
384 // assignment operators
385 //
386 // const FWGUIEventDataAdder& FWGUIEventDataAdder::operator=(const FWGUIEventDataAdder& rhs)
387 // {
388 // //An exception safe implementation is
389 // FWGUIEventDataAdder temp(rhs);
390 // swap(rhs);
391 //
392 // return *this;
393 // }
394 
395 //
396 // member functions
397 //
398 void
400 {
401  TClass* theClass = TClass::GetClass(m_type.c_str());
402  if(0==theClass) {
403  return;
404  }
405  const std::string moduleLabel = m_moduleLabel;
406  if(moduleLabel.empty()) {
407  return;
408  }
409 
410  const std::string name = m_name->GetText();
411  if(name.empty()) {
412  return;
413  }
414 
415  if ( m_manager->find( name ) ) {
416  TString msg("Event item '");
417  msg += name;
418  msg += "' is already registered. Please use another name.";
419  fwLog(fwlog::kWarning) << msg.Data() << std::endl;
420  new TGMsgBox(gClient->GetDefaultRoot(), m_frame,
421  "Error - Name conflict", msg, kMBIconExclamation, kMBOk);
422  return;
423  }
424 
425  int largest = -1;
426  if(m_manager->begin() != m_manager->end()) {
427  if ( *(m_manager->begin()) )
428  largest = (*(m_manager->begin()))->layer();
429  }
431  itEnd = m_manager->end();
432  it!=itEnd;
433  ++it) {
434  if((*it) && largest < (*it)->layer()) {
435  largest = (*it)->layer();
436  }
437  }
438  ++largest;
440  if(m_doNotUseProcessName->IsOn() && m_doNotUseProcessName->IsEnabled()) {
441  processName="";
442  }
443  FWPhysicsObjectDesc desc(name, theClass, m_purpose,
445  moduleLabel,
447  processName,
448  "",
449  largest);
450  m_manager->add(desc);
451 }
452 
453 void
455 {
456  addNewItem();
457  windowIsClosing();
458 }
459 
460 void
462 {
463  // Map main frame
464  if(0==m_frame) {
465  createWindow();
466  }
467  m_frame->MapWindow();
468 }
469 
470 void
472 {
473  m_name->SetText("");
474  m_search->SetText("");
475  m_purpose.clear();
476  m_type.clear();
477  m_moduleLabel.clear();
478  m_processName.clear();
479  m_productInstanceLabel.clear();
480  m_apply->SetEnabled(false);
481  m_applyAndClose->SetEnabled(false);
482 
483  m_frame->UnmapWindow();
484  m_frame->DontCallClose();
485 }
486 
487 void
489 {
492 }
493 
494 void
496 {
499 
500  m_frame = new TGTransientFrame(gClient->GetDefaultRoot(),m_parentFrame,600,400);
501  m_frame->Connect("CloseWindow()","FWGUIEventDataAdder",this,"windowIsClosing()");
502 
503  FWDialogBuilder builder(m_frame);
504  TGTextButton *cancelButton, *resetButton;
505 
506  builder.indent(10)
507  .spaceDown(15)
508  .addLabel("Search:", 0).expand(false).spaceUp(4).floatLeft(4)
509  .addTextEntry("", &m_search).spaceUp(0)
510  .frameSpaceDown(10)
511  .addLabel("Viewable Collections", 8)
512  .frameSpaceDown(5)
514  .addLabel("Name:", 0).expand(false).spaceUp(4).floatLeft(4)
515  .addTextEntry("", &m_name).spaceUp(0).floatLeft(4)
516  .addTextButton(" Reset ", &resetButton).expand(false, false)
517  .frameSpaceUpDown(5)
518  .addCheckbox("Do not use Process Name and "
519  "instead only get this data "
520  "from the most recent Process",
522  .frameSpaceDown(15)
523  .hSpacer().floatLeft(0)
524  .addTextButton(" Close ", &cancelButton).expand(false).floatLeft(4)
525  .addTextButton(" Add Data ", &m_apply).expand(false).floatLeft(4)
526  .addTextButton(" Add Data && Close ", &m_applyAndClose).expand(false)
527  .spaceRight(25).spaceDown(15);
528 
529  m_search->Connect("TextChanged(const char *)", "FWGUIEventDataAdder",
530  this, "updateFilterString(const char *)");
531  m_search->SetEnabled(true);
535  m_tableWidget->Connect("rowClicked(Int_t,Int_t,Int_t,Int_t,Int_t)",
536  "FWGUIEventDataAdder",this,
537  "rowClicked(Int_t,Int_t,Int_t,Int_t,Int_t)");
538 
540  m_name->SetState(true);
541  resetButton->SetEnabled(true);
542  resetButton->Connect("Clicked()", "FWGUIEventDataAdder", this, "resetNameEntry()");
543  m_doNotUseProcessName->SetState(kButtonDown);
544  cancelButton->Connect("Clicked()","FWGUIEventDataAdder", this, "windowIsClosing()");
545  cancelButton->SetEnabled(true);
546  m_apply->Connect("Clicked()", "FWGUIEventDataAdder", this, "addNewItem()");
547  m_applyAndClose->Connect("Clicked()", "FWGUIEventDataAdder", this, "addNewItemAndClose()");
548 
549  m_frame->SetWindowName("Add Collection");
550  m_frame->MapSubwindows();
551  m_frame->Layout();
552 }
553 
558 void
560 {
562  m_tableManager->sort(0, true);
563 }
564 
565 void
567 {
568  m_name->SetText(m_apply->IsEnabled() ? m_moduleLabel.c_str() : "", kFALSE);
569 }
570 
571 void
573 {
574  if(-1 != iSelectedIndex) {
575  std::vector<FWJobMetadataManager::Data> &metadata = m_metadataManager->usableData();
576  m_purpose = metadata[iSelectedIndex].purpose_;
577  m_type = metadata[iSelectedIndex].type_;
578  std::string oldModuleLabel = m_moduleLabel;
579  m_moduleLabel = metadata[iSelectedIndex].moduleLabel_;
580  m_productInstanceLabel = metadata[iSelectedIndex].productInstanceLabel_;
581  m_processName = metadata[iSelectedIndex].processName_;
582 
583  if(strlen(m_name->GetText())==0 || oldModuleLabel == m_name->GetText()) {
584  m_name->SetText(m_moduleLabel.c_str());
585  }
586  m_apply->SetEnabled(true);
587  m_applyAndClose->SetEnabled(true);
588 
589  //Check to see if this is the last process, if it is then we can let the user decide
590  // to not use the process name when doing the lookup. This makes a saved configuration
591  // more robust. However, if they choose a collection not from the last process then we need the
592  // process name in order to correctly get the data they want
593  bool isMostRecentProcess =true;
594  int index = 0;
595  for(std::vector<FWJobMetadataManager::Data>::iterator it = metadata.begin(), itEnd = metadata.end();
596  it != itEnd && isMostRecentProcess;
597  ++it,++index) {
598  if(index == iSelectedIndex) {continue;}
599  if(it->moduleLabel_ == m_moduleLabel &&
600  it->purpose_ == m_purpose &&
601  it->type_ == m_type &&
602  it->productInstanceLabel_ == m_productInstanceLabel) {
603  //see if this process is newer than the data requested
604 
605  for(size_t pni = 0, pne = m_metadataManager->processNamesInJob().size();
606  pni != pne; ++pni)
607  {
609  if (m_processName == processName)
610  break;
611 
612  if(it->processName_ == processName)
613  {
614  isMostRecentProcess = false;
615  break;
616  }
617  }
618  }
619  }
620  if(isMostRecentProcess) {
621  if(!m_doNotUseProcessName->IsEnabled()) {
622  m_doNotUseProcessName->SetEnabled(true);
623  }
624  } else {
625  //NOTE: must remember state before we get here because 'enable' and 'on' are mutually
626  // exlcusive :(
627  m_doNotUseProcessName->SetEnabled(false);
628  }
629  }
630 }
631 
632 void
633 FWGUIEventDataAdder::rowClicked(Int_t iRow,Int_t iButton,Int_t iKeyMod,Int_t,Int_t)
634 {
635  if(iButton==kButton1) {
636  m_tableManager->setSelection(iRow,iKeyMod);
637  }
638 }
639 
640 //
641 // const member functions
642 //
643 
644 //
645 // static member functions
646 //
FWDialogBuilder & spaceUp(size_t spacing=3)
Definition: BitonicSort.h:8
FWTextTableCellRenderer m_renderer
int i
Definition: DBlmapReader.cc:9
void SetBackgroundColor(Pixel_t)
TGTextButton * m_applyAndClose
virtual 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.
virtual bool rowIsSelected(int row) const
void setSelection(int row, int mask)
virtual int numberOfRows() const override
Number of rows in the table.
FWEventItemsManager * m_manager
FWDialogBuilder & addLabel(const char *text, size_t fontSize=12, size_t weight=0, TGLabel **out=0)
std::vector< int > m_row_to_index
sigc::signal< void > metadataChanged_
void sort(int iCol, bool iSortOrder)
Call to have table sorted on values in column iCol with the sort order being descending if iSortOrder...
virtual FWTableCellRendererBase * cellRenderer(int iSortedRowNumber, int iCol) const override
std::vector< std::string > & processNamesInJob()
void SetHeaderBackgroundColor(Pixel_t)
void dataChanged()
Classes which inherit from FWTableManagerBase must call this when their underlying data changes...
virtual const std::string title() const
FWDialogBuilder & addTable(FWTableManagerBase *manager, FWTableWidget **out=0)
static const FWDisplayProperties defaultProperties
void SetLineSeparatorColor(Pixel_t)
virtual 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...
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 & addTextButton(const char *text, TGTextButton **out=0)
FWDialogBuilder & frameSpaceUpDown(size_t spacing=3)
virtual int numberOfColumns() const override
Number of columns in the table.
virtual void sortWithFilter(const char *filter)
std::vector< Data > & usableData()
TGCheckButton * m_doNotUseProcessName
TGTransientFrame * m_frame
const FWEventItem * find(const std::string &iName) const
FWDialogBuilder & hSpacer(size_t size=0)
FWDialogBuilder & addTextEntry(const char *defaultText, TGTextEntry **out)
void setData(const std::string &, bool isSelected)
const_iterator begin() const
NOTE: iterator is allowed to return a null object for items that have been removed.
FWDialogBuilder & floatLeft(size_t spacing=3)
#define fwLog(_level_)
Definition: fwLog.h:50
double b
Definition: hdecay.h:120
FWDialogBuilder & expand(size_t expandX=true, size_t expandY=false)
static const std::string & dataForColumn(const FWJobMetadataManager::Data &iData, int iCol)
#define begin
Definition: vmac.h:30
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
double a
Definition: hdecay.h:121
sigc::signal< void, int > indexSelected_
void visualPropertiesChanged()
Classes which inherit from FWTableManagerBase must call this when how the data is shown (e...
const FWEventItem * add(const FWPhysicsObjectDesc &iItem, const FWConfiguration *pbConf=0)
FWTableWidget * m_tableWidget
DataAdderTableManager * m_tableManager
void rowClicked(Int_t iRow, Int_t iButton, Int_t iKeyMod, Int_t, Int_t)
virtual std::vector< std::string > getTitles() const override
returns the title names for each column
int col
Definition: cuy.py:1008
FWDialogBuilder & addCheckbox(const char *text, TGCheckButton **out=0)
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:43
tuple size
Write out results.
FWDialogBuilder & spaceDown(size_t spacing=3)
FWJobMetadataManager * m_manager
static const unsigned int kNColumns
const_iterator end() const
FWDialogBuilder & spaceRight(size_t spacing=3)