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