]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MONITOR/AliMonitorClient.cxx
monitor histograms for HLT added
[u/mrichter/AliRoot.git] / MONITOR / AliMonitorClient.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  This class receives monitor histograms from a monitor process and        //
21 //  provides a graphical user interface for browsing and analysing the       //
22 //  monitor histograms.                                                      //
23 //                                                                           //
24 ///////////////////////////////////////////////////////////////////////////////
25
26
27 #include "AliMonitorClient.h"
28 #include "AliMonitorDialog.h"
29 #include "AliMonitorProcess.h"
30 #include <TGMsgBox.h>
31 #include <TGFileDialog.h>
32 #include <TSystem.h>
33 #include <TMessage.h>
34 #include <TCanvas.h>
35 #include <TApplication.h>
36 #include <TStyle.h>
37
38
39 ClassImp(AliMonitorClient) 
40
41
42 const char* AliMonitorClient::fgSettingsFileName = ".AliMonitorClient";
43
44 //_____________________________________________________________________________
45 class AliMonitorStringDlg : public AliMonitorDialog {
46
47 public:
48   AliMonitorStringDlg(TString& string, TGFrame* main, const char* title,
49                       const char* label);
50   virtual ~AliMonitorStringDlg();
51
52   virtual void       OnOkClicked();
53
54 private:
55   TGLayoutHints*     fStringLayout;
56   TGLabel*           fStringLabel;
57   TGTextEntry*       fStringEntry;
58
59   TString&           fString;
60 };
61
62
63 //_____________________________________________________________________________
64 AliMonitorStringDlg::AliMonitorStringDlg(TString& string, TGFrame* main, 
65                                          const char* title, 
66                                          const char* label) :
67   AliMonitorDialog(main, 300, 80), fString(string)
68 {
69 // create a dialog for connecting to a monitor process
70
71   fStringLayout = new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 5, 2, 2);
72   fStringLabel = new TGLabel(fFrame, label);
73   fFrame->AddFrame(fStringLabel, fStringLayout);
74   fStringEntry = new TGTextEntry(fFrame, string.Data());
75   fStringEntry->Resize(100, fStringEntry->GetDefaultHeight());
76   fFrame->AddFrame(fStringEntry, fStringLayout);
77
78   fString = "";
79
80   fMain->SetWindowName(title);
81   fMain->MapSubwindows();
82   fMain->Layout();
83   gClient->WaitFor(fMain);
84 }
85
86 //_____________________________________________________________________________
87 AliMonitorStringDlg::~AliMonitorStringDlg()
88 {
89 // clean up
90
91   delete fStringLabel;
92   delete fStringLayout;
93   delete fStringEntry;
94 }
95
96 //_____________________________________________________________________________
97 void AliMonitorStringDlg::OnOkClicked()
98 {
99   fString = fStringEntry->GetText();
100 }
101
102
103
104 //_____________________________________________________________________________
105 class AliMonitorNumberDlg : public AliMonitorDialog {
106
107 public:
108   AliMonitorNumberDlg(Float_t& value, TGFrame* main, const char* title,
109                       const char* label, Float_t min);
110   virtual ~AliMonitorNumberDlg();
111
112   virtual void       OnOkClicked();
113
114 private:
115   TGLayoutHints*     fNumberLayout;
116   TGLabel*           fNumberLabel;
117   TGNumberEntry*     fNumberEntry;
118
119   Float_t&           fNumber;
120 };
121
122
123 //_____________________________________________________________________________
124 AliMonitorNumberDlg::AliMonitorNumberDlg(Float_t& value, TGFrame* main, 
125                                          const char* title, const char* label, 
126                                          Float_t min) :
127   AliMonitorDialog(main, 250, 80), fNumber(value)
128 {
129 // create a dialog for getting a number
130
131   fNumberLayout = new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 5, 2, 2);
132   fNumberLabel = new TGLabel(fFrame, label);
133   fFrame->AddFrame(fNumberLabel, fNumberLayout);
134   fNumberEntry = new TGNumberEntry(fFrame, value, 4, -1,
135                                    TGNumberFormat::kNESRealOne);
136   fNumberEntry->SetLimits(TGNumberFormat::kNELLimitMin, min, 0);
137   fFrame->AddFrame(fNumberEntry, fNumberLayout);
138
139   fNumber = -1;
140
141   fMain->SetWindowName(title);
142   fMain->MapSubwindows();
143   fMain->Layout();
144   gClient->WaitFor(fMain);
145 }
146
147 //_____________________________________________________________________________
148 AliMonitorNumberDlg::~AliMonitorNumberDlg()
149 {
150 // clean up
151
152   delete fNumberLabel;
153   delete fNumberLayout;
154   delete fNumberEntry;
155 }
156
157 //_____________________________________________________________________________
158 void AliMonitorNumberDlg::OnOkClicked()
159 {
160   fNumber = fNumberEntry->GetNumber();
161 }
162
163
164
165 // constants for menu entries
166 enum {kMenuFileConnect, kMenuFileDisconnect, kMenuFileOpen, kMenuFileExit,
167       kMenuViewToolBar, kMenuViewTree, kMenuViewDescription, 
168       kMenuViewReference, kMenuViewStatistics,
169       kMenuFavAdd, kMenuFavDelete, 
170       kMenuFavLoad, kMenuFavSave,  kMenuFavSaveAs, kMenuFavSaveOnExit,
171       kMenuRefLoad, kMenuRefThreshold, 
172       kMenuRefTakeCurrent, kMenuRefSave, kMenuRefSaveAs,
173       kMenuOptLoop, kMenuOptPrint, 
174       kMenuOptSave, kMenuOptSaveOnExit,
175       kMenuHelpDoc, kMenuHelpAbout
176 };
177
178 //_____________________________________________________________________________
179 AliMonitorClient::AliMonitorClient():
180   TGMainFrame(gClient->GetRoot(), 500, 300)
181 {
182 // initialize the monitoring client window
183
184   // *** menu bar ***
185   fMenuBarLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX,
186                                       0, 0, 1, 1);
187   fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0);
188   fMenuBarHelpLayout = new TGLayoutHints(kLHintsTop | kLHintsRight);
189
190   // File menu
191   fMenuFile = new TGPopupMenu(gClient->GetRoot());
192   fMenuFile->AddEntry("&Connect...", kMenuFileConnect);
193   fMenuFile->AddEntry("&Disconnect...", kMenuFileDisconnect);
194   fMenuFile->HideEntry(kMenuFileDisconnect);
195   fMenuFile->AddEntry("&Open...", kMenuFileOpen);
196   fMenuFile->AddSeparator();
197   fMenuFile->AddEntry("E&xit", kMenuFileExit);
198   fMenuFile->Connect("Activated(Int_t)", "AliMonitorClient", this,
199                      "OnMenuActivated(Int_t)");
200
201   // View menu
202   fMenuView = new TGPopupMenu(gClient->GetRoot());
203   fMenuView->AddEntry("Tool&bar", kMenuViewToolBar);
204   fMenuView->CheckEntry(kMenuViewToolBar);
205   fMenuView->AddEntry("&Tree", kMenuViewTree);
206   fMenuView->CheckEntry(kMenuViewTree);
207   fMenuView->AddEntry("&Description", kMenuViewDescription);
208   fMenuView->CheckEntry(kMenuViewDescription);
209   fMenuView->AddSeparator();
210   fMenuView->AddEntry("&Reference", kMenuViewReference);
211   fMenuView->CheckEntry(kMenuViewReference);
212   AliMonitorHisto::SetDrawRef(kTRUE);
213   fMenuView->AddEntry("&Statistics", kMenuViewStatistics);
214   fMenuView->CheckEntry(kMenuViewStatistics);
215   gStyle->SetOptStat(1110);
216   fMenuView->Connect("Activated(Int_t)", "AliMonitorClient", this,
217                      "OnMenuActivated(Int_t)");
218
219   // Favorites menu
220   fMenuFavorites = new TGPopupMenu(gClient->GetRoot());
221   fMenuFavorites->AddEntry("&Add", kMenuFavAdd);
222   fMenuFavorites->DisableEntry(kMenuFavAdd);
223   fMenuFavorites->AddEntry("&Delete", kMenuFavDelete);
224   fMenuFavorites->DisableEntry(kMenuFavDelete);
225   fMenuFavorites->AddSeparator();
226   fMenuFavorites->AddEntry("&Load...", kMenuFavLoad);
227   fMenuFavorites->AddEntry("&Save", kMenuFavSave);
228   fMenuFavorites->DisableEntry(kMenuFavSave);
229   fMenuFavorites->AddEntry("&Save As...", kMenuFavSaveAs);
230   fMenuFavorites->DisableEntry(kMenuFavSaveAs);
231   fMenuFavorites->AddEntry("Save On &Exit", kMenuFavSaveOnExit);
232   fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
233   fMenuFavorites->Connect("Activated(Int_t)", "AliMonitorClient", this,
234                           "OnMenuActivated(Int_t)");
235
236   // Reference menu
237   fMenuReference = new TGPopupMenu(gClient->GetRoot());
238   fMenuReference->AddEntry("&Load...", kMenuRefLoad);
239   fMenuReference->AddEntry("&Threshold...", kMenuRefThreshold);
240   fMenuReference->AddSeparator();
241   fMenuReference->AddEntry("Take &Current", kMenuRefTakeCurrent);
242   fMenuReference->DisableEntry(kMenuRefTakeCurrent);
243   fMenuReference->AddEntry("&Save", kMenuRefSave);
244   fMenuReference->DisableEntry(kMenuRefSave);
245   fMenuReference->AddEntry("Save &As...", kMenuRefSaveAs);
246   fMenuReference->DisableEntry(kMenuRefSaveAs);
247   fMenuReference->Connect("Activated(Int_t)", "AliMonitorClient", this,
248                           "OnMenuActivated(Int_t)");
249
250   // Options menu
251   fMenuOptions = new TGPopupMenu(gClient->GetRoot());
252   fMenuOptions->AddEntry("&Loop Interval...", kMenuOptLoop);
253   fMenuOptions->AddEntry("&Print Command...", kMenuOptPrint);
254   fMenuOptions->AddSeparator();
255   fMenuOptions->AddEntry("&Save Settings", kMenuOptSave);
256   fMenuOptions->AddEntry("Save Settings on &Exit", kMenuOptSaveOnExit);
257   fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
258   fMenuOptions->Connect("Activated(Int_t)", "AliMonitorClient", this,
259                         "OnMenuActivated(Int_t)");
260
261   // Help menu
262   fMenuHelp = new TGPopupMenu(gClient->GetRoot());
263   fMenuHelp->AddEntry("&Documentation...", kMenuHelpDoc);
264   fMenuHelp->AddEntry("A&bout...", kMenuHelpAbout);
265   fMenuHelp->Connect("Activated(Int_t)", "AliMonitorClient", this,
266                      "OnMenuActivated(Int_t)");
267
268   // menu bar
269   fMenuBar = new TGMenuBar(this, 1, 1, kHorizontalFrame);
270   fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout);
271   fMenuBar->AddPopup("&View", fMenuView, fMenuBarItemLayout);
272   fMenuBar->AddPopup("F&avorites", fMenuFavorites, fMenuBarItemLayout);
273   fMenuBar->AddPopup("&Reference", fMenuReference, fMenuBarItemLayout);
274   fMenuBar->AddPopup("&Options", fMenuOptions, fMenuBarItemLayout);
275   fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout);
276
277   AddFrame(fMenuBar, fMenuBarLayout);
278
279
280   // *** tool bar ***
281   fToolBarLayout = new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 2, 2);
282   fToolBarSep = new TGHorizontal3DLine(this);
283   AddFrame(fToolBarSep, fToolBarLayout);
284   fToolBar = new TGToolBar(this, 60, 20, kHorizontalFrame);
285   AddFrame(fToolBar, fToolBarLayout);
286
287   // event number field
288   fEventNumberLayout = new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 
289                                          10, 2, 10, 5);
290   fEventNumber = new TGNumberEntry(fToolBar, 1, 4, 10, 
291                                    TGNumberFormat::kNESInteger);
292   fEventNumber->SetLimits(TGNumberFormat::kNELLimitMin, 1, 0);
293   fToolBar->AddFrame(fEventNumber, fEventNumberLayout);
294   fEventNumber->GetNumberEntry()->Connect("ReturnPressed()", 
295                                           "AliMonitorClient", this,
296                                           "OnEventNumberChanged()");
297   fEventNumber->GetButtonUp()->Connect("Clicked()", 
298                                        "AliMonitorClient", this,
299                                        "OnEventNumberChanged()");
300   fEventNumber->GetButtonDown()->Connect("Clicked()", 
301                                          "AliMonitorClient", this,
302                                          "OnEventNumberChanged()");
303
304   // draw event button
305   ToolBarData_t eventButton = {"h1_s.xpm", "draw event histogram", 
306                                kTRUE, 11, NULL};
307   fToolBar->AddButton(this, &eventButton, 5);
308   fEventButton = eventButton.fButton;
309   fEventButton->Connect("Pressed()", "AliMonitorClient", this,
310                         "OnEventButtonPressed()");
311
312   // draw sum button
313   ToolBarData_t sumButton = {"h2_s.xpm", "draw sum histogram", 
314                              kTRUE, 12, NULL};
315   fToolBar->AddButton(this, &sumButton, 5);
316   fSumButton = sumButton.fButton;
317   fSumButton->Connect("Pressed()", "AliMonitorClient", this,
318                       "OnSumButtonPressed()");
319
320   // draw run button
321   ToolBarData_t runButton = {"h3_s.xpm", "draw run histogram", 
322                              kTRUE, 13, NULL};
323   fToolBar->AddButton(this, &runButton, 5);
324   fRunButton = runButton.fButton;
325   fRunButton->SetDown(kTRUE);
326   fRunButton->Connect("Pressed()", "AliMonitorClient", this,
327                       "OnRunButtonPressed()");
328
329   // loop button
330   char fileName[256];
331   sprintf(fileName, "%s/MONITOR/loop_on.xpm", gSystem->Getenv("ALICE_ROOT"));
332   ToolBarData_t loopButton = {fileName, "loop over histograms", 
333                               kFALSE, 21, NULL};
334   fToolBar->AddButton(this, &loopButton, 25);
335   fLoopButton = loopButton.fButton;
336   fLoopButton->Connect("Clicked()", "AliMonitorClient", this,
337                        "OnLoopButtonClicked()");
338   fLoopOnPicture = gClient->GetPicture(fileName);
339   sprintf(fileName, "%s/MONITOR/loop_off2.xpm", gSystem->Getenv("ALICE_ROOT"));
340   fLoopOffPicture = gClient->GetPicture(fileName);
341
342   // previous button
343   sprintf(fileName, "%s/MONITOR/previous_s.xpm", 
344           gSystem->Getenv("ALICE_ROOT"));
345   ToolBarData_t previousButton = {fileName, "go to previous histogram", 
346                                   kFALSE, 22, NULL};
347   fToolBar->AddButton(this, &previousButton, 5);
348   fPreviousButton = previousButton.fButton;
349   fPreviousButton->Connect("Clicked()", "AliMonitorClient", this,
350                            "OnPreviousButtonClicked()");
351
352   // next button
353   sprintf(fileName, "%s/MONITOR/next_s.xpm", gSystem->Getenv("ALICE_ROOT"));
354   ToolBarData_t nextButton = {fileName, "go to next histogram", 
355                               kFALSE, 23, NULL};
356   fToolBar->AddButton(this, &nextButton, 5);
357   fNextButton = nextButton.fButton;
358   fNextButton->Connect("Clicked()", "AliMonitorClient", this,
359                        "OnNextButtonClicked()");
360
361   // copy button
362   sprintf(fileName, "%s/MONITOR/copy_s.xpm", gSystem->Getenv("ALICE_ROOT"));
363   ToolBarData_t copyButton = {fileName, 
364                               "copy the current histogram to a new canvas", 
365                               kFALSE, 31, NULL};
366   fToolBar->AddButton(this, &copyButton, 25);
367   fCopyButton = copyButton.fButton;
368   fCopyButton->Connect("Clicked()", "AliMonitorClient", this,
369                        "OnCopyButtonClicked()");
370
371   // save button
372   sprintf(fileName, "%s/MONITOR/save_s.xpm", gSystem->Getenv("ALICE_ROOT"));
373   ToolBarData_t saveButton = {fileName, "save the current histogram", 
374                               kFALSE, 32, NULL};
375   fToolBar->AddButton(this, &saveButton, 5);
376   fSaveButton = saveButton.fButton;
377   fSaveButton->Connect("Clicked()", "AliMonitorClient", this,
378                        "OnSaveButtonClicked()");
379
380   // print button
381   ToolBarData_t printButton = {"printer_s.xpm", "print the current histogram", 
382                              kFALSE, 33, NULL};
383   fToolBar->AddButton(this, &printButton, 5);
384   fPrintButton = printButton.fButton;
385   fPrintButton->Connect("Clicked()", "AliMonitorClient", this,
386                         "OnPrintButtonClicked()");
387
388   // *** frames ***
389   fBottomLayout = new TGLayoutHints(kLHintsExpandX | kLHintsBottom);
390   fLeftLayout = new TGLayoutHints(kLHintsLeft | kLHintsExpandY);
391   fExpandLayout = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY);
392
393   fVerticalFrame = new TGVerticalFrame(this, 10, 10);
394   AddFrame(fVerticalFrame, fExpandLayout);
395
396   fHorizontalFrame = new TGHorizontalFrame(fVerticalFrame, 10, 10);
397   fVerticalFrame->AddFrame(fHorizontalFrame, fExpandLayout);
398
399   // tree frame
400   fTreeFrame = new TGCompositeFrame(fHorizontalFrame, 10, 10, 
401                                     kSunkenFrame | kFixedWidth);
402   fHorizontalFrame->AddFrame(fTreeFrame, fLeftLayout);
403   fTreeCanvas = new TGCanvas(fTreeFrame, 10, 10);
404   fTreeFrame->AddFrame(fTreeCanvas, fExpandLayout);
405   fTree = new TGListTree(fTreeCanvas, kHorizontalFrame);
406   fTreeCanvas->AddFrame(fTree, fExpandLayout);
407   fTree->Connect("Clicked(TGListTreeItem*,Int_t)", "AliMonitorClient",
408                  this, "OnTreeClicked(TGListTreeItem*,Int_t)");
409   fTree->Connect("ReturnPressed(TGListTreeItem*)", "AliMonitorClient",
410                  this, "OnTreeReturnPressed(TGListTreeItem*)");
411
412   // tree items
413   fAllItem = fTree->AddItem(NULL, "All");
414   fFavoritesItem = fTree->AddItem(NULL, "Favorites");
415   fComparisonItem = fTree->AddItem(NULL, "Comparison");
416   fHistoPicture = fClient->GetPicture("h1_t.xpm"); 
417   fTreeFrame->Resize(100, fTreeFrame->GetDefaultHeight());
418
419   // tree / histogram splitter
420   fTreeSplitter = new TGVSplitter(fHorizontalFrame, 4);
421   fTreeSplitter->SetFrame(fTreeFrame, kTRUE);
422   fHorizontalFrame->AddFrame(fTreeSplitter, fLeftLayout);
423
424   // histogram frame
425   fDrawFrame = new TGCompositeFrame(fHorizontalFrame, 10, 10, kSunkenFrame);
426   fHorizontalFrame->AddFrame(fDrawFrame, fExpandLayout);
427   fDrawCanvas = new TRootEmbeddedCanvas("current monitor histogram", 
428                                         fDrawFrame, 10, 10);
429   fDrawFrame->AddFrame(fDrawCanvas, fExpandLayout);
430
431   // description frame
432   fDescriptionFrame = new TGCompositeFrame(fVerticalFrame, 10, 60, 
433                                            kSunkenFrame | kFixedHeight);
434   fVerticalFrame->AddFrame(fDescriptionFrame, fBottomLayout);
435   fDescription = new TGTextView(fDescriptionFrame, 10, 60, "");
436   fDescriptionFrame->AddFrame(fDescription, fExpandLayout);
437
438   // histogram / description splitter
439   fDescriptionSplitter = new TGHSplitter(fVerticalFrame, 4, 4);
440   fVerticalFrame->AddFrame(fDescriptionSplitter, fBottomLayout);
441   fDescriptionSplitter->SetFrame(fDescriptionFrame, kFALSE);
442
443   // main window
444   Connect("CloseWindow()", "AliMonitorClient", this, "CloseWindow()");
445   SetWindowName("Monitor Client");
446   SetWMSize(GetWidth(), GetHeight());
447   Move(100, 100);
448   SetWMPosition(100, 100);
449   MapSubwindows();
450   Layout();
451   MapWindow();
452
453
454   // default data members
455   fServerName = "localhost";
456   fSocket = NULL;
457   fSocketHandler = NULL;
458
459   fFolder = CreateTopFolder();
460
461   fCurrentItem = NULL;
462   fBaseItem = NULL;
463   fLoopTimer = NULL;
464   fLoopInterval = 1000;
465
466   fFavoritesFileName = "";
467
468   fReferenceFileName = "";
469   fReference = CreateTopFolder();
470   AliMonitorHisto::SetThreshold(5.0);
471
472   fPrintCommand = "gv";
473
474   // load saved settings
475   LoadSettings();
476 }
477
478 //_____________________________________________________________________________
479 AliMonitorClient::~AliMonitorClient()
480 {
481 // clean up
482
483   delete fMenuBarLayout;
484   delete fMenuBarItemLayout;
485   delete fMenuBarHelpLayout;
486   delete fMenuFile;
487   delete fMenuView;
488   delete fMenuFavorites;
489   delete fMenuReference;
490   delete fMenuOptions;
491   delete fMenuHelp;
492   delete fMenuBar;
493
494   delete fEventNumberLayout;
495   delete fEventNumber;
496   delete fToolBarLayout;
497   delete fToolBarSep;
498   delete fToolBar;
499
500   delete fBottomLayout;
501   delete fLeftLayout;
502   delete fExpandLayout;
503
504   delete fTree;
505   delete fTreeCanvas;
506   delete fTreeFrame;
507   delete fTreeSplitter;
508
509   delete fDrawCanvas;
510   delete fDrawFrame;
511
512   delete fDescriptionSplitter;
513   delete fDescription;
514   delete fDescriptionFrame;
515
516   delete fVerticalFrame;
517   delete fHorizontalFrame;
518
519   if (fSocket) {
520     fSocket->Close();
521     delete fSocket;
522     delete fSocketHandler;
523   }
524
525   if (fFolder) delete fFolder;
526
527   if (fLoopTimer) {
528     fLoopTimer->TurnOff();
529     delete fLoopTimer;
530   }
531
532   if (fReference) delete fReference;
533 }
534
535
536 //_____________________________________________________________________________
537 void AliMonitorClient::CloseWindow()
538 {
539 // terminate the application when the window is closed
540
541   if (fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit)) {
542     SaveFavorites();
543   }
544   if (fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit)) {
545     SaveSettings();
546   }
547   gApplication->Terminate(0);
548 }
549
550
551 //_____________________________________________________________________________
552 void AliMonitorClient::OnNewData()
553 {
554 // called when data has arrived from the monitor server
555
556   if (CheckForNewData()) UpdateAll();
557 }
558
559
560 //_____________________________________________________________________________
561 void AliMonitorClient::OnMenuActivated(Int_t id)
562 {
563 // called when a menu item was selected
564
565   switch (id) {
566
567   case kMenuFileConnect: {
568     if (ConnectToServer()) UpdateAll();
569     break;
570   }
571
572   case kMenuFileDisconnect: {
573     DisconnectFromServer();
574     break;
575   }
576
577   case kMenuFileOpen: {
578     if (OpenFile()) UpdateAll();
579     break;
580   }
581
582   case kMenuFileExit: {
583     CloseWindow();
584     break;
585   }
586
587   case kMenuViewToolBar: {
588     ViewToolBar(!fMenuView->IsEntryChecked(kMenuViewToolBar));
589     break;
590   }
591
592   case kMenuViewTree: {
593     ViewTree(!fMenuView->IsEntryChecked(kMenuViewTree));
594     break;
595   }
596
597   case kMenuViewDescription: {
598     ViewDescription(!fMenuView->IsEntryChecked(kMenuViewDescription));
599     break;
600   }
601
602   case kMenuViewReference: {
603     ViewReference(!fMenuView->IsEntryChecked(kMenuViewReference));
604     UpdateHisto();
605     break;
606   }
607
608   case kMenuViewStatistics: {
609     ViewStatistics(!fMenuView->IsEntryChecked(kMenuViewStatistics));
610     UpdateHisto();
611     break;
612   }
613
614   case kMenuFavAdd: {
615     if (AddFavorite()) {
616       fMenuFavorites->EnableEntry(kMenuFavSave);
617       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
618     }
619     break;
620   }
621
622   case kMenuFavDelete: {
623     if (DeleteFavorite()) {
624       UpdateHisto();
625       UpdateDescription();
626       fMenuFavorites->DisableEntry(kMenuFavDelete);
627       fMenuFavorites->EnableEntry(kMenuFavSave);
628       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
629     }
630     break;
631   }
632
633   case kMenuFavLoad: {
634     if (LoadFavorites()) {
635       UpdateHisto();
636       UpdateDescription();
637       fMenuFavorites->DisableEntry(kMenuFavSave);
638       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
639     }
640     break;
641   }
642
643   case kMenuFavSave: {
644     if (SaveFavorites()) {
645       fMenuFavorites->DisableEntry(kMenuFavSave);
646     }
647     break;
648   }
649
650   case kMenuFavSaveAs: {
651     if (SaveFavoritesAs()) {
652       fMenuFavorites->DisableEntry(kMenuFavSave);
653     }
654     break;
655   }
656
657   case kMenuFavSaveOnExit: {
658     if (fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit)) {
659       fMenuFavorites->UnCheckEntry(kMenuFavSaveOnExit);
660     } else {
661       fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
662     }
663     break;
664   }
665
666   case kMenuRefLoad: {
667     if (LoadReference()) {
668       SetReference();
669       UpdateHisto();
670       UpdateComparisonTree();
671       fMenuReference->EnableEntry(kMenuRefSaveAs);
672     }
673     break;
674   }
675
676   case kMenuRefThreshold: {
677     Float_t threshold = AliMonitorHisto::GetThreshold();
678     new AliMonitorNumberDlg(threshold, this, 
679                             "Comparison with Reference Histograms",
680                             "threshold for comparison:", 0.);
681     if (threshold < 0) break;
682
683     AliMonitorHisto::SetThreshold(threshold);
684     UpdateHisto();
685     UpdateComparisonTree();
686     break;
687   }
688
689   case kMenuRefTakeCurrent: {
690     if (TakeCurrentReference()) {
691       UpdateHisto();
692       UpdateComparisonTree();
693       fMenuReference->EnableEntry(kMenuRefSave);
694       fMenuReference->EnableEntry(kMenuRefSaveAs);
695     }
696     break;
697   }
698
699   case kMenuRefSave: {
700     if (SaveReference()) {
701       fMenuReference->DisableEntry(kMenuRefSave);
702     }
703     break;
704   }
705
706   case kMenuRefSaveAs: {
707     if (SaveReferenceAs()) {
708       fMenuReference->DisableEntry(kMenuRefSave);
709     }
710     break;
711   }
712
713   case kMenuOptLoop: {
714     Float_t interval = fLoopInterval * 0.001;
715     new AliMonitorNumberDlg(interval, this, "Loop Interval",
716                             "loop time in seconds:", 0.1);
717     if (interval < 0) break;
718
719     fLoopInterval = Int_t(1000 * interval);
720     if (fLoopTimer) {
721       fLoopTimer->Stop();
722       fLoopTimer->Start(fLoopInterval);
723     }
724     break;
725   }
726
727   case kMenuOptPrint: {
728     TString printCommand(fPrintCommand);
729     new AliMonitorStringDlg(printCommand, this, "Print Command",
730                             "shell command for printing:");
731     if (printCommand.IsNull()) break;
732
733     fPrintCommand = printCommand;
734     break;
735   }
736
737   case kMenuOptSaveOnExit: {
738     if (fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit)) {
739       fMenuOptions->UnCheckEntry(kMenuOptSaveOnExit);
740     } else {
741       fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
742     }
743     break;
744   }
745
746   case kMenuOptSave: {
747     SaveSettings();
748     break;
749   }
750
751   case kMenuHelpAbout: {
752     Int_t result;
753     new TGMsgBox(gClient->GetRoot(), this, 
754                  "About", "AliMonitorClient $Revision$", 
755                  kMBIconAsterisk, kMBOk, &result);
756     break;
757   }
758
759   default: {
760     Int_t result;
761     new TGMsgBox(gClient->GetRoot(), this, 
762                  "AliMonitorClient", "not yet implemented", 
763                  kMBIconExclamation, kMBOk, &result);
764   }
765   }
766 }
767
768
769 //_____________________________________________________________________________
770 void AliMonitorClient::OnEventNumberChanged()
771 {
772 // called when the event number in the tool button was changed
773
774   if (!fRunButton->IsDown()) {
775     UpdateHisto();
776     UpdateComparisonTree();
777   }
778 }
779
780 //_____________________________________________________________________________
781 void AliMonitorClient::OnEventButtonPressed()
782 {
783 // called when the event tool button was clicked
784
785   fSumButton->SetDown(kFALSE);
786   fRunButton->SetDown(kFALSE);
787   UpdateHisto();
788   UpdateComparisonTree();
789 }
790
791 //_____________________________________________________________________________
792 void AliMonitorClient::OnSumButtonPressed()
793 {
794 // called when the sum tool button was clicked
795
796   fEventButton->SetDown(kFALSE);
797   fRunButton->SetDown(kFALSE);
798   UpdateHisto();
799   UpdateComparisonTree();
800 }
801
802 //_____________________________________________________________________________
803 void AliMonitorClient::OnRunButtonPressed()
804 {
805 // called when the run tool button was clicked
806
807   fEventButton->SetDown(kFALSE);
808   fSumButton->SetDown(kFALSE);
809   UpdateHisto();
810   UpdateComparisonTree();
811 }
812
813 //_____________________________________________________________________________
814 void AliMonitorClient::OnLoopButtonClicked()
815 {
816 // called when the loop tool button was clicked
817
818   // if loop is not running, start the loop timer and 
819   // set the stop loop button picture
820   if (!fLoopTimer) {  
821     if (!fBaseItem) {
822       if (!GetBaseItem()) return;
823     }
824     fLoopTimer = new TTimer(fLoopInterval);
825     fLoopTimer->Connect("Timeout()", "AliMonitorClient", this, 
826                         "OnLoopTimer()");
827     ((TGPictureButton*) fLoopButton)->SetPicture(fLoopOffPicture);
828     fLoopTimer->TurnOn();
829
830   // if the loop is running, stop it
831   } else {
832     StopLoop();
833   }
834 }
835
836 //_____________________________________________________________________________
837 void AliMonitorClient::OnPreviousButtonClicked()
838 {
839 // called when the previous tool button was clicked
840
841   if (!fBaseItem) {
842     if (!GetBaseItem()) return;
843   }
844   StopLoop();
845   GoToPreviousItem();
846 }
847
848 //_____________________________________________________________________________
849 void AliMonitorClient::OnNextButtonClicked()
850 {
851 // called when the next tool button was clicked
852
853   if (!fBaseItem) {
854     if (!GetBaseItem()) return;
855   }
856   StopLoop();
857   GoToNextItem();
858 }
859
860 //_____________________________________________________________________________
861 void AliMonitorClient::OnCopyButtonClicked()
862 {
863 // called when the copy tool button was clicked
864
865   fDrawCanvas->GetCanvas()->DrawClone();
866 }
867
868 //_____________________________________________________________________________
869 void AliMonitorClient::OnSaveButtonClicked()
870 {
871 // called when the save tool button was clicked
872
873   // display a file save dialog
874   static TGFileInfo fileInfo;
875   static const char* fileTypes[] = {"PostScript",   "*.ps",
876                                     "Encapsulated PostScript", "*.eps",
877                                     "SVG",          "*.svg",
878                                     "Gif files",    "*.gif",
879                                     "Macro files",  "*.C",
880                                     "ROOT files", "*.root", 
881                                     "All files",  "*", 
882                                     NULL,         NULL};
883   fileInfo.fFileTypes = fileTypes;
884   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
885   if (!fileInfo.fFilename) return;
886
887   fDrawCanvas->GetCanvas()->SaveAs(fileInfo.fFilename);
888 }
889
890 //_____________________________________________________________________________
891 void AliMonitorClient::OnPrintButtonClicked()
892 {
893 // called when the print tool button was clicked
894
895   // save the canvas to a temporary postscript file
896   char fileName[L_tmpnam+4];
897   sprintf(fileName, "%s.ps", tmpnam(NULL));
898   fDrawCanvas->GetCanvas()->SaveAs(fileName);
899
900   // call the print command and delete the temporary file
901   char command[256];
902   sprintf(command, "%s %s", fPrintCommand.Data(), fileName);
903   gSystem->Exec(command);
904   gSystem->Unlink(fileName);
905 }
906
907
908 //_____________________________________________________________________________
909 void AliMonitorClient::OnTreeClicked(TGListTreeItem* item, Int_t)
910 {
911 // called when an item in the histogram tree is clicked
912
913   OnTreeReturnPressed(item);
914 }
915
916 //_____________________________________________________________________________
917 void AliMonitorClient::OnTreeReturnPressed(TGListTreeItem* item)
918 {
919 // called when return is pressed at an item in the histogram tree
920
921   fCurrentItem = item;
922   fBaseItem = NULL;
923   StopLoop();
924   UpdateItem(kFALSE);
925 }
926
927
928 //_____________________________________________________________________________
929 void AliMonitorClient::OnLoopTimer()
930 {
931 // called by the loop timer when a new histogram should be displayed
932
933   if (!fBaseItem) {
934     if (!GetBaseItem()) return;
935   }
936   GoToNextItem();
937 }
938
939
940 //_____________________________________________________________________________
941 TFolder* AliMonitorClient::CreateTopFolder()
942 {
943 // create a top folder for monitor histograms
944
945   return (new TFolder("Monitor", "monitor histograms"));
946 }
947
948 //_____________________________________________________________________________
949 AliMonitorHisto* AliMonitorClient::GetHisto(const char* folderName, 
950                                             const char* histoName)
951 {
952 // find the monitor histogram with the given name in the given folder
953
954   TGListTreeItem* folderItem = fTree->FindChildByName(fAllItem, folderName);
955   if (folderItem) {
956     TGListTreeItem* histoItem = fTree->FindChildByName(folderItem, histoName);
957     if (histoItem) return (AliMonitorHisto*) histoItem->GetUserData();
958   }
959   return NULL;
960 }
961
962 //_____________________________________________________________________________
963 TGListTreeItem* AliMonitorClient::GetItem(TGListTreeItem* base, 
964                                           const char* folderName, 
965                                           const char* histoName, 
966                                           Bool_t create)
967 {
968 // find the tree item with given name in the given folder
969 // if create is kTRUE it is created if it is not there
970
971   // get or create the folder
972   TGListTreeItem* folderItem = fTree->FindChildByName(base, folderName);
973   if (!folderItem) {
974     if (!create) return NULL;
975     folderItem = fTree->AddItem(base, folderName);
976   }
977
978   // get or create the histo
979   TGListTreeItem* histoItem = fTree->FindChildByName(folderItem, histoName);
980   if (!histoItem) {
981     if (!create) return NULL;
982     histoItem = fTree->AddItem(folderItem, histoName,
983                                fClient->GetPicture("h1_t.xpm"),
984                                fClient->GetPicture("h1_t.xpm"));
985   }
986   return histoItem;
987 }
988
989
990 //_____________________________________________________________________________
991 Bool_t AliMonitorClient::ConnectToServer()
992 {
993 // display the dialog for the server name or ip and try to connect to it
994
995   TString serverName(fServerName);
996
997   do {
998     // ask for the server name or ip
999     new AliMonitorStringDlg(serverName, this, "Connection to monitor process",
1000                             "monitor server name or ip:");
1001     if (serverName.IsNull()) return kFALSE;
1002
1003     // connect to the server
1004     fSocket = new TSocket(serverName, AliMonitorProcess::kgPort);
1005     if (!fSocket || !fSocket->IsValid() || (fSocket->Send("client") <= 0)) {
1006       if (fSocket) delete fSocket;
1007       fSocket = NULL;
1008       Int_t result;
1009       new TGMsgBox(gClient->GetRoot(), this, "Connect",
1010                    "connection to monitor server failed", 
1011                    kMBIconExclamation, kMBOk, &result);
1012
1013     } else {  // set up a handler for notifying when new data is there
1014       fServerName = serverName;
1015       fSocketHandler = new TFileHandler(fSocket->GetDescriptor(), 
1016                                         TFileHandler::kRead);
1017       fSocketHandler->Connect("Notified()", "AliMonitorClient", this,
1018                               "OnNewData()");
1019       fSocketHandler->Add();
1020       TInetAddress adr = fSocket->GetInetAddress();
1021       Info("ConnectToServer", "connected to server:\n %s (%s), port %d\n",
1022            adr.GetHostName(), adr.GetHostAddress(), adr.GetPort());
1023       fMenuFile->HideEntry(kMenuFileConnect);
1024       fMenuFile->HideEntry(kMenuFileOpen);
1025       fMenuFile->EnableEntry(kMenuFileDisconnect);
1026     };
1027
1028   } while (!fSocket);
1029
1030   // delete the old monitor histos
1031   if (fFolder) delete fFolder;
1032   fFolder = CreateTopFolder();
1033   return kTRUE;
1034 }
1035
1036 //_____________________________________________________________________________
1037 void AliMonitorClient::DisconnectFromServer()
1038 {
1039 // disconnect from the monitor server
1040
1041   // are-you-really-sure-dialog
1042   Int_t result;
1043   new TGMsgBox(gClient->GetRoot(), this, "Disconnect",
1044                "Do you really want to disconnect from the monitor server?", 
1045                kMBIconQuestion, kMBYes | kMBNo, &result);
1046   if (result == kMBNo) return;
1047
1048   // disconnect from the server
1049   fSocket->Close();
1050   delete fSocket;
1051   fSocket = NULL;
1052   fMenuFile->HideEntry(kMenuFileDisconnect);
1053   fMenuFile->EnableEntry(kMenuFileConnect);
1054   fMenuFile->EnableEntry(kMenuFileOpen);
1055 }
1056
1057 //_____________________________________________________________________________
1058 Bool_t AliMonitorClient::OpenFile()
1059 {
1060 // open a file with monitor histograms
1061
1062   // display a file open dialog
1063   static TGFileInfo fileInfo;
1064   static const char* fileTypes[] = {"ROOT files", "*.root", 
1065                                     "All files",  "*", 
1066                                     NULL,         NULL};
1067   fileInfo.fFileTypes = fileTypes;
1068   new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1069   if (!fileInfo.fFilename) return kFALSE;
1070
1071   // open the root file
1072   TFile* file = TFile::Open(fileInfo.fFilename);
1073   if (!file || !file->IsOpen()) {
1074     Int_t result;
1075     new TGMsgBox(gClient->GetRoot(), this, "Open",
1076                  "The file could not be opened.", 
1077                  kMBIconExclamation, kMBOk, &result);
1078     return kFALSE;
1079   }
1080
1081   // get the folder with the monitor histograms
1082   TFolder* folder = (TFolder*) file->Get("Monitor");
1083   if (!folder || !folder->InheritsFrom(TFolder::Class())) {
1084     Int_t result;
1085     new TGMsgBox(gClient->GetRoot(), this, "Open",
1086                  "The file does not contain monitor histograms.", 
1087                  kMBIconExclamation, kMBOk, &result);
1088     file->Close();
1089     delete file;
1090     return kFALSE;
1091   }
1092
1093   // replace the old folder with the new one
1094   file->Clear();
1095   file->Close();
1096   delete file;
1097   if (fFolder) delete fFolder;
1098   fFolder = folder;
1099   return kTRUE;
1100 }
1101
1102
1103 //_____________________________________________________________________________
1104 void AliMonitorClient::ViewToolBar(Bool_t visible)
1105 {
1106 // en- or disable the view of the tool bar
1107
1108   if (visible) {
1109     ShowFrame(fToolBarSep);
1110     ShowFrame(fToolBar);
1111     fMenuView->CheckEntry(kMenuViewToolBar);
1112   } else {
1113     HideFrame(fToolBarSep);
1114     HideFrame(fToolBar);
1115     fMenuView->UnCheckEntry(kMenuViewToolBar);
1116   }
1117 }
1118
1119 //_____________________________________________________________________________
1120 void AliMonitorClient::ViewTree(Bool_t visible)
1121 {
1122 // en- or disable the view of the tree
1123
1124   if (visible) {
1125     fHorizontalFrame->ShowFrame(fTreeFrame);
1126     fHorizontalFrame->ShowFrame(fTreeSplitter);
1127     fMenuView->CheckEntry(kMenuViewTree);
1128   } else {
1129     fHorizontalFrame->HideFrame(fTreeFrame);
1130     fHorizontalFrame->HideFrame(fTreeSplitter);
1131     fMenuView->UnCheckEntry(kMenuViewTree);
1132   }
1133 }
1134
1135 //_____________________________________________________________________________
1136 void AliMonitorClient::ViewDescription(Bool_t visible)
1137 {
1138 // en- or disable the view of the histogram description
1139
1140   if (visible) {
1141     fVerticalFrame->ShowFrame(fDescriptionFrame);
1142     fVerticalFrame->ShowFrame(fDescriptionSplitter);
1143     fMenuView->CheckEntry(kMenuViewDescription);
1144   } else {
1145     fVerticalFrame->HideFrame(fDescriptionFrame);
1146     fVerticalFrame->HideFrame(fDescriptionSplitter);
1147     fMenuView->UnCheckEntry(kMenuViewDescription);
1148   }
1149 }
1150
1151 //_____________________________________________________________________________
1152 void AliMonitorClient::ViewReference(Bool_t visible)
1153 {
1154 // en- or disable the view of the reference histos
1155
1156   if (visible) {
1157     AliMonitorHisto::SetDrawRef(kTRUE);
1158     fMenuView->CheckEntry(kMenuViewReference);
1159   } else {
1160     AliMonitorHisto::SetDrawRef(kFALSE);
1161     fMenuView->UnCheckEntry(kMenuViewReference);
1162   }
1163 }
1164
1165 //_____________________________________________________________________________
1166 void AliMonitorClient::ViewStatistics(Bool_t visible)
1167 {
1168 // en- or disable the view of the statistics box
1169
1170   if (visible) {
1171     gStyle->SetOptStat(1110);
1172     fMenuView->CheckEntry(kMenuViewStatistics);
1173   } else {
1174     gStyle->SetOptStat(0);
1175     fMenuView->UnCheckEntry(kMenuViewStatistics);
1176   }
1177 }
1178
1179
1180 //_____________________________________________________________________________
1181 Bool_t AliMonitorClient::AddFavorite()
1182 {
1183 // add the current histogram or folder to the list of favorites
1184
1185   if (!fCurrentItem || !fCurrentItem->GetParent()) return kFALSE;
1186
1187   // get the folder item
1188   TGListTreeItem* folderItem = fCurrentItem->GetParent();
1189   if (fCurrentItem->GetFirstChild()) folderItem = fCurrentItem;
1190
1191   Bool_t result = kFALSE;
1192
1193   // add a folder
1194   if (fCurrentItem->GetFirstChild()) {
1195     TGListTreeItem* histoItem = fCurrentItem->GetFirstChild();
1196     while (histoItem) {
1197       if (!GetItem(fFavoritesItem, folderItem->GetText(), 
1198                    histoItem->GetText(), kFALSE)) result = kTRUE;
1199       TGListTreeItem* item = GetItem(fFavoritesItem, folderItem->GetText(), 
1200                                      histoItem->GetText(), kTRUE);
1201       item->SetUserData(histoItem->GetUserData());
1202       histoItem = histoItem->GetNextSibling();
1203     }
1204
1205   // add a histo
1206   } else {
1207     if (!GetItem(fFavoritesItem, folderItem->GetText(), 
1208                  fCurrentItem->GetText(), kFALSE)) result = kTRUE;
1209     TGListTreeItem* item = GetItem(fFavoritesItem, folderItem->GetText(), 
1210                                    fCurrentItem->GetText(), kTRUE);
1211     item->SetUserData(fCurrentItem->GetUserData());
1212   }
1213
1214   if (result) gClient->NeedRedraw(fTree);
1215   return result;
1216 }
1217
1218 //_____________________________________________________________________________
1219 Bool_t AliMonitorClient::DeleteFavorite()
1220 {
1221 // delete the current histogram or folder from the list of favorites
1222
1223   // check that the current item is a favorites histo or folder
1224   if (!fCurrentItem || !fCurrentItem->GetParent()) return kFALSE;
1225   TGListTreeItem* base = fCurrentItem;
1226   while (base->GetParent()) base = base->GetParent();
1227   if (base != fFavoritesItem) return kFALSE;
1228
1229   // delete it
1230   TGListTreeItem* parent = fCurrentItem->GetParent();
1231   fTree->DeleteItem(fCurrentItem);
1232   fCurrentItem = NULL;
1233
1234   // delete the parent folder if it is empty now
1235   if (parent->GetParent() != NULL) {
1236     if (!parent->GetFirstChild()) fTree->DeleteItem(parent);
1237   }
1238
1239   gClient->NeedRedraw(fTree);
1240   return kTRUE;
1241 }
1242
1243 //_____________________________________________________________________________
1244 Bool_t AliMonitorClient::LoadFavorites(Bool_t dialog)
1245 {
1246 // load the list of favorites from a file
1247
1248   // display a file open dialog
1249   TGFileInfo fileInfo;
1250   static const char* fileTypes[] = {"Favorites files", "*.fav", 
1251                                     "All files",  "*", 
1252                                     NULL,         NULL};
1253   fileInfo.fFileTypes = fileTypes;
1254   fileInfo.fIniDir = StrDup(".");
1255   fileInfo.fFilename = StrDup(fFavoritesFileName.Data());
1256   if (dialog) {
1257     new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1258     if (!fileInfo.fFilename) return kFALSE;
1259   }
1260
1261   // open the text file
1262   FILE* file = fopen(fileInfo.fFilename, "rt");
1263   if (!file) {
1264     Int_t result;
1265     new TGMsgBox(gClient->GetRoot(), this, "Load Favorites",
1266                  "The file could not be opened.", 
1267                  kMBIconExclamation, kMBOk, &result);
1268     return kFALSE;
1269   }
1270
1271   // delete the old favorites
1272   TGListTreeItem* favFolderItem = fFavoritesItem->GetFirstChild();
1273   while (favFolderItem) {
1274     TGListTreeItem* deleteItem = favFolderItem;
1275     favFolderItem = favFolderItem->GetNextSibling();
1276     fTree->DeleteItem(deleteItem);
1277   }
1278
1279   // scan the text file and add the favorites histos
1280   char buffer[256];
1281   while (!feof(file)) {
1282     if (fgets(buffer, 255, file) == NULL) break;
1283     char* folder = strtok(buffer, "/");
1284     char* item = strtok(NULL, "\n");
1285     if (item[strlen(item)-1] == '\n') item[strlen(item)-1] = 0;
1286     if (!folder || !item) continue;
1287
1288     AliMonitorHisto* histo = GetHisto(folder, item);
1289     TGListTreeItem* histoItem = GetItem(fFavoritesItem, folder, item, kTRUE);
1290     histoItem->SetUserData(histo);
1291   }
1292   fclose(file);
1293
1294   return kTRUE;
1295 }
1296
1297 //_____________________________________________________________________________
1298 Bool_t AliMonitorClient::SaveFavorites()
1299 {
1300 // save the list of favorites in a file with the name fFavoritesFileName
1301
1302   // if no file name is given use a default one
1303   if (fFavoritesFileName.IsNull()) {
1304     char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1305                                              "AliMonitorClient.fav");
1306     fFavoritesFileName = fileName;
1307     free(fileName);
1308   }
1309
1310   // open the text file
1311   FILE* file = fopen(fFavoritesFileName.Data(), "wt");
1312   if (!file) {
1313     Int_t result;
1314     new TGMsgBox(gClient->GetRoot(), this, "Save Favorites",
1315                  "The file could not be opened.", 
1316                  kMBIconExclamation, kMBOk, &result);
1317     return kFALSE;
1318   }
1319
1320   // loop over folders
1321   TGListTreeItem* folderItem = fFavoritesItem->GetFirstChild();
1322   while (folderItem) {
1323
1324     // loop over histos
1325     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1326     while (histoItem) {
1327
1328       // write the favorites
1329       if (fprintf(file, "%s/%s\n", folderItem->GetText(), 
1330                   histoItem->GetText()) <= 0) {
1331         Int_t result;
1332         new TGMsgBox(gClient->GetRoot(), this, "Save Favorites",
1333                      "An error occured while sving the favorites.", 
1334                      kMBIconExclamation, kMBOk, &result);
1335         fclose(file);
1336         return kFALSE;
1337       }
1338       histoItem = histoItem->GetNextSibling();
1339     }
1340
1341     folderItem = folderItem->GetNextSibling();
1342   }
1343
1344   fclose(file);
1345   Info("SaveFavorites", "favorites saved to file %s", 
1346        fFavoritesFileName.Data());
1347   return kTRUE;
1348 }
1349
1350 //_____________________________________________________________________________
1351 Bool_t AliMonitorClient::SaveFavoritesAs()
1352 {
1353 // ask for a file name and save the favorites to this file
1354
1355   // display a save file dialog
1356   TGFileInfo fileInfo;
1357   static const char* fileTypes[] = {"Favorites files", "*.fav", 
1358                                     "All files",  "*", 
1359                                     NULL,         NULL};
1360   fileInfo.fFileTypes = fileTypes;
1361   fileInfo.fIniDir = StrDup(".");
1362   fileInfo.fFilename = StrDup(fFavoritesFileName.Data());
1363   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
1364   if (!fileInfo.fFilename) return kFALSE;
1365
1366   // save the favorites
1367   fFavoritesFileName = fileInfo.fFilename;
1368   return SaveFavorites();
1369 }
1370
1371
1372 //_____________________________________________________________________________
1373 Bool_t AliMonitorClient::LoadReference(Bool_t dialog)
1374 {
1375 // load reference histograms from a file
1376
1377   // display a file open dialog
1378   TGFileInfo fileInfo;
1379   static const char* fileTypes[] = {"ROOT files", "*.root", 
1380                                     "All files",  "*", 
1381                                     NULL,         NULL};
1382   fileInfo.fFileTypes = fileTypes;
1383   fileInfo.fIniDir = StrDup(".");
1384   fileInfo.fFilename = StrDup(fReferenceFileName.Data());
1385   if (dialog) {
1386     new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1387     if (!fileInfo.fFilename) return kFALSE;
1388   }
1389
1390   // open the root file
1391   TFile* file = TFile::Open(fileInfo.fFilename);
1392   if (!file || !file->IsOpen()) {
1393     Int_t result;
1394     new TGMsgBox(gClient->GetRoot(), this, "Load Reference",
1395                  "The file could not be opened.", 
1396                  kMBIconExclamation, kMBOk, &result);
1397     return kFALSE;
1398   }
1399
1400   // get the folder with the monitor histograms
1401   TFolder* folder = (TFolder*) file->Get("Monitor");
1402   if (!folder || !folder->InheritsFrom(TFolder::Class())) {
1403     Int_t result;
1404     new TGMsgBox(gClient->GetRoot(), this, "Load Reference",
1405                  "The file does not contain monitor histograms.", 
1406                  kMBIconExclamation, kMBOk, &result);
1407     file->Close();
1408     delete file;
1409     return kFALSE;
1410   }
1411
1412   // replace the old reference folder with the new one
1413   fReferenceFileName = fileInfo.fFilename;
1414   file->Clear();
1415   file->Close();
1416   delete file;
1417   if (fReference) delete fReference;
1418   fReference = folder;
1419   return kTRUE;
1420 }
1421
1422 //_____________________________________________________________________________
1423 void AliMonitorClient::SetReference()
1424 {
1425 // set the reference histograms for all monitor histograms
1426
1427   // loop over folder
1428   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
1429   while (TFolder* folder = (TFolder*) iFolder->Next()) {
1430     TFolder* refFolder = (TFolder*) fReference->FindObject(folder->GetName());
1431     if (!refFolder) continue;
1432
1433     // loop over histos
1434     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
1435     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
1436       AliMonitorHisto* refHisto = 
1437         (AliMonitorHisto*) refFolder->FindObject(histo->GetName());
1438       if (!refHisto) continue;
1439       histo->SetReference(refHisto);
1440     }
1441     delete iHisto;
1442
1443   }
1444   delete iFolder;
1445 }
1446
1447 //_____________________________________________________________________________
1448 Bool_t AliMonitorClient::TakeCurrentReference()
1449 {
1450 // take the current monitor histogram or folder as reference
1451
1452   // check that a histo or folder is selected
1453   if (!fCurrentItem) return kFALSE;
1454   AliMonitorHisto* histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
1455   if (!histo && !fCurrentItem->GetFirstChild()) return kFALSE;
1456
1457   // confirm-dialog
1458   char message[256];
1459   if (histo) {
1460     sprintf(message, "Do you want to take the current histogram %s/%s "
1461             "as reference histogram?", fCurrentItem->GetParent()->GetText(),
1462             histo->GetName());
1463   } else {
1464     sprintf(message, "Do you want to take all current histogram of the "
1465             "folder %s as reference histogram?", fCurrentItem->GetText());
1466   }
1467   Int_t result;
1468   new TGMsgBox(gClient->GetRoot(), this, "Take Current as Reference",
1469                message, kMBIconQuestion, kMBYes | kMBNo, &result);
1470   if (result != kMBYes) return kFALSE;
1471
1472   // take ...
1473   if (histo) {   // ... a histo
1474     TakeReferenceHisto(fCurrentItem->GetParent()->GetText(), histo);
1475   } else if (fCurrentItem->GetParent()) {  // ... a folder
1476     TakeReferenceFolder(fCurrentItem);
1477   } else {  // ... a top folder
1478     TGListTreeItem* folderItem = fCurrentItem->GetFirstChild();
1479     while (folderItem) {
1480       TakeReferenceFolder(folderItem);
1481       folderItem = folderItem->GetNextSibling();
1482     }
1483   }
1484   return kTRUE;
1485 }
1486
1487 //_____________________________________________________________________________
1488 void AliMonitorClient::TakeReferenceHisto(const char* folderName,
1489                                           AliMonitorHisto* histo)
1490 {
1491 // take the given monitor histogram as reference histogram
1492
1493   // get or create the reference folder
1494   TFolder* refFolder = (TFolder*) fReference->FindObject(folderName);
1495   if (!refFolder) refFolder = fReference->AddFolder(folderName, folderName);
1496
1497   // delete the old reference histo
1498   AliMonitorHisto* refHisto = 
1499     (AliMonitorHisto*) refFolder->FindObject(histo->GetName());
1500   if (refHisto) {
1501     refFolder->Remove(refHisto);
1502     delete refHisto;
1503   }
1504
1505   // add the new one and use it as reference
1506   refFolder->Add(new AliMonitorHisto(*histo));
1507   histo->SetReference(histo);
1508 }
1509
1510 //_____________________________________________________________________________
1511 void AliMonitorClient::TakeReferenceFolder(TGListTreeItem* item)
1512 {
1513 // take all monitor histogram in the given folder as reference histograms
1514
1515   // loop over histos
1516   TGListTreeItem* histoItem = item->GetFirstChild();
1517   while (histoItem) {
1518     AliMonitorHisto* histo = (AliMonitorHisto*) histoItem->GetUserData();
1519     if (histo) TakeReferenceHisto(item->GetText(), histo);
1520     histoItem = histoItem->GetNextSibling();
1521   }
1522 }
1523
1524 //_____________________________________________________________________________
1525 Bool_t AliMonitorClient::SaveReference()
1526 {
1527 // save the reference histograms to the file with name fReferenceFileName
1528
1529   // if no file name is given use a default one
1530   if (fFavoritesFileName.IsNull()) {
1531     char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1532                                              "AliMonitorClientRef.root");
1533     fFavoritesFileName = fileName;
1534     free(fileName);
1535   }
1536
1537   // open the root file
1538   TFile* file = TFile::Open(fReferenceFileName, "RECREATE");
1539   if (!file || !file->IsOpen()) {
1540     Int_t result;
1541     new TGMsgBox(gClient->GetRoot(), this, "Save Reference",
1542                  "The file could not be opened.", 
1543                  kMBIconExclamation, kMBOk, &result);
1544     if (file) delete file;
1545     return kFALSE;
1546   }
1547
1548   // write the reference folder
1549   fReference->Write();
1550   file->Close();
1551   delete file;
1552   Info("SaveReference", "reference histograms saved to file %s", 
1553        fReferenceFileName.Data());
1554   return kTRUE;
1555 }
1556
1557 //_____________________________________________________________________________
1558 Bool_t AliMonitorClient::SaveReferenceAs()
1559 {
1560 // ask for a file name and save the reference histograms to this file
1561
1562   // display a save file dialog
1563   TGFileInfo fileInfo;
1564   static const char* fileTypes[] = {"ROOT files", "*.root", 
1565                                     "All files",  "*", 
1566                                     NULL,         NULL};
1567   fileInfo.fFileTypes = fileTypes;
1568   fileInfo.fIniDir = StrDup(".");
1569   fileInfo.fFilename = StrDup(fReferenceFileName.Data());
1570   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
1571   if (!fileInfo.fFilename) return kFALSE;
1572
1573   // save the references
1574   fReferenceFileName = fileInfo.fFilename;
1575   return SaveReference();
1576 }
1577
1578
1579 //_____________________________________________________________________________
1580 void AliMonitorClient::StopLoop()
1581 {
1582 // stop looping over histograms
1583
1584   // stop the timer and reset the loop button picture
1585   if (fLoopTimer) {
1586     fLoopTimer->TurnOff();
1587     delete fLoopTimer;
1588     fLoopTimer = NULL;
1589     ((TGPictureButton*) fLoopButton)->SetPicture(fLoopOnPicture);
1590   }
1591 }
1592
1593 //_____________________________________________________________________________
1594 void AliMonitorClient::LoadSettings()
1595 {
1596 // load setting from the file with the name fgSettingFileName and apply them
1597
1598   // open the text file
1599   char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1600                                            fgSettingsFileName);
1601   FILE* file = fopen(fileName, "rt");
1602   if (!file) {
1603     free(fileName);
1604     return;
1605   }
1606
1607   // scan the text file and apply the settings
1608   char buffer[256];
1609   while (!feof(file)) {
1610     if (fgets(buffer, 255, file) == NULL) break;
1611     char* token = strtok(buffer, "=");
1612     char* value = strtok(NULL, "\n");
1613     if (!token || !value) continue;
1614     if (value[strlen(value)-1] == '\n') value[strlen(value)-1] = 0;
1615
1616     if (strcmp(token, "ServerName") == 0) {
1617       fServerName = value;
1618
1619     } else if (strcmp(token, "ViewToolBar") == 0) {
1620       ViewToolBar(strcmp(value, "0") != 0);
1621     } else if (strcmp(token, "ViewTree") == 0) {
1622       ViewTree(strcmp(value, "0") != 0);
1623     } else if (strcmp(token, "ViewDescription") == 0) {
1624       ViewDescription(strcmp(value, "0") != 0);
1625     } else if (strcmp(token, "ViewReference") == 0) {
1626       ViewReference(strcmp(value, "0") != 0);
1627     } else if (strcmp(token, "ViewStatistics") == 0) {
1628       ViewStatistics(strcmp(value, "0") != 0);
1629
1630     } else if (strcmp(token, "FavoritesFileName") == 0) {
1631       fFavoritesFileName = value;
1632       LoadFavorites(kFALSE);
1633     } else if (strcmp(token, "FavoritesSaveOnExit") == 0) {
1634       if (strcmp(value, "0") != 0) {
1635         fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
1636       } else {
1637         fMenuFavorites->UnCheckEntry(kMenuFavSaveOnExit);
1638       }
1639
1640     } else if (strcmp(token, "ReferenceFileName") == 0) {
1641       fReferenceFileName = value;
1642       LoadReference(kFALSE);
1643     } else if (strcmp(token, "ReferenceThreshold") == 0) {
1644       AliMonitorHisto::SetThreshold(atof(value));
1645
1646     } else if (strcmp(token, "LoopInterval") == 0) {
1647       fLoopInterval = atoi(value);
1648     } else if (strcmp(token, "PrintCommand") == 0) {
1649       fPrintCommand = value;
1650     } else if (strcmp(token, "SettingsSaveOnExit") == 0) {
1651       if (strcmp(value, "0") != 0) {
1652         fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
1653       } else {
1654         fMenuOptions->UnCheckEntry(kMenuOptSaveOnExit);
1655       }
1656     }
1657   }
1658
1659   fclose(file);
1660   Info("LoadSettings", "settings from file %s applied", fileName);
1661   free(fileName);
1662 }
1663
1664 //_____________________________________________________________________________
1665 void AliMonitorClient::SaveSettings()
1666 {
1667 // save setting to the file with the name fgSettingFileName
1668
1669   // open the text file
1670   char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1671                                            fgSettingsFileName);
1672   FILE* file = fopen(fileName, "wt");
1673   if (!file) {
1674     Int_t result;
1675     new TGMsgBox(gClient->GetRoot(), this, "Save Settings",
1676                  "The file could not be opened.", 
1677                  kMBIconExclamation, kMBOk, &result);
1678     free(fileName);
1679     return;
1680   }
1681
1682   // write the settings
1683   fprintf(file, "ServerName=%s\n", fServerName.Data());
1684
1685   fprintf(file, "ViewToolBar=%d\n", 
1686           fMenuView->IsEntryChecked(kMenuViewToolBar));
1687   fprintf(file, "ViewTree=%d\n", 
1688           fMenuView->IsEntryChecked(kMenuViewTree));
1689   fprintf(file, "ViewDescription=%d\n", 
1690           fMenuView->IsEntryChecked(kMenuViewDescription));
1691   fprintf(file, "ViewReference=%d\n", 
1692           fMenuView->IsEntryChecked(kMenuViewReference));
1693   fprintf(file, "ViewStatistics=%d\n", 
1694           fMenuView->IsEntryChecked(kMenuViewStatistics));
1695
1696   if (!fFavoritesFileName.IsNull()) {
1697     fprintf(file, "FavoritesFileName=%s\n", fFavoritesFileName.Data());
1698   }
1699   fprintf(file, "FavoritesSaveOnExit=%d\n", 
1700           fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit));
1701
1702   if (!fReferenceFileName.IsNull()) {
1703     fprintf(file, "ReferenceFileName=%s\n", fReferenceFileName.Data());
1704   }
1705   fprintf(file, "ReferenceThreshold=%.1f\n", AliMonitorHisto::GetThreshold());
1706
1707   fprintf(file, "LoopInterval=%d\n", fLoopInterval);
1708   fprintf(file, "PrintCommand=%s\n", fPrintCommand.Data());
1709   fprintf(file, "SettingsSaveOnExit=%d\n", 
1710           fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit));
1711
1712   fclose(file);
1713   Info("SaveSettings", "settings saved to file %s", fileName);
1714   free(fileName);
1715 }
1716
1717
1718 //_____________________________________________________________________________
1719 Bool_t AliMonitorClient::GetBaseItem()
1720 {
1721 // get the base item for looping over histograms
1722
1723   if (fCurrentItem) {
1724     // the base item is a folder
1725     fBaseItem = fCurrentItem;
1726     // if the current item is a histo, its parent is the base folder
1727     if (fBaseItem->GetParent() && fBaseItem->GetParent()->GetParent()) {
1728       fBaseItem = fBaseItem->GetParent();
1729     }
1730
1731   } else {  // if no item is selected the All item is the base item
1732     fBaseItem = fAllItem;
1733     fCurrentItem = fBaseItem->GetFirstChild();
1734     if (!fCurrentItem) return kFALSE;
1735   }
1736
1737   return kTRUE;
1738 }
1739
1740 //_____________________________________________________________________________
1741 Bool_t AliMonitorClient::GoToNextItem()
1742 {
1743 // go to the next histogram in the loop
1744
1745   if (!fCurrentItem) return kFALSE;
1746   if (!fBaseItem || !fBaseItem->GetFirstChild()) return kFALSE;
1747
1748   // remember the start item to avoid an endless loop
1749   TGListTreeItem* startItem = fCurrentItem;
1750
1751   do {
1752     // folder -> first child
1753     if (fCurrentItem->GetFirstChild()) {
1754       fCurrentItem = fCurrentItem->GetFirstChild();
1755
1756     // histo -> next histo
1757     } else if ((fCurrentItem != fBaseItem) &&
1758                (fCurrentItem->GetNextSibling())) {
1759       fCurrentItem = fCurrentItem->GetNextSibling();
1760
1761     // last histo in folder -> next folder
1762     } else if ((fCurrentItem != fBaseItem) &&
1763                (fCurrentItem->GetParent() != fBaseItem) &&
1764                fCurrentItem->GetParent()->GetNextSibling()) {
1765       fCurrentItem = fCurrentItem->GetParent()->GetNextSibling();
1766
1767     // last histo in last folder -> first folder
1768     } else {
1769       fCurrentItem = fBaseItem->GetFirstChild();
1770     }
1771
1772     // abort if no next item found
1773     if (fCurrentItem == startItem) return kFALSE;
1774
1775   // end loop if an item with a monitor histo was found
1776   } while (!fCurrentItem->GetUserData());
1777
1778   UpdateItem(kTRUE);
1779   return kTRUE;
1780 }
1781
1782 //_____________________________________________________________________________
1783 Bool_t AliMonitorClient::GoToPreviousItem()
1784 {
1785 // go to the previous histogram in the loop
1786
1787   if (!fCurrentItem) return kFALSE;
1788   if (!fBaseItem || !fBaseItem->GetFirstChild()) return kFALSE;
1789
1790   // remember the start item to avoid an endless loop
1791   TGListTreeItem* startItem = fCurrentItem;
1792
1793   do {
1794     // folder -> last child
1795     if (fCurrentItem->GetFirstChild()) {
1796       fCurrentItem = fCurrentItem->GetFirstChild();
1797       while (fCurrentItem->GetNextSibling()) {
1798         fCurrentItem = fCurrentItem->GetNextSibling();
1799       }
1800
1801     // histo -> previous histo
1802     } else if ((fCurrentItem != fBaseItem) && 
1803                (fCurrentItem->GetPrevSibling())) {
1804       fCurrentItem = fCurrentItem->GetPrevSibling();
1805
1806     // first histo in folder -> previous folder
1807     } else if ((fCurrentItem != fBaseItem) && 
1808                (fCurrentItem->GetParent() != fBaseItem) &&
1809                fCurrentItem->GetParent()->GetPrevSibling()) {
1810       fCurrentItem = fCurrentItem->GetParent()->GetPrevSibling();
1811
1812     // first histo in first folder -> last folder
1813     } else {
1814       fCurrentItem = fBaseItem->GetFirstChild();
1815       while (fCurrentItem->GetNextSibling()) {
1816         fCurrentItem = fCurrentItem->GetNextSibling();
1817       }
1818     }
1819
1820     // abort if no next item found
1821     if (fCurrentItem == startItem) return kFALSE;
1822
1823   // end loop if an item with a monitor histo was found
1824   } while (!fCurrentItem->GetUserData());
1825
1826   UpdateItem(kTRUE);
1827   return kTRUE;
1828 }
1829
1830 //_____________________________________________________________________________
1831 void AliMonitorClient::UpdateItem(Bool_t highlight)
1832 {
1833 // update the displayed tree for currently selected item
1834
1835   if (highlight) {  // highlight the selected item and open its parent folders
1836     TGListTreeItem* parent = fCurrentItem->GetParent();
1837     while (parent) {
1838       if (!parent->IsOpen()) fTree->OpenItem(parent);
1839       parent = parent->GetParent();
1840     }
1841     fTree->HighlightItem(fCurrentItem);
1842     gClient->NeedRedraw(fTree);
1843   }
1844
1845   // update displayed histo
1846   UpdateDescription();
1847   UpdateHisto();
1848
1849   // en- or disable the "Reference/Take Current" menu item
1850   TGListTreeItem* base = fCurrentItem;
1851   while (base->GetParent()) base = base->GetParent();
1852   if (base != fComparisonItem) {
1853     fMenuReference->EnableEntry(kMenuRefTakeCurrent);
1854   } else {
1855     fMenuReference->DisableEntry(kMenuRefTakeCurrent);
1856   }
1857
1858   // en- or disable the "Favorites/Add" and "Favorites/Delete" menu items
1859   if (fCurrentItem->GetParent()) {
1860     if (base == fFavoritesItem) {
1861       fMenuFavorites->DisableEntry(kMenuFavAdd);
1862       fMenuFavorites->EnableEntry(kMenuFavDelete);
1863     } else {
1864       fMenuFavorites->EnableEntry(kMenuFavAdd);
1865       fMenuFavorites->DisableEntry(kMenuFavDelete);
1866     }
1867   } else {
1868     fMenuFavorites->DisableEntry(kMenuFavAdd);
1869     fMenuFavorites->DisableEntry(kMenuFavDelete);
1870   }
1871 }
1872
1873
1874 //_____________________________________________________________________________
1875 Bool_t AliMonitorClient::CheckForNewData()
1876 {
1877 // check whether the monitor process server sent new data
1878
1879   // receive a message from the server
1880   if (!fSocket || !fSocket->IsValid()) return kFALSE;
1881   TMessage* message = NULL;
1882   Int_t result = fSocket->Recv(message);
1883
1884   // replace the old folder of monitor histos with the new one
1885   if (result > 0) {
1886     if (fFolder) delete fFolder;
1887     fFolder = (TFolder*) message->ReadObject(message->GetClass());
1888     return kTRUE;
1889   }
1890
1891   return kFALSE;
1892 }
1893
1894 //_____________________________________________________________________________
1895 void AliMonitorClient::ClearItems(TGListTreeItem* base)
1896 {
1897 // remove the references to the histograms from all subitems of the 
1898 // given tree item
1899
1900   // loop over folders
1901   TGListTreeItem* folderItem = base->GetFirstChild();
1902   while (folderItem) {
1903
1904     // loop over histos
1905     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1906     while (histoItem) {
1907       histoItem->SetUserData(NULL);
1908       histoItem = histoItem->GetNextSibling();
1909     }
1910
1911     folderItem = folderItem->GetNextSibling();
1912   }
1913 }
1914
1915 //_____________________________________________________________________________
1916 void AliMonitorClient::CleanUpTree(TGListTreeItem* base)
1917 {
1918 // remove items without monitor histograms and 
1919 // folders without monitor histograms
1920
1921   // loop over folders
1922   TGListTreeItem* folderItem = base->GetFirstChild();
1923   while (folderItem) {
1924
1925     // loop over histos
1926     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1927     while (histoItem) {
1928       TGListTreeItem* deleteItem = NULL;
1929       if (!histoItem->GetUserData()) deleteItem = histoItem;
1930       histoItem = histoItem->GetNextSibling();
1931       if (fCurrentItem == deleteItem) fCurrentItem = NULL;
1932       if (deleteItem) fTree->DeleteItem(deleteItem);
1933     }
1934
1935     folderItem = folderItem->GetNextSibling();
1936   }
1937
1938   // loop over folders and remove empty folders
1939   folderItem = base->GetFirstChild();
1940   while (folderItem) {
1941     TGListTreeItem* deleteItem = NULL;
1942     if (!folderItem->GetFirstChild()) deleteItem = folderItem;
1943     folderItem = folderItem->GetNextSibling();
1944     if (fCurrentItem == deleteItem) fCurrentItem = NULL;
1945     if (deleteItem) fTree->DeleteItem(deleteItem);
1946   }
1947 }
1948
1949 //_____________________________________________________________________________
1950 void AliMonitorClient::UpdateTree()
1951 {
1952 // update the tree of monitor histograms
1953
1954   // delete references to old monitor histograms
1955   ClearItems(fAllItem);
1956
1957   // loop over folder
1958   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
1959   while (TFolder* folder = (TFolder*) iFolder->Next()) {
1960
1961     // loop over histos
1962     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
1963     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
1964
1965       // add new monitor histograms
1966       TGListTreeItem* histoItem = GetItem(fAllItem, folder->GetName(),
1967                                           histo->GetName(), kTRUE);
1968       histoItem->SetUserData(histo);
1969     }
1970     delete iHisto;
1971
1972   }
1973   delete iFolder;
1974
1975   // remove items and folders without monitor histograms
1976   CleanUpTree(fAllItem);
1977
1978   gClient->NeedRedraw(fTree);
1979 }
1980
1981 //_____________________________________________________________________________
1982 void AliMonitorClient::UpdateFavoritesTree()
1983 {
1984 // update the tree of favorite monitor histograms
1985
1986   // loop over folders
1987   TGListTreeItem* folderItem = fFavoritesItem->GetFirstChild();
1988   while (folderItem) {
1989
1990     // loop over histos
1991     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1992     while (histoItem) {
1993
1994       // set monitor histo
1995       histoItem->SetUserData(GetHisto(folderItem->GetText(), 
1996                                       histoItem->GetText()));
1997       histoItem = histoItem->GetNextSibling();
1998     }
1999
2000     folderItem = folderItem->GetNextSibling();
2001   }
2002 }
2003
2004 //_____________________________________________________________________________
2005 void AliMonitorClient::UpdateComparisonTree()
2006 {
2007 // update the tree of monitor histograms with significant deviation
2008 // from the reference histograms
2009
2010   if (!fFolder) return;
2011
2012   // delete references to old monitor histograms
2013   ClearItems(fComparisonItem);
2014
2015   // add monitor histograms where the comparison returns a deviation
2016   // loop over folders
2017   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
2018   while (TFolder* folder = (TFolder*) iFolder->Next()) {
2019
2020     // loop over histos
2021     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
2022     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
2023
2024       // compare the histo to its reference
2025       Bool_t comparison = kTRUE;
2026       if (fEventButton->IsDown()) {
2027         comparison = histo->CompareEvent(fEventNumber->GetIntNumber());
2028       } else if (fSumButton->IsDown()) {
2029         comparison = histo->CompareSum(fEventNumber->GetIntNumber());
2030       } else {
2031         comparison = histo->CompareRun();
2032       }
2033
2034       // add it to the comparison tree in case of a bad comparison result
2035       if (!comparison) {
2036         TGListTreeItem* histoItem = GetItem(fComparisonItem, folder->GetName(),
2037                                             histo->GetName(), kTRUE);
2038         histoItem->SetUserData(histo);
2039       }
2040     }
2041     delete iHisto;
2042
2043   }
2044   delete iFolder;
2045
2046   // remove items and folders without monitor histograms
2047   CleanUpTree(fComparisonItem);
2048
2049   gClient->NeedRedraw(fTree);
2050 }
2051
2052 //_____________________________________________________________________________
2053 void AliMonitorClient::UpdateDescription()
2054 {
2055 // update the description of the current monitor histogram
2056
2057   fDescription->Clear();
2058   AliMonitorHisto* histo = NULL;
2059   if (fCurrentItem) histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
2060   if (histo) fDescription->LoadBuffer(histo->GetDescription().Data());
2061
2062   gClient->NeedRedraw(fDescription);
2063 }
2064
2065 //_____________________________________________________________________________
2066 void AliMonitorClient::UpdateHisto()
2067 {
2068 // update the current monitor histogram
2069
2070   // clear the canvas if no histo is selected
2071   AliMonitorHisto* histo = NULL;
2072   if (fCurrentItem) histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
2073   if (!histo) {
2074     fDrawCanvas->GetCanvas()->Clear();
2075     fDrawCanvas->GetCanvas()->Update();
2076     return;
2077   }
2078
2079   // draw the histo for a single event or summed over several events or a run
2080   fDrawCanvas->GetCanvas()->cd();
2081   if (fEventButton->IsDown()) {
2082     histo->DrawEvent(fEventNumber->GetIntNumber());
2083   } else if (fSumButton->IsDown()) {
2084     histo->DrawSum(fEventNumber->GetIntNumber());
2085   } else {
2086     histo->DrawRun();
2087   }
2088 }
2089
2090 //_____________________________________________________________________________
2091 void AliMonitorClient::UpdateAll()
2092 {
2093 // update the trees, the histogram and the description
2094
2095   UpdateTree();
2096   UpdateFavoritesTree();
2097   UpdateComparisonTree();
2098   UpdateDescription();
2099   UpdateHisto();
2100 }
2101