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