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