00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <iostream>
00016 #include <sigc++/signal.h>
00017 #include <boost/bind.hpp>
00018 #include <algorithm>
00019 #include <cctype>
00020 #include <string>
00021
00022 #include "TGFrame.h"
00023 #include "TGTextEntry.h"
00024 #include "TGButton.h"
00025 #include "TGMsgBox.h"
00026 #include "TClass.h"
00027 #include "TFile.h"
00028 #include "TTree.h"
00029 #include "TBranch.h"
00030
00031
00032 #include "Fireworks/Core/src/FWGUIEventDataAdder.h"
00033 #include "Fireworks/Core/interface/FWPhysicsObjectDesc.h"
00034 #include "Fireworks/Core/interface/FWEventItemsManager.h"
00035 #include "Fireworks/Core/interface/FWEventItem.h"
00036 #include "Fireworks/Core/interface/FWItemAccessorFactory.h"
00037 #include "Fireworks/Core/interface/FWJobMetadataManager.h"
00038 #include "Fireworks/TableWidget/interface/FWTableWidget.h"
00039 #include "Fireworks/TableWidget/interface/FWTableManagerBase.h"
00040 #include "Fireworks/TableWidget/interface/FWTextTableCellRenderer.h"
00041 #include "Fireworks/Core/interface/fwLog.h"
00042 #include "Fireworks/Core/src/FWDialogBuilder.h"
00043
00044
00045
00046 static const std::string& dataForColumn( const FWJobMetadataManager::Data& iData, int iCol)
00047 {
00048 switch (iCol) {
00049 case 0:
00050 return iData.purpose_;
00051 break;
00052 case 4:
00053 return iData.type_;
00054 break;
00055 case 1:
00056 return iData.moduleLabel_;
00057 break;
00058 case 2:
00059 return iData.productInstanceLabel_;
00060 break;
00061 case 3:
00062 return iData.processName_;
00063 break;
00064 default:
00065 break;
00066 }
00067 static const std::string s_blank;
00068 return s_blank;
00069 }
00070
00071 static const unsigned int kNColumns = 5;
00072 class DataAdderTableManager : public FWTableManagerBase {
00073 public:
00074 DataAdderTableManager(FWJobMetadataManager *manager):
00075 m_manager(manager), m_selectedRow(-1), m_filter()
00076 {
00077 reset();
00078 }
00079
00080 virtual int numberOfRows() const {
00081 return m_row_to_index.size();
00082 }
00083 virtual int numberOfColumns() const {
00084 return kNColumns;
00085 }
00086
00091 virtual void sortWithFilter(const char *filter)
00092 {
00093 m_filter = filter;
00094 sort(-1, sortOrder());
00095 dataChanged();
00096 }
00097
00098 virtual int unsortedRowNumber(int iSortedRowNumber) const {
00099 return m_row_to_index[iSortedRowNumber];
00100 }
00101
00102 virtual void implSort(int col, bool sortOrder);
00103 virtual std::vector<std::string> getTitles() const {
00104 std::vector<std::string> returnValue;
00105 returnValue.reserve(kNColumns);
00106 returnValue.push_back("Purpose");
00107 returnValue.push_back("Module Label");
00108 returnValue.push_back("Product Instance Label");
00109 returnValue.push_back("Process Name");
00110 returnValue.push_back("C++ Class");
00111 return returnValue;
00112 }
00113
00114 virtual FWTableCellRendererBase* cellRenderer(int iSortedRowNumber, int iCol) const
00115 {
00116
00117 if(static_cast<int>(m_row_to_index.size())>iSortedRowNumber) {
00118 int unsortedRow = m_row_to_index[iSortedRowNumber];
00119 const FWJobMetadataManager::Data& data = (m_manager->usableData())[unsortedRow];
00120
00121 m_renderer.setData(dataForColumn(data,iCol),m_selectedRow==unsortedRow);
00122 } else {
00123 m_renderer.setData(std::string(),false);
00124 }
00125 return &m_renderer;
00126 }
00127
00128 void setSelection (int row, int mask) {
00129 if(mask == 4) {
00130 if( row == m_selectedRow) {
00131 row = -1;
00132 }
00133 }
00134 changeSelection(row);
00135 }
00136
00137 virtual const std::string title() const {
00138 return "Viewable Collections";
00139 }
00140
00141 int selectedRow() const {
00142 return m_selectedRow;
00143 }
00144
00145 virtual bool rowIsSelected(int row) const {
00146 return m_selectedRow == row;
00147 }
00148
00149 void reset() {
00150 changeSelection(-1);
00151 m_row_to_index.clear();
00152 m_row_to_index.reserve(m_manager->usableData().size());
00153 for(unsigned int i =0; i < m_manager->usableData().size(); ++i) {
00154 m_row_to_index.push_back(i);
00155 }
00156 dataChanged();
00157 }
00158 sigc::signal<void,int> indexSelected_;
00159 private:
00160 void changeSelection(int iRow) {
00161 if(iRow != m_selectedRow) {
00162 m_selectedRow=iRow;
00163 if(-1 == iRow) {
00164 indexSelected_(-1);
00165 } else {
00166 indexSelected_(iRow);
00167 }
00168 visualPropertiesChanged();
00169 }
00170 }
00171 FWJobMetadataManager* m_manager;
00172 std::vector<int> m_row_to_index;
00173 int m_selectedRow;
00174 std::string m_filter;
00175 mutable FWTextTableCellRenderer m_renderer;
00176 };
00177
00178 namespace {
00179 void strip(std::string &source, const char *str)
00180 {
00181 std::string remove(str);
00182 while(true)
00183 {
00184 size_t found = source.find(remove);
00185 if (found == std::string::npos)
00186 break;
00187 source.erase(found, remove.size());
00188 }
00189 }
00190
00208 class SortAndFilter
00209 {
00210 public:
00211 SortAndFilter(const char *filter, int column, bool order,
00212 const std::vector<FWJobMetadataManager::Data> &data)
00213 : m_filter(filter),
00214 m_column(column),
00215 m_order(order),
00216 m_data(data)
00217 {
00218 simplify(m_filter);
00219 m_weights.resize(data.size());
00220
00221
00222
00223
00224 for (size_t i = 0, e = m_weights.size(); i != e; ++i)
00225 m_weights[i] = matchesFilter(m_data[i]);
00226 }
00227
00231 static void simplify(std::string &str)
00232 {
00233 std::transform(str.begin(), str.end(), str.begin(), tolower);
00234 strip(str, "std::");
00235 strip(str, "edm::");
00236 strip(str, "vector<");
00237 strip(str, "clonepolicy");
00238 strip(str, "ownvector");
00239 strip(str, "rangemap<");
00240 strip(str, "strictweakordering<");
00241 strip(str, "sortedcollection<");
00242 strip(str, "reco::");
00243 strip(str, "edmnew::");
00244 }
00245
00246 unsigned int matches(const std::string &str) const
00247 {
00248 std::string up(str);
00249 simplify(up);
00250 const char *begin = up.c_str();
00251
00252
00253
00254
00255
00256 if ((!m_filter.empty()) && str.empty())
00257 return 0;
00258
00259
00260
00261
00262 if (strstr(begin, m_filter.c_str()))
00263 return 2;
00264
00265 return 0;
00266 }
00267
00273 unsigned int matchesFilter(const FWJobMetadataManager::Data &data) const
00274 {
00275 std::vector<unsigned int> scores;
00276 scores.reserve(10);
00277 scores.push_back(matches(data.purpose_));
00278 scores.push_back(matches(data.type_));
00279 scores.push_back(matches(data.moduleLabel_));
00280 scores.push_back(matches(data.productInstanceLabel_));
00281 scores.push_back(matches(data.processName_));
00282 std::sort(scores.begin(), scores.end());
00283 return scores.back();
00284 }
00285
00289 bool operator()(const int &aIndex, const int &bIndex)
00290 {
00291
00292
00293 if (m_column == -1)
00294 return m_weights[aIndex] >= m_weights[bIndex];
00295
00296 const FWJobMetadataManager::Data &a = m_data[aIndex];
00297 const FWJobMetadataManager::Data &b = m_data[bIndex];
00298
00299 if (m_order)
00300 return dataForColumn(a, m_column) < dataForColumn(b, m_column);
00301 else
00302 return dataForColumn(a, m_column) > dataForColumn(b, m_column);
00303 }
00304 private:
00305 std::string m_filter;
00306 int m_column;
00307 bool m_order;
00308
00309 const std::vector<FWJobMetadataManager::Data> &m_data;
00310 std::vector<unsigned int> m_weights;
00311 };
00312
00313 void doSort(int column,
00314 const char *filter,
00315 bool descentSort,
00316 const std::vector<FWJobMetadataManager::Data>& iData,
00317 std::vector<int>& oRowToIndex)
00318 {
00319 std::vector<int> ordered;
00320 ordered.reserve(iData.size());
00321
00322 for (size_t i = 0, e = iData.size(); i != e; ++i)
00323 ordered.push_back(i);
00324
00325 SortAndFilter sorter(filter, column, descentSort, iData);
00326
00327 std::stable_sort(ordered.begin(), ordered.end(), sorter);
00328
00329 oRowToIndex.clear();
00330 oRowToIndex.reserve(ordered.size());
00331
00332 for (size_t i = 0, e = ordered.size(); i != e; ++i)
00333 if (sorter.matchesFilter(iData[ordered[i]]) != 0)
00334 oRowToIndex.push_back(ordered[i]);
00335 }
00336 }
00337
00338 void
00339 DataAdderTableManager::implSort(int column, bool sortOrder)
00340 {
00341 doSort(column, m_filter.c_str(), sortOrder, m_manager->usableData(), m_row_to_index);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 FWGUIEventDataAdder::FWGUIEventDataAdder(
00353 UInt_t iWidth,UInt_t iHeight,
00354 FWEventItemsManager* iManager,
00355 TGFrame* iParent,
00356 FWJobMetadataManager *iMetadataManager)
00357 :
00358 m_manager(iManager),
00359 m_metadataManager(iMetadataManager),
00360 m_parentFrame(iParent)
00361 {
00362 m_metadataManager->metadataChanged_.connect(boost::bind(&FWGUIEventDataAdder::metadataUpdatedSlot, this));
00363 createWindow();
00364 }
00365
00366
00367
00368
00369
00370
00371 FWGUIEventDataAdder::~FWGUIEventDataAdder()
00372 {
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 void
00400 FWGUIEventDataAdder::addNewItem()
00401 {
00402 TClass* theClass = TClass::GetClass(m_type.c_str());
00403 if(0==theClass) {
00404 return;
00405 }
00406 const std::string moduleLabel = m_moduleLabel;
00407 if(moduleLabel.empty()) {
00408 return;
00409 }
00410
00411 const std::string name = m_name->GetText();
00412 if(name.empty()) {
00413 return;
00414 }
00415
00416 if ( m_manager->find( name ) ) {
00417 TString msg("Event item '");
00418 msg += name;
00419 msg += "' is already registered. Please use another name.";
00420 fwLog(fwlog::kWarning) << msg.Data() << std::endl;
00421 new TGMsgBox(gClient->GetDefaultRoot(), m_frame,
00422 "Error - Name conflict", msg, kMBIconExclamation, kMBOk);
00423 return;
00424 }
00425
00426 int largest = -1;
00427 if(m_manager->begin() != m_manager->end()) {
00428 if ( *(m_manager->begin()) )
00429 largest = (*(m_manager->begin()))->layer();
00430 }
00431 for(FWEventItemsManager::const_iterator it = m_manager->begin(),
00432 itEnd = m_manager->end();
00433 it!=itEnd;
00434 ++it) {
00435 if((*it) && largest < (*it)->layer()) {
00436 largest = (*it)->layer();
00437 }
00438 }
00439 ++largest;
00440 std::string processName = m_processName;
00441 if(m_doNotUseProcessName->IsOn() && m_doNotUseProcessName->IsEnabled()) {
00442 processName="";
00443 }
00444 FWPhysicsObjectDesc desc(name, theClass, m_purpose,
00445 FWDisplayProperties::defaultProperties,
00446 moduleLabel,
00447 m_productInstanceLabel,
00448 processName,
00449 "",
00450 largest);
00451 m_manager->add(desc);
00452 }
00453
00454 void
00455 FWGUIEventDataAdder::addNewItemAndClose()
00456 {
00457 addNewItem();
00458 windowIsClosing();
00459 }
00460
00461 void
00462 FWGUIEventDataAdder::show()
00463 {
00464
00465 if(0==m_frame) {
00466 createWindow();
00467 }
00468 m_frame->MapWindow();
00469 }
00470
00471 void
00472 FWGUIEventDataAdder::windowIsClosing()
00473 {
00474 m_name->SetText("");
00475 m_search->SetText("");
00476 m_purpose.clear();
00477 m_type.clear();
00478 m_moduleLabel.clear();
00479 m_processName.clear();
00480 m_productInstanceLabel.clear();
00481 m_apply->SetEnabled(false);
00482 m_applyAndClose->SetEnabled(false);
00483
00484 m_frame->UnmapWindow();
00485 m_frame->DontCallClose();
00486 }
00487
00488 void
00489 FWGUIEventDataAdder::updateFilterString(const char *str)
00490 {
00491 m_tableManager->sortWithFilter(str);
00492 m_tableManager->dataChanged();
00493 }
00494
00495 void
00496 FWGUIEventDataAdder::createWindow()
00497 {
00498 m_tableManager = new DataAdderTableManager(m_metadataManager);
00499 m_tableManager->indexSelected_.connect(boost::bind(&FWGUIEventDataAdder::newIndexSelected,this,_1));
00500
00501 m_frame = new TGTransientFrame(gClient->GetDefaultRoot(),m_parentFrame,600,400);
00502 m_frame->Connect("CloseWindow()","FWGUIEventDataAdder",this,"windowIsClosing()");
00503
00504 FWDialogBuilder builder(m_frame);
00505 TGTextButton *cancelButton, *resetButton;
00506
00507 builder.indent(10)
00508 .spaceDown(15)
00509 .addLabel("Search:", 0).expand(false).spaceUp(4).floatLeft(4)
00510 .addTextEntry("", &m_search).spaceUp(0)
00511 .frameSpaceDown(10)
00512 .addLabel("Viewable Collections", 8)
00513 .frameSpaceDown(5)
00514 .addTable(m_tableManager, &m_tableWidget).expand(true, true)
00515 .addLabel("Name:", 0).expand(false).spaceUp(4).floatLeft(4)
00516 .addTextEntry("", &m_name).spaceUp(0).floatLeft(4)
00517 .addTextButton(" Reset ", &resetButton).expand(false, false)
00518 .frameSpaceUpDown(5)
00519 .addCheckbox("Do not use Process Name and "
00520 "instead only get this data "
00521 "from the most recent Process",
00522 &m_doNotUseProcessName)
00523 .frameSpaceDown(15)
00524 .hSpacer().floatLeft(0)
00525 .addTextButton(" Close ", &cancelButton).expand(false).floatLeft(4)
00526 .addTextButton(" Add Data ", &m_apply).expand(false).floatLeft(4)
00527 .addTextButton(" Add Data && Close ", &m_applyAndClose).expand(false)
00528 .spaceRight(25).spaceDown(15);
00529
00530 m_search->Connect("TextChanged(const char *)", "FWGUIEventDataAdder",
00531 this, "updateFilterString(const char *)");
00532 m_search->SetEnabled(true);
00533 m_tableWidget->SetBackgroundColor(0xffffff);
00534 m_tableWidget->SetLineSeparatorColor(0x000000);
00535 m_tableWidget->SetHeaderBackgroundColor(0xececec);
00536 m_tableWidget->Connect("rowClicked(Int_t,Int_t,Int_t,Int_t,Int_t)",
00537 "FWGUIEventDataAdder",this,
00538 "rowClicked(Int_t,Int_t,Int_t,Int_t,Int_t)");
00539
00540 m_tableWidget->disableGrowInWidth();
00541 m_name->SetState(true);
00542 resetButton->SetEnabled(true);
00543 resetButton->Connect("Clicked()", "FWGUIEventDataAdder", this, "resetNameEntry()");
00544 m_doNotUseProcessName->SetState(kButtonDown);
00545 cancelButton->Connect("Clicked()","FWGUIEventDataAdder", this, "windowIsClosing()");
00546 cancelButton->SetEnabled(true);
00547 m_apply->Connect("Clicked()", "FWGUIEventDataAdder", this, "addNewItem()");
00548 m_applyAndClose->Connect("Clicked()", "FWGUIEventDataAdder", this, "addNewItemAndClose()");
00549
00550 m_frame->SetWindowName("Add Collection");
00551 m_frame->MapSubwindows();
00552 m_frame->Layout();
00553 }
00554
00559 void
00560 FWGUIEventDataAdder::metadataUpdatedSlot(void)
00561 {
00562 m_tableManager->reset();
00563 m_tableManager->sort(0, true);
00564 }
00565
00566 void
00567 FWGUIEventDataAdder::resetNameEntry()
00568 {
00569 m_name->SetText(m_apply->IsEnabled() ? m_moduleLabel.c_str() : "", kFALSE);
00570 }
00571
00572 void
00573 FWGUIEventDataAdder::newIndexSelected(int iSelectedIndex)
00574 {
00575 if(-1 != iSelectedIndex) {
00576 std::vector<FWJobMetadataManager::Data> &metadata = m_metadataManager->usableData();
00577 m_purpose = metadata[iSelectedIndex].purpose_;
00578 m_type = metadata[iSelectedIndex].type_;
00579 std::string oldModuleLabel = m_moduleLabel;
00580 m_moduleLabel = metadata[iSelectedIndex].moduleLabel_;
00581 m_productInstanceLabel = metadata[iSelectedIndex].productInstanceLabel_;
00582 m_processName = metadata[iSelectedIndex].processName_;
00583
00584 if(strlen(m_name->GetText())==0 || oldModuleLabel == m_name->GetText()) {
00585 m_name->SetText(m_moduleLabel.c_str());
00586 }
00587 m_apply->SetEnabled(true);
00588 m_applyAndClose->SetEnabled(true);
00589
00590
00591
00592
00593
00594 bool isMostRecentProcess =true;
00595 int index = 0;
00596 for(std::vector<FWJobMetadataManager::Data>::iterator it = metadata.begin(), itEnd = metadata.end();
00597 it != itEnd && isMostRecentProcess;
00598 ++it,++index) {
00599 if(index == iSelectedIndex) {continue;}
00600 if(it->moduleLabel_ == m_moduleLabel &&
00601 it->purpose_ == m_purpose &&
00602 it->type_ == m_type &&
00603 it->productInstanceLabel_ == m_productInstanceLabel) {
00604
00605
00606 for(size_t pni = 0, pne = m_metadataManager->processNamesInJob().size();
00607 pni != pne; ++pni)
00608 {
00609 const std::string &processName = m_metadataManager->processNamesInJob()[pni];
00610 if (m_processName == processName)
00611 break;
00612
00613 if(it->processName_ == processName)
00614 {
00615 isMostRecentProcess = false;
00616 break;
00617 }
00618 }
00619 }
00620 }
00621 if(isMostRecentProcess) {
00622 if(!m_doNotUseProcessName->IsEnabled()) {
00623 m_doNotUseProcessName->SetEnabled(true);
00624 }
00625 } else {
00626
00627
00628 m_doNotUseProcessName->SetEnabled(false);
00629 }
00630 }
00631 }
00632
00633 void
00634 FWGUIEventDataAdder::rowClicked(Int_t iRow,Int_t iButton,Int_t iKeyMod,Int_t,Int_t)
00635 {
00636 if(iButton==kButton1) {
00637 m_tableManager->setSelection(iRow,iKeyMod);
00638 }
00639 }
00640
00641
00642
00643
00644
00645
00646
00647