runinfo.cc

00001 #include "runinfo.hh"
00002 #include "TGClient.h"
00003 #include "TApplication.h"
00004 #include "TGFrame.h"
00005 #include "TGCanvas.h"
00006 #include "TGTextEntry.h"
00007 #include "TGDockableFrame.h"
00008 #include "TGButton.h"
00009 #include "TGButtonGroup.h"
00010 #include "TQObject.h"
00011 #include "TGToolTip.h"
00012 #include "TGLabel.h"
00013 #include "TGComboBox.h"
00014 #include "TGMsgBox.h"
00015 #include "TMacro.h"
00016 #include "TList.h"
00017 #include "TObjString.h"
00018 
00019 typedef runinfo::stringmap stringmap;
00020 typedef runinfo::stringvec stringvec;
00021 typedef runinfo::DialogField DialogField;
00022 typedef runinfo::FieldList FieldList;
00023 
00024 //utility class to read now-obsolete comment parameter and put into metadata
00025 class CommentReader{
00026   runinfo* _info;
00027 public:
00028   CommentReader(runinfo* info) : _info(info) {}
00029   std::istream& operator()(std::istream& in)
00030   { phrase dummy; 
00031     if(in>>dummy) _info->SetMetadata("comment",dummy); 
00032     return in; 
00033   }
00034 };
00035 
00036 runinfo::runinfo(long id) : 
00037   ParameterList("runinfo","metadata about daq runs")
00038 {
00039   Init();
00040   runid = id;
00041 }
00042 
00043 //reset variables that can be read from the raw data
00044 void runinfo::ResetRunStats()
00045 {
00046   starttime = 0;
00047   endtime = 0;
00048   triggers = 0;
00049   events = 0;
00050 }
00051 
00052 void runinfo::Init(bool reset)
00053 {
00054   runid=-1;
00055   starttime=0;
00056   endtime=0;
00057   triggers=0;
00058   events=0;
00059   
00060   metadata.clear();
00061   prerun_dialog_fields.clear();
00062   postrun_dialog_fields.clear();
00063   force_prerun_dialog = false;
00064   force_postrun_dialog = false;
00065   channel_metadata.clear();
00066   
00067   if(!reset)
00068     InitializeParameterList();
00069 }
00070 
00071 void runinfo::InitializeParameterList()
00072 {
00073   RegisterParameter("runid", runid, "unique ID number for the run");
00074   RegisterParameter("starttime",starttime,"Timestamp at start of run");
00075   RegisterParameter("endtime",endtime, "Timestamp at end of run");
00076   RegisterParameter("triggers",triggers,"Total triggers requested during run");
00077   RegisterParameter("events", events, "Number of events recorded during run");
00078   
00079   RegisterParameter("metadata", metadata, 
00080                     "User-defined per run info categories");
00081   RegisterParameter("prerun_dialog_fields", prerun_dialog_fields,
00082                     "List of fields to query user for at start of run");
00083   RegisterParameter("postrun_dialog_fields", postrun_dialog_fields,
00084                     "List of fields to query user for at end of run");
00085   RegisterParameter("force_prerun_dialog", force_prerun_dialog,
00086                     "Show prerun dialog even if all required fields valid");
00087   RegisterParameter("force_postrun_dialog", force_postrun_dialog,
00088                     "Show postrun dialog even if all required fields valid");
00089   
00090   RegisterParameter("channel_metadata", channel_metadata,
00091                     "map of channel ID to per-channel metadata");
00092   
00093   RegisterReadFunction("comment",CommentReader(this),
00094                        "Handle obsolete separate comment parameter (now in metadata)");
00095 }
00096 
00097 
00098 int runinfo::LoadSavedInfo(TMacro* mac)
00099 {
00100   //first, read the macro into a stringstream
00101   TList* lines = mac->GetListOfLines();
00102   if(!lines || !lines->GetEntries())
00103     return 1;
00104   std::stringstream s;
00105   TIter next(lines);
00106   TObjString *obj;
00107   while ((obj = (TObjString*) next()))
00108     s<<obj->GetName()<<"\n";
00109   //now use the ParameterList methods to read from the stream
00110   try{
00111     ReadFromByKey(s, GetDefaultKey());
00112   }
00113   catch(std::exception& e){
00114     //there was an error reading
00115     return 2;
00116   }
00117   //if we get here, we should have been successful
00118   return 0;
00119 }
00120 
00122 
00123 bool AreAllFieldsValid(FieldList* fields, stringmap* metadata)
00124 {
00125   //see if all fields are valid
00126   bool allvalid = true;
00127   FieldList::iterator field;
00128   for(field = fields->begin(); field != fields->end(); ++field){
00129     if( !field->IsValueValid( (*metadata)[field->fieldname] ) ){
00130       allvalid = false;
00131       break;
00132     }
00133   }
00134   return allvalid;
00135 }
00136 
00137 DialogField::DialogField(const std::string& field, 
00138                          const std::string& desc,
00139                          bool required_, 
00140                          const std::string& default_) : 
00141   ParameterList(field,"Specify a metadata field to query the user for"),
00142   fieldname(field), description(desc), required(required_), 
00143   defaultvalue(default_) 
00144 { 
00145   RegisterParameter("fieldname", fieldname);
00146   RegisterParameter("description", description);
00147   RegisterParameter("allowed_values", allowed_values);
00148   RegisterParameter("required",required);
00149   RegisterParameter("defaultvalue",defaultvalue);
00150 }
00151 
00152 
00153 bool DialogField::IsValueValid(const std::string& val) const
00154 {
00155   if(!allowed_values.empty() && 
00156      std::find(allowed_values.begin(), allowed_values.end(), val) == 
00157      allowed_values.end() )
00158     return false;
00159   if(required)
00160     return val != "";
00161   return true;
00162 }
00163 
00164 class DialogFieldFrame : public TGVerticalFrame{
00165 public:
00166   DialogFieldFrame(const DialogField* field, stringmap* metadata, 
00167                    const TGWindow* p=0);
00168 
00169   virtual ~DialogFieldFrame(){}
00170   
00171   TGTextEntry* GetTextEntry() const { return _textentry; }
00172   
00173   virtual Bool_t Notify(); //override this method to receive change signals
00174 private:
00175   const DialogField* _field;
00176   stringmap* _metadata;
00177   TGTextEntry* _textentry;
00178   TGComboBox* _combobox;
00179 };
00180 
00181 DialogFieldFrame::DialogFieldFrame(const DialogField* field, stringmap* metadata,
00182                                    const TGWindow* p) :
00183   TGVerticalFrame(p), _field(field), _metadata(metadata),
00184   _textentry(0), _combobox(0)
00185 {
00186   std::string defaultvalue = field->defaultvalue;
00187   if((*metadata)[field->fieldname] != "")
00188     defaultvalue = (*metadata)[field->fieldname];
00189 
00190   TGHorizontalFrame* hframe = new TGHorizontalFrame(this);
00191   AddFrame(hframe, new TGLayoutHints(kLHintsExpandX|kLHintsTop,0,0,5));
00192   std::string label = "   ";
00193   if(field->required)
00194     label = "*  ";
00195   label += field->fieldname;
00196   hframe->AddFrame(new TGLabel(hframe, label.c_str()), new TGLayoutHints(kLHintsLeft));
00197   if(field->description != ""){
00198     std::string desc = "( ";
00199     desc += field->description + " )";
00200     hframe->AddFrame(new TGLabel(hframe, desc.c_str()), new TGLayoutHints(kLHintsRight));
00201   }
00202   
00203   if(field->allowed_values.empty()){
00204     _textentry = new TGTextEntry(this, defaultvalue.c_str());
00205     AddFrame(_textentry, new TGLayoutHints(kLHintsExpandX, 10));
00206     _textentry->Connect("TextChanged(const char*)","TGFrame",this,"Notify()");
00207   }
00208   else{
00209     _combobox = new TGComboBox(this);
00210     stringvec::const_iterator opt;
00211     int id=-1;
00212     for(opt = field->allowed_values.begin(); opt != field->allowed_values.end(); ++opt){
00213       _combobox->AddEntry(opt->c_str(), ++id);
00214       if(*opt == defaultvalue)
00215         _combobox->Select(id,false);
00216     }
00217     _combobox->SetHeight(20);
00218     AddFrame(_combobox, new TGLayoutHints(kLHintsExpandX,10));
00219     _combobox->Connect("Selected(const char*)","TGFrame",this,"Notify()");
00220   }
00221   
00222   Notify();
00223 }
00224 
00225 Bool_t DialogFieldFrame::Notify()
00226 {
00227   std::string newval="";
00228   if(_textentry)
00229     newval = _textentry->GetText();
00230   else if(_combobox){
00231     TGTextLBEntry* e = (TGTextLBEntry*)(_combobox->GetSelectedEntry());
00232     if(e)
00233       newval = e->GetTitle();
00234   }
00235   (*_metadata)[_field->fieldname] = newval;
00236   int color = kYellow-9;
00237   if( _field->IsValueValid(newval) )
00238     color = kWhite;
00239   Pixel_t pixel = gVirtualX->GetPixel(color);
00240   if(_textentry)
00241     _textentry->SetBackgroundColor(pixel);
00242   else if(_combobox){
00243     _combobox->SetBackgroundColor(pixel);
00244     _combobox->SetEnabled(true);
00245   }
00246 
00247   return false;
00248 }
00249 
00250 class RunInfoFillHelper : public TGTransientFrame{
00251 public:
00252   static int MetadataDialog(stringmap* metadata, FieldList* fields);
00253 private:
00254   static int _returnval;
00255   RunInfoFillHelper(stringmap* metadata, FieldList* fields);
00256   virtual ~RunInfoFillHelper();
00257 public:
00259   virtual Bool_t ProcessMessage(Long_t b, Long_t, Long_t); 
00260 private:
00261   stringmap* _metadata;
00262   FieldList* _fields;
00263   TGCanvas* can; // won't auto cleanup, so must do on our own
00264   TGCompositeFrame* mf2; //container of TGCanvas, need to delete manually
00265 };
00266 
00267 RunInfoFillHelper::~RunInfoFillHelper()
00268 {
00269 }
00270 
00271 int RunInfoFillHelper::_returnval=1; //default value for window closed
00272 int RunInfoFillHelper::MetadataDialog(stringmap* metadata, FieldList* fields)
00273 {
00274   if(!gApplication)
00275     new TApplication("_app",0,0);
00276   gApplication->NeedGraphicsLibs();
00277   gApplication->InitializeGraphics();
00278   new RunInfoFillHelper(metadata, fields);
00279   return _returnval;
00280 }
00281 
00282 Bool_t RunInfoFillHelper::ProcessMessage(Long_t b, Long_t, Long_t)
00283 {
00284   if(b==1){ //OK was pressed
00285     //see if all fields are valid
00286     bool allvalid = true;
00287     for(FieldList::iterator field = _fields->begin(); field != _fields->end(); ++field){
00288       if( !field->IsValueValid( (*_metadata)[field->fieldname] ) ){
00289         allvalid = false;
00290         break;
00291       }
00292     }
00293     if(!allvalid){
00294       new TGMsgBox(gClient->GetRoot(), this, "Invalid Fields","One or more required fields (marked yellow) do not have values assigned. Please enter valid values in these fields and submit again.");
00295       return false;
00296     }
00297     else //all fields successfully validated
00298       _returnval = 0;
00299   }
00300   else if(b==2){ // cancel was pressed
00301     _returnval = 2;
00302   }
00303   CloseWindow();
00304   return false;
00305 }
00306 
00307 //do all work in constructor
00308 RunInfoFillHelper::RunInfoFillHelper(stringmap* metadata, FieldList* fields) : 
00309   TGTransientFrame(gClient->GetRoot()),
00310   _metadata(metadata), _fields(fields)
00311 {
00312   SetWindowName("Please fill out run information");
00313   //build up frames to put text entry fields in
00314   TGCanvas* can = new TGCanvas(this,10, 10, kChildFrame);
00315   AddFrame(can, new TGLayoutHints(kLHintsExpandX|kLHintsExpandY,0,0,10));
00316   TGCompositeFrame* mf2 = new TGVerticalFrame(can->GetViewPort(),10,10);
00317   can->SetContainer(mf2);
00318   
00319   //Add OK and cancel buttons
00320   TGButtonGroup* bg = new TGButtonGroup(this,"",kChildFrame|kHorizontalFrame|kFixedSize);
00321   bg->Resize(300,70);
00322   AddFrame(bg,new TGLayoutHints(kLHintsBottom|kLHintsCenterX));
00323   TGTextButton* ok = new TGTextButton(bg,"OK");
00324   /*TGTextButton* cancel = */new TGTextButton(bg,"Cancel");
00325   bg->SetLayoutHints(new TGLayoutHints(kLHintsExpandX|kLHintsExpandY,10,10,3,3));
00326   bg->Connect("Clicked(Int_t)","TGCompositeFrame",this,
00327               "ProcessMessage(Long_t,Long_t,Long_t)");
00328   
00329   TGTextEntry* first = 0, *last = 0;
00330   
00331   for(FieldList::const_iterator field = _fields->begin(); 
00332       field != _fields->end(); ++field){
00333     DialogFieldFrame* frame = new DialogFieldFrame(&(*field), metadata, mf2);
00334     mf2->AddFrame(frame, new TGLayoutHints(kLHintsExpandX,10,10,5,5));
00335     TGTextEntry* te = frame->GetTextEntry();
00336     if(te){
00337       //connect to the OK button 
00338       te->Connect("ReturnPressed()","TGButton",ok,"Clicked()");
00339       
00340       if(!first) first = te;
00341       //connect to previous with tab commands
00342       if(last){
00343         last->Connect("TabPressed()","TGTextEntry",te,"SetFocus()");
00344         last->Connect("TabPressed()","TGTextEntry",te,"SelectAll()");
00345         te->Connect("ShiftTabPressed()","TGTextEntry",last,"SetFocus()");
00346         te->Connect("ShiftTabPressed()","TGTextEntry",last,"SelectAll()");
00347       }
00348       last = te;
00349     }
00350   } //end loop over field list
00351   
00352   //connect the first and last to wrap tabbing
00353   if(first && last && first != last){
00354     first->SetFocus();
00355     first->Connect("ShiftTabPressed()","TGTextEntry",last,"SetFocus()");
00356     first->Connect("ShiftTabPressed()","TGTextEntry",last,"SelectAll()");
00357     last->Connect("TabPressed()","TGTextEntry",first,"SetFocus()");
00358     last->Connect("TabPressed()","TGTextEntry",first,"SelectAll()");
00359   }
00360     
00361   //make sure we clean up properly at the end
00362   SetCleanup(kDeepCleanup);
00363   can->GetViewPort()->SetCleanup(kDeepCleanup);
00364   //draw the window
00365   MapSubwindows();
00366   Resize(500,500);
00367   CenterOnParent();
00368   MapWindow();
00369   gClient->WaitFor(this);
00370 }
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00379 
00380 int runinfo::FillDataForRun(runinfo::FILLTIME when)
00381 {
00382   FieldList* fields = (when == RUNSTART ? &prerun_dialog_fields : 
00383                                           &postrun_dialog_fields );
00384   bool forcedialog = (when == RUNSTART ? force_prerun_dialog : 
00385                                          force_postrun_dialog );
00386   if(fields && !fields->empty() && 
00387      (forcedialog || !AreAllFieldsValid(fields, &metadata)) )
00388     return RunInfoFillHelper::MetadataDialog(&metadata, fields);
00389   return 0;
00390 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on 20 Jun 2014 for daqman by  doxygen 1.6.1